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