1 //
2 // Copyright 2019 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 #include "libANGLE/renderer/d3d/d3d11/ExternalImageSiblingImpl11.h"
8
9 #include "libANGLE/Context.h"
10 #include "libANGLE/Error.h"
11 #include "libANGLE/angletypes.h"
12 #include "libANGLE/formatutils.h"
13 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
14 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
15 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
16 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
17 #include "libANGLE/renderer/d3d/d3d11/texture_format_table.h"
18
19 namespace rx
20 {
ExternalImageSiblingImpl11(Renderer11 * renderer,EGLClientBuffer buffer,const egl::AttributeMap & attribs)21 ExternalImageSiblingImpl11::ExternalImageSiblingImpl11(Renderer11 *renderer,
22 EGLClientBuffer buffer,
23 const egl::AttributeMap &attribs)
24 : mRenderer(renderer), mBuffer(buffer), mAttribs(attribs)
25 {}
26
~ExternalImageSiblingImpl11()27 ExternalImageSiblingImpl11::~ExternalImageSiblingImpl11() {}
28
initialize(const egl::Display * display)29 egl::Error ExternalImageSiblingImpl11::initialize(const egl::Display *display)
30 {
31 const angle::Format *angleFormat = nullptr;
32 ANGLE_TRY(mRenderer->getD3DTextureInfo(nullptr, static_cast<IUnknown *>(mBuffer), mAttribs,
33 &mWidth, &mHeight, &mSamples, &mFormat, &angleFormat,
34 &mArraySlice));
35 ID3D11Texture2D *texture =
36 d3d11::DynamicCastComObject<ID3D11Texture2D>(static_cast<IUnknown *>(mBuffer));
37 ASSERT(texture != nullptr);
38
39 D3D11_TEXTURE2D_DESC textureDesc = {};
40 texture->GetDesc(&textureDesc);
41
42 if (d3d11::IsSupportedMultiplanarFormat(textureDesc.Format))
43 {
44 if (!mAttribs.contains(EGL_D3D11_TEXTURE_PLANE_ANGLE))
45 {
46 return egl::EglBadParameter()
47 << "EGL_D3D11_TEXTURE_PLANE_ANGLE must be specified for YUV textures.";
48 }
49
50 EGLint plane = mAttribs.getAsInt(EGL_D3D11_TEXTURE_PLANE_ANGLE);
51 if (plane < 0 || plane > 1)
52 {
53 return egl::EglBadParameter() << "Invalid client buffer texture plane: " << plane;
54 }
55
56 mTexture.set(texture, d3d11::GetYUVPlaneFormat(textureDesc.Format, plane));
57 }
58 else
59 {
60 // TextureHelper11 will release texture on destruction.
61 mTexture.set(texture, d3d11::Format::Get(angleFormat->glInternalFormat,
62 mRenderer->getRenderer11DeviceCaps()));
63 }
64
65 IDXGIResource *resource = d3d11::DynamicCastComObject<IDXGIResource>(mTexture.get());
66 ASSERT(resource != nullptr);
67 DXGI_USAGE resourceUsage = 0;
68 resource->GetUsage(&resourceUsage);
69 SafeRelease(resource);
70
71 mIsRenderable = (textureDesc.BindFlags & D3D11_BIND_RENDER_TARGET) &&
72 (resourceUsage & DXGI_USAGE_RENDER_TARGET_OUTPUT) &&
73 !(resourceUsage & DXGI_USAGE_READ_ONLY);
74
75 mIsTexturable = (textureDesc.BindFlags & D3D11_BIND_SHADER_RESOURCE) &&
76 (resourceUsage & DXGI_USAGE_SHADER_INPUT);
77
78 mIsTextureArray = (textureDesc.ArraySize > 1);
79
80 return egl::NoError();
81 }
82
getFormat() const83 gl::Format ExternalImageSiblingImpl11::getFormat() const
84 {
85 return mFormat;
86 }
87
isRenderable(const gl::Context * context) const88 bool ExternalImageSiblingImpl11::isRenderable(const gl::Context *context) const
89 {
90 return mIsRenderable;
91 }
92
isTexturable(const gl::Context * context) const93 bool ExternalImageSiblingImpl11::isTexturable(const gl::Context *context) const
94 {
95 return mIsTexturable;
96 }
97
isYUV() const98 bool ExternalImageSiblingImpl11::isYUV() const
99 {
100 return false;
101 }
102
hasProtectedContent() const103 bool ExternalImageSiblingImpl11::hasProtectedContent() const
104 {
105 return false;
106 }
107
getSize() const108 gl::Extents ExternalImageSiblingImpl11::getSize() const
109 {
110 return gl::Extents(mWidth, mHeight, 1);
111 }
112
getSamples() const113 size_t ExternalImageSiblingImpl11::getSamples() const
114 {
115 return mSamples;
116 }
117
getAttachmentRenderTarget(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex,GLsizei samples,FramebufferAttachmentRenderTarget ** rtOut)118 angle::Result ExternalImageSiblingImpl11::getAttachmentRenderTarget(
119 const gl::Context *context,
120 GLenum binding,
121 const gl::ImageIndex &imageIndex,
122 GLsizei samples,
123 FramebufferAttachmentRenderTarget **rtOut)
124 {
125 ANGLE_TRY(createRenderTarget(context));
126 *rtOut = mRenderTarget.get();
127 return angle::Result::Continue;
128 }
129
initializeContents(const gl::Context * context,GLenum binding,const gl::ImageIndex & imageIndex)130 angle::Result ExternalImageSiblingImpl11::initializeContents(const gl::Context *context,
131 GLenum binding,
132 const gl::ImageIndex &imageIndex)
133 {
134 UNREACHABLE();
135 return angle::Result::Stop;
136 }
137
createRenderTarget(const gl::Context * context)138 angle::Result ExternalImageSiblingImpl11::createRenderTarget(const gl::Context *context)
139 {
140 if (mRenderTarget)
141 return angle::Result::Continue;
142
143 Context11 *context11 = GetImplAs<Context11>(context);
144 const d3d11::Format &formatInfo = mTexture.getFormatSet();
145
146 d3d11::RenderTargetView rtv;
147 if (mIsRenderable)
148 {
149 D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
150 rtvDesc.Format = formatInfo.rtvFormat;
151 if (mIsTextureArray)
152 {
153 if (mSamples == 0)
154 {
155 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
156 rtvDesc.Texture2DArray.MipSlice = 0;
157 rtvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
158 rtvDesc.Texture2DArray.ArraySize = 1;
159 }
160 else
161 {
162 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMSARRAY;
163 rtvDesc.Texture2DMSArray.FirstArraySlice = mArraySlice;
164 rtvDesc.Texture2DMSArray.ArraySize = 1;
165 }
166 }
167 else
168 {
169 if (mSamples == 0)
170 {
171 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
172 rtvDesc.Texture2D.MipSlice = 0;
173 }
174 else
175 {
176 rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS;
177 }
178 }
179
180 ANGLE_TRY(mRenderer->allocateResource(context11, rtvDesc, mTexture.get(), &rtv));
181 rtv.setInternalName("getAttachmentRenderTarget.RTV");
182 }
183
184 d3d11::SharedSRV srv;
185 if (mIsTexturable)
186 {
187 D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
188 srvDesc.Format = formatInfo.srvFormat;
189 if (mIsTextureArray)
190 {
191 if (mSamples == 0)
192 {
193 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY;
194 srvDesc.Texture2DArray.MostDetailedMip = 0;
195 srvDesc.Texture2DArray.MipLevels = 1;
196 srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
197 srvDesc.Texture2DArray.ArraySize = 1;
198 }
199 else
200 {
201 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY;
202 srvDesc.Texture2DArray.FirstArraySlice = mArraySlice;
203 srvDesc.Texture2DArray.ArraySize = 1;
204 }
205 }
206 else
207 {
208 if (mSamples == 0)
209 {
210 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
211 srvDesc.Texture2D.MostDetailedMip = 0;
212 srvDesc.Texture2D.MipLevels = 1;
213 }
214 else
215 {
216 srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DMS;
217 }
218 }
219
220 ANGLE_TRY(mRenderer->allocateResource(context11, srvDesc, mTexture.get(), &srv));
221 srv.setInternalName("getAttachmentRenderTarget.SRV");
222 }
223 d3d11::SharedSRV blitSrv = srv.makeCopy();
224
225 mRenderTarget = std::make_unique<TextureRenderTarget11>(
226 std::move(rtv), mTexture, std::move(srv), std::move(blitSrv), mFormat.info->internalFormat,
227 formatInfo, mWidth, mHeight, 1, mSamples);
228 return angle::Result::Continue;
229 }
230
231 } // namespace rx
232