1 //
2 // Copyright (c) 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 // StreamProducerNV12.cpp: Implements the stream producer for NV12 textures
8 
9 #include "libANGLE/renderer/d3d/d3d11/StreamProducerNV12.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 namespace rx
16 {
17 
StreamProducerNV12(Renderer11 * renderer)18 StreamProducerNV12::StreamProducerNV12(Renderer11 *renderer)
19     : mRenderer(renderer), mTexture(nullptr), mArraySlice(0), mTextureWidth(0), mTextureHeight(0)
20 {
21 }
22 
~StreamProducerNV12()23 StreamProducerNV12::~StreamProducerNV12()
24 {
25     SafeRelease(mTexture);
26 }
27 
validateD3DNV12Texture(void * pointer) const28 egl::Error StreamProducerNV12::validateD3DNV12Texture(void *pointer) const
29 {
30     ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
31 
32     // Check that the texture originated from our device
33     ID3D11Device *device;
34     textureD3D->GetDevice(&device);
35     if (device != mRenderer->getDevice())
36     {
37         return egl::EglBadParameter() << "Texture not created on ANGLE D3D device";
38     }
39 
40     // Get the description and validate it
41     D3D11_TEXTURE2D_DESC desc;
42     textureD3D->GetDesc(&desc);
43     if (desc.Format != DXGI_FORMAT_NV12)
44     {
45         return egl::EglBadParameter() << "Texture format not DXGI_FORMAT_NV12";
46     }
47     if (desc.Width < 1 || desc.Height < 1)
48     {
49         return egl::EglBadParameter() << "Texture is of size 0";
50     }
51     if ((desc.Width % 2) != 0 || (desc.Height % 2) != 0)
52     {
53         return egl::EglBadParameter() << "Texture dimensions are not even";
54     }
55     return egl::NoError();
56 }
57 
postD3DNV12Texture(void * pointer,const egl::AttributeMap & attributes)58 void StreamProducerNV12::postD3DNV12Texture(void *pointer, const egl::AttributeMap &attributes)
59 {
60     ASSERT(pointer != nullptr);
61     ID3D11Texture2D *textureD3D = static_cast<ID3D11Texture2D *>(pointer);
62 
63     // Check that the texture originated from our device
64     ID3D11Device *device;
65     textureD3D->GetDevice(&device);
66 
67     // Get the description
68     D3D11_TEXTURE2D_DESC desc;
69     textureD3D->GetDesc(&desc);
70 
71     // Release the previous texture if there is one
72     SafeRelease(mTexture);
73 
74     mTexture = textureD3D;
75     mTexture->AddRef();
76     mTextureWidth  = desc.Width;
77     mTextureHeight = desc.Height;
78     mArraySlice    = static_cast<UINT>(attributes.get(EGL_D3D_TEXTURE_SUBRESOURCE_ID_ANGLE, 0));
79 }
80 
getGLFrameDescription(int planeIndex)81 egl::Stream::GLTextureDescription StreamProducerNV12::getGLFrameDescription(int planeIndex)
82 {
83     // The UV plane of NV12 textures has half the width/height of the Y plane
84     egl::Stream::GLTextureDescription desc;
85     desc.width          = (planeIndex == 0) ? mTextureWidth : (mTextureWidth / 2);
86     desc.height         = (planeIndex == 0) ? mTextureHeight : (mTextureHeight / 2);
87     desc.internalFormat = (planeIndex == 0) ? GL_R8 : GL_RG8;
88     desc.mipLevels      = 0;
89     return desc;
90 }
91 
getD3DTexture()92 ID3D11Texture2D *StreamProducerNV12::getD3DTexture()
93 {
94     return mTexture;
95 }
96 
getArraySlice()97 UINT StreamProducerNV12::getArraySlice()
98 {
99     return mArraySlice;
100 }
101 
102 }  // namespace rx
103