xref: /aosp_15_r20/external/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2014 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker // FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/FramebufferD3D.h"
10*8975f5c5SAndroid Build Coastguard Worker 
11*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
12*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ErrorStrings.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Framebuffer.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/FramebufferAttachment.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/ContextD3D.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/RenderTargetD3D.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/RenderbufferD3D.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/RendererD3D.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/SurfaceD3D.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/SwapChainD3D.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/d3d/TextureD3D.h"
26*8975f5c5SAndroid Build Coastguard Worker 
27*8975f5c5SAndroid Build Coastguard Worker namespace rx
28*8975f5c5SAndroid Build Coastguard Worker {
29*8975f5c5SAndroid Build Coastguard Worker 
30*8975f5c5SAndroid Build Coastguard Worker namespace
31*8975f5c5SAndroid Build Coastguard Worker {
32*8975f5c5SAndroid Build Coastguard Worker 
GetClearParameters(const gl::State & state,GLbitfield mask)33*8975f5c5SAndroid Build Coastguard Worker ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
34*8975f5c5SAndroid Build Coastguard Worker {
35*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams;
36*8975f5c5SAndroid Build Coastguard Worker     memset(&clearParams, 0, sizeof(ClearParameters));
37*8975f5c5SAndroid Build Coastguard Worker 
38*8975f5c5SAndroid Build Coastguard Worker     clearParams.colorF           = state.getColorClearValue();
39*8975f5c5SAndroid Build Coastguard Worker     clearParams.colorType        = GL_FLOAT;
40*8975f5c5SAndroid Build Coastguard Worker     clearParams.clearDepth       = false;
41*8975f5c5SAndroid Build Coastguard Worker     clearParams.depthValue       = state.getDepthClearValue();
42*8975f5c5SAndroid Build Coastguard Worker     clearParams.clearStencil     = false;
43*8975f5c5SAndroid Build Coastguard Worker     clearParams.stencilValue     = state.getStencilClearValue();
44*8975f5c5SAndroid Build Coastguard Worker     clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker     const auto *framebufferObject      = state.getDrawFramebuffer();
47*8975f5c5SAndroid Build Coastguard Worker     const gl::Extents &framebufferSize = framebufferObject->getFirstNonNullAttachment()->getSize();
48*8975f5c5SAndroid Build Coastguard Worker     const gl::Offset &surfaceTextureOffset = framebufferObject->getSurfaceTextureOffset();
49*8975f5c5SAndroid Build Coastguard Worker     if (state.isScissorTestEnabled())
50*8975f5c5SAndroid Build Coastguard Worker     {
51*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissorEnabled = true;
52*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissor        = state.getScissor();
53*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissor.x      = clearParams.scissor.x + surfaceTextureOffset.x;
54*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissor.y      = clearParams.scissor.y + surfaceTextureOffset.y;
55*8975f5c5SAndroid Build Coastguard Worker     }
56*8975f5c5SAndroid Build Coastguard Worker     else if (surfaceTextureOffset != gl::kOffsetZero)
57*8975f5c5SAndroid Build Coastguard Worker     {
58*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissorEnabled = true;
59*8975f5c5SAndroid Build Coastguard Worker         clearParams.scissor        = gl::Rectangle(surfaceTextureOffset.x, surfaceTextureOffset.y,
60*8975f5c5SAndroid Build Coastguard Worker                                                    framebufferSize.width, framebufferSize.height);
61*8975f5c5SAndroid Build Coastguard Worker     }
62*8975f5c5SAndroid Build Coastguard Worker 
63*8975f5c5SAndroid Build Coastguard Worker     const bool clearColor =
64*8975f5c5SAndroid Build Coastguard Worker         (mask & GL_COLOR_BUFFER_BIT) && framebufferObject->hasEnabledDrawBuffer();
65*8975f5c5SAndroid Build Coastguard Worker     if (clearColor)
66*8975f5c5SAndroid Build Coastguard Worker     {
67*8975f5c5SAndroid Build Coastguard Worker         clearParams.clearColor.set();
68*8975f5c5SAndroid Build Coastguard Worker     }
69*8975f5c5SAndroid Build Coastguard Worker     else
70*8975f5c5SAndroid Build Coastguard Worker     {
71*8975f5c5SAndroid Build Coastguard Worker         clearParams.clearColor.reset();
72*8975f5c5SAndroid Build Coastguard Worker     }
73*8975f5c5SAndroid Build Coastguard Worker     clearParams.colorMask = state.getBlendStateExt().getColorMaskBits();
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker     if (mask & GL_DEPTH_BUFFER_BIT)
76*8975f5c5SAndroid Build Coastguard Worker     {
77*8975f5c5SAndroid Build Coastguard Worker         if (state.getDepthStencilState().depthMask &&
78*8975f5c5SAndroid Build Coastguard Worker             framebufferObject->getDepthAttachment() != nullptr)
79*8975f5c5SAndroid Build Coastguard Worker         {
80*8975f5c5SAndroid Build Coastguard Worker             clearParams.clearDepth = true;
81*8975f5c5SAndroid Build Coastguard Worker         }
82*8975f5c5SAndroid Build Coastguard Worker     }
83*8975f5c5SAndroid Build Coastguard Worker 
84*8975f5c5SAndroid Build Coastguard Worker     if (mask & GL_STENCIL_BUFFER_BIT)
85*8975f5c5SAndroid Build Coastguard Worker     {
86*8975f5c5SAndroid Build Coastguard Worker         if (framebufferObject->getStencilAttachment() != nullptr &&
87*8975f5c5SAndroid Build Coastguard Worker             framebufferObject->getStencilAttachment()->getStencilSize() > 0)
88*8975f5c5SAndroid Build Coastguard Worker         {
89*8975f5c5SAndroid Build Coastguard Worker             clearParams.clearStencil = true;
90*8975f5c5SAndroid Build Coastguard Worker         }
91*8975f5c5SAndroid Build Coastguard Worker     }
92*8975f5c5SAndroid Build Coastguard Worker 
93*8975f5c5SAndroid Build Coastguard Worker     return clearParams;
94*8975f5c5SAndroid Build Coastguard Worker }
95*8975f5c5SAndroid Build Coastguard Worker }  // namespace
96*8975f5c5SAndroid Build Coastguard Worker 
97*8975f5c5SAndroid Build Coastguard Worker ClearParameters::ClearParameters() = default;
98*8975f5c5SAndroid Build Coastguard Worker 
99*8975f5c5SAndroid Build Coastguard Worker ClearParameters::ClearParameters(const ClearParameters &other) = default;
100*8975f5c5SAndroid Build Coastguard Worker 
FramebufferD3D(const gl::FramebufferState & data,RendererD3D * renderer)101*8975f5c5SAndroid Build Coastguard Worker FramebufferD3D::FramebufferD3D(const gl::FramebufferState &data, RendererD3D *renderer)
102*8975f5c5SAndroid Build Coastguard Worker     : FramebufferImpl(data), mRenderer(renderer), mMockAttachment()
103*8975f5c5SAndroid Build Coastguard Worker {}
104*8975f5c5SAndroid Build Coastguard Worker 
~FramebufferD3D()105*8975f5c5SAndroid Build Coastguard Worker FramebufferD3D::~FramebufferD3D() {}
106*8975f5c5SAndroid Build Coastguard Worker 
clear(const gl::Context * context,GLbitfield mask)107*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::clear(const gl::Context *context, GLbitfield mask)
108*8975f5c5SAndroid Build Coastguard Worker {
109*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams = GetClearParameters(context->getState(), mask);
110*8975f5c5SAndroid Build Coastguard Worker     return clearImpl(context, clearParams);
111*8975f5c5SAndroid Build Coastguard Worker }
112*8975f5c5SAndroid Build Coastguard Worker 
clearBufferfv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)113*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::clearBufferfv(const gl::Context *context,
114*8975f5c5SAndroid Build Coastguard Worker                                             GLenum buffer,
115*8975f5c5SAndroid Build Coastguard Worker                                             GLint drawbuffer,
116*8975f5c5SAndroid Build Coastguard Worker                                             const GLfloat *values)
117*8975f5c5SAndroid Build Coastguard Worker {
118*8975f5c5SAndroid Build Coastguard Worker     // glClearBufferfv can be called to clear the color buffer or depth buffer
119*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams = GetClearParameters(context->getState(), 0);
120*8975f5c5SAndroid Build Coastguard Worker 
121*8975f5c5SAndroid Build Coastguard Worker     if (buffer == GL_COLOR)
122*8975f5c5SAndroid Build Coastguard Worker     {
123*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
124*8975f5c5SAndroid Build Coastguard Worker         {
125*8975f5c5SAndroid Build Coastguard Worker             clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
126*8975f5c5SAndroid Build Coastguard Worker         }
127*8975f5c5SAndroid Build Coastguard Worker         clearParams.colorF    = gl::ColorF(values[0], values[1], values[2], values[3]);
128*8975f5c5SAndroid Build Coastguard Worker         clearParams.colorType = GL_FLOAT;
129*8975f5c5SAndroid Build Coastguard Worker     }
130*8975f5c5SAndroid Build Coastguard Worker 
131*8975f5c5SAndroid Build Coastguard Worker     if (buffer == GL_DEPTH)
132*8975f5c5SAndroid Build Coastguard Worker     {
133*8975f5c5SAndroid Build Coastguard Worker         clearParams.clearDepth = true;
134*8975f5c5SAndroid Build Coastguard Worker         clearParams.depthValue = values[0];
135*8975f5c5SAndroid Build Coastguard Worker     }
136*8975f5c5SAndroid Build Coastguard Worker 
137*8975f5c5SAndroid Build Coastguard Worker     return clearImpl(context, clearParams);
138*8975f5c5SAndroid Build Coastguard Worker }
139*8975f5c5SAndroid Build Coastguard Worker 
clearBufferuiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)140*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::clearBufferuiv(const gl::Context *context,
141*8975f5c5SAndroid Build Coastguard Worker                                              GLenum buffer,
142*8975f5c5SAndroid Build Coastguard Worker                                              GLint drawbuffer,
143*8975f5c5SAndroid Build Coastguard Worker                                              const GLuint *values)
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker     // glClearBufferuiv can only be called to clear a color buffer
146*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams = GetClearParameters(context->getState(), 0);
147*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
148*8975f5c5SAndroid Build Coastguard Worker     {
149*8975f5c5SAndroid Build Coastguard Worker         clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
150*8975f5c5SAndroid Build Coastguard Worker     }
151*8975f5c5SAndroid Build Coastguard Worker     clearParams.colorUI   = gl::ColorUI(values[0], values[1], values[2], values[3]);
152*8975f5c5SAndroid Build Coastguard Worker     clearParams.colorType = GL_UNSIGNED_INT;
153*8975f5c5SAndroid Build Coastguard Worker 
154*8975f5c5SAndroid Build Coastguard Worker     return clearImpl(context, clearParams);
155*8975f5c5SAndroid Build Coastguard Worker }
156*8975f5c5SAndroid Build Coastguard Worker 
clearBufferiv(const gl::Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)157*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::clearBufferiv(const gl::Context *context,
158*8975f5c5SAndroid Build Coastguard Worker                                             GLenum buffer,
159*8975f5c5SAndroid Build Coastguard Worker                                             GLint drawbuffer,
160*8975f5c5SAndroid Build Coastguard Worker                                             const GLint *values)
161*8975f5c5SAndroid Build Coastguard Worker {
162*8975f5c5SAndroid Build Coastguard Worker     // glClearBufferiv can be called to clear the color buffer or stencil buffer
163*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams = GetClearParameters(context->getState(), 0);
164*8975f5c5SAndroid Build Coastguard Worker 
165*8975f5c5SAndroid Build Coastguard Worker     if (buffer == GL_COLOR)
166*8975f5c5SAndroid Build Coastguard Worker     {
167*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int i = 0; i < clearParams.clearColor.size(); i++)
168*8975f5c5SAndroid Build Coastguard Worker         {
169*8975f5c5SAndroid Build Coastguard Worker             clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
170*8975f5c5SAndroid Build Coastguard Worker         }
171*8975f5c5SAndroid Build Coastguard Worker         clearParams.colorI    = gl::ColorI(values[0], values[1], values[2], values[3]);
172*8975f5c5SAndroid Build Coastguard Worker         clearParams.colorType = GL_INT;
173*8975f5c5SAndroid Build Coastguard Worker     }
174*8975f5c5SAndroid Build Coastguard Worker 
175*8975f5c5SAndroid Build Coastguard Worker     if (buffer == GL_STENCIL)
176*8975f5c5SAndroid Build Coastguard Worker     {
177*8975f5c5SAndroid Build Coastguard Worker         clearParams.clearStencil = true;
178*8975f5c5SAndroid Build Coastguard Worker         clearParams.stencilValue = values[0];
179*8975f5c5SAndroid Build Coastguard Worker     }
180*8975f5c5SAndroid Build Coastguard Worker 
181*8975f5c5SAndroid Build Coastguard Worker     return clearImpl(context, clearParams);
182*8975f5c5SAndroid Build Coastguard Worker }
183*8975f5c5SAndroid Build Coastguard Worker 
clearBufferfi(const gl::Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)184*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::clearBufferfi(const gl::Context *context,
185*8975f5c5SAndroid Build Coastguard Worker                                             GLenum buffer,
186*8975f5c5SAndroid Build Coastguard Worker                                             GLint drawbuffer,
187*8975f5c5SAndroid Build Coastguard Worker                                             GLfloat depth,
188*8975f5c5SAndroid Build Coastguard Worker                                             GLint stencil)
189*8975f5c5SAndroid Build Coastguard Worker {
190*8975f5c5SAndroid Build Coastguard Worker     // glClearBufferfi can only be called to clear a depth stencil buffer
191*8975f5c5SAndroid Build Coastguard Worker     ClearParameters clearParams = GetClearParameters(context->getState(), 0);
192*8975f5c5SAndroid Build Coastguard Worker     clearParams.clearDepth      = true;
193*8975f5c5SAndroid Build Coastguard Worker     clearParams.depthValue      = depth;
194*8975f5c5SAndroid Build Coastguard Worker     clearParams.clearStencil    = true;
195*8975f5c5SAndroid Build Coastguard Worker     clearParams.stencilValue    = stencil;
196*8975f5c5SAndroid Build Coastguard Worker 
197*8975f5c5SAndroid Build Coastguard Worker     return clearImpl(context, clearParams);
198*8975f5c5SAndroid Build Coastguard Worker }
199*8975f5c5SAndroid Build Coastguard Worker 
readPixels(const gl::Context * context,const gl::Rectangle & area,GLenum format,GLenum type,const gl::PixelPackState & pack,gl::Buffer * packBuffer,void * pixels)200*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::readPixels(const gl::Context *context,
201*8975f5c5SAndroid Build Coastguard Worker                                          const gl::Rectangle &area,
202*8975f5c5SAndroid Build Coastguard Worker                                          GLenum format,
203*8975f5c5SAndroid Build Coastguard Worker                                          GLenum type,
204*8975f5c5SAndroid Build Coastguard Worker                                          const gl::PixelPackState &pack,
205*8975f5c5SAndroid Build Coastguard Worker                                          gl::Buffer *packBuffer,
206*8975f5c5SAndroid Build Coastguard Worker                                          void *pixels)
207*8975f5c5SAndroid Build Coastguard Worker {
208*8975f5c5SAndroid Build Coastguard Worker     // Clip read area to framebuffer.
209*8975f5c5SAndroid Build Coastguard Worker     const gl::Extents fbSize = getState().getReadPixelsAttachment(format)->getSize();
210*8975f5c5SAndroid Build Coastguard Worker     const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
211*8975f5c5SAndroid Build Coastguard Worker     gl::Rectangle clippedArea;
212*8975f5c5SAndroid Build Coastguard Worker     if (!ClipRectangle(area, fbRect, &clippedArea))
213*8975f5c5SAndroid Build Coastguard Worker     {
214*8975f5c5SAndroid Build Coastguard Worker         // nothing to read
215*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
216*8975f5c5SAndroid Build Coastguard Worker     }
217*8975f5c5SAndroid Build Coastguard Worker 
218*8975f5c5SAndroid Build Coastguard Worker     const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(format, type);
219*8975f5c5SAndroid Build Coastguard Worker 
220*8975f5c5SAndroid Build Coastguard Worker     ContextD3D *contextD3D = GetImplAs<ContextD3D>(context);
221*8975f5c5SAndroid Build Coastguard Worker 
222*8975f5c5SAndroid Build Coastguard Worker     GLuint outputPitch = 0;
223*8975f5c5SAndroid Build Coastguard Worker     ANGLE_CHECK_GL_MATH(contextD3D,
224*8975f5c5SAndroid Build Coastguard Worker                         sizedFormatInfo.computeRowPitch(type, area.width, pack.alignment,
225*8975f5c5SAndroid Build Coastguard Worker                                                         pack.rowLength, &outputPitch));
226*8975f5c5SAndroid Build Coastguard Worker 
227*8975f5c5SAndroid Build Coastguard Worker     GLuint outputSkipBytes = 0;
228*8975f5c5SAndroid Build Coastguard Worker     ANGLE_CHECK_GL_MATH(contextD3D, sizedFormatInfo.computeSkipBytes(type, outputPitch, 0, pack,
229*8975f5c5SAndroid Build Coastguard Worker                                                                      false, &outputSkipBytes));
230*8975f5c5SAndroid Build Coastguard Worker     outputSkipBytes += (clippedArea.x - area.x) * sizedFormatInfo.pixelBytes +
231*8975f5c5SAndroid Build Coastguard Worker                        (clippedArea.y - area.y) * outputPitch;
232*8975f5c5SAndroid Build Coastguard Worker 
233*8975f5c5SAndroid Build Coastguard Worker     return readPixelsImpl(context, clippedArea, format, type, outputPitch, pack, packBuffer,
234*8975f5c5SAndroid Build Coastguard Worker                           static_cast<uint8_t *>(pixels) + outputSkipBytes);
235*8975f5c5SAndroid Build Coastguard Worker }
236*8975f5c5SAndroid Build Coastguard Worker 
blit(const gl::Context * context,const gl::Rectangle & sourceArea,const gl::Rectangle & destArea,GLbitfield mask,GLenum filter)237*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::blit(const gl::Context *context,
238*8975f5c5SAndroid Build Coastguard Worker                                    const gl::Rectangle &sourceArea,
239*8975f5c5SAndroid Build Coastguard Worker                                    const gl::Rectangle &destArea,
240*8975f5c5SAndroid Build Coastguard Worker                                    GLbitfield mask,
241*8975f5c5SAndroid Build Coastguard Worker                                    GLenum filter)
242*8975f5c5SAndroid Build Coastguard Worker {
243*8975f5c5SAndroid Build Coastguard Worker     const auto &glState                      = context->getState();
244*8975f5c5SAndroid Build Coastguard Worker     const gl::Framebuffer *sourceFramebuffer = glState.getReadFramebuffer();
245*8975f5c5SAndroid Build Coastguard Worker     const gl::Rectangle *scissor = glState.isScissorTestEnabled() ? &glState.getScissor() : nullptr;
246*8975f5c5SAndroid Build Coastguard Worker     ANGLE_TRY(blitImpl(context, sourceArea, destArea, scissor, (mask & GL_COLOR_BUFFER_BIT) != 0,
247*8975f5c5SAndroid Build Coastguard Worker                        (mask & GL_DEPTH_BUFFER_BIT) != 0, (mask & GL_STENCIL_BUFFER_BIT) != 0,
248*8975f5c5SAndroid Build Coastguard Worker                        filter, sourceFramebuffer));
249*8975f5c5SAndroid Build Coastguard Worker 
250*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
251*8975f5c5SAndroid Build Coastguard Worker }
252*8975f5c5SAndroid Build Coastguard Worker 
checkStatus(const gl::Context * context) const253*8975f5c5SAndroid Build Coastguard Worker gl::FramebufferStatus FramebufferD3D::checkStatus(const gl::Context *context) const
254*8975f5c5SAndroid Build Coastguard Worker {
255*8975f5c5SAndroid Build Coastguard Worker     // if we have both a depth and stencil buffer, they must refer to the same object
256*8975f5c5SAndroid Build Coastguard Worker     // since we only support packed_depth_stencil and not separate depth and stencil
257*8975f5c5SAndroid Build Coastguard Worker     if (mState.hasSeparateDepthAndStencilAttachments())
258*8975f5c5SAndroid Build Coastguard Worker     {
259*8975f5c5SAndroid Build Coastguard Worker         return gl::FramebufferStatus::Incomplete(
260*8975f5c5SAndroid Build Coastguard Worker             GL_FRAMEBUFFER_UNSUPPORTED,
261*8975f5c5SAndroid Build Coastguard Worker             gl::err::kFramebufferIncompleteUnsupportedSeparateDepthStencilBuffers);
262*8975f5c5SAndroid Build Coastguard Worker     }
263*8975f5c5SAndroid Build Coastguard Worker 
264*8975f5c5SAndroid Build Coastguard Worker     // D3D11 does not allow for overlapping RenderTargetViews.
265*8975f5c5SAndroid Build Coastguard Worker     // If WebGL compatibility is enabled, this has already been checked at a higher level.
266*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!context->isWebGL() || mState.colorAttachmentsAreUniqueImages());
267*8975f5c5SAndroid Build Coastguard Worker     if (!context->isWebGL())
268*8975f5c5SAndroid Build Coastguard Worker     {
269*8975f5c5SAndroid Build Coastguard Worker         if (!mState.colorAttachmentsAreUniqueImages())
270*8975f5c5SAndroid Build Coastguard Worker         {
271*8975f5c5SAndroid Build Coastguard Worker             return gl::FramebufferStatus::Incomplete(
272*8975f5c5SAndroid Build Coastguard Worker                 GL_FRAMEBUFFER_UNSUPPORTED,
273*8975f5c5SAndroid Build Coastguard Worker                 gl::err::kFramebufferIncompleteUnsupportedNonUniqueAttachments);
274*8975f5c5SAndroid Build Coastguard Worker         }
275*8975f5c5SAndroid Build Coastguard Worker     }
276*8975f5c5SAndroid Build Coastguard Worker 
277*8975f5c5SAndroid Build Coastguard Worker     // D3D requires all render targets to have the same dimensions.
278*8975f5c5SAndroid Build Coastguard Worker     if (!mState.attachmentsHaveSameDimensions())
279*8975f5c5SAndroid Build Coastguard Worker     {
280*8975f5c5SAndroid Build Coastguard Worker         return gl::FramebufferStatus::Incomplete(
281*8975f5c5SAndroid Build Coastguard Worker             GL_FRAMEBUFFER_UNSUPPORTED,
282*8975f5c5SAndroid Build Coastguard Worker             gl::err::kFramebufferIncompleteUnsupportedMissmatchedDimensions);
283*8975f5c5SAndroid Build Coastguard Worker     }
284*8975f5c5SAndroid Build Coastguard Worker 
285*8975f5c5SAndroid Build Coastguard Worker     return gl::FramebufferStatus::Complete();
286*8975f5c5SAndroid Build Coastguard Worker }
287*8975f5c5SAndroid Build Coastguard Worker 
syncState(const gl::Context * context,GLenum binding,const gl::Framebuffer::DirtyBits & dirtyBits,gl::Command command)288*8975f5c5SAndroid Build Coastguard Worker angle::Result FramebufferD3D::syncState(const gl::Context *context,
289*8975f5c5SAndroid Build Coastguard Worker                                         GLenum binding,
290*8975f5c5SAndroid Build Coastguard Worker                                         const gl::Framebuffer::DirtyBits &dirtyBits,
291*8975f5c5SAndroid Build Coastguard Worker                                         gl::Command command)
292*8975f5c5SAndroid Build Coastguard Worker {
293*8975f5c5SAndroid Build Coastguard Worker     if (!mColorAttachmentsForRender.valid())
294*8975f5c5SAndroid Build Coastguard Worker     {
295*8975f5c5SAndroid Build Coastguard Worker         return angle::Result::Continue;
296*8975f5c5SAndroid Build Coastguard Worker     }
297*8975f5c5SAndroid Build Coastguard Worker 
298*8975f5c5SAndroid Build Coastguard Worker     for (auto dirtyBit : dirtyBits)
299*8975f5c5SAndroid Build Coastguard Worker     {
300*8975f5c5SAndroid Build Coastguard Worker         if ((dirtyBit >= gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 &&
301*8975f5c5SAndroid Build Coastguard Worker              dirtyBit < gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX) ||
302*8975f5c5SAndroid Build Coastguard Worker             dirtyBit == gl::Framebuffer::DIRTY_BIT_DRAW_BUFFERS)
303*8975f5c5SAndroid Build Coastguard Worker         {
304*8975f5c5SAndroid Build Coastguard Worker             mColorAttachmentsForRender.reset();
305*8975f5c5SAndroid Build Coastguard Worker         }
306*8975f5c5SAndroid Build Coastguard Worker     }
307*8975f5c5SAndroid Build Coastguard Worker 
308*8975f5c5SAndroid Build Coastguard Worker     return angle::Result::Continue;
309*8975f5c5SAndroid Build Coastguard Worker }
310*8975f5c5SAndroid Build Coastguard Worker 
getColorAttachmentsForRender(const gl::Context * context)311*8975f5c5SAndroid Build Coastguard Worker const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const gl::Context *context)
312*8975f5c5SAndroid Build Coastguard Worker {
313*8975f5c5SAndroid Build Coastguard Worker     gl::DrawBufferMask activeProgramOutputs =
314*8975f5c5SAndroid Build Coastguard Worker         context->getState().getProgramExecutable()->getActiveOutputVariablesMask();
315*8975f5c5SAndroid Build Coastguard Worker 
316*8975f5c5SAndroid Build Coastguard Worker     if (mColorAttachmentsForRender.valid() && mCurrentActiveProgramOutputs == activeProgramOutputs)
317*8975f5c5SAndroid Build Coastguard Worker     {
318*8975f5c5SAndroid Build Coastguard Worker         return mColorAttachmentsForRender.value();
319*8975f5c5SAndroid Build Coastguard Worker     }
320*8975f5c5SAndroid Build Coastguard Worker 
321*8975f5c5SAndroid Build Coastguard Worker     // Does not actually free memory
322*8975f5c5SAndroid Build Coastguard Worker     gl::AttachmentList colorAttachmentsForRender;
323*8975f5c5SAndroid Build Coastguard Worker     mColorAttachmentsForRenderMask.reset();
324*8975f5c5SAndroid Build Coastguard Worker 
325*8975f5c5SAndroid Build Coastguard Worker     const auto &colorAttachments = mState.getColorAttachments();
326*8975f5c5SAndroid Build Coastguard Worker     const auto &drawBufferStates = mState.getDrawBufferStates();
327*8975f5c5SAndroid Build Coastguard Worker     const auto &features         = mRenderer->getFeatures();
328*8975f5c5SAndroid Build Coastguard Worker 
329*8975f5c5SAndroid Build Coastguard Worker     for (size_t attachmentIndex = 0; attachmentIndex < colorAttachments.size(); ++attachmentIndex)
330*8975f5c5SAndroid Build Coastguard Worker     {
331*8975f5c5SAndroid Build Coastguard Worker         GLenum drawBufferState                           = drawBufferStates[attachmentIndex];
332*8975f5c5SAndroid Build Coastguard Worker         const gl::FramebufferAttachment &colorAttachment = colorAttachments[attachmentIndex];
333*8975f5c5SAndroid Build Coastguard Worker 
334*8975f5c5SAndroid Build Coastguard Worker         if (colorAttachment.isAttached() && drawBufferState != GL_NONE &&
335*8975f5c5SAndroid Build Coastguard Worker             activeProgramOutputs[attachmentIndex])
336*8975f5c5SAndroid Build Coastguard Worker         {
337*8975f5c5SAndroid Build Coastguard Worker             ASSERT(drawBufferState == GL_BACK ||
338*8975f5c5SAndroid Build Coastguard Worker                    drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
339*8975f5c5SAndroid Build Coastguard Worker             colorAttachmentsForRender.push_back(&colorAttachment);
340*8975f5c5SAndroid Build Coastguard Worker             mColorAttachmentsForRenderMask.set(attachmentIndex);
341*8975f5c5SAndroid Build Coastguard Worker         }
342*8975f5c5SAndroid Build Coastguard Worker         else if (!features.mrtPerfWorkaround.enabled)
343*8975f5c5SAndroid Build Coastguard Worker         {
344*8975f5c5SAndroid Build Coastguard Worker             colorAttachmentsForRender.push_back(nullptr);
345*8975f5c5SAndroid Build Coastguard Worker             mColorAttachmentsForRenderMask.set(attachmentIndex);
346*8975f5c5SAndroid Build Coastguard Worker         }
347*8975f5c5SAndroid Build Coastguard Worker     }
348*8975f5c5SAndroid Build Coastguard Worker 
349*8975f5c5SAndroid Build Coastguard Worker     // When rendering with no render target on D3D, two bugs lead to incorrect behavior on Intel
350*8975f5c5SAndroid Build Coastguard Worker     // drivers < 4815. The rendering samples always pass neglecting discard statements in pixel
351*8975f5c5SAndroid Build Coastguard Worker     // shader. We add a mock texture as render target in such case.
352*8975f5c5SAndroid Build Coastguard Worker     if (mRenderer->getFeatures().addMockTextureNoRenderTarget.enabled &&
353*8975f5c5SAndroid Build Coastguard Worker         colorAttachmentsForRender.empty() && activeProgramOutputs.any())
354*8975f5c5SAndroid Build Coastguard Worker     {
355*8975f5c5SAndroid Build Coastguard Worker         static_assert(static_cast<size_t>(activeProgramOutputs.size()) <= 32,
356*8975f5c5SAndroid Build Coastguard Worker                       "Size of active program outputs should less or equal than 32.");
357*8975f5c5SAndroid Build Coastguard Worker         const GLuint activeProgramLocation = static_cast<GLuint>(
358*8975f5c5SAndroid Build Coastguard Worker             gl::ScanForward(static_cast<uint32_t>(activeProgramOutputs.bits())));
359*8975f5c5SAndroid Build Coastguard Worker 
360*8975f5c5SAndroid Build Coastguard Worker         if (mMockAttachment.isAttached() &&
361*8975f5c5SAndroid Build Coastguard Worker             (mMockAttachment.getBinding() - GL_COLOR_ATTACHMENT0) == activeProgramLocation)
362*8975f5c5SAndroid Build Coastguard Worker         {
363*8975f5c5SAndroid Build Coastguard Worker             colorAttachmentsForRender.push_back(&mMockAttachment);
364*8975f5c5SAndroid Build Coastguard Worker         }
365*8975f5c5SAndroid Build Coastguard Worker         else
366*8975f5c5SAndroid Build Coastguard Worker         {
367*8975f5c5SAndroid Build Coastguard Worker             // Remove mock attachment to prevents us from leaking it, and the program may require
368*8975f5c5SAndroid Build Coastguard Worker             // it to be attached to a new binding point.
369*8975f5c5SAndroid Build Coastguard Worker             if (mMockAttachment.isAttached())
370*8975f5c5SAndroid Build Coastguard Worker             {
371*8975f5c5SAndroid Build Coastguard Worker                 mMockAttachment.detach(context, UniqueSerial());
372*8975f5c5SAndroid Build Coastguard Worker             }
373*8975f5c5SAndroid Build Coastguard Worker 
374*8975f5c5SAndroid Build Coastguard Worker             gl::Texture *mockTex = nullptr;
375*8975f5c5SAndroid Build Coastguard Worker             // TODO(jmadill): Handle error if mock texture can't be created.
376*8975f5c5SAndroid Build Coastguard Worker             (void)mRenderer->getIncompleteTexture(context, gl::TextureType::_2D, &mockTex);
377*8975f5c5SAndroid Build Coastguard Worker             if (mockTex)
378*8975f5c5SAndroid Build Coastguard Worker             {
379*8975f5c5SAndroid Build Coastguard Worker                 gl::ImageIndex index = gl::ImageIndex::Make2D(0);
380*8975f5c5SAndroid Build Coastguard Worker                 mMockAttachment      = gl::FramebufferAttachment(
381*8975f5c5SAndroid Build Coastguard Worker                     context, GL_TEXTURE, GL_COLOR_ATTACHMENT0_EXT + activeProgramLocation, index,
382*8975f5c5SAndroid Build Coastguard Worker                     mockTex, UniqueSerial());
383*8975f5c5SAndroid Build Coastguard Worker                 colorAttachmentsForRender.push_back(&mMockAttachment);
384*8975f5c5SAndroid Build Coastguard Worker             }
385*8975f5c5SAndroid Build Coastguard Worker         }
386*8975f5c5SAndroid Build Coastguard Worker     }
387*8975f5c5SAndroid Build Coastguard Worker 
388*8975f5c5SAndroid Build Coastguard Worker     mColorAttachmentsForRender   = std::move(colorAttachmentsForRender);
389*8975f5c5SAndroid Build Coastguard Worker     mCurrentActiveProgramOutputs = activeProgramOutputs;
390*8975f5c5SAndroid Build Coastguard Worker 
391*8975f5c5SAndroid Build Coastguard Worker     return mColorAttachmentsForRender.value();
392*8975f5c5SAndroid Build Coastguard Worker }
393*8975f5c5SAndroid Build Coastguard Worker 
destroy(const gl::Context * context)394*8975f5c5SAndroid Build Coastguard Worker void FramebufferD3D::destroy(const gl::Context *context)
395*8975f5c5SAndroid Build Coastguard Worker {
396*8975f5c5SAndroid Build Coastguard Worker     if (mMockAttachment.isAttached())
397*8975f5c5SAndroid Build Coastguard Worker     {
398*8975f5c5SAndroid Build Coastguard Worker         mMockAttachment.detach(context, UniqueSerial());
399*8975f5c5SAndroid Build Coastguard Worker     }
400*8975f5c5SAndroid Build Coastguard Worker }
401*8975f5c5SAndroid Build Coastguard Worker 
402*8975f5c5SAndroid Build Coastguard Worker }  // namespace rx
403