1 //
2 // Copyright (c) 2002-2013 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/Optional.h"
16 #include "common/angleutils.h"
17 #include "libANGLE/Constants.h"
18 #include "libANGLE/Debug.h"
19 #include "libANGLE/Error.h"
20 #include "libANGLE/FramebufferAttachment.h"
21 #include "libANGLE/RefCountObject.h"
22 #include "libANGLE/signal_utils.h"
23 
24 namespace rx
25 {
26 class GLImplFactory;
27 class FramebufferImpl;
28 class RenderbufferImpl;
29 class SurfaceImpl;
30 }
31 
32 namespace egl
33 {
34 class Display;
35 class Surface;
36 }
37 
38 namespace gl
39 {
40 class Context;
41 class ContextState;
42 class Framebuffer;
43 class Renderbuffer;
44 class State;
45 class Texture;
46 class TextureCapsMap;
47 class ValidationContext;
48 struct Caps;
49 struct Extensions;
50 struct ImageIndex;
51 struct Rectangle;
52 
53 class FramebufferState final : angle::NonCopyable
54 {
55   public:
56     FramebufferState();
57     explicit FramebufferState(const Caps &caps);
58     ~FramebufferState();
59 
60     const std::string &getLabel();
61     size_t getReadIndex() const;
62 
63     const FramebufferAttachment *getAttachment(GLenum attachment) const;
64     const FramebufferAttachment *getReadAttachment() const;
65     const FramebufferAttachment *getFirstNonNullAttachment() const;
66     const FramebufferAttachment *getFirstColorAttachment() const;
67     const FramebufferAttachment *getDepthOrStencilAttachment() const;
68     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
69     const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const;
70     const FramebufferAttachment *getDepthAttachment() const;
71     const FramebufferAttachment *getStencilAttachment() const;
72     const FramebufferAttachment *getDepthStencilAttachment() const;
73 
getDrawBufferStates()74     const std::vector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; }
getEnabledDrawBuffers()75     DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; }
getReadBufferState()76     GLenum getReadBufferState() const { return mReadBufferState; }
getColorAttachments()77     const std::vector<FramebufferAttachment> &getColorAttachments() const
78     {
79         return mColorAttachments;
80     }
81 
82     bool attachmentsHaveSameDimensions() const;
83     bool colorAttachmentsAreUniqueImages() const;
84     Box getDimensions() const;
85 
86     const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const;
87     size_t getDrawBufferCount() const;
88 
getDefaultWidth()89     GLint getDefaultWidth() const { return mDefaultWidth; };
getDefaultHeight()90     GLint getDefaultHeight() const { return mDefaultHeight; };
getDefaultSamples()91     GLint getDefaultSamples() const { return mDefaultSamples; };
getDefaultFixedSampleLocations()92     bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; };
93 
94     bool hasDepth() const;
95     bool hasStencil() const;
96 
97     GLenum getMultiviewLayout() const;
98     GLsizei getNumViews() const;
99     const std::vector<Offset> *getViewportOffsets() const;
100     GLint getBaseViewIndex() const;
101 
102   private:
103     friend class Framebuffer;
104 
105     std::string mLabel;
106 
107     std::vector<FramebufferAttachment> mColorAttachments;
108     FramebufferAttachment mDepthAttachment;
109     FramebufferAttachment mStencilAttachment;
110 
111     std::vector<GLenum> mDrawBufferStates;
112     GLenum mReadBufferState;
113     DrawBufferMask mEnabledDrawBuffers;
114 
115     GLint mDefaultWidth;
116     GLint mDefaultHeight;
117     GLint mDefaultSamples;
118     bool mDefaultFixedSampleLocations;
119 
120     // It's necessary to store all this extra state so we can restore attachments
121     // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1.
122     FramebufferAttachment mWebGLDepthStencilAttachment;
123     FramebufferAttachment mWebGLDepthAttachment;
124     FramebufferAttachment mWebGLStencilAttachment;
125     bool mWebGLDepthStencilConsistent;
126 
127     // Tracks if we need to initialize the resources for each attachment.
128     angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit;
129 };
130 
131 class Framebuffer final : public LabeledObject, public OnAttachmentDirtyReceiver
132 {
133   public:
134     // Constructor to build application-defined framebuffers
135     Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id);
136     // Constructor to build default framebuffers for a surface
137     Framebuffer(const egl::Display *display, egl::Surface *surface);
138     // Constructor to build a fake default framebuffer when surfaceless
139     Framebuffer(rx::GLImplFactory *factory);
140 
141     ~Framebuffer() override;
142     void onDestroy(const Context *context);
143     void destroyDefault(const egl::Display *display);
144 
145     void setLabel(const std::string &label) override;
146     const std::string &getLabel() const override;
147 
getImplementation()148     rx::FramebufferImpl *getImplementation() const { return mImpl; }
149 
id()150     GLuint id() const { return mId; }
151 
152     void setAttachment(const Context *context,
153                        GLenum type,
154                        GLenum binding,
155                        const ImageIndex &textureIndex,
156                        FramebufferAttachmentObject *resource);
157     void setAttachmentMultiviewLayered(const Context *context,
158                                        GLenum type,
159                                        GLenum binding,
160                                        const ImageIndex &textureIndex,
161                                        FramebufferAttachmentObject *resource,
162                                        GLsizei numViews,
163                                        GLint baseViewIndex);
164     void setAttachmentMultiviewSideBySide(const Context *context,
165                                           GLenum type,
166                                           GLenum binding,
167                                           const ImageIndex &textureIndex,
168                                           FramebufferAttachmentObject *resource,
169                                           GLsizei numViews,
170                                           const GLint *viewportOffsets);
171     void resetAttachment(const Context *context, GLenum binding);
172 
173     bool detachTexture(const Context *context, GLuint texture);
174     bool detachRenderbuffer(const Context *context, GLuint renderbuffer);
175 
176     const FramebufferAttachment *getColorbuffer(size_t colorAttachment) const;
177     const FramebufferAttachment *getDepthbuffer() const;
178     const FramebufferAttachment *getStencilbuffer() const;
179     const FramebufferAttachment *getDepthStencilBuffer() const;
180     const FramebufferAttachment *getDepthOrStencilbuffer() const;
181     const FramebufferAttachment *getStencilOrDepthStencilAttachment() const;
182     const FramebufferAttachment *getReadColorbuffer() const;
183     GLenum getReadColorbufferType() const;
184     const FramebufferAttachment *getFirstColorbuffer() const;
185     const FramebufferAttachment *getFirstNonNullAttachment() const;
186 
187     const FramebufferAttachment *getAttachment(GLenum attachment) const;
188     GLenum getMultiviewLayout() const;
189     GLsizei getNumViews() const;
190     GLint getBaseViewIndex() const;
191     const std::vector<Offset> *getViewportOffsets() const;
192 
193     size_t getDrawbufferStateCount() const;
194     GLenum getDrawBufferState(size_t drawBuffer) const;
195     const std::vector<GLenum> &getDrawBufferStates() const;
196     void setDrawBuffers(size_t count, const GLenum *buffers);
197     const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const;
198     GLenum getDrawbufferWriteType(size_t drawBuffer) const;
199     bool hasEnabledDrawBuffer() const;
200 
201     GLenum getReadBufferState() const;
202     void setReadBuffer(GLenum buffer);
203 
204     size_t getNumColorBuffers() const;
205     bool hasDepth() const;
206     bool hasStencil() const;
207 
208     bool usingExtendedDrawBuffers() const;
209 
210     // This method calls checkStatus.
211     int getSamples(const Context *context);
212 
213     Error getSamplePosition(size_t index, GLfloat *xy) const;
214 
215     GLint getDefaultWidth() const;
216     GLint getDefaultHeight() const;
217     GLint getDefaultSamples() const;
218     bool getDefaultFixedSampleLocations() const;
219     void setDefaultWidth(GLint defaultWidth);
220     void setDefaultHeight(GLint defaultHeight);
221     void setDefaultSamples(GLint defaultSamples);
222     void setDefaultFixedSampleLocations(bool defaultFixedSampleLocations);
223 
224     void invalidateCompletenessCache();
225 
226     GLenum checkStatus(const Context *context);
227 
228     // TODO(jmadill): Remove this kludge.
229     GLenum checkStatus(const ValidationContext *context);
230     int getSamples(const ValidationContext *context);
231 
232     // For when we don't want to check completeness in getSamples().
233     int getCachedSamples(const Context *context);
234 
235     // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE.
236     bool complete(const Context *context);
237     bool cachedComplete() const;
238 
239     bool hasValidDepthStencil() const;
240 
241     Error discard(const Context *context, size_t count, const GLenum *attachments);
242     Error invalidate(const Context *context, size_t count, const GLenum *attachments);
243     Error invalidateSub(const Context *context,
244                         size_t count,
245                         const GLenum *attachments,
246                         const gl::Rectangle &area);
247 
248     Error clear(const gl::Context *context, GLbitfield mask);
249     Error clearBufferfv(const gl::Context *context,
250                         GLenum buffer,
251                         GLint drawbuffer,
252                         const GLfloat *values);
253     Error clearBufferuiv(const gl::Context *context,
254                          GLenum buffer,
255                          GLint drawbuffer,
256                          const GLuint *values);
257     Error clearBufferiv(const gl::Context *context,
258                         GLenum buffer,
259                         GLint drawbuffer,
260                         const GLint *values);
261     Error clearBufferfi(const gl::Context *context,
262                         GLenum buffer,
263                         GLint drawbuffer,
264                         GLfloat depth,
265                         GLint stencil);
266 
267     GLenum getImplementationColorReadFormat(const Context *context) const;
268     GLenum getImplementationColorReadType(const Context *context) const;
269     Error readPixels(const gl::Context *context,
270                      const gl::Rectangle &area,
271                      GLenum format,
272                      GLenum type,
273                      void *pixels);
274 
275     Error blit(const gl::Context *context,
276                const Rectangle &sourceArea,
277                const Rectangle &destArea,
278                GLbitfield mask,
279                GLenum filter);
280 
281     enum DirtyBitType : size_t
282     {
283         DIRTY_BIT_COLOR_ATTACHMENT_0,
284         DIRTY_BIT_COLOR_ATTACHMENT_MAX =
285             DIRTY_BIT_COLOR_ATTACHMENT_0 + gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS,
286         DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX,
287         DIRTY_BIT_STENCIL_ATTACHMENT,
288         DIRTY_BIT_DRAW_BUFFERS,
289         DIRTY_BIT_READ_BUFFER,
290         DIRTY_BIT_DEFAULT_WIDTH,
291         DIRTY_BIT_DEFAULT_HEIGHT,
292         DIRTY_BIT_DEFAULT_SAMPLES,
293         DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS,
294         DIRTY_BIT_UNKNOWN,
295         DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN
296     };
297 
298     typedef angle::BitSet<DIRTY_BIT_MAX> DirtyBits;
hasAnyDirtyBit()299     bool hasAnyDirtyBit() const { return mDirtyBits.any(); }
300 
301     void syncState(const Context *context);
302 
303     // OnAttachmentChangedReceiver implementation
304     void signal(size_t dirtyBit, InitState state) override;
305 
306     bool formsRenderingFeedbackLoopWith(const State &state) const;
307     bool formsCopyingFeedbackLoopWith(GLuint copyTextureID,
308                                       GLint copyTextureLevel,
309                                       GLint copyTextureLayer) const;
310 
311     Error ensureDrawAttachmentsInitialized(const Context *context);
312     Error ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask);
313     Box getDimensions() const;
314 
315     bool hasTextureAttachment(const Texture *texture) const;
316 
317   private:
318     bool detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId);
319     bool detachMatchingAttachment(const Context *context,
320                                   FramebufferAttachment *attachment,
321                                   GLenum matchType,
322                                   GLuint matchId,
323                                   size_t dirtyBit);
324     GLenum checkStatusImpl(const Context *context);
325     void setAttachment(const Context *context,
326                        GLenum type,
327                        GLenum binding,
328                        const ImageIndex &textureIndex,
329                        FramebufferAttachmentObject *resource,
330                        GLsizei numViews,
331                        GLuint baseViewIndex,
332                        GLenum multiviewLayout,
333                        const GLint *viewportOffsets);
334     void commitWebGL1DepthStencilIfConsistent(const Context *context,
335                                               GLsizei numViews,
336                                               GLuint baseViewIndex,
337                                               GLenum multiviewLayout,
338                                               const GLint *viewportOffsets);
339     void setAttachmentImpl(const Context *context,
340                            GLenum type,
341                            GLenum binding,
342                            const ImageIndex &textureIndex,
343                            FramebufferAttachmentObject *resource,
344                            GLsizei numViews,
345                            GLuint baseViewIndex,
346                            GLenum multiviewLayout,
347                            const GLint *viewportOffsets);
348     void updateAttachment(const Context *context,
349                           FramebufferAttachment *attachment,
350                           size_t dirtyBit,
351                           OnAttachmentDirtyBinding *onDirtyBinding,
352                           GLenum type,
353                           GLenum binding,
354                           const ImageIndex &textureIndex,
355                           FramebufferAttachmentObject *resource,
356                           GLsizei numViews,
357                           GLuint baseViewIndex,
358                           GLenum multiviewLayout,
359                           const GLint *viewportOffsets);
360 
361     void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil);
362     void markBufferInitialized(GLenum bufferType, GLint bufferIndex);
363     Error ensureBufferInitialized(const Context *context, GLenum bufferType, GLint bufferIndex);
364 
365     // Checks that we have a partially masked clear:
366     // * some color channels are masked out
367     // * some stencil values are masked out
368     // * scissor test partially overlaps the framebuffer
369     bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil);
370     bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType);
371 
372     FramebufferState mState;
373     rx::FramebufferImpl *mImpl;
374     GLuint mId;
375 
376     Optional<GLenum> mCachedStatus;
377     std::vector<OnAttachmentDirtyBinding> mDirtyColorAttachmentBindings;
378     OnAttachmentDirtyBinding mDirtyDepthAttachmentBinding;
379     OnAttachmentDirtyBinding mDirtyStencilAttachmentBinding;
380 
381     DirtyBits mDirtyBits;
382 
383     // A cache of attached textures for quick validation of feedback loops.
384     mutable Optional<std::set<const FramebufferAttachmentObject *>> mAttachedTextures;
385 };
386 
387 }  // namespace gl
388 
389 #endif  // LIBANGLE_FRAMEBUFFER_H_
390