• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
isCompleteFramebufferStatus54     bool isComplete() const { return status == GL_FRAMEBUFFER_COMPLETE; }
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 
121     GLsizei getNumViews() const;
122 
123     GLint getBaseViewIndex() const;
124 
getWriteControlMode()125     SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; }
126 
id()127     FramebufferID id() const { return mId; }
128 
129     bool isDefault() const;
130 
getSurfaceTextureOffset()131     const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
132 
getFramebufferSerial()133     rx::UniqueSerial getFramebufferSerial() const { return mFramebufferSerial; }
134 
135     bool isBoundAsDrawFramebuffer(const Context *context) const;
136 
isFoveationEnabled()137     bool isFoveationEnabled() const { return mFoveationState.isFoveated(); }
138 
getFoveationState()139     const FoveationState &getFoveationState() const { return mFoveationState; }
140 
141   private:
142     const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
143     const FramebufferAttachment *getWebGLDepthAttachment() const;
144     const FramebufferAttachment *getWebGLStencilAttachment() const;
145 
146     friend class Framebuffer;
147 
148     // The Framebuffer ID is unique to a Context.
149     // The Framebuffer UniqueSerial is unique to a Share Group.
150     FramebufferID mId;
151     rx::UniqueSerial mFramebufferSerial;
152     std::string mLabel;
153 
154     DrawBuffersVector<FramebufferAttachment> mColorAttachments;
155     FramebufferAttachment mDepthAttachment;
156     FramebufferAttachment mStencilAttachment;
157 
158     // Tracks all the color buffers attached to this FramebufferDesc
159     DrawBufferMask mColorAttachmentsMask;
160 
161     DrawBuffersVector<GLenum> mDrawBufferStates;
162     GLenum mReadBufferState;
163     DrawBufferMask mEnabledDrawBuffers;
164     ComponentTypeMask mDrawBufferTypeMask;
165 
166     GLint mDefaultWidth;
167     GLint mDefaultHeight;
168     GLint mDefaultSamples;
169     bool mDefaultFixedSampleLocations;
170     GLint mDefaultLayers;
171     bool mFlipY;
172 
173     // It's necessary to store all this extra state so we can restore attachments
174     // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
175     FramebufferAttachment mWebGLDepthStencilAttachment;
176     FramebufferAttachment mWebGLDepthAttachment;
177     FramebufferAttachment mWebGLStencilAttachment;
178     bool mWebGLDepthStencilConsistent;
179 
180     // Tracks if we need to initialize the resources for each attachment.
181     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
182 
183     bool mDefaultFramebufferReadAttachmentInitialized;
184     FramebufferAttachment mDefaultFramebufferReadAttachment;
185 
186     // EXT_sRGB_write_control
187     SrgbWriteControlMode mSrgbWriteControlMode;
188 
189     Offset mSurfaceTextureOffset;
190 
191     // GL_QCOM_framebuffer_foveated
192     FoveationState mFoveationState;
193 };
194 
195 class Framebuffer final : public angle::ObserverInterface,
196                           public LabeledObject,
197                           public angle::Subject
198 {
199   public:
200     // Constructor to build default framebuffers.
201     Framebuffer(const Context *context, rx::GLImplFactory *factory);
202     // Constructor to build application-defined framebuffers
203     Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id);
204 
205     ~Framebuffer() override;
206     void onDestroy(const Context *context);
207 
208     egl::Error setSurfaces(const Context *context,
209                            egl::Surface *surface,
210                            egl::Surface *readSurface);
211     void setReadSurface(const Context *context, egl::Surface *readSurface);
212     egl::Error unsetSurfaces(const Context *context);
213     angle::Result setLabel(const Context *context, const std::string &label) override;
214     const std::string &getLabel() const override;
215 
getImplementation()216     rx::FramebufferImpl *getImplementation() const { return mImpl; }
217 
id()218     FramebufferID id() const { return mState.mId; }
219 
220     void setAttachment(const Context *context,
221                        GLenum type,
222                        GLenum binding,
223                        const ImageIndex &textureIndex,
224                        FramebufferAttachmentObject *resource);
225     void setAttachmentMultisample(const Context *context,
226                                   GLenum type,
227                                   GLenum binding,
228                                   const ImageIndex &textureIndex,
229                                   FramebufferAttachmentObject *resource,
230                                   GLsizei samples);
231     void setAttachmentMultiview(const Context *context,
232                                 GLenum type,
233                                 GLenum binding,
234                                 const ImageIndex &textureIndex,
235                                 FramebufferAttachmentObject *resource,
236                                 GLsizei numViews,
237                                 GLint baseViewIndex);
238     void resetAttachment(const Context *context, GLenum binding);
239 
240     bool detachTexture(Context *context, TextureID texture);
241     bool detachRenderbuffer(Context *context, RenderbufferID renderbuffer);
242 
243     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
244     const FramebufferAttachment *getDepthAttachment() const;
245     const FramebufferAttachment *getStencilAttachment() const;
246     const FramebufferAttachment *getDepthStencilAttachment() const;
247     const FramebufferAttachment *getDepthOrStencilAttachment() const;
248     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
249     const FramebufferAttachment *getReadColorAttachment() const;
250     GLenum getReadColorAttachmentType() const;
251     const FramebufferAttachment *getFirstColorAttachment() const;
252     const FramebufferAttachment *getFirstNonNullAttachment() const;
253 
getColorAttachments()254     const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const
255     {
256         return mState.mColorAttachments;
257     }
258 
getState()259     const FramebufferState &getState() const { return mState; }
260 
261     const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
262     bool isMultiview() const;
263     bool readDisallowedByMultiview() const;
getNumViews()264     ANGLE_INLINE GLsizei getNumViews() const { return mState.getNumViews(); }
265     GLint getBaseViewIndex() const;
266     Extents getExtents() const;
267 
268     size_t getDrawbufferStateCount() const;
269     GLenum getDrawBufferState(size_t drawBuffer) const;
270     const DrawBuffersVector<GLenum> &getDrawBufferStates() const;
271     void setDrawBuffers(size_t count, const GLenum *buffers);
272     const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
273     ComponentType getDrawbufferWriteType(size_t drawBuffer) const;
274     ComponentTypeMask getDrawBufferTypeMask() const;
getDrawBufferMask()275     DrawBufferMask getDrawBufferMask() const { return mState.mEnabledDrawBuffers; }
276     bool hasEnabledDrawBuffer() const;
277 
278     GLenum getReadBufferState() const;
279     void setReadBuffer(GLenum buffer);
280 
getNumColorAttachments()281     size_t getNumColorAttachments() const { return mState.mColorAttachments.size(); }
hasDepth()282     bool hasDepth() const { return mState.hasDepth(); }
hasStencil()283     bool hasStencil() const { return mState.hasStencil(); }
getStencilBitCount()284     GLuint getStencilBitCount() const { return mState.getStencilBitCount(); }
285 
hasExternalTextureAttachment()286     bool hasExternalTextureAttachment() const { return mState.hasExternalTextureAttachment(); }
hasYUVAttachment()287     bool hasYUVAttachment() const { return mState.hasYUVAttachment(); }
288 
289     // This method calls checkStatus.
290     int getSamples(const Context *context) const;
291     int getReadBufferResourceSamples(const Context *context) const;
292 
293     angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const;
294 
295     GLint getDefaultWidth() const;
296     GLint getDefaultHeight() const;
297     GLint getDefaultSamples() const;
298     bool getDefaultFixedSampleLocations() const;
299     GLint getDefaultLayers() const;
300     bool getFlipY() const;
301     void setDefaultWidth(const Context *context, GLint defaultWidth);
302     void setDefaultHeight(const Context *context, GLint defaultHeight);
303     void setDefaultSamples(const Context *context, GLint defaultSamples);
304     void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations);
305     void setDefaultLayers(GLint defaultLayers);
306     void setFlipY(bool flipY);
307 
isFoveationEnabled()308     bool isFoveationEnabled() const
309     {
310         return (mState.mFoveationState.getFoveatedFeatureBits() & GL_FOVEATION_ENABLE_BIT_QCOM);
311     }
312     void setFoveatedFeatureBits(const GLuint features);
313     GLuint getFoveatedFeatureBits() const;
314     bool isFoveationConfigured() const;
315     void configureFoveation();
316     void setFocalPoint(uint32_t layer,
317                        uint32_t focalPointIndex,
318                        float focalX,
319                        float focalY,
320                        float gainX,
321                        float gainY,
322                        float foveaArea);
323     const FocalPoint &getFocalPoint(uint32_t layer, uint32_t focalPoint) const;
324     GLuint getSupportedFoveationFeatures() const;
hasAnyAttachmentChanged()325     bool hasAnyAttachmentChanged() const { return mAttachmentChangedAfterEnablingFoveation; }
326 
327     void invalidateCompletenessCache();
cachedStatusValid()328     ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
329 
checkStatus(const Context * context)330     ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
331     {
332         // The default framebuffer is always complete except when it is surfaceless in which
333         // case it is always unsupported.
334         ASSERT(!isDefault() || mCachedStatus.valid());
335         if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid()))
336         {
337             return mCachedStatus.value();
338         }
339 
340         return checkStatusImpl(context);
341     }
342 
343     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
isComplete(const Context * context)344     ANGLE_INLINE bool isComplete(const Context *context) const
345     {
346         return checkStatus(context).isComplete();
347     }
348 
349     bool hasValidDepthStencil() const;
350 
351     // Returns the offset into the texture backing the default framebuffer's surface if any. Returns
352     // zero offset otherwise.  The renderer will apply the offset to scissor and viewport rects used
353     // for draws, clears, and blits.
354     const Offset &getSurfaceTextureOffset() const;
355 
356     angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
357     angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
358     angle::Result invalidateSub(const Context *context,
359                                 size_t count,
360                                 const GLenum *attachments,
361                                 const Rectangle &area);
362 
363     angle::Result clear(const Context *context, GLbitfield mask);
364     angle::Result clearBufferfv(const Context *context,
365                                 GLenum buffer,
366                                 GLint drawbuffer,
367                                 const GLfloat *values);
368     angle::Result clearBufferuiv(const Context *context,
369                                  GLenum buffer,
370                                  GLint drawbuffer,
371                                  const GLuint *values);
372     angle::Result clearBufferiv(const Context *context,
373                                 GLenum buffer,
374                                 GLint drawbuffer,
375                                 const GLint *values);
376     angle::Result clearBufferfi(const Context *context,
377                                 GLenum buffer,
378                                 GLint drawbuffer,
379                                 GLfloat depth,
380                                 GLint stencil);
381 
382     GLenum getImplementationColorReadFormat(const Context *context);
383     GLenum getImplementationColorReadType(const Context *context);
384 
385     angle::Result readPixels(const Context *context,
386                              const Rectangle &area,
387                              GLenum format,
388                              GLenum type,
389                              const PixelPackState &pack,
390                              Buffer *packBuffer,
391                              void *pixels);
392 
393     angle::Result blit(const Context *context,
394                        const Rectangle &sourceArea,
395                        const Rectangle &destArea,
396                        GLbitfield mask,
397                        GLenum filter);
isDefault()398     bool isDefault() const { return mState.isDefault(); }
399 
400     enum DirtyBitType : size_t
401     {
402         DIRTY_BIT_COLOR_ATTACHMENT_0,
403         DIRTY_BIT_COLOR_ATTACHMENT_MAX =
404             DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
405         DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
406         DIRTY_BIT_STENCIL_ATTACHMENT,
407         DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
408         DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
409             DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
410         DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
411         DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
412         DIRTY_BIT_DRAW_BUFFERS,
413         DIRTY_BIT_READ_BUFFER,
414         DIRTY_BIT_DEFAULT_WIDTH,
415         DIRTY_BIT_DEFAULT_HEIGHT,
416         DIRTY_BIT_DEFAULT_SAMPLES,
417         DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
418         DIRTY_BIT_DEFAULT_LAYERS,
419         DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
420         DIRTY_BIT_FLIP_Y,
421         DIRTY_BIT_FOVEATION,
422         DIRTY_BIT_UNKNOWN,
423         DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
424     };
425 
426     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
hasAnyDirtyBit()427     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
428 
getActiveFloat32ColorAttachmentDrawBufferMask()429     DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const
430     {
431         return mFloat32ColorAttachmentBits & getDrawBufferMask();
432     }
433 
getActiveSharedExponentColorAttachmentDrawBufferMask()434     DrawBufferMask getActiveSharedExponentColorAttachmentDrawBufferMask() const
435     {
436         return mSharedExponentColorAttachmentBits & getDrawBufferMask();
437     }
438 
hasResourceThatNeedsInit()439     bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
440 
441     angle::Result syncState(const Context *context,
442                             GLenum framebufferBinding,
443                             Command command) const;
444 
445     void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode);
446 
447     // Observer implementation
448     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
449 
450     bool formsRenderingFeedbackLoopWith(const Context *context) const;
451     bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
452                                       GLint copyTextureLevel,
453                                       GLint copyTextureLayer) const;
454 
455     angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask);
456     angle::Result ensureClearBufferAttachmentsInitialized(const Context *context,
457                                                           GLenum buffer,
458                                                           GLint drawbuffer);
459     angle::Result ensureDrawAttachmentsInitialized(const Context *context);
460 
461     // Conservatively initializes both read color and depth. Blit can access the depth buffer.
462     angle::Result ensureReadAttachmentsInitialized(const Context *context);
463     Box getDimensions() const;
464 
465     // ANGLE_shader_pixel_local_storage.
466     // Lazily creates a PixelLocalStorage object for this Framebuffer.
467     PixelLocalStorage &getPixelLocalStorage(const Context *);
468     // Returns nullptr if the pixel local storage object has not been created yet.
peekPixelLocalStorage()469     PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); }
470     // Detaches the the pixel local storage object so the Context can call deleteContextObjects().
471     std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage();
472 
onSwapChainImageChanged()473     void onSwapChainImageChanged()
474     {
475         mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
476         onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
477     }
478 
479     static const FramebufferID kDefaultDrawFramebufferHandle;
480 
481   private:
482     bool detachResourceById(Context *context, GLenum resourceType, GLuint resourceId);
483     bool detachMatchingAttachment(Context *context,
484                                   FramebufferAttachment *attachment,
485                                   GLenum matchType,
486                                   GLuint matchId);
487     FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
488     const FramebufferStatus &checkStatusImpl(const Context *context) const;
489     void setAttachment(const Context *context,
490                        GLenum type,
491                        GLenum binding,
492                        const ImageIndex &textureIndex,
493                        FramebufferAttachmentObject *resource,
494                        GLsizei numViews,
495                        GLuint baseViewIndex,
496                        bool isMultiview,
497                        GLsizei samplesIn);
498     void commitWebGL1DepthStencilIfConsistent(const Context *context,
499                                               GLsizei numViews,
500                                               GLuint baseViewIndex,
501                                               bool isMultiview,
502                                               GLsizei samples);
503     void setAttachmentImpl(const Context *context,
504                            GLenum type,
505                            GLenum binding,
506                            const ImageIndex &textureIndex,
507                            FramebufferAttachmentObject *resource,
508                            GLsizei numViews,
509                            GLuint baseViewIndex,
510                            bool isMultiview,
511                            GLsizei samples);
512     void updateAttachment(const Context *context,
513                           FramebufferAttachment *attachment,
514                           size_t dirtyBit,
515                           angle::ObserverBinding *onDirtyBinding,
516                           GLenum type,
517                           GLenum binding,
518                           const ImageIndex &textureIndex,
519                           FramebufferAttachmentObject *resource,
520                           GLsizei numViews,
521                           GLuint baseViewIndex,
522                           bool isMultiview,
523                           GLsizei samples);
524 
525     void markAttachmentsInitialized(const DrawBufferMask &color, bool depth, bool stencil);
526 
527     // Checks that we have a partially masked clear:
528     // * some color channels are masked out
529     // * some stencil values are masked out
530     // * scissor test partially overlaps the framebuffer
531     bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
532     bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
533 
534     FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
535 
updateFloat32AndSharedExponentColorAttachmentBits(size_t index,const InternalFormat * format)536     ANGLE_INLINE void updateFloat32AndSharedExponentColorAttachmentBits(
537         size_t index,
538         const InternalFormat *format)
539     {
540         mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
541         mSharedExponentColorAttachmentBits.set(index, format->type == GL_UNSIGNED_INT_5_9_9_9_REV);
542     }
543 
544     angle::Result syncAllDrawAttachmentState(const Context *context, Command command) const;
545     angle::Result syncAttachmentState(const Context *context,
546                                       Command command,
547                                       const FramebufferAttachment *attachment) const;
548 
549     FramebufferState mState;
550     rx::FramebufferImpl *mImpl;
551 
552     mutable Optional<FramebufferStatus> mCachedStatus;
553     DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
554     angle::ObserverBinding mDirtyDepthAttachmentBinding;
555     angle::ObserverBinding mDirtyStencilAttachmentBinding;
556 
557     mutable DirtyBits mDirtyBits;
558     DrawBufferMask mFloat32ColorAttachmentBits;
559     DrawBufferMask mSharedExponentColorAttachmentBits;
560 
561     // The dirty bits guard is checked when we get a dependent state change message. We verify that
562     // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
563     mutable Optional<DirtyBits> mDirtyBitsGuard;
564 
565     // ANGLE_shader_pixel_local_storage
566     std::unique_ptr<PixelLocalStorage> mPixelLocalStorage;
567 
568     // QCOM_framebuffer_foveated
569     bool mAttachmentChangedAfterEnablingFoveation;
570 };
571 
isDefault()572 inline bool FramebufferState::isDefault() const
573 {
574     return mId == Framebuffer::kDefaultDrawFramebufferHandle;
575 }
576 
577 using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>;
578 
getFirstNonNullAttachment()579 ANGLE_INLINE const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
580 {
581     auto *colorAttachment = getFirstColorAttachment();
582     if (colorAttachment)
583     {
584         return colorAttachment;
585     }
586     return getDepthOrStencilAttachment();
587 }
588 
getFirstColorAttachment()589 ANGLE_INLINE const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
590 {
591     for (const FramebufferAttachment &colorAttachment : mColorAttachments)
592     {
593         if (colorAttachment.isAttached())
594         {
595             return &colorAttachment;
596         }
597     }
598 
599     return nullptr;
600 }
601 
getDepthOrStencilAttachment()602 ANGLE_INLINE const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
603 {
604     if (mDepthAttachment.isAttached())
605     {
606         return &mDepthAttachment;
607     }
608     if (mStencilAttachment.isAttached())
609     {
610         return &mStencilAttachment;
611     }
612     return nullptr;
613 }
614 
getNumViews()615 ANGLE_INLINE GLsizei FramebufferState::getNumViews() const
616 {
617     const FramebufferAttachment *attachment = getFirstNonNullAttachment();
618     if (attachment == nullptr)
619     {
620         return FramebufferAttachment::kDefaultNumViews;
621     }
622     return attachment->getNumViews();
623 }
624 
625 }  // namespace gl
626 
627 #endif  // LIBANGLE_FRAMEBUFFER_H_
628