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