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