xref: /aosp_15_r20/external/angle/src/libANGLE/Framebuffer.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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