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