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