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