StreamProducerD3DTexture.cpp (4968B)
1 // 2 // Copyright 2016 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // StreamProducerD3DTexture.cpp: Implements the stream producer for D3D11 textures 8 9 #include "libANGLE/renderer/d3d/d3d11/StreamProducerD3DTexture.h" 10 11 #include "common/utilities.h" 12 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h" 13 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h" 14 15 #include <array> 16 17 namespace rx 18 { 19 20 namespace 21 { 22 23 egl::Error GetGLDescFromTex(ID3D11Texture2D *const tex, 24 const UINT planeIndex, 25 egl::Stream::GLTextureDescription *const out) 26 { 27 if (!tex) 28 return egl::EglBadParameter() << "Texture is null"; 29 30 D3D11_TEXTURE2D_DESC desc; 31 tex->GetDesc(&desc); 32 33 if (desc.Width < 1 || desc.Height < 1) 34 return egl::EglBadParameter() << "Width or height < 1"; 35 36 out->width = desc.Width; 37 out->height = desc.Height; 38 out->mipLevels = 0; 39 40 std::array<uint32_t, 2> planeFormats = {}; 41 switch (desc.Format) 42 { 43 case DXGI_FORMAT_NV12: 44 planeFormats = {GL_R8, GL_RG8}; 45 break; 46 47 case DXGI_FORMAT_P010: 48 case DXGI_FORMAT_P016: 49 planeFormats = {GL_R16_EXT, GL_RG16_EXT}; 50 break; 51 52 case DXGI_FORMAT_R8_UNORM: 53 planeFormats = {GL_R8}; 54 break; 55 case DXGI_FORMAT_R8G8_UNORM: 56 planeFormats[0] = GL_RG8; 57 break; 58 case DXGI_FORMAT_R8G8B8A8_UNORM: 59 planeFormats[0] = GL_RGBA8; 60 break; 61 case DXGI_FORMAT_B8G8R8A8_UNORM: 62 planeFormats[0] = GL_BGRA8_EXT; 63 break; 64 65 case DXGI_FORMAT_R16_UNORM: 66 planeFormats[0] = GL_R16_EXT; 67 break; 68 case DXGI_FORMAT_R16G16_UNORM: 69 planeFormats[0] = GL_RG16_EXT; 70 break; 71 case DXGI_FORMAT_R16G16B16A16_UNORM: 72 planeFormats[0] = GL_RGBA16_EXT; 73 break; 74 case DXGI_FORMAT_R16G16B16A16_FLOAT: 75 planeFormats[0] = GL_RGBA16F; 76 break; 77 78 default: 79 return egl::EglBadParameter() << "Unsupported format"; 80 } 81 82 if (planeFormats[1]) // If we have YUV planes, expect 4:2:0. 83 { 84 if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0) 85 return egl::EglBadParameter() << "YUV 4:2:0 textures must have even width and height."; 86 } 87 if (planeIndex > 0) 88 { 89 out->width /= 2; 90 out->height /= 2; 91 } 92 93 out->internalFormat = 0; 94 if (planeIndex < planeFormats.size()) 95 { 96 out->internalFormat = planeFormats[planeIndex]; 97 } 98 if (!out->internalFormat) 99 return egl::EglBadParameter() << "Plane out of range"; 100 101 return egl::NoError(); 102 } 103 104 } // namespace 105 106 StreamProducerD3DTexture::StreamProducerD3DTexture(Renderer11 *renderer) 107 : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mPlaneOffset(0) 108 {} 109 110 StreamProducerD3DTexture::~StreamProducerD3DTexture() 111 { 112 SafeRelease(mTexture); 113 } 114 115 egl::Error StreamProducerD3DTexture::validateD3DTexture(const void *pointer, 116 const egl::AttributeMap &attributes) const 117 { 118 // We must remove the const qualifier because "GetDevice" and "GetDesc" are non-const in D3D11. 119 ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(const_cast<void *>(pointer)); 120 121 // Check that the texture originated from our device 122 angle::ComPtr<ID3D11Device> device; 123 textureD3D->GetDevice(&device); 124 if (device.Get() != mRenderer->getDevice()) 125 { 126 return egl::EglBadParameter() << "Texture not created on ANGLE D3D device"; 127 } 128 129 const auto planeId = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0)); 130 egl::Stream::GLTextureDescription unused; 131 return GetGLDescFromTex(textureD3D, planeId, &unused); 132 } 133 134 void StreamProducerD3DTexture::postD3DTexture(void *pointer, const egl::AttributeMap &attributes) 135 { 136 ASSERT(pointer != nullptr); 137 ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer); 138 139 // Release the previous texture if there is one 140 SafeRelease(mTexture); 141 142 mTexture = textureD3D; 143 mTexture->AddRef(); 144 mPlaneOffset = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0)); 145 mArraySlice = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0)); 146 } 147 148 egl::Stream::GLTextureDescription StreamProducerD3DTexture::getGLFrameDescription(int planeIndex) 149 { 150 const auto planeOffsetIndex = static_cast<UINT>(planeIndex + mPlaneOffset); 151 egl::Stream::GLTextureDescription ret; 152 ANGLE_SWALLOW_ERR(GetGLDescFromTex(mTexture, planeOffsetIndex, &ret)); 153 return ret; 154 } 155 156 ID3D11Texture2D *StreamProducerD3DTexture::getD3DTexture() 157 { 158 return mTexture; 159 } 160 161 UINT StreamProducerD3DTexture::getArraySlice() 162 { 163 return mArraySlice; 164 } 165 166 } // namespace rx