• 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 Renderbuffer;
49 class TextureCapsMap;
50 
51 struct FramebufferStatus
52 {
53     bool isComplete() const;
54 
55     static FramebufferStatus Complete();
56     static FramebufferStatus Incomplete(GLenum status, const char *reason);
57 
58     GLenum status      = GL_FRAMEBUFFER_COMPLETE;
59     const char *reason = nullptr;
60 };
61 
62 class FramebufferState final : angle::NonCopyable
63 {
64   public:
65     explicit FramebufferState(rx::Serial serial);
66     FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial);
67     ~FramebufferState();
68 
69     const std::string &getLabel() const;
70     uint32_t getReadIndex() const;
71 
72     const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
73     const FramebufferAttachment *getReadAttachment() const;
74     const FramebufferAttachment *getFirstNonNullAttachment() const;
75     const FramebufferAttachment *getFirstColorAttachment() const;
76     const FramebufferAttachment *getDepthOrStencilAttachment() const;
77     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
78     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
79     const FramebufferAttachment *getDepthAttachment() const;
80     const FramebufferAttachment *getStencilAttachment() const;
81     const FramebufferAttachment *getDepthStencilAttachment() const;
82     const FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const;
83 
getDrawBufferStates()84     const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
getEnabledDrawBuffers()85     DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
getReadBufferState()86     GLenum getReadBufferState() const { return mReadBufferState; }
getColorAttachments()87     const std::vector<FramebufferAttachment> &getColorAttachments() const
88     {
89         return mColorAttachments;
90     }
getColorAttachmentsMask()91     const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; }
92 
93     const Extents getAttachmentExtentsIntersection() const;
94     bool attachmentsHaveSameDimensions() const;
95     bool hasSeparateDepthAndStencilAttachments() const;
96     bool colorAttachmentsAreUniqueImages() const;
97     Box getDimensions() const;
98     Extents getExtents() const;
99 
100     const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
101     size_t getDrawBufferCount() const;
102 
getDefaultWidth()103     GLint getDefaultWidth() const { return mDefaultWidth; }
getDefaultHeight()104     GLint getDefaultHeight() const { return mDefaultHeight; }
getDefaultSamples()105     GLint getDefaultSamples() const { return mDefaultSamples; }
getDefaultFixedSampleLocations()106     bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; }
getDefaultLayers()107     GLint getDefaultLayers() const { return mDefaultLayers; }
getFlipY()108     bool getFlipY() const { return mFlipY; }
109 
110     bool hasDepth() const;
111     bool hasStencil() const;
112 
113     bool hasExternalTextureAttachment() const;
114     bool hasYUVAttachment() const;
115 
116     bool isMultiview() const;
117 
getNumViews()118     ANGLE_INLINE GLsizei getNumViews() const
119     {
120         const FramebufferAttachment *attachment = getFirstNonNullAttachment();
121         if (attachment == nullptr)
122         {
123             return FramebufferAttachment::kDefaultNumViews;
124         }
125         return attachment->getNumViews();
126     }
127 
128     GLint getBaseViewIndex() const;
129 
getWriteControlMode()130     SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; }
131 
id()132     FramebufferID id() const { return mId; }
133 
134     bool isDefault() const;
135 
getSurfaceTextureOffset()136     const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; }
137 
getFramebufferSerial()138     rx::Serial getFramebufferSerial() const { return mFramebufferSerial; }
139 
140     bool isBoundAsDrawFramebuffer(const Context *context) const;
141 
142   private:
143     const FramebufferAttachment *getWebGLDepthStencilAttachment() const;
144     const FramebufferAttachment *getWebGLDepthAttachment() const;
145     const FramebufferAttachment *getWebGLStencilAttachment() const;
146 
147     friend class Framebuffer;
148 
149     // The Framebuffer ID is unique to a Context.
150     // The Framebuffer Serial is unique to a Share Group.
151     FramebufferID mId;
152     rx::Serial mFramebufferSerial;
153     std::string mLabel;
154 
155     std::vector<FramebufferAttachment> mColorAttachments;
156     FramebufferAttachment mDepthAttachment;
157     FramebufferAttachment mStencilAttachment;
158 
159     // Tracks all the color buffers attached to this FramebufferDesc
160     DrawBufferMask mColorAttachmentsMask;
161 
162     std::vector<GLenum> mDrawBufferStates;
163     GLenum mReadBufferState;
164     DrawBufferMask mEnabledDrawBuffers;
165     ComponentTypeMask mDrawBufferTypeMask;
166 
167     GLint mDefaultWidth;
168     GLint mDefaultHeight;
169     GLint mDefaultSamples;
170     bool mDefaultFixedSampleLocations;
171     GLint mDefaultLayers;
172     bool mFlipY;
173 
174     // It's necessary to store all this extra state so we can restore attachments
175     // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
176     FramebufferAttachment mWebGLDepthStencilAttachment;
177     FramebufferAttachment mWebGLDepthAttachment;
178     FramebufferAttachment mWebGLStencilAttachment;
179     bool mWebGLDepthStencilConsistent;
180 
181     // Tracks if we need to initialize the resources for each attachment.
182     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
183 
184     bool mDefaultFramebufferReadAttachmentInitialized;
185     FramebufferAttachment mDefaultFramebufferReadAttachment;
186 
187     // EXT_sRGB_write_control
188     SrgbWriteControlMode mSrgbWriteControlMode;
189 
190     Offset mSurfaceTextureOffset;
191 };
192 
193 class Framebuffer final : public angle::ObserverInterface,
194                           public LabeledObject,
195                           public angle::Subject
196 {
197   public:
198     // Constructor to build application-defined framebuffers
199     Framebuffer(const Caps &caps,
200                 rx::GLImplFactory *factory,
201                 FramebufferID id,
202                 egl::ShareGroup *shareGroup);
203     // Constructor to build default framebuffers for a surface and context pair
204     Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface);
205     // Constructor to build a fake default framebuffer when surfaceless
206     Framebuffer(const Context *context, rx::GLImplFactory *factory, egl::Surface *readSurface);
207 
208     ~Framebuffer() override;
209     void onDestroy(const Context *context);
210 
211     void setReadSurface(const Context *context, egl::Surface *readSurface);
212     void setLabel(const Context *context, const std::string &label) override;
213     const std::string &getLabel() const override;
214 
getImplementation()215     rx::FramebufferImpl *getImplementation() const { return mImpl; }
216 
id()217     FramebufferID id() const { return mState.mId; }
218 
219     void setAttachment(const Context *context,
220                        GLenum type,
221                        GLenum binding,
222                        const ImageIndex &textureIndex,
223                        FramebufferAttachmentObject *resource);
224     void setAttachmentMultisample(const Context *context,
225                                   GLenum type,
226                                   GLenum binding,
227                                   const ImageIndex &textureIndex,
228                                   FramebufferAttachmentObject *resource,
229                                   GLsizei samples);
230     void setAttachmentMultiview(const Context *context,
231                                 GLenum type,
232                                 GLenum binding,
233                                 const ImageIndex &textureIndex,
234                                 FramebufferAttachmentObject *resource,
235                                 GLsizei numViews,
236                                 GLint baseViewIndex);
237     void resetAttachment(const Context *context, GLenum binding);
238 
239     bool detachTexture(const Context *context, TextureID texture);
240     bool detachRenderbuffer(const Context *context, RenderbufferID renderbuffer);
241 
242     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
243     const FramebufferAttachment *getDepthAttachment() const;
244     const FramebufferAttachment *getStencilAttachment() const;
245     const FramebufferAttachment *getDepthStencilAttachment() const;
246     const FramebufferAttachment *getDepthOrStencilAttachment() const;
247     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
248     const FramebufferAttachment *getReadColorAttachment() const;
249     GLenum getReadColorAttachmentType() const;
250     const FramebufferAttachment *getFirstColorAttachment() const;
251     const FramebufferAttachment *getFirstNonNullAttachment() const;
252 
getColorAttachments()253     const std::vector<FramebufferAttachment> &getColorAttachments() const
254     {
255         return mState.mColorAttachments;
256     }
257 
getState()258     const FramebufferState &getState() const { return mState; }
259 
260     const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const;
261     bool isMultiview() const;
262     bool readDisallowedByMultiview() const;
263     GLsizei getNumViews() const;
264     GLint getBaseViewIndex() const;
265     Extents getExtents() const;
266 
267     size_t getDrawbufferStateCount() const;
268     GLenum getDrawBufferState(size_t drawBuffer) const;
269     const std::vector<GLenum> &getDrawBufferStates() const;
270     void setDrawBuffers(size_t count, const GLenum *buffers);
271     const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
272     ComponentType getDrawbufferWriteType(size_t drawBuffer) const;
273     ComponentTypeMask getDrawBufferTypeMask() const;
274     DrawBufferMask getDrawBufferMask() const;
275     bool hasEnabledDrawBuffer() const;
276 
277     GLenum getReadBufferState() const;
278     void setReadBuffer(GLenum buffer);
279 
280     size_t getNumColorAttachments() const;
281     bool hasDepth() const;
282     bool hasStencil() const;
283 
284     bool hasExternalTextureAttachment() const;
285     bool hasYUVAttachment() const;
286 
287     bool usingExtendedDrawBuffers() const;
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 
308     void invalidateCompletenessCache();
cachedStatusValid()309     ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); }
310 
checkStatus(const Context * context)311     ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const
312     {
313         // The default framebuffer is always complete except when it is surfaceless in which
314         // case it is always unsupported.
315         ASSERT(!isDefault() || mCachedStatus.valid());
316         if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid()))
317         {
318             return mCachedStatus.value();
319         }
320 
321         return checkStatusImpl(context);
322     }
323 
324     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
isComplete(const Context * context)325     ANGLE_INLINE bool isComplete(const Context *context) const
326     {
327         return checkStatus(context).isComplete();
328     }
329 
330     bool hasValidDepthStencil() const;
331 
332     // Returns the offset into the texture backing the default framebuffer's surface if any. Returns
333     // zero offset otherwise.  The renderer will apply the offset to scissor and viewport rects used
334     // for draws, clears, and blits.
335     const Offset &getSurfaceTextureOffset() const;
336 
337     angle::Result discard(const Context *context, size_t count, const GLenum *attachments);
338     angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments);
339     angle::Result invalidateSub(const Context *context,
340                                 size_t count,
341                                 const GLenum *attachments,
342                                 const Rectangle &area);
343 
344     angle::Result clear(const Context *context, GLbitfield mask);
345     angle::Result clearBufferfv(const Context *context,
346                                 GLenum buffer,
347                                 GLint drawbuffer,
348                                 const GLfloat *values);
349     angle::Result clearBufferuiv(const Context *context,
350                                  GLenum buffer,
351                                  GLint drawbuffer,
352                                  const GLuint *values);
353     angle::Result clearBufferiv(const Context *context,
354                                 GLenum buffer,
355                                 GLint drawbuffer,
356                                 const GLint *values);
357     angle::Result clearBufferfi(const Context *context,
358                                 GLenum buffer,
359                                 GLint drawbuffer,
360                                 GLfloat depth,
361                                 GLint stencil);
362 
363     GLenum getImplementationColorReadFormat(const Context *context);
364     GLenum getImplementationColorReadType(const Context *context);
365 
366     angle::Result readPixels(const Context *context,
367                              const Rectangle &area,
368                              GLenum format,
369                              GLenum type,
370                              const PixelPackState &pack,
371                              Buffer *packBuffer,
372                              void *pixels);
373 
374     angle::Result blit(const Context *context,
375                        const Rectangle &sourceArea,
376                        const Rectangle &destArea,
377                        GLbitfield mask,
378                        GLenum filter);
isDefault()379     bool isDefault() const { return mState.isDefault(); }
380 
381     enum DirtyBitType : size_t
382     {
383         DIRTY_BIT_COLOR_ATTACHMENT_0,
384         DIRTY_BIT_COLOR_ATTACHMENT_MAX =
385             DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
386         DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
387         DIRTY_BIT_STENCIL_ATTACHMENT,
388         DIRTY_BIT_COLOR_BUFFER_CONTENTS_0,
389         DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX =
390             DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS,
391         DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX,
392         DIRTY_BIT_STENCIL_BUFFER_CONTENTS,
393         DIRTY_BIT_DRAW_BUFFERS,
394         DIRTY_BIT_READ_BUFFER,
395         DIRTY_BIT_DEFAULT_WIDTH,
396         DIRTY_BIT_DEFAULT_HEIGHT,
397         DIRTY_BIT_DEFAULT_SAMPLES,
398         DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
399         DIRTY_BIT_DEFAULT_LAYERS,
400         DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE,
401         DIRTY_BIT_FLIP_Y,
402         DIRTY_BIT_UNKNOWN,
403         DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
404     };
405 
406     using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>;
hasAnyDirtyBit()407     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
408 
getActiveFloat32ColorAttachmentDrawBufferMask()409     DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const
410     {
411         return mFloat32ColorAttachmentBits & getDrawBufferMask();
412     }
413 
hasResourceThatNeedsInit()414     bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); }
415 
416     angle::Result syncState(const Context *context,
417                             GLenum framebufferBinding,
418                             Command command) const;
419 
420     void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode);
421 
422     // Observer implementation
423     void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override;
424 
425     bool formsRenderingFeedbackLoopWith(const Context *context) const;
426     bool formsCopyingFeedbackLoopWith(TextureID copyTextureID,
427                                       GLint copyTextureLevel,
428                                       GLint copyTextureLayer) const;
429 
430     angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask);
431     angle::Result ensureClearBufferAttachmentsInitialized(const Context *context,
432                                                           GLenum buffer,
433                                                           GLint drawbuffer);
434     angle::Result ensureDrawAttachmentsInitialized(const Context *context);
435 
436     // Conservatively initializes both read color and depth. Blit can access the depth buffer.
437     angle::Result ensureReadAttachmentsInitialized(const Context *context);
438     Box getDimensions() const;
439 
440     static const FramebufferID kDefaultDrawFramebufferHandle;
441 
442   private:
443     bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
444     bool detachMatchingAttachment(const Context *context,
445                                   FramebufferAttachment *attachment,
446                                   GLenum matchType,
447                                   GLuint matchId);
448     FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const;
449     const FramebufferStatus &checkStatusImpl(const Context *context) const;
450     void setAttachment(const Context *context,
451                        GLenum type,
452                        GLenum binding,
453                        const ImageIndex &textureIndex,
454                        FramebufferAttachmentObject *resource,
455                        GLsizei numViews,
456                        GLuint baseViewIndex,
457                        bool isMultiview,
458                        GLsizei samplesIn);
459     void commitWebGL1DepthStencilIfConsistent(const Context *context,
460                                               GLsizei numViews,
461                                               GLuint baseViewIndex,
462                                               bool isMultiview,
463                                               GLsizei samples);
464     void setAttachmentImpl(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 samples);
473     void updateAttachment(const Context *context,
474                           FramebufferAttachment *attachment,
475                           size_t dirtyBit,
476                           angle::ObserverBinding *onDirtyBinding,
477                           GLenum type,
478                           GLenum binding,
479                           const ImageIndex &textureIndex,
480                           FramebufferAttachmentObject *resource,
481                           GLsizei numViews,
482                           GLuint baseViewIndex,
483                           bool isMultiview,
484                           GLsizei samples);
485 
486     void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil);
487     void markBufferInitialized(GLenum bufferType, GLint bufferIndex);
488     angle::Result ensureBufferInitialized(const Context *context,
489                                           GLenum bufferType,
490                                           GLint bufferIndex);
491 
492     // Checks that we have a partially masked clear:
493     // * some color channels are masked out
494     // * some stencil values are masked out
495     // * scissor test partially overlaps the framebuffer
496     bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
497     bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
498 
499     FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index);
500 
updateFloat32ColorAttachmentBits(size_t index,const InternalFormat * format)501     ANGLE_INLINE void updateFloat32ColorAttachmentBits(size_t index, const InternalFormat *format)
502     {
503         mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT);
504     }
505 
506     FramebufferState mState;
507     rx::FramebufferImpl *mImpl;
508 
509     mutable Optional<FramebufferStatus> mCachedStatus;
510     std::vector<angle::ObserverBinding> mDirtyColorAttachmentBindings;
511     angle::ObserverBinding mDirtyDepthAttachmentBinding;
512     angle::ObserverBinding mDirtyStencilAttachmentBinding;
513 
514     mutable DirtyBits mDirtyBits;
515     DrawBufferMask mFloat32ColorAttachmentBits;
516 
517     // The dirty bits guard is checked when we get a dependent state change message. We verify that
518     // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState.
519     mutable Optional<DirtyBits> mDirtyBitsGuard;
520 };
521 
522 }  // namespace gl
523 
524 #endif  // LIBANGLE_FRAMEBUFFER_H_
525