Beispiel #1
0
gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
                                         const gl::Box &sourceArea,
                                         const TextureHelper11 &textureHelper,
                                         UINT sourceSubResource)
{
    // No conversion needed-- use copyback fastpath
    const TextureHelper11 *stagingTexture = nullptr;
    unsigned int stagingSubresourceIndex = 0;
    ANGLE_TRY(getStagingTexture(&stagingTexture, &stagingSubresourceIndex));

    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    const gl::Extents &extents = textureHelper.getExtents();

    D3D11_BOX srcBox;
    srcBox.left   = sourceArea.x;
    srcBox.right  = sourceArea.x + sourceArea.width;
    srcBox.top    = sourceArea.y;
    srcBox.bottom = sourceArea.y + sourceArea.height;
    srcBox.front  = sourceArea.z;
    srcBox.back   = sourceArea.z + sourceArea.depth;

    if (textureHelper.is2D() && textureHelper.getSampleCount() > 1)
    {
        D3D11_TEXTURE2D_DESC resolveDesc;
        resolveDesc.Width              = extents.width;
        resolveDesc.Height             = extents.height;
        resolveDesc.MipLevels          = 1;
        resolveDesc.ArraySize          = 1;
        resolveDesc.Format             = textureHelper.getFormat();
        resolveDesc.SampleDesc.Count   = 1;
        resolveDesc.SampleDesc.Quality = 0;
        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
        resolveDesc.BindFlags          = 0;
        resolveDesc.CPUAccessFlags     = 0;
        resolveDesc.MiscFlags          = 0;

        d3d11::Texture2D resolveTex;
        ANGLE_TRY(mRenderer->allocateResource(resolveDesc, &resolveTex));

        deviceContext->ResolveSubresource(resolveTex.get(), 0, textureHelper.get(),
                                          sourceSubResource, textureHelper.getFormat());

        deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
                                             destOffset.x, destOffset.y, destOffset.z,
                                             resolveTex.get(), 0, &srcBox);
    }
    else
    {
        deviceContext->CopySubresourceRegion(stagingTexture->get(), stagingSubresourceIndex,
                                             destOffset.x, destOffset.y, destOffset.z,
                                             textureHelper.get(), sourceSubResource, &srcBox);
    }

    mDirty = true;
    return gl::NoError();
}
Void D3D11TextureCube::Copy( D3D11TextureCube * pDstTexture, const D3D11SubResourceIndex * pDstIndex, D3D11TextureCubeFace iDstFace, const D3D11Point2 * pDstPoint,
                             const D3D11SubResourceIndex * pSrcIndex, D3D11TextureCubeFace iSrcFace, const D3D11Rectangle * pSrcRect, D3D11DeferredContext * pContext ) const
{
    DebugAssert( IsCreated() && pDstTexture->IsCreated() );
    DebugAssert( !m_bLocked && !(pDstTexture->m_bLocked) );
    DebugAssert( pDstTexture->CanGPUWrite() );

    DebugAssert( pDstTexture->m_hTextureDesc.Format == m_hTextureDesc.Format );

    UInt iSrcSubResource = _GetSubResourceIndex( pSrcIndex, iSrcFace, m_hTextureDesc.MipLevels, m_hTextureDesc.ArraySize );
    DebugAssert( pSrcRect->iLeft >= 0 && pSrcRect->iLeft < pSrcRect->iRight && pSrcRect->iRight <= (signed)_GetBound(m_hTextureDesc.Width,pSrcIndex->iMipSlice) );
    DebugAssert( pSrcRect->iTop >= 0 && pSrcRect->iTop < pSrcRect->iBottom && pSrcRect->iBottom <= (signed)_GetBound(m_hTextureDesc.Height,pSrcIndex->iMipSlice) );

    UInt iDstSubResource = _GetSubResourceIndex( pDstIndex, iDstFace, pDstTexture->m_hTextureDesc.MipLevels, pDstTexture->m_hTextureDesc.ArraySize );
    DebugAssert( pDstPoint->iX + (pSrcRect->iRight - pSrcRect->iLeft) <= _GetBound(pDstTexture->m_hTextureDesc.Width,pDstIndex->iMipSlice) );
    DebugAssert( pDstPoint->iY + (pSrcRect->iBottom - pSrcRect->iTop) <= _GetBound(pDstTexture->m_hTextureDesc.Height,pDstIndex->iMipSlice) );

    D3D11_BOX hSrcBox;
    hSrcBox.left = pSrcRect->iLeft;
    hSrcBox.right = pSrcRect->iRight;
    hSrcBox.top = pSrcRect->iTop;
    hSrcBox.bottom = pSrcRect->iBottom;
    hSrcBox.front = 0;
    hSrcBox.back = 1;
    
    ID3D11DeviceContext * pDeviceContext = m_pRenderer->m_pImmediateContext;
    if ( pContext != NULL && pContext->IsCreated() )
        pDeviceContext = pContext->m_pDeferredContext;

    pDeviceContext->CopySubresourceRegion( pDstTexture->m_pTexture, iDstSubResource, pDstPoint->iX, pDstPoint->iY, 0, m_pTexture, iSrcSubResource, &hSrcBox );
}
Void D3D11Texture3D::Copy( D3D11Texture3D * pDstTexture, const D3D11SubResourceIndex * pDstIndex, const D3D11Point3 * pDstPoint, const D3D11SubResourceIndex * pSrcIndex, const D3D11Box * pSrcBox,
                           D3D11DeferredContext * pContext ) const
{
    DebugAssert( IsCreated() && pDstTexture->IsCreated() );
    DebugAssert( !m_bLocked && !(pDstTexture->m_bLocked) );
    DebugAssert( pDstTexture->CanGPUWrite() );

    DebugAssert( pDstTexture->m_hTextureDesc.Format == m_hTextureDesc.Format );

    UInt iSrcSubResource = _GetSubResourceIndex( pSrcIndex, m_hTextureDesc.MipLevels, 1 );
    DebugAssert( pSrcBox->iLeft < pSrcBox->iRight && pSrcBox->iRight <= _GetBound(m_hTextureDesc.Width,pSrcIndex->iMipSlice) );
    DebugAssert( pSrcBox->iTop < pSrcBox->iBottom && pSrcBox->iBottom <= _GetBound(m_hTextureDesc.Height,pSrcIndex->iMipSlice) );
    DebugAssert( pSrcBox->iFront < pSrcBox->iBack && pSrcBox->iBack <= _GetBound(m_hTextureDesc.Depth,pSrcIndex->iMipSlice) );

    UInt iDstSubResource = _GetSubResourceIndex( pDstIndex, pDstTexture->m_hTextureDesc.MipLevels, 1 );
    DebugAssert( pDstPoint->iX + (pSrcBox->iRight - pSrcBox->iLeft) <= _GetBound(pDstTexture->m_hTextureDesc.Width,pDstIndex->iMipSlice) );
    DebugAssert( pDstPoint->iY + (pSrcBox->iBottom - pSrcBox->iTop) <= _GetBound(pDstTexture->m_hTextureDesc.Height,pDstIndex->iMipSlice) );
    DebugAssert( pDstPoint->iZ + (pSrcBox->iBack - pSrcBox->iFront) <= _GetBound(pDstTexture->m_hTextureDesc.Depth,pDstIndex->iMipSlice) );

    D3D11_BOX hSrcBox;
    hSrcBox.left = pSrcBox->iLeft;
    hSrcBox.right = pSrcBox->iRight;
    hSrcBox.top = pSrcBox->iTop;
    hSrcBox.bottom = pSrcBox->iBottom;
    hSrcBox.front = pSrcBox->iFront;
    hSrcBox.back = pSrcBox->iBack;
    
    ID3D11DeviceContext * pDeviceContext = m_pRenderer->m_pImmediateContext;
    if ( pContext != NULL && pContext->IsCreated() )
        pDeviceContext = pContext->m_pDeferredContext;

    pDeviceContext->CopySubresourceRegion( pDstTexture->m_pTexture, iDstSubResource, pDstPoint->iX, pDstPoint->iY, pDstPoint->iZ, m_pTexture, iSrcSubResource, &hSrcBox );
}
Void D3D11Texture1D::Copy( D3D11Texture1D * pDstTexture, const D3D11SubResourceIndex * pDstIndex, UInt iDstX, const D3D11SubResourceIndex * pSrcIndex, UInt iSrcX, UInt iSrcWidth, D3D11DeferredContext * pContext ) const
{
    DebugAssert( IsCreated() && pDstTexture->IsCreated() );
    DebugAssert( !m_bLocked && !(pDstTexture->m_bLocked) );
    DebugAssert( pDstTexture->CanGPUWrite() );

    DebugAssert( m_hTextureDesc.Format == pDstTexture->m_hTextureDesc.Format );

    UInt iSrcSubResource = _GetSubResourceIndex( pSrcIndex, m_hTextureDesc.MipLevels, m_hTextureDesc.ArraySize );
    DebugAssert( iSrcX + iSrcWidth <= _GetBound(m_hTextureDesc.Width,pSrcIndex->iMipSlice) );

    UInt iDstSubResource = _GetSubResourceIndex( pDstIndex, pDstTexture->m_hTextureDesc.MipLevels, pDstTexture->m_hTextureDesc.ArraySize );
    DebugAssert( iDstX + iSrcWidth <= _GetBound(pDstTexture->m_hTextureDesc.Width,pDstIndex->iMipSlice) );

    D3D11_BOX hSrcBox;
    hSrcBox.left = iSrcX;
    hSrcBox.right = iSrcX + iSrcWidth;
    hSrcBox.top = 0;
    hSrcBox.bottom = 1;
    hSrcBox.front = 0;
    hSrcBox.back = 1;

    ID3D11DeviceContext * pDeviceContext = m_pRenderer->m_pImmediateContext;
    if ( pContext != NULL && pContext->IsCreated() )
        pDeviceContext = pContext->m_pDeferredContext;

    pDeviceContext->CopySubresourceRegion( pDstTexture->m_pTexture, iDstSubResource, iDstX, 0, 0, m_pTexture, iSrcSubResource, &hSrcBox );
}
static bool grabFrameD3D11(IDXGISwapChain *swap)
{
  ID3D11Device *device = 0;
  ID3D11DeviceContext *context = 0;
  ID3D11Texture2D *tex = 0, *captureTex = 0;

  if (FAILED(swap->GetBuffer(0, IID_ID3D11Texture2D, (void**)&tex)))
    return false;

  D3D11_TEXTURE2D_DESC desc;
  tex->GetDevice(&device);
  tex->GetDesc(&desc);

  // re-creating the capture staging texture each frame is definitely not the most efficient
  // way to handle things, but it frees me of all kind of resource management trouble, so
  // here goes...
  desc.MipLevels = 1;
  desc.ArraySize = 1;
  desc.SampleDesc.Count = 1;
  desc.SampleDesc.Quality = 0;
  desc.Usage = D3D11_USAGE_STAGING;
  desc.BindFlags = 0;
  desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
  desc.MiscFlags = 0;

  if(FAILED(device->CreateTexture2D(&desc,0,&captureTex)))
    printLog("video/d3d11: couldn't create staging texture for gpu->cpu download!\n");
  else
    setCaptureResolution(desc.Width,desc.Height);

  device->GetImmediateContext(&context);
  context->CopySubresourceRegion(captureTex,0,0,0,0,tex,0,0);

  D3D11_MAPPED_SUBRESOURCE mapped;
  bool grabOk = false;

  if(captureTex && SUCCEEDED(context->Map(captureTex,0,D3D11_MAP_READ,0,&mapped)))
  {
    switch(desc.Format)
    {
    case DXGI_FORMAT_R8G8B8A8_UNORM:
      blitAndFlipRGBAToCaptureData((unsigned char *) mapped.pData,mapped.RowPitch);
      grabOk = true;
      break;

    default:
      printLog("video/d3d11: unsupported backbuffer format, can't grab pixels!\n");
      break;
    }

    context->Unmap(captureTex,0);
  }

  tex->Release();
  if(captureTex) captureTex->Release();
  context->Release();
  device->Release();

  return grabOk;
}
Beispiel #6
0
// Returns true if it recreates the direct buffer
bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset,
                                               size_t size, size_t destOffset)
{
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();

    size_t requiredSize = sourceOffset + size;
    bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;

    // (Re)initialize D3D buffer if needed
    if (createBuffer)
    {
        bool preserveData = (destOffset > 0);
        resize(source->getSize(), preserveData);
    }

    if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
        source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
    {
        ASSERT(source->isMappable());

        uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);

        D3D11_MAPPED_SUBRESOURCE mappedResource;
        HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource);
        UNUSED_ASSERTION_VARIABLE(hr);
        ASSERT(SUCCEEDED(hr));

        uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset;

        // Offset bounds are validated at the API layer
        ASSERT(sourceOffset + size <= destOffset + mBufferSize);
        memcpy(destPointer, sourcePointer, size);

        context->Unmap(mNativeStorage, 0);
        source->unmap();
    }
    else
    {
        ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));

        D3D11_BOX srcBox;
        srcBox.left = sourceOffset;
        srcBox.right = sourceOffset + size;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));
        ID3D11Buffer *sourceBuffer = static_cast<NativeStorage*>(source)->getNativeStorage();

        context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
    }

    return createBuffer;
}
Beispiel #7
0
gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
{
    ID3D11Device *device = mRenderer->getDevice();
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();

    D3D11_BUFFER_DESC bufferDesc;
    fillBufferDesc(&bufferDesc, mRenderer, mUsage, size);

    ID3D11Buffer *newBuffer;
    HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);

    if (FAILED(result))
    {
        return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result);
    }

    if (mNativeStorage && preserveData)
    {
        // We don't call resize if the buffer is big enough already.
        ASSERT(mBufferSize <= size);

        D3D11_BOX srcBox;
        srcBox.left = 0;
        srcBox.right = mBufferSize;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox);
    }

    // No longer need the old buffer
    SafeRelease(mNativeStorage);
    mNativeStorage = newBuffer;

    mBufferSize = bufferDesc.ByteWidth;

    return gl::Error(GL_NO_ERROR);
}
Beispiel #8
0
CBaseTexture* CGUIFontTTFDX::ReallocTexture(unsigned int& newHeight)
{
  assert(newHeight != 0);
  assert(m_textureWidth != 0);
  if(m_textureHeight == 0)
  {
    delete m_texture;
    m_texture = NULL;
    delete m_speedupTexture;
    m_speedupTexture = NULL;
  }
  m_staticCache.Flush();
  m_dynamicCache.Flush();

  CDXTexture* pNewTexture = new CDXTexture(m_textureWidth, newHeight, XB_FMT_A8);
  CD3DTexture* newSpeedupTexture = new CD3DTexture();
  if (!newSpeedupTexture->Create(m_textureWidth, newHeight, 1, D3D11_USAGE_DEFAULT, DXGI_FORMAT_R8_UNORM))
  {
    SAFE_DELETE(newSpeedupTexture);
    SAFE_DELETE(pNewTexture);
    return NULL;
  }

  ID3D11DeviceContext* pContext = g_Windowing.GetImmediateContext();

  // There might be data to copy from the previous texture
  if (newSpeedupTexture && m_speedupTexture)
  {
    CD3D11_BOX rect(0, 0, 0, m_textureWidth, m_textureHeight, 1);
    pContext->CopySubresourceRegion(newSpeedupTexture->Get(), 0, 0, 0, 0, m_speedupTexture->Get(), 0, &rect);
  }

  SAFE_DELETE(m_texture);
  SAFE_DELETE(m_speedupTexture);
  m_textureHeight = newHeight;
  m_textureScaleY = 1.0f / m_textureHeight;
  m_speedupTexture = newSpeedupTexture;

  return pNewTexture;
}
    void CCoherentViewListener::DrawFrameDX11SharedTexture( Coherent::UI::CoherentHandle handle, int width, int height )
    {
        if ( gCoherentUISystem == NULL )
        {
            return;
        }

        void* pNativeTexture = gCoherentUISystem->GetNativeTextureFromSharedHandle( handle );

        if ( pNativeTexture == NULL )
        {
            return;
        }

        ID3D11Texture2D* pSourceResource = static_cast<ID3D11Texture2D*>( pNativeTexture );
        ID3D11Texture2D* pDestResource = static_cast<ID3D11Texture2D*>( m_pTexture );

        ID3D11DeviceContext* pContext = NULL;
        ID3D11Device* pDevice = static_cast<ID3D11Device*>( gD3DDevice );
        pDevice->GetImmediateContext( &pContext );

        pContext->CopySubresourceRegion( pDestResource, 0, 0, 0, 0, pSourceResource, 0, NULL );
    }
bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData)
{
    ID3D11Device *device = mRenderer->getDevice();
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();

    D3D11_BUFFER_DESC bufferDesc;
    fillBufferDesc(&bufferDesc, mRenderer, mUsage, size);

    ID3D11Buffer *newBuffer;
    HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);

    if (FAILED(result))
    {
        return gl::error(GL_OUT_OF_MEMORY, false);
    }

    if (mNativeBuffer && preserveData)
    {
        D3D11_BOX srcBox;
        srcBox.left = 0;
        srcBox.right = size;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox);
    }

    // No longer need the old buffer
    SafeRelease(mNativeBuffer);
    mNativeBuffer = newBuffer;

    mBufferSize = bufferDesc.ByteWidth;

    return true;
}
void MultipleRenderTargetsWindow::OnIdle()
{
    mTimer.Measure();

    mCameraRig.Move();

    // Render the square to offscreen memory.
    mEngine->Enable(mDrawTarget);
    mEngine->ClearBuffers();
    mEngine->Draw(mSquare);
    mEngine->Disable(mDrawTarget);

    // PSMain of MultipleRenderTarget.hlsl has written linearized depth to the
    // depth buffer.  It is not possible to attach a depth-stencil texture as
    // a shader input; you cannot create a shader resource view for it.  The
    // best you can do is read it back from the GPU and copy it to a texture
    // that is a shader input.  NOTE: If you really want to use depth as a
    // shader input, pass the 'perspectiveDepth' to the pixel shader as is
    // done in MultipleRenderTarget.hlsl and write it to a render target, not
    // to the depth-stencil texture.  You can then attach that render target
    // as a shader input.  This avoids the expensive read-back-and-copy step
    // here.
    std::shared_ptr<TextureDS> dsTexture = mDrawTarget->GetDSTexture();

    // Simple code for reading the depth texture from GPU to CPU, repackaging
    // it as a regular texture, and uploading from CPU to GPU is as follows.
    // On the AMD 7970, the initial display runs at 720 fps for a 512x512
    // application window.
    //
    // mEngine->CopyGpuToCpu(dsTexture);
    // memcpy(mLinearDepth->GetData(), dsTexture->GetData(),
    //     dsTexture->GetNumBytes());
    // mEngine->CopyCpuToGpu(mLinearDepth);
    //
    // This block of code does
    //   gpu -> srcStaging -> cpu(lineardepth) -> dstStaging -> gpu
    // The block of code below skips the cpu memory,
    //   gpu -> srcStaging -> dstStaging -> gpu
    //
    // We currently do not have wrappers CopyGpuToStaging, CopyStagingToGpu,
    // or CopyStagingToStaging.  CopyGpuToGpu can use CopySubresourceRegion
    // or CopyRegion as long as the resources are compatible.  But in the
    // situation here, the depth format DF_D24_UNORM_S8_UINT is not compatible
    // with DF_R32_UINT according to the error messages produced by the D3D11
    // debug layer when calling CopyResource, even though the textures are the
    // dimensions and have the same number of bytes.  In fact, CopyResource
    // does not have a return value that indicates the failure to copy, so
    // how does one trap the error?  On the AMD 7970, the initial display
    // runs at 840 fps for a 512x512 application window.
    ID3D11DeviceContext* context = mEngine->GetImmediate();
    DX11TextureDS* srcTexture = (DX11TextureDS*)mEngine->Bind(dsTexture);
    ID3D11Resource* srcResource = srcTexture->GetDXResource();
    ID3D11Resource* srcStaging = srcTexture->GetStagingResource();
    DX11Texture2* dstTexture = (DX11Texture2*)mEngine->Bind(mLinearDepth);
    ID3D11Resource* dstResource = dstTexture->GetDXResource();
    ID3D11Resource* dstStaging = dstTexture->GetStagingResource();
    context->CopySubresourceRegion(srcStaging, 0, 0, 0, 0, srcResource, 0,
        nullptr);
    D3D11_MAPPED_SUBRESOURCE srcSub, dstSub;
    HRESULT hr = context->Map(srcStaging, 0, D3D11_MAP_READ, 0, &srcSub);
    hr = context->Map(dstStaging, 0, D3D11_MAP_WRITE, 0, &dstSub);
    Memcpy(dstSub.pData, srcSub.pData, dsTexture->GetNumBytes());
    context->Unmap(srcStaging, 0);
    context->Unmap(dstStaging, 0);
    context->CopySubresourceRegion(dstResource, 0, 0, 0, 0, dstStaging, 0,
        nullptr);

    if (mActiveOverlay == 0)
    {
        // mSquare was rendered to the render target attached to mOverlay[0].
        // Draw the overlay, which contains the stone-textured 3D rendering.
        mEngine->Draw(mOverlay[0]);
    }
    else if (1 <= mActiveOverlay && mActiveOverlay <= 4)
    {
        mEngine->Draw(mOverlay[mActiveOverlay]);
    }
    else if (mActiveOverlay == 5)
    {
        // The output depth for the rendering of mSquare is set to linearized
        // depth, not the default perspective depth.  The depth texture of the
        // draw target is of the form 0xSSDDDDDD, which means the high-order
        // 8 bits are stencil values and the low-order 24 bits are depth values.
        // The depth texture was read from GPU to CPU as a 32-bit integer and
        // copied to mLinearDepth, a regular 2D texture with format R32_INT.
        // This texture is attached as an input to the gsOverlay1PShader pixel
        // shader and used as the pixel color output, which is the texture
        // attached to mOverlay[1].  The linearized depth as R32_INT has
        // values between 0 and 0xFFFFFF (16777215) but is normalized to
        // [0,1] on output.  The background is white because the depth buffer
        // was cleared to 1.0f, causing linearized depth to be 0xFFFFFF, and
        // normalized output to be 1.0f.  Rotate the square so it is not
        // parallel to the view direction and  move the camera backward
        // (press down arrow) so that the square is clipped by the far plane.
        // You will see the linearized depth become gray-to-white close to the
        // far plane, indicating the depth is varying from 0.0f (close to
        // near) to 1.0f (close to far).
        mEngine->Draw(mOverlay[5]);
    }
    else // mActiveOverlay == 6
    {
        // mOverlay[1] causes the gsOverlay1PShader shader to be executed,
        // which leads to writing the UAV colorTexture that is attached to
        // mOverlay[2].  We then draw that color texture using mOverlay[2].
        // This verifies that indeed the UAV can be written by a pixel
        // shader.
        mEngine->Draw(mOverlay[5]);
        mEngine->Draw(mOverlay[6]);
    }

    mEngine->Draw(8, mYSize - 8, { 0.0f, 0.0f, 0.0f, 1.0f }, mTimer.GetFPS());
    mEngine->DisplayColorBuffer(0);

    mTimer.UpdateFrameCount();
}
void D3D11Grab(ID3D11Texture2D *pBackBuffer) {
    D3D11_TEXTURE2D_DESC tex_desc;
    pBackBuffer->GetDesc(&tex_desc);

    ID3D11Device *pDev;
    pBackBuffer->GetDevice(&pDev);
    ID3D11DeviceContext * pDevContext;
    pDev->GetImmediateContext(&pDevContext);

    ID3D11Texture2D * pTexture;
    D3D11_MAPPED_SUBRESOURCE mappedTexture;
    tex_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    tex_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    tex_desc.ArraySize = 1;
    tex_desc.MipLevels = 1;
    tex_desc.BindFlags = 0;
    tex_desc.SampleDesc.Count = 1;
    tex_desc.SampleDesc.Quality = 0;
    tex_desc.Usage = D3D11_USAGE_STAGING;
    tex_desc.MiscFlags = 0;

    HRESULT hr = pDev->CreateTexture2D(&tex_desc, NULL, &pTexture);
//    reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 pDev->CreateTexture2D 0x%x", hr);

    pDevContext->CopyResource(pTexture, pBackBuffer);
    D3D11_BOX box = {0, 0, tex_desc.Width, tex_desc.Height, 0, 1};
    pDevContext->CopySubresourceRegion(pTexture, 0, 0, 0, 0, pBackBuffer, 0, &box);

    DxgiFrameGrabber *dxgiFrameGrabber = DxgiFrameGrabber::getInstance();
    IPCContext *ipcContext = dxgiFrameGrabber->m_ipcContext;
    Logger *logger = dxgiFrameGrabber->m_logger;

    //        __asm__("int $3");
    if (S_OK != (hr = pDevContext->Map(pTexture, D3D11CalcSubresource(0, 0, 1), D3D11_MAP_READ, 0, &mappedTexture))) {
        logger->reportLogError(L"d3d11 couldn't map texture, hresult = 0x%x", hr);
        goto end;
    }

    ipcContext->m_memDesc.width = tex_desc.Width;
    ipcContext->m_memDesc.height = tex_desc.Height;
    ipcContext->m_memDesc.rowPitch = mappedTexture.RowPitch;
    ipcContext->m_memDesc.frameId++;

//    reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 texture description. width: %u, height: %u, pitch: %u", tex_desc.Width, tex_desc.Height, mappedTexture.RowPitch);

    DWORD errorcode;
    if (WAIT_OBJECT_0 == (errorcode = WaitForSingleObject(ipcContext->m_hMutex, 0))) {
        //            __asm__("int $3");
//        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 writing description to mem mapped file");
        memcpy(ipcContext->m_pMemMap, &ipcContext->m_memDesc, sizeof (ipcContext->m_memDesc));
//        reportLog(EVENTLOG_INFORMATION_TYPE, L"d3d11 writing data to mem mapped file");
        PVOID pMemDataMap = incPtr(ipcContext->m_pMemMap, sizeof (ipcContext->m_memDesc));
        if (mappedTexture.RowPitch == tex_desc.Width * 4) {
            memcpy(pMemDataMap, mappedTexture.pData, tex_desc.Width * tex_desc.Height * 4);
        } else {
            UINT i = 0, cleanOffset = 0, pitchOffset = 0;
            while (i < tex_desc.Height) {
                memcpy(incPtr(pMemDataMap, cleanOffset), incPtr(mappedTexture.pData, pitchOffset), tex_desc.Width * 4);
                cleanOffset += tex_desc.Width * 4;
                pitchOffset += mappedTexture.RowPitch;
                i++;
            }
        }
        ReleaseMutex(ipcContext->m_hMutex);
        SetEvent(ipcContext->m_hFrameGrabbedEvent);
    } else {
        logger->reportLogError(L"d3d11 couldn't wait mutex. errocode = 0x%x", errorcode);
    }

    pDevContext->Unmap(pTexture, D3D10CalcSubresource(0, 0, 1));
end:
    pTexture->Release();
    pDevContext->Release();
    pDev->Release();
}
void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset, GLenum bindingPoint)
{
    ID3D11Device *device = mRenderer->getDevice();
    ID3D11DeviceContext *context = mRenderer->getDeviceContext();
    HRESULT result;

    unsigned int requiredBufferSize = size + offset;
    unsigned int requiredStagingSize = size;
    bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);

    if (!directInitialization)
    {
        if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize)
        {
            if (mStagingBuffer)
            {
                mStagingBuffer->Release();
                mStagingBuffer = NULL;
                mStagingBufferSize = 0;
            }

            D3D11_BUFFER_DESC bufferDesc;
            bufferDesc.ByteWidth = size;
            bufferDesc.Usage = D3D11_USAGE_STAGING;
            bufferDesc.BindFlags = 0;
            bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
            bufferDesc.MiscFlags = 0;
            bufferDesc.StructureByteStride = 0;

            if (data)
            {
                D3D11_SUBRESOURCE_DATA initialData;
                initialData.pSysMem = data;
                initialData.SysMemPitch = size;
                initialData.SysMemSlicePitch = 0;

                result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer);
            }
            else
            {
                result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
            }

            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY);
            }

            mStagingBufferSize = size;
        }
        else if (data)
        {
            D3D11_MAPPED_SUBRESOURCE mappedResource;
            result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY);
            }

            memcpy(mappedResource.pData, data, size);

            context->Unmap(mStagingBuffer, 0);
        }
    }

    if (!mBuffer || mBufferSize < size + offset)
    {
        D3D11_BUFFER_DESC bufferDesc;
        bufferDesc.ByteWidth = requiredBufferSize;
        bufferDesc.Usage = D3D11_USAGE_DEFAULT;
        if (mRenderer->getMajorShaderModel() > 2)
            bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
        else
        {
            if (bindingPoint == GL_ARRAY_BUFFER)
                bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
            else
                bufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
        }
        bufferDesc.CPUAccessFlags = 0;
        bufferDesc.MiscFlags = 0;
        bufferDesc.StructureByteStride = 0;

        if (directInitialization)
        {
            // Since the data will fill the entire buffer (being larger than the initial size and having
            // no offset), the buffer can be initialized with the data so no staging buffer is required

            // No longer need the old buffer
            if (mBuffer)
            {
                mBuffer->Release();
                mBuffer = NULL;
                mBufferSize = 0;
            }

            if (data)
            {
                D3D11_SUBRESOURCE_DATA initialData;
                initialData.pSysMem = data;
                initialData.SysMemPitch = size;
                initialData.SysMemSlicePitch = 0;

                result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer);
            }
            else
            {
                result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
            }

            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY);
            }
        }
        else if (mBuffer && offset > 0)
        {
            // If offset is greater than zero and the buffer is non-null, need to preserve the data from
            // the old buffer up to offset
            ID3D11Buffer *newBuffer = NULL;

            result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY);
            }

            D3D11_BOX srcBox;
            srcBox.left = 0;
            srcBox.right = std::min(offset, mBufferSize);
            srcBox.top = 0;
            srcBox.bottom = 1;
            srcBox.front = 0;
            srcBox.back = 1;

            context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);

            mBuffer->Release();
            mBuffer = newBuffer;
        }
        else
        {
            // Simple case, nothing needs to be copied from the old buffer to the new one, just create
            // a new buffer

            // No longer need the old buffer
            if (mBuffer)
            {
                mBuffer->Release();
                mBuffer = NULL;
                mBufferSize = 0;
            }

            // Create a new buffer for data storage
            result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY);
            }
        }

        updateSerial();
        mBufferSize = bufferDesc.ByteWidth;
    }

    if (!directInitialization)
    {
        ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize);

        // Data is already put into the staging buffer, copy it over to the data buffer
        D3D11_BOX srcBox;
        srcBox.left = 0;
        srcBox.right = size;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox);
    }

    mSize = std::max(mSize, offset + size);

    mWriteUsageCount = 0;

    mResolvedDataValid = false;
}
void *BufferStorage11::getData()
{
    if (!mResolvedDataValid)
    {
        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *context = mRenderer->getDeviceContext();
        HRESULT result;

        if (!mStagingBuffer || mStagingBufferSize < mBufferSize)
        {
            if (mStagingBuffer)
            {
                mStagingBuffer->Release();
                mStagingBuffer = NULL;
                mStagingBufferSize = 0;
            }

            D3D11_BUFFER_DESC bufferDesc;
            bufferDesc.ByteWidth = mSize;
            bufferDesc.Usage = D3D11_USAGE_STAGING;
            bufferDesc.BindFlags = 0;
            bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
            bufferDesc.MiscFlags = 0;
            bufferDesc.StructureByteStride = 0;

            result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
            if (FAILED(result))
            {
                return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
            }

            mStagingBufferSize = bufferDesc.ByteWidth;
        }

        if (!mResolvedData || mResolvedDataSize < mBufferSize)
        {
            free(mResolvedData);
            mResolvedData = malloc(mSize);
            mResolvedDataSize = mSize;
        }

        D3D11_BOX srcBox;
        srcBox.left = 0;
        srcBox.right = mSize;
        srcBox.top = 0;
        srcBox.bottom = 1;
        srcBox.front = 0;
        srcBox.back = 1;

        context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);

        D3D11_MAPPED_SUBRESOURCE mappedResource;
        result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
        if (FAILED(result))
        {
            return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
        }

        memcpy(mResolvedData, mappedResource.pData, mSize);

        context->Unmap(mStagingBuffer, 0);

        mResolvedDataValid = true;
    }

    mReadUsageCount = 0;

    return mResolvedData;
}
Beispiel #15
0
mfxStatus D3D11FrameAllocator::LockFrame(mfxMemId mid, mfxFrameData *ptr)
{
    HRESULT hRes = S_OK;

    D3D11_TEXTURE2D_DESC desc = {0};
    D3D11_MAPPED_SUBRESOURCE lockedRect = {0};

    //check that texture exists
    TextureSubResource sr = GetResourceFromMid(mid);
    if (!sr.GetTexture())
        return MFX_ERR_LOCK_MEMORY;

    D3D11_MAP mapType = D3D11_MAP_READ;
    UINT mapFlags = D3D11_MAP_FLAG_DO_NOT_WAIT;
    {
        ASSERT(NULL != sr.GetStaging());
        sr.GetTexture()->GetDesc(&desc);

        if (DXGI_FORMAT_NV12 != desc.Format)
        {
            return MFX_ERR_LOCK_MEMORY;
        }

#ifdef D3D11_PARALLEL_COPY  
        // copy original frame to staging frame - CPU can't access original frame
        // parallel copy is a little faster
        D3D11_BOX box;
        MSDK_ZERO_VAR(box);
        D3D11_TEXTURE2D_DESC desc;
        sr.GetTexture()->GetDesc(&desc);
        box.right = desc.Width;
        box.bottom = desc.Height;

        int count = 2;
        ID3D11DeviceContext* pDeviceContext = m_pDeviceContext;
        Concurrency::parallel_for(0, count+1, [pDeviceContext, &sr, &box, count](int i)
        {
            int block = MSDK_ALIGN16(box.bottom / count);
            D3D11_BOX tmp_box = box;
            tmp_box.top    = i * block;
            tmp_box.bottom = (i == count) ? box.bottom : tmp_box.top + block;
            pDeviceContext->CopySubresourceRegion(sr.GetStaging(), 0, tmp_box.left, tmp_box.top, 0, sr.GetTexture(), sr.GetSubResource(), &tmp_box); 
        });
#else
        // Single threaded copy
        m_pDeviceContext->CopySubresourceRegion(sr.GetStaging(), 0, 0, 0, 0, sr.GetTexture(), sr.GetSubResource(), NULL); 
#endif
        do
        {
            hRes = m_pDeviceContext->Map(sr.GetStaging(), 0, mapType, mapFlags, &lockedRect);
            if (S_OK != hRes && DXGI_ERROR_WAS_STILL_DRAWING != hRes)
            {
                MSDK_TRACE("ERROR: m_pDeviceContext->Map = 0x%lX\n", hRes);
            }
        }
        while (DXGI_ERROR_WAS_STILL_DRAWING == hRes);
    }

    if (FAILED(hRes))
        return MFX_ERR_LOCK_MEMORY;

    MSDK_CHECK_NOT_EQUAL(desc.Format, DXGI_FORMAT_NV12, MFX_ERR_LOCK_MEMORY);
    ptr->Pitch = (mfxU16)lockedRect.RowPitch;
    ptr->Y = (mfxU8 *)lockedRect.pData;
    ptr->U = (mfxU8 *)lockedRect.pData + desc.Height * lockedRect.RowPitch;
    ptr->V = ptr->U + 1;

    return MFX_ERR_NONE;
}
Beispiel #16
0
void Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
{
    gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();

    if (colorbuffer && colorbuffer->getActualFormat() == mActualFormat)
    {
        // No conversion needed-- use copyback fastpath
        ID3D11Texture2D *colorBufferTexture = NULL;
        unsigned int subresourceIndex = 0;

        if (mRenderer->getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture))
        {
            D3D11_TEXTURE2D_DESC textureDesc;
            colorBufferTexture->GetDesc(&textureDesc);

            ID3D11Device *device = mRenderer->getDevice();
            ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

            ID3D11Texture2D* srcTex = NULL;
            if (textureDesc.SampleDesc.Count > 1)
            {
                D3D11_TEXTURE2D_DESC resolveDesc;
                resolveDesc.Width = textureDesc.Width;
                resolveDesc.Height = textureDesc.Height;
                resolveDesc.MipLevels = 1;
                resolveDesc.ArraySize = 1;
                resolveDesc.Format = textureDesc.Format;
                resolveDesc.SampleDesc.Count = 1;
                resolveDesc.SampleDesc.Quality = 0;
                resolveDesc.Usage = D3D11_USAGE_DEFAULT;
                resolveDesc.BindFlags = 0;
                resolveDesc.CPUAccessFlags = 0;
                resolveDesc.MiscFlags = 0;

                HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
                if (FAILED(result))
                {
                    ERR("Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
                    return;
                }

                deviceContext->ResolveSubresource(srcTex, 0, colorBufferTexture, subresourceIndex, textureDesc.Format);
                subresourceIndex = 0;
            }
            else
            {
                srcTex = colorBufferTexture;
                srcTex->AddRef();
            }

            D3D11_BOX srcBox;
            srcBox.left = x;
            srcBox.right = x + width;
            srcBox.top = y;
            srcBox.bottom = y + height;
            srcBox.front = 0;
            srcBox.back = 1;

            deviceContext->CopySubresourceRegion(mStagingTexture, 0, xoffset, yoffset, zoffset, srcTex, subresourceIndex, &srcBox);

            SafeRelease(srcTex);
            SafeRelease(colorBufferTexture);
        }
    }
    else
    {
        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
        D3D11_MAPPED_SUBRESOURCE mappedImage;
        HRESULT result = map(D3D11_MAP_WRITE, &mappedImage);
        if (FAILED(result))
        {
            ERR("Failed to map texture for Image11::copy, HRESULT: 0x%X.", result);
            return;
        }

        // determine the offset coordinate into the destination buffer
        GLsizei rowOffset = gl::GetPixelBytes(mActualFormat) * xoffset;
        void *dataOffset = static_cast<unsigned char*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;

        GLenum format = gl::GetFormat(mInternalFormat);
        GLenum type = gl::GetType(mInternalFormat);

        mRenderer->readPixels(source, x, y, width, height, format, type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);

        unmap();
    }
}
Beispiel #17
0
gl::Error Image11::copyWithoutConversion(const gl::Offset &destOffset,
                                         const gl::Box &sourceArea,
                                         const TextureHelper11 &textureHelper,
                                         UINT sourceSubResource)
{
    // No conversion needed-- use copyback fastpath
    ID3D11Resource *stagingTexture       = nullptr;
    unsigned int stagingSubresourceIndex = 0;
    gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
    if (error.isError())
    {
        return error;
    }

    ID3D11Device *device               = mRenderer->getDevice();
    ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

    UINT subresourceAfterResolve = sourceSubResource;

    ID3D11Resource *srcTex     = nullptr;
    const gl::Extents &extents = textureHelper.getExtents();

    bool needResolve =
        (textureHelper.getTextureType() == GL_TEXTURE_2D && textureHelper.getSampleCount() > 1);

    if (needResolve)
    {
        D3D11_TEXTURE2D_DESC resolveDesc;
        resolveDesc.Width              = extents.width;
        resolveDesc.Height             = extents.height;
        resolveDesc.MipLevels          = 1;
        resolveDesc.ArraySize          = 1;
        resolveDesc.Format             = textureHelper.getFormat();
        resolveDesc.SampleDesc.Count   = 1;
        resolveDesc.SampleDesc.Quality = 0;
        resolveDesc.Usage              = D3D11_USAGE_DEFAULT;
        resolveDesc.BindFlags          = 0;
        resolveDesc.CPUAccessFlags     = 0;
        resolveDesc.MiscFlags          = 0;

        ID3D11Texture2D *srcTex2D = NULL;
        HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
        if (FAILED(result))
        {
            return gl::Error(GL_OUT_OF_MEMORY,
                             "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.",
                             result);
        }
        srcTex = srcTex2D;

        deviceContext->ResolveSubresource(srcTex, 0, textureHelper.getTexture2D(),
                                          sourceSubResource, textureHelper.getFormat());
        subresourceAfterResolve = 0;
    }
    else
    {
        srcTex = textureHelper.getResource();
    }

    D3D11_BOX srcBox;
    srcBox.left   = sourceArea.x;
    srcBox.right  = sourceArea.x + sourceArea.width;
    srcBox.top    = sourceArea.y;
    srcBox.bottom = sourceArea.y + sourceArea.height;
    srcBox.front  = sourceArea.z;
    srcBox.back   = sourceArea.z + sourceArea.depth;

    deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x,
                                         destOffset.y, destOffset.z, srcTex,
                                         subresourceAfterResolve, &srcBox);

    if (needResolve)
    {
        SafeRelease(srcTex);
    }

    mDirty = true;
    return gl::Error(GL_NO_ERROR);
}
Beispiel #18
0
gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
{
    gl::Error error = flushQueuedPackCommand();
    if (error.isError())
    {
        return error;
    }

    mQueuedPackCommand = new PackPixelsParams(params);

    D3D11_TEXTURE2D_DESC textureDesc;
    srcTexure->GetDesc(&textureDesc);

    if (mStagingTexture != NULL &&
        (mTextureFormat != textureDesc.Format ||
         mTextureSize.width != params.area.width ||
         mTextureSize.height != params.area.height))
    {
        SafeRelease(mStagingTexture);
        mTextureSize.width = 0;
        mTextureSize.height = 0;
        mTextureFormat = DXGI_FORMAT_UNKNOWN;
    }

    if (mStagingTexture == NULL)
    {
        ID3D11Device *device = mRenderer->getDevice();
        HRESULT hr;

        mTextureSize.width = params.area.width;
        mTextureSize.height = params.area.height;
        mTextureFormat = textureDesc.Format;

        D3D11_TEXTURE2D_DESC stagingDesc;
        stagingDesc.Width = params.area.width;
        stagingDesc.Height = params.area.height;
        stagingDesc.MipLevels = 1;
        stagingDesc.ArraySize = 1;
        stagingDesc.Format = mTextureFormat;
        stagingDesc.SampleDesc.Count = 1;
        stagingDesc.SampleDesc.Quality = 0;
        stagingDesc.Usage = D3D11_USAGE_STAGING;
        stagingDesc.BindFlags = 0;
        stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
        stagingDesc.MiscFlags = 0;

        hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
        if (FAILED(hr))
        {
            ASSERT(hr == E_OUTOFMEMORY);
            return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture.");
        }
    }

    // ReadPixels from multisampled FBOs isn't supported in current GL
    ASSERT(textureDesc.SampleDesc.Count <= 1);

    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
    D3D11_BOX srcBox;
    srcBox.left   = params.area.x;
    srcBox.right  = params.area.x + params.area.width;
    srcBox.top    = params.area.y;
    srcBox.bottom = params.area.y + params.area.height;
    srcBox.front  = 0;
    srcBox.back   = 1;

    // Asynchronous copy
    immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);

    return gl::Error(GL_NO_ERROR);
}
Beispiel #19
0
EGLint SwapChain11::resetOffscreenColorBuffer(int backbufferWidth, int backbufferHeight)
{
    ASSERT(mNeedsOffscreenTexture);

    TRACE_EVENT0("gpu.angle", "SwapChain11::resetOffscreenTexture");
    ID3D11Device *device = mRenderer->getDevice();

    ASSERT(device != NULL);

    // D3D11 does not allow zero size textures
    ASSERT(backbufferWidth >= 1);
    ASSERT(backbufferHeight >= 1);

    // Preserve the render target content
    ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
    if (previousOffscreenTexture)
    {
        previousOffscreenTexture->AddRef();
    }
    const int previousWidth = mWidth;
    const int previousHeight = mHeight;

    releaseOffscreenColorBuffer();

    const d3d11::Format &backbufferFormatInfo =
        d3d11::Format::Get(mOffscreenRenderTargetFormat, mRenderer->getRenderer11DeviceCaps());

    // If the app passed in a share handle, open the resource
    // See EGL_ANGLE_d3d_share_handle_client_buffer
    if (mAppCreatedShareHandle)
    {
        ID3D11Resource *tempResource11;
        HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);

        if (FAILED(result))
        {
            ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
            release();
            return EGL_BAD_PARAMETER;
        }

        result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
        SafeRelease(tempResource11);

        if (FAILED(result))
        {
            ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
            release();
            return EGL_BAD_PARAMETER;
        }

        // Validate offscreen texture parameters
        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
        mOffscreenTexture->GetDesc(&offscreenTextureDesc);

        if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
            offscreenTextureDesc.Height != (UINT)backbufferHeight ||
            offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
            offscreenTextureDesc.MipLevels != 1 || offscreenTextureDesc.ArraySize != 1)
        {
            ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
            release();
            return EGL_BAD_PARAMETER;
        }
    }
    else
    {
        const bool useSharedResource =
            !mNativeWindow->getNativeWindow() && mRenderer->getShareHandleSupport();

        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
        offscreenTextureDesc.Width = backbufferWidth;
        offscreenTextureDesc.Height = backbufferHeight;
        offscreenTextureDesc.Format               = backbufferFormatInfo.texFormat;
        offscreenTextureDesc.MipLevels = 1;
        offscreenTextureDesc.ArraySize = 1;
        offscreenTextureDesc.SampleDesc.Count = 1;
        offscreenTextureDesc.SampleDesc.Quality = 0;
        offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
        offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
        offscreenTextureDesc.CPUAccessFlags = 0;
        offscreenTextureDesc.MiscFlags = useSharedResource ? ANGLE_RESOURCE_SHARE_TYPE : 0;

        HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);

        if (FAILED(result))
        {
            ERR("Could not create offscreen texture: %08lX", result);
            release();

            if (d3d11::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }

        d3d11::SetDebugName(mOffscreenTexture, "Offscreen back buffer texture");

        // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
        if (useSharedResource)
        {
            IDXGIResource *offscreenTextureResource = NULL;
            result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);

            // Fall back to no share handle on failure
            if (FAILED(result))
            {
                ERR("Could not query offscreen texture resource: %08lX", result);
            }
            else
            {
                result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
                SafeRelease(offscreenTextureResource);

                if (FAILED(result))
                {
                    mShareHandle = NULL;
                    ERR("Could not get offscreen texture shared handle: %08lX", result);
                }
            }
        }
    }

    // This may return null if the original texture was created without a keyed mutex.
    mKeyedMutex = d3d11::DynamicCastComObject<IDXGIKeyedMutex>(mOffscreenTexture);

    D3D11_RENDER_TARGET_VIEW_DESC offscreenRTVDesc;
    offscreenRTVDesc.Format             = backbufferFormatInfo.rtvFormat;
    offscreenRTVDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
    offscreenRTVDesc.Texture2D.MipSlice = 0;

    HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, &offscreenRTVDesc, &mOffscreenRTView);
    ASSERT(SUCCEEDED(result));
    d3d11::SetDebugName(mOffscreenRTView, "Offscreen back buffer render target");

    D3D11_SHADER_RESOURCE_VIEW_DESC offscreenSRVDesc;
    offscreenSRVDesc.Format                    = backbufferFormatInfo.srvFormat;
    offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
    offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
    offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);

    result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
    ASSERT(SUCCEEDED(result));
    d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");

    if (previousOffscreenTexture != nullptr)
    {
        D3D11_BOX sourceBox = {0};
        sourceBox.left      = 0;
        sourceBox.right     = std::min(previousWidth, backbufferWidth);
        sourceBox.top       = std::max(previousHeight - backbufferHeight, 0);
        sourceBox.bottom    = previousHeight;
        sourceBox.front     = 0;
        sourceBox.back      = 1;

        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
        const int yoffset = std::max(backbufferHeight - previousHeight, 0);
        deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0,
                                             previousOffscreenTexture, 0, &sourceBox);

        SafeRelease(previousOffscreenTexture);

        if (mSwapChain)
        {
            swapRect(0, 0, backbufferWidth, backbufferHeight);
        }
    }

    return EGL_SUCCESS;
}
Beispiel #20
0
gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource)
{
    D3D11_RESOURCE_DIMENSION dim;
    source->GetType(&dim);

    DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
    gl::Extents extents;
    UINT sampleCount = 0;

    ID3D11Texture2D *source2D = NULL;

    if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
    {
        D3D11_TEXTURE2D_DESC textureDesc2D;
        source2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(source);
        ASSERT(source2D);
        source2D->GetDesc(&textureDesc2D);

        format = textureDesc2D.Format;
        extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1);
        sampleCount = textureDesc2D.SampleDesc.Count;
    }
    else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
    {
        D3D11_TEXTURE3D_DESC textureDesc3D;
        ID3D11Texture3D *source3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(source);
        ASSERT(source3D);
        source3D->GetDesc(&textureDesc3D);

        format = textureDesc3D.Format;
        extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth);
        sampleCount = 1;
    }
    else
    {
        UNREACHABLE();
    }

    if (format == mDXGIFormat)
    {
        // No conversion needed-- use copyback fastpath
        ID3D11Resource *stagingTexture = NULL;
        unsigned int stagingSubresourceIndex = 0;
        gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
        if (error.isError())
        {
            return error;
        }

        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

        UINT subresourceAfterResolve = sourceSubResource;

        ID3D11Resource *srcTex = NULL;

        bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1);

        if (needResolve)
        {
            D3D11_TEXTURE2D_DESC resolveDesc;
            resolveDesc.Width = extents.width;
            resolveDesc.Height = extents.height;
            resolveDesc.MipLevels = 1;
            resolveDesc.ArraySize = 1;
            resolveDesc.Format = format;
            resolveDesc.SampleDesc.Count = 1;
            resolveDesc.SampleDesc.Quality = 0;
            resolveDesc.Usage = D3D11_USAGE_DEFAULT;
            resolveDesc.BindFlags = 0;
            resolveDesc.CPUAccessFlags = 0;
            resolveDesc.MiscFlags = 0;

            ID3D11Texture2D *srcTex2D = NULL;
            HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
            if (FAILED(result))
            {
                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
            }
            srcTex = srcTex2D;

            deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format);
            subresourceAfterResolve = 0;
        }
        else
        {
            srcTex = source;
        }

        D3D11_BOX srcBox;
        srcBox.left = sourceArea.x;
        srcBox.right = sourceArea.x + sourceArea.width;
        srcBox.top = sourceArea.y;
        srcBox.bottom = sourceArea.y + sourceArea.height;
        srcBox.front = sourceArea.z;
        srcBox.back = sourceArea.z + sourceArea.depth;

        deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y,
                                             destOffset.z, srcTex, subresourceAfterResolve, &srcBox);

        if (needResolve)
        {
            SafeRelease(srcTex);
        }
    }
    else
    {
        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
        D3D11_MAPPED_SUBRESOURCE mappedImage;
        gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
        if (error.isError())
        {
            return error;
        }

        // determine the offset coordinate into the destination buffer
        const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
        GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x;
        uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch;

        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);

        // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer
        // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats.
        ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D);
        ASSERT(sourceArea.z == 0 && sourceArea.depth == 1);
        gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height);
        error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);

        unmap();

        if (error.isError())
        {
            return error;
        }
    }

    mDirty = true;

    return gl::Error(GL_NO_ERROR);
}
void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
{
    flushQueuedPackCommand();
    mQueuedPackCommand = new PackPixelsParams(params);

    D3D11_TEXTURE2D_DESC textureDesc;
    srcTexure->GetDesc(&textureDesc);

    if (mStagingTexture != NULL &&
        (mTextureFormat != textureDesc.Format ||
         mTextureSize.width != params.area.width ||
         mTextureSize.height != params.area.height))
    {
        SafeRelease(mStagingTexture);
        mTextureSize.width = 0;
        mTextureSize.height = 0;
        mTextureFormat = DXGI_FORMAT_UNKNOWN;
    }

    if (mStagingTexture == NULL)
    {
        ID3D11Device *device = mRenderer->getDevice();
        HRESULT hr;

        mTextureSize.width = params.area.width;
        mTextureSize.height = params.area.height;
        mTextureFormat = textureDesc.Format;

        D3D11_TEXTURE2D_DESC stagingDesc;
        stagingDesc.Width = params.area.width;
        stagingDesc.Height = params.area.height;
        stagingDesc.MipLevels = 1;
        stagingDesc.ArraySize = 1;
        stagingDesc.Format = mTextureFormat;
        stagingDesc.SampleDesc.Count = 1;
        stagingDesc.SampleDesc.Quality = 0;
        stagingDesc.Usage = D3D11_USAGE_STAGING;
        stagingDesc.BindFlags = 0;
        stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
        stagingDesc.MiscFlags = 0;

        hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
        ASSERT(SUCCEEDED(hr));
    }

    if (textureDesc.SampleDesc.Count > 1)
    {
        UNIMPLEMENTED();
    }

    ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
    D3D11_BOX srcBox;
    srcBox.left   = params.area.x;
    srcBox.right  = params.area.x + params.area.width;
    srcBox.top    = params.area.y;
    srcBox.bottom = params.area.y + params.area.height;
    srcBox.front  = 0;
    srcBox.back   = 1;

    // Asynchronous copy
    immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
}
Beispiel #22
0
gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource)
{
    D3D11_TEXTURE2D_DESC textureDesc;
    source->GetDesc(&textureDesc);

    if (textureDesc.Format == mDXGIFormat)
    {
        // No conversion needed-- use copyback fastpath
        ID3D11Resource *stagingTexture = NULL;
        unsigned int stagingSubresourceIndex = 0;
        gl::Error error = getStagingTexture(&stagingTexture, &stagingSubresourceIndex);
        if (error.isError())
        {
            return error;
        }

        ID3D11Device *device = mRenderer->getDevice();
        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();

        UINT subresourceAfterResolve = sourceSubResource;

        ID3D11Texture2D* srcTex = NULL;
        if (textureDesc.SampleDesc.Count > 1)
        {
            D3D11_TEXTURE2D_DESC resolveDesc;
            resolveDesc.Width = textureDesc.Width;
            resolveDesc.Height = textureDesc.Height;
            resolveDesc.MipLevels = 1;
            resolveDesc.ArraySize = 1;
            resolveDesc.Format = textureDesc.Format;
            resolveDesc.SampleDesc.Count = 1;
            resolveDesc.SampleDesc.Quality = 0;
            resolveDesc.Usage = D3D11_USAGE_DEFAULT;
            resolveDesc.BindFlags = 0;
            resolveDesc.CPUAccessFlags = 0;
            resolveDesc.MiscFlags = 0;

            HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
            if (FAILED(result))
            {
                return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
            }

            deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format);
            subresourceAfterResolve = 0;
        }
        else
        {
            srcTex = source;
        }

        D3D11_BOX srcBox;
        srcBox.left = sourceArea.x;
        srcBox.right = sourceArea.x + sourceArea.width;
        srcBox.top = sourceArea.y;
        srcBox.bottom = sourceArea.y + sourceArea.height;
        srcBox.front = 0;
        srcBox.back = 1;

        deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);

        if (textureDesc.SampleDesc.Count > 1)
        {
            SafeRelease(srcTex);
        }
    }
    else
    {
        // This format requires conversion, so we must copy the texture to staging and manually convert via readPixels
        D3D11_MAPPED_SUBRESOURCE mappedImage;
        gl::Error error = map(D3D11_MAP_WRITE, &mappedImage);
        if (error.isError())
        {
            return error;
        }

        // determine the offset coordinate into the destination buffer
        GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
        uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;

        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);

        error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);

        unmap();

        if (error.isError())
        {
            return error;
        }
    }

    mDirty = true;

    return gl::Error(GL_NO_ERROR);
}
EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHeight)
{
    ID3D11Device *device = mRenderer->getDevice();

    ASSERT(device != NULL);

    // D3D11 does not allow zero size textures
    ASSERT(backbufferWidth >= 1);
    ASSERT(backbufferHeight >= 1);

    // Preserve the render target content
    ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
    if (previousOffscreenTexture)
    {
        previousOffscreenTexture->AddRef();
    }
    const int previousWidth = mWidth;
    const int previousHeight = mHeight;

    releaseOffscreenTexture();

    // If the app passed in a share handle, open the resource
    // See EGL_ANGLE_d3d_share_handle_client_buffer
    if (mAppCreatedShareHandle)
    {
        ID3D11Resource *tempResource11;
        HRESULT result = device->OpenSharedResource(mShareHandle, __uuidof(ID3D11Resource), (void**)&tempResource11);

        if (FAILED(result))
        {
            ERR("Failed to open the swap chain pbuffer share handle: %08lX", result);
            release();
            return EGL_BAD_PARAMETER;
        }

        result = tempResource11->QueryInterface(__uuidof(ID3D11Texture2D), (void**)&mOffscreenTexture);
        tempResource11->Release();

        if (FAILED(result))
        {
            ERR("Failed to query texture2d interface in pbuffer share handle: %08lX", result);
            release();
            return EGL_BAD_PARAMETER;
        }

        // Validate offscreen texture parameters
        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
        mOffscreenTexture->GetDesc(&offscreenTextureDesc);

        if (offscreenTextureDesc.Width != (UINT)backbufferWidth
            || offscreenTextureDesc.Height != (UINT)backbufferHeight
            || offscreenTextureDesc.Format != gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat)
            || offscreenTextureDesc.MipLevels != 1
            || offscreenTextureDesc.ArraySize != 1)
        {
            ERR("Invalid texture parameters in the shared offscreen texture pbuffer");
            release();
            return EGL_BAD_PARAMETER;
        }
    }
    else
    {
        const bool useSharedResource = !mWindow && mRenderer->getShareHandleSupport();

        D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
        offscreenTextureDesc.Width = backbufferWidth;
        offscreenTextureDesc.Height = backbufferHeight;
        offscreenTextureDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mBackBufferFormat);
        offscreenTextureDesc.MipLevels = 1;
        offscreenTextureDesc.ArraySize = 1;
        offscreenTextureDesc.SampleDesc.Count = 1;
        offscreenTextureDesc.SampleDesc.Quality = 0;
        offscreenTextureDesc.Usage = D3D11_USAGE_DEFAULT;
        offscreenTextureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
        offscreenTextureDesc.CPUAccessFlags = 0;
        offscreenTextureDesc.MiscFlags = useSharedResource ? D3D11_RESOURCE_MISC_SHARED : 0;

        HRESULT result = device->CreateTexture2D(&offscreenTextureDesc, NULL, &mOffscreenTexture);

        if (FAILED(result))
        {
            ERR("Could not create offscreen texture: %08lX", result);
            release();

            if (d3d11::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }

        d3d11::SetDebugName(mOffscreenTexture, "Offscreen texture");

        // EGL_ANGLE_surface_d3d_texture_2d_share_handle requires that we store a share handle for the client
        if (useSharedResource)
        {
            IDXGIResource *offscreenTextureResource = NULL;
            result = mOffscreenTexture->QueryInterface(__uuidof(IDXGIResource), (void**)&offscreenTextureResource);

            // Fall back to no share handle on failure
            if (FAILED(result))
            {
                ERR("Could not query offscreen texture resource: %08lX", result);
            }
            else
            {
                result = offscreenTextureResource->GetSharedHandle(&mShareHandle);
                offscreenTextureResource->Release();

                if (FAILED(result))
                {
                    mShareHandle = NULL;
                    ERR("Could not get offscreen texture shared handle: %08lX", result);
                }
            }
        }
    }
        
    HRESULT result = device->CreateRenderTargetView(mOffscreenTexture, NULL, &mOffscreenRTView);

    ASSERT(SUCCEEDED(result));
    d3d11::SetDebugName(mOffscreenRTView, "Offscreen render target");

    result = device->CreateShaderResourceView(mOffscreenTexture, NULL, &mOffscreenSRView);
    ASSERT(SUCCEEDED(result));
    d3d11::SetDebugName(mOffscreenSRView, "Offscreen shader resource");

    if (mDepthBufferFormat != GL_NONE)
    {
        D3D11_TEXTURE2D_DESC depthStencilDesc = {0};
        depthStencilDesc.Width = backbufferWidth;
        depthStencilDesc.Height = backbufferHeight;
        depthStencilDesc.Format = gl_d3d11::ConvertRenderbufferFormat(mDepthBufferFormat);
        depthStencilDesc.MipLevels = 1;
        depthStencilDesc.ArraySize = 1;
        depthStencilDesc.SampleDesc.Count = 1;
        depthStencilDesc.SampleDesc.Quality = 0;
        depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
        depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
        depthStencilDesc.CPUAccessFlags = 0;
        depthStencilDesc.MiscFlags = 0;

        result = device->CreateTexture2D(&depthStencilDesc, NULL, &mDepthStencilTexture);
        if (FAILED(result))
        {
            ERR("Could not create depthstencil surface for new swap chain: 0x%08X", result);
            release();

            if (d3d11::isDeviceLostError(result))
            {
                return EGL_CONTEXT_LOST;
            }
            else
            {
                return EGL_BAD_ALLOC;
            }
        }
        d3d11::SetDebugName(mDepthStencilTexture, "Depth stencil texture");

        result = device->CreateDepthStencilView(mDepthStencilTexture, NULL, &mDepthStencilDSView);
        ASSERT(SUCCEEDED(result));
        d3d11::SetDebugName(mDepthStencilDSView, "Depth stencil view");
    }

    mWidth = backbufferWidth;
    mHeight = backbufferHeight;

    if (previousOffscreenTexture != NULL)
    {
        D3D11_BOX sourceBox = {0};
        sourceBox.left = 0;
        sourceBox.right = std::min(previousWidth, mWidth);
        sourceBox.top = std::max(previousHeight - mHeight, 0);
        sourceBox.bottom = previousHeight;
        sourceBox.front = 0;
        sourceBox.back = 1;

        ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
        const int yoffset = std::max(mHeight - previousHeight, 0);
        deviceContext->CopySubresourceRegion(mOffscreenTexture, 0, 0, yoffset, 0, previousOffscreenTexture, 0, &sourceBox);

        previousOffscreenTexture->Release();

        if (mSwapChain)
        {
            swapRect(0, 0, mWidth, mHeight);
        }
    }

    return EGL_SUCCESS;
}