1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 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 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8*8975f5c5SAndroid Build Coastguard Worker // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9*8975f5c5SAndroid Build Coastguard Worker
10*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Framebuffer.h"
11*8975f5c5SAndroid Build Coastguard Worker
12*8975f5c5SAndroid Build Coastguard Worker #include "common/Optional.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/bitset_utils.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Config.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Context.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Display.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ErrorStrings.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/FramebufferAttachment.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/PixelLocalStorage.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Renderbuffer.h"
22*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/ShareGroup.h"
23*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Surface.h"
24*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/Texture.h"
25*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/angletypes.h"
26*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/formatutils.h"
27*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/ContextImpl.h"
28*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/FramebufferImpl.h"
29*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/GLImplFactory.h"
30*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/RenderbufferImpl.h"
31*8975f5c5SAndroid Build Coastguard Worker #include "libANGLE/renderer/SurfaceImpl.h"
32*8975f5c5SAndroid Build Coastguard Worker
33*8975f5c5SAndroid Build Coastguard Worker using namespace angle;
34*8975f5c5SAndroid Build Coastguard Worker
35*8975f5c5SAndroid Build Coastguard Worker namespace gl
36*8975f5c5SAndroid Build Coastguard Worker {
37*8975f5c5SAndroid Build Coastguard Worker
38*8975f5c5SAndroid Build Coastguard Worker namespace
39*8975f5c5SAndroid Build Coastguard Worker {
40*8975f5c5SAndroid Build Coastguard Worker
41*8975f5c5SAndroid Build Coastguard Worker // Check the |checkAttachment| in reference to |firstAttachment| for the sake of multiview
42*8975f5c5SAndroid Build Coastguard Worker // framebuffer completeness.
CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment * firstAttachment,const FramebufferAttachment * checkAttachment)43*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus CheckMultiviewStateMatchesForCompleteness(
44*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *firstAttachment,
45*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *checkAttachment)
46*8975f5c5SAndroid Build Coastguard Worker {
47*8975f5c5SAndroid Build Coastguard Worker ASSERT(firstAttachment && checkAttachment);
48*8975f5c5SAndroid Build Coastguard Worker ASSERT(firstAttachment->isAttached() && checkAttachment->isAttached());
49*8975f5c5SAndroid Build Coastguard Worker
50*8975f5c5SAndroid Build Coastguard Worker if (firstAttachment->isMultiview() != checkAttachment->isMultiview())
51*8975f5c5SAndroid Build Coastguard Worker {
52*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
53*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultiviewMismatch);
54*8975f5c5SAndroid Build Coastguard Worker }
55*8975f5c5SAndroid Build Coastguard Worker if (firstAttachment->getNumViews() != checkAttachment->getNumViews())
56*8975f5c5SAndroid Build Coastguard Worker {
57*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
58*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultiviewViewsMismatch);
59*8975f5c5SAndroid Build Coastguard Worker }
60*8975f5c5SAndroid Build Coastguard Worker if (checkAttachment->getBaseViewIndex() + checkAttachment->getNumViews() >
61*8975f5c5SAndroid Build Coastguard Worker checkAttachment->getSize().depth)
62*8975f5c5SAndroid Build Coastguard Worker {
63*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR,
64*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultiviewBaseViewMismatch);
65*8975f5c5SAndroid Build Coastguard Worker }
66*8975f5c5SAndroid Build Coastguard Worker
67*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Complete();
68*8975f5c5SAndroid Build Coastguard Worker }
69*8975f5c5SAndroid Build Coastguard Worker
CheckAttachmentCompleteness(const Context * context,const FramebufferAttachment & attachment)70*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus CheckAttachmentCompleteness(const Context *context,
71*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &attachment)
72*8975f5c5SAndroid Build Coastguard Worker {
73*8975f5c5SAndroid Build Coastguard Worker ASSERT(attachment.isAttached());
74*8975f5c5SAndroid Build Coastguard Worker
75*8975f5c5SAndroid Build Coastguard Worker const Extents &size = attachment.getSize();
76*8975f5c5SAndroid Build Coastguard Worker if (size.width == 0 || size.height == 0)
77*8975f5c5SAndroid Build Coastguard Worker {
78*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
79*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentZeroSize);
80*8975f5c5SAndroid Build Coastguard Worker }
81*8975f5c5SAndroid Build Coastguard Worker
82*8975f5c5SAndroid Build Coastguard Worker if (!attachment.isRenderable(context))
83*8975f5c5SAndroid Build Coastguard Worker {
84*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
85*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentNotRenderable);
86*8975f5c5SAndroid Build Coastguard Worker }
87*8975f5c5SAndroid Build Coastguard Worker
88*8975f5c5SAndroid Build Coastguard Worker if (attachment.type() == GL_TEXTURE)
89*8975f5c5SAndroid Build Coastguard Worker {
90*8975f5c5SAndroid Build Coastguard Worker // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness"
91*8975f5c5SAndroid Build Coastguard Worker // If <image> is a three-dimensional texture or a two-dimensional array texture and the
92*8975f5c5SAndroid Build Coastguard Worker // attachment is not layered, the selected layer is less than the depth or layer count,
93*8975f5c5SAndroid Build Coastguard Worker // respectively, of the texture.
94*8975f5c5SAndroid Build Coastguard Worker if (!attachment.isLayered())
95*8975f5c5SAndroid Build Coastguard Worker {
96*8975f5c5SAndroid Build Coastguard Worker if (attachment.layer() >= size.depth)
97*8975f5c5SAndroid Build Coastguard Worker {
98*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
99*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
100*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentLayerGreaterThanDepth);
101*8975f5c5SAndroid Build Coastguard Worker }
102*8975f5c5SAndroid Build Coastguard Worker }
103*8975f5c5SAndroid Build Coastguard Worker // If <image> is a three-dimensional texture or a two-dimensional array texture and the
104*8975f5c5SAndroid Build Coastguard Worker // attachment is layered, the depth or layer count, respectively, of the texture is less
105*8975f5c5SAndroid Build Coastguard Worker // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
106*8975f5c5SAndroid Build Coastguard Worker else
107*8975f5c5SAndroid Build Coastguard Worker {
108*8975f5c5SAndroid Build Coastguard Worker if (size.depth >= context->getCaps().maxFramebufferLayers)
109*8975f5c5SAndroid Build Coastguard Worker {
110*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
111*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
112*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentDepthGreaterThanMaxLayers);
113*8975f5c5SAndroid Build Coastguard Worker }
114*8975f5c5SAndroid Build Coastguard Worker }
115*8975f5c5SAndroid Build Coastguard Worker
116*8975f5c5SAndroid Build Coastguard Worker // ES3 specifies that cube map texture attachments must be cube complete.
117*8975f5c5SAndroid Build Coastguard Worker // This language is missing from the ES2 spec, but we enforce it here because some
118*8975f5c5SAndroid Build Coastguard Worker // desktop OpenGL drivers also enforce this validation.
119*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
120*8975f5c5SAndroid Build Coastguard Worker const Texture *texture = attachment.getTexture();
121*8975f5c5SAndroid Build Coastguard Worker ASSERT(texture);
122*8975f5c5SAndroid Build Coastguard Worker if (texture->getType() == TextureType::CubeMap &&
123*8975f5c5SAndroid Build Coastguard Worker !texture->getTextureState().isCubeComplete())
124*8975f5c5SAndroid Build Coastguard Worker {
125*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
126*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
127*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentNotCubeComplete);
128*8975f5c5SAndroid Build Coastguard Worker }
129*8975f5c5SAndroid Build Coastguard Worker
130*8975f5c5SAndroid Build Coastguard Worker if (!texture->getImmutableFormat())
131*8975f5c5SAndroid Build Coastguard Worker {
132*8975f5c5SAndroid Build Coastguard Worker GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
133*8975f5c5SAndroid Build Coastguard Worker
134*8975f5c5SAndroid Build Coastguard Worker // From the ES 3.0 spec, pg 213:
135*8975f5c5SAndroid Build Coastguard Worker // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
136*8975f5c5SAndroid Build Coastguard Worker // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
137*8975f5c5SAndroid Build Coastguard Worker // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
138*8975f5c5SAndroid Build Coastguard Worker // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
139*8975f5c5SAndroid Build Coastguard Worker // the effective maximum texture level defined in the Mipmapping discussion of
140*8975f5c5SAndroid Build Coastguard Worker // section 3.8.10.4.
141*8975f5c5SAndroid Build Coastguard Worker if (attachmentMipLevel < texture->getBaseLevel() ||
142*8975f5c5SAndroid Build Coastguard Worker attachmentMipLevel > texture->getMipmapMaxLevel())
143*8975f5c5SAndroid Build Coastguard Worker {
144*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
145*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
146*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentLevelOutOfBaseMaxLevelRange);
147*8975f5c5SAndroid Build Coastguard Worker }
148*8975f5c5SAndroid Build Coastguard Worker
149*8975f5c5SAndroid Build Coastguard Worker // Form the ES 3.0 spec, pg 213/214:
150*8975f5c5SAndroid Build Coastguard Worker // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
151*8975f5c5SAndroid Build Coastguard Worker // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
152*8975f5c5SAndroid Build Coastguard Worker // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
153*8975f5c5SAndroid Build Coastguard Worker // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
154*8975f5c5SAndroid Build Coastguard Worker // a cubemap texture, the texture must also be cube complete.
155*8975f5c5SAndroid Build Coastguard Worker if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
156*8975f5c5SAndroid Build Coastguard Worker {
157*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
158*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
159*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentLevelNotBaseLevelForIncompleteMipTexture);
160*8975f5c5SAndroid Build Coastguard Worker }
161*8975f5c5SAndroid Build Coastguard Worker }
162*8975f5c5SAndroid Build Coastguard Worker }
163*8975f5c5SAndroid Build Coastguard Worker
164*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Complete();
165*8975f5c5SAndroid Build Coastguard Worker }
166*8975f5c5SAndroid Build Coastguard Worker
CheckAttachmentSampleCounts(const Context * context,GLsizei currAttachmentSamples,GLsizei samples,bool colorAttachment)167*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus CheckAttachmentSampleCounts(const Context *context,
168*8975f5c5SAndroid Build Coastguard Worker GLsizei currAttachmentSamples,
169*8975f5c5SAndroid Build Coastguard Worker GLsizei samples,
170*8975f5c5SAndroid Build Coastguard Worker bool colorAttachment)
171*8975f5c5SAndroid Build Coastguard Worker {
172*8975f5c5SAndroid Build Coastguard Worker if (currAttachmentSamples != samples)
173*8975f5c5SAndroid Build Coastguard Worker {
174*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment)
175*8975f5c5SAndroid Build Coastguard Worker {
176*8975f5c5SAndroid Build Coastguard Worker // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
177*8975f5c5SAndroid Build Coastguard Worker // all color attachments have the same number of samples for the FBO to be complete.
178*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
179*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
180*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultisampleInconsistentSampleCounts);
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker else
183*8975f5c5SAndroid Build Coastguard Worker {
184*8975f5c5SAndroid Build Coastguard Worker // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
185*8975f5c5SAndroid Build Coastguard Worker // when its depth or stencil samples are a multiple of the number of color samples.
186*8975f5c5SAndroid Build Coastguard Worker if (!context->getExtensions().framebufferMixedSamplesCHROMIUM)
187*8975f5c5SAndroid Build Coastguard Worker {
188*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
189*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
190*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultisampleInconsistentSampleCounts);
191*8975f5c5SAndroid Build Coastguard Worker }
192*8975f5c5SAndroid Build Coastguard Worker
193*8975f5c5SAndroid Build Coastguard Worker if ((currAttachmentSamples % std::max(samples, 1)) != 0)
194*8975f5c5SAndroid Build Coastguard Worker {
195*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
196*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
197*8975f5c5SAndroid Build Coastguard Worker err::
198*8975f5c5SAndroid Build Coastguard Worker kFramebufferIncompleteMultisampleDepthStencilSampleCountDivisibleByColorSampleCount);
199*8975f5c5SAndroid Build Coastguard Worker }
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker }
202*8975f5c5SAndroid Build Coastguard Worker
203*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Complete();
204*8975f5c5SAndroid Build Coastguard Worker }
205*8975f5c5SAndroid Build Coastguard Worker
CheckAttachmentSampleCompleteness(const Context * context,const FramebufferAttachment & attachment,bool colorAttachment,Optional<int> * samples,Optional<bool> * fixedSampleLocations,Optional<int> * renderToTextureSamples)206*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context,
207*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &attachment,
208*8975f5c5SAndroid Build Coastguard Worker bool colorAttachment,
209*8975f5c5SAndroid Build Coastguard Worker Optional<int> *samples,
210*8975f5c5SAndroid Build Coastguard Worker Optional<bool> *fixedSampleLocations,
211*8975f5c5SAndroid Build Coastguard Worker Optional<int> *renderToTextureSamples)
212*8975f5c5SAndroid Build Coastguard Worker {
213*8975f5c5SAndroid Build Coastguard Worker ASSERT(attachment.isAttached());
214*8975f5c5SAndroid Build Coastguard Worker
215*8975f5c5SAndroid Build Coastguard Worker if (attachment.type() == GL_TEXTURE)
216*8975f5c5SAndroid Build Coastguard Worker {
217*8975f5c5SAndroid Build Coastguard Worker const Texture *texture = attachment.getTexture();
218*8975f5c5SAndroid Build Coastguard Worker ASSERT(texture);
219*8975f5c5SAndroid Build Coastguard Worker GLenum sizedInternalFormat = attachment.getFormat().info->sizedInternalFormat;
220*8975f5c5SAndroid Build Coastguard Worker const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
221*8975f5c5SAndroid Build Coastguard Worker if (static_cast<GLuint>(attachment.getSamples()) > formatCaps.getMaxSamples())
222*8975f5c5SAndroid Build Coastguard Worker {
223*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
224*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
225*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentSamplesGreaterThanMaxSupportedSamples);
226*8975f5c5SAndroid Build Coastguard Worker }
227*8975f5c5SAndroid Build Coastguard Worker
228*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
229*8975f5c5SAndroid Build Coastguard Worker bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
230*8975f5c5SAndroid Build Coastguard Worker if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
231*8975f5c5SAndroid Build Coastguard Worker {
232*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
233*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
234*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultisampleInconsistentFixedSampleLocations);
235*8975f5c5SAndroid Build Coastguard Worker }
236*8975f5c5SAndroid Build Coastguard Worker else
237*8975f5c5SAndroid Build Coastguard Worker {
238*8975f5c5SAndroid Build Coastguard Worker *fixedSampleLocations = fixedSampleloc;
239*8975f5c5SAndroid Build Coastguard Worker }
240*8975f5c5SAndroid Build Coastguard Worker }
241*8975f5c5SAndroid Build Coastguard Worker
242*8975f5c5SAndroid Build Coastguard Worker if (renderToTextureSamples->valid())
243*8975f5c5SAndroid Build Coastguard Worker {
244*8975f5c5SAndroid Build Coastguard Worker // Only check against RenderToTextureSamples if they actually exist.
245*8975f5c5SAndroid Build Coastguard Worker if (renderToTextureSamples->value() !=
246*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples)
247*8975f5c5SAndroid Build Coastguard Worker {
248*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus sampleCountStatus =
249*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentSampleCounts(context, attachment.getRenderToTextureSamples(),
250*8975f5c5SAndroid Build Coastguard Worker renderToTextureSamples->value(), colorAttachment);
251*8975f5c5SAndroid Build Coastguard Worker if (!sampleCountStatus.isComplete())
252*8975f5c5SAndroid Build Coastguard Worker {
253*8975f5c5SAndroid Build Coastguard Worker return sampleCountStatus;
254*8975f5c5SAndroid Build Coastguard Worker }
255*8975f5c5SAndroid Build Coastguard Worker }
256*8975f5c5SAndroid Build Coastguard Worker }
257*8975f5c5SAndroid Build Coastguard Worker else
258*8975f5c5SAndroid Build Coastguard Worker {
259*8975f5c5SAndroid Build Coastguard Worker *renderToTextureSamples = attachment.getRenderToTextureSamples();
260*8975f5c5SAndroid Build Coastguard Worker }
261*8975f5c5SAndroid Build Coastguard Worker
262*8975f5c5SAndroid Build Coastguard Worker if (samples->valid())
263*8975f5c5SAndroid Build Coastguard Worker {
264*8975f5c5SAndroid Build Coastguard Worker // RenderToTextureSamples takes precedence if they exist.
265*8975f5c5SAndroid Build Coastguard Worker if (renderToTextureSamples->value() ==
266*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples)
267*8975f5c5SAndroid Build Coastguard Worker {
268*8975f5c5SAndroid Build Coastguard Worker
269*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus sampleCountStatus = CheckAttachmentSampleCounts(
270*8975f5c5SAndroid Build Coastguard Worker context, attachment.getSamples(), samples->value(), colorAttachment);
271*8975f5c5SAndroid Build Coastguard Worker if (!sampleCountStatus.isComplete())
272*8975f5c5SAndroid Build Coastguard Worker {
273*8975f5c5SAndroid Build Coastguard Worker return sampleCountStatus;
274*8975f5c5SAndroid Build Coastguard Worker }
275*8975f5c5SAndroid Build Coastguard Worker }
276*8975f5c5SAndroid Build Coastguard Worker }
277*8975f5c5SAndroid Build Coastguard Worker else
278*8975f5c5SAndroid Build Coastguard Worker {
279*8975f5c5SAndroid Build Coastguard Worker *samples = attachment.getSamples();
280*8975f5c5SAndroid Build Coastguard Worker }
281*8975f5c5SAndroid Build Coastguard Worker
282*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Complete();
283*8975f5c5SAndroid Build Coastguard Worker }
284*8975f5c5SAndroid Build Coastguard Worker
285*8975f5c5SAndroid Build Coastguard Worker // Needed to index into the attachment arrays/bitsets.
286*8975f5c5SAndroid Build Coastguard Worker static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) ==
287*8975f5c5SAndroid Build Coastguard Worker Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
288*8975f5c5SAndroid Build Coastguard Worker "Framebuffer Dirty bit mismatch");
289*8975f5c5SAndroid Build Coastguard Worker static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) ==
290*8975f5c5SAndroid Build Coastguard Worker Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
291*8975f5c5SAndroid Build Coastguard Worker "Framebuffer Dirty bit mismatch");
292*8975f5c5SAndroid Build Coastguard Worker static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS + 1) ==
293*8975f5c5SAndroid Build Coastguard Worker Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
294*8975f5c5SAndroid Build Coastguard Worker "Framebuffer Dirty bit mismatch");
295*8975f5c5SAndroid Build Coastguard Worker
InitAttachment(const Context * context,FramebufferAttachment * attachment)296*8975f5c5SAndroid Build Coastguard Worker angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment)
297*8975f5c5SAndroid Build Coastguard Worker {
298*8975f5c5SAndroid Build Coastguard Worker ASSERT(attachment->isAttached());
299*8975f5c5SAndroid Build Coastguard Worker if (attachment->initState() == InitState::MayNeedInit)
300*8975f5c5SAndroid Build Coastguard Worker {
301*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(attachment->initializeContents(context));
302*8975f5c5SAndroid Build Coastguard Worker }
303*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
304*8975f5c5SAndroid Build Coastguard Worker }
305*8975f5c5SAndroid Build Coastguard Worker
AttachmentOverlapsWithTexture(const FramebufferAttachment & attachment,const Texture * texture,const Sampler * sampler)306*8975f5c5SAndroid Build Coastguard Worker bool AttachmentOverlapsWithTexture(const FramebufferAttachment &attachment,
307*8975f5c5SAndroid Build Coastguard Worker const Texture *texture,
308*8975f5c5SAndroid Build Coastguard Worker const Sampler *sampler)
309*8975f5c5SAndroid Build Coastguard Worker {
310*8975f5c5SAndroid Build Coastguard Worker if (!attachment.isTextureWithId(texture->id()))
311*8975f5c5SAndroid Build Coastguard Worker {
312*8975f5c5SAndroid Build Coastguard Worker return false;
313*8975f5c5SAndroid Build Coastguard Worker }
314*8975f5c5SAndroid Build Coastguard Worker
315*8975f5c5SAndroid Build Coastguard Worker const gl::ImageIndex &index = attachment.getTextureImageIndex();
316*8975f5c5SAndroid Build Coastguard Worker GLuint attachmentLevel = static_cast<GLuint>(index.getLevelIndex());
317*8975f5c5SAndroid Build Coastguard Worker GLuint textureEffectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel();
318*8975f5c5SAndroid Build Coastguard Worker GLuint textureMaxLevel = textureEffectiveBaseLevel;
319*8975f5c5SAndroid Build Coastguard Worker if ((sampler && IsMipmapFiltered(sampler->getSamplerState().getMinFilter())) ||
320*8975f5c5SAndroid Build Coastguard Worker IsMipmapFiltered(texture->getSamplerState().getMinFilter()))
321*8975f5c5SAndroid Build Coastguard Worker {
322*8975f5c5SAndroid Build Coastguard Worker textureMaxLevel = texture->getMipmapMaxLevel();
323*8975f5c5SAndroid Build Coastguard Worker }
324*8975f5c5SAndroid Build Coastguard Worker
325*8975f5c5SAndroid Build Coastguard Worker return attachmentLevel >= textureEffectiveBaseLevel && attachmentLevel <= textureMaxLevel;
326*8975f5c5SAndroid Build Coastguard Worker }
327*8975f5c5SAndroid Build Coastguard Worker
GetAttachmentComponentType(GLenum componentType)328*8975f5c5SAndroid Build Coastguard Worker constexpr ComponentType GetAttachmentComponentType(GLenum componentType)
329*8975f5c5SAndroid Build Coastguard Worker {
330*8975f5c5SAndroid Build Coastguard Worker switch (componentType)
331*8975f5c5SAndroid Build Coastguard Worker {
332*8975f5c5SAndroid Build Coastguard Worker case GL_INT:
333*8975f5c5SAndroid Build Coastguard Worker return ComponentType::Int;
334*8975f5c5SAndroid Build Coastguard Worker case GL_UNSIGNED_INT:
335*8975f5c5SAndroid Build Coastguard Worker return ComponentType::UnsignedInt;
336*8975f5c5SAndroid Build Coastguard Worker default:
337*8975f5c5SAndroid Build Coastguard Worker return ComponentType::Float;
338*8975f5c5SAndroid Build Coastguard Worker }
339*8975f5c5SAndroid Build Coastguard Worker }
340*8975f5c5SAndroid Build Coastguard Worker
HasSupportedStencilBitCount(const Framebuffer * framebuffer)341*8975f5c5SAndroid Build Coastguard Worker bool HasSupportedStencilBitCount(const Framebuffer *framebuffer)
342*8975f5c5SAndroid Build Coastguard Worker {
343*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *stencilAttachment =
344*8975f5c5SAndroid Build Coastguard Worker framebuffer ? framebuffer->getStencilOrDepthStencilAttachment() : nullptr;
345*8975f5c5SAndroid Build Coastguard Worker return !stencilAttachment || stencilAttachment->getStencilSize() == 8;
346*8975f5c5SAndroid Build Coastguard Worker }
347*8975f5c5SAndroid Build Coastguard Worker
348*8975f5c5SAndroid Build Coastguard Worker } // anonymous namespace
349*8975f5c5SAndroid Build Coastguard Worker
isComplete() const350*8975f5c5SAndroid Build Coastguard Worker bool FramebufferStatus::isComplete() const
351*8975f5c5SAndroid Build Coastguard Worker {
352*8975f5c5SAndroid Build Coastguard Worker return status == GL_FRAMEBUFFER_COMPLETE;
353*8975f5c5SAndroid Build Coastguard Worker }
354*8975f5c5SAndroid Build Coastguard Worker
Complete()355*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus FramebufferStatus::Complete()
356*8975f5c5SAndroid Build Coastguard Worker {
357*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus result;
358*8975f5c5SAndroid Build Coastguard Worker result.status = GL_FRAMEBUFFER_COMPLETE;
359*8975f5c5SAndroid Build Coastguard Worker result.reason = nullptr;
360*8975f5c5SAndroid Build Coastguard Worker return result;
361*8975f5c5SAndroid Build Coastguard Worker }
362*8975f5c5SAndroid Build Coastguard Worker
Incomplete(GLenum status,const char * reason)363*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus FramebufferStatus::Incomplete(GLenum status, const char *reason)
364*8975f5c5SAndroid Build Coastguard Worker {
365*8975f5c5SAndroid Build Coastguard Worker ASSERT(status != GL_FRAMEBUFFER_COMPLETE);
366*8975f5c5SAndroid Build Coastguard Worker
367*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus result;
368*8975f5c5SAndroid Build Coastguard Worker result.status = status;
369*8975f5c5SAndroid Build Coastguard Worker result.reason = reason;
370*8975f5c5SAndroid Build Coastguard Worker return result;
371*8975f5c5SAndroid Build Coastguard Worker }
372*8975f5c5SAndroid Build Coastguard Worker
373*8975f5c5SAndroid Build Coastguard Worker // This constructor is only used for default framebuffers.
FramebufferState(rx::UniqueSerial serial)374*8975f5c5SAndroid Build Coastguard Worker FramebufferState::FramebufferState(rx::UniqueSerial serial)
375*8975f5c5SAndroid Build Coastguard Worker : mId(Framebuffer::kDefaultDrawFramebufferHandle),
376*8975f5c5SAndroid Build Coastguard Worker mFramebufferSerial(serial),
377*8975f5c5SAndroid Build Coastguard Worker mLabel(),
378*8975f5c5SAndroid Build Coastguard Worker mColorAttachments(1),
379*8975f5c5SAndroid Build Coastguard Worker mColorAttachmentsMask(0),
380*8975f5c5SAndroid Build Coastguard Worker mDrawBufferStates(1, GL_BACK),
381*8975f5c5SAndroid Build Coastguard Worker mReadBufferState(GL_BACK),
382*8975f5c5SAndroid Build Coastguard Worker mDrawBufferTypeMask(),
383*8975f5c5SAndroid Build Coastguard Worker mDefaultWidth(0),
384*8975f5c5SAndroid Build Coastguard Worker mDefaultHeight(0),
385*8975f5c5SAndroid Build Coastguard Worker mDefaultSamples(0),
386*8975f5c5SAndroid Build Coastguard Worker mDefaultFixedSampleLocations(GL_FALSE),
387*8975f5c5SAndroid Build Coastguard Worker mDefaultLayers(0),
388*8975f5c5SAndroid Build Coastguard Worker mFlipY(GL_FALSE),
389*8975f5c5SAndroid Build Coastguard Worker mWebGLDepthStencilConsistent(true),
390*8975f5c5SAndroid Build Coastguard Worker mDefaultFramebufferReadAttachmentInitialized(false),
391*8975f5c5SAndroid Build Coastguard Worker mSrgbWriteControlMode(SrgbWriteControlMode::Default)
392*8975f5c5SAndroid Build Coastguard Worker {
393*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDrawBufferStates.size() > 0);
394*8975f5c5SAndroid Build Coastguard Worker mEnabledDrawBuffers.set(0);
395*8975f5c5SAndroid Build Coastguard Worker }
396*8975f5c5SAndroid Build Coastguard Worker
FramebufferState(const Caps & caps,FramebufferID id,rx::UniqueSerial serial)397*8975f5c5SAndroid Build Coastguard Worker FramebufferState::FramebufferState(const Caps &caps, FramebufferID id, rx::UniqueSerial serial)
398*8975f5c5SAndroid Build Coastguard Worker : mId(id),
399*8975f5c5SAndroid Build Coastguard Worker mFramebufferSerial(serial),
400*8975f5c5SAndroid Build Coastguard Worker mLabel(),
401*8975f5c5SAndroid Build Coastguard Worker mColorAttachments(caps.maxColorAttachments),
402*8975f5c5SAndroid Build Coastguard Worker mColorAttachmentsMask(0),
403*8975f5c5SAndroid Build Coastguard Worker mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
404*8975f5c5SAndroid Build Coastguard Worker mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
405*8975f5c5SAndroid Build Coastguard Worker mDrawBufferTypeMask(),
406*8975f5c5SAndroid Build Coastguard Worker mDefaultWidth(0),
407*8975f5c5SAndroid Build Coastguard Worker mDefaultHeight(0),
408*8975f5c5SAndroid Build Coastguard Worker mDefaultSamples(0),
409*8975f5c5SAndroid Build Coastguard Worker mDefaultFixedSampleLocations(GL_FALSE),
410*8975f5c5SAndroid Build Coastguard Worker mDefaultLayers(0),
411*8975f5c5SAndroid Build Coastguard Worker mFlipY(GL_FALSE),
412*8975f5c5SAndroid Build Coastguard Worker mWebGLDepthStencilConsistent(true),
413*8975f5c5SAndroid Build Coastguard Worker mDefaultFramebufferReadAttachmentInitialized(false),
414*8975f5c5SAndroid Build Coastguard Worker mSrgbWriteControlMode(SrgbWriteControlMode::Default)
415*8975f5c5SAndroid Build Coastguard Worker {
416*8975f5c5SAndroid Build Coastguard Worker ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
417*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDrawBufferStates.size() > 0);
418*8975f5c5SAndroid Build Coastguard Worker mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
419*8975f5c5SAndroid Build Coastguard Worker }
420*8975f5c5SAndroid Build Coastguard Worker
~FramebufferState()421*8975f5c5SAndroid Build Coastguard Worker FramebufferState::~FramebufferState() {}
422*8975f5c5SAndroid Build Coastguard Worker
getLabel() const423*8975f5c5SAndroid Build Coastguard Worker const std::string &FramebufferState::getLabel() const
424*8975f5c5SAndroid Build Coastguard Worker {
425*8975f5c5SAndroid Build Coastguard Worker return mLabel;
426*8975f5c5SAndroid Build Coastguard Worker }
427*8975f5c5SAndroid Build Coastguard Worker
getAttachment(const Context * context,GLenum attachment) const428*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
429*8975f5c5SAndroid Build Coastguard Worker GLenum attachment) const
430*8975f5c5SAndroid Build Coastguard Worker {
431*8975f5c5SAndroid Build Coastguard Worker if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
432*8975f5c5SAndroid Build Coastguard Worker {
433*8975f5c5SAndroid Build Coastguard Worker return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
434*8975f5c5SAndroid Build Coastguard Worker }
435*8975f5c5SAndroid Build Coastguard Worker
436*8975f5c5SAndroid Build Coastguard Worker // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
437*8975f5c5SAndroid Build Coastguard Worker // multiple conflicting attachment points) and requires us to return the framebuffer attachment
438*8975f5c5SAndroid Build Coastguard Worker // associated with WebGL.
439*8975f5c5SAndroid Build Coastguard Worker switch (attachment)
440*8975f5c5SAndroid Build Coastguard Worker {
441*8975f5c5SAndroid Build Coastguard Worker case GL_COLOR:
442*8975f5c5SAndroid Build Coastguard Worker case GL_BACK:
443*8975f5c5SAndroid Build Coastguard Worker return getColorAttachment(0);
444*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH:
445*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_ATTACHMENT:
446*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL1())
447*8975f5c5SAndroid Build Coastguard Worker {
448*8975f5c5SAndroid Build Coastguard Worker return getWebGLDepthAttachment();
449*8975f5c5SAndroid Build Coastguard Worker }
450*8975f5c5SAndroid Build Coastguard Worker else
451*8975f5c5SAndroid Build Coastguard Worker {
452*8975f5c5SAndroid Build Coastguard Worker return getDepthAttachment();
453*8975f5c5SAndroid Build Coastguard Worker }
454*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL:
455*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL_ATTACHMENT:
456*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL1())
457*8975f5c5SAndroid Build Coastguard Worker {
458*8975f5c5SAndroid Build Coastguard Worker return getWebGLStencilAttachment();
459*8975f5c5SAndroid Build Coastguard Worker }
460*8975f5c5SAndroid Build Coastguard Worker else
461*8975f5c5SAndroid Build Coastguard Worker {
462*8975f5c5SAndroid Build Coastguard Worker return getStencilAttachment();
463*8975f5c5SAndroid Build Coastguard Worker }
464*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL:
465*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL_ATTACHMENT:
466*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL1())
467*8975f5c5SAndroid Build Coastguard Worker {
468*8975f5c5SAndroid Build Coastguard Worker return getWebGLDepthStencilAttachment();
469*8975f5c5SAndroid Build Coastguard Worker }
470*8975f5c5SAndroid Build Coastguard Worker else
471*8975f5c5SAndroid Build Coastguard Worker {
472*8975f5c5SAndroid Build Coastguard Worker return getDepthStencilAttachment();
473*8975f5c5SAndroid Build Coastguard Worker }
474*8975f5c5SAndroid Build Coastguard Worker default:
475*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
476*8975f5c5SAndroid Build Coastguard Worker return nullptr;
477*8975f5c5SAndroid Build Coastguard Worker }
478*8975f5c5SAndroid Build Coastguard Worker }
479*8975f5c5SAndroid Build Coastguard Worker
getReadIndex() const480*8975f5c5SAndroid Build Coastguard Worker uint32_t FramebufferState::getReadIndex() const
481*8975f5c5SAndroid Build Coastguard Worker {
482*8975f5c5SAndroid Build Coastguard Worker ASSERT(mReadBufferState == GL_BACK ||
483*8975f5c5SAndroid Build Coastguard Worker (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
484*8975f5c5SAndroid Build Coastguard Worker uint32_t readIndex = mReadBufferState == GL_BACK ? 0 : mReadBufferState - GL_COLOR_ATTACHMENT0;
485*8975f5c5SAndroid Build Coastguard Worker ASSERT(readIndex < mColorAttachments.size());
486*8975f5c5SAndroid Build Coastguard Worker return readIndex;
487*8975f5c5SAndroid Build Coastguard Worker }
488*8975f5c5SAndroid Build Coastguard Worker
getReadAttachment() const489*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getReadAttachment() const
490*8975f5c5SAndroid Build Coastguard Worker {
491*8975f5c5SAndroid Build Coastguard Worker if (mReadBufferState == GL_NONE)
492*8975f5c5SAndroid Build Coastguard Worker {
493*8975f5c5SAndroid Build Coastguard Worker return nullptr;
494*8975f5c5SAndroid Build Coastguard Worker }
495*8975f5c5SAndroid Build Coastguard Worker
496*8975f5c5SAndroid Build Coastguard Worker uint32_t readIndex = getReadIndex();
497*8975f5c5SAndroid Build Coastguard Worker const gl::FramebufferAttachment &framebufferAttachment =
498*8975f5c5SAndroid Build Coastguard Worker isDefault() ? mDefaultFramebufferReadAttachment : mColorAttachments[readIndex];
499*8975f5c5SAndroid Build Coastguard Worker
500*8975f5c5SAndroid Build Coastguard Worker return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr;
501*8975f5c5SAndroid Build Coastguard Worker }
502*8975f5c5SAndroid Build Coastguard Worker
getReadPixelsAttachment(GLenum readFormat) const503*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getReadPixelsAttachment(GLenum readFormat) const
504*8975f5c5SAndroid Build Coastguard Worker {
505*8975f5c5SAndroid Build Coastguard Worker switch (readFormat)
506*8975f5c5SAndroid Build Coastguard Worker {
507*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_COMPONENT:
508*8975f5c5SAndroid Build Coastguard Worker return getDepthAttachment();
509*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL_INDEX_OES:
510*8975f5c5SAndroid Build Coastguard Worker return getStencilOrDepthStencilAttachment();
511*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL_OES:
512*8975f5c5SAndroid Build Coastguard Worker return getDepthStencilAttachment();
513*8975f5c5SAndroid Build Coastguard Worker default:
514*8975f5c5SAndroid Build Coastguard Worker return getReadAttachment();
515*8975f5c5SAndroid Build Coastguard Worker }
516*8975f5c5SAndroid Build Coastguard Worker }
517*8975f5c5SAndroid Build Coastguard Worker
getFirstNonNullAttachment() const518*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
519*8975f5c5SAndroid Build Coastguard Worker {
520*8975f5c5SAndroid Build Coastguard Worker auto *colorAttachment = getFirstColorAttachment();
521*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment)
522*8975f5c5SAndroid Build Coastguard Worker {
523*8975f5c5SAndroid Build Coastguard Worker return colorAttachment;
524*8975f5c5SAndroid Build Coastguard Worker }
525*8975f5c5SAndroid Build Coastguard Worker return getDepthOrStencilAttachment();
526*8975f5c5SAndroid Build Coastguard Worker }
527*8975f5c5SAndroid Build Coastguard Worker
getFirstColorAttachment() const528*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
529*8975f5c5SAndroid Build Coastguard Worker {
530*8975f5c5SAndroid Build Coastguard Worker for (const FramebufferAttachment &colorAttachment : mColorAttachments)
531*8975f5c5SAndroid Build Coastguard Worker {
532*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.isAttached())
533*8975f5c5SAndroid Build Coastguard Worker {
534*8975f5c5SAndroid Build Coastguard Worker return &colorAttachment;
535*8975f5c5SAndroid Build Coastguard Worker }
536*8975f5c5SAndroid Build Coastguard Worker }
537*8975f5c5SAndroid Build Coastguard Worker
538*8975f5c5SAndroid Build Coastguard Worker return nullptr;
539*8975f5c5SAndroid Build Coastguard Worker }
540*8975f5c5SAndroid Build Coastguard Worker
getDepthOrStencilAttachment() const541*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
542*8975f5c5SAndroid Build Coastguard Worker {
543*8975f5c5SAndroid Build Coastguard Worker if (mDepthAttachment.isAttached())
544*8975f5c5SAndroid Build Coastguard Worker {
545*8975f5c5SAndroid Build Coastguard Worker return &mDepthAttachment;
546*8975f5c5SAndroid Build Coastguard Worker }
547*8975f5c5SAndroid Build Coastguard Worker if (mStencilAttachment.isAttached())
548*8975f5c5SAndroid Build Coastguard Worker {
549*8975f5c5SAndroid Build Coastguard Worker return &mStencilAttachment;
550*8975f5c5SAndroid Build Coastguard Worker }
551*8975f5c5SAndroid Build Coastguard Worker return nullptr;
552*8975f5c5SAndroid Build Coastguard Worker }
553*8975f5c5SAndroid Build Coastguard Worker
getStencilOrDepthStencilAttachment() const554*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
555*8975f5c5SAndroid Build Coastguard Worker {
556*8975f5c5SAndroid Build Coastguard Worker if (mStencilAttachment.isAttached())
557*8975f5c5SAndroid Build Coastguard Worker {
558*8975f5c5SAndroid Build Coastguard Worker return &mStencilAttachment;
559*8975f5c5SAndroid Build Coastguard Worker }
560*8975f5c5SAndroid Build Coastguard Worker return getDepthStencilAttachment();
561*8975f5c5SAndroid Build Coastguard Worker }
562*8975f5c5SAndroid Build Coastguard Worker
getColorAttachment(size_t colorAttachment) const563*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
564*8975f5c5SAndroid Build Coastguard Worker {
565*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorAttachment < mColorAttachments.size());
566*8975f5c5SAndroid Build Coastguard Worker return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
567*8975f5c5SAndroid Build Coastguard Worker : nullptr;
568*8975f5c5SAndroid Build Coastguard Worker }
569*8975f5c5SAndroid Build Coastguard Worker
getDepthAttachment() const570*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getDepthAttachment() const
571*8975f5c5SAndroid Build Coastguard Worker {
572*8975f5c5SAndroid Build Coastguard Worker return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
573*8975f5c5SAndroid Build Coastguard Worker }
574*8975f5c5SAndroid Build Coastguard Worker
getWebGLDepthAttachment() const575*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
576*8975f5c5SAndroid Build Coastguard Worker {
577*8975f5c5SAndroid Build Coastguard Worker return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
578*8975f5c5SAndroid Build Coastguard Worker }
579*8975f5c5SAndroid Build Coastguard Worker
getWebGLDepthStencilAttachment() const580*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
581*8975f5c5SAndroid Build Coastguard Worker {
582*8975f5c5SAndroid Build Coastguard Worker return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
583*8975f5c5SAndroid Build Coastguard Worker }
584*8975f5c5SAndroid Build Coastguard Worker
getStencilAttachment() const585*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getStencilAttachment() const
586*8975f5c5SAndroid Build Coastguard Worker {
587*8975f5c5SAndroid Build Coastguard Worker return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
588*8975f5c5SAndroid Build Coastguard Worker }
589*8975f5c5SAndroid Build Coastguard Worker
getWebGLStencilAttachment() const590*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
591*8975f5c5SAndroid Build Coastguard Worker {
592*8975f5c5SAndroid Build Coastguard Worker return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
593*8975f5c5SAndroid Build Coastguard Worker }
594*8975f5c5SAndroid Build Coastguard Worker
getDepthStencilAttachment() const595*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
596*8975f5c5SAndroid Build Coastguard Worker {
597*8975f5c5SAndroid Build Coastguard Worker // A valid depth-stencil attachment has the same resource bound to both the
598*8975f5c5SAndroid Build Coastguard Worker // depth and stencil attachment points.
599*8975f5c5SAndroid Build Coastguard Worker if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
600*8975f5c5SAndroid Build Coastguard Worker mDepthAttachment == mStencilAttachment)
601*8975f5c5SAndroid Build Coastguard Worker {
602*8975f5c5SAndroid Build Coastguard Worker return &mDepthAttachment;
603*8975f5c5SAndroid Build Coastguard Worker }
604*8975f5c5SAndroid Build Coastguard Worker
605*8975f5c5SAndroid Build Coastguard Worker return nullptr;
606*8975f5c5SAndroid Build Coastguard Worker }
607*8975f5c5SAndroid Build Coastguard Worker
getAttachmentExtentsIntersection() const608*8975f5c5SAndroid Build Coastguard Worker const Extents FramebufferState::getAttachmentExtentsIntersection() const
609*8975f5c5SAndroid Build Coastguard Worker {
610*8975f5c5SAndroid Build Coastguard Worker int32_t width = std::numeric_limits<int32_t>::max();
611*8975f5c5SAndroid Build Coastguard Worker int32_t height = std::numeric_limits<int32_t>::max();
612*8975f5c5SAndroid Build Coastguard Worker for (const FramebufferAttachment &attachment : mColorAttachments)
613*8975f5c5SAndroid Build Coastguard Worker {
614*8975f5c5SAndroid Build Coastguard Worker if (attachment.isAttached())
615*8975f5c5SAndroid Build Coastguard Worker {
616*8975f5c5SAndroid Build Coastguard Worker width = std::min(width, attachment.getSize().width);
617*8975f5c5SAndroid Build Coastguard Worker height = std::min(height, attachment.getSize().height);
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker }
620*8975f5c5SAndroid Build Coastguard Worker
621*8975f5c5SAndroid Build Coastguard Worker if (mDepthAttachment.isAttached())
622*8975f5c5SAndroid Build Coastguard Worker {
623*8975f5c5SAndroid Build Coastguard Worker width = std::min(width, mDepthAttachment.getSize().width);
624*8975f5c5SAndroid Build Coastguard Worker height = std::min(height, mDepthAttachment.getSize().height);
625*8975f5c5SAndroid Build Coastguard Worker }
626*8975f5c5SAndroid Build Coastguard Worker
627*8975f5c5SAndroid Build Coastguard Worker if (mStencilAttachment.isAttached())
628*8975f5c5SAndroid Build Coastguard Worker {
629*8975f5c5SAndroid Build Coastguard Worker width = std::min(width, mStencilAttachment.getSize().width);
630*8975f5c5SAndroid Build Coastguard Worker height = std::min(height, mStencilAttachment.getSize().height);
631*8975f5c5SAndroid Build Coastguard Worker }
632*8975f5c5SAndroid Build Coastguard Worker
633*8975f5c5SAndroid Build Coastguard Worker return Extents(width, height, 0);
634*8975f5c5SAndroid Build Coastguard Worker }
635*8975f5c5SAndroid Build Coastguard Worker
attachmentsHaveSameDimensions() const636*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::attachmentsHaveSameDimensions() const
637*8975f5c5SAndroid Build Coastguard Worker {
638*8975f5c5SAndroid Build Coastguard Worker Optional<Extents> attachmentSize;
639*8975f5c5SAndroid Build Coastguard Worker
640*8975f5c5SAndroid Build Coastguard Worker auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
641*8975f5c5SAndroid Build Coastguard Worker if (!attachment.isAttached())
642*8975f5c5SAndroid Build Coastguard Worker {
643*8975f5c5SAndroid Build Coastguard Worker return false;
644*8975f5c5SAndroid Build Coastguard Worker }
645*8975f5c5SAndroid Build Coastguard Worker
646*8975f5c5SAndroid Build Coastguard Worker if (!attachmentSize.valid())
647*8975f5c5SAndroid Build Coastguard Worker {
648*8975f5c5SAndroid Build Coastguard Worker attachmentSize = attachment.getSize();
649*8975f5c5SAndroid Build Coastguard Worker return false;
650*8975f5c5SAndroid Build Coastguard Worker }
651*8975f5c5SAndroid Build Coastguard Worker
652*8975f5c5SAndroid Build Coastguard Worker const auto &prevSize = attachmentSize.value();
653*8975f5c5SAndroid Build Coastguard Worker const auto &curSize = attachment.getSize();
654*8975f5c5SAndroid Build Coastguard Worker return (curSize.width != prevSize.width || curSize.height != prevSize.height);
655*8975f5c5SAndroid Build Coastguard Worker };
656*8975f5c5SAndroid Build Coastguard Worker
657*8975f5c5SAndroid Build Coastguard Worker for (const auto &attachment : mColorAttachments)
658*8975f5c5SAndroid Build Coastguard Worker {
659*8975f5c5SAndroid Build Coastguard Worker if (hasMismatchedSize(attachment))
660*8975f5c5SAndroid Build Coastguard Worker {
661*8975f5c5SAndroid Build Coastguard Worker return false;
662*8975f5c5SAndroid Build Coastguard Worker }
663*8975f5c5SAndroid Build Coastguard Worker }
664*8975f5c5SAndroid Build Coastguard Worker
665*8975f5c5SAndroid Build Coastguard Worker if (hasMismatchedSize(mDepthAttachment))
666*8975f5c5SAndroid Build Coastguard Worker {
667*8975f5c5SAndroid Build Coastguard Worker return false;
668*8975f5c5SAndroid Build Coastguard Worker }
669*8975f5c5SAndroid Build Coastguard Worker
670*8975f5c5SAndroid Build Coastguard Worker return !hasMismatchedSize(mStencilAttachment);
671*8975f5c5SAndroid Build Coastguard Worker }
672*8975f5c5SAndroid Build Coastguard Worker
hasSeparateDepthAndStencilAttachments() const673*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
674*8975f5c5SAndroid Build Coastguard Worker {
675*8975f5c5SAndroid Build Coastguard Worker // if we have both a depth and stencil buffer, they must refer to the same object
676*8975f5c5SAndroid Build Coastguard Worker // since we only support packed_depth_stencil and not separate depth and stencil
677*8975f5c5SAndroid Build Coastguard Worker return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
678*8975f5c5SAndroid Build Coastguard Worker getDepthStencilAttachment() == nullptr);
679*8975f5c5SAndroid Build Coastguard Worker }
680*8975f5c5SAndroid Build Coastguard Worker
getDrawBuffer(size_t drawBufferIdx) const681*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
682*8975f5c5SAndroid Build Coastguard Worker {
683*8975f5c5SAndroid Build Coastguard Worker ASSERT(drawBufferIdx < mDrawBufferStates.size());
684*8975f5c5SAndroid Build Coastguard Worker if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
685*8975f5c5SAndroid Build Coastguard Worker {
686*8975f5c5SAndroid Build Coastguard Worker // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
687*8975f5c5SAndroid Build Coastguard Worker // must be COLOR_ATTACHMENTi or NONE"
688*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
689*8975f5c5SAndroid Build Coastguard Worker (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
690*8975f5c5SAndroid Build Coastguard Worker
691*8975f5c5SAndroid Build Coastguard Worker if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
692*8975f5c5SAndroid Build Coastguard Worker {
693*8975f5c5SAndroid Build Coastguard Worker return getColorAttachment(0);
694*8975f5c5SAndroid Build Coastguard Worker }
695*8975f5c5SAndroid Build Coastguard Worker else
696*8975f5c5SAndroid Build Coastguard Worker {
697*8975f5c5SAndroid Build Coastguard Worker return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
698*8975f5c5SAndroid Build Coastguard Worker }
699*8975f5c5SAndroid Build Coastguard Worker }
700*8975f5c5SAndroid Build Coastguard Worker else
701*8975f5c5SAndroid Build Coastguard Worker {
702*8975f5c5SAndroid Build Coastguard Worker return nullptr;
703*8975f5c5SAndroid Build Coastguard Worker }
704*8975f5c5SAndroid Build Coastguard Worker }
705*8975f5c5SAndroid Build Coastguard Worker
getDrawBufferCount() const706*8975f5c5SAndroid Build Coastguard Worker size_t FramebufferState::getDrawBufferCount() const
707*8975f5c5SAndroid Build Coastguard Worker {
708*8975f5c5SAndroid Build Coastguard Worker return mDrawBufferStates.size();
709*8975f5c5SAndroid Build Coastguard Worker }
710*8975f5c5SAndroid Build Coastguard Worker
colorAttachmentsAreUniqueImages() const711*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::colorAttachmentsAreUniqueImages() const
712*8975f5c5SAndroid Build Coastguard Worker {
713*8975f5c5SAndroid Build Coastguard Worker for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
714*8975f5c5SAndroid Build Coastguard Worker firstAttachmentIdx++)
715*8975f5c5SAndroid Build Coastguard Worker {
716*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
717*8975f5c5SAndroid Build Coastguard Worker if (!firstAttachment.isAttached())
718*8975f5c5SAndroid Build Coastguard Worker {
719*8975f5c5SAndroid Build Coastguard Worker continue;
720*8975f5c5SAndroid Build Coastguard Worker }
721*8975f5c5SAndroid Build Coastguard Worker
722*8975f5c5SAndroid Build Coastguard Worker for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
723*8975f5c5SAndroid Build Coastguard Worker secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
724*8975f5c5SAndroid Build Coastguard Worker {
725*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
726*8975f5c5SAndroid Build Coastguard Worker if (!secondAttachment.isAttached())
727*8975f5c5SAndroid Build Coastguard Worker {
728*8975f5c5SAndroid Build Coastguard Worker continue;
729*8975f5c5SAndroid Build Coastguard Worker }
730*8975f5c5SAndroid Build Coastguard Worker
731*8975f5c5SAndroid Build Coastguard Worker if (firstAttachment == secondAttachment)
732*8975f5c5SAndroid Build Coastguard Worker {
733*8975f5c5SAndroid Build Coastguard Worker return false;
734*8975f5c5SAndroid Build Coastguard Worker }
735*8975f5c5SAndroid Build Coastguard Worker }
736*8975f5c5SAndroid Build Coastguard Worker }
737*8975f5c5SAndroid Build Coastguard Worker
738*8975f5c5SAndroid Build Coastguard Worker return true;
739*8975f5c5SAndroid Build Coastguard Worker }
740*8975f5c5SAndroid Build Coastguard Worker
hasDepth() const741*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::hasDepth() const
742*8975f5c5SAndroid Build Coastguard Worker {
743*8975f5c5SAndroid Build Coastguard Worker return mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0;
744*8975f5c5SAndroid Build Coastguard Worker }
745*8975f5c5SAndroid Build Coastguard Worker
hasStencil() const746*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::hasStencil() const
747*8975f5c5SAndroid Build Coastguard Worker {
748*8975f5c5SAndroid Build Coastguard Worker return mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0;
749*8975f5c5SAndroid Build Coastguard Worker }
750*8975f5c5SAndroid Build Coastguard Worker
getStencilBitCount() const751*8975f5c5SAndroid Build Coastguard Worker GLuint FramebufferState::getStencilBitCount() const
752*8975f5c5SAndroid Build Coastguard Worker {
753*8975f5c5SAndroid Build Coastguard Worker return mStencilAttachment.isAttached() ? mStencilAttachment.getStencilSize() : 0;
754*8975f5c5SAndroid Build Coastguard Worker }
755*8975f5c5SAndroid Build Coastguard Worker
hasExternalTextureAttachment() const756*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::hasExternalTextureAttachment() const
757*8975f5c5SAndroid Build Coastguard Worker {
758*8975f5c5SAndroid Build Coastguard Worker // External textures can only be bound to color attachment 0
759*8975f5c5SAndroid Build Coastguard Worker return mColorAttachments[0].isAttached() && mColorAttachments[0].isExternalTexture();
760*8975f5c5SAndroid Build Coastguard Worker }
761*8975f5c5SAndroid Build Coastguard Worker
hasYUVAttachment() const762*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::hasYUVAttachment() const
763*8975f5c5SAndroid Build Coastguard Worker {
764*8975f5c5SAndroid Build Coastguard Worker // The only attachments that can be YUV are external textures and surfaces, both are attached at
765*8975f5c5SAndroid Build Coastguard Worker // color attachment 0.
766*8975f5c5SAndroid Build Coastguard Worker return mColorAttachments[0].isAttached() && mColorAttachments[0].isYUV();
767*8975f5c5SAndroid Build Coastguard Worker }
768*8975f5c5SAndroid Build Coastguard Worker
isMultiview() const769*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::isMultiview() const
770*8975f5c5SAndroid Build Coastguard Worker {
771*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *attachment = getFirstNonNullAttachment();
772*8975f5c5SAndroid Build Coastguard Worker if (attachment == nullptr)
773*8975f5c5SAndroid Build Coastguard Worker {
774*8975f5c5SAndroid Build Coastguard Worker return false;
775*8975f5c5SAndroid Build Coastguard Worker }
776*8975f5c5SAndroid Build Coastguard Worker return attachment->isMultiview();
777*8975f5c5SAndroid Build Coastguard Worker }
778*8975f5c5SAndroid Build Coastguard Worker
getBaseViewIndex() const779*8975f5c5SAndroid Build Coastguard Worker int FramebufferState::getBaseViewIndex() const
780*8975f5c5SAndroid Build Coastguard Worker {
781*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *attachment = getFirstNonNullAttachment();
782*8975f5c5SAndroid Build Coastguard Worker if (attachment == nullptr)
783*8975f5c5SAndroid Build Coastguard Worker {
784*8975f5c5SAndroid Build Coastguard Worker return GL_NONE;
785*8975f5c5SAndroid Build Coastguard Worker }
786*8975f5c5SAndroid Build Coastguard Worker return attachment->getBaseViewIndex();
787*8975f5c5SAndroid Build Coastguard Worker }
788*8975f5c5SAndroid Build Coastguard Worker
getDimensions() const789*8975f5c5SAndroid Build Coastguard Worker Box FramebufferState::getDimensions() const
790*8975f5c5SAndroid Build Coastguard Worker {
791*8975f5c5SAndroid Build Coastguard Worker Extents extents = getExtents();
792*8975f5c5SAndroid Build Coastguard Worker return Box(0, 0, 0, extents.width, extents.height, extents.depth);
793*8975f5c5SAndroid Build Coastguard Worker }
794*8975f5c5SAndroid Build Coastguard Worker
getExtents() const795*8975f5c5SAndroid Build Coastguard Worker Extents FramebufferState::getExtents() const
796*8975f5c5SAndroid Build Coastguard Worker {
797*8975f5c5SAndroid Build Coastguard Worker // OpenGLES3.0 (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf
798*8975f5c5SAndroid Build Coastguard Worker // section 4.4.4.2) allows attachments have unequal size.
799*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *first = getFirstNonNullAttachment();
800*8975f5c5SAndroid Build Coastguard Worker if (first)
801*8975f5c5SAndroid Build Coastguard Worker {
802*8975f5c5SAndroid Build Coastguard Worker return getAttachmentExtentsIntersection();
803*8975f5c5SAndroid Build Coastguard Worker }
804*8975f5c5SAndroid Build Coastguard Worker return Extents(getDefaultWidth(), getDefaultHeight(), 0);
805*8975f5c5SAndroid Build Coastguard Worker }
806*8975f5c5SAndroid Build Coastguard Worker
isDefault() const807*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::isDefault() const
808*8975f5c5SAndroid Build Coastguard Worker {
809*8975f5c5SAndroid Build Coastguard Worker return mId == Framebuffer::kDefaultDrawFramebufferHandle;
810*8975f5c5SAndroid Build Coastguard Worker }
811*8975f5c5SAndroid Build Coastguard Worker
isBoundAsDrawFramebuffer(const Context * context) const812*8975f5c5SAndroid Build Coastguard Worker bool FramebufferState::isBoundAsDrawFramebuffer(const Context *context) const
813*8975f5c5SAndroid Build Coastguard Worker {
814*8975f5c5SAndroid Build Coastguard Worker return context->getState().getDrawFramebuffer()->id() == mId;
815*8975f5c5SAndroid Build Coastguard Worker }
816*8975f5c5SAndroid Build Coastguard Worker
817*8975f5c5SAndroid Build Coastguard Worker const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
818*8975f5c5SAndroid Build Coastguard Worker
Framebuffer(const Context * context,rx::GLImplFactory * factory)819*8975f5c5SAndroid Build Coastguard Worker Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory)
820*8975f5c5SAndroid Build Coastguard Worker : mState(context->getShareGroup()->generateFramebufferSerial()),
821*8975f5c5SAndroid Build Coastguard Worker mImpl(factory->createFramebuffer(mState)),
822*8975f5c5SAndroid Build Coastguard Worker mCachedStatus(FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES,
823*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteSurfaceless)),
824*8975f5c5SAndroid Build Coastguard Worker mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
825*8975f5c5SAndroid Build Coastguard Worker mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT),
826*8975f5c5SAndroid Build Coastguard Worker mAttachmentChangedAfterEnablingFoveation(false)
827*8975f5c5SAndroid Build Coastguard Worker {
828*8975f5c5SAndroid Build Coastguard Worker mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
829*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
830*8975f5c5SAndroid Build Coastguard Worker }
831*8975f5c5SAndroid Build Coastguard Worker
Framebuffer(const Context * context,rx::GLImplFactory * factory,FramebufferID id)832*8975f5c5SAndroid Build Coastguard Worker Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id)
833*8975f5c5SAndroid Build Coastguard Worker : mState(context->getCaps(), id, context->getShareGroup()->generateFramebufferSerial()),
834*8975f5c5SAndroid Build Coastguard Worker mImpl(factory->createFramebuffer(mState)),
835*8975f5c5SAndroid Build Coastguard Worker mCachedStatus(),
836*8975f5c5SAndroid Build Coastguard Worker mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
837*8975f5c5SAndroid Build Coastguard Worker mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT),
838*8975f5c5SAndroid Build Coastguard Worker mAttachmentChangedAfterEnablingFoveation(false)
839*8975f5c5SAndroid Build Coastguard Worker {
840*8975f5c5SAndroid Build Coastguard Worker ASSERT(mImpl != nullptr);
841*8975f5c5SAndroid Build Coastguard Worker ASSERT(mState.mColorAttachments.size() ==
842*8975f5c5SAndroid Build Coastguard Worker static_cast<size_t>(context->getCaps().maxColorAttachments));
843*8975f5c5SAndroid Build Coastguard Worker
844*8975f5c5SAndroid Build Coastguard Worker for (uint32_t colorIndex = 0;
845*8975f5c5SAndroid Build Coastguard Worker colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
846*8975f5c5SAndroid Build Coastguard Worker {
847*8975f5c5SAndroid Build Coastguard Worker mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
848*8975f5c5SAndroid Build Coastguard Worker }
849*8975f5c5SAndroid Build Coastguard Worker if (context->getClientVersion() >= ES_3_0)
850*8975f5c5SAndroid Build Coastguard Worker {
851*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
852*8975f5c5SAndroid Build Coastguard Worker }
853*8975f5c5SAndroid Build Coastguard Worker }
854*8975f5c5SAndroid Build Coastguard Worker
~Framebuffer()855*8975f5c5SAndroid Build Coastguard Worker Framebuffer::~Framebuffer()
856*8975f5c5SAndroid Build Coastguard Worker {
857*8975f5c5SAndroid Build Coastguard Worker SafeDelete(mImpl);
858*8975f5c5SAndroid Build Coastguard Worker }
859*8975f5c5SAndroid Build Coastguard Worker
onDestroy(const Context * context)860*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::onDestroy(const Context *context)
861*8975f5c5SAndroid Build Coastguard Worker {
862*8975f5c5SAndroid Build Coastguard Worker if (isDefault())
863*8975f5c5SAndroid Build Coastguard Worker {
864*8975f5c5SAndroid Build Coastguard Worker std::ignore = unsetSurfaces(context);
865*8975f5c5SAndroid Build Coastguard Worker }
866*8975f5c5SAndroid Build Coastguard Worker
867*8975f5c5SAndroid Build Coastguard Worker for (auto &attachment : mState.mColorAttachments)
868*8975f5c5SAndroid Build Coastguard Worker {
869*8975f5c5SAndroid Build Coastguard Worker attachment.detach(context, mState.mFramebufferSerial);
870*8975f5c5SAndroid Build Coastguard Worker }
871*8975f5c5SAndroid Build Coastguard Worker mState.mDepthAttachment.detach(context, mState.mFramebufferSerial);
872*8975f5c5SAndroid Build Coastguard Worker mState.mStencilAttachment.detach(context, mState.mFramebufferSerial);
873*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthAttachment.detach(context, mState.mFramebufferSerial);
874*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLStencilAttachment.detach(context, mState.mFramebufferSerial);
875*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthStencilAttachment.detach(context, mState.mFramebufferSerial);
876*8975f5c5SAndroid Build Coastguard Worker
877*8975f5c5SAndroid Build Coastguard Worker if (mPixelLocalStorage)
878*8975f5c5SAndroid Build Coastguard Worker {
879*8975f5c5SAndroid Build Coastguard Worker mPixelLocalStorage->onFramebufferDestroyed(context);
880*8975f5c5SAndroid Build Coastguard Worker }
881*8975f5c5SAndroid Build Coastguard Worker
882*8975f5c5SAndroid Build Coastguard Worker mImpl->destroy(context);
883*8975f5c5SAndroid Build Coastguard Worker }
884*8975f5c5SAndroid Build Coastguard Worker
setSurfaces(const Context * context,egl::Surface * surface,egl::Surface * readSurface)885*8975f5c5SAndroid Build Coastguard Worker egl::Error Framebuffer::setSurfaces(const Context *context,
886*8975f5c5SAndroid Build Coastguard Worker egl::Surface *surface,
887*8975f5c5SAndroid Build Coastguard Worker egl::Surface *readSurface)
888*8975f5c5SAndroid Build Coastguard Worker {
889*8975f5c5SAndroid Build Coastguard Worker // This has to be a default framebuffer.
890*8975f5c5SAndroid Build Coastguard Worker ASSERT(isDefault());
891*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings.size() == 1);
892*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
893*8975f5c5SAndroid Build Coastguard Worker
894*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mColorAttachments[0].isAttached());
895*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mDepthAttachment.isAttached());
896*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mStencilAttachment.isAttached());
897*8975f5c5SAndroid Build Coastguard Worker
898*8975f5c5SAndroid Build Coastguard Worker if (surface)
899*8975f5c5SAndroid Build Coastguard Worker {
900*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
901*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews,
902*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultBaseViewIndex, false,
903*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples);
904*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
905*8975f5c5SAndroid Build Coastguard Worker
906*8975f5c5SAndroid Build Coastguard Worker if (surface->getConfig()->depthSize > 0)
907*8975f5c5SAndroid Build Coastguard Worker {
908*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
909*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews,
910*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultBaseViewIndex, false,
911*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples);
912*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
913*8975f5c5SAndroid Build Coastguard Worker }
914*8975f5c5SAndroid Build Coastguard Worker
915*8975f5c5SAndroid Build Coastguard Worker if (surface->getConfig()->stencilSize > 0)
916*8975f5c5SAndroid Build Coastguard Worker {
917*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
918*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews,
919*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultBaseViewIndex, false,
920*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples);
921*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
922*8975f5c5SAndroid Build Coastguard Worker }
923*8975f5c5SAndroid Build Coastguard Worker
924*8975f5c5SAndroid Build Coastguard Worker mState.mSurfaceTextureOffset = surface->getTextureOffset();
925*8975f5c5SAndroid Build Coastguard Worker
926*8975f5c5SAndroid Build Coastguard Worker // Ensure the backend has a chance to synchronize its content for a new backbuffer.
927*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
928*8975f5c5SAndroid Build Coastguard Worker }
929*8975f5c5SAndroid Build Coastguard Worker
930*8975f5c5SAndroid Build Coastguard Worker setReadSurface(context, readSurface);
931*8975f5c5SAndroid Build Coastguard Worker
932*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
933*8975f5c5SAndroid Build Coastguard Worker
934*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES);
935*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless);
936*8975f5c5SAndroid Build Coastguard Worker if (surface)
937*8975f5c5SAndroid Build Coastguard Worker {
938*8975f5c5SAndroid Build Coastguard Worker mCachedStatus = FramebufferStatus::Complete();
939*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(surface->getImplementation()->attachToFramebuffer(context, this));
940*8975f5c5SAndroid Build Coastguard Worker }
941*8975f5c5SAndroid Build Coastguard Worker
942*8975f5c5SAndroid Build Coastguard Worker return egl::NoError();
943*8975f5c5SAndroid Build Coastguard Worker }
944*8975f5c5SAndroid Build Coastguard Worker
setReadSurface(const Context * context,egl::Surface * readSurface)945*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
946*8975f5c5SAndroid Build Coastguard Worker {
947*8975f5c5SAndroid Build Coastguard Worker // This has to be a default framebuffer.
948*8975f5c5SAndroid Build Coastguard Worker ASSERT(isDefault());
949*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings.size() == 1);
950*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
951*8975f5c5SAndroid Build Coastguard Worker
952*8975f5c5SAndroid Build Coastguard Worker // Read surface is not attached.
953*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mDefaultFramebufferReadAttachment.isAttached());
954*8975f5c5SAndroid Build Coastguard Worker
955*8975f5c5SAndroid Build Coastguard Worker // updateAttachment() without mState.mResourceNeedsInit.set()
956*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultFramebufferReadAttachment.attach(
957*8975f5c5SAndroid Build Coastguard Worker context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
958*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
959*8975f5c5SAndroid Build Coastguard Worker false, FramebufferAttachment::kDefaultRenderToTextureSamples, mState.mFramebufferSerial);
960*8975f5c5SAndroid Build Coastguard Worker
961*8975f5c5SAndroid Build Coastguard Worker if (context->getClientVersion() >= ES_3_0)
962*8975f5c5SAndroid Build Coastguard Worker {
963*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
964*8975f5c5SAndroid Build Coastguard Worker }
965*8975f5c5SAndroid Build Coastguard Worker }
966*8975f5c5SAndroid Build Coastguard Worker
unsetSurfaces(const Context * context)967*8975f5c5SAndroid Build Coastguard Worker egl::Error Framebuffer::unsetSurfaces(const Context *context)
968*8975f5c5SAndroid Build Coastguard Worker {
969*8975f5c5SAndroid Build Coastguard Worker // This has to be a default framebuffer.
970*8975f5c5SAndroid Build Coastguard Worker ASSERT(isDefault());
971*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings.size() == 1);
972*8975f5c5SAndroid Build Coastguard Worker ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0);
973*8975f5c5SAndroid Build Coastguard Worker
974*8975f5c5SAndroid Build Coastguard Worker if (mState.mColorAttachments[0].isAttached())
975*8975f5c5SAndroid Build Coastguard Worker {
976*8975f5c5SAndroid Build Coastguard Worker const egl::Surface *surface = mState.mColorAttachments[0].getSurface();
977*8975f5c5SAndroid Build Coastguard Worker mState.mColorAttachments[0].detach(context, mState.mFramebufferSerial);
978*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
979*8975f5c5SAndroid Build Coastguard Worker
980*8975f5c5SAndroid Build Coastguard Worker if (mState.mDepthAttachment.isAttached())
981*8975f5c5SAndroid Build Coastguard Worker {
982*8975f5c5SAndroid Build Coastguard Worker mState.mDepthAttachment.detach(context, mState.mFramebufferSerial);
983*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
984*8975f5c5SAndroid Build Coastguard Worker }
985*8975f5c5SAndroid Build Coastguard Worker
986*8975f5c5SAndroid Build Coastguard Worker if (mState.mStencilAttachment.isAttached())
987*8975f5c5SAndroid Build Coastguard Worker {
988*8975f5c5SAndroid Build Coastguard Worker mState.mStencilAttachment.detach(context, mState.mFramebufferSerial);
989*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
990*8975f5c5SAndroid Build Coastguard Worker }
991*8975f5c5SAndroid Build Coastguard Worker
992*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(surface->getImplementation()->detachFromFramebuffer(context, this));
993*8975f5c5SAndroid Build Coastguard Worker
994*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_COMPLETE);
995*8975f5c5SAndroid Build Coastguard Worker mCachedStatus = FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES,
996*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteSurfaceless);
997*8975f5c5SAndroid Build Coastguard Worker }
998*8975f5c5SAndroid Build Coastguard Worker else
999*8975f5c5SAndroid Build Coastguard Worker {
1000*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mDepthAttachment.isAttached());
1001*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mState.mStencilAttachment.isAttached());
1002*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES);
1003*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless);
1004*8975f5c5SAndroid Build Coastguard Worker }
1005*8975f5c5SAndroid Build Coastguard Worker
1006*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultFramebufferReadAttachment.detach(context, mState.mFramebufferSerial);
1007*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultFramebufferReadAttachmentInitialized = false;
1008*8975f5c5SAndroid Build Coastguard Worker return egl::NoError();
1009*8975f5c5SAndroid Build Coastguard Worker }
1010*8975f5c5SAndroid Build Coastguard Worker
setLabel(const Context * context,const std::string & label)1011*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::setLabel(const Context *context, const std::string &label)
1012*8975f5c5SAndroid Build Coastguard Worker {
1013*8975f5c5SAndroid Build Coastguard Worker mState.mLabel = label;
1014*8975f5c5SAndroid Build Coastguard Worker
1015*8975f5c5SAndroid Build Coastguard Worker if (mImpl)
1016*8975f5c5SAndroid Build Coastguard Worker {
1017*8975f5c5SAndroid Build Coastguard Worker return mImpl->onLabelUpdate(context);
1018*8975f5c5SAndroid Build Coastguard Worker }
1019*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1020*8975f5c5SAndroid Build Coastguard Worker }
1021*8975f5c5SAndroid Build Coastguard Worker
getLabel() const1022*8975f5c5SAndroid Build Coastguard Worker const std::string &Framebuffer::getLabel() const
1023*8975f5c5SAndroid Build Coastguard Worker {
1024*8975f5c5SAndroid Build Coastguard Worker return mState.mLabel;
1025*8975f5c5SAndroid Build Coastguard Worker }
1026*8975f5c5SAndroid Build Coastguard Worker
detachTexture(Context * context,TextureID textureId)1027*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::detachTexture(Context *context, TextureID textureId)
1028*8975f5c5SAndroid Build Coastguard Worker {
1029*8975f5c5SAndroid Build Coastguard Worker return detachResourceById(context, GL_TEXTURE, textureId.value);
1030*8975f5c5SAndroid Build Coastguard Worker }
1031*8975f5c5SAndroid Build Coastguard Worker
detachRenderbuffer(Context * context,RenderbufferID renderbufferId)1032*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::detachRenderbuffer(Context *context, RenderbufferID renderbufferId)
1033*8975f5c5SAndroid Build Coastguard Worker {
1034*8975f5c5SAndroid Build Coastguard Worker return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
1035*8975f5c5SAndroid Build Coastguard Worker }
1036*8975f5c5SAndroid Build Coastguard Worker
detachResourceById(Context * context,GLenum resourceType,GLuint resourceId)1037*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::detachResourceById(Context *context, GLenum resourceType, GLuint resourceId)
1038*8975f5c5SAndroid Build Coastguard Worker {
1039*8975f5c5SAndroid Build Coastguard Worker bool found = false;
1040*8975f5c5SAndroid Build Coastguard Worker
1041*8975f5c5SAndroid Build Coastguard Worker for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
1042*8975f5c5SAndroid Build Coastguard Worker {
1043*8975f5c5SAndroid Build Coastguard Worker if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
1044*8975f5c5SAndroid Build Coastguard Worker resourceId))
1045*8975f5c5SAndroid Build Coastguard Worker {
1046*8975f5c5SAndroid Build Coastguard Worker found = true;
1047*8975f5c5SAndroid Build Coastguard Worker }
1048*8975f5c5SAndroid Build Coastguard Worker }
1049*8975f5c5SAndroid Build Coastguard Worker
1050*8975f5c5SAndroid Build Coastguard Worker if (context->isWebGL1())
1051*8975f5c5SAndroid Build Coastguard Worker {
1052*8975f5c5SAndroid Build Coastguard Worker const std::array<FramebufferAttachment *, 3> attachments = {
1053*8975f5c5SAndroid Build Coastguard Worker {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
1054*8975f5c5SAndroid Build Coastguard Worker &mState.mWebGLStencilAttachment}};
1055*8975f5c5SAndroid Build Coastguard Worker for (FramebufferAttachment *attachment : attachments)
1056*8975f5c5SAndroid Build Coastguard Worker {
1057*8975f5c5SAndroid Build Coastguard Worker if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
1058*8975f5c5SAndroid Build Coastguard Worker {
1059*8975f5c5SAndroid Build Coastguard Worker found = true;
1060*8975f5c5SAndroid Build Coastguard Worker }
1061*8975f5c5SAndroid Build Coastguard Worker }
1062*8975f5c5SAndroid Build Coastguard Worker }
1063*8975f5c5SAndroid Build Coastguard Worker else
1064*8975f5c5SAndroid Build Coastguard Worker {
1065*8975f5c5SAndroid Build Coastguard Worker if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
1066*8975f5c5SAndroid Build Coastguard Worker {
1067*8975f5c5SAndroid Build Coastguard Worker found = true;
1068*8975f5c5SAndroid Build Coastguard Worker }
1069*8975f5c5SAndroid Build Coastguard Worker if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
1070*8975f5c5SAndroid Build Coastguard Worker {
1071*8975f5c5SAndroid Build Coastguard Worker found = true;
1072*8975f5c5SAndroid Build Coastguard Worker }
1073*8975f5c5SAndroid Build Coastguard Worker }
1074*8975f5c5SAndroid Build Coastguard Worker
1075*8975f5c5SAndroid Build Coastguard Worker return found;
1076*8975f5c5SAndroid Build Coastguard Worker }
1077*8975f5c5SAndroid Build Coastguard Worker
detachMatchingAttachment(Context * context,FramebufferAttachment * attachment,GLenum matchType,GLuint matchId)1078*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::detachMatchingAttachment(Context *context,
1079*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment *attachment,
1080*8975f5c5SAndroid Build Coastguard Worker GLenum matchType,
1081*8975f5c5SAndroid Build Coastguard Worker GLuint matchId)
1082*8975f5c5SAndroid Build Coastguard Worker {
1083*8975f5c5SAndroid Build Coastguard Worker if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
1084*8975f5c5SAndroid Build Coastguard Worker {
1085*8975f5c5SAndroid Build Coastguard Worker const State &contextState = context->getState();
1086*8975f5c5SAndroid Build Coastguard Worker if (contextState.getPixelLocalStorageActivePlanes() != 0 &&
1087*8975f5c5SAndroid Build Coastguard Worker this == contextState.getDrawFramebuffer())
1088*8975f5c5SAndroid Build Coastguard Worker {
1089*8975f5c5SAndroid Build Coastguard Worker // If a (renderbuffer, texture) object is deleted while its image is attached to the
1090*8975f5c5SAndroid Build Coastguard Worker // currently bound draw framebuffer object, and pixel local storage is active, then it
1091*8975f5c5SAndroid Build Coastguard Worker // is as if EndPixelLocalStorageANGLE() had been called with
1092*8975f5c5SAndroid Build Coastguard Worker // <n>=PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE and <storeops> of STORE_OP_STORE_ANGLE.
1093*8975f5c5SAndroid Build Coastguard Worker context->endPixelLocalStorageImplicit();
1094*8975f5c5SAndroid Build Coastguard Worker }
1095*8975f5c5SAndroid Build Coastguard Worker // We go through resetAttachment to make sure that all the required bookkeeping will be done
1096*8975f5c5SAndroid Build Coastguard Worker // such as updating enabled draw buffer state.
1097*8975f5c5SAndroid Build Coastguard Worker resetAttachment(context, attachment->getBinding());
1098*8975f5c5SAndroid Build Coastguard Worker return true;
1099*8975f5c5SAndroid Build Coastguard Worker }
1100*8975f5c5SAndroid Build Coastguard Worker
1101*8975f5c5SAndroid Build Coastguard Worker return false;
1102*8975f5c5SAndroid Build Coastguard Worker }
1103*8975f5c5SAndroid Build Coastguard Worker
getColorAttachment(size_t colorAttachment) const1104*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
1105*8975f5c5SAndroid Build Coastguard Worker {
1106*8975f5c5SAndroid Build Coastguard Worker return mState.getColorAttachment(colorAttachment);
1107*8975f5c5SAndroid Build Coastguard Worker }
1108*8975f5c5SAndroid Build Coastguard Worker
getDepthAttachment() const1109*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getDepthAttachment() const
1110*8975f5c5SAndroid Build Coastguard Worker {
1111*8975f5c5SAndroid Build Coastguard Worker return mState.getDepthAttachment();
1112*8975f5c5SAndroid Build Coastguard Worker }
1113*8975f5c5SAndroid Build Coastguard Worker
getStencilAttachment() const1114*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getStencilAttachment() const
1115*8975f5c5SAndroid Build Coastguard Worker {
1116*8975f5c5SAndroid Build Coastguard Worker return mState.getStencilAttachment();
1117*8975f5c5SAndroid Build Coastguard Worker }
1118*8975f5c5SAndroid Build Coastguard Worker
getDepthStencilAttachment() const1119*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
1120*8975f5c5SAndroid Build Coastguard Worker {
1121*8975f5c5SAndroid Build Coastguard Worker return mState.getDepthStencilAttachment();
1122*8975f5c5SAndroid Build Coastguard Worker }
1123*8975f5c5SAndroid Build Coastguard Worker
getDepthOrStencilAttachment() const1124*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
1125*8975f5c5SAndroid Build Coastguard Worker {
1126*8975f5c5SAndroid Build Coastguard Worker return mState.getDepthOrStencilAttachment();
1127*8975f5c5SAndroid Build Coastguard Worker }
1128*8975f5c5SAndroid Build Coastguard Worker
getStencilOrDepthStencilAttachment() const1129*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
1130*8975f5c5SAndroid Build Coastguard Worker {
1131*8975f5c5SAndroid Build Coastguard Worker return mState.getStencilOrDepthStencilAttachment();
1132*8975f5c5SAndroid Build Coastguard Worker }
1133*8975f5c5SAndroid Build Coastguard Worker
getReadColorAttachment() const1134*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
1135*8975f5c5SAndroid Build Coastguard Worker {
1136*8975f5c5SAndroid Build Coastguard Worker return mState.getReadAttachment();
1137*8975f5c5SAndroid Build Coastguard Worker }
1138*8975f5c5SAndroid Build Coastguard Worker
getReadColorAttachmentType() const1139*8975f5c5SAndroid Build Coastguard Worker GLenum Framebuffer::getReadColorAttachmentType() const
1140*8975f5c5SAndroid Build Coastguard Worker {
1141*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *readAttachment = mState.getReadAttachment();
1142*8975f5c5SAndroid Build Coastguard Worker return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
1143*8975f5c5SAndroid Build Coastguard Worker }
1144*8975f5c5SAndroid Build Coastguard Worker
getFirstColorAttachment() const1145*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
1146*8975f5c5SAndroid Build Coastguard Worker {
1147*8975f5c5SAndroid Build Coastguard Worker return mState.getFirstColorAttachment();
1148*8975f5c5SAndroid Build Coastguard Worker }
1149*8975f5c5SAndroid Build Coastguard Worker
getFirstNonNullAttachment() const1150*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
1151*8975f5c5SAndroid Build Coastguard Worker {
1152*8975f5c5SAndroid Build Coastguard Worker return mState.getFirstNonNullAttachment();
1153*8975f5c5SAndroid Build Coastguard Worker }
1154*8975f5c5SAndroid Build Coastguard Worker
getAttachment(const Context * context,GLenum attachment) const1155*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
1156*8975f5c5SAndroid Build Coastguard Worker GLenum attachment) const
1157*8975f5c5SAndroid Build Coastguard Worker {
1158*8975f5c5SAndroid Build Coastguard Worker return mState.getAttachment(context, attachment);
1159*8975f5c5SAndroid Build Coastguard Worker }
1160*8975f5c5SAndroid Build Coastguard Worker
getDrawbufferStateCount() const1161*8975f5c5SAndroid Build Coastguard Worker size_t Framebuffer::getDrawbufferStateCount() const
1162*8975f5c5SAndroid Build Coastguard Worker {
1163*8975f5c5SAndroid Build Coastguard Worker return mState.mDrawBufferStates.size();
1164*8975f5c5SAndroid Build Coastguard Worker }
1165*8975f5c5SAndroid Build Coastguard Worker
getDrawBufferState(size_t drawBuffer) const1166*8975f5c5SAndroid Build Coastguard Worker GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
1167*8975f5c5SAndroid Build Coastguard Worker {
1168*8975f5c5SAndroid Build Coastguard Worker ASSERT(drawBuffer < mState.mDrawBufferStates.size());
1169*8975f5c5SAndroid Build Coastguard Worker return mState.mDrawBufferStates[drawBuffer];
1170*8975f5c5SAndroid Build Coastguard Worker }
1171*8975f5c5SAndroid Build Coastguard Worker
getDrawBufferStates() const1172*8975f5c5SAndroid Build Coastguard Worker const DrawBuffersVector<GLenum> &Framebuffer::getDrawBufferStates() const
1173*8975f5c5SAndroid Build Coastguard Worker {
1174*8975f5c5SAndroid Build Coastguard Worker return mState.getDrawBufferStates();
1175*8975f5c5SAndroid Build Coastguard Worker }
1176*8975f5c5SAndroid Build Coastguard Worker
setDrawBuffers(size_t count,const GLenum * buffers)1177*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
1178*8975f5c5SAndroid Build Coastguard Worker {
1179*8975f5c5SAndroid Build Coastguard Worker auto &drawStates = mState.mDrawBufferStates;
1180*8975f5c5SAndroid Build Coastguard Worker
1181*8975f5c5SAndroid Build Coastguard Worker ASSERT(count <= drawStates.size());
1182*8975f5c5SAndroid Build Coastguard Worker std::copy(buffers, buffers + count, drawStates.begin());
1183*8975f5c5SAndroid Build Coastguard Worker std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
1184*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
1185*8975f5c5SAndroid Build Coastguard Worker
1186*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledDrawBuffers.reset();
1187*8975f5c5SAndroid Build Coastguard Worker mState.mDrawBufferTypeMask.reset();
1188*8975f5c5SAndroid Build Coastguard Worker
1189*8975f5c5SAndroid Build Coastguard Worker for (size_t index = 0; index < count; ++index)
1190*8975f5c5SAndroid Build Coastguard Worker {
1191*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
1192*8975f5c5SAndroid Build Coastguard Worker
1193*8975f5c5SAndroid Build Coastguard Worker if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
1194*8975f5c5SAndroid Build Coastguard Worker {
1195*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledDrawBuffers.set(index);
1196*8975f5c5SAndroid Build Coastguard Worker }
1197*8975f5c5SAndroid Build Coastguard Worker }
1198*8975f5c5SAndroid Build Coastguard Worker }
1199*8975f5c5SAndroid Build Coastguard Worker
getDrawBuffer(size_t drawBuffer) const1200*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
1201*8975f5c5SAndroid Build Coastguard Worker {
1202*8975f5c5SAndroid Build Coastguard Worker return mState.getDrawBuffer(drawBuffer);
1203*8975f5c5SAndroid Build Coastguard Worker }
1204*8975f5c5SAndroid Build Coastguard Worker
getDrawbufferWriteType(size_t drawBuffer) const1205*8975f5c5SAndroid Build Coastguard Worker ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
1206*8975f5c5SAndroid Build Coastguard Worker {
1207*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
1208*8975f5c5SAndroid Build Coastguard Worker if (attachment == nullptr)
1209*8975f5c5SAndroid Build Coastguard Worker {
1210*8975f5c5SAndroid Build Coastguard Worker return ComponentType::NoType;
1211*8975f5c5SAndroid Build Coastguard Worker }
1212*8975f5c5SAndroid Build Coastguard Worker
1213*8975f5c5SAndroid Build Coastguard Worker return GetAttachmentComponentType(attachment->getFormat().info->componentType);
1214*8975f5c5SAndroid Build Coastguard Worker }
1215*8975f5c5SAndroid Build Coastguard Worker
getDrawBufferTypeMask() const1216*8975f5c5SAndroid Build Coastguard Worker ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
1217*8975f5c5SAndroid Build Coastguard Worker {
1218*8975f5c5SAndroid Build Coastguard Worker return mState.mDrawBufferTypeMask;
1219*8975f5c5SAndroid Build Coastguard Worker }
1220*8975f5c5SAndroid Build Coastguard Worker
getDrawBufferMask() const1221*8975f5c5SAndroid Build Coastguard Worker DrawBufferMask Framebuffer::getDrawBufferMask() const
1222*8975f5c5SAndroid Build Coastguard Worker {
1223*8975f5c5SAndroid Build Coastguard Worker return mState.mEnabledDrawBuffers;
1224*8975f5c5SAndroid Build Coastguard Worker }
1225*8975f5c5SAndroid Build Coastguard Worker
hasEnabledDrawBuffer() const1226*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::hasEnabledDrawBuffer() const
1227*8975f5c5SAndroid Build Coastguard Worker {
1228*8975f5c5SAndroid Build Coastguard Worker for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
1229*8975f5c5SAndroid Build Coastguard Worker {
1230*8975f5c5SAndroid Build Coastguard Worker if (getDrawBuffer(drawbufferIdx) != nullptr)
1231*8975f5c5SAndroid Build Coastguard Worker {
1232*8975f5c5SAndroid Build Coastguard Worker return true;
1233*8975f5c5SAndroid Build Coastguard Worker }
1234*8975f5c5SAndroid Build Coastguard Worker }
1235*8975f5c5SAndroid Build Coastguard Worker
1236*8975f5c5SAndroid Build Coastguard Worker return false;
1237*8975f5c5SAndroid Build Coastguard Worker }
1238*8975f5c5SAndroid Build Coastguard Worker
getReadBufferState() const1239*8975f5c5SAndroid Build Coastguard Worker GLenum Framebuffer::getReadBufferState() const
1240*8975f5c5SAndroid Build Coastguard Worker {
1241*8975f5c5SAndroid Build Coastguard Worker return mState.mReadBufferState;
1242*8975f5c5SAndroid Build Coastguard Worker }
1243*8975f5c5SAndroid Build Coastguard Worker
setReadBuffer(GLenum buffer)1244*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setReadBuffer(GLenum buffer)
1245*8975f5c5SAndroid Build Coastguard Worker {
1246*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
1247*8975f5c5SAndroid Build Coastguard Worker (buffer >= GL_COLOR_ATTACHMENT0 &&
1248*8975f5c5SAndroid Build Coastguard Worker (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
1249*8975f5c5SAndroid Build Coastguard Worker if (mState.mReadBufferState != buffer)
1250*8975f5c5SAndroid Build Coastguard Worker {
1251*8975f5c5SAndroid Build Coastguard Worker mState.mReadBufferState = buffer;
1252*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
1253*8975f5c5SAndroid Build Coastguard Worker }
1254*8975f5c5SAndroid Build Coastguard Worker }
1255*8975f5c5SAndroid Build Coastguard Worker
invalidateCompletenessCache()1256*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::invalidateCompletenessCache()
1257*8975f5c5SAndroid Build Coastguard Worker {
1258*8975f5c5SAndroid Build Coastguard Worker if (!isDefault())
1259*8975f5c5SAndroid Build Coastguard Worker {
1260*8975f5c5SAndroid Build Coastguard Worker mCachedStatus.reset();
1261*8975f5c5SAndroid Build Coastguard Worker }
1262*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1263*8975f5c5SAndroid Build Coastguard Worker }
1264*8975f5c5SAndroid Build Coastguard Worker
checkStatusImpl(const Context * context) const1265*8975f5c5SAndroid Build Coastguard Worker const FramebufferStatus &Framebuffer::checkStatusImpl(const Context *context) const
1266*8975f5c5SAndroid Build Coastguard Worker {
1267*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isDefault());
1268*8975f5c5SAndroid Build Coastguard Worker ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
1269*8975f5c5SAndroid Build Coastguard Worker
1270*8975f5c5SAndroid Build Coastguard Worker mCachedStatus = checkStatusWithGLFrontEnd(context);
1271*8975f5c5SAndroid Build Coastguard Worker
1272*8975f5c5SAndroid Build Coastguard Worker if (mCachedStatus.value().isComplete())
1273*8975f5c5SAndroid Build Coastguard Worker {
1274*8975f5c5SAndroid Build Coastguard Worker // We can skip syncState on several back-ends.
1275*8975f5c5SAndroid Build Coastguard Worker if (mImpl->shouldSyncStateBeforeCheckStatus())
1276*8975f5c5SAndroid Build Coastguard Worker {
1277*8975f5c5SAndroid Build Coastguard Worker {
1278*8975f5c5SAndroid Build Coastguard Worker angle::Result err = syncAllDrawAttachmentState(context, Command::Other);
1279*8975f5c5SAndroid Build Coastguard Worker if (err != angle::Result::Continue)
1280*8975f5c5SAndroid Build Coastguard Worker {
1281*8975f5c5SAndroid Build Coastguard Worker mCachedStatus =
1282*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus::Incomplete(0, err::kFramebufferIncompleteInternalError);
1283*8975f5c5SAndroid Build Coastguard Worker return mCachedStatus.value();
1284*8975f5c5SAndroid Build Coastguard Worker }
1285*8975f5c5SAndroid Build Coastguard Worker }
1286*8975f5c5SAndroid Build Coastguard Worker
1287*8975f5c5SAndroid Build Coastguard Worker {
1288*8975f5c5SAndroid Build Coastguard Worker // This binding is not totally correct. It is ok because the parameter isn't used in
1289*8975f5c5SAndroid Build Coastguard Worker // the GL back-end and the GL back-end is the only user of
1290*8975f5c5SAndroid Build Coastguard Worker // syncStateBeforeCheckStatus.
1291*8975f5c5SAndroid Build Coastguard Worker angle::Result err = syncState(context, GL_FRAMEBUFFER, Command::Other);
1292*8975f5c5SAndroid Build Coastguard Worker if (err != angle::Result::Continue)
1293*8975f5c5SAndroid Build Coastguard Worker {
1294*8975f5c5SAndroid Build Coastguard Worker mCachedStatus =
1295*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus::Incomplete(0, err::kFramebufferIncompleteInternalError);
1296*8975f5c5SAndroid Build Coastguard Worker return mCachedStatus.value();
1297*8975f5c5SAndroid Build Coastguard Worker }
1298*8975f5c5SAndroid Build Coastguard Worker }
1299*8975f5c5SAndroid Build Coastguard Worker }
1300*8975f5c5SAndroid Build Coastguard Worker
1301*8975f5c5SAndroid Build Coastguard Worker mCachedStatus = mImpl->checkStatus(context);
1302*8975f5c5SAndroid Build Coastguard Worker }
1303*8975f5c5SAndroid Build Coastguard Worker
1304*8975f5c5SAndroid Build Coastguard Worker return mCachedStatus.value();
1305*8975f5c5SAndroid Build Coastguard Worker }
1306*8975f5c5SAndroid Build Coastguard Worker
checkStatusWithGLFrontEnd(const Context * context) const1307*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) const
1308*8975f5c5SAndroid Build Coastguard Worker {
1309*8975f5c5SAndroid Build Coastguard Worker const State &state = context->getState();
1310*8975f5c5SAndroid Build Coastguard Worker
1311*8975f5c5SAndroid Build Coastguard Worker ASSERT(!isDefault());
1312*8975f5c5SAndroid Build Coastguard Worker
1313*8975f5c5SAndroid Build Coastguard Worker bool hasAttachments = false;
1314*8975f5c5SAndroid Build Coastguard Worker Optional<unsigned int> colorbufferSize;
1315*8975f5c5SAndroid Build Coastguard Worker Optional<int> samples;
1316*8975f5c5SAndroid Build Coastguard Worker Optional<bool> fixedSampleLocations;
1317*8975f5c5SAndroid Build Coastguard Worker bool hasRenderbuffer = false;
1318*8975f5c5SAndroid Build Coastguard Worker Optional<int> renderToTextureSamples;
1319*8975f5c5SAndroid Build Coastguard Worker uint32_t foveatedRenderingAttachmentCount = 0;
1320*8975f5c5SAndroid Build Coastguard Worker
1321*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1322*8975f5c5SAndroid Build Coastguard Worker
1323*8975f5c5SAndroid Build Coastguard Worker Optional<bool> isLayered;
1324*8975f5c5SAndroid Build Coastguard Worker Optional<TextureType> colorAttachmentsTextureType;
1325*8975f5c5SAndroid Build Coastguard Worker
1326*8975f5c5SAndroid Build Coastguard Worker for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
1327*8975f5c5SAndroid Build Coastguard Worker {
1328*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.isAttached())
1329*8975f5c5SAndroid Build Coastguard Worker {
1330*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentCompleteness =
1331*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentCompleteness(context, colorAttachment);
1332*8975f5c5SAndroid Build Coastguard Worker if (!attachmentCompleteness.isComplete())
1333*8975f5c5SAndroid Build Coastguard Worker {
1334*8975f5c5SAndroid Build Coastguard Worker return attachmentCompleteness;
1335*8975f5c5SAndroid Build Coastguard Worker }
1336*8975f5c5SAndroid Build Coastguard Worker
1337*8975f5c5SAndroid Build Coastguard Worker const InternalFormat &format = *colorAttachment.getFormat().info;
1338*8975f5c5SAndroid Build Coastguard Worker if (format.depthBits > 0 || format.stencilBits > 0)
1339*8975f5c5SAndroid Build Coastguard Worker {
1340*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1341*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1342*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteDepthStencilInColorBuffer);
1343*8975f5c5SAndroid Build Coastguard Worker }
1344*8975f5c5SAndroid Build Coastguard Worker
1345*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentSampleCompleteness =
1346*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1347*8975f5c5SAndroid Build Coastguard Worker &fixedSampleLocations, &renderToTextureSamples);
1348*8975f5c5SAndroid Build Coastguard Worker if (!attachmentSampleCompleteness.isComplete())
1349*8975f5c5SAndroid Build Coastguard Worker {
1350*8975f5c5SAndroid Build Coastguard Worker return attachmentSampleCompleteness;
1351*8975f5c5SAndroid Build Coastguard Worker }
1352*8975f5c5SAndroid Build Coastguard Worker
1353*8975f5c5SAndroid Build Coastguard Worker // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1354*8975f5c5SAndroid Build Coastguard Worker // in GLES 3.0, there is no such restriction
1355*8975f5c5SAndroid Build Coastguard Worker if (state.getClientMajorVersion() < 3)
1356*8975f5c5SAndroid Build Coastguard Worker {
1357*8975f5c5SAndroid Build Coastguard Worker if (colorbufferSize.valid())
1358*8975f5c5SAndroid Build Coastguard Worker {
1359*8975f5c5SAndroid Build Coastguard Worker if (format.pixelBytes != colorbufferSize.value())
1360*8975f5c5SAndroid Build Coastguard Worker {
1361*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1362*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED,
1363*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentInconsistantBitPlanes);
1364*8975f5c5SAndroid Build Coastguard Worker }
1365*8975f5c5SAndroid Build Coastguard Worker }
1366*8975f5c5SAndroid Build Coastguard Worker else
1367*8975f5c5SAndroid Build Coastguard Worker {
1368*8975f5c5SAndroid Build Coastguard Worker colorbufferSize = format.pixelBytes;
1369*8975f5c5SAndroid Build Coastguard Worker }
1370*8975f5c5SAndroid Build Coastguard Worker }
1371*8975f5c5SAndroid Build Coastguard Worker
1372*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentMultiviewCompleteness =
1373*8975f5c5SAndroid Build Coastguard Worker CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment);
1374*8975f5c5SAndroid Build Coastguard Worker if (!attachmentMultiviewCompleteness.isComplete())
1375*8975f5c5SAndroid Build Coastguard Worker {
1376*8975f5c5SAndroid Build Coastguard Worker return attachmentMultiviewCompleteness;
1377*8975f5c5SAndroid Build Coastguard Worker }
1378*8975f5c5SAndroid Build Coastguard Worker
1379*8975f5c5SAndroid Build Coastguard Worker hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1380*8975f5c5SAndroid Build Coastguard Worker
1381*8975f5c5SAndroid Build Coastguard Worker if (!hasAttachments)
1382*8975f5c5SAndroid Build Coastguard Worker {
1383*8975f5c5SAndroid Build Coastguard Worker isLayered = colorAttachment.isLayered();
1384*8975f5c5SAndroid Build Coastguard Worker if (isLayered.value())
1385*8975f5c5SAndroid Build Coastguard Worker {
1386*8975f5c5SAndroid Build Coastguard Worker colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1387*8975f5c5SAndroid Build Coastguard Worker }
1388*8975f5c5SAndroid Build Coastguard Worker hasAttachments = true;
1389*8975f5c5SAndroid Build Coastguard Worker }
1390*8975f5c5SAndroid Build Coastguard Worker else
1391*8975f5c5SAndroid Build Coastguard Worker {
1392*8975f5c5SAndroid Build Coastguard Worker // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1393*8975f5c5SAndroid Build Coastguard Worker // If any framebuffer attachment is layered, all populated attachments
1394*8975f5c5SAndroid Build Coastguard Worker // must be layered. Additionally, all populated color attachments must
1395*8975f5c5SAndroid Build Coastguard Worker // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1396*8975f5c5SAndroid Build Coastguard Worker ASSERT(isLayered.valid());
1397*8975f5c5SAndroid Build Coastguard Worker if (isLayered.value() != colorAttachment.isLayered())
1398*8975f5c5SAndroid Build Coastguard Worker {
1399*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1400*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
1401*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMismatchedLayeredAttachments);
1402*8975f5c5SAndroid Build Coastguard Worker }
1403*8975f5c5SAndroid Build Coastguard Worker else if (isLayered.value())
1404*8975f5c5SAndroid Build Coastguard Worker {
1405*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorAttachmentsTextureType.valid());
1406*8975f5c5SAndroid Build Coastguard Worker if (colorAttachmentsTextureType.value() !=
1407*8975f5c5SAndroid Build Coastguard Worker colorAttachment.getTextureImageIndex().getType())
1408*8975f5c5SAndroid Build Coastguard Worker {
1409*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1410*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
1411*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMismatchedLayeredTexturetypes);
1412*8975f5c5SAndroid Build Coastguard Worker }
1413*8975f5c5SAndroid Build Coastguard Worker }
1414*8975f5c5SAndroid Build Coastguard Worker }
1415*8975f5c5SAndroid Build Coastguard Worker if (colorAttachment.hasFoveatedRendering())
1416*8975f5c5SAndroid Build Coastguard Worker {
1417*8975f5c5SAndroid Build Coastguard Worker foveatedRenderingAttachmentCount++;
1418*8975f5c5SAndroid Build Coastguard Worker }
1419*8975f5c5SAndroid Build Coastguard Worker }
1420*8975f5c5SAndroid Build Coastguard Worker }
1421*8975f5c5SAndroid Build Coastguard Worker
1422*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
1423*8975f5c5SAndroid Build Coastguard Worker if (depthAttachment.isAttached())
1424*8975f5c5SAndroid Build Coastguard Worker {
1425*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentCompleteness =
1426*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentCompleteness(context, depthAttachment);
1427*8975f5c5SAndroid Build Coastguard Worker if (!attachmentCompleteness.isComplete())
1428*8975f5c5SAndroid Build Coastguard Worker {
1429*8975f5c5SAndroid Build Coastguard Worker return attachmentCompleteness;
1430*8975f5c5SAndroid Build Coastguard Worker }
1431*8975f5c5SAndroid Build Coastguard Worker
1432*8975f5c5SAndroid Build Coastguard Worker const InternalFormat &format = *depthAttachment.getFormat().info;
1433*8975f5c5SAndroid Build Coastguard Worker if (format.depthBits == 0)
1434*8975f5c5SAndroid Build Coastguard Worker {
1435*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1436*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1437*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentNoDepthBitsInDepthBuffer);
1438*8975f5c5SAndroid Build Coastguard Worker }
1439*8975f5c5SAndroid Build Coastguard Worker
1440*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentSampleCompleteness =
1441*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1442*8975f5c5SAndroid Build Coastguard Worker &fixedSampleLocations, &renderToTextureSamples);
1443*8975f5c5SAndroid Build Coastguard Worker if (!attachmentSampleCompleteness.isComplete())
1444*8975f5c5SAndroid Build Coastguard Worker {
1445*8975f5c5SAndroid Build Coastguard Worker return attachmentSampleCompleteness;
1446*8975f5c5SAndroid Build Coastguard Worker }
1447*8975f5c5SAndroid Build Coastguard Worker
1448*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentMultiviewCompleteness =
1449*8975f5c5SAndroid Build Coastguard Worker CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment);
1450*8975f5c5SAndroid Build Coastguard Worker if (!attachmentMultiviewCompleteness.isComplete())
1451*8975f5c5SAndroid Build Coastguard Worker {
1452*8975f5c5SAndroid Build Coastguard Worker return attachmentMultiviewCompleteness;
1453*8975f5c5SAndroid Build Coastguard Worker }
1454*8975f5c5SAndroid Build Coastguard Worker
1455*8975f5c5SAndroid Build Coastguard Worker hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1456*8975f5c5SAndroid Build Coastguard Worker
1457*8975f5c5SAndroid Build Coastguard Worker if (!hasAttachments)
1458*8975f5c5SAndroid Build Coastguard Worker {
1459*8975f5c5SAndroid Build Coastguard Worker isLayered = depthAttachment.isLayered();
1460*8975f5c5SAndroid Build Coastguard Worker hasAttachments = true;
1461*8975f5c5SAndroid Build Coastguard Worker }
1462*8975f5c5SAndroid Build Coastguard Worker else
1463*8975f5c5SAndroid Build Coastguard Worker {
1464*8975f5c5SAndroid Build Coastguard Worker // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1465*8975f5c5SAndroid Build Coastguard Worker // If any framebuffer attachment is layered, all populated attachments
1466*8975f5c5SAndroid Build Coastguard Worker // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1467*8975f5c5SAndroid Build Coastguard Worker ASSERT(isLayered.valid());
1468*8975f5c5SAndroid Build Coastguard Worker if (isLayered.value() != depthAttachment.isLayered())
1469*8975f5c5SAndroid Build Coastguard Worker {
1470*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1471*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
1472*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMismatchedLayeredAttachments);
1473*8975f5c5SAndroid Build Coastguard Worker }
1474*8975f5c5SAndroid Build Coastguard Worker }
1475*8975f5c5SAndroid Build Coastguard Worker }
1476*8975f5c5SAndroid Build Coastguard Worker
1477*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
1478*8975f5c5SAndroid Build Coastguard Worker if (stencilAttachment.isAttached())
1479*8975f5c5SAndroid Build Coastguard Worker {
1480*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentCompleteness =
1481*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentCompleteness(context, stencilAttachment);
1482*8975f5c5SAndroid Build Coastguard Worker if (!attachmentCompleteness.isComplete())
1483*8975f5c5SAndroid Build Coastguard Worker {
1484*8975f5c5SAndroid Build Coastguard Worker return attachmentCompleteness;
1485*8975f5c5SAndroid Build Coastguard Worker }
1486*8975f5c5SAndroid Build Coastguard Worker
1487*8975f5c5SAndroid Build Coastguard Worker const InternalFormat &format = *stencilAttachment.getFormat().info;
1488*8975f5c5SAndroid Build Coastguard Worker if (format.stencilBits == 0)
1489*8975f5c5SAndroid Build Coastguard Worker {
1490*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1491*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1492*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentNoStencilBitsInStencilBuffer);
1493*8975f5c5SAndroid Build Coastguard Worker }
1494*8975f5c5SAndroid Build Coastguard Worker
1495*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentSampleCompleteness =
1496*8975f5c5SAndroid Build Coastguard Worker CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1497*8975f5c5SAndroid Build Coastguard Worker &fixedSampleLocations, &renderToTextureSamples);
1498*8975f5c5SAndroid Build Coastguard Worker if (!attachmentSampleCompleteness.isComplete())
1499*8975f5c5SAndroid Build Coastguard Worker {
1500*8975f5c5SAndroid Build Coastguard Worker return attachmentSampleCompleteness;
1501*8975f5c5SAndroid Build Coastguard Worker }
1502*8975f5c5SAndroid Build Coastguard Worker
1503*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentMultiviewCompleteness =
1504*8975f5c5SAndroid Build Coastguard Worker CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment);
1505*8975f5c5SAndroid Build Coastguard Worker if (!attachmentMultiviewCompleteness.isComplete())
1506*8975f5c5SAndroid Build Coastguard Worker {
1507*8975f5c5SAndroid Build Coastguard Worker return attachmentMultiviewCompleteness;
1508*8975f5c5SAndroid Build Coastguard Worker }
1509*8975f5c5SAndroid Build Coastguard Worker
1510*8975f5c5SAndroid Build Coastguard Worker hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1511*8975f5c5SAndroid Build Coastguard Worker
1512*8975f5c5SAndroid Build Coastguard Worker if (!hasAttachments)
1513*8975f5c5SAndroid Build Coastguard Worker {
1514*8975f5c5SAndroid Build Coastguard Worker hasAttachments = true;
1515*8975f5c5SAndroid Build Coastguard Worker }
1516*8975f5c5SAndroid Build Coastguard Worker else
1517*8975f5c5SAndroid Build Coastguard Worker {
1518*8975f5c5SAndroid Build Coastguard Worker // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1519*8975f5c5SAndroid Build Coastguard Worker // If any framebuffer attachment is layered, all populated attachments
1520*8975f5c5SAndroid Build Coastguard Worker // must be layered.
1521*8975f5c5SAndroid Build Coastguard Worker // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1522*8975f5c5SAndroid Build Coastguard Worker ASSERT(isLayered.valid());
1523*8975f5c5SAndroid Build Coastguard Worker if (isLayered.value() != stencilAttachment.isLayered())
1524*8975f5c5SAndroid Build Coastguard Worker {
1525*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1526*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT,
1527*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMismatchedLayeredAttachments);
1528*8975f5c5SAndroid Build Coastguard Worker }
1529*8975f5c5SAndroid Build Coastguard Worker }
1530*8975f5c5SAndroid Build Coastguard Worker }
1531*8975f5c5SAndroid Build Coastguard Worker
1532*8975f5c5SAndroid Build Coastguard Worker // Starting from ES 3.0 stencil and depth, if present, should be the same image
1533*8975f5c5SAndroid Build Coastguard Worker if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1534*8975f5c5SAndroid Build Coastguard Worker stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1535*8975f5c5SAndroid Build Coastguard Worker {
1536*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1537*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED,
1538*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteDepthAndStencilBuffersNotTheSame);
1539*8975f5c5SAndroid Build Coastguard Worker }
1540*8975f5c5SAndroid Build Coastguard Worker
1541*8975f5c5SAndroid Build Coastguard Worker // [QCOM_texture_foveated] - Additions to Chapter 9.4 (Framebuffer Completeness) -
1542*8975f5c5SAndroid Build Coastguard Worker // - More than one color attachment is foveated.
1543*8975f5c5SAndroid Build Coastguard Worker // { FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM }
1544*8975f5c5SAndroid Build Coastguard Worker // - Depth or stencil attachments are foveated textures.
1545*8975f5c5SAndroid Build Coastguard Worker // { FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM }
1546*8975f5c5SAndroid Build Coastguard Worker // - The framebuffer has been configured for foveation via QCOM_framebuffer_foveated
1547*8975f5c5SAndroid Build Coastguard Worker // and any color attachment is a foveated texture.
1548*8975f5c5SAndroid Build Coastguard Worker // { FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM }
1549*8975f5c5SAndroid Build Coastguard Worker const bool multipleAttachmentsAreFoveated = foveatedRenderingAttachmentCount > 1;
1550*8975f5c5SAndroid Build Coastguard Worker const bool depthAttachmentIsFoveated =
1551*8975f5c5SAndroid Build Coastguard Worker depthAttachment.isAttached() && depthAttachment.hasFoveatedRendering();
1552*8975f5c5SAndroid Build Coastguard Worker const bool stencilAttachmentIsFoveated =
1553*8975f5c5SAndroid Build Coastguard Worker stencilAttachment.isAttached() && stencilAttachment.hasFoveatedRendering();
1554*8975f5c5SAndroid Build Coastguard Worker const bool framebufferAndAttachmentsAreFoveated =
1555*8975f5c5SAndroid Build Coastguard Worker isFoveationEnabled() && foveatedRenderingAttachmentCount > 0;
1556*8975f5c5SAndroid Build Coastguard Worker if (multipleAttachmentsAreFoveated || depthAttachmentIsFoveated ||
1557*8975f5c5SAndroid Build Coastguard Worker stencilAttachmentIsFoveated || framebufferAndAttachmentsAreFoveated)
1558*8975f5c5SAndroid Build Coastguard Worker {
1559*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM,
1560*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteFoveatedRendering);
1561*8975f5c5SAndroid Build Coastguard Worker }
1562*8975f5c5SAndroid Build Coastguard Worker
1563*8975f5c5SAndroid Build Coastguard Worker // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1564*8975f5c5SAndroid Build Coastguard Worker if (state.isWebGL1())
1565*8975f5c5SAndroid Build Coastguard Worker {
1566*8975f5c5SAndroid Build Coastguard Worker if (!mState.mWebGLDepthStencilConsistent)
1567*8975f5c5SAndroid Build Coastguard Worker {
1568*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1569*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_UNSUPPORTED,
1570*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteWebGLDepthStencilInconsistant);
1571*8975f5c5SAndroid Build Coastguard Worker }
1572*8975f5c5SAndroid Build Coastguard Worker
1573*8975f5c5SAndroid Build Coastguard Worker if (mState.mWebGLDepthStencilAttachment.isAttached())
1574*8975f5c5SAndroid Build Coastguard Worker {
1575*8975f5c5SAndroid Build Coastguard Worker if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1576*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1577*8975f5c5SAndroid Build Coastguard Worker {
1578*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1579*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1580*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentWebGLDepthStencilNoDepthOrStencilBits);
1581*8975f5c5SAndroid Build Coastguard Worker }
1582*8975f5c5SAndroid Build Coastguard Worker
1583*8975f5c5SAndroid Build Coastguard Worker FramebufferStatus attachmentMultiviewCompleteness =
1584*8975f5c5SAndroid Build Coastguard Worker CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1585*8975f5c5SAndroid Build Coastguard Worker &mState.mWebGLDepthStencilAttachment);
1586*8975f5c5SAndroid Build Coastguard Worker if (!attachmentMultiviewCompleteness.isComplete())
1587*8975f5c5SAndroid Build Coastguard Worker {
1588*8975f5c5SAndroid Build Coastguard Worker return attachmentMultiviewCompleteness;
1589*8975f5c5SAndroid Build Coastguard Worker }
1590*8975f5c5SAndroid Build Coastguard Worker }
1591*8975f5c5SAndroid Build Coastguard Worker else if (mState.mStencilAttachment.isAttached() &&
1592*8975f5c5SAndroid Build Coastguard Worker mState.mStencilAttachment.getDepthSize() > 0)
1593*8975f5c5SAndroid Build Coastguard Worker {
1594*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1595*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1596*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentWebGLStencilBufferHasDepthBits);
1597*8975f5c5SAndroid Build Coastguard Worker }
1598*8975f5c5SAndroid Build Coastguard Worker else if (mState.mDepthAttachment.isAttached() &&
1599*8975f5c5SAndroid Build Coastguard Worker mState.mDepthAttachment.getStencilSize() > 0)
1600*8975f5c5SAndroid Build Coastguard Worker {
1601*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1602*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
1603*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentWebGLDepthBufferHasStencilBits);
1604*8975f5c5SAndroid Build Coastguard Worker }
1605*8975f5c5SAndroid Build Coastguard Worker }
1606*8975f5c5SAndroid Build Coastguard Worker
1607*8975f5c5SAndroid Build Coastguard Worker // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1608*8975f5c5SAndroid Build Coastguard Worker // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1609*8975f5c5SAndroid Build Coastguard Worker // is zero, the framebuffer is considered incomplete.
1610*8975f5c5SAndroid Build Coastguard Worker GLint defaultWidth = mState.getDefaultWidth();
1611*8975f5c5SAndroid Build Coastguard Worker GLint defaultHeight = mState.getDefaultHeight();
1612*8975f5c5SAndroid Build Coastguard Worker if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
1613*8975f5c5SAndroid Build Coastguard Worker {
1614*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT,
1615*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteDefaultZeroSize);
1616*8975f5c5SAndroid Build Coastguard Worker }
1617*8975f5c5SAndroid Build Coastguard Worker
1618*8975f5c5SAndroid Build Coastguard Worker // In ES 2.0 and WebGL, all color attachments must have the same width and height.
1619*8975f5c5SAndroid Build Coastguard Worker // In ES 3.0, there is no such restriction.
1620*8975f5c5SAndroid Build Coastguard Worker if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibilityANGLE) &&
1621*8975f5c5SAndroid Build Coastguard Worker !mState.attachmentsHaveSameDimensions())
1622*8975f5c5SAndroid Build Coastguard Worker {
1623*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1624*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS,
1625*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteInconsistantAttachmentSizes);
1626*8975f5c5SAndroid Build Coastguard Worker }
1627*8975f5c5SAndroid Build Coastguard Worker
1628*8975f5c5SAndroid Build Coastguard Worker // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1629*8975f5c5SAndroid Build Coastguard Worker // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
1630*8975f5c5SAndroid Build Coastguard Worker if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1631*8975f5c5SAndroid Build Coastguard Worker {
1632*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(
1633*8975f5c5SAndroid Build Coastguard Worker GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE,
1634*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteMultisampleNonFixedSamplesWithRenderbuffers);
1635*8975f5c5SAndroid Build Coastguard Worker }
1636*8975f5c5SAndroid Build Coastguard Worker
1637*8975f5c5SAndroid Build Coastguard Worker // The WebGL conformance tests implicitly define that all framebuffer
1638*8975f5c5SAndroid Build Coastguard Worker // attachments must be unique. For example, the same level of a texture can
1639*8975f5c5SAndroid Build Coastguard Worker // not be attached to two different color attachments.
1640*8975f5c5SAndroid Build Coastguard Worker if (state.getExtensions().webglCompatibilityANGLE)
1641*8975f5c5SAndroid Build Coastguard Worker {
1642*8975f5c5SAndroid Build Coastguard Worker if (!mState.colorAttachmentsAreUniqueImages())
1643*8975f5c5SAndroid Build Coastguard Worker {
1644*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNSUPPORTED,
1645*8975f5c5SAndroid Build Coastguard Worker err::kFramebufferIncompleteAttachmentsNotUnique);
1646*8975f5c5SAndroid Build Coastguard Worker }
1647*8975f5c5SAndroid Build Coastguard Worker }
1648*8975f5c5SAndroid Build Coastguard Worker
1649*8975f5c5SAndroid Build Coastguard Worker return FramebufferStatus::Complete();
1650*8975f5c5SAndroid Build Coastguard Worker }
1651*8975f5c5SAndroid Build Coastguard Worker
discard(const Context * context,size_t count,const GLenum * attachments)1652*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
1653*8975f5c5SAndroid Build Coastguard Worker {
1654*8975f5c5SAndroid Build Coastguard Worker // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1655*8975f5c5SAndroid Build Coastguard Worker // can be no-ops, so we should probably do that to ensure consistency.
1656*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1657*8975f5c5SAndroid Build Coastguard Worker
1658*8975f5c5SAndroid Build Coastguard Worker return mImpl->discard(context, count, attachments);
1659*8975f5c5SAndroid Build Coastguard Worker }
1660*8975f5c5SAndroid Build Coastguard Worker
invalidate(const Context * context,size_t count,const GLenum * attachments)1661*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::invalidate(const Context *context,
1662*8975f5c5SAndroid Build Coastguard Worker size_t count,
1663*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments)
1664*8975f5c5SAndroid Build Coastguard Worker {
1665*8975f5c5SAndroid Build Coastguard Worker // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1666*8975f5c5SAndroid Build Coastguard Worker // can be no-ops, so we should probably do that to ensure consistency.
1667*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1668*8975f5c5SAndroid Build Coastguard Worker
1669*8975f5c5SAndroid Build Coastguard Worker return mImpl->invalidate(context, count, attachments);
1670*8975f5c5SAndroid Build Coastguard Worker }
1671*8975f5c5SAndroid Build Coastguard Worker
partialClearNeedsInit(const Context * context,bool color,bool depth,bool stencil)1672*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::partialClearNeedsInit(const Context *context,
1673*8975f5c5SAndroid Build Coastguard Worker bool color,
1674*8975f5c5SAndroid Build Coastguard Worker bool depth,
1675*8975f5c5SAndroid Build Coastguard Worker bool stencil)
1676*8975f5c5SAndroid Build Coastguard Worker {
1677*8975f5c5SAndroid Build Coastguard Worker const auto &glState = context->getState();
1678*8975f5c5SAndroid Build Coastguard Worker
1679*8975f5c5SAndroid Build Coastguard Worker if (!glState.isRobustResourceInitEnabled())
1680*8975f5c5SAndroid Build Coastguard Worker {
1681*8975f5c5SAndroid Build Coastguard Worker return false;
1682*8975f5c5SAndroid Build Coastguard Worker }
1683*8975f5c5SAndroid Build Coastguard Worker
1684*8975f5c5SAndroid Build Coastguard Worker if (depth && context->getFrontendFeatures().forceDepthAttachmentInitOnClear.enabled)
1685*8975f5c5SAndroid Build Coastguard Worker {
1686*8975f5c5SAndroid Build Coastguard Worker return true;
1687*8975f5c5SAndroid Build Coastguard Worker }
1688*8975f5c5SAndroid Build Coastguard Worker
1689*8975f5c5SAndroid Build Coastguard Worker // Scissors can affect clearing.
1690*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Check for complete scissor overlap.
1691*8975f5c5SAndroid Build Coastguard Worker if (glState.isScissorTestEnabled())
1692*8975f5c5SAndroid Build Coastguard Worker {
1693*8975f5c5SAndroid Build Coastguard Worker return true;
1694*8975f5c5SAndroid Build Coastguard Worker }
1695*8975f5c5SAndroid Build Coastguard Worker
1696*8975f5c5SAndroid Build Coastguard Worker // If colors masked, we must clear before we clear. Do a simple check.
1697*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Filter out unused color channels from the test.
1698*8975f5c5SAndroid Build Coastguard Worker if (color && glState.anyActiveDrawBufferChannelMasked())
1699*8975f5c5SAndroid Build Coastguard Worker {
1700*8975f5c5SAndroid Build Coastguard Worker return true;
1701*8975f5c5SAndroid Build Coastguard Worker }
1702*8975f5c5SAndroid Build Coastguard Worker
1703*8975f5c5SAndroid Build Coastguard Worker if (stencil)
1704*8975f5c5SAndroid Build Coastguard Worker {
1705*8975f5c5SAndroid Build Coastguard Worker ASSERT(HasSupportedStencilBitCount(glState.getDrawFramebuffer()));
1706*8975f5c5SAndroid Build Coastguard Worker
1707*8975f5c5SAndroid Build Coastguard Worker // The least significant |stencilBits| of stencil mask state specify a
1708*8975f5c5SAndroid Build Coastguard Worker // mask. Compare the masks for differences only in those bits, ignoring any
1709*8975f5c5SAndroid Build Coastguard Worker // difference in the high bits.
1710*8975f5c5SAndroid Build Coastguard Worker const auto &depthStencil = glState.getDepthStencilState();
1711*8975f5c5SAndroid Build Coastguard Worker const GLuint differentFwdMasks = depthStencil.stencilMask ^ depthStencil.stencilWritemask;
1712*8975f5c5SAndroid Build Coastguard Worker const GLuint differentBackMasks =
1713*8975f5c5SAndroid Build Coastguard Worker depthStencil.stencilBackMask ^ depthStencil.stencilBackWritemask;
1714*8975f5c5SAndroid Build Coastguard Worker
1715*8975f5c5SAndroid Build Coastguard Worker if (((differentFwdMasks | differentBackMasks) & 0xFF) != 0)
1716*8975f5c5SAndroid Build Coastguard Worker {
1717*8975f5c5SAndroid Build Coastguard Worker return true;
1718*8975f5c5SAndroid Build Coastguard Worker }
1719*8975f5c5SAndroid Build Coastguard Worker }
1720*8975f5c5SAndroid Build Coastguard Worker
1721*8975f5c5SAndroid Build Coastguard Worker return false;
1722*8975f5c5SAndroid Build Coastguard Worker }
1723*8975f5c5SAndroid Build Coastguard Worker
invalidateSub(const Context * context,size_t count,const GLenum * attachments,const Rectangle & area)1724*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::invalidateSub(const Context *context,
1725*8975f5c5SAndroid Build Coastguard Worker size_t count,
1726*8975f5c5SAndroid Build Coastguard Worker const GLenum *attachments,
1727*8975f5c5SAndroid Build Coastguard Worker const Rectangle &area)
1728*8975f5c5SAndroid Build Coastguard Worker {
1729*8975f5c5SAndroid Build Coastguard Worker // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1730*8975f5c5SAndroid Build Coastguard Worker // can be no-ops, so we should probably do that to ensure consistency.
1731*8975f5c5SAndroid Build Coastguard Worker // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1732*8975f5c5SAndroid Build Coastguard Worker
1733*8975f5c5SAndroid Build Coastguard Worker return mImpl->invalidateSub(context, count, attachments, area);
1734*8975f5c5SAndroid Build Coastguard Worker }
1735*8975f5c5SAndroid Build Coastguard Worker
clear(const Context * context,GLbitfield mask)1736*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
1737*8975f5c5SAndroid Build Coastguard Worker {
1738*8975f5c5SAndroid Build Coastguard Worker ASSERT(mask && !context->getState().isRasterizerDiscardEnabled());
1739*8975f5c5SAndroid Build Coastguard Worker
1740*8975f5c5SAndroid Build Coastguard Worker return mImpl->clear(context, mask);
1741*8975f5c5SAndroid Build Coastguard Worker }
1742*8975f5c5SAndroid Build Coastguard Worker
clearBufferfv(const Context * context,GLenum buffer,GLint drawbuffer,const GLfloat * values)1743*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::clearBufferfv(const Context *context,
1744*8975f5c5SAndroid Build Coastguard Worker GLenum buffer,
1745*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer,
1746*8975f5c5SAndroid Build Coastguard Worker const GLfloat *values)
1747*8975f5c5SAndroid Build Coastguard Worker {
1748*8975f5c5SAndroid Build Coastguard Worker return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
1749*8975f5c5SAndroid Build Coastguard Worker }
1750*8975f5c5SAndroid Build Coastguard Worker
clearBufferuiv(const Context * context,GLenum buffer,GLint drawbuffer,const GLuint * values)1751*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::clearBufferuiv(const Context *context,
1752*8975f5c5SAndroid Build Coastguard Worker GLenum buffer,
1753*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer,
1754*8975f5c5SAndroid Build Coastguard Worker const GLuint *values)
1755*8975f5c5SAndroid Build Coastguard Worker {
1756*8975f5c5SAndroid Build Coastguard Worker return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
1757*8975f5c5SAndroid Build Coastguard Worker }
1758*8975f5c5SAndroid Build Coastguard Worker
clearBufferiv(const Context * context,GLenum buffer,GLint drawbuffer,const GLint * values)1759*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::clearBufferiv(const Context *context,
1760*8975f5c5SAndroid Build Coastguard Worker GLenum buffer,
1761*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer,
1762*8975f5c5SAndroid Build Coastguard Worker const GLint *values)
1763*8975f5c5SAndroid Build Coastguard Worker {
1764*8975f5c5SAndroid Build Coastguard Worker return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
1765*8975f5c5SAndroid Build Coastguard Worker }
1766*8975f5c5SAndroid Build Coastguard Worker
clearBufferfi(const Context * context,GLenum buffer,GLint drawbuffer,GLfloat depth,GLint stencil)1767*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::clearBufferfi(const Context *context,
1768*8975f5c5SAndroid Build Coastguard Worker GLenum buffer,
1769*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer,
1770*8975f5c5SAndroid Build Coastguard Worker GLfloat depth,
1771*8975f5c5SAndroid Build Coastguard Worker GLint stencil)
1772*8975f5c5SAndroid Build Coastguard Worker {
1773*8975f5c5SAndroid Build Coastguard Worker const bool clearDepth =
1774*8975f5c5SAndroid Build Coastguard Worker getDepthAttachment() != nullptr && context->getState().getDepthStencilState().depthMask;
1775*8975f5c5SAndroid Build Coastguard Worker const bool clearStencil = getStencilAttachment() != nullptr &&
1776*8975f5c5SAndroid Build Coastguard Worker context->getState().getDepthStencilState().stencilWritemask != 0;
1777*8975f5c5SAndroid Build Coastguard Worker
1778*8975f5c5SAndroid Build Coastguard Worker if (clearDepth && clearStencil)
1779*8975f5c5SAndroid Build Coastguard Worker {
1780*8975f5c5SAndroid Build Coastguard Worker ASSERT(buffer == GL_DEPTH_STENCIL);
1781*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1782*8975f5c5SAndroid Build Coastguard Worker }
1783*8975f5c5SAndroid Build Coastguard Worker else if (clearDepth && !clearStencil)
1784*8975f5c5SAndroid Build Coastguard Worker {
1785*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1786*8975f5c5SAndroid Build Coastguard Worker }
1787*8975f5c5SAndroid Build Coastguard Worker else if (!clearDepth && clearStencil)
1788*8975f5c5SAndroid Build Coastguard Worker {
1789*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1790*8975f5c5SAndroid Build Coastguard Worker }
1791*8975f5c5SAndroid Build Coastguard Worker
1792*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1793*8975f5c5SAndroid Build Coastguard Worker }
1794*8975f5c5SAndroid Build Coastguard Worker
getImplementationColorReadFormat(const Context * context)1795*8975f5c5SAndroid Build Coastguard Worker GLenum Framebuffer::getImplementationColorReadFormat(const Context *context)
1796*8975f5c5SAndroid Build Coastguard Worker {
1797*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
1798*8975f5c5SAndroid Build Coastguard Worker return format.getReadPixelsFormat(context->getExtensions());
1799*8975f5c5SAndroid Build Coastguard Worker }
1800*8975f5c5SAndroid Build Coastguard Worker
getImplementationColorReadType(const Context * context)1801*8975f5c5SAndroid Build Coastguard Worker GLenum Framebuffer::getImplementationColorReadType(const Context *context)
1802*8975f5c5SAndroid Build Coastguard Worker {
1803*8975f5c5SAndroid Build Coastguard Worker const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context);
1804*8975f5c5SAndroid Build Coastguard Worker return format.getReadPixelsType(context->getClientVersion());
1805*8975f5c5SAndroid Build Coastguard Worker }
1806*8975f5c5SAndroid Build Coastguard Worker
readPixels(const Context * context,const Rectangle & area,GLenum format,GLenum type,const PixelPackState & pack,Buffer * packBuffer,void * pixels)1807*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::readPixels(const Context *context,
1808*8975f5c5SAndroid Build Coastguard Worker const Rectangle &area,
1809*8975f5c5SAndroid Build Coastguard Worker GLenum format,
1810*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1811*8975f5c5SAndroid Build Coastguard Worker const PixelPackState &pack,
1812*8975f5c5SAndroid Build Coastguard Worker Buffer *packBuffer,
1813*8975f5c5SAndroid Build Coastguard Worker void *pixels)
1814*8975f5c5SAndroid Build Coastguard Worker {
1815*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->readPixels(context, area, format, type, pack, packBuffer, pixels));
1816*8975f5c5SAndroid Build Coastguard Worker
1817*8975f5c5SAndroid Build Coastguard Worker if (packBuffer)
1818*8975f5c5SAndroid Build Coastguard Worker {
1819*8975f5c5SAndroid Build Coastguard Worker packBuffer->onDataChanged();
1820*8975f5c5SAndroid Build Coastguard Worker }
1821*8975f5c5SAndroid Build Coastguard Worker
1822*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1823*8975f5c5SAndroid Build Coastguard Worker }
1824*8975f5c5SAndroid Build Coastguard Worker
blit(const Context * context,const Rectangle & sourceArea,const Rectangle & destArea,GLbitfield mask,GLenum filter)1825*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::blit(const Context *context,
1826*8975f5c5SAndroid Build Coastguard Worker const Rectangle &sourceArea,
1827*8975f5c5SAndroid Build Coastguard Worker const Rectangle &destArea,
1828*8975f5c5SAndroid Build Coastguard Worker GLbitfield mask,
1829*8975f5c5SAndroid Build Coastguard Worker GLenum filter)
1830*8975f5c5SAndroid Build Coastguard Worker {
1831*8975f5c5SAndroid Build Coastguard Worker ASSERT(mask != 0);
1832*8975f5c5SAndroid Build Coastguard Worker
1833*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->blit(context, sourceArea, destArea, mask, filter));
1834*8975f5c5SAndroid Build Coastguard Worker
1835*8975f5c5SAndroid Build Coastguard Worker // Mark the contents of the attachments dirty
1836*8975f5c5SAndroid Build Coastguard Worker if ((mask & GL_COLOR_BUFFER_BIT) != 0)
1837*8975f5c5SAndroid Build Coastguard Worker {
1838*8975f5c5SAndroid Build Coastguard Worker for (size_t colorIndex : mState.mEnabledDrawBuffers)
1839*8975f5c5SAndroid Build Coastguard Worker {
1840*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + colorIndex);
1841*8975f5c5SAndroid Build Coastguard Worker }
1842*8975f5c5SAndroid Build Coastguard Worker }
1843*8975f5c5SAndroid Build Coastguard Worker if ((mask & GL_DEPTH_BUFFER_BIT) != 0)
1844*8975f5c5SAndroid Build Coastguard Worker {
1845*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEPTH_BUFFER_CONTENTS);
1846*8975f5c5SAndroid Build Coastguard Worker }
1847*8975f5c5SAndroid Build Coastguard Worker if ((mask & GL_STENCIL_BUFFER_BIT) != 0)
1848*8975f5c5SAndroid Build Coastguard Worker {
1849*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_STENCIL_BUFFER_CONTENTS);
1850*8975f5c5SAndroid Build Coastguard Worker }
1851*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
1852*8975f5c5SAndroid Build Coastguard Worker
1853*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1854*8975f5c5SAndroid Build Coastguard Worker }
1855*8975f5c5SAndroid Build Coastguard Worker
getSamples(const Context * context) const1856*8975f5c5SAndroid Build Coastguard Worker int Framebuffer::getSamples(const Context *context) const
1857*8975f5c5SAndroid Build Coastguard Worker {
1858*8975f5c5SAndroid Build Coastguard Worker if (!isComplete(context))
1859*8975f5c5SAndroid Build Coastguard Worker {
1860*8975f5c5SAndroid Build Coastguard Worker return 0;
1861*8975f5c5SAndroid Build Coastguard Worker }
1862*8975f5c5SAndroid Build Coastguard Worker
1863*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete());
1864*8975f5c5SAndroid Build Coastguard Worker
1865*8975f5c5SAndroid Build Coastguard Worker // For a complete framebuffer, all attachments must have the same sample count.
1866*8975f5c5SAndroid Build Coastguard Worker // In this case return the first nonzero sample size.
1867*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1868*8975f5c5SAndroid Build Coastguard Worker ASSERT(firstNonNullAttachment == nullptr || firstNonNullAttachment->isAttached());
1869*8975f5c5SAndroid Build Coastguard Worker
1870*8975f5c5SAndroid Build Coastguard Worker return firstNonNullAttachment ? firstNonNullAttachment->getSamples() : 0;
1871*8975f5c5SAndroid Build Coastguard Worker }
1872*8975f5c5SAndroid Build Coastguard Worker
getReadBufferResourceSamples(const Context * context) const1873*8975f5c5SAndroid Build Coastguard Worker int Framebuffer::getReadBufferResourceSamples(const Context *context) const
1874*8975f5c5SAndroid Build Coastguard Worker {
1875*8975f5c5SAndroid Build Coastguard Worker if (!isComplete(context))
1876*8975f5c5SAndroid Build Coastguard Worker {
1877*8975f5c5SAndroid Build Coastguard Worker return 0;
1878*8975f5c5SAndroid Build Coastguard Worker }
1879*8975f5c5SAndroid Build Coastguard Worker
1880*8975f5c5SAndroid Build Coastguard Worker ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete());
1881*8975f5c5SAndroid Build Coastguard Worker
1882*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *readAttachment = mState.getReadAttachment();
1883*8975f5c5SAndroid Build Coastguard Worker ASSERT(readAttachment == nullptr || readAttachment->isAttached());
1884*8975f5c5SAndroid Build Coastguard Worker
1885*8975f5c5SAndroid Build Coastguard Worker return readAttachment ? readAttachment->getResourceSamples() : 0;
1886*8975f5c5SAndroid Build Coastguard Worker }
1887*8975f5c5SAndroid Build Coastguard Worker
getSamplePosition(const Context * context,size_t index,GLfloat * xy) const1888*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::getSamplePosition(const Context *context,
1889*8975f5c5SAndroid Build Coastguard Worker size_t index,
1890*8975f5c5SAndroid Build Coastguard Worker GLfloat *xy) const
1891*8975f5c5SAndroid Build Coastguard Worker {
1892*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
1893*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
1894*8975f5c5SAndroid Build Coastguard Worker }
1895*8975f5c5SAndroid Build Coastguard Worker
hasValidDepthStencil() const1896*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::hasValidDepthStencil() const
1897*8975f5c5SAndroid Build Coastguard Worker {
1898*8975f5c5SAndroid Build Coastguard Worker return mState.getDepthStencilAttachment() != nullptr;
1899*8975f5c5SAndroid Build Coastguard Worker }
1900*8975f5c5SAndroid Build Coastguard Worker
getSurfaceTextureOffset() const1901*8975f5c5SAndroid Build Coastguard Worker const gl::Offset &Framebuffer::getSurfaceTextureOffset() const
1902*8975f5c5SAndroid Build Coastguard Worker {
1903*8975f5c5SAndroid Build Coastguard Worker return mState.getSurfaceTextureOffset();
1904*8975f5c5SAndroid Build Coastguard Worker }
1905*8975f5c5SAndroid Build Coastguard Worker
setAttachment(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource)1906*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setAttachment(const Context *context,
1907*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1908*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
1909*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
1910*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource)
1911*8975f5c5SAndroid Build Coastguard Worker {
1912*8975f5c5SAndroid Build Coastguard Worker setAttachment(context, type, binding, textureIndex, resource,
1913*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews,
1914*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultBaseViewIndex, false,
1915*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples);
1916*8975f5c5SAndroid Build Coastguard Worker }
1917*8975f5c5SAndroid Build Coastguard Worker
setAttachmentMultisample(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei samples)1918*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setAttachmentMultisample(const Context *context,
1919*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1920*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
1921*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
1922*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource,
1923*8975f5c5SAndroid Build Coastguard Worker GLsizei samples)
1924*8975f5c5SAndroid Build Coastguard Worker {
1925*8975f5c5SAndroid Build Coastguard Worker setAttachment(context, type, binding, textureIndex, resource,
1926*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultNumViews,
1927*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultBaseViewIndex, false, samples);
1928*8975f5c5SAndroid Build Coastguard Worker }
1929*8975f5c5SAndroid Build Coastguard Worker
setAttachment(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samplesIn)1930*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setAttachment(const Context *context,
1931*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1932*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
1933*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
1934*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource,
1935*8975f5c5SAndroid Build Coastguard Worker GLsizei numViews,
1936*8975f5c5SAndroid Build Coastguard Worker GLuint baseViewIndex,
1937*8975f5c5SAndroid Build Coastguard Worker bool isMultiview,
1938*8975f5c5SAndroid Build Coastguard Worker GLsizei samplesIn)
1939*8975f5c5SAndroid Build Coastguard Worker {
1940*8975f5c5SAndroid Build Coastguard Worker GLsizei samples = samplesIn;
1941*8975f5c5SAndroid Build Coastguard Worker // Match the sample count to the attachment's sample count.
1942*8975f5c5SAndroid Build Coastguard Worker if (resource)
1943*8975f5c5SAndroid Build Coastguard Worker {
1944*8975f5c5SAndroid Build Coastguard Worker const InternalFormat *info = resource->getAttachmentFormat(binding, textureIndex).info;
1945*8975f5c5SAndroid Build Coastguard Worker ASSERT(info);
1946*8975f5c5SAndroid Build Coastguard Worker GLenum sizedInternalFormat = info->sizedInternalFormat;
1947*8975f5c5SAndroid Build Coastguard Worker const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat);
1948*8975f5c5SAndroid Build Coastguard Worker samples = formatCaps.getNearestSamples(samples);
1949*8975f5c5SAndroid Build Coastguard Worker }
1950*8975f5c5SAndroid Build Coastguard Worker
1951*8975f5c5SAndroid Build Coastguard Worker // Context may be null in unit tests.
1952*8975f5c5SAndroid Build Coastguard Worker if (!context || !context->isWebGL1())
1953*8975f5c5SAndroid Build Coastguard Worker {
1954*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1955*8975f5c5SAndroid Build Coastguard Worker isMultiview, samples);
1956*8975f5c5SAndroid Build Coastguard Worker return;
1957*8975f5c5SAndroid Build Coastguard Worker }
1958*8975f5c5SAndroid Build Coastguard Worker
1959*8975f5c5SAndroid Build Coastguard Worker switch (binding)
1960*8975f5c5SAndroid Build Coastguard Worker {
1961*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL:
1962*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL_ATTACHMENT:
1963*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthStencilAttachment.attach(
1964*8975f5c5SAndroid Build Coastguard Worker context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1965*8975f5c5SAndroid Build Coastguard Worker isMultiview, samples, mState.mFramebufferSerial);
1966*8975f5c5SAndroid Build Coastguard Worker break;
1967*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH:
1968*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_ATTACHMENT:
1969*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1970*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples,
1971*8975f5c5SAndroid Build Coastguard Worker mState.mFramebufferSerial);
1972*8975f5c5SAndroid Build Coastguard Worker break;
1973*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL:
1974*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL_ATTACHMENT:
1975*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1976*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples,
1977*8975f5c5SAndroid Build Coastguard Worker mState.mFramebufferSerial);
1978*8975f5c5SAndroid Build Coastguard Worker break;
1979*8975f5c5SAndroid Build Coastguard Worker default:
1980*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1981*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
1982*8975f5c5SAndroid Build Coastguard Worker return;
1983*8975f5c5SAndroid Build Coastguard Worker }
1984*8975f5c5SAndroid Build Coastguard Worker
1985*8975f5c5SAndroid Build Coastguard Worker commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview, samples);
1986*8975f5c5SAndroid Build Coastguard Worker }
1987*8975f5c5SAndroid Build Coastguard Worker
setAttachmentMultiview(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLint baseViewIndex)1988*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setAttachmentMultiview(const Context *context,
1989*8975f5c5SAndroid Build Coastguard Worker GLenum type,
1990*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
1991*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
1992*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource,
1993*8975f5c5SAndroid Build Coastguard Worker GLsizei numViews,
1994*8975f5c5SAndroid Build Coastguard Worker GLint baseViewIndex)
1995*8975f5c5SAndroid Build Coastguard Worker {
1996*8975f5c5SAndroid Build Coastguard Worker setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true,
1997*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment::kDefaultRenderToTextureSamples);
1998*8975f5c5SAndroid Build Coastguard Worker }
1999*8975f5c5SAndroid Build Coastguard Worker
commitWebGL1DepthStencilIfConsistent(const Context * context,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samples)2000*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
2001*8975f5c5SAndroid Build Coastguard Worker GLsizei numViews,
2002*8975f5c5SAndroid Build Coastguard Worker GLuint baseViewIndex,
2003*8975f5c5SAndroid Build Coastguard Worker bool isMultiview,
2004*8975f5c5SAndroid Build Coastguard Worker GLsizei samples)
2005*8975f5c5SAndroid Build Coastguard Worker {
2006*8975f5c5SAndroid Build Coastguard Worker int count = 0;
2007*8975f5c5SAndroid Build Coastguard Worker
2008*8975f5c5SAndroid Build Coastguard Worker std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
2009*8975f5c5SAndroid Build Coastguard Worker &mState.mWebGLDepthAttachment,
2010*8975f5c5SAndroid Build Coastguard Worker &mState.mWebGLStencilAttachment}};
2011*8975f5c5SAndroid Build Coastguard Worker for (FramebufferAttachment *attachment : attachments)
2012*8975f5c5SAndroid Build Coastguard Worker {
2013*8975f5c5SAndroid Build Coastguard Worker if (attachment->isAttached())
2014*8975f5c5SAndroid Build Coastguard Worker {
2015*8975f5c5SAndroid Build Coastguard Worker count++;
2016*8975f5c5SAndroid Build Coastguard Worker }
2017*8975f5c5SAndroid Build Coastguard Worker }
2018*8975f5c5SAndroid Build Coastguard Worker
2019*8975f5c5SAndroid Build Coastguard Worker mState.mWebGLDepthStencilConsistent = (count <= 1);
2020*8975f5c5SAndroid Build Coastguard Worker if (!mState.mWebGLDepthStencilConsistent)
2021*8975f5c5SAndroid Build Coastguard Worker {
2022*8975f5c5SAndroid Build Coastguard Worker // Inconsistent.
2023*8975f5c5SAndroid Build Coastguard Worker return;
2024*8975f5c5SAndroid Build Coastguard Worker }
2025*8975f5c5SAndroid Build Coastguard Worker
2026*8975f5c5SAndroid Build Coastguard Worker auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
2027*8975f5c5SAndroid Build Coastguard Worker if (attachment.type() == GL_TEXTURE)
2028*8975f5c5SAndroid Build Coastguard Worker {
2029*8975f5c5SAndroid Build Coastguard Worker return attachment.getTextureImageIndex();
2030*8975f5c5SAndroid Build Coastguard Worker }
2031*8975f5c5SAndroid Build Coastguard Worker else
2032*8975f5c5SAndroid Build Coastguard Worker {
2033*8975f5c5SAndroid Build Coastguard Worker return ImageIndex();
2034*8975f5c5SAndroid Build Coastguard Worker }
2035*8975f5c5SAndroid Build Coastguard Worker };
2036*8975f5c5SAndroid Build Coastguard Worker
2037*8975f5c5SAndroid Build Coastguard Worker if (mState.mWebGLDepthAttachment.isAttached())
2038*8975f5c5SAndroid Build Coastguard Worker {
2039*8975f5c5SAndroid Build Coastguard Worker const auto &depth = mState.mWebGLDepthAttachment;
2040*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
2041*8975f5c5SAndroid Build Coastguard Worker getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
2042*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
2043*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
2044*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
2045*8975f5c5SAndroid Build Coastguard Worker }
2046*8975f5c5SAndroid Build Coastguard Worker else if (mState.mWebGLStencilAttachment.isAttached())
2047*8975f5c5SAndroid Build Coastguard Worker {
2048*8975f5c5SAndroid Build Coastguard Worker const auto &stencil = mState.mWebGLStencilAttachment;
2049*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
2050*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
2051*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
2052*8975f5c5SAndroid Build Coastguard Worker getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
2053*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples);
2054*8975f5c5SAndroid Build Coastguard Worker }
2055*8975f5c5SAndroid Build Coastguard Worker else if (mState.mWebGLDepthStencilAttachment.isAttached())
2056*8975f5c5SAndroid Build Coastguard Worker {
2057*8975f5c5SAndroid Build Coastguard Worker const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
2058*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
2059*8975f5c5SAndroid Build Coastguard Worker getImageIndexIfTextureAttachment(depthStencil),
2060*8975f5c5SAndroid Build Coastguard Worker depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
2061*8975f5c5SAndroid Build Coastguard Worker samples);
2062*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
2063*8975f5c5SAndroid Build Coastguard Worker getImageIndexIfTextureAttachment(depthStencil),
2064*8975f5c5SAndroid Build Coastguard Worker depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
2065*8975f5c5SAndroid Build Coastguard Worker samples);
2066*8975f5c5SAndroid Build Coastguard Worker }
2067*8975f5c5SAndroid Build Coastguard Worker else
2068*8975f5c5SAndroid Build Coastguard Worker {
2069*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
2070*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
2071*8975f5c5SAndroid Build Coastguard Worker setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
2072*8975f5c5SAndroid Build Coastguard Worker baseViewIndex, isMultiview, samples);
2073*8975f5c5SAndroid Build Coastguard Worker }
2074*8975f5c5SAndroid Build Coastguard Worker }
2075*8975f5c5SAndroid Build Coastguard Worker
setAttachmentImpl(const Context * context,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samples)2076*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setAttachmentImpl(const Context *context,
2077*8975f5c5SAndroid Build Coastguard Worker GLenum type,
2078*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
2079*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
2080*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource,
2081*8975f5c5SAndroid Build Coastguard Worker GLsizei numViews,
2082*8975f5c5SAndroid Build Coastguard Worker GLuint baseViewIndex,
2083*8975f5c5SAndroid Build Coastguard Worker bool isMultiview,
2084*8975f5c5SAndroid Build Coastguard Worker GLsizei samples)
2085*8975f5c5SAndroid Build Coastguard Worker {
2086*8975f5c5SAndroid Build Coastguard Worker switch (binding)
2087*8975f5c5SAndroid Build Coastguard Worker {
2088*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL:
2089*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL_ATTACHMENT:
2090*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
2091*8975f5c5SAndroid Build Coastguard Worker &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
2092*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples);
2093*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
2094*8975f5c5SAndroid Build Coastguard Worker &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
2095*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples);
2096*8975f5c5SAndroid Build Coastguard Worker break;
2097*8975f5c5SAndroid Build Coastguard Worker
2098*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH:
2099*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_ATTACHMENT:
2100*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
2101*8975f5c5SAndroid Build Coastguard Worker &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
2102*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples);
2103*8975f5c5SAndroid Build Coastguard Worker break;
2104*8975f5c5SAndroid Build Coastguard Worker
2105*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL:
2106*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL_ATTACHMENT:
2107*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
2108*8975f5c5SAndroid Build Coastguard Worker &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
2109*8975f5c5SAndroid Build Coastguard Worker numViews, baseViewIndex, isMultiview, samples);
2110*8975f5c5SAndroid Build Coastguard Worker break;
2111*8975f5c5SAndroid Build Coastguard Worker
2112*8975f5c5SAndroid Build Coastguard Worker case GL_BACK:
2113*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
2114*8975f5c5SAndroid Build Coastguard Worker &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
2115*8975f5c5SAndroid Build Coastguard Worker resource, numViews, baseViewIndex, isMultiview, samples);
2116*8975f5c5SAndroid Build Coastguard Worker mState.mColorAttachmentsMask.set(0);
2117*8975f5c5SAndroid Build Coastguard Worker
2118*8975f5c5SAndroid Build Coastguard Worker break;
2119*8975f5c5SAndroid Build Coastguard Worker
2120*8975f5c5SAndroid Build Coastguard Worker default:
2121*8975f5c5SAndroid Build Coastguard Worker {
2122*8975f5c5SAndroid Build Coastguard Worker const size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
2123*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndex < mState.mColorAttachments.size());
2124*8975f5c5SAndroid Build Coastguard Worker
2125*8975f5c5SAndroid Build Coastguard Worker // Caches must be updated before notifying the observers.
2126*8975f5c5SAndroid Build Coastguard Worker ComponentType componentType = ComponentType::NoType;
2127*8975f5c5SAndroid Build Coastguard Worker if (!resource)
2128*8975f5c5SAndroid Build Coastguard Worker {
2129*8975f5c5SAndroid Build Coastguard Worker mFloat32ColorAttachmentBits.reset(colorIndex);
2130*8975f5c5SAndroid Build Coastguard Worker mSharedExponentColorAttachmentBits.reset(colorIndex);
2131*8975f5c5SAndroid Build Coastguard Worker mState.mColorAttachmentsMask.reset(colorIndex);
2132*8975f5c5SAndroid Build Coastguard Worker }
2133*8975f5c5SAndroid Build Coastguard Worker else
2134*8975f5c5SAndroid Build Coastguard Worker {
2135*8975f5c5SAndroid Build Coastguard Worker const InternalFormat *formatInfo =
2136*8975f5c5SAndroid Build Coastguard Worker resource->getAttachmentFormat(binding, textureIndex).info;
2137*8975f5c5SAndroid Build Coastguard Worker componentType = GetAttachmentComponentType(formatInfo->componentType);
2138*8975f5c5SAndroid Build Coastguard Worker updateFloat32AndSharedExponentColorAttachmentBits(colorIndex, formatInfo);
2139*8975f5c5SAndroid Build Coastguard Worker mState.mColorAttachmentsMask.set(colorIndex);
2140*8975f5c5SAndroid Build Coastguard Worker }
2141*8975f5c5SAndroid Build Coastguard Worker const bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
2142*8975f5c5SAndroid Build Coastguard Worker mState.mEnabledDrawBuffers.set(colorIndex, enabled);
2143*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(componentType, colorIndex, &mState.mDrawBufferTypeMask);
2144*8975f5c5SAndroid Build Coastguard Worker
2145*8975f5c5SAndroid Build Coastguard Worker const size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
2146*8975f5c5SAndroid Build Coastguard Worker updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
2147*8975f5c5SAndroid Build Coastguard Worker &mDirtyColorAttachmentBindings[colorIndex], type, binding,
2148*8975f5c5SAndroid Build Coastguard Worker textureIndex, resource, numViews, baseViewIndex, isMultiview, samples);
2149*8975f5c5SAndroid Build Coastguard Worker }
2150*8975f5c5SAndroid Build Coastguard Worker break;
2151*8975f5c5SAndroid Build Coastguard Worker }
2152*8975f5c5SAndroid Build Coastguard Worker }
2153*8975f5c5SAndroid Build Coastguard Worker
updateAttachment(const Context * context,FramebufferAttachment * attachment,size_t dirtyBit,angle::ObserverBinding * onDirtyBinding,GLenum type,GLenum binding,const ImageIndex & textureIndex,FramebufferAttachmentObject * resource,GLsizei numViews,GLuint baseViewIndex,bool isMultiview,GLsizei samples)2154*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::updateAttachment(const Context *context,
2155*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment *attachment,
2156*8975f5c5SAndroid Build Coastguard Worker size_t dirtyBit,
2157*8975f5c5SAndroid Build Coastguard Worker angle::ObserverBinding *onDirtyBinding,
2158*8975f5c5SAndroid Build Coastguard Worker GLenum type,
2159*8975f5c5SAndroid Build Coastguard Worker GLenum binding,
2160*8975f5c5SAndroid Build Coastguard Worker const ImageIndex &textureIndex,
2161*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachmentObject *resource,
2162*8975f5c5SAndroid Build Coastguard Worker GLsizei numViews,
2163*8975f5c5SAndroid Build Coastguard Worker GLuint baseViewIndex,
2164*8975f5c5SAndroid Build Coastguard Worker bool isMultiview,
2165*8975f5c5SAndroid Build Coastguard Worker GLsizei samples)
2166*8975f5c5SAndroid Build Coastguard Worker {
2167*8975f5c5SAndroid Build Coastguard Worker attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
2168*8975f5c5SAndroid Build Coastguard Worker isMultiview, samples, mState.mFramebufferSerial);
2169*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(dirtyBit);
2170*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
2171*8975f5c5SAndroid Build Coastguard Worker onDirtyBinding->bind(resource);
2172*8975f5c5SAndroid Build Coastguard Worker mAttachmentChangedAfterEnablingFoveation = isFoveationEnabled();
2173*8975f5c5SAndroid Build Coastguard Worker
2174*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2175*8975f5c5SAndroid Build Coastguard Worker }
2176*8975f5c5SAndroid Build Coastguard Worker
resetAttachment(const Context * context,GLenum binding)2177*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::resetAttachment(const Context *context, GLenum binding)
2178*8975f5c5SAndroid Build Coastguard Worker {
2179*8975f5c5SAndroid Build Coastguard Worker setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
2180*8975f5c5SAndroid Build Coastguard Worker }
2181*8975f5c5SAndroid Build Coastguard Worker
setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode)2182*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode)
2183*8975f5c5SAndroid Build Coastguard Worker {
2184*8975f5c5SAndroid Build Coastguard Worker if (srgbWriteControlMode != mState.getWriteControlMode())
2185*8975f5c5SAndroid Build Coastguard Worker {
2186*8975f5c5SAndroid Build Coastguard Worker mState.mSrgbWriteControlMode = srgbWriteControlMode;
2187*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE);
2188*8975f5c5SAndroid Build Coastguard Worker }
2189*8975f5c5SAndroid Build Coastguard Worker }
2190*8975f5c5SAndroid Build Coastguard Worker
syncState(const Context * context,GLenum framebufferBinding,Command command) const2191*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::syncState(const Context *context,
2192*8975f5c5SAndroid Build Coastguard Worker GLenum framebufferBinding,
2193*8975f5c5SAndroid Build Coastguard Worker Command command) const
2194*8975f5c5SAndroid Build Coastguard Worker {
2195*8975f5c5SAndroid Build Coastguard Worker if (mDirtyBits.any())
2196*8975f5c5SAndroid Build Coastguard Worker {
2197*8975f5c5SAndroid Build Coastguard Worker mDirtyBitsGuard = mDirtyBits;
2198*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->syncState(context, framebufferBinding, mDirtyBits, command));
2199*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.reset();
2200*8975f5c5SAndroid Build Coastguard Worker mDirtyBitsGuard.reset();
2201*8975f5c5SAndroid Build Coastguard Worker }
2202*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2203*8975f5c5SAndroid Build Coastguard Worker }
2204*8975f5c5SAndroid Build Coastguard Worker
onSubjectStateChange(angle::SubjectIndex index,angle::SubjectMessage message)2205*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
2206*8975f5c5SAndroid Build Coastguard Worker {
2207*8975f5c5SAndroid Build Coastguard Worker if (message != angle::SubjectMessage::SubjectChanged)
2208*8975f5c5SAndroid Build Coastguard Worker {
2209*8975f5c5SAndroid Build Coastguard Worker // This can be triggered by SubImage calls for Textures.
2210*8975f5c5SAndroid Build Coastguard Worker if (message == angle::SubjectMessage::ContentsChanged)
2211*8975f5c5SAndroid Build Coastguard Worker {
2212*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
2213*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
2214*8975f5c5SAndroid Build Coastguard Worker return;
2215*8975f5c5SAndroid Build Coastguard Worker }
2216*8975f5c5SAndroid Build Coastguard Worker
2217*8975f5c5SAndroid Build Coastguard Worker // Swapchain changes should only result in color buffer changes.
2218*8975f5c5SAndroid Build Coastguard Worker if (message == angle::SubjectMessage::SwapchainImageChanged)
2219*8975f5c5SAndroid Build Coastguard Worker {
2220*8975f5c5SAndroid Build Coastguard Worker if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
2221*8975f5c5SAndroid Build Coastguard Worker {
2222*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
2223*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
2224*8975f5c5SAndroid Build Coastguard Worker }
2225*8975f5c5SAndroid Build Coastguard Worker return;
2226*8975f5c5SAndroid Build Coastguard Worker }
2227*8975f5c5SAndroid Build Coastguard Worker
2228*8975f5c5SAndroid Build Coastguard Worker ASSERT(message != angle::SubjectMessage::BindingChanged);
2229*8975f5c5SAndroid Build Coastguard Worker
2230*8975f5c5SAndroid Build Coastguard Worker // This can be triggered by external changes to the default framebuffer.
2231*8975f5c5SAndroid Build Coastguard Worker if (message == angle::SubjectMessage::SurfaceChanged)
2232*8975f5c5SAndroid Build Coastguard Worker {
2233*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::SurfaceChanged);
2234*8975f5c5SAndroid Build Coastguard Worker return;
2235*8975f5c5SAndroid Build Coastguard Worker }
2236*8975f5c5SAndroid Build Coastguard Worker
2237*8975f5c5SAndroid Build Coastguard Worker // This can be triggered by freeing TextureStorage in D3D back-end.
2238*8975f5c5SAndroid Build Coastguard Worker if (message == angle::SubjectMessage::StorageReleased)
2239*8975f5c5SAndroid Build Coastguard Worker {
2240*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(index);
2241*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2242*8975f5c5SAndroid Build Coastguard Worker return;
2243*8975f5c5SAndroid Build Coastguard Worker }
2244*8975f5c5SAndroid Build Coastguard Worker
2245*8975f5c5SAndroid Build Coastguard Worker // This can be triggered when a subject's foveated rendering state is changed
2246*8975f5c5SAndroid Build Coastguard Worker if (message == angle::SubjectMessage::FoveatedRenderingStateChanged)
2247*8975f5c5SAndroid Build Coastguard Worker {
2248*8975f5c5SAndroid Build Coastguard Worker // Only a color attachment can be foveated.
2249*8975f5c5SAndroid Build Coastguard Worker ASSERT(index >= DIRTY_BIT_COLOR_ATTACHMENT_0 && index < DIRTY_BIT_COLOR_ATTACHMENT_MAX);
2250*8975f5c5SAndroid Build Coastguard Worker // Mark the attachment as dirty so we can grab its updated foveation state.
2251*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(index);
2252*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
2253*8975f5c5SAndroid Build Coastguard Worker return;
2254*8975f5c5SAndroid Build Coastguard Worker }
2255*8975f5c5SAndroid Build Coastguard Worker
2256*8975f5c5SAndroid Build Coastguard Worker // This can be triggered by the GL back-end TextureGL class.
2257*8975f5c5SAndroid Build Coastguard Worker ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged ||
2258*8975f5c5SAndroid Build Coastguard Worker message == angle::SubjectMessage::TextureIDDeleted);
2259*8975f5c5SAndroid Build Coastguard Worker return;
2260*8975f5c5SAndroid Build Coastguard Worker }
2261*8975f5c5SAndroid Build Coastguard Worker
2262*8975f5c5SAndroid Build Coastguard Worker ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
2263*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(index);
2264*8975f5c5SAndroid Build Coastguard Worker
2265*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2266*8975f5c5SAndroid Build Coastguard Worker
2267*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
2268*8975f5c5SAndroid Build Coastguard Worker
2269*8975f5c5SAndroid Build Coastguard Worker // Mark the appropriate init flag.
2270*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
2271*8975f5c5SAndroid Build Coastguard Worker
2272*8975f5c5SAndroid Build Coastguard Worker static_assert(DIRTY_BIT_COLOR_ATTACHMENT_MAX <= DIRTY_BIT_DEPTH_ATTACHMENT);
2273*8975f5c5SAndroid Build Coastguard Worker static_assert(DIRTY_BIT_COLOR_ATTACHMENT_MAX <= DIRTY_BIT_STENCIL_ATTACHMENT);
2274*8975f5c5SAndroid Build Coastguard Worker
2275*8975f5c5SAndroid Build Coastguard Worker // Update component type mask, mFloat32ColorAttachmentBits,
2276*8975f5c5SAndroid Build Coastguard Worker // and mSharedExponentColorAttachmentBits cache
2277*8975f5c5SAndroid Build Coastguard Worker if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
2278*8975f5c5SAndroid Build Coastguard Worker {
2279*8975f5c5SAndroid Build Coastguard Worker const size_t colorIndex = index - DIRTY_BIT_COLOR_ATTACHMENT_0;
2280*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndex < mState.mColorAttachments.size());
2281*8975f5c5SAndroid Build Coastguard Worker SetComponentTypeMask(
2282*8975f5c5SAndroid Build Coastguard Worker GetAttachmentComponentType(attachment->getFormat().info->componentType), colorIndex,
2283*8975f5c5SAndroid Build Coastguard Worker &mState.mDrawBufferTypeMask);
2284*8975f5c5SAndroid Build Coastguard Worker updateFloat32AndSharedExponentColorAttachmentBits(colorIndex, attachment->getFormat().info);
2285*8975f5c5SAndroid Build Coastguard Worker }
2286*8975f5c5SAndroid Build Coastguard Worker }
2287*8975f5c5SAndroid Build Coastguard Worker
getAttachmentFromSubjectIndex(angle::SubjectIndex index)2288*8975f5c5SAndroid Build Coastguard Worker FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
2289*8975f5c5SAndroid Build Coastguard Worker {
2290*8975f5c5SAndroid Build Coastguard Worker switch (index)
2291*8975f5c5SAndroid Build Coastguard Worker {
2292*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEPTH_ATTACHMENT:
2293*8975f5c5SAndroid Build Coastguard Worker return &mState.mDepthAttachment;
2294*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_STENCIL_ATTACHMENT:
2295*8975f5c5SAndroid Build Coastguard Worker return &mState.mStencilAttachment;
2296*8975f5c5SAndroid Build Coastguard Worker default:
2297*8975f5c5SAndroid Build Coastguard Worker size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
2298*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorIndex < mState.mColorAttachments.size());
2299*8975f5c5SAndroid Build Coastguard Worker return &mState.mColorAttachments[colorIndex];
2300*8975f5c5SAndroid Build Coastguard Worker }
2301*8975f5c5SAndroid Build Coastguard Worker }
2302*8975f5c5SAndroid Build Coastguard Worker
formsRenderingFeedbackLoopWith(const Context * context) const2303*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
2304*8975f5c5SAndroid Build Coastguard Worker {
2305*8975f5c5SAndroid Build Coastguard Worker const State &glState = context->getState();
2306*8975f5c5SAndroid Build Coastguard Worker const ProgramExecutable *executable = glState.getLinkedProgramExecutable(context);
2307*8975f5c5SAndroid Build Coastguard Worker
2308*8975f5c5SAndroid Build Coastguard Worker // In some error cases there may be no bound program or executable.
2309*8975f5c5SAndroid Build Coastguard Worker if (!executable)
2310*8975f5c5SAndroid Build Coastguard Worker return false;
2311*8975f5c5SAndroid Build Coastguard Worker
2312*8975f5c5SAndroid Build Coastguard Worker const ActiveTextureMask &activeTextures = executable->getActiveSamplersMask();
2313*8975f5c5SAndroid Build Coastguard Worker const ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes();
2314*8975f5c5SAndroid Build Coastguard Worker
2315*8975f5c5SAndroid Build Coastguard Worker for (size_t textureIndex : activeTextures)
2316*8975f5c5SAndroid Build Coastguard Worker {
2317*8975f5c5SAndroid Build Coastguard Worker unsigned int uintIndex = static_cast<unsigned int>(textureIndex);
2318*8975f5c5SAndroid Build Coastguard Worker Texture *texture = glState.getSamplerTexture(uintIndex, textureTypes[textureIndex]);
2319*8975f5c5SAndroid Build Coastguard Worker const Sampler *sampler = glState.getSampler(uintIndex);
2320*8975f5c5SAndroid Build Coastguard Worker if (texture && texture->isSamplerComplete(context, sampler) &&
2321*8975f5c5SAndroid Build Coastguard Worker texture->isBoundToFramebuffer(mState.mFramebufferSerial))
2322*8975f5c5SAndroid Build Coastguard Worker {
2323*8975f5c5SAndroid Build Coastguard Worker // Check for level overlap.
2324*8975f5c5SAndroid Build Coastguard Worker for (const FramebufferAttachment &attachment : mState.mColorAttachments)
2325*8975f5c5SAndroid Build Coastguard Worker {
2326*8975f5c5SAndroid Build Coastguard Worker if (AttachmentOverlapsWithTexture(attachment, texture, sampler))
2327*8975f5c5SAndroid Build Coastguard Worker {
2328*8975f5c5SAndroid Build Coastguard Worker return true;
2329*8975f5c5SAndroid Build Coastguard Worker }
2330*8975f5c5SAndroid Build Coastguard Worker }
2331*8975f5c5SAndroid Build Coastguard Worker
2332*8975f5c5SAndroid Build Coastguard Worker if (AttachmentOverlapsWithTexture(mState.mDepthAttachment, texture, sampler))
2333*8975f5c5SAndroid Build Coastguard Worker {
2334*8975f5c5SAndroid Build Coastguard Worker return true;
2335*8975f5c5SAndroid Build Coastguard Worker }
2336*8975f5c5SAndroid Build Coastguard Worker
2337*8975f5c5SAndroid Build Coastguard Worker if (AttachmentOverlapsWithTexture(mState.mStencilAttachment, texture, sampler))
2338*8975f5c5SAndroid Build Coastguard Worker {
2339*8975f5c5SAndroid Build Coastguard Worker return true;
2340*8975f5c5SAndroid Build Coastguard Worker }
2341*8975f5c5SAndroid Build Coastguard Worker }
2342*8975f5c5SAndroid Build Coastguard Worker }
2343*8975f5c5SAndroid Build Coastguard Worker
2344*8975f5c5SAndroid Build Coastguard Worker return false;
2345*8975f5c5SAndroid Build Coastguard Worker }
2346*8975f5c5SAndroid Build Coastguard Worker
formsCopyingFeedbackLoopWith(TextureID copyTextureID,GLint copyTextureLevel,GLint copyTextureLayer) const2347*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID,
2348*8975f5c5SAndroid Build Coastguard Worker GLint copyTextureLevel,
2349*8975f5c5SAndroid Build Coastguard Worker GLint copyTextureLayer) const
2350*8975f5c5SAndroid Build Coastguard Worker {
2351*8975f5c5SAndroid Build Coastguard Worker if (mState.isDefault())
2352*8975f5c5SAndroid Build Coastguard Worker {
2353*8975f5c5SAndroid Build Coastguard Worker // It seems impossible to form a texture copying feedback loop with the default FBO.
2354*8975f5c5SAndroid Build Coastguard Worker return false;
2355*8975f5c5SAndroid Build Coastguard Worker }
2356*8975f5c5SAndroid Build Coastguard Worker
2357*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *readAttachment = getReadColorAttachment();
2358*8975f5c5SAndroid Build Coastguard Worker ASSERT(readAttachment);
2359*8975f5c5SAndroid Build Coastguard Worker
2360*8975f5c5SAndroid Build Coastguard Worker if (readAttachment->isTextureWithId(copyTextureID))
2361*8975f5c5SAndroid Build Coastguard Worker {
2362*8975f5c5SAndroid Build Coastguard Worker const auto &imageIndex = readAttachment->getTextureImageIndex();
2363*8975f5c5SAndroid Build Coastguard Worker if (imageIndex.getLevelIndex() == copyTextureLevel)
2364*8975f5c5SAndroid Build Coastguard Worker {
2365*8975f5c5SAndroid Build Coastguard Worker // Check 3D/Array texture layers.
2366*8975f5c5SAndroid Build Coastguard Worker return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2367*8975f5c5SAndroid Build Coastguard Worker imageIndex.getLayerIndex() == copyTextureLayer;
2368*8975f5c5SAndroid Build Coastguard Worker }
2369*8975f5c5SAndroid Build Coastguard Worker }
2370*8975f5c5SAndroid Build Coastguard Worker return false;
2371*8975f5c5SAndroid Build Coastguard Worker }
2372*8975f5c5SAndroid Build Coastguard Worker
getDefaultWidth() const2373*8975f5c5SAndroid Build Coastguard Worker GLint Framebuffer::getDefaultWidth() const
2374*8975f5c5SAndroid Build Coastguard Worker {
2375*8975f5c5SAndroid Build Coastguard Worker return mState.getDefaultWidth();
2376*8975f5c5SAndroid Build Coastguard Worker }
2377*8975f5c5SAndroid Build Coastguard Worker
getDefaultHeight() const2378*8975f5c5SAndroid Build Coastguard Worker GLint Framebuffer::getDefaultHeight() const
2379*8975f5c5SAndroid Build Coastguard Worker {
2380*8975f5c5SAndroid Build Coastguard Worker return mState.getDefaultHeight();
2381*8975f5c5SAndroid Build Coastguard Worker }
2382*8975f5c5SAndroid Build Coastguard Worker
getDefaultSamples() const2383*8975f5c5SAndroid Build Coastguard Worker GLint Framebuffer::getDefaultSamples() const
2384*8975f5c5SAndroid Build Coastguard Worker {
2385*8975f5c5SAndroid Build Coastguard Worker return mState.getDefaultSamples();
2386*8975f5c5SAndroid Build Coastguard Worker }
2387*8975f5c5SAndroid Build Coastguard Worker
getDefaultFixedSampleLocations() const2388*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::getDefaultFixedSampleLocations() const
2389*8975f5c5SAndroid Build Coastguard Worker {
2390*8975f5c5SAndroid Build Coastguard Worker return mState.getDefaultFixedSampleLocations();
2391*8975f5c5SAndroid Build Coastguard Worker }
2392*8975f5c5SAndroid Build Coastguard Worker
getDefaultLayers() const2393*8975f5c5SAndroid Build Coastguard Worker GLint Framebuffer::getDefaultLayers() const
2394*8975f5c5SAndroid Build Coastguard Worker {
2395*8975f5c5SAndroid Build Coastguard Worker return mState.getDefaultLayers();
2396*8975f5c5SAndroid Build Coastguard Worker }
2397*8975f5c5SAndroid Build Coastguard Worker
getFlipY() const2398*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::getFlipY() const
2399*8975f5c5SAndroid Build Coastguard Worker {
2400*8975f5c5SAndroid Build Coastguard Worker return mState.getFlipY();
2401*8975f5c5SAndroid Build Coastguard Worker }
2402*8975f5c5SAndroid Build Coastguard Worker
setDefaultWidth(const Context * context,GLint defaultWidth)2403*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
2404*8975f5c5SAndroid Build Coastguard Worker {
2405*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultWidth = defaultWidth;
2406*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
2407*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2408*8975f5c5SAndroid Build Coastguard Worker }
2409*8975f5c5SAndroid Build Coastguard Worker
setDefaultHeight(const Context * context,GLint defaultHeight)2410*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
2411*8975f5c5SAndroid Build Coastguard Worker {
2412*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultHeight = defaultHeight;
2413*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
2414*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2415*8975f5c5SAndroid Build Coastguard Worker }
2416*8975f5c5SAndroid Build Coastguard Worker
setDefaultSamples(const Context * context,GLint defaultSamples)2417*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
2418*8975f5c5SAndroid Build Coastguard Worker {
2419*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultSamples = defaultSamples;
2420*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
2421*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2422*8975f5c5SAndroid Build Coastguard Worker }
2423*8975f5c5SAndroid Build Coastguard Worker
setDefaultFixedSampleLocations(const Context * context,bool defaultFixedSampleLocations)2424*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2425*8975f5c5SAndroid Build Coastguard Worker bool defaultFixedSampleLocations)
2426*8975f5c5SAndroid Build Coastguard Worker {
2427*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2428*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
2429*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2430*8975f5c5SAndroid Build Coastguard Worker }
2431*8975f5c5SAndroid Build Coastguard Worker
setDefaultLayers(GLint defaultLayers)2432*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setDefaultLayers(GLint defaultLayers)
2433*8975f5c5SAndroid Build Coastguard Worker {
2434*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultLayers = defaultLayers;
2435*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2436*8975f5c5SAndroid Build Coastguard Worker }
2437*8975f5c5SAndroid Build Coastguard Worker
setFlipY(bool flipY)2438*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setFlipY(bool flipY)
2439*8975f5c5SAndroid Build Coastguard Worker {
2440*8975f5c5SAndroid Build Coastguard Worker mState.mFlipY = flipY;
2441*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_FLIP_Y);
2442*8975f5c5SAndroid Build Coastguard Worker invalidateCompletenessCache();
2443*8975f5c5SAndroid Build Coastguard Worker }
2444*8975f5c5SAndroid Build Coastguard Worker
getNumViews() const2445*8975f5c5SAndroid Build Coastguard Worker GLsizei Framebuffer::getNumViews() const
2446*8975f5c5SAndroid Build Coastguard Worker {
2447*8975f5c5SAndroid Build Coastguard Worker return mState.getNumViews();
2448*8975f5c5SAndroid Build Coastguard Worker }
2449*8975f5c5SAndroid Build Coastguard Worker
getBaseViewIndex() const2450*8975f5c5SAndroid Build Coastguard Worker GLint Framebuffer::getBaseViewIndex() const
2451*8975f5c5SAndroid Build Coastguard Worker {
2452*8975f5c5SAndroid Build Coastguard Worker return mState.getBaseViewIndex();
2453*8975f5c5SAndroid Build Coastguard Worker }
2454*8975f5c5SAndroid Build Coastguard Worker
isMultiview() const2455*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::isMultiview() const
2456*8975f5c5SAndroid Build Coastguard Worker {
2457*8975f5c5SAndroid Build Coastguard Worker return mState.isMultiview();
2458*8975f5c5SAndroid Build Coastguard Worker }
2459*8975f5c5SAndroid Build Coastguard Worker
readDisallowedByMultiview() const2460*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::readDisallowedByMultiview() const
2461*8975f5c5SAndroid Build Coastguard Worker {
2462*8975f5c5SAndroid Build Coastguard Worker return (mState.isMultiview() && mState.getNumViews() > 1);
2463*8975f5c5SAndroid Build Coastguard Worker }
2464*8975f5c5SAndroid Build Coastguard Worker
ensureClearAttachmentsInitialized(const Context * context,GLbitfield mask)2465*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2466*8975f5c5SAndroid Build Coastguard Worker GLbitfield mask)
2467*8975f5c5SAndroid Build Coastguard Worker {
2468*8975f5c5SAndroid Build Coastguard Worker const auto &glState = context->getState();
2469*8975f5c5SAndroid Build Coastguard Worker if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2470*8975f5c5SAndroid Build Coastguard Worker {
2471*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2472*8975f5c5SAndroid Build Coastguard Worker }
2473*8975f5c5SAndroid Build Coastguard Worker
2474*8975f5c5SAndroid Build Coastguard Worker const DepthStencilState &depthStencil = glState.getDepthStencilState();
2475*8975f5c5SAndroid Build Coastguard Worker
2476*8975f5c5SAndroid Build Coastguard Worker bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !glState.allActiveDrawBufferChannelsMasked();
2477*8975f5c5SAndroid Build Coastguard Worker bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !depthStencil.isDepthMaskedOut();
2478*8975f5c5SAndroid Build Coastguard Worker bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 &&
2479*8975f5c5SAndroid Build Coastguard Worker !depthStencil.isStencilMaskedOut(getStencilBitCount());
2480*8975f5c5SAndroid Build Coastguard Worker
2481*8975f5c5SAndroid Build Coastguard Worker if (!color && !depth && !stencil)
2482*8975f5c5SAndroid Build Coastguard Worker {
2483*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2484*8975f5c5SAndroid Build Coastguard Worker }
2485*8975f5c5SAndroid Build Coastguard Worker
2486*8975f5c5SAndroid Build Coastguard Worker if (partialClearNeedsInit(context, color, depth, stencil))
2487*8975f5c5SAndroid Build Coastguard Worker {
2488*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2489*8975f5c5SAndroid Build Coastguard Worker }
2490*8975f5c5SAndroid Build Coastguard Worker
2491*8975f5c5SAndroid Build Coastguard Worker // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2492*8975f5c5SAndroid Build Coastguard Worker // still be marked initialized. This simplifies design, allowing this method to be called before
2493*8975f5c5SAndroid Build Coastguard Worker // the clear.
2494*8975f5c5SAndroid Build Coastguard Worker DrawBufferMask clearedColorAttachments =
2495*8975f5c5SAndroid Build Coastguard Worker color ? mState.getEnabledDrawBuffers() : DrawBufferMask();
2496*8975f5c5SAndroid Build Coastguard Worker markAttachmentsInitialized(clearedColorAttachments, depth, stencil);
2497*8975f5c5SAndroid Build Coastguard Worker
2498*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2499*8975f5c5SAndroid Build Coastguard Worker }
2500*8975f5c5SAndroid Build Coastguard Worker
ensureClearBufferAttachmentsInitialized(const Context * context,GLenum buffer,GLint drawbuffer)2501*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2502*8975f5c5SAndroid Build Coastguard Worker GLenum buffer,
2503*8975f5c5SAndroid Build Coastguard Worker GLint drawbuffer)
2504*8975f5c5SAndroid Build Coastguard Worker {
2505*8975f5c5SAndroid Build Coastguard Worker if (!context->isRobustResourceInitEnabled() ||
2506*8975f5c5SAndroid Build Coastguard Worker context->getState().isRasterizerDiscardEnabled() ||
2507*8975f5c5SAndroid Build Coastguard Worker context->isClearBufferMaskedOut(buffer, drawbuffer, getStencilBitCount()) ||
2508*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.none())
2509*8975f5c5SAndroid Build Coastguard Worker {
2510*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2511*8975f5c5SAndroid Build Coastguard Worker }
2512*8975f5c5SAndroid Build Coastguard Worker
2513*8975f5c5SAndroid Build Coastguard Worker DrawBufferMask clearColorAttachments;
2514*8975f5c5SAndroid Build Coastguard Worker bool clearDepth = false;
2515*8975f5c5SAndroid Build Coastguard Worker bool clearStencil = false;
2516*8975f5c5SAndroid Build Coastguard Worker
2517*8975f5c5SAndroid Build Coastguard Worker switch (buffer)
2518*8975f5c5SAndroid Build Coastguard Worker {
2519*8975f5c5SAndroid Build Coastguard Worker case GL_COLOR:
2520*8975f5c5SAndroid Build Coastguard Worker {
2521*8975f5c5SAndroid Build Coastguard Worker ASSERT(drawbuffer < static_cast<GLint>(mState.mColorAttachments.size()));
2522*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[drawbuffer])
2523*8975f5c5SAndroid Build Coastguard Worker {
2524*8975f5c5SAndroid Build Coastguard Worker clearColorAttachments.set(drawbuffer);
2525*8975f5c5SAndroid Build Coastguard Worker }
2526*8975f5c5SAndroid Build Coastguard Worker break;
2527*8975f5c5SAndroid Build Coastguard Worker }
2528*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH:
2529*8975f5c5SAndroid Build Coastguard Worker {
2530*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2531*8975f5c5SAndroid Build Coastguard Worker {
2532*8975f5c5SAndroid Build Coastguard Worker clearDepth = true;
2533*8975f5c5SAndroid Build Coastguard Worker }
2534*8975f5c5SAndroid Build Coastguard Worker break;
2535*8975f5c5SAndroid Build Coastguard Worker }
2536*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL:
2537*8975f5c5SAndroid Build Coastguard Worker {
2538*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2539*8975f5c5SAndroid Build Coastguard Worker {
2540*8975f5c5SAndroid Build Coastguard Worker clearStencil = true;
2541*8975f5c5SAndroid Build Coastguard Worker }
2542*8975f5c5SAndroid Build Coastguard Worker break;
2543*8975f5c5SAndroid Build Coastguard Worker }
2544*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL:
2545*8975f5c5SAndroid Build Coastguard Worker {
2546*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2547*8975f5c5SAndroid Build Coastguard Worker {
2548*8975f5c5SAndroid Build Coastguard Worker clearDepth = true;
2549*8975f5c5SAndroid Build Coastguard Worker }
2550*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2551*8975f5c5SAndroid Build Coastguard Worker {
2552*8975f5c5SAndroid Build Coastguard Worker clearStencil = true;
2553*8975f5c5SAndroid Build Coastguard Worker }
2554*8975f5c5SAndroid Build Coastguard Worker break;
2555*8975f5c5SAndroid Build Coastguard Worker }
2556*8975f5c5SAndroid Build Coastguard Worker default:
2557*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2558*8975f5c5SAndroid Build Coastguard Worker break;
2559*8975f5c5SAndroid Build Coastguard Worker }
2560*8975f5c5SAndroid Build Coastguard Worker
2561*8975f5c5SAndroid Build Coastguard Worker if (partialBufferClearNeedsInit(context, buffer) &&
2562*8975f5c5SAndroid Build Coastguard Worker (clearColorAttachments.any() || clearDepth || clearStencil))
2563*8975f5c5SAndroid Build Coastguard Worker {
2564*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->ensureAttachmentsInitialized(context, clearColorAttachments, clearDepth,
2565*8975f5c5SAndroid Build Coastguard Worker clearStencil));
2566*8975f5c5SAndroid Build Coastguard Worker }
2567*8975f5c5SAndroid Build Coastguard Worker
2568*8975f5c5SAndroid Build Coastguard Worker markAttachmentsInitialized(clearColorAttachments, clearDepth, clearStencil);
2569*8975f5c5SAndroid Build Coastguard Worker
2570*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2571*8975f5c5SAndroid Build Coastguard Worker }
2572*8975f5c5SAndroid Build Coastguard Worker
ensureDrawAttachmentsInitialized(const Context * context)2573*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
2574*8975f5c5SAndroid Build Coastguard Worker {
2575*8975f5c5SAndroid Build Coastguard Worker if (!context->isRobustResourceInitEnabled())
2576*8975f5c5SAndroid Build Coastguard Worker {
2577*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2578*8975f5c5SAndroid Build Coastguard Worker }
2579*8975f5c5SAndroid Build Coastguard Worker
2580*8975f5c5SAndroid Build Coastguard Worker DrawBufferMask clearColorAttachments;
2581*8975f5c5SAndroid Build Coastguard Worker bool clearDepth = false;
2582*8975f5c5SAndroid Build Coastguard Worker bool clearStencil = false;
2583*8975f5c5SAndroid Build Coastguard Worker
2584*8975f5c5SAndroid Build Coastguard Worker // Note: we don't actually filter by the draw attachment enum. Just init everything.
2585*8975f5c5SAndroid Build Coastguard Worker for (size_t bit : mState.mResourceNeedsInit)
2586*8975f5c5SAndroid Build Coastguard Worker {
2587*8975f5c5SAndroid Build Coastguard Worker switch (bit)
2588*8975f5c5SAndroid Build Coastguard Worker {
2589*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_DEPTH_ATTACHMENT:
2590*8975f5c5SAndroid Build Coastguard Worker clearDepth = true;
2591*8975f5c5SAndroid Build Coastguard Worker break;
2592*8975f5c5SAndroid Build Coastguard Worker case DIRTY_BIT_STENCIL_ATTACHMENT:
2593*8975f5c5SAndroid Build Coastguard Worker clearStencil = true;
2594*8975f5c5SAndroid Build Coastguard Worker break;
2595*8975f5c5SAndroid Build Coastguard Worker default:
2596*8975f5c5SAndroid Build Coastguard Worker clearColorAttachments[bit] = true;
2597*8975f5c5SAndroid Build Coastguard Worker break;
2598*8975f5c5SAndroid Build Coastguard Worker }
2599*8975f5c5SAndroid Build Coastguard Worker }
2600*8975f5c5SAndroid Build Coastguard Worker
2601*8975f5c5SAndroid Build Coastguard Worker if (clearColorAttachments.any() || clearDepth || clearStencil)
2602*8975f5c5SAndroid Build Coastguard Worker {
2603*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->ensureAttachmentsInitialized(context, clearColorAttachments, clearDepth,
2604*8975f5c5SAndroid Build Coastguard Worker clearStencil));
2605*8975f5c5SAndroid Build Coastguard Worker markAttachmentsInitialized(clearColorAttachments, clearDepth, clearStencil);
2606*8975f5c5SAndroid Build Coastguard Worker }
2607*8975f5c5SAndroid Build Coastguard Worker
2608*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2609*8975f5c5SAndroid Build Coastguard Worker }
2610*8975f5c5SAndroid Build Coastguard Worker
ensureReadAttachmentsInitialized(const Context * context)2611*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
2612*8975f5c5SAndroid Build Coastguard Worker {
2613*8975f5c5SAndroid Build Coastguard Worker ASSERT(context->isRobustResourceInitEnabled());
2614*8975f5c5SAndroid Build Coastguard Worker
2615*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit.none())
2616*8975f5c5SAndroid Build Coastguard Worker {
2617*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2618*8975f5c5SAndroid Build Coastguard Worker }
2619*8975f5c5SAndroid Build Coastguard Worker
2620*8975f5c5SAndroid Build Coastguard Worker DrawBufferMask clearColorAttachments;
2621*8975f5c5SAndroid Build Coastguard Worker bool clearDepth = false;
2622*8975f5c5SAndroid Build Coastguard Worker bool clearStencil = false;
2623*8975f5c5SAndroid Build Coastguard Worker
2624*8975f5c5SAndroid Build Coastguard Worker if (mState.mReadBufferState != GL_NONE)
2625*8975f5c5SAndroid Build Coastguard Worker {
2626*8975f5c5SAndroid Build Coastguard Worker if (isDefault())
2627*8975f5c5SAndroid Build Coastguard Worker {
2628*8975f5c5SAndroid Build Coastguard Worker if (!mState.mDefaultFramebufferReadAttachmentInitialized)
2629*8975f5c5SAndroid Build Coastguard Worker {
2630*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
2631*8975f5c5SAndroid Build Coastguard Worker mState.mDefaultFramebufferReadAttachmentInitialized = true;
2632*8975f5c5SAndroid Build Coastguard Worker }
2633*8975f5c5SAndroid Build Coastguard Worker }
2634*8975f5c5SAndroid Build Coastguard Worker else
2635*8975f5c5SAndroid Build Coastguard Worker {
2636*8975f5c5SAndroid Build Coastguard Worker size_t readIndex = mState.getReadIndex();
2637*8975f5c5SAndroid Build Coastguard Worker if (mState.mResourceNeedsInit[readIndex])
2638*8975f5c5SAndroid Build Coastguard Worker {
2639*8975f5c5SAndroid Build Coastguard Worker clearColorAttachments[readIndex] = true;
2640*8975f5c5SAndroid Build Coastguard Worker }
2641*8975f5c5SAndroid Build Coastguard Worker }
2642*8975f5c5SAndroid Build Coastguard Worker }
2643*8975f5c5SAndroid Build Coastguard Worker
2644*8975f5c5SAndroid Build Coastguard Worker // Conservatively init depth since it can be read by BlitFramebuffer.
2645*8975f5c5SAndroid Build Coastguard Worker if (hasDepth() && mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2646*8975f5c5SAndroid Build Coastguard Worker {
2647*8975f5c5SAndroid Build Coastguard Worker clearDepth = true;
2648*8975f5c5SAndroid Build Coastguard Worker }
2649*8975f5c5SAndroid Build Coastguard Worker
2650*8975f5c5SAndroid Build Coastguard Worker // Conservatively init stencil since it can be read by BlitFramebuffer.
2651*8975f5c5SAndroid Build Coastguard Worker if (hasStencil() && mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2652*8975f5c5SAndroid Build Coastguard Worker {
2653*8975f5c5SAndroid Build Coastguard Worker clearStencil = true;
2654*8975f5c5SAndroid Build Coastguard Worker }
2655*8975f5c5SAndroid Build Coastguard Worker
2656*8975f5c5SAndroid Build Coastguard Worker if (clearColorAttachments.any() || clearDepth || clearStencil)
2657*8975f5c5SAndroid Build Coastguard Worker {
2658*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(mImpl->ensureAttachmentsInitialized(context, clearColorAttachments, clearDepth,
2659*8975f5c5SAndroid Build Coastguard Worker clearStencil));
2660*8975f5c5SAndroid Build Coastguard Worker markAttachmentsInitialized(clearColorAttachments, clearDepth, clearStencil);
2661*8975f5c5SAndroid Build Coastguard Worker }
2662*8975f5c5SAndroid Build Coastguard Worker
2663*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2664*8975f5c5SAndroid Build Coastguard Worker }
2665*8975f5c5SAndroid Build Coastguard Worker
markAttachmentsInitialized(const DrawBufferMask & color,bool depth,bool stencil)2666*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::markAttachmentsInitialized(const DrawBufferMask &color, bool depth, bool stencil)
2667*8975f5c5SAndroid Build Coastguard Worker {
2668*8975f5c5SAndroid Build Coastguard Worker // Mark attachments as initialized.
2669*8975f5c5SAndroid Build Coastguard Worker for (auto colorIndex : color)
2670*8975f5c5SAndroid Build Coastguard Worker {
2671*8975f5c5SAndroid Build Coastguard Worker auto &colorAttachment = mState.mColorAttachments[colorIndex];
2672*8975f5c5SAndroid Build Coastguard Worker ASSERT(colorAttachment.isAttached());
2673*8975f5c5SAndroid Build Coastguard Worker colorAttachment.setInitState(InitState::Initialized);
2674*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.reset(colorIndex);
2675*8975f5c5SAndroid Build Coastguard Worker }
2676*8975f5c5SAndroid Build Coastguard Worker
2677*8975f5c5SAndroid Build Coastguard Worker if (depth && mState.mDepthAttachment.isAttached())
2678*8975f5c5SAndroid Build Coastguard Worker {
2679*8975f5c5SAndroid Build Coastguard Worker mState.mDepthAttachment.setInitState(InitState::Initialized);
2680*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2681*8975f5c5SAndroid Build Coastguard Worker }
2682*8975f5c5SAndroid Build Coastguard Worker
2683*8975f5c5SAndroid Build Coastguard Worker if (stencil && mState.mStencilAttachment.isAttached())
2684*8975f5c5SAndroid Build Coastguard Worker {
2685*8975f5c5SAndroid Build Coastguard Worker mState.mStencilAttachment.setInitState(InitState::Initialized);
2686*8975f5c5SAndroid Build Coastguard Worker mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2687*8975f5c5SAndroid Build Coastguard Worker }
2688*8975f5c5SAndroid Build Coastguard Worker }
2689*8975f5c5SAndroid Build Coastguard Worker
getDimensions() const2690*8975f5c5SAndroid Build Coastguard Worker Box Framebuffer::getDimensions() const
2691*8975f5c5SAndroid Build Coastguard Worker {
2692*8975f5c5SAndroid Build Coastguard Worker return mState.getDimensions();
2693*8975f5c5SAndroid Build Coastguard Worker }
2694*8975f5c5SAndroid Build Coastguard Worker
getExtents() const2695*8975f5c5SAndroid Build Coastguard Worker Extents Framebuffer::getExtents() const
2696*8975f5c5SAndroid Build Coastguard Worker {
2697*8975f5c5SAndroid Build Coastguard Worker return mState.getExtents();
2698*8975f5c5SAndroid Build Coastguard Worker }
2699*8975f5c5SAndroid Build Coastguard Worker
isFoveationEnabled() const2700*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::isFoveationEnabled() const
2701*8975f5c5SAndroid Build Coastguard Worker {
2702*8975f5c5SAndroid Build Coastguard Worker return (mState.mFoveationState.getFoveatedFeatureBits() & GL_FOVEATION_ENABLE_BIT_QCOM);
2703*8975f5c5SAndroid Build Coastguard Worker }
2704*8975f5c5SAndroid Build Coastguard Worker
getFoveatedFeatureBits() const2705*8975f5c5SAndroid Build Coastguard Worker GLuint Framebuffer::getFoveatedFeatureBits() const
2706*8975f5c5SAndroid Build Coastguard Worker {
2707*8975f5c5SAndroid Build Coastguard Worker return mState.mFoveationState.getFoveatedFeatureBits();
2708*8975f5c5SAndroid Build Coastguard Worker }
2709*8975f5c5SAndroid Build Coastguard Worker
setFoveatedFeatureBits(const GLuint features)2710*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setFoveatedFeatureBits(const GLuint features)
2711*8975f5c5SAndroid Build Coastguard Worker {
2712*8975f5c5SAndroid Build Coastguard Worker mState.mFoveationState.setFoveatedFeatureBits(features);
2713*8975f5c5SAndroid Build Coastguard Worker }
2714*8975f5c5SAndroid Build Coastguard Worker
isFoveationConfigured() const2715*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::isFoveationConfigured() const
2716*8975f5c5SAndroid Build Coastguard Worker {
2717*8975f5c5SAndroid Build Coastguard Worker return mState.mFoveationState.isConfigured();
2718*8975f5c5SAndroid Build Coastguard Worker }
2719*8975f5c5SAndroid Build Coastguard Worker
configureFoveation()2720*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::configureFoveation()
2721*8975f5c5SAndroid Build Coastguard Worker {
2722*8975f5c5SAndroid Build Coastguard Worker mState.mFoveationState.configure();
2723*8975f5c5SAndroid Build Coastguard Worker }
2724*8975f5c5SAndroid Build Coastguard Worker
setFocalPoint(uint32_t layer,uint32_t focalPointIndex,float focalX,float focalY,float gainX,float gainY,float foveaArea)2725*8975f5c5SAndroid Build Coastguard Worker void Framebuffer::setFocalPoint(uint32_t layer,
2726*8975f5c5SAndroid Build Coastguard Worker uint32_t focalPointIndex,
2727*8975f5c5SAndroid Build Coastguard Worker float focalX,
2728*8975f5c5SAndroid Build Coastguard Worker float focalY,
2729*8975f5c5SAndroid Build Coastguard Worker float gainX,
2730*8975f5c5SAndroid Build Coastguard Worker float gainY,
2731*8975f5c5SAndroid Build Coastguard Worker float foveaArea)
2732*8975f5c5SAndroid Build Coastguard Worker {
2733*8975f5c5SAndroid Build Coastguard Worker gl::FocalPoint newFocalPoint(focalX, focalY, gainX, gainY, foveaArea);
2734*8975f5c5SAndroid Build Coastguard Worker if (mState.mFoveationState.getFocalPoint(layer, focalPointIndex) == newFocalPoint)
2735*8975f5c5SAndroid Build Coastguard Worker {
2736*8975f5c5SAndroid Build Coastguard Worker // Nothing to do, early out.
2737*8975f5c5SAndroid Build Coastguard Worker return;
2738*8975f5c5SAndroid Build Coastguard Worker }
2739*8975f5c5SAndroid Build Coastguard Worker
2740*8975f5c5SAndroid Build Coastguard Worker mState.mFoveationState.setFocalPoint(layer, focalPointIndex, newFocalPoint);
2741*8975f5c5SAndroid Build Coastguard Worker mState.mFoveationState.setFoveatedFeatureBits(GL_FOVEATION_ENABLE_BIT_QCOM);
2742*8975f5c5SAndroid Build Coastguard Worker mDirtyBits.set(DIRTY_BIT_FOVEATION);
2743*8975f5c5SAndroid Build Coastguard Worker onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
2744*8975f5c5SAndroid Build Coastguard Worker }
2745*8975f5c5SAndroid Build Coastguard Worker
getFocalPoint(uint32_t layer,uint32_t focalPoint) const2746*8975f5c5SAndroid Build Coastguard Worker const FocalPoint &Framebuffer::getFocalPoint(uint32_t layer, uint32_t focalPoint) const
2747*8975f5c5SAndroid Build Coastguard Worker {
2748*8975f5c5SAndroid Build Coastguard Worker return mState.mFoveationState.getFocalPoint(layer, focalPoint);
2749*8975f5c5SAndroid Build Coastguard Worker }
2750*8975f5c5SAndroid Build Coastguard Worker
getSupportedFoveationFeatures() const2751*8975f5c5SAndroid Build Coastguard Worker GLuint Framebuffer::getSupportedFoveationFeatures() const
2752*8975f5c5SAndroid Build Coastguard Worker {
2753*8975f5c5SAndroid Build Coastguard Worker return mState.mFoveationState.getSupportedFoveationFeatures();
2754*8975f5c5SAndroid Build Coastguard Worker }
2755*8975f5c5SAndroid Build Coastguard Worker
partialBufferClearNeedsInit(const Context * context,GLenum bufferType)2756*8975f5c5SAndroid Build Coastguard Worker bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2757*8975f5c5SAndroid Build Coastguard Worker {
2758*8975f5c5SAndroid Build Coastguard Worker if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2759*8975f5c5SAndroid Build Coastguard Worker {
2760*8975f5c5SAndroid Build Coastguard Worker return false;
2761*8975f5c5SAndroid Build Coastguard Worker }
2762*8975f5c5SAndroid Build Coastguard Worker
2763*8975f5c5SAndroid Build Coastguard Worker switch (bufferType)
2764*8975f5c5SAndroid Build Coastguard Worker {
2765*8975f5c5SAndroid Build Coastguard Worker case GL_COLOR:
2766*8975f5c5SAndroid Build Coastguard Worker return partialClearNeedsInit(context, true, false, false);
2767*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH:
2768*8975f5c5SAndroid Build Coastguard Worker return partialClearNeedsInit(context, false, true, false);
2769*8975f5c5SAndroid Build Coastguard Worker case GL_STENCIL:
2770*8975f5c5SAndroid Build Coastguard Worker return partialClearNeedsInit(context, false, false, true);
2771*8975f5c5SAndroid Build Coastguard Worker case GL_DEPTH_STENCIL:
2772*8975f5c5SAndroid Build Coastguard Worker return partialClearNeedsInit(context, false, true, true);
2773*8975f5c5SAndroid Build Coastguard Worker default:
2774*8975f5c5SAndroid Build Coastguard Worker UNREACHABLE();
2775*8975f5c5SAndroid Build Coastguard Worker return false;
2776*8975f5c5SAndroid Build Coastguard Worker }
2777*8975f5c5SAndroid Build Coastguard Worker }
2778*8975f5c5SAndroid Build Coastguard Worker
getPixelLocalStorage(const Context * context)2779*8975f5c5SAndroid Build Coastguard Worker PixelLocalStorage &Framebuffer::getPixelLocalStorage(const Context *context)
2780*8975f5c5SAndroid Build Coastguard Worker {
2781*8975f5c5SAndroid Build Coastguard Worker ASSERT(id().value != 0);
2782*8975f5c5SAndroid Build Coastguard Worker if (!mPixelLocalStorage)
2783*8975f5c5SAndroid Build Coastguard Worker {
2784*8975f5c5SAndroid Build Coastguard Worker mPixelLocalStorage = PixelLocalStorage::Make(context);
2785*8975f5c5SAndroid Build Coastguard Worker }
2786*8975f5c5SAndroid Build Coastguard Worker return *mPixelLocalStorage.get();
2787*8975f5c5SAndroid Build Coastguard Worker }
2788*8975f5c5SAndroid Build Coastguard Worker
detachPixelLocalStorage()2789*8975f5c5SAndroid Build Coastguard Worker std::unique_ptr<PixelLocalStorage> Framebuffer::detachPixelLocalStorage()
2790*8975f5c5SAndroid Build Coastguard Worker {
2791*8975f5c5SAndroid Build Coastguard Worker return std::move(mPixelLocalStorage);
2792*8975f5c5SAndroid Build Coastguard Worker }
2793*8975f5c5SAndroid Build Coastguard Worker
syncAllDrawAttachmentState(const Context * context,Command command) const2794*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::syncAllDrawAttachmentState(const Context *context, Command command) const
2795*8975f5c5SAndroid Build Coastguard Worker {
2796*8975f5c5SAndroid Build Coastguard Worker for (size_t drawbufferIdx = 0; drawbufferIdx < mState.getDrawBufferCount(); ++drawbufferIdx)
2797*8975f5c5SAndroid Build Coastguard Worker {
2798*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncAttachmentState(context, command, mState.getDrawBuffer(drawbufferIdx)));
2799*8975f5c5SAndroid Build Coastguard Worker }
2800*8975f5c5SAndroid Build Coastguard Worker
2801*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncAttachmentState(context, command, mState.getDepthAttachment()));
2802*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(syncAttachmentState(context, command, mState.getStencilAttachment()));
2803*8975f5c5SAndroid Build Coastguard Worker
2804*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2805*8975f5c5SAndroid Build Coastguard Worker }
2806*8975f5c5SAndroid Build Coastguard Worker
syncAttachmentState(const Context * context,Command command,const FramebufferAttachment * attachment) const2807*8975f5c5SAndroid Build Coastguard Worker angle::Result Framebuffer::syncAttachmentState(const Context *context,
2808*8975f5c5SAndroid Build Coastguard Worker Command command,
2809*8975f5c5SAndroid Build Coastguard Worker const FramebufferAttachment *attachment) const
2810*8975f5c5SAndroid Build Coastguard Worker {
2811*8975f5c5SAndroid Build Coastguard Worker if (!attachment)
2812*8975f5c5SAndroid Build Coastguard Worker {
2813*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2814*8975f5c5SAndroid Build Coastguard Worker }
2815*8975f5c5SAndroid Build Coastguard Worker
2816*8975f5c5SAndroid Build Coastguard Worker // Only texture attachments can sync state. Renderbuffer and Surface attachments are always
2817*8975f5c5SAndroid Build Coastguard Worker // synchronized.
2818*8975f5c5SAndroid Build Coastguard Worker if (attachment->type() == GL_TEXTURE)
2819*8975f5c5SAndroid Build Coastguard Worker {
2820*8975f5c5SAndroid Build Coastguard Worker Texture *texture = attachment->getTexture();
2821*8975f5c5SAndroid Build Coastguard Worker if (texture->hasAnyDirtyBitExcludingBoundAsAttachmentBit())
2822*8975f5c5SAndroid Build Coastguard Worker {
2823*8975f5c5SAndroid Build Coastguard Worker ANGLE_TRY(texture->syncState(context, command));
2824*8975f5c5SAndroid Build Coastguard Worker }
2825*8975f5c5SAndroid Build Coastguard Worker }
2826*8975f5c5SAndroid Build Coastguard Worker
2827*8975f5c5SAndroid Build Coastguard Worker return angle::Result::Continue;
2828*8975f5c5SAndroid Build Coastguard Worker }
2829*8975f5c5SAndroid Build Coastguard Worker } // namespace gl
2830