Example #1
0
void QtTestGui::resizeEvent(QResizeEvent *e){
	HRESULT hr = S_OK;

	uint32_t width = static_cast<uint32_t>((std::max)(this->width(), 1));
	uint32_t height = static_cast<uint32_t>((std::max)(this->height(), 1));
	std::lock_guard<std::mutex> lk(this->d3dMtx);

	this->d3dRtView = nullptr;

	if (!this->d3dSwapChain){
		Microsoft::WRL::ComPtr<IDXGIDevice2> dxgiDevice;
		Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
		Microsoft::WRL::ComPtr<IDXGIFactory2> dxgiFactory;
		Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChainTmp;

		hr = this->d3dDev.As(&dxgiDevice);
		hr = dxgiDevice->GetParent(IID_PPV_ARGS(dxgiAdapter.GetAddressOf()));
		hr = dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.GetAddressOf()));

		HWND hwnd = reinterpret_cast<HWND>(this->winId());
		HWND hwnd2 = reinterpret_cast<HWND>(this->effectiveWinId());
		DXGI_SWAP_CHAIN_DESC1 swapChainDesc;
		DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreenDesc;

		swapChainDesc.Width = width;
		swapChainDesc.Height = height;
		swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
		swapChainDesc.Stereo = FALSE;
		swapChainDesc.SampleDesc.Count = 1;
		swapChainDesc.SampleDesc.Quality = 0;
		swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
		swapChainDesc.BufferCount = 2;
		swapChainDesc.Scaling = DXGI_SCALING::DXGI_SCALING_STRETCH;
		swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT::DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;// DXGI_SWAP_EFFECT::DXGI_SWAP_EFFECT_SEQUENTIAL;
		swapChainDesc.AlphaMode = DXGI_ALPHA_MODE::DXGI_ALPHA_MODE_IGNORE;
		swapChainDesc.Flags = 0;

		fullscreenDesc.RefreshRate.Numerator = 0;
		fullscreenDesc.RefreshRate.Denominator = 0;
		fullscreenDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER::DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
		fullscreenDesc.Scaling = DXGI_MODE_SCALING::DXGI_MODE_SCALING_CENTERED;
		fullscreenDesc.Windowed = TRUE;

		hr = dxgiFactory->CreateSwapChainForHwnd(this->d3dDev.Get(), hwnd, &swapChainDesc, &fullscreenDesc, nullptr, swapChainTmp.GetAddressOf());
		hr = swapChainTmp.As(&this->d3dSwapChain);
	}
	else{
		hr = this->d3dSwapChain->ResizeBuffers(2, width, height, DXGI_FORMAT_R8G8B8A8_UNORM, 0);
	}

	Microsoft::WRL::ComPtr<IDXGISurface> dxgiSurface;
	Microsoft::WRL::ComPtr<ID3D11Texture2D> d3dTex;

	hr = this->d3dSwapChain->GetBuffer(0, IID_PPV_ARGS(dxgiSurface.GetAddressOf()));
	hr = dxgiSurface.As(&d3dTex);

	D3D11_TEXTURE2D_DESC tex2dDec;
	D3D11_RENDER_TARGET_VIEW_DESC d3dRtDesc;

	d3dTex->GetDesc(&tex2dDec);

	d3dRtDesc.ViewDimension = D3D11_RTV_DIMENSION::D3D11_RTV_DIMENSION_TEXTURE2D;
	d3dRtDesc.Format = tex2dDec.Format;
	d3dRtDesc.Texture2D.MipSlice = 0;

	this->d3dDev->CreateRenderTargetView(d3dTex.Get(), &d3dRtDesc, this->d3dRtView.ReleaseAndGetAddressOf());

	D3D11_VIEWPORT viewPort;

	viewPort.TopLeftX = viewPort.TopLeftY = 0.0f;
	viewPort.Width = static_cast<float>(width);
	viewPort.Height = static_cast<float>(height);
	viewPort.MinDepth = 0.0f;
	viewPort.MaxDepth = 1.0f;

	this->d3dCtx->RSSetViewports(1, &viewPort);

	this->UpdateProjection();
}
Example #2
0
void DirectXPanelBase::CreateSizeDependentResources()
{
    bool setSwapChain = false;

    // Ensure dependent objects have been released.
    ReleaseSizeDependentResources();
    
    // If the swap chain already exists, then resize it.
    if (m_swapChain != nullptr)
    {
        // If the swap chain already exists, resize it.
        HRESULT hr = m_swapChain->ResizeBuffers(
            2, // Double-buffered swap chain.
            static_cast<UINT>((float) max(m_width * m_compositionScaleX, 1)),
            static_cast<UINT>((float) max(m_height * m_compositionScaleY, 1)),
            DXGI_FORMAT_B8G8R8A8_UNORM,
            0
        );

        if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
        {
            // If the device was removed for any reason, a new device and swap chain will need to be created.
            HandleDeviceLost();

            // Everything is set up now. Do not continue execution of this method. 
            return;
        }
        else
        {
            DX::ThrowIfFailed(hr);
        }
    }
    else // Otherwise, create a new one.
    {
        DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
        swapChainDesc.Width = static_cast<UINT>((float) max(m_width * m_compositionScaleX, 1));      // Match the size of the panel.
        swapChainDesc.Height = static_cast<UINT>((float) max(m_height * m_compositionScaleY, 1));
        swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;                  // This is the most common swap chain format.
        swapChainDesc.Stereo = false;
        swapChainDesc.SampleDesc.Count = 1;                                 // Don't use multi-sampling.
        swapChainDesc.SampleDesc.Quality = 0;
        swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        swapChainDesc.BufferCount = 2;                                      // Use double buffering to enable flip.
        swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;        // All Windows Store apps must use this SwapEffect.
        swapChainDesc.Flags = 0;
        swapChainDesc.AlphaMode = m_alphaMode;

        // Get underlying DXGI Device from D3D Device.
        Microsoft::WRL::ComPtr<IDXGIDevice1> dxgiDevice;
        DX::ThrowIfFailed(
            m_d3dDevice.As(&dxgiDevice)
        );

        // Get adapter.
        Microsoft::WRL::ComPtr<IDXGIAdapter> dxgiAdapter;
        DX::ThrowIfFailed(
            dxgiDevice->GetAdapter(&dxgiAdapter)
        );

        // Get factory.
        Microsoft::WRL::ComPtr<IDXGIFactory2> dxgiFactory;
        DX::ThrowIfFailed(
            dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory))
        );

        Microsoft::WRL::ComPtr<IDXGISwapChain1> swapChain;
        // Create swap chain.
        DX::ThrowIfFailed(
            dxgiFactory->CreateSwapChainForComposition(
                m_d3dDevice.Get(),
                &swapChainDesc,
                nullptr,
                &swapChain
            )
        );
        swapChain.As(&m_swapChain);

        // Ensure that DXGI does not queue more than one frame at a time. This both reduces 
        // latency and ensures that the application will only render after each VSync, minimizing 
        // power consumption.
        DX::ThrowIfFailed(
            dxgiDevice->SetMaximumFrameLatency(1)
        );

        setSwapChain = true;
    }

    // Ensure the physical pixel size of the swap chain takes into account both the XAML SwapChainPanel's logical layout size and 
    // any cumulative composition scale applied due to zooming, render transforms, or the system's current scaling plateau.
    // For example, if a 100x100 SwapChainPanel has a cumulative 2x scale transform applied, we instead create a 200x200 swap chain 
    // to avoid artifacts from scaling it up by 2x, then apply an inverse 1/2x transform to the swap chain to cancel out the 2x transform.
    DXGI_MATRIX_3X2_F inverseScale = { 0 };
    inverseScale._11 = 1.0f / m_compositionScaleX;
    inverseScale._22 = 1.0f / m_compositionScaleY;

    m_swapChain->SetMatrixTransform(&inverseScale);

    D2D1_BITMAP_PROPERTIES1 bitmapProperties =
        D2D1::BitmapProperties1(
            D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
            D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_PREMULTIPLIED),
            s_dipsPerInch * m_compositionScaleX,
            s_dipsPerInch * m_compositionScaleY
    );

    // Direct2D needs the DXGI version of the backbuffer surface pointer.
    Microsoft::WRL::ComPtr<IDXGISurface> dxgiBackBuffer;
    DX::ThrowIfFailed(
        m_swapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer))
    );

    // Get a D2D surface from the DXGI back buffer to use as the D2D render target.
    DX::ThrowIfFailed(
        m_d2dContext->CreateBitmapFromDxgiSurface(
            dxgiBackBuffer.Get(),
            &bitmapProperties,
            &m_d2dTargetBitmap
        )
    );

    m_d2dContext->SetDpi(s_dipsPerInch * m_compositionScaleX, s_dipsPerInch * m_compositionScaleY);
    m_d2dContext->SetTarget(m_d2dTargetBitmap.Get());

    if (setSwapChain)
    {
        SetSwapChain();
    }
}