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 #include "libANGLE/State.h" 25 #include "libANGLE/angletypes.h" 26 27 namespace rx 28 { 29 class GLImplFactory; 30 class FramebufferImpl; 31 class RenderbufferImpl; 32 class SurfaceImpl; 33 } // namespace rx 34 35 namespace egl 36 { 37 class Display; 38 class Surface; 39 } // namespace egl 40 41 namespace gl 42 { 43 struct Caps; 44 class Context; 45 struct Extensions; 46 class Framebuffer; 47 class ImageIndex; 48 class PixelLocalStorage; 49 class Renderbuffer; 50 class TextureCapsMap; 51 52 struct FramebufferStatus 53 { 54 bool isComplete() const; 55 56 static FramebufferStatus Complete(); 57 static FramebufferStatus Incomplete(GLenum status, const char *reason); 58 59 GLenum status = GL_FRAMEBUFFER_COMPLETE; 60 const char *reason = nullptr; 61 }; 62 63 class FramebufferState final : angle::NonCopyable 64 { 65 public: 66 explicit FramebufferState(rx::UniqueSerial serial); 67 FramebufferState(const Caps &caps, FramebufferID id, rx::UniqueSerial serial); 68 ~FramebufferState(); 69 70 const std::string &getLabel() const; 71 uint32_t getReadIndex() const; 72 73 const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const; 74 const FramebufferAttachment *getReadAttachment() const; 75 const FramebufferAttachment *getFirstNonNullAttachment() const; 76 const FramebufferAttachment *getFirstColorAttachment() const; 77 const FramebufferAttachment *getDepthOrStencilAttachment() const; 78 const FramebufferAttachment *getStencilOrDepthStencilAttachment() const; 79 const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; 80 const FramebufferAttachment *getDepthAttachment() const; 81 const FramebufferAttachment *getStencilAttachment() const; 82 const FramebufferAttachment *getDepthStencilAttachment() const; 83 const FramebufferAttachment *getReadPixelsAttachment(GLenum readFormat) const; 84 getDrawBufferStates()85 const DrawBuffersVector<GLenum> &getDrawBufferStates() const { return mDrawBufferStates; } getEnabledDrawBuffers()86 DrawBufferMask getEnabledDrawBuffers() const { return mEnabledDrawBuffers; } getReadBufferState()87 GLenum getReadBufferState() const { return mReadBufferState; } 88 getColorAttachments()89 const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const 90 { 91 return mColorAttachments; 92 } getColorAttachmentsMask()93 const DrawBufferMask getColorAttachmentsMask() const { return mColorAttachmentsMask; } 94 95 const Extents getAttachmentExtentsIntersection() const; 96 bool attachmentsHaveSameDimensions() const; 97 bool hasSeparateDepthAndStencilAttachments() const; 98 bool colorAttachmentsAreUniqueImages() const; 99 Box getDimensions() const; 100 Extents getExtents() const; 101 102 const FramebufferAttachment *getDrawBuffer(size_t drawBufferIdx) const; 103 size_t getDrawBufferCount() const; 104 getDefaultWidth()105 GLint getDefaultWidth() const { return mDefaultWidth; } getDefaultHeight()106 GLint getDefaultHeight() const { return mDefaultHeight; } getDefaultSamples()107 GLint getDefaultSamples() const { return mDefaultSamples; } getDefaultFixedSampleLocations()108 bool getDefaultFixedSampleLocations() const { return mDefaultFixedSampleLocations; } getDefaultLayers()109 GLint getDefaultLayers() const { return mDefaultLayers; } getFlipY()110 bool getFlipY() const { return mFlipY; } 111 112 bool hasDepth() const; 113 bool hasStencil() const; 114 115 bool hasExternalTextureAttachment() const; 116 bool hasYUVAttachment() const; 117 118 bool isMultiview() const; 119 getNumViews()120 ANGLE_INLINE GLsizei getNumViews() const 121 { 122 const FramebufferAttachment *attachment = getFirstNonNullAttachment(); 123 if (attachment == nullptr) 124 { 125 return FramebufferAttachment::kDefaultNumViews; 126 } 127 return attachment->getNumViews(); 128 } 129 130 GLint getBaseViewIndex() const; 131 getWriteControlMode()132 SrgbWriteControlMode getWriteControlMode() const { return mSrgbWriteControlMode; } 133 id()134 FramebufferID id() const { return mId; } 135 136 bool isDefault() const; 137 getSurfaceTextureOffset()138 const Offset &getSurfaceTextureOffset() const { return mSurfaceTextureOffset; } 139 getFramebufferSerial()140 rx::UniqueSerial getFramebufferSerial() const { return mFramebufferSerial; } 141 142 bool isBoundAsDrawFramebuffer(const Context *context) const; 143 144 private: 145 const FramebufferAttachment *getWebGLDepthStencilAttachment() const; 146 const FramebufferAttachment *getWebGLDepthAttachment() const; 147 const FramebufferAttachment *getWebGLStencilAttachment() const; 148 149 friend class Framebuffer; 150 151 // The Framebuffer ID is unique to a Context. 152 // The Framebuffer UniqueSerial is unique to a Share Group. 153 FramebufferID mId; 154 rx::UniqueSerial mFramebufferSerial; 155 std::string mLabel; 156 157 DrawBuffersVector<FramebufferAttachment> mColorAttachments; 158 FramebufferAttachment mDepthAttachment; 159 FramebufferAttachment mStencilAttachment; 160 161 // Tracks all the color buffers attached to this FramebufferDesc 162 DrawBufferMask mColorAttachmentsMask; 163 164 DrawBuffersVector<GLenum> mDrawBufferStates; 165 GLenum mReadBufferState; 166 DrawBufferMask mEnabledDrawBuffers; 167 ComponentTypeMask mDrawBufferTypeMask; 168 169 GLint mDefaultWidth; 170 GLint mDefaultHeight; 171 GLint mDefaultSamples; 172 bool mDefaultFixedSampleLocations; 173 GLint mDefaultLayers; 174 bool mFlipY; 175 176 // It's necessary to store all this extra state so we can restore attachments 177 // when DEPTH_STENCIL/DEPTH/STENCIL is unbound in WebGL 1. 178 FramebufferAttachment mWebGLDepthStencilAttachment; 179 FramebufferAttachment mWebGLDepthAttachment; 180 FramebufferAttachment mWebGLStencilAttachment; 181 bool mWebGLDepthStencilConsistent; 182 183 // Tracks if we need to initialize the resources for each attachment. 184 angle::BitSet<IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 2> mResourceNeedsInit; 185 186 bool mDefaultFramebufferReadAttachmentInitialized; 187 FramebufferAttachment mDefaultFramebufferReadAttachment; 188 189 // EXT_sRGB_write_control 190 SrgbWriteControlMode mSrgbWriteControlMode; 191 192 Offset mSurfaceTextureOffset; 193 }; 194 195 class Framebuffer final : public angle::ObserverInterface, 196 public LabeledObject, 197 public angle::Subject 198 { 199 public: 200 // Constructor to build default framebuffers. 201 Framebuffer(const Context *context, rx::GLImplFactory *factory); 202 // Constructor to build application-defined framebuffers 203 Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id); 204 205 ~Framebuffer() override; 206 void onDestroy(const Context *context); 207 208 egl::Error setSurfaces(const Context *context, 209 egl::Surface *surface, 210 egl::Surface *readSurface); 211 void setReadSurface(const Context *context, egl::Surface *readSurface); 212 egl::Error unsetSurfaces(const Context *context); 213 angle::Result setLabel(const Context *context, const std::string &label) override; 214 const std::string &getLabel() const override; 215 getImplementation()216 rx::FramebufferImpl *getImplementation() const { return mImpl; } 217 id()218 FramebufferID id() const { return mState.mId; } 219 220 void setAttachment(const Context *context, 221 GLenum type, 222 GLenum binding, 223 const ImageIndex &textureIndex, 224 FramebufferAttachmentObject *resource); 225 void setAttachmentMultisample(const Context *context, 226 GLenum type, 227 GLenum binding, 228 const ImageIndex &textureIndex, 229 FramebufferAttachmentObject *resource, 230 GLsizei samples); 231 void setAttachmentMultiview(const Context *context, 232 GLenum type, 233 GLenum binding, 234 const ImageIndex &textureIndex, 235 FramebufferAttachmentObject *resource, 236 GLsizei numViews, 237 GLint baseViewIndex); 238 void resetAttachment(const Context *context, GLenum binding); 239 240 bool detachTexture(Context *context, TextureID texture); 241 bool detachRenderbuffer(Context *context, RenderbufferID renderbuffer); 242 243 const FramebufferAttachment *getColorAttachment(size_t colorAttachment) const; 244 const FramebufferAttachment *getDepthAttachment() const; 245 const FramebufferAttachment *getStencilAttachment() const; 246 const FramebufferAttachment *getDepthStencilAttachment() const; 247 const FramebufferAttachment *getDepthOrStencilAttachment() const; 248 const FramebufferAttachment *getStencilOrDepthStencilAttachment() const; 249 const FramebufferAttachment *getReadColorAttachment() const; 250 GLenum getReadColorAttachmentType() const; 251 const FramebufferAttachment *getFirstColorAttachment() const; 252 const FramebufferAttachment *getFirstNonNullAttachment() const; 253 getColorAttachments()254 const DrawBuffersVector<FramebufferAttachment> &getColorAttachments() const 255 { 256 return mState.mColorAttachments; 257 } 258 getState()259 const FramebufferState &getState() const { return mState; } 260 261 const FramebufferAttachment *getAttachment(const Context *context, GLenum attachment) const; 262 bool isMultiview() const; 263 bool readDisallowedByMultiview() const; 264 GLsizei getNumViews() const; 265 GLint getBaseViewIndex() const; 266 Extents getExtents() const; 267 268 size_t getDrawbufferStateCount() const; 269 GLenum getDrawBufferState(size_t drawBuffer) const; 270 const DrawBuffersVector<GLenum> &getDrawBufferStates() const; 271 void setDrawBuffers(size_t count, const GLenum *buffers); 272 const FramebufferAttachment *getDrawBuffer(size_t drawBuffer) const; 273 ComponentType getDrawbufferWriteType(size_t drawBuffer) const; 274 ComponentTypeMask getDrawBufferTypeMask() const; 275 DrawBufferMask getDrawBufferMask() const; 276 bool hasEnabledDrawBuffer() const; 277 278 GLenum getReadBufferState() const; 279 void setReadBuffer(GLenum buffer); 280 281 size_t getNumColorAttachments() const; 282 bool hasDepth() const; 283 bool hasStencil() const; 284 285 bool hasExternalTextureAttachment() const; 286 bool hasYUVAttachment() const; 287 288 bool usingExtendedDrawBuffers() const; 289 290 // This method calls checkStatus. 291 int getSamples(const Context *context) const; 292 int getReadBufferResourceSamples(const Context *context) const; 293 294 angle::Result getSamplePosition(const Context *context, size_t index, GLfloat *xy) const; 295 296 GLint getDefaultWidth() const; 297 GLint getDefaultHeight() const; 298 GLint getDefaultSamples() const; 299 bool getDefaultFixedSampleLocations() const; 300 GLint getDefaultLayers() const; 301 bool getFlipY() const; 302 void setDefaultWidth(const Context *context, GLint defaultWidth); 303 void setDefaultHeight(const Context *context, GLint defaultHeight); 304 void setDefaultSamples(const Context *context, GLint defaultSamples); 305 void setDefaultFixedSampleLocations(const Context *context, bool defaultFixedSampleLocations); 306 void setDefaultLayers(GLint defaultLayers); 307 void setFlipY(bool flipY); 308 309 void invalidateCompletenessCache(); cachedStatusValid()310 ANGLE_INLINE bool cachedStatusValid() { return mCachedStatus.valid(); } 311 checkStatus(const Context * context)312 ANGLE_INLINE const FramebufferStatus &checkStatus(const Context *context) const 313 { 314 // The default framebuffer is always complete except when it is surfaceless in which 315 // case it is always unsupported. 316 ASSERT(!isDefault() || mCachedStatus.valid()); 317 if (isDefault() || (!hasAnyDirtyBit() && mCachedStatus.valid())) 318 { 319 return mCachedStatus.value(); 320 } 321 322 return checkStatusImpl(context); 323 } 324 325 // Helper for checkStatus == GL_FRAMEBUFFER_COMPLETE. isComplete(const Context * context)326 ANGLE_INLINE bool isComplete(const Context *context) const 327 { 328 return checkStatus(context).isComplete(); 329 } 330 331 bool hasValidDepthStencil() const; 332 333 // Returns the offset into the texture backing the default framebuffer's surface if any. Returns 334 // zero offset otherwise. The renderer will apply the offset to scissor and viewport rects used 335 // for draws, clears, and blits. 336 const Offset &getSurfaceTextureOffset() const; 337 338 angle::Result discard(const Context *context, size_t count, const GLenum *attachments); 339 angle::Result invalidate(const Context *context, size_t count, const GLenum *attachments); 340 angle::Result invalidateSub(const Context *context, 341 size_t count, 342 const GLenum *attachments, 343 const Rectangle &area); 344 345 angle::Result clear(const Context *context, GLbitfield mask); 346 angle::Result clearBufferfv(const Context *context, 347 GLenum buffer, 348 GLint drawbuffer, 349 const GLfloat *values); 350 angle::Result clearBufferuiv(const Context *context, 351 GLenum buffer, 352 GLint drawbuffer, 353 const GLuint *values); 354 angle::Result clearBufferiv(const Context *context, 355 GLenum buffer, 356 GLint drawbuffer, 357 const GLint *values); 358 angle::Result clearBufferfi(const Context *context, 359 GLenum buffer, 360 GLint drawbuffer, 361 GLfloat depth, 362 GLint stencil); 363 364 GLenum getImplementationColorReadFormat(const Context *context); 365 GLenum getImplementationColorReadType(const Context *context); 366 367 angle::Result readPixels(const Context *context, 368 const Rectangle &area, 369 GLenum format, 370 GLenum type, 371 const PixelPackState &pack, 372 Buffer *packBuffer, 373 void *pixels); 374 375 angle::Result blit(const Context *context, 376 const Rectangle &sourceArea, 377 const Rectangle &destArea, 378 GLbitfield mask, 379 GLenum filter); isDefault()380 bool isDefault() const { return mState.isDefault(); } 381 382 enum DirtyBitType : size_t 383 { 384 DIRTY_BIT_COLOR_ATTACHMENT_0, 385 DIRTY_BIT_COLOR_ATTACHMENT_MAX = 386 DIRTY_BIT_COLOR_ATTACHMENT_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS, 387 DIRTY_BIT_DEPTH_ATTACHMENT = DIRTY_BIT_COLOR_ATTACHMENT_MAX, 388 DIRTY_BIT_STENCIL_ATTACHMENT, 389 DIRTY_BIT_COLOR_BUFFER_CONTENTS_0, 390 DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX = 391 DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + IMPLEMENTATION_MAX_DRAW_BUFFERS, 392 DIRTY_BIT_DEPTH_BUFFER_CONTENTS = DIRTY_BIT_COLOR_BUFFER_CONTENTS_MAX, 393 DIRTY_BIT_STENCIL_BUFFER_CONTENTS, 394 DIRTY_BIT_DRAW_BUFFERS, 395 DIRTY_BIT_READ_BUFFER, 396 DIRTY_BIT_DEFAULT_WIDTH, 397 DIRTY_BIT_DEFAULT_HEIGHT, 398 DIRTY_BIT_DEFAULT_SAMPLES, 399 DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS, 400 DIRTY_BIT_DEFAULT_LAYERS, 401 DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE, 402 DIRTY_BIT_FLIP_Y, 403 DIRTY_BIT_UNKNOWN, 404 DIRTY_BIT_MAX = DIRTY_BIT_UNKNOWN 405 }; 406 407 using DirtyBits = angle::BitSet<DIRTY_BIT_MAX>; hasAnyDirtyBit()408 bool hasAnyDirtyBit() const { return mDirtyBits.any(); } 409 getActiveFloat32ColorAttachmentDrawBufferMask()410 DrawBufferMask getActiveFloat32ColorAttachmentDrawBufferMask() const 411 { 412 return mFloat32ColorAttachmentBits & getDrawBufferMask(); 413 } 414 getActiveSharedExponentColorAttachmentDrawBufferMask()415 DrawBufferMask getActiveSharedExponentColorAttachmentDrawBufferMask() const 416 { 417 return mSharedExponentColorAttachmentBits & getDrawBufferMask(); 418 } 419 hasResourceThatNeedsInit()420 bool hasResourceThatNeedsInit() const { return mState.mResourceNeedsInit.any(); } 421 422 angle::Result syncState(const Context *context, 423 GLenum framebufferBinding, 424 Command command) const; 425 426 void setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode); 427 428 // Observer implementation 429 void onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) override; 430 431 bool formsRenderingFeedbackLoopWith(const Context *context) const; 432 bool formsCopyingFeedbackLoopWith(TextureID copyTextureID, 433 GLint copyTextureLevel, 434 GLint copyTextureLayer) const; 435 436 angle::Result ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask); 437 angle::Result ensureClearBufferAttachmentsInitialized(const Context *context, 438 GLenum buffer, 439 GLint drawbuffer); 440 angle::Result ensureDrawAttachmentsInitialized(const Context *context); 441 442 // Conservatively initializes both read color and depth. Blit can access the depth buffer. 443 angle::Result ensureReadAttachmentsInitialized(const Context *context); 444 Box getDimensions() const; 445 446 // ANGLE_shader_pixel_local_storage. 447 // Lazily creates a PixelLocalStorage object for this Framebuffer. 448 PixelLocalStorage &getPixelLocalStorage(const Context *); 449 // Returns nullptr if the pixel local storage object has not been created yet. peekPixelLocalStorage()450 PixelLocalStorage *peekPixelLocalStorage() const { return mPixelLocalStorage.get(); } 451 // Detaches the the pixel local storage object so the Context can call deleteContextObjects(). 452 std::unique_ptr<PixelLocalStorage> detachPixelLocalStorage(); 453 454 static const FramebufferID kDefaultDrawFramebufferHandle; 455 456 private: 457 bool detachResourceById(Context *context, GLenum resourceType, GLuint resourceId); 458 bool detachMatchingAttachment(Context *context, 459 FramebufferAttachment *attachment, 460 GLenum matchType, 461 GLuint matchId); 462 FramebufferStatus checkStatusWithGLFrontEnd(const Context *context) const; 463 const FramebufferStatus &checkStatusImpl(const Context *context) const; 464 void setAttachment(const Context *context, 465 GLenum type, 466 GLenum binding, 467 const ImageIndex &textureIndex, 468 FramebufferAttachmentObject *resource, 469 GLsizei numViews, 470 GLuint baseViewIndex, 471 bool isMultiview, 472 GLsizei samplesIn); 473 void commitWebGL1DepthStencilIfConsistent(const Context *context, 474 GLsizei numViews, 475 GLuint baseViewIndex, 476 bool isMultiview, 477 GLsizei samples); 478 void setAttachmentImpl(const Context *context, 479 GLenum type, 480 GLenum binding, 481 const ImageIndex &textureIndex, 482 FramebufferAttachmentObject *resource, 483 GLsizei numViews, 484 GLuint baseViewIndex, 485 bool isMultiview, 486 GLsizei samples); 487 void updateAttachment(const Context *context, 488 FramebufferAttachment *attachment, 489 size_t dirtyBit, 490 angle::ObserverBinding *onDirtyBinding, 491 GLenum type, 492 GLenum binding, 493 const ImageIndex &textureIndex, 494 FramebufferAttachmentObject *resource, 495 GLsizei numViews, 496 GLuint baseViewIndex, 497 bool isMultiview, 498 GLsizei samples); 499 500 void markDrawAttachmentsInitialized(bool color, bool depth, bool stencil); 501 void markBufferInitialized(GLenum bufferType, GLint bufferIndex); 502 angle::Result ensureBufferInitialized(const Context *context, 503 GLenum bufferType, 504 GLint bufferIndex); 505 506 // Checks that we have a partially masked clear: 507 // * some color channels are masked out 508 // * some stencil values are masked out 509 // * scissor test partially overlaps the framebuffer 510 bool partialClearNeedsInit(const Context *context, bool color, bool depth, bool stencil); 511 bool partialBufferClearNeedsInit(const Context *context, GLenum bufferType); 512 513 FramebufferAttachment *getAttachmentFromSubjectIndex(angle::SubjectIndex index); 514 updateFloat32AndSharedExponentColorAttachmentBits(size_t index,const InternalFormat * format)515 ANGLE_INLINE void updateFloat32AndSharedExponentColorAttachmentBits( 516 size_t index, 517 const InternalFormat *format) 518 { 519 mFloat32ColorAttachmentBits.set(index, format->type == GL_FLOAT); 520 mSharedExponentColorAttachmentBits.set(index, format->type == GL_UNSIGNED_INT_5_9_9_9_REV); 521 } 522 523 angle::Result syncAllDrawAttachmentState(const Context *context, Command command) const; 524 angle::Result syncAttachmentState(const Context *context, 525 Command command, 526 const FramebufferAttachment *attachment) const; 527 528 FramebufferState mState; 529 rx::FramebufferImpl *mImpl; 530 531 mutable Optional<FramebufferStatus> mCachedStatus; 532 DrawBuffersVector<angle::ObserverBinding> mDirtyColorAttachmentBindings; 533 angle::ObserverBinding mDirtyDepthAttachmentBinding; 534 angle::ObserverBinding mDirtyStencilAttachmentBinding; 535 536 mutable DirtyBits mDirtyBits; 537 DrawBufferMask mFloat32ColorAttachmentBits; 538 DrawBufferMask mSharedExponentColorAttachmentBits; 539 540 // The dirty bits guard is checked when we get a dependent state change message. We verify that 541 // we don't set a dirty bit that isn't already set, when inside the dirty bits syncState. 542 mutable Optional<DirtyBits> mDirtyBitsGuard; 543 544 // ANGLE_shader_pixel_local_storage 545 std::unique_ptr<PixelLocalStorage> mPixelLocalStorage; 546 }; 547 548 using UniqueFramebufferPointer = angle::UniqueObjectPointer<Framebuffer, Context>; 549 550 } // namespace gl 551 552 #endif // LIBANGLE_FRAMEBUFFER_H_ 553