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