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