| // |
| // Copyright 2016 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| |
| // StreamProducerD3DTexture.cpp: Implements the stream producer for D3D11 textures |
| |
| #include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h" |
| |
| #include "common/utilities.h" |
| #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" |
| #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" |
| |
| #include <array> |
| |
| namespace rx |
| { |
| |
| namespace |
| { |
| |
| egl::Error GetGLDescFromTex(ID3D11Texture2D *const tex, |
| const UINT planeIndex, |
| egl::Stream::GLTextureDescription *const out) |
| { |
| if (!tex) |
| return egl::EglBadParameter() << "Texture is null"; |
| |
| D3D11_TEXTURE2D_DESC desc; |
| tex->GetDesc(&desc); |
| |
| if (desc.Width < 1 || desc.Height < 1) |
| return egl::EglBadParameter() << "Width or height < 1"; |
| |
| out->width = desc.Width; |
| out->height = desc.Height; |
| out->mipLevels = 0; |
| |
| std::array<uint32_t, 2> planeFormats = {}; |
| switch (desc.Format) |
| { |
| case DXGI_FORMAT_NV12: |
| planeFormats = {GL_R8, GL_RG8}; |
| break; |
| |
| case DXGI_FORMAT_P010: |
| case DXGI_FORMAT_P016: |
| planeFormats = {GL_R16_EXT, GL_RG16_EXT}; |
| break; |
| |
| case DXGI_FORMAT_R8_UNORM: |
| planeFormats = {GL_R8}; |
| break; |
| case DXGI_FORMAT_R8G8_UNORM: |
| planeFormats[0] = GL_RG8; |
| break; |
| case DXGI_FORMAT_R8G8B8A8_UNORM: |
| planeFormats[0] = GL_RGBA8; |
| break; |
| case DXGI_FORMAT_B8G8R8A8_UNORM: |
| planeFormats[0] = GL_BGRA8_EXT; |
| break; |
| |
| case DXGI_FORMAT_R16_UNORM: |
| planeFormats[0] = GL_R16_EXT; |
| break; |
| case DXGI_FORMAT_R16G16_UNORM: |
| planeFormats[0] = GL_RG16_EXT; |
| break; |
| case DXGI_FORMAT_R16G16B16A16_UNORM: |
| planeFormats[0] = GL_RGBA16_EXT; |
| break; |
| |
| default: |
| return egl::EglBadParameter() << "Unsupported format"; |
| } |
| |
| if (planeFormats[1]) // If we have YUV planes, expect 4:2:0. |
| { |
| if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0) |
| return egl::EglBadParameter() << "YUV 4:2:0 textures must have even width and height."; |
| } |
| if (planeIndex > 0) |
| { |
| out->width /= 2; |
| out->height /= 2; |
| } |
| |
| out->internalFormat = 0; |
| if (planeIndex < planeFormats.size()) |
| { |
| out->internalFormat = planeFormats[planeIndex]; |
| } |
| if (!out->internalFormat) |
| return egl::EglBadParameter() << "Plane out of range"; |
| |
| return egl::NoError(); |
| } |
| |
| } // namespace |
| |
| StreamProducerD3DTexture::StreamProducerD3DTexture(Renderer11 *renderer) |
| : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mPlaneOffset(0) |
| {} |
| |
| StreamProducerD3DTexture::~StreamProducerD3DTexture() |
| { |
| SafeRelease(mTexture); |
| } |
| |
| egl::Error StreamProducerD3DTexture::validateD3DTexture(void *pointer, |
| const egl::AttributeMap &attributes) const |
| { |
| ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer); |
| |
| // Check that the texture originated from our device |
| ID3D11Device *device; |
| textureD3D->GetDevice(&device); |
| if (device != mRenderer->getDevice()) |
| { |
| return egl::EglBadParameter() << "Texture not created on ANGLE D3D device"; |
| } |
| |
| const auto planeId = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0)); |
| egl::Stream::GLTextureDescription unused; |
| return GetGLDescFromTex(textureD3D, planeId, &unused); |
| } |
| |
| void StreamProducerD3DTexture::postD3DTexture(void *pointer, const egl::AttributeMap &attributes) |
| { |
| ASSERT(pointer != nullptr); |
| ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer); |
| |
| // Release the previous texture if there is one |
| SafeRelease(mTexture); |
| |
| mTexture = textureD3D; |
| mTexture->AddRef(); |
| mPlaneOffset = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0)); |
| mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0)); |
| } |
| |
| egl::Stream::GLTextureDescription StreamProducerD3DTexture::getGLFrameDescription(int planeIndex) |
| { |
| const auto planeOffsetIndex = static_cast<UINT>(planeIndex + mPlaneOffset); |
| egl::Stream::GLTextureDescription ret; |
| ANGLE_SWALLOW_ERR(GetGLDescFromTex(mTexture, planeOffsetIndex, &ret)); |
| return ret; |
| } |
| |
| ID3D11Texture2D *StreamProducerD3DTexture::getD3DTexture() |
| { |
| return mTexture; |
| } |
| |
| UINT StreamProducerD3DTexture::getArraySlice() |
| { |
| return mArraySlice; |
| } |
| |
| } // namespace rx |