xref: /aosp_15_r20/external/angle/src/libANGLE/Framebuffer.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 // Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9 
10 #ifndef LIBANGLE_FRAMEBUFFER_H_
11 #define LIBANGLE_FRAMEBUFFER_H_
12 
13 #include <vector>
14 
15 #include "common/FixedVector.h"
16 #include "common/Optional.h"
17 #include "common/angleutils.h"
18 #include "libANGLE/Constants.h"
19 #include "libANGLE/Debug.h"
20 #include "libANGLE/Error.h"
21 #include "libANGLE/FramebufferAttachment.h"
22 #include "libANGLE/Observer.h"
23 #include "libANGLE/RefCountObject.h"
24 #include "libANGLE/State.h"
25 #include "libANGLE/angletypes.h"
26 
27 namespace rx
28 {
29 class GLImplFactory;
30 class FramebufferImpl;
31 class RenderbufferImpl;
32 class SurfaceImpl;
33 }  // namespace rx
34 
35 namespace egl
36 {
37 class Display;
38 class Surface;
39 }  // namespace egl
40 
41 namespace gl
42 {
43 struct Caps;
44 class Context;
45 struct Extensions;
46 class Framebuffer;
47 class ImageIndex;
48 class PixelLocalStorage;
49 class Renderbuffer;
50 class TextureCapsMap;
51 
52 struct FramebufferStatus
53 {
54     bool isComplete() const;
55 
56     static FramebufferStatus Complete();
57     static FramebufferStatus Incomplete(GLenum status, const char *reason);
58 
59     GLenum status      = GL_FRAMEBUFFER_COMPLETE;
60     const char *reason = nullptr;
61 };
62 
63 class FramebufferState final : angle::NonCopyable
64 {
65   public:
66     explicit FramebufferState(rx::UniqueSerial serial);
67     FramebufferState(const Caps &caps, FramebufferID id, rx::UniqueSerial serial);
68     ~FramebufferState();
69 
70     const std::string &getLabel() const;
71     uint32_t getReadIndex() const;
72 
73     const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
74     const FramebufferAttachment *getReadAttachment() const;
75     const FramebufferAttachment *getFirstNonNullAttachment() const;
76     const FramebufferAttachment *getFirstColorAttachment() const;
77     const FramebufferAttachment *getDepthOrStencilAttachment() const;
78     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
79     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
80     const FramebufferAttachment *getDepthAttachment() const;
81     const FramebufferAttachment *getStencilAttachment() const;
82     const FramebufferAttachment *getDepthStencilAttachment() const;
83     const FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const;
84 
getDrawBufferStates()85     const DrawBuffersVector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
getEnabledDrawBuffers()86     DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
getReadBufferState()87     GLenum getReadBufferState() const { return mReadBufferState; }
88 
getColorAttachments()89     const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const
90     {
91         return mColorAttachments;
92     }
getColorAttachmentsMask()93     const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; }
94 
95     const Extents getAttachmentExtentsIntersection() const;
96     bool attachmentsHaveSameDimensions() const;
97     bool hasSeparateDepthAndStencilAttachments() const;
98     bool colorAttachmentsAreUniqueImages() const;
99     Box getDimensions() const;
100     Extents getExtents() const;
101 
102     const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
103     size_t getDrawBufferCount() const;
104 
getDefaultWidth()105     GLint getDefaultWidth() const { return mDefaultWidth; }
getDefaultHeight()106     GLint getDefaultHeight() const { return mDefaultHeight; }
getDefaultSamples()107     GLint getDefaultSamples() const { return mDefaultSamples; }
getDefaultFixedSampleLocations()108     bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; }
getDefaultLayers()109     GLint getDefaultLayers() const { return mDefaultLayers; }
getFlipY()110     bool getFlipY() const { return mFlipY; }
111 
112     bool hasDepth() const;
113     bool hasStencil() const;
114     GLuint getStencilBitCount() const;
115 
116     bool hasExternalTextureAttachment() const;
117     bool hasYUVAttachment() const;
118 
119     bool isMultiview() const;
120 
getNumViews()121     ANGLE_INLINE GLsizei getNumViews() const
122     {
123         const FramebufferAttachment *attachment = getFirstNonNullAttachment();
124         if (attachment == nullptr)
125         {
126             return FramebufferAttachment::kDefaultNumViews;
127         }
128         return attachment->getNumViews();
129     }
130 
131     GLint getBaseViewIndex() const;
132 
getWriteControlMode()133     SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; }
134 
id()135     FramebufferID id() const { return mId; }
136 
137     bool isDefault() const;
138 
getSurfaceTextureOffset()139     const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
140 
getFramebufferSerial()141     rx::UniqueSerial getFramebufferSerial() const { return mFramebufferSerial; }
142 
143     bool isBoundAsDrawFramebuffer(const Context *context) const;
144 
isFoveationEnabled()145     bool isFoveationEnabled() const { return mFoveationState.isFoveated(); }
146 
getFoveationState()147     const FoveationState &getFoveationState() const { return mFoveationState; }
148 
149   private:
150     const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
151     const FramebufferAttachment *getWebGLDepthAttachment() const;
152     const FramebufferAttachment *getWebGLStencilAttachment() const;
153 
154     friend class Framebuffer;
155 
156     // The Framebuffer ID is unique to a Context.
157     // The Framebuffer UniqueSerial is unique to a Share Group.
158     FramebufferID mId;
159     rx::UniqueSerial mFramebufferSerial;
160     std::string mLabel;
161 
162     DrawBuffersVector<FramebufferAttachment> mColorAttachments;
163     FramebufferAttachment mDepthAttachment;
164     FramebufferAttachment mStencilAttachment;
165 
166     // Tracks all the color buffers attached to this FramebufferDesc
167     DrawBufferMask mColorAttachmentsMask;
168 
169     DrawBuffersVector<GLenum> mDrawBufferStates;
170     GLenum mReadBufferState;
171     DrawBufferMask mEnabledDrawBuffers;
172     ComponentTypeMask mDrawBufferTypeMask;
173 
174     GLint mDefaultWidth;
175     GLint mDefaultHeight;
176     GLint mDefaultSamples;
177     bool mDefaultFixedSampleLocations;
178     GLint mDefaultLayers;
179     bool mFlipY;
180 
181     // It's necessary to store all this extra state so we can restore attachments
182     // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
183     FramebufferAttachment mWebGLDepthStencilAttachment;
184     FramebufferAttachment mWebGLDepthAttachment;
185     FramebufferAttachment mWebGLStencilAttachment;
186     bool mWebGLDepthStencilConsistent;
187 
188     // Tracks if we need to initialize the resources for each attachment.
189     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
190 
191     bool mDefaultFramebufferReadAttachmentInitialized;
192     FramebufferAttachment mDefaultFramebufferReadAttachment;
193 
194     // EXT_sRGB_write_control
195     SrgbWriteControlMode mSrgbWriteControlMode;
196 
197     Offset mSurfaceTextureOffset;
198 
199     // GL_QCOM_framebuffer_foveated
200     FoveationState mFoveationState;
201 };
202 
203 class Framebuffer final : public angle::ObserverInterface,
204                           public LabeledObject,
205                           public angle::Subject
206 {
207   public:
208     // Constructor to build default framebuffers.
209     Framebuffer(const Context *context, rx::GLImplFactory *factory);
210     // Constructor to build application-defined framebuffers
211     Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id);
212 
213     ~Framebuffer() override;
214     void onDestroy(const Context *context);
215 
216     egl::Error setSurfaces(const Context *context,
217                            egl::Surface *surface,
218                            egl::Surface *readSurface);
219     void setReadSurface(const Context *context, egl::Surface *readSurface);
220     egl::Error unsetSurfaces(const Context *context);
221     angle::Result setLabel(const Context *context, const std::string &label) override;
222     const std::string &getLabel() const override;
223 
getImplementation()224     rx::FramebufferImpl *getImplementation() const { return mImpl; }
225 
id()226     FramebufferID id() const { return mState.mId; }
227 
228     void setAttachment(const Context *context,
229                        GLenum type,
230                        GLenum binding,
231                        const ImageIndex &textureIndex,
232                        FramebufferAttachmentObject *resource);
233     void setAttachmentMultisample(const Context *context,
234                                   GLenum type,
235                                   GLenum binding,
236                                   const ImageIndex &textureIndex,
237                                   FramebufferAttachmentObject *resource,
238                                   GLsizei samples);
239     void setAttachmentMultiview(const Context *context,
240                                 GLenum type,
241                                 GLenum binding,
242                                 const ImageIndex &textureIndex,
243                                 FramebufferAttachmentObject *resource,
244                                 GLsizei numViews,
245                                 GLint baseViewIndex);
246     void resetAttachment(const Context *context, GLenum binding);
247 
248     bool detachTexture(Context *context, TextureID texture);
249     bool detachRenderbuffer(Context *context, RenderbufferID renderbuffer);
250 
251     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
252     const FramebufferAttachment *getDepthAttachment() const;
253     const FramebufferAttachment *getStencilAttachment() const;
254     const FramebufferAttachment *getDepthStencilAttachment() const;
255     const FramebufferAttachment *getDepthOrStencilAttachment() const;
256     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
257     const FramebufferAttachment *getReadColorAttachment() const;
258     GLenum getReadColorAttachmentType() const;
259     const FramebufferAttachment *getFirstColorAttachment() const;
260     const FramebufferAttachment *getFirstNonNullAttachment() const;
261 
getColorAttachments()262     const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const
263     {
264         return mState.mColorAttachments;
265     }
266 
getState()267     const FramebufferState &getState() const { return mState; }
268 
269     const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
270     bool isMultiview() const;
271     bool readDisallowedByMultiview() const;
272     GLsizei getNumViews() const;
273     GLint getBaseViewIndex() const;
274     Extents getExtents() const;
275 
276     size_t getDrawbufferStateCount() const;
277     GLenum getDrawBufferState(size_t drawBuffer) const;
278     const DrawBuffersVector<GLenum> &getDrawBufferStates() const;
279     void setDrawBuffers(size_t count, const GLenum *buffers);
280     const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
281     ComponentType getDrawbufferWriteType(size_t drawBuffer) const;
282     ComponentTypeMask getDrawBufferTypeMask() const;
283     DrawBufferMask getDrawBufferMask() const;
284     bool hasEnabledDrawBuffer() const;
285 
286     GLenum getReadBufferState() const;
287     void setReadBuffer(GLenum buffer);
288 
getNumColorAttachments()289     size_t getNumColorAttachments() const { return mState.mColorAttachments.size(); }
hasDepth()290     bool hasDepth() const { return mState.hasDepth(); }
hasStencil()291     bool hasStencil() const { return mState.hasStencil(); }
getStencilBitCount()292     GLuint getStencilBitCount() const { return mState.getStencilBitCount(); }
293 
hasExternalTextureAttachment()294     bool hasExternalTextureAttachment() const { return mState.hasExternalTextureAttachment(); }
hasYUVAttachment()295     bool hasYUVAttachment() const { return mState.hasYUVAttachment(); }
296 
297     // This method calls checkStatus.
298     int getSamples(const Context *context) const;
299     int getReadBufferResourceSamples(const Context *context) const;
300 
301     angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const;
302 
303     GLint getDefaultWidth() const;
304     GLint getDefaultHeight() const;
305     GLint getDefaultSamples() const;
306     bool getDefaultFixedSampleLocations() const;
307     GLint getDefaultLayers() const;
308     bool getFlipY() const;
309     void setDefaultWidth(const Context *context, GLint defaultWidth);
310     void setDefaultHeight(const Context *context, GLint defaultHeight);
311     void setDefaultSamples(const Context *context, GLint defaultSamples);
312     void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations);
313     void setDefaultLayers(GLint defaultLayers);
314     void setFlipY(bool flipY);
315 
316     bool isFoveationEnabled() const;
317     void setFoveatedFeatureBits(const GLuint features);
318     GLuint getFoveatedFeatureBits() const;
319     bool isFoveationConfigured() const;
320     void configureFoveation();
321     void setFocalPoint(uint32_t layer,
322                        uint32_t focalPointIndex,
323                        float focalX,
324                        float focalY,
325                        float gainX,
326                        float gainY,
327                        float foveaArea);
328     const FocalPoint &getFocalPoint(uint32_t layer, uint32_t focalPoint) const;
329     GLuint getSupportedFoveationFeatures() const;
hasAnyAttachmentChanged()330     bool hasAnyAttachmentChanged() const { return mAttachmentChangedAfterEnablingFoveation; }
331 
332     void invalidateCompletenessCache();
cachedStatusValid()333     ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
334 
checkStatus(const Context * context)335     ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
336     {
337         // The default framebuffer is always complete except when it is surfaceless in which
338         // case it is always unsupported.
339         ASSERT(!isDefault() || mCachedStatus.valid());
340         if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid()))
341         {
342             return mCachedStatus.value();
343         }
344 
345         return checkStatusImpl(context);
346     }
347 
348     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
isComplete(const Context * context)349     ANGLE_INLINE bool isComplete(const Context *context) const
350     {
351         return checkStatus(context).isComplete();
352     }
353 
354     bool hasValidDepthStencil() const;
355 
356     // Returns the offset into the texture backing the default framebuffer's surface if any. Returns
357     // zero offset otherwise.  The renderer will apply the offset to scissor and viewport rects used
358     // for draws, clears, and blits.
359     const Offset &getSurfaceTextureOffset() const;
360 
361     angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
362     angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
363     angle::Result invalidateSub(const Context *context,
364                                 size_t count,
365                                 const GLenum *attachments,
366                                 const Rectangle &area);
367 
368     angle::Result clear(const Context *context, GLbitfield mask);
369     angle::Result clearBufferfv(const Context *context,
370                                 GLenum buffer,
371                                 GLint drawbuffer,
372                                 const GLfloat *values);
373     angle::Result clearBufferuiv(const Context *context,
374                                  GLenum buffer,
375                                  GLint drawbuffer,
376                                  const GLuint *values);
377     angle::Result clearBufferiv(const Context *context,
378                                 GLenum buffer,
379                                 GLint drawbuffer,
380                                 const GLint *values);
381     angle::Result clearBufferfi(const Context *context,
382                                 GLenum buffer,
383                                 GLint drawbuffer,
384                                 GLfloat depth,
385                                 GLint stencil);
386 
387     GLenum getImplementationColorReadFormat(const Context *context);
388     GLenum getImplementationColorReadType(const Context *context);
389 
390     angle::Result readPixels(const Context *context,
391                              const Rectangle &area,
392                              GLenum format,
393                              GLenum type,
394                              const PixelPackState &pack,
395                              Buffer *packBuffer,
396                              void *pixels);
397 
398     angle::Result blit(const Context *context,
399                        const Rectangle &sourceArea,
400                        const Rectangle &destArea,
401                        GLbitfield mask,
402                        GLenum filter);
isDefault()403     bool isDefault() const { return mState.isDefault(); }
404 
405     enum DirtyBitType : size_t
406     {
407         DIRTY_BIT_COLOR_ATTACHMENT_0,
408         DIRTY_BIT_COLOR_ATTACHMENT_MAX =
409             DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
410         DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
411         DIRTY_BIT_STENCIL_ATTACHMENT,
412         DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
413         DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
414             DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
415         DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
416         DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
417         DIRTY_BIT_DRAW_BUFFERS,
418         DIRTY_BIT_READ_BUFFER,
419         DIRTY_BIT_DEFAULT_WIDTH,
420         DIRTY_BIT_DEFAULT_HEIGHT,
421         DIRTY_BIT_DEFAULT_SAMPLES,
422         DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
423         DIRTY_BIT_DEFAULT_LAYERS,
424         DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
425         DIRTY_BIT_FLIP_Y,
426         DIRTY_BIT_FOVEATION,
427         DIRTY_BIT_UNKNOWN,
428         DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
429     };
430 
431     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
hasAnyDirtyBit()432     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
433 
getActiveFloat32ColorAttachmentDrawBufferMask()434     DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const
435     {
436         return mFloat32ColorAttachmentBits & getDrawBufferMask();
437     }
438 
getActiveSharedExponentColorAttachmentDrawBufferMask()439     DrawBufferMask getActiveSharedExponentColorAttachmentDrawBufferMask() const
440     {
441         return mSharedExponentColorAttachmentBits & getDrawBufferMask();
442     }
443 
hasResourceThatNeedsInit()444     bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
445 
446     angle::Result syncState(const Context *context,
447                             GLenum framebufferBinding,
448                             Command command) const;
449 
450     void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode);
451 
452     // Observer implementation
453     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
454 
455     bool formsRenderingFeedbackLoopWith(const Context *context) const;
456     bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
457                                       GLint copyTextureLevel,
458                                       GLint copyTextureLayer) const;
459 
460     angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask);
461     angle::Result ensureClearBufferAttachmentsInitialized(const Context *context,
462                                                           GLenum buffer,
463                                                           GLint drawbuffer);
464     angle::Result ensureDrawAttachmentsInitialized(const Context *context);
465 
466     // Conservatively initializes both read color and depth. Blit can access the depth buffer.
467     angle::Result ensureReadAttachmentsInitialized(const Context *context);
468     Box getDimensions() const;
469 
470     // ANGLE_shader_pixel_local_storage.
471     // Lazily creates a PixelLocalStorage object for this Framebuffer.
472     PixelLocalStorage &getPixelLocalStorage(const Context *);
473     // Returns nullptr if the pixel local storage object has not been created yet.
peekPixelLocalStorage()474     PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); }
475     // Detaches the the pixel local storage object so the Context can call deleteContextObjects().
476     std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage();
477 
478     static const FramebufferID kDefaultDrawFramebufferHandle;
479 
480   private:
481     bool detachResourceById(Context *context, GLenum resourceType, GLuint resourceId);
482     bool detachMatchingAttachment(Context *context,
483                                   FramebufferAttachment *attachment,
484                                   GLenum matchType,
485                                   GLuint matchId);
486     FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
487     const FramebufferStatus &checkStatusImpl(const Context *context) const;
488     void setAttachment(const Context *context,
489                        GLenum type,
490                        GLenum binding,
491                        const ImageIndex &textureIndex,
492                        FramebufferAttachmentObject *resource,
493                        GLsizei numViews,
494                        GLuint baseViewIndex,
495                        bool isMultiview,
496                        GLsizei samplesIn);
497     void commitWebGL1DepthStencilIfConsistent(const Context *context,
498                                               GLsizei numViews,
499                                               GLuint baseViewIndex,
500                                               bool isMultiview,
501                                               GLsizei samples);
502     void setAttachmentImpl(const Context *context,
503                            GLenum type,
504                            GLenum binding,
505                            const ImageIndex &textureIndex,
506                            FramebufferAttachmentObject *resource,
507                            GLsizei numViews,
508                            GLuint baseViewIndex,
509                            bool isMultiview,
510                            GLsizei samples);
511     void updateAttachment(const Context *context,
512                           FramebufferAttachment *attachment,
513                           size_t dirtyBit,
514                           angle::ObserverBinding *onDirtyBinding,
515                           GLenum type,
516                           GLenum binding,
517                           const ImageIndex &textureIndex,
518                           FramebufferAttachmentObject *resource,
519                           GLsizei numViews,
520                           GLuint baseViewIndex,
521                           bool isMultiview,
522                           GLsizei samples);
523 
524     void markAttachmentsInitialized(const DrawBufferMask &color, bool depth, bool stencil);
525 
526     // Checks that we have a partially masked clear:
527     // * some color channels are masked out
528     // * some stencil values are masked out
529     // * scissor test partially overlaps the framebuffer
530     bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
531     bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
532 
533     FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
534 
updateFloat32AndSharedExponentColorAttachmentBits(size_t index,const InternalFormat * format)535     ANGLE_INLINE void updateFloat32AndSharedExponentColorAttachmentBits(
536         size_t index,
537         const InternalFormat *format)
538     {
539         mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
540         mSharedExponentColorAttachmentBits.set(index, format->type == GL_UNSIGNED_INT_5_9_9_9_REV);
541     }
542 
543     angle::Result syncAllDrawAttachmentState(const Context *context, Command command) const;
544     angle::Result syncAttachmentState(const Context *context,
545                                       Command command,
546                                       const FramebufferAttachment *attachment) const;
547 
548     FramebufferState mState;
549     rx::FramebufferImpl *mImpl;
550 
551     mutable Optional<FramebufferStatus> mCachedStatus;
552     DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
553     angle::ObserverBinding mDirtyDepthAttachmentBinding;
554     angle::ObserverBinding mDirtyStencilAttachmentBinding;
555 
556     mutable DirtyBits mDirtyBits;
557     DrawBufferMask mFloat32ColorAttachmentBits;
558     DrawBufferMask mSharedExponentColorAttachmentBits;
559 
560     // The dirty bits guard is checked when we get a dependent state change message. We verify that
561     // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
562     mutable Optional<DirtyBits> mDirtyBitsGuard;
563 
564     // ANGLE_shader_pixel_local_storage
565     std::unique_ptr<PixelLocalStorage> mPixelLocalStorage;
566 
567     // QCOM_framebuffer_foveated
568     bool mAttachmentChangedAfterEnablingFoveation;
569 };
570 
571 using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>;
572 
573 }  // namespace gl
574 
575 #endif  // LIBANGLE_FRAMEBUFFER_H_
576