• 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::Error(EGL_BAD_PARAMETER, "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::Error(EGL_BAD_PARAMETER, "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::Error(EGL_BAD_PARAMETER, "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::Error(EGL_BAD_PARAMETER,
86                               "YUV 4:2:0 textures must have even width and height.");
87     }
88     if (planeIndex > 0)
89     {
90         out->width /= 2;
91         out->height /= 2;
92     }
93 
94     out->internalFormat = 0;
95     if (planeIndex < planeFormats.size())
96     {
97         out->internalFormat = planeFormats[planeIndex];
98     }
99     if (!out->internalFormat)
100         return egl::Error(EGL_BAD_PARAMETER, "Plane out of range");
101 
102     return egl::NoError();
103 }
104 
105 }  // namespace
106 
StreamProducerD3DTexture(Renderer11 * renderer)107 StreamProducerD3DTexture::StreamProducerD3DTexture(Renderer11 *renderer)
108     : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mPlaneOffset(0)
109 {}
110 
~StreamProducerD3DTexture()111 StreamProducerD3DTexture::~StreamProducerD3DTexture()
112 {
113     SafeRelease(mTexture);
114 }
115 
validateD3DTexture(const void * pointer,const egl::AttributeMap & attributes) const116 egl::Error StreamProducerD3DTexture::validateD3DTexture(const void *pointer,
117                                                         const egl::AttributeMap &attributes) const
118 {
119     // We must remove the const qualifier because "GetDevice" and "GetDesc" are non-const in D3D11.
120     ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(const_cast<void *>(pointer));
121 
122     // Check that the texture originated from our device
123     angle::ComPtr<ID3D11Device> device;
124     textureD3D->GetDevice(&device);
125     if (device.Get() != mRenderer->getDevice())
126     {
127         return egl::Error(EGL_BAD_PARAMETER, "Texture not created on ANGLE D3D device");
128     }
129 
130     const auto planeId = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0));
131     egl::Stream::GLTextureDescription unused;
132     return GetGLDescFromTex(textureD3D, planeId, &unused);
133 }
134 
postD3DTexture(void * pointer,const egl::AttributeMap & attributes)135 void StreamProducerD3DTexture::postD3DTexture(void *pointer, const egl::AttributeMap &attributes)
136 {
137     ASSERT(pointer != nullptr);
138     ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
139 
140     // Release the previous texture if there is one
141     SafeRelease(mTexture);
142 
143     mTexture = textureD3D;
144     mTexture->AddRef();
145     mPlaneOffset = static_cast<UINT>(attributes.get(EGL_NATIVE_BUFFER_PLANE_OFFSET_IMG, 0));
146     mArraySlice  = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
147 }
148 
getGLFrameDescription(int planeIndex)149 egl::Stream::GLTextureDescription StreamProducerD3DTexture::getGLFrameDescription(int planeIndex)
150 {
151     const auto planeOffsetIndex = static_cast<UINT>(planeIndex + mPlaneOffset);
152     egl::Stream::GLTextureDescription ret;
153     ANGLE_SWALLOW_ERR(GetGLDescFromTex(mTexture, planeOffsetIndex, &ret));
154     return ret;
155 }
156 
getD3DTexture()157 ID3D11Texture2D *StreamProducerD3DTexture::getD3DTexture()
158 {
159     return mTexture;
160 }
161 
getArraySlice()162 UINT StreamProducerD3DTexture::getArraySlice()
163 {
164     return mArraySlice;
165 }
166 
167 }  // namespace rx
168