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