• 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 {
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 
115     bool hasExternalTextureAttachment() const;
116     bool hasYUVAttachment() const;
117 
118     bool isMultiview() const;
119 
getNumViews()120     ANGLE_INLINE GLsizei getNumViews() const
121     {
122         const FramebufferAttachment *attachment = getFirstNonNullAttachment();
123         if (attachment == nullptr)
124         {
125             return FramebufferAttachment::kDefaultNumViews;
126         }
127         return attachment->getNumViews();
128     }
129 
130     GLint getBaseViewIndex() const;
131 
getWriteControlMode()132     SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; }
133 
id()134     FramebufferID id() const { return mId; }
135 
136     bool isDefault() const;
137 
getSurfaceTextureOffset()138     const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
139 
getFramebufferSerial()140     rx::UniqueSerial getFramebufferSerial() const { return mFramebufferSerial; }
141 
142     bool isBoundAsDrawFramebuffer(const Context *context) const;
143 
144   private:
145     const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
146     const FramebufferAttachment *getWebGLDepthAttachment() const;
147     const FramebufferAttachment *getWebGLStencilAttachment() const;
148 
149     friend class Framebuffer;
150 
151     // The Framebuffer ID is unique to a Context.
152     // The Framebuffer UniqueSerial is unique to a Share Group.
153     FramebufferID mId;
154     rx::UniqueSerial mFramebufferSerial;
155     std::string mLabel;
156 
157     DrawBuffersVector<FramebufferAttachment> mColorAttachments;
158     FramebufferAttachment mDepthAttachment;
159     FramebufferAttachment mStencilAttachment;
160 
161     // Tracks all the color buffers attached to this FramebufferDesc
162     DrawBufferMask mColorAttachmentsMask;
163 
164     DrawBuffersVector<GLenum> mDrawBufferStates;
165     GLenum mReadBufferState;
166     DrawBufferMask mEnabledDrawBuffers;
167     ComponentTypeMask mDrawBufferTypeMask;
168 
169     GLint mDefaultWidth;
170     GLint mDefaultHeight;
171     GLint mDefaultSamples;
172     bool mDefaultFixedSampleLocations;
173     GLint mDefaultLayers;
174     bool mFlipY;
175 
176     // It's necessary to store all this extra state so we can restore attachments
177     // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
178     FramebufferAttachment mWebGLDepthStencilAttachment;
179     FramebufferAttachment mWebGLDepthAttachment;
180     FramebufferAttachment mWebGLStencilAttachment;
181     bool mWebGLDepthStencilConsistent;
182 
183     // Tracks if we need to initialize the resources for each attachment.
184     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
185 
186     bool mDefaultFramebufferReadAttachmentInitialized;
187     FramebufferAttachment mDefaultFramebufferReadAttachment;
188 
189     // EXT_sRGB_write_control
190     SrgbWriteControlMode mSrgbWriteControlMode;
191 
192     Offset mSurfaceTextureOffset;
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;
264     GLsizei getNumViews() const;
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;
275     DrawBufferMask getDrawBufferMask() const;
276     bool hasEnabledDrawBuffer() const;
277 
278     GLenum getReadBufferState() const;
279     void setReadBuffer(GLenum buffer);
280 
281     size_t getNumColorAttachments() const;
282     bool hasDepth() const;
283     bool hasStencil() const;
284 
285     bool hasExternalTextureAttachment() const;
286     bool hasYUVAttachment() const;
287 
288     bool usingExtendedDrawBuffers() const;
289 
290     // This method calls checkStatus.
291     int getSamples(const Context *context) const;
292     int getReadBufferResourceSamples(const Context *context) const;
293 
294     angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const;
295 
296     GLint getDefaultWidth() const;
297     GLint getDefaultHeight() const;
298     GLint getDefaultSamples() const;
299     bool getDefaultFixedSampleLocations() const;
300     GLint getDefaultLayers() const;
301     bool getFlipY() const;
302     void setDefaultWidth(const Context *context, GLint defaultWidth);
303     void setDefaultHeight(const Context *context, GLint defaultHeight);
304     void setDefaultSamples(const Context *context, GLint defaultSamples);
305     void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations);
306     void setDefaultLayers(GLint defaultLayers);
307     void setFlipY(bool flipY);
308 
309     void invalidateCompletenessCache();
cachedStatusValid()310     ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
311 
checkStatus(const Context * context)312     ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
313     {
314         // The default framebuffer is always complete except when it is surfaceless in which
315         // case it is always unsupported.
316         ASSERT(!isDefault() || mCachedStatus.valid());
317         if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid()))
318         {
319             return mCachedStatus.value();
320         }
321 
322         return checkStatusImpl(context);
323     }
324 
325     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
isComplete(const Context * context)326     ANGLE_INLINE bool isComplete(const Context *context) const
327     {
328         return checkStatus(context).isComplete();
329     }
330 
331     bool hasValidDepthStencil() const;
332 
333     // Returns the offset into the texture backing the default framebuffer's surface if any. Returns
334     // zero offset otherwise.  The renderer will apply the offset to scissor and viewport rects used
335     // for draws, clears, and blits.
336     const Offset &getSurfaceTextureOffset() const;
337 
338     angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
339     angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
340     angle::Result invalidateSub(const Context *context,
341                                 size_t count,
342                                 const GLenum *attachments,
343                                 const Rectangle &area);
344 
345     angle::Result clear(const Context *context, GLbitfield mask);
346     angle::Result clearBufferfv(const Context *context,
347                                 GLenum buffer,
348                                 GLint drawbuffer,
349                                 const GLfloat *values);
350     angle::Result clearBufferuiv(const Context *context,
351                                  GLenum buffer,
352                                  GLint drawbuffer,
353                                  const GLuint *values);
354     angle::Result clearBufferiv(const Context *context,
355                                 GLenum buffer,
356                                 GLint drawbuffer,
357                                 const GLint *values);
358     angle::Result clearBufferfi(const Context *context,
359                                 GLenum buffer,
360                                 GLint drawbuffer,
361                                 GLfloat depth,
362                                 GLint stencil);
363 
364     GLenum getImplementationColorReadFormat(const Context *context);
365     GLenum getImplementationColorReadType(const Context *context);
366 
367     angle::Result readPixels(const Context *context,
368                              const Rectangle &area,
369                              GLenum format,
370                              GLenum type,
371                              const PixelPackState &pack,
372                              Buffer *packBuffer,
373                              void *pixels);
374 
375     angle::Result blit(const Context *context,
376                        const Rectangle &sourceArea,
377                        const Rectangle &destArea,
378                        GLbitfield mask,
379                        GLenum filter);
isDefault()380     bool isDefault() const { return mState.isDefault(); }
381 
382     enum DirtyBitType : size_t
383     {
384         DIRTY_BIT_COLOR_ATTACHMENT_0,
385         DIRTY_BIT_COLOR_ATTACHMENT_MAX =
386             DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
387         DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
388         DIRTY_BIT_STENCIL_ATTACHMENT,
389         DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
390         DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
391             DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
392         DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
393         DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
394         DIRTY_BIT_DRAW_BUFFERS,
395         DIRTY_BIT_READ_BUFFER,
396         DIRTY_BIT_DEFAULT_WIDTH,
397         DIRTY_BIT_DEFAULT_HEIGHT,
398         DIRTY_BIT_DEFAULT_SAMPLES,
399         DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
400         DIRTY_BIT_DEFAULT_LAYERS,
401         DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
402         DIRTY_BIT_FLIP_Y,
403         DIRTY_BIT_UNKNOWN,
404         DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
405     };
406 
407     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
hasAnyDirtyBit()408     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
409 
getActiveFloat32ColorAttachmentDrawBufferMask()410     DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const
411     {
412         return mFloat32ColorAttachmentBits & getDrawBufferMask();
413     }
414 
getActiveSharedExponentColorAttachmentDrawBufferMask()415     DrawBufferMask getActiveSharedExponentColorAttachmentDrawBufferMask() const
416     {
417         return mSharedExponentColorAttachmentBits & getDrawBufferMask();
418     }
419 
hasResourceThatNeedsInit()420     bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
421 
422     angle::Result syncState(const Context *context,
423                             GLenum framebufferBinding,
424                             Command command) const;
425 
426     void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode);
427 
428     // Observer implementation
429     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
430 
431     bool formsRenderingFeedbackLoopWith(const Context *context) const;
432     bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
433                                       GLint copyTextureLevel,
434                                       GLint copyTextureLayer) const;
435 
436     angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask);
437     angle::Result ensureClearBufferAttachmentsInitialized(const Context *context,
438                                                           GLenum buffer,
439                                                           GLint drawbuffer);
440     angle::Result ensureDrawAttachmentsInitialized(const Context *context);
441 
442     // Conservatively initializes both read color and depth. Blit can access the depth buffer.
443     angle::Result ensureReadAttachmentsInitialized(const Context *context);
444     Box getDimensions() const;
445 
446     // ANGLE_shader_pixel_local_storage.
447     // Lazily creates a PixelLocalStorage object for this Framebuffer.
448     PixelLocalStorage &getPixelLocalStorage(const Context *);
449     // Returns nullptr if the pixel local storage object has not been created yet.
peekPixelLocalStorage()450     PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); }
451     // Detaches the the pixel local storage object so the Context can call deleteContextObjects().
452     std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage();
453 
454     static const FramebufferID kDefaultDrawFramebufferHandle;
455 
456   private:
457     bool detachResourceById(Context *context, GLenum resourceType, GLuint resourceId);
458     bool detachMatchingAttachment(Context *context,
459                                   FramebufferAttachment *attachment,
460                                   GLenum matchType,
461                                   GLuint matchId);
462     FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
463     const FramebufferStatus &checkStatusImpl(const Context *context) const;
464     void setAttachment(const Context *context,
465                        GLenum type,
466                        GLenum binding,
467                        const ImageIndex &textureIndex,
468                        FramebufferAttachmentObject *resource,
469                        GLsizei numViews,
470                        GLuint baseViewIndex,
471                        bool isMultiview,
472                        GLsizei samplesIn);
473     void commitWebGL1DepthStencilIfConsistent(const Context *context,
474                                               GLsizei numViews,
475                                               GLuint baseViewIndex,
476                                               bool isMultiview,
477                                               GLsizei samples);
478     void setAttachmentImpl(const Context *context,
479                            GLenum type,
480                            GLenum binding,
481                            const ImageIndex &textureIndex,
482                            FramebufferAttachmentObject *resource,
483                            GLsizei numViews,
484                            GLuint baseViewIndex,
485                            bool isMultiview,
486                            GLsizei samples);
487     void updateAttachment(const Context *context,
488                           FramebufferAttachment *attachment,
489                           size_t dirtyBit,
490                           angle::ObserverBinding *onDirtyBinding,
491                           GLenum type,
492                           GLenum binding,
493                           const ImageIndex &textureIndex,
494                           FramebufferAttachmentObject *resource,
495                           GLsizei numViews,
496                           GLuint baseViewIndex,
497                           bool isMultiview,
498                           GLsizei samples);
499 
500     void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil);
501     void markBufferInitialized(GLenum bufferType, GLint bufferIndex);
502     angle::Result ensureBufferInitialized(const Context *context,
503                                           GLenum bufferType,
504                                           GLint bufferIndex);
505 
506     // Checks that we have a partially masked clear:
507     // * some color channels are masked out
508     // * some stencil values are masked out
509     // * scissor test partially overlaps the framebuffer
510     bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
511     bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
512 
513     FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
514 
updateFloat32AndSharedExponentColorAttachmentBits(size_t index,const InternalFormat * format)515     ANGLE_INLINE void updateFloat32AndSharedExponentColorAttachmentBits(
516         size_t index,
517         const InternalFormat *format)
518     {
519         mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
520         mSharedExponentColorAttachmentBits.set(index, format->type == GL_UNSIGNED_INT_5_9_9_9_REV);
521     }
522 
523     angle::Result syncAllDrawAttachmentState(const Context *context, Command command) const;
524     angle::Result syncAttachmentState(const Context *context,
525                                       Command command,
526                                       const FramebufferAttachment *attachment) const;
527 
528     FramebufferState mState;
529     rx::FramebufferImpl *mImpl;
530 
531     mutable Optional<FramebufferStatus> mCachedStatus;
532     DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
533     angle::ObserverBinding mDirtyDepthAttachmentBinding;
534     angle::ObserverBinding mDirtyStencilAttachmentBinding;
535 
536     mutable DirtyBits mDirtyBits;
537     DrawBufferMask mFloat32ColorAttachmentBits;
538     DrawBufferMask mSharedExponentColorAttachmentBits;
539 
540     // The dirty bits guard is checked when we get a dependent state change message. We verify that
541     // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
542     mutable Optional<DirtyBits> mDirtyBitsGuard;
543 
544     // ANGLE_shader_pixel_local_storage
545     std::unique_ptr<PixelLocalStorage> mPixelLocalStorage;
546 };
547 
548 using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>;
549 
550 }  // namespace gl
551 
552 #endif  // LIBANGLE_FRAMEBUFFER_H_
553