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