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