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