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