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