• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetGLDescFromTex(ID3D11Texture2D * const tex,const UINT planeIndex,egl::Stream::GLTextureDescription * const out)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 
StreamProducerD3DTexture(Renderer11 * renderer)106 StreamProducerD3DTexture::StreamProducerD3DTexture(Renderer11 *renderer)
107     : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mPlaneOffset(0)
108 {}
109 
~StreamProducerD3DTexture()110 StreamProducerD3DTexture::~StreamProducerD3DTexture()
111 {
112     SafeRelease(mTexture);
113 }
114 
validateD3DTexture(const void * pointer,const egl::AttributeMap & attributes) const115 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     ID3D11Device *device;
123     textureD3D->GetDevice(&device);
124     if (device != 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 
postD3DTexture(void * pointer,const egl::AttributeMap & attributes)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 
getGLFrameDescription(int planeIndex)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 
getD3DTexture()156 ID3D11Texture2D *StreamProducerD3DTexture::getD3DTexture()
157 {
158     return mTexture;
159 }
160 
getArraySlice()161 UINT StreamProducerD3DTexture::getArraySlice()
162 {
163     return mArraySlice;
164 }
165 
166 }  // namespace rx
167