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; }
// 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; }
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); }
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; }
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; }
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(); } }
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); }
gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms) { 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); }
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; }
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 ¶ms) { 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); }
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; }