Framebuffer.cpp (97242B)
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.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer 8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. 9 10 #include "libANGLE/Framebuffer.h" 11 12 #include "common/Optional.h" 13 #include "common/bitset_utils.h" 14 #include "common/utilities.h" 15 #include "libANGLE/Config.h" 16 #include "libANGLE/Context.h" 17 #include "libANGLE/Display.h" 18 #include "libANGLE/ErrorStrings.h" 19 #include "libANGLE/FramebufferAttachment.h" 20 #include "libANGLE/PixelLocalStorage.h" 21 #include "libANGLE/Renderbuffer.h" 22 #include "libANGLE/Surface.h" 23 #include "libANGLE/Texture.h" 24 #include "libANGLE/angletypes.h" 25 #include "libANGLE/formatutils.h" 26 #include "libANGLE/renderer/ContextImpl.h" 27 #include "libANGLE/renderer/FramebufferImpl.h" 28 #include "libANGLE/renderer/GLImplFactory.h" 29 #include "libANGLE/renderer/RenderbufferImpl.h" 30 #include "libANGLE/renderer/SurfaceImpl.h" 31 32 using namespace angle; 33 34 namespace gl 35 { 36 37 namespace 38 { 39 40 // Check the |checkAttachment| in reference to |firstAttachment| for the sake of multiview 41 // framebuffer completeness. 42 FramebufferStatus CheckMultiviewStateMatchesForCompleteness( 43 const FramebufferAttachment *firstAttachment, 44 const FramebufferAttachment *checkAttachment) 45 { 46 ASSERT(firstAttachment && checkAttachment); 47 ASSERT(firstAttachment->isAttached() && checkAttachment->isAttached()); 48 49 if (firstAttachment->isMultiview() != checkAttachment->isMultiview()) 50 { 51 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 52 err::kFramebufferIncompleteMultiviewMismatch); 53 } 54 if (firstAttachment->getNumViews() != checkAttachment->getNumViews()) 55 { 56 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 57 err::kFramebufferIncompleteMultiviewViewsMismatch); 58 } 59 if (checkAttachment->getBaseViewIndex() + checkAttachment->getNumViews() > 60 checkAttachment->getSize().depth) 61 { 62 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR, 63 err::kFramebufferIncompleteMultiviewBaseViewMismatch); 64 } 65 66 return FramebufferStatus::Complete(); 67 } 68 69 FramebufferStatus CheckAttachmentCompleteness(const Context *context, 70 const FramebufferAttachment &attachment) 71 { 72 ASSERT(attachment.isAttached()); 73 74 const Extents &size = attachment.getSize(); 75 if (size.width == 0 || size.height == 0) 76 { 77 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 78 err::kFramebufferIncompleteAttachmentZeroSize); 79 } 80 81 if (!attachment.isRenderable(context)) 82 { 83 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 84 err::kFramebufferIncompleteAttachmentNotRenderable); 85 } 86 87 if (attachment.type() == GL_TEXTURE) 88 { 89 // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness" 90 // If <image> is a three-dimensional texture or a two-dimensional array texture and the 91 // attachment is not layered, the selected layer is less than the depth or layer count, 92 // respectively, of the texture. 93 if (!attachment.isLayered()) 94 { 95 if (attachment.layer() >= size.depth) 96 { 97 return FramebufferStatus::Incomplete( 98 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 99 err::kFramebufferIncompleteAttachmentLayerGreaterThanDepth); 100 } 101 } 102 // If <image> is a three-dimensional texture or a two-dimensional array texture and the 103 // attachment is layered, the depth or layer count, respectively, of the texture is less 104 // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT. 105 else 106 { 107 if (size.depth >= context->getCaps().maxFramebufferLayers) 108 { 109 return FramebufferStatus::Incomplete( 110 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 111 err::kFramebufferIncompleteAttachmentDepthGreaterThanMaxLayers); 112 } 113 } 114 115 // ES3 specifies that cube map texture attachments must be cube complete. 116 // This language is missing from the ES2 spec, but we enforce it here because some 117 // desktop OpenGL drivers also enforce this validation. 118 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness. 119 const Texture *texture = attachment.getTexture(); 120 ASSERT(texture); 121 if (texture->getType() == TextureType::CubeMap && 122 !texture->getTextureState().isCubeComplete()) 123 { 124 return FramebufferStatus::Incomplete( 125 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 126 err::kFramebufferIncompleteAttachmentNotCubeComplete); 127 } 128 129 if (!texture->getImmutableFormat()) 130 { 131 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel()); 132 133 // From the ES 3.0 spec, pg 213: 134 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of 135 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture, 136 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the 137 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is 138 // the effective maximum texture level defined in the Mipmapping discussion of 139 // section 3.8.10.4. 140 if (attachmentMipLevel < texture->getBaseLevel() || 141 attachmentMipLevel > texture->getMipmapMaxLevel()) 142 { 143 return FramebufferStatus::Incomplete( 144 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 145 err::kFramebufferIncompleteAttachmentLevelOutOfBaseMaxLevelRange); 146 } 147 148 // Form the ES 3.0 spec, pg 213/214: 149 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of 150 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and 151 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the 152 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names 153 // a cubemap texture, the texture must also be cube complete. 154 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete()) 155 { 156 return FramebufferStatus::Incomplete( 157 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 158 err::kFramebufferIncompleteAttachmentLevelNotBaseLevelForIncompleteMipTexture); 159 } 160 } 161 } 162 163 return FramebufferStatus::Complete(); 164 } 165 166 FramebufferStatus CheckAttachmentSampleCounts(const Context *context, 167 GLsizei currAttachmentSamples, 168 GLsizei samples, 169 bool colorAttachment) 170 { 171 if (currAttachmentSamples != samples) 172 { 173 if (colorAttachment) 174 { 175 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that 176 // all color attachments have the same number of samples for the FBO to be complete. 177 return FramebufferStatus::Incomplete( 178 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 179 err::kFramebufferIncompleteMultisampleInconsistentSampleCounts); 180 } 181 else 182 { 183 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete 184 // when its depth or stencil samples are a multiple of the number of color samples. 185 if (!context->getExtensions().framebufferMixedSamplesCHROMIUM) 186 { 187 return FramebufferStatus::Incomplete( 188 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 189 err::kFramebufferIncompleteMultisampleInconsistentSampleCounts); 190 } 191 192 if ((currAttachmentSamples % std::max(samples, 1)) != 0) 193 { 194 return FramebufferStatus::Incomplete( 195 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 196 err:: 197 kFramebufferIncompleteMultisampleDepthStencilSampleCountDivisibleByColorSampleCount); 198 } 199 } 200 } 201 202 return FramebufferStatus::Complete(); 203 } 204 205 FramebufferStatus CheckAttachmentSampleCompleteness(const Context *context, 206 const FramebufferAttachment &attachment, 207 bool colorAttachment, 208 Optional<int> *samples, 209 Optional<bool> *fixedSampleLocations, 210 Optional<int> *renderToTextureSamples) 211 { 212 ASSERT(attachment.isAttached()); 213 214 if (attachment.type() == GL_TEXTURE) 215 { 216 const Texture *texture = attachment.getTexture(); 217 ASSERT(texture); 218 GLenum sizedInternalFormat = attachment.getFormat().info->sizedInternalFormat; 219 const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); 220 if (static_cast<GLuint>(attachment.getSamples()) > formatCaps.getMaxSamples()) 221 { 222 return FramebufferStatus::Incomplete( 223 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 224 err::kFramebufferIncompleteAttachmentSamplesGreaterThanMaxSupportedSamples); 225 } 226 227 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex(); 228 bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex); 229 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value()) 230 { 231 return FramebufferStatus::Incomplete( 232 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 233 err::kFramebufferIncompleteMultisampleInconsistentFixedSampleLocations); 234 } 235 else 236 { 237 *fixedSampleLocations = fixedSampleloc; 238 } 239 } 240 241 if (renderToTextureSamples->valid()) 242 { 243 // Only check against RenderToTextureSamples if they actually exist. 244 if (renderToTextureSamples->value() != 245 FramebufferAttachment::kDefaultRenderToTextureSamples) 246 { 247 FramebufferStatus sampleCountStatus = 248 CheckAttachmentSampleCounts(context, attachment.getRenderToTextureSamples(), 249 renderToTextureSamples->value(), colorAttachment); 250 if (!sampleCountStatus.isComplete()) 251 { 252 return sampleCountStatus; 253 } 254 } 255 } 256 else 257 { 258 *renderToTextureSamples = attachment.getRenderToTextureSamples(); 259 } 260 261 if (samples->valid()) 262 { 263 // RenderToTextureSamples takes precedence if they exist. 264 if (renderToTextureSamples->value() == 265 FramebufferAttachment::kDefaultRenderToTextureSamples) 266 { 267 268 FramebufferStatus sampleCountStatus = CheckAttachmentSampleCounts( 269 context, attachment.getSamples(), samples->value(), colorAttachment); 270 if (!sampleCountStatus.isComplete()) 271 { 272 return sampleCountStatus; 273 } 274 } 275 } 276 else 277 { 278 *samples = attachment.getSamples(); 279 } 280 281 return FramebufferStatus::Complete(); 282 } 283 284 // Needed to index into the attachment arrays/bitsets. 285 static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) == 286 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX, 287 "Framebuffer Dirty bit mismatch"); 288 static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS) == 289 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT, 290 "Framebuffer Dirty bit mismatch"); 291 static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_DRAW_BUFFERS + 1) == 292 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT, 293 "Framebuffer Dirty bit mismatch"); 294 295 angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment) 296 { 297 ASSERT(attachment->isAttached()); 298 if (attachment->initState() == InitState::MayNeedInit) 299 { 300 ANGLE_TRY(attachment->initializeContents(context)); 301 } 302 return angle::Result::Continue; 303 } 304 305 bool AttachmentOverlapsWithTexture(const FramebufferAttachment &attachment, 306 const Texture *texture, 307 const Sampler *sampler) 308 { 309 if (!attachment.isTextureWithId(texture->id())) 310 { 311 return false; 312 } 313 314 const gl::ImageIndex &index = attachment.getTextureImageIndex(); 315 GLuint attachmentLevel = static_cast<GLuint>(index.getLevelIndex()); 316 GLuint textureEffectiveBaseLevel = texture->getTextureState().getEffectiveBaseLevel(); 317 GLuint textureMaxLevel = textureEffectiveBaseLevel; 318 if ((sampler && IsMipmapFiltered(sampler->getSamplerState().getMinFilter())) || 319 IsMipmapFiltered(texture->getSamplerState().getMinFilter())) 320 { 321 textureMaxLevel = texture->getMipmapMaxLevel(); 322 } 323 324 return attachmentLevel >= textureEffectiveBaseLevel && attachmentLevel <= textureMaxLevel; 325 } 326 327 } // anonymous namespace 328 329 bool FramebufferStatus::isComplete() const 330 { 331 return status == GL_FRAMEBUFFER_COMPLETE; 332 } 333 334 FramebufferStatus FramebufferStatus::Complete() 335 { 336 FramebufferStatus result; 337 result.status = GL_FRAMEBUFFER_COMPLETE; 338 result.reason = nullptr; 339 return result; 340 } 341 342 FramebufferStatus FramebufferStatus::Incomplete(GLenum status, const char *reason) 343 { 344 ASSERT(status != GL_FRAMEBUFFER_COMPLETE); 345 346 FramebufferStatus result; 347 result.status = status; 348 result.reason = reason; 349 return result; 350 } 351 352 // This constructor is only used for default framebuffers. 353 FramebufferState::FramebufferState(rx::Serial serial) 354 : mId(Framebuffer::kDefaultDrawFramebufferHandle), 355 mFramebufferSerial(serial), 356 mLabel(), 357 mColorAttachments(1), 358 mColorAttachmentsMask(0), 359 mDrawBufferStates(1, GL_BACK), 360 mReadBufferState(GL_BACK), 361 mDrawBufferTypeMask(), 362 mDefaultWidth(0), 363 mDefaultHeight(0), 364 mDefaultSamples(0), 365 mDefaultFixedSampleLocations(GL_FALSE), 366 mDefaultLayers(0), 367 mFlipY(GL_FALSE), 368 mWebGLDepthStencilConsistent(true), 369 mDefaultFramebufferReadAttachmentInitialized(false), 370 mSrgbWriteControlMode(SrgbWriteControlMode::Default) 371 { 372 ASSERT(mDrawBufferStates.size() > 0); 373 mEnabledDrawBuffers.set(0); 374 } 375 376 FramebufferState::FramebufferState(const Caps &caps, FramebufferID id, rx::Serial serial) 377 : mId(id), 378 mFramebufferSerial(serial), 379 mLabel(), 380 mColorAttachments(caps.maxColorAttachments), 381 mColorAttachmentsMask(0), 382 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE), 383 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT), 384 mDrawBufferTypeMask(), 385 mDefaultWidth(0), 386 mDefaultHeight(0), 387 mDefaultSamples(0), 388 mDefaultFixedSampleLocations(GL_FALSE), 389 mDefaultLayers(0), 390 mFlipY(GL_FALSE), 391 mWebGLDepthStencilConsistent(true), 392 mDefaultFramebufferReadAttachmentInitialized(false), 393 mSrgbWriteControlMode(SrgbWriteControlMode::Default) 394 { 395 ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle); 396 ASSERT(mDrawBufferStates.size() > 0); 397 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; 398 } 399 400 FramebufferState::~FramebufferState() {} 401 402 const std::string &FramebufferState::getLabel() const 403 { 404 return mLabel; 405 } 406 407 const FramebufferAttachment *FramebufferState::getAttachment(const Context *context, 408 GLenum attachment) const 409 { 410 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15) 411 { 412 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0); 413 } 414 415 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e. 416 // multiple conflicting attachment points) and requires us to return the framebuffer attachment 417 // associated with WebGL. 418 switch (attachment) 419 { 420 case GL_COLOR: 421 case GL_BACK: 422 return getColorAttachment(0); 423 case GL_DEPTH: 424 case GL_DEPTH_ATTACHMENT: 425 if (context->isWebGL1()) 426 { 427 return getWebGLDepthAttachment(); 428 } 429 else 430 { 431 return getDepthAttachment(); 432 } 433 case GL_STENCIL: 434 case GL_STENCIL_ATTACHMENT: 435 if (context->isWebGL1()) 436 { 437 return getWebGLStencilAttachment(); 438 } 439 else 440 { 441 return getStencilAttachment(); 442 } 443 case GL_DEPTH_STENCIL: 444 case GL_DEPTH_STENCIL_ATTACHMENT: 445 if (context->isWebGL1()) 446 { 447 return getWebGLDepthStencilAttachment(); 448 } 449 else 450 { 451 return getDepthStencilAttachment(); 452 } 453 default: 454 UNREACHABLE(); 455 return nullptr; 456 } 457 } 458 459 uint32_t FramebufferState::getReadIndex() const 460 { 461 ASSERT(mReadBufferState == GL_BACK || 462 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15)); 463 uint32_t readIndex = mReadBufferState == GL_BACK ? 0 : mReadBufferState - GL_COLOR_ATTACHMENT0; 464 ASSERT(readIndex < mColorAttachments.size()); 465 return readIndex; 466 } 467 468 const FramebufferAttachment *FramebufferState::getReadAttachment() const 469 { 470 if (mReadBufferState == GL_NONE) 471 { 472 return nullptr; 473 } 474 475 uint32_t readIndex = getReadIndex(); 476 const gl::FramebufferAttachment &framebufferAttachment = 477 isDefault() ? mDefaultFramebufferReadAttachment : mColorAttachments[readIndex]; 478 479 return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr; 480 } 481 482 const FramebufferAttachment *FramebufferState::getReadPixelsAttachment(GLenum readFormat) const 483 { 484 switch (readFormat) 485 { 486 case GL_DEPTH_COMPONENT: 487 return getDepthAttachment(); 488 case GL_STENCIL_INDEX_OES: 489 return getStencilOrDepthStencilAttachment(); 490 case GL_DEPTH_STENCIL_OES: 491 return getDepthStencilAttachment(); 492 default: 493 return getReadAttachment(); 494 } 495 } 496 497 const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const 498 { 499 auto *colorAttachment = getFirstColorAttachment(); 500 if (colorAttachment) 501 { 502 return colorAttachment; 503 } 504 return getDepthOrStencilAttachment(); 505 } 506 507 const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const 508 { 509 for (const FramebufferAttachment &colorAttachment : mColorAttachments) 510 { 511 if (colorAttachment.isAttached()) 512 { 513 return &colorAttachment; 514 } 515 } 516 517 return nullptr; 518 } 519 520 const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const 521 { 522 if (mDepthAttachment.isAttached()) 523 { 524 return &mDepthAttachment; 525 } 526 if (mStencilAttachment.isAttached()) 527 { 528 return &mStencilAttachment; 529 } 530 return nullptr; 531 } 532 533 const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const 534 { 535 if (mStencilAttachment.isAttached()) 536 { 537 return &mStencilAttachment; 538 } 539 return getDepthStencilAttachment(); 540 } 541 542 const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const 543 { 544 ASSERT(colorAttachment < mColorAttachments.size()); 545 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment] 546 : nullptr; 547 } 548 549 const FramebufferAttachment *FramebufferState::getDepthAttachment() const 550 { 551 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr; 552 } 553 554 const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const 555 { 556 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr; 557 } 558 559 const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const 560 { 561 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr; 562 } 563 564 const FramebufferAttachment *FramebufferState::getStencilAttachment() const 565 { 566 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr; 567 } 568 569 const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const 570 { 571 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr; 572 } 573 574 const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const 575 { 576 // A valid depth-stencil attachment has the same resource bound to both the 577 // depth and stencil attachment points. 578 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() && 579 mDepthAttachment == mStencilAttachment) 580 { 581 return &mDepthAttachment; 582 } 583 584 return nullptr; 585 } 586 587 const Extents FramebufferState::getAttachmentExtentsIntersection() const 588 { 589 int32_t width = std::numeric_limits<int32_t>::max(); 590 int32_t height = std::numeric_limits<int32_t>::max(); 591 for (const FramebufferAttachment &attachment : mColorAttachments) 592 { 593 if (attachment.isAttached()) 594 { 595 width = std::min(width, attachment.getSize().width); 596 height = std::min(height, attachment.getSize().height); 597 } 598 } 599 600 if (mDepthAttachment.isAttached()) 601 { 602 width = std::min(width, mDepthAttachment.getSize().width); 603 height = std::min(height, mDepthAttachment.getSize().height); 604 } 605 606 if (mStencilAttachment.isAttached()) 607 { 608 width = std::min(width, mStencilAttachment.getSize().width); 609 height = std::min(height, mStencilAttachment.getSize().height); 610 } 611 612 return Extents(width, height, 0); 613 } 614 615 bool FramebufferState::attachmentsHaveSameDimensions() const 616 { 617 Optional<Extents> attachmentSize; 618 619 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) { 620 if (!attachment.isAttached()) 621 { 622 return false; 623 } 624 625 if (!attachmentSize.valid()) 626 { 627 attachmentSize = attachment.getSize(); 628 return false; 629 } 630 631 const auto &prevSize = attachmentSize.value(); 632 const auto &curSize = attachment.getSize(); 633 return (curSize.width != prevSize.width || curSize.height != prevSize.height); 634 }; 635 636 for (const auto &attachment : mColorAttachments) 637 { 638 if (hasMismatchedSize(attachment)) 639 { 640 return false; 641 } 642 } 643 644 if (hasMismatchedSize(mDepthAttachment)) 645 { 646 return false; 647 } 648 649 return !hasMismatchedSize(mStencilAttachment); 650 } 651 652 bool FramebufferState::hasSeparateDepthAndStencilAttachments() const 653 { 654 // if we have both a depth and stencil buffer, they must refer to the same object 655 // since we only support packed_depth_stencil and not separate depth and stencil 656 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr && 657 getDepthStencilAttachment() == nullptr); 658 } 659 660 const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const 661 { 662 ASSERT(drawBufferIdx < mDrawBufferStates.size()); 663 if (mDrawBufferStates[drawBufferIdx] != GL_NONE) 664 { 665 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs 666 // must be COLOR_ATTACHMENTi or NONE" 667 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx || 668 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK)); 669 670 if (mDrawBufferStates[drawBufferIdx] == GL_BACK) 671 { 672 return getColorAttachment(0); 673 } 674 else 675 { 676 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0); 677 } 678 } 679 else 680 { 681 return nullptr; 682 } 683 } 684 685 size_t FramebufferState::getDrawBufferCount() const 686 { 687 return mDrawBufferStates.size(); 688 } 689 690 bool FramebufferState::colorAttachmentsAreUniqueImages() const 691 { 692 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size(); 693 firstAttachmentIdx++) 694 { 695 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx]; 696 if (!firstAttachment.isAttached()) 697 { 698 continue; 699 } 700 701 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1; 702 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++) 703 { 704 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx]; 705 if (!secondAttachment.isAttached()) 706 { 707 continue; 708 } 709 710 if (firstAttachment == secondAttachment) 711 { 712 return false; 713 } 714 } 715 } 716 717 return true; 718 } 719 720 bool FramebufferState::hasDepth() const 721 { 722 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0); 723 } 724 725 bool FramebufferState::hasStencil() const 726 { 727 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0); 728 } 729 730 bool FramebufferState::hasExternalTextureAttachment() const 731 { 732 // External textures can only be bound to color attachment 0 733 return (mColorAttachments[0].isAttached() && mColorAttachments[0].isExternalTexture()); 734 } 735 736 bool FramebufferState::hasYUVAttachment() const 737 { 738 // The only attachments that can be YUV are external textures and surfaces, both are attached at 739 // color attachment 0. 740 return (mColorAttachments[0].isAttached() && mColorAttachments[0].isYUV()); 741 } 742 743 bool FramebufferState::isMultiview() const 744 { 745 const FramebufferAttachment *attachment = getFirstNonNullAttachment(); 746 if (attachment == nullptr) 747 { 748 return false; 749 } 750 return attachment->isMultiview(); 751 } 752 753 int FramebufferState::getBaseViewIndex() const 754 { 755 const FramebufferAttachment *attachment = getFirstNonNullAttachment(); 756 if (attachment == nullptr) 757 { 758 return GL_NONE; 759 } 760 return attachment->getBaseViewIndex(); 761 } 762 763 Box FramebufferState::getDimensions() const 764 { 765 Extents extents = getExtents(); 766 return Box(0, 0, 0, extents.width, extents.height, extents.depth); 767 } 768 769 Extents FramebufferState::getExtents() const 770 { 771 // OpenGLES3.0 (https://www.khronos.org/registry/OpenGL/specs/es/3.0/es_spec_3.0.pdf 772 // section 4.4.4.2) allows attachments have unequal size. 773 const FramebufferAttachment *first = getFirstNonNullAttachment(); 774 if (first) 775 { 776 return getAttachmentExtentsIntersection(); 777 } 778 return Extents(getDefaultWidth(), getDefaultHeight(), 0); 779 } 780 781 bool FramebufferState::isDefault() const 782 { 783 return mId == Framebuffer::kDefaultDrawFramebufferHandle; 784 } 785 786 bool FramebufferState::isBoundAsDrawFramebuffer(const Context *context) const 787 { 788 return context->getState().getDrawFramebuffer()->id() == mId; 789 } 790 791 const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0}; 792 793 Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory) 794 : mState(context->getShareGroup()->generateFramebufferSerial()), 795 mImpl(factory->createFramebuffer(mState)), 796 mCachedStatus(FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES, 797 err::kFramebufferIncompleteSurfaceless)), 798 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT), 799 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT) 800 { 801 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0); 802 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask); 803 } 804 805 Framebuffer::Framebuffer(const Context *context, rx::GLImplFactory *factory, FramebufferID id) 806 : mState(context->getCaps(), id, context->getShareGroup()->generateFramebufferSerial()), 807 mImpl(factory->createFramebuffer(mState)), 808 mCachedStatus(), 809 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT), 810 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT) 811 { 812 ASSERT(mImpl != nullptr); 813 ASSERT(mState.mColorAttachments.size() == 814 static_cast<size_t>(context->getCaps().maxColorAttachments)); 815 816 for (uint32_t colorIndex = 0; 817 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex) 818 { 819 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex); 820 } 821 if (context->getClientVersion() >= ES_3_0) 822 { 823 mDirtyBits.set(DIRTY_BIT_READ_BUFFER); 824 } 825 } 826 827 Framebuffer::~Framebuffer() 828 { 829 SafeDelete(mImpl); 830 } 831 832 void Framebuffer::onDestroy(const Context *context) 833 { 834 if (isDefault()) 835 { 836 std::ignore = unsetSurfaces(context); 837 } 838 839 for (auto &attachment : mState.mColorAttachments) 840 { 841 attachment.detach(context, mState.mFramebufferSerial); 842 } 843 mState.mDepthAttachment.detach(context, mState.mFramebufferSerial); 844 mState.mStencilAttachment.detach(context, mState.mFramebufferSerial); 845 mState.mWebGLDepthAttachment.detach(context, mState.mFramebufferSerial); 846 mState.mWebGLStencilAttachment.detach(context, mState.mFramebufferSerial); 847 mState.mWebGLDepthStencilAttachment.detach(context, mState.mFramebufferSerial); 848 849 if (mPixelLocalStorage) 850 { 851 mPixelLocalStorage->onFramebufferDestroyed(context); 852 } 853 854 mImpl->destroy(context); 855 } 856 857 egl::Error Framebuffer::setSurfaces(const Context *context, 858 egl::Surface *surface, 859 egl::Surface *readSurface) 860 { 861 // This has to be a default framebuffer. 862 ASSERT(isDefault()); 863 ASSERT(mDirtyColorAttachmentBindings.size() == 1); 864 ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0); 865 866 ASSERT(!mState.mColorAttachments[0].isAttached()); 867 ASSERT(!mState.mDepthAttachment.isAttached()); 868 ASSERT(!mState.mStencilAttachment.isAttached()); 869 870 if (surface) 871 { 872 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface, 873 FramebufferAttachment::kDefaultNumViews, 874 FramebufferAttachment::kDefaultBaseViewIndex, false, 875 FramebufferAttachment::kDefaultRenderToTextureSamples); 876 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0); 877 878 if (surface->getConfig()->depthSize > 0) 879 { 880 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface, 881 FramebufferAttachment::kDefaultNumViews, 882 FramebufferAttachment::kDefaultBaseViewIndex, false, 883 FramebufferAttachment::kDefaultRenderToTextureSamples); 884 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); 885 } 886 887 if (surface->getConfig()->stencilSize > 0) 888 { 889 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface, 890 FramebufferAttachment::kDefaultNumViews, 891 FramebufferAttachment::kDefaultBaseViewIndex, false, 892 FramebufferAttachment::kDefaultRenderToTextureSamples); 893 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); 894 } 895 896 mState.mSurfaceTextureOffset = surface->getTextureOffset(); 897 898 // Ensure the backend has a chance to synchronize its content for a new backbuffer. 899 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0); 900 } 901 902 setReadSurface(context, readSurface); 903 904 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask); 905 906 ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES); 907 ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless); 908 if (surface) 909 { 910 mCachedStatus = FramebufferStatus::Complete(); 911 ANGLE_TRY(surface->getImplementation()->attachToFramebuffer(context, this)); 912 } 913 914 return egl::NoError(); 915 } 916 917 void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface) 918 { 919 // This has to be a default framebuffer. 920 ASSERT(isDefault()); 921 ASSERT(mDirtyColorAttachmentBindings.size() == 1); 922 ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0); 923 924 // Read surface is not attached. 925 ASSERT(!mState.mDefaultFramebufferReadAttachment.isAttached()); 926 927 // updateAttachment() without mState.mResourceNeedsInit.set() 928 mState.mDefaultFramebufferReadAttachment.attach( 929 context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface, 930 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex, 931 false, FramebufferAttachment::kDefaultRenderToTextureSamples, mState.mFramebufferSerial); 932 933 if (context->getClientVersion() >= ES_3_0) 934 { 935 mDirtyBits.set(DIRTY_BIT_READ_BUFFER); 936 } 937 } 938 939 egl::Error Framebuffer::unsetSurfaces(const Context *context) 940 { 941 // This has to be a default framebuffer. 942 ASSERT(isDefault()); 943 ASSERT(mDirtyColorAttachmentBindings.size() == 1); 944 ASSERT(mDirtyColorAttachmentBindings[0].getSubjectIndex() == DIRTY_BIT_COLOR_ATTACHMENT_0); 945 946 if (mState.mColorAttachments[0].isAttached()) 947 { 948 const egl::Surface *surface = mState.mColorAttachments[0].getSurface(); 949 mState.mColorAttachments[0].detach(context, mState.mFramebufferSerial); 950 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0); 951 952 if (mState.mDepthAttachment.isAttached()) 953 { 954 mState.mDepthAttachment.detach(context, mState.mFramebufferSerial); 955 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT); 956 } 957 958 if (mState.mStencilAttachment.isAttached()) 959 { 960 mState.mStencilAttachment.detach(context, mState.mFramebufferSerial); 961 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT); 962 } 963 964 ANGLE_TRY(surface->getImplementation()->detachFromFramebuffer(context, this)); 965 966 ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_COMPLETE); 967 mCachedStatus = FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNDEFINED_OES, 968 err::kFramebufferIncompleteSurfaceless); 969 } 970 else 971 { 972 ASSERT(!mState.mDepthAttachment.isAttached()); 973 ASSERT(!mState.mStencilAttachment.isAttached()); 974 ASSERT(mCachedStatus.value().status == GL_FRAMEBUFFER_UNDEFINED_OES); 975 ASSERT(mCachedStatus.value().reason == err::kFramebufferIncompleteSurfaceless); 976 } 977 978 mState.mDefaultFramebufferReadAttachment.detach(context, mState.mFramebufferSerial); 979 mState.mDefaultFramebufferReadAttachmentInitialized = false; 980 return egl::NoError(); 981 } 982 983 angle::Result Framebuffer::setLabel(const Context *context, const std::string &label) 984 { 985 mState.mLabel = label; 986 987 if (mImpl) 988 { 989 return mImpl->onLabelUpdate(context); 990 } 991 return angle::Result::Continue; 992 } 993 994 const std::string &Framebuffer::getLabel() const 995 { 996 return mState.mLabel; 997 } 998 999 bool Framebuffer::detachTexture(const Context *context, TextureID textureId) 1000 { 1001 return detachResourceById(context, GL_TEXTURE, textureId.value); 1002 } 1003 1004 bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId) 1005 { 1006 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value); 1007 } 1008 1009 bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId) 1010 { 1011 bool found = false; 1012 1013 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex) 1014 { 1015 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType, 1016 resourceId)) 1017 { 1018 found = true; 1019 } 1020 } 1021 1022 if (context->isWebGL1()) 1023 { 1024 const std::array<FramebufferAttachment *, 3> attachments = { 1025 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment, 1026 &mState.mWebGLStencilAttachment}}; 1027 for (FramebufferAttachment *attachment : attachments) 1028 { 1029 if (detachMatchingAttachment(context, attachment, resourceType, resourceId)) 1030 { 1031 found = true; 1032 } 1033 } 1034 } 1035 else 1036 { 1037 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId)) 1038 { 1039 found = true; 1040 } 1041 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId)) 1042 { 1043 found = true; 1044 } 1045 } 1046 1047 return found; 1048 } 1049 1050 bool Framebuffer::detachMatchingAttachment(const Context *context, 1051 FramebufferAttachment *attachment, 1052 GLenum matchType, 1053 GLuint matchId) 1054 { 1055 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId) 1056 { 1057 // We go through resetAttachment to make sure that all the required bookkeeping will be done 1058 // such as updating enabled draw buffer state. 1059 resetAttachment(context, attachment->getBinding()); 1060 return true; 1061 } 1062 1063 return false; 1064 } 1065 1066 const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const 1067 { 1068 return mState.getColorAttachment(colorAttachment); 1069 } 1070 1071 const FramebufferAttachment *Framebuffer::getDepthAttachment() const 1072 { 1073 return mState.getDepthAttachment(); 1074 } 1075 1076 const FramebufferAttachment *Framebuffer::getStencilAttachment() const 1077 { 1078 return mState.getStencilAttachment(); 1079 } 1080 1081 const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const 1082 { 1083 return mState.getDepthStencilAttachment(); 1084 } 1085 1086 const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const 1087 { 1088 return mState.getDepthOrStencilAttachment(); 1089 } 1090 1091 const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const 1092 { 1093 return mState.getStencilOrDepthStencilAttachment(); 1094 } 1095 1096 const FramebufferAttachment *Framebuffer::getReadColorAttachment() const 1097 { 1098 return mState.getReadAttachment(); 1099 } 1100 1101 GLenum Framebuffer::getReadColorAttachmentType() const 1102 { 1103 const FramebufferAttachment *readAttachment = mState.getReadAttachment(); 1104 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE); 1105 } 1106 1107 const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const 1108 { 1109 return mState.getFirstColorAttachment(); 1110 } 1111 1112 const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const 1113 { 1114 return mState.getFirstNonNullAttachment(); 1115 } 1116 1117 const FramebufferAttachment *Framebuffer::getAttachment(const Context *context, 1118 GLenum attachment) const 1119 { 1120 return mState.getAttachment(context, attachment); 1121 } 1122 1123 size_t Framebuffer::getDrawbufferStateCount() const 1124 { 1125 return mState.mDrawBufferStates.size(); 1126 } 1127 1128 GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const 1129 { 1130 ASSERT(drawBuffer < mState.mDrawBufferStates.size()); 1131 return mState.mDrawBufferStates[drawBuffer]; 1132 } 1133 1134 const DrawBuffersVector<GLenum> &Framebuffer::getDrawBufferStates() const 1135 { 1136 return mState.getDrawBufferStates(); 1137 } 1138 1139 void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers) 1140 { 1141 auto &drawStates = mState.mDrawBufferStates; 1142 1143 ASSERT(count <= drawStates.size()); 1144 std::copy(buffers, buffers + count, drawStates.begin()); 1145 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE); 1146 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS); 1147 1148 mState.mEnabledDrawBuffers.reset(); 1149 mState.mDrawBufferTypeMask.reset(); 1150 1151 for (size_t index = 0; index < count; ++index) 1152 { 1153 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask); 1154 1155 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached()) 1156 { 1157 mState.mEnabledDrawBuffers.set(index); 1158 } 1159 } 1160 } 1161 1162 const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const 1163 { 1164 return mState.getDrawBuffer(drawBuffer); 1165 } 1166 1167 ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const 1168 { 1169 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer); 1170 if (attachment == nullptr) 1171 { 1172 return ComponentType::NoType; 1173 } 1174 1175 GLenum componentType = attachment->getFormat().info->componentType; 1176 switch (componentType) 1177 { 1178 case GL_INT: 1179 return ComponentType::Int; 1180 case GL_UNSIGNED_INT: 1181 return ComponentType::UnsignedInt; 1182 1183 default: 1184 return ComponentType::Float; 1185 } 1186 } 1187 1188 ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const 1189 { 1190 return mState.mDrawBufferTypeMask; 1191 } 1192 1193 DrawBufferMask Framebuffer::getDrawBufferMask() const 1194 { 1195 return mState.mEnabledDrawBuffers; 1196 } 1197 1198 bool Framebuffer::hasEnabledDrawBuffer() const 1199 { 1200 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx) 1201 { 1202 if (getDrawBuffer(drawbufferIdx) != nullptr) 1203 { 1204 return true; 1205 } 1206 } 1207 1208 return false; 1209 } 1210 1211 GLenum Framebuffer::getReadBufferState() const 1212 { 1213 return mState.mReadBufferState; 1214 } 1215 1216 void Framebuffer::setReadBuffer(GLenum buffer) 1217 { 1218 ASSERT(buffer == GL_BACK || buffer == GL_NONE || 1219 (buffer >= GL_COLOR_ATTACHMENT0 && 1220 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size())); 1221 if (mState.mReadBufferState != buffer) 1222 { 1223 mState.mReadBufferState = buffer; 1224 mDirtyBits.set(DIRTY_BIT_READ_BUFFER); 1225 } 1226 } 1227 1228 size_t Framebuffer::getNumColorAttachments() const 1229 { 1230 return mState.mColorAttachments.size(); 1231 } 1232 1233 bool Framebuffer::hasDepth() const 1234 { 1235 return mState.hasDepth(); 1236 } 1237 1238 bool Framebuffer::hasStencil() const 1239 { 1240 return mState.hasStencil(); 1241 } 1242 1243 bool Framebuffer::hasExternalTextureAttachment() const 1244 { 1245 return mState.hasExternalTextureAttachment(); 1246 } 1247 1248 bool Framebuffer::hasYUVAttachment() const 1249 { 1250 return mState.hasYUVAttachment(); 1251 } 1252 1253 bool Framebuffer::usingExtendedDrawBuffers() const 1254 { 1255 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx) 1256 { 1257 if (getDrawBuffer(drawbufferIdx) != nullptr) 1258 { 1259 return true; 1260 } 1261 } 1262 1263 return false; 1264 } 1265 1266 void Framebuffer::invalidateCompletenessCache() 1267 { 1268 if (!isDefault()) 1269 { 1270 mCachedStatus.reset(); 1271 } 1272 onStateChange(angle::SubjectMessage::DirtyBitsFlagged); 1273 } 1274 1275 const FramebufferStatus &Framebuffer::checkStatusImpl(const Context *context) const 1276 { 1277 ASSERT(!isDefault()); 1278 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid()); 1279 1280 mCachedStatus = checkStatusWithGLFrontEnd(context); 1281 1282 if (mCachedStatus.value().isComplete()) 1283 { 1284 // We can skip syncState on several back-ends. 1285 if (mImpl->shouldSyncStateBeforeCheckStatus()) 1286 { 1287 // This binding is not totally correct. It is ok because the parameter isn't used in 1288 // the GL back-end and the GL back-end is the only user of syncStateBeforeCheckStatus. 1289 angle::Result err = syncState(context, GL_FRAMEBUFFER, Command::Other); 1290 if (err != angle::Result::Continue) 1291 { 1292 mCachedStatus = 1293 FramebufferStatus::Incomplete(0, err::kFramebufferIncompleteInternalError); 1294 return mCachedStatus.value(); 1295 } 1296 } 1297 1298 mCachedStatus = mImpl->checkStatus(context); 1299 } 1300 1301 return mCachedStatus.value(); 1302 } 1303 1304 FramebufferStatus Framebuffer::checkStatusWithGLFrontEnd(const Context *context) const 1305 { 1306 const State &state = context->getState(); 1307 1308 ASSERT(!isDefault()); 1309 1310 bool hasAttachments = false; 1311 Optional<unsigned int> colorbufferSize; 1312 Optional<int> samples; 1313 Optional<bool> fixedSampleLocations; 1314 bool hasRenderbuffer = false; 1315 Optional<int> renderToTextureSamples; 1316 1317 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment(); 1318 1319 Optional<bool> isLayered; 1320 Optional<TextureType> colorAttachmentsTextureType; 1321 1322 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments) 1323 { 1324 if (colorAttachment.isAttached()) 1325 { 1326 FramebufferStatus attachmentCompleteness = 1327 CheckAttachmentCompleteness(context, colorAttachment); 1328 if (!attachmentCompleteness.isComplete()) 1329 { 1330 return attachmentCompleteness; 1331 } 1332 1333 const InternalFormat &format = *colorAttachment.getFormat().info; 1334 if (format.depthBits > 0 || format.stencilBits > 0) 1335 { 1336 return FramebufferStatus::Incomplete( 1337 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1338 err::kFramebufferIncompleteDepthStencilInColorBuffer); 1339 } 1340 1341 FramebufferStatus attachmentSampleCompleteness = 1342 CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples, 1343 &fixedSampleLocations, &renderToTextureSamples); 1344 if (!attachmentSampleCompleteness.isComplete()) 1345 { 1346 return attachmentSampleCompleteness; 1347 } 1348 1349 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes 1350 // in GLES 3.0, there is no such restriction 1351 if (state.getClientMajorVersion() < 3) 1352 { 1353 if (colorbufferSize.valid()) 1354 { 1355 if (format.pixelBytes != colorbufferSize.value()) 1356 { 1357 return FramebufferStatus::Incomplete( 1358 GL_FRAMEBUFFER_UNSUPPORTED, 1359 err::kFramebufferIncompleteAttachmentInconsistantBitPlanes); 1360 } 1361 } 1362 else 1363 { 1364 colorbufferSize = format.pixelBytes; 1365 } 1366 } 1367 1368 FramebufferStatus attachmentMultiviewCompleteness = 1369 CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment); 1370 if (!attachmentMultiviewCompleteness.isComplete()) 1371 { 1372 return attachmentMultiviewCompleteness; 1373 } 1374 1375 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER); 1376 1377 if (!hasAttachments) 1378 { 1379 isLayered = colorAttachment.isLayered(); 1380 if (isLayered.value()) 1381 { 1382 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType(); 1383 } 1384 hasAttachments = true; 1385 } 1386 else 1387 { 1388 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness" 1389 // If any framebuffer attachment is layered, all populated attachments 1390 // must be layered. Additionally, all populated color attachments must 1391 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT } 1392 ASSERT(isLayered.valid()); 1393 if (isLayered.value() != colorAttachment.isLayered()) 1394 { 1395 return FramebufferStatus::Incomplete( 1396 GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 1397 err::kFramebufferIncompleteMismatchedLayeredAttachments); 1398 } 1399 else if (isLayered.value()) 1400 { 1401 ASSERT(colorAttachmentsTextureType.valid()); 1402 if (colorAttachmentsTextureType.value() != 1403 colorAttachment.getTextureImageIndex().getType()) 1404 { 1405 return FramebufferStatus::Incomplete( 1406 GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 1407 err::kFramebufferIncompleteMismatchedLayeredTexturetypes); 1408 } 1409 } 1410 } 1411 } 1412 } 1413 1414 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment; 1415 if (depthAttachment.isAttached()) 1416 { 1417 FramebufferStatus attachmentCompleteness = 1418 CheckAttachmentCompleteness(context, depthAttachment); 1419 if (!attachmentCompleteness.isComplete()) 1420 { 1421 return attachmentCompleteness; 1422 } 1423 1424 const InternalFormat &format = *depthAttachment.getFormat().info; 1425 if (format.depthBits == 0) 1426 { 1427 return FramebufferStatus::Incomplete( 1428 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1429 err::kFramebufferIncompleteAttachmentNoDepthBitsInDepthBuffer); 1430 } 1431 1432 FramebufferStatus attachmentSampleCompleteness = 1433 CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples, 1434 &fixedSampleLocations, &renderToTextureSamples); 1435 if (!attachmentSampleCompleteness.isComplete()) 1436 { 1437 return attachmentSampleCompleteness; 1438 } 1439 1440 FramebufferStatus attachmentMultiviewCompleteness = 1441 CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment); 1442 if (!attachmentMultiviewCompleteness.isComplete()) 1443 { 1444 return attachmentMultiviewCompleteness; 1445 } 1446 1447 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER); 1448 1449 if (!hasAttachments) 1450 { 1451 isLayered = depthAttachment.isLayered(); 1452 hasAttachments = true; 1453 } 1454 else 1455 { 1456 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness" 1457 // If any framebuffer attachment is layered, all populated attachments 1458 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT } 1459 ASSERT(isLayered.valid()); 1460 if (isLayered.value() != depthAttachment.isLayered()) 1461 { 1462 return FramebufferStatus::Incomplete( 1463 GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 1464 err::kFramebufferIncompleteMismatchedLayeredAttachments); 1465 } 1466 } 1467 } 1468 1469 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment; 1470 if (stencilAttachment.isAttached()) 1471 { 1472 FramebufferStatus attachmentCompleteness = 1473 CheckAttachmentCompleteness(context, stencilAttachment); 1474 if (!attachmentCompleteness.isComplete()) 1475 { 1476 return attachmentCompleteness; 1477 } 1478 1479 const InternalFormat &format = *stencilAttachment.getFormat().info; 1480 if (format.stencilBits == 0) 1481 { 1482 return FramebufferStatus::Incomplete( 1483 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1484 err::kFramebufferIncompleteAttachmentNoStencilBitsInStencilBuffer); 1485 } 1486 1487 FramebufferStatus attachmentSampleCompleteness = 1488 CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples, 1489 &fixedSampleLocations, &renderToTextureSamples); 1490 if (!attachmentSampleCompleteness.isComplete()) 1491 { 1492 return attachmentSampleCompleteness; 1493 } 1494 1495 FramebufferStatus attachmentMultiviewCompleteness = 1496 CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment); 1497 if (!attachmentMultiviewCompleteness.isComplete()) 1498 { 1499 return attachmentMultiviewCompleteness; 1500 } 1501 1502 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER); 1503 1504 if (!hasAttachments) 1505 { 1506 hasAttachments = true; 1507 } 1508 else 1509 { 1510 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness" 1511 // If any framebuffer attachment is layered, all populated attachments 1512 // must be layered. 1513 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT } 1514 ASSERT(isLayered.valid()); 1515 if (isLayered.value() != stencilAttachment.isLayered()) 1516 { 1517 return FramebufferStatus::Incomplete( 1518 GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, 1519 err::kFramebufferIncompleteMismatchedLayeredAttachments); 1520 } 1521 } 1522 } 1523 1524 // Starting from ES 3.0 stencil and depth, if present, should be the same image 1525 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() && 1526 stencilAttachment.isAttached() && stencilAttachment != depthAttachment) 1527 { 1528 return FramebufferStatus::Incomplete( 1529 GL_FRAMEBUFFER_UNSUPPORTED, 1530 err::kFramebufferIncompleteDepthAndStencilBuffersNotTheSame); 1531 } 1532 1533 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL. 1534 if (state.isWebGL1()) 1535 { 1536 if (!mState.mWebGLDepthStencilConsistent) 1537 { 1538 return FramebufferStatus::Incomplete( 1539 GL_FRAMEBUFFER_UNSUPPORTED, 1540 err::kFramebufferIncompleteWebGLDepthStencilInconsistant); 1541 } 1542 1543 if (mState.mWebGLDepthStencilAttachment.isAttached()) 1544 { 1545 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 || 1546 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0) 1547 { 1548 return FramebufferStatus::Incomplete( 1549 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1550 err::kFramebufferIncompleteAttachmentWebGLDepthStencilNoDepthOrStencilBits); 1551 } 1552 1553 FramebufferStatus attachmentMultiviewCompleteness = 1554 CheckMultiviewStateMatchesForCompleteness(firstAttachment, 1555 &mState.mWebGLDepthStencilAttachment); 1556 if (!attachmentMultiviewCompleteness.isComplete()) 1557 { 1558 return attachmentMultiviewCompleteness; 1559 } 1560 } 1561 else if (mState.mStencilAttachment.isAttached() && 1562 mState.mStencilAttachment.getDepthSize() > 0) 1563 { 1564 return FramebufferStatus::Incomplete( 1565 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1566 err::kFramebufferIncompleteAttachmentWebGLStencilBufferHasDepthBits); 1567 } 1568 else if (mState.mDepthAttachment.isAttached() && 1569 mState.mDepthAttachment.getStencilSize() > 0) 1570 { 1571 return FramebufferStatus::Incomplete( 1572 GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, 1573 err::kFramebufferIncompleteAttachmentWebGLDepthBufferHasStencilBits); 1574 } 1575 } 1576 1577 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the 1578 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters 1579 // is zero, the framebuffer is considered incomplete. 1580 GLint defaultWidth = mState.getDefaultWidth(); 1581 GLint defaultHeight = mState.getDefaultHeight(); 1582 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0)) 1583 { 1584 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, 1585 err::kFramebufferIncompleteDefaultZeroSize); 1586 } 1587 1588 // In ES 2.0 and WebGL, all color attachments must have the same width and height. 1589 // In ES 3.0, there is no such restriction. 1590 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibilityANGLE) && 1591 !mState.attachmentsHaveSameDimensions()) 1592 { 1593 return FramebufferStatus::Incomplete( 1594 GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, 1595 err::kFramebufferIncompleteInconsistantAttachmentSizes); 1596 } 1597 1598 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and 1599 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures. 1600 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value()) 1601 { 1602 return FramebufferStatus::Incomplete( 1603 GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, 1604 err::kFramebufferIncompleteMultisampleNonFixedSamplesWithRenderbuffers); 1605 } 1606 1607 // The WebGL conformance tests implicitly define that all framebuffer 1608 // attachments must be unique. For example, the same level of a texture can 1609 // not be attached to two different color attachments. 1610 if (state.getExtensions().webglCompatibilityANGLE) 1611 { 1612 if (!mState.colorAttachmentsAreUniqueImages()) 1613 { 1614 return FramebufferStatus::Incomplete(GL_FRAMEBUFFER_UNSUPPORTED, 1615 err::kFramebufferIncompleteAttachmentsNotUnique); 1616 } 1617 } 1618 1619 return FramebufferStatus::Complete(); 1620 } 1621 1622 angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments) 1623 { 1624 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations 1625 // can be no-ops, so we should probably do that to ensure consistency. 1626 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL. 1627 1628 return mImpl->discard(context, count, attachments); 1629 } 1630 1631 angle::Result Framebuffer::invalidate(const Context *context, 1632 size_t count, 1633 const GLenum *attachments) 1634 { 1635 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations 1636 // can be no-ops, so we should probably do that to ensure consistency. 1637 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL. 1638 1639 return mImpl->invalidate(context, count, attachments); 1640 } 1641 1642 bool Framebuffer::partialClearNeedsInit(const Context *context, 1643 bool color, 1644 bool depth, 1645 bool stencil) 1646 { 1647 const auto &glState = context->getState(); 1648 1649 if (!glState.isRobustResourceInitEnabled()) 1650 { 1651 return false; 1652 } 1653 1654 if (depth && context->getFrontendFeatures().forceDepthAttachmentInitOnClear.enabled) 1655 { 1656 return true; 1657 } 1658 1659 // Scissors can affect clearing. 1660 // TODO(jmadill): Check for complete scissor overlap. 1661 if (glState.isScissorTestEnabled()) 1662 { 1663 return true; 1664 } 1665 1666 // If colors masked, we must clear before we clear. Do a simple check. 1667 // TODO(jmadill): Filter out unused color channels from the test. 1668 if (color && glState.anyActiveDrawBufferChannelMasked()) 1669 { 1670 return true; 1671 } 1672 1673 const auto &depthStencil = glState.getDepthStencilState(); 1674 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask || 1675 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask)) 1676 { 1677 return true; 1678 } 1679 1680 return false; 1681 } 1682 1683 angle::Result Framebuffer::invalidateSub(const Context *context, 1684 size_t count, 1685 const GLenum *attachments, 1686 const Rectangle &area) 1687 { 1688 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations 1689 // can be no-ops, so we should probably do that to ensure consistency. 1690 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0. 1691 1692 return mImpl->invalidateSub(context, count, attachments, area); 1693 } 1694 1695 angle::Result Framebuffer::clear(const Context *context, GLbitfield mask) 1696 { 1697 ASSERT(mask && !context->getState().isRasterizerDiscardEnabled()); 1698 1699 return mImpl->clear(context, mask); 1700 } 1701 1702 angle::Result Framebuffer::clearBufferfv(const Context *context, 1703 GLenum buffer, 1704 GLint drawbuffer, 1705 const GLfloat *values) 1706 { 1707 return mImpl->clearBufferfv(context, buffer, drawbuffer, values); 1708 } 1709 1710 angle::Result Framebuffer::clearBufferuiv(const Context *context, 1711 GLenum buffer, 1712 GLint drawbuffer, 1713 const GLuint *values) 1714 { 1715 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values); 1716 } 1717 1718 angle::Result Framebuffer::clearBufferiv(const Context *context, 1719 GLenum buffer, 1720 GLint drawbuffer, 1721 const GLint *values) 1722 { 1723 return mImpl->clearBufferiv(context, buffer, drawbuffer, values); 1724 } 1725 1726 angle::Result Framebuffer::clearBufferfi(const Context *context, 1727 GLenum buffer, 1728 GLint drawbuffer, 1729 GLfloat depth, 1730 GLint stencil) 1731 { 1732 const bool clearDepth = 1733 getDepthAttachment() != nullptr && context->getState().getDepthStencilState().depthMask; 1734 const bool clearStencil = getStencilAttachment() != nullptr && 1735 context->getState().getDepthStencilState().stencilWritemask != 0; 1736 1737 if (clearDepth && clearStencil) 1738 { 1739 ASSERT(buffer == GL_DEPTH_STENCIL); 1740 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil)); 1741 } 1742 else if (clearDepth && !clearStencil) 1743 { 1744 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth)); 1745 } 1746 else if (!clearDepth && clearStencil) 1747 { 1748 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil)); 1749 } 1750 1751 return angle::Result::Continue; 1752 } 1753 1754 GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) 1755 { 1756 const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context); 1757 return format.getReadPixelsFormat(context->getExtensions()); 1758 } 1759 1760 GLenum Framebuffer::getImplementationColorReadType(const Context *context) 1761 { 1762 const gl::InternalFormat &format = mImpl->getImplementationColorReadFormat(context); 1763 return format.getReadPixelsType(context->getClientVersion()); 1764 } 1765 1766 angle::Result Framebuffer::readPixels(const Context *context, 1767 const Rectangle &area, 1768 GLenum format, 1769 GLenum type, 1770 const PixelPackState &pack, 1771 Buffer *packBuffer, 1772 void *pixels) 1773 { 1774 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pack, packBuffer, pixels)); 1775 1776 if (packBuffer) 1777 { 1778 packBuffer->onDataChanged(); 1779 } 1780 1781 return angle::Result::Continue; 1782 } 1783 1784 angle::Result Framebuffer::blit(const Context *context, 1785 const Rectangle &sourceArea, 1786 const Rectangle &destArea, 1787 GLbitfield mask, 1788 GLenum filter) 1789 { 1790 ASSERT(mask != 0); 1791 1792 ANGLE_TRY(mImpl->blit(context, sourceArea, destArea, mask, filter)); 1793 1794 // Mark the contents of the attachments dirty 1795 if ((mask & GL_COLOR_BUFFER_BIT) != 0) 1796 { 1797 for (size_t colorIndex : mState.mEnabledDrawBuffers) 1798 { 1799 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + colorIndex); 1800 } 1801 } 1802 if ((mask & GL_DEPTH_BUFFER_BIT) != 0) 1803 { 1804 mDirtyBits.set(DIRTY_BIT_DEPTH_BUFFER_CONTENTS); 1805 } 1806 if ((mask & GL_STENCIL_BUFFER_BIT) != 0) 1807 { 1808 mDirtyBits.set(DIRTY_BIT_STENCIL_BUFFER_CONTENTS); 1809 } 1810 onStateChange(angle::SubjectMessage::DirtyBitsFlagged); 1811 1812 return angle::Result::Continue; 1813 } 1814 1815 int Framebuffer::getSamples(const Context *context) const 1816 { 1817 if (!isComplete(context)) 1818 { 1819 return 0; 1820 } 1821 1822 ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete()); 1823 1824 // For a complete framebuffer, all attachments must have the same sample count. 1825 // In this case return the first nonzero sample size. 1826 const FramebufferAttachment *firstNonNullAttachment = mState.getFirstNonNullAttachment(); 1827 ASSERT(firstNonNullAttachment == nullptr || firstNonNullAttachment->isAttached()); 1828 1829 return firstNonNullAttachment ? firstNonNullAttachment->getSamples() : 0; 1830 } 1831 1832 int Framebuffer::getReadBufferResourceSamples(const Context *context) const 1833 { 1834 if (!isComplete(context)) 1835 { 1836 return 0; 1837 } 1838 1839 ASSERT(mCachedStatus.valid() && mCachedStatus.value().isComplete()); 1840 1841 const FramebufferAttachment *readAttachment = mState.getReadAttachment(); 1842 ASSERT(readAttachment == nullptr || readAttachment->isAttached()); 1843 1844 return readAttachment ? readAttachment->getResourceSamples() : 0; 1845 } 1846 1847 angle::Result Framebuffer::getSamplePosition(const Context *context, 1848 size_t index, 1849 GLfloat *xy) const 1850 { 1851 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy)); 1852 return angle::Result::Continue; 1853 } 1854 1855 bool Framebuffer::hasValidDepthStencil() const 1856 { 1857 return mState.getDepthStencilAttachment() != nullptr; 1858 } 1859 1860 const gl::Offset &Framebuffer::getSurfaceTextureOffset() const 1861 { 1862 return mState.getSurfaceTextureOffset(); 1863 } 1864 1865 void Framebuffer::setAttachment(const Context *context, 1866 GLenum type, 1867 GLenum binding, 1868 const ImageIndex &textureIndex, 1869 FramebufferAttachmentObject *resource) 1870 { 1871 setAttachment(context, type, binding, textureIndex, resource, 1872 FramebufferAttachment::kDefaultNumViews, 1873 FramebufferAttachment::kDefaultBaseViewIndex, false, 1874 FramebufferAttachment::kDefaultRenderToTextureSamples); 1875 } 1876 1877 void Framebuffer::setAttachmentMultisample(const Context *context, 1878 GLenum type, 1879 GLenum binding, 1880 const ImageIndex &textureIndex, 1881 FramebufferAttachmentObject *resource, 1882 GLsizei samples) 1883 { 1884 setAttachment(context, type, binding, textureIndex, resource, 1885 FramebufferAttachment::kDefaultNumViews, 1886 FramebufferAttachment::kDefaultBaseViewIndex, false, samples); 1887 } 1888 1889 void Framebuffer::setAttachment(const Context *context, 1890 GLenum type, 1891 GLenum binding, 1892 const ImageIndex &textureIndex, 1893 FramebufferAttachmentObject *resource, 1894 GLsizei numViews, 1895 GLuint baseViewIndex, 1896 bool isMultiview, 1897 GLsizei samplesIn) 1898 { 1899 GLsizei samples = samplesIn; 1900 // Match the sample count to the attachment's sample count. 1901 if (resource) 1902 { 1903 const InternalFormat *info = resource->getAttachmentFormat(binding, textureIndex).info; 1904 ASSERT(info); 1905 GLenum sizedInternalFormat = info->sizedInternalFormat; 1906 const TextureCaps &formatCaps = context->getTextureCaps().get(sizedInternalFormat); 1907 samples = formatCaps.getNearestSamples(samples); 1908 } 1909 1910 // Context may be null in unit tests. 1911 if (!context || !context->isWebGL1()) 1912 { 1913 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex, 1914 isMultiview, samples); 1915 return; 1916 } 1917 1918 switch (binding) 1919 { 1920 case GL_DEPTH_STENCIL: 1921 case GL_DEPTH_STENCIL_ATTACHMENT: 1922 mState.mWebGLDepthStencilAttachment.attach( 1923 context, type, binding, textureIndex, resource, numViews, baseViewIndex, 1924 isMultiview, samples, mState.mFramebufferSerial); 1925 break; 1926 case GL_DEPTH: 1927 case GL_DEPTH_ATTACHMENT: 1928 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource, 1929 numViews, baseViewIndex, isMultiview, samples, 1930 mState.mFramebufferSerial); 1931 break; 1932 case GL_STENCIL: 1933 case GL_STENCIL_ATTACHMENT: 1934 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource, 1935 numViews, baseViewIndex, isMultiview, samples, 1936 mState.mFramebufferSerial); 1937 break; 1938 default: 1939 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, 1940 baseViewIndex, isMultiview, samples); 1941 return; 1942 } 1943 1944 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview, samples); 1945 } 1946 1947 void Framebuffer::setAttachmentMultiview(const Context *context, 1948 GLenum type, 1949 GLenum binding, 1950 const ImageIndex &textureIndex, 1951 FramebufferAttachmentObject *resource, 1952 GLsizei numViews, 1953 GLint baseViewIndex) 1954 { 1955 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true, 1956 FramebufferAttachment::kDefaultRenderToTextureSamples); 1957 } 1958 1959 void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context, 1960 GLsizei numViews, 1961 GLuint baseViewIndex, 1962 bool isMultiview, 1963 GLsizei samples) 1964 { 1965 int count = 0; 1966 1967 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment, 1968 &mState.mWebGLDepthAttachment, 1969 &mState.mWebGLStencilAttachment}}; 1970 for (FramebufferAttachment *attachment : attachments) 1971 { 1972 if (attachment->isAttached()) 1973 { 1974 count++; 1975 } 1976 } 1977 1978 mState.mWebGLDepthStencilConsistent = (count <= 1); 1979 if (!mState.mWebGLDepthStencilConsistent) 1980 { 1981 // Inconsistent. 1982 return; 1983 } 1984 1985 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) { 1986 if (attachment.type() == GL_TEXTURE) 1987 { 1988 return attachment.getTextureImageIndex(); 1989 } 1990 else 1991 { 1992 return ImageIndex(); 1993 } 1994 }; 1995 1996 if (mState.mWebGLDepthAttachment.isAttached()) 1997 { 1998 const auto &depth = mState.mWebGLDepthAttachment; 1999 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT, 2000 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews, 2001 baseViewIndex, isMultiview, samples); 2002 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews, 2003 baseViewIndex, isMultiview, samples); 2004 } 2005 else if (mState.mWebGLStencilAttachment.isAttached()) 2006 { 2007 const auto &stencil = mState.mWebGLStencilAttachment; 2008 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews, 2009 baseViewIndex, isMultiview, samples); 2010 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT, 2011 getImageIndexIfTextureAttachment(stencil), stencil.getResource(), 2012 numViews, baseViewIndex, isMultiview, samples); 2013 } 2014 else if (mState.mWebGLDepthStencilAttachment.isAttached()) 2015 { 2016 const auto &depthStencil = mState.mWebGLDepthStencilAttachment; 2017 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT, 2018 getImageIndexIfTextureAttachment(depthStencil), 2019 depthStencil.getResource(), numViews, baseViewIndex, isMultiview, 2020 samples); 2021 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT, 2022 getImageIndexIfTextureAttachment(depthStencil), 2023 depthStencil.getResource(), numViews, baseViewIndex, isMultiview, 2024 samples); 2025 } 2026 else 2027 { 2028 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews, 2029 baseViewIndex, isMultiview, samples); 2030 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews, 2031 baseViewIndex, isMultiview, samples); 2032 } 2033 } 2034 2035 void Framebuffer::setAttachmentImpl(const Context *context, 2036 GLenum type, 2037 GLenum binding, 2038 const ImageIndex &textureIndex, 2039 FramebufferAttachmentObject *resource, 2040 GLsizei numViews, 2041 GLuint baseViewIndex, 2042 bool isMultiview, 2043 GLsizei samples) 2044 { 2045 switch (binding) 2046 { 2047 case GL_DEPTH_STENCIL: 2048 case GL_DEPTH_STENCIL_ATTACHMENT: 2049 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT, 2050 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource, 2051 numViews, baseViewIndex, isMultiview, samples); 2052 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT, 2053 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource, 2054 numViews, baseViewIndex, isMultiview, samples); 2055 break; 2056 2057 case GL_DEPTH: 2058 case GL_DEPTH_ATTACHMENT: 2059 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT, 2060 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource, 2061 numViews, baseViewIndex, isMultiview, samples); 2062 break; 2063 2064 case GL_STENCIL: 2065 case GL_STENCIL_ATTACHMENT: 2066 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT, 2067 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource, 2068 numViews, baseViewIndex, isMultiview, samples); 2069 break; 2070 2071 case GL_BACK: 2072 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0, 2073 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex, 2074 resource, numViews, baseViewIndex, isMultiview, samples); 2075 mState.mColorAttachmentsMask.set(0); 2076 2077 break; 2078 2079 default: 2080 { 2081 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0; 2082 ASSERT(colorIndex < mState.mColorAttachments.size()); 2083 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex; 2084 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit, 2085 &mDirtyColorAttachmentBindings[colorIndex], type, binding, 2086 textureIndex, resource, numViews, baseViewIndex, isMultiview, samples); 2087 2088 if (!resource) 2089 { 2090 mFloat32ColorAttachmentBits.reset(colorIndex); 2091 mState.mColorAttachmentsMask.reset(colorIndex); 2092 } 2093 else 2094 { 2095 updateFloat32ColorAttachmentBits( 2096 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info); 2097 mState.mColorAttachmentsMask.set(colorIndex); 2098 } 2099 2100 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE); 2101 mState.mEnabledDrawBuffers.set(colorIndex, enabled); 2102 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex, 2103 &mState.mDrawBufferTypeMask); 2104 } 2105 break; 2106 } 2107 } 2108 2109 void Framebuffer::updateAttachment(const Context *context, 2110 FramebufferAttachment *attachment, 2111 size_t dirtyBit, 2112 angle::ObserverBinding *onDirtyBinding, 2113 GLenum type, 2114 GLenum binding, 2115 const ImageIndex &textureIndex, 2116 FramebufferAttachmentObject *resource, 2117 GLsizei numViews, 2118 GLuint baseViewIndex, 2119 bool isMultiview, 2120 GLsizei samples) 2121 { 2122 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex, 2123 isMultiview, samples, mState.mFramebufferSerial); 2124 mDirtyBits.set(dirtyBit); 2125 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit); 2126 onDirtyBinding->bind(resource); 2127 2128 invalidateCompletenessCache(); 2129 } 2130 2131 void Framebuffer::resetAttachment(const Context *context, GLenum binding) 2132 { 2133 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr); 2134 } 2135 2136 void Framebuffer::setWriteControlMode(SrgbWriteControlMode srgbWriteControlMode) 2137 { 2138 if (srgbWriteControlMode != mState.getWriteControlMode()) 2139 { 2140 mState.mSrgbWriteControlMode = srgbWriteControlMode; 2141 mDirtyBits.set(DIRTY_BIT_FRAMEBUFFER_SRGB_WRITE_CONTROL_MODE); 2142 } 2143 } 2144 2145 angle::Result Framebuffer::syncState(const Context *context, 2146 GLenum framebufferBinding, 2147 Command command) const 2148 { 2149 if (mDirtyBits.any()) 2150 { 2151 mDirtyBitsGuard = mDirtyBits; 2152 ANGLE_TRY(mImpl->syncState(context, framebufferBinding, mDirtyBits, command)); 2153 mDirtyBits.reset(); 2154 mDirtyBitsGuard.reset(); 2155 } 2156 return angle::Result::Continue; 2157 } 2158 2159 void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message) 2160 { 2161 if (message != angle::SubjectMessage::SubjectChanged) 2162 { 2163 // This can be triggered by SubImage calls for Textures. 2164 if (message == angle::SubjectMessage::ContentsChanged) 2165 { 2166 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index); 2167 onStateChange(angle::SubjectMessage::DirtyBitsFlagged); 2168 return; 2169 } 2170 2171 // Swapchain changes should only result in color buffer changes. 2172 if (message == angle::SubjectMessage::SwapchainImageChanged) 2173 { 2174 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX) 2175 { 2176 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index); 2177 onStateChange(angle::SubjectMessage::DirtyBitsFlagged); 2178 } 2179 return; 2180 } 2181 2182 ASSERT(message != angle::SubjectMessage::BindingChanged); 2183 2184 // This can be triggered by external changes to the default framebuffer. 2185 if (message == angle::SubjectMessage::SurfaceChanged) 2186 { 2187 onStateChange(angle::SubjectMessage::SurfaceChanged); 2188 return; 2189 } 2190 2191 // This can be triggered by freeing TextureStorage in D3D back-end. 2192 if (message == angle::SubjectMessage::StorageReleased) 2193 { 2194 mDirtyBits.set(index); 2195 invalidateCompletenessCache(); 2196 return; 2197 } 2198 2199 // This can be triggered by the GL back-end TextureGL class. 2200 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged); 2201 return; 2202 } 2203 2204 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index)); 2205 mDirtyBits.set(index); 2206 2207 invalidateCompletenessCache(); 2208 2209 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index); 2210 2211 // Mark the appropriate init flag. 2212 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit); 2213 2214 // Update mFloat32ColorAttachmentBits Cache 2215 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX) 2216 { 2217 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT); 2218 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT); 2219 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0, 2220 attachment->getFormat().info); 2221 } 2222 } 2223 2224 FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index) 2225 { 2226 switch (index) 2227 { 2228 case DIRTY_BIT_DEPTH_ATTACHMENT: 2229 return &mState.mDepthAttachment; 2230 case DIRTY_BIT_STENCIL_ATTACHMENT: 2231 return &mState.mStencilAttachment; 2232 default: 2233 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0); 2234 ASSERT(colorIndex < mState.mColorAttachments.size()); 2235 return &mState.mColorAttachments[colorIndex]; 2236 } 2237 } 2238 2239 bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const 2240 { 2241 const State &glState = context->getState(); 2242 const ProgramExecutable *executable = glState.getLinkedProgramExecutable(context); 2243 2244 // In some error cases there may be no bound program or executable. 2245 if (!executable) 2246 return false; 2247 2248 const ActiveTextureMask &activeTextures = executable->getActiveSamplersMask(); 2249 const ActiveTextureTypeArray &textureTypes = executable->getActiveSamplerTypes(); 2250 2251 for (size_t textureIndex : activeTextures) 2252 { 2253 unsigned int uintIndex = static_cast<unsigned int>(textureIndex); 2254 Texture *texture = glState.getSamplerTexture(uintIndex, textureTypes[textureIndex]); 2255 const Sampler *sampler = glState.getSampler(uintIndex); 2256 if (texture && texture->isSamplerComplete(context, sampler) && 2257 texture->isBoundToFramebuffer(mState.mFramebufferSerial)) 2258 { 2259 // Check for level overlap. 2260 for (const FramebufferAttachment &attachment : mState.mColorAttachments) 2261 { 2262 if (AttachmentOverlapsWithTexture(attachment, texture, sampler)) 2263 { 2264 return true; 2265 } 2266 } 2267 2268 if (AttachmentOverlapsWithTexture(mState.mDepthAttachment, texture, sampler)) 2269 { 2270 return true; 2271 } 2272 2273 if (AttachmentOverlapsWithTexture(mState.mStencilAttachment, texture, sampler)) 2274 { 2275 return true; 2276 } 2277 } 2278 } 2279 2280 return false; 2281 } 2282 2283 bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID, 2284 GLint copyTextureLevel, 2285 GLint copyTextureLayer) const 2286 { 2287 if (mState.isDefault()) 2288 { 2289 // It seems impossible to form a texture copying feedback loop with the default FBO. 2290 return false; 2291 } 2292 2293 const FramebufferAttachment *readAttachment = getReadColorAttachment(); 2294 ASSERT(readAttachment); 2295 2296 if (readAttachment->isTextureWithId(copyTextureID)) 2297 { 2298 const auto &imageIndex = readAttachment->getTextureImageIndex(); 2299 if (imageIndex.getLevelIndex() == copyTextureLevel) 2300 { 2301 // Check 3D/Array texture layers. 2302 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel || 2303 imageIndex.getLayerIndex() == copyTextureLayer; 2304 } 2305 } 2306 return false; 2307 } 2308 2309 GLint Framebuffer::getDefaultWidth() const 2310 { 2311 return mState.getDefaultWidth(); 2312 } 2313 2314 GLint Framebuffer::getDefaultHeight() const 2315 { 2316 return mState.getDefaultHeight(); 2317 } 2318 2319 GLint Framebuffer::getDefaultSamples() const 2320 { 2321 return mState.getDefaultSamples(); 2322 } 2323 2324 bool Framebuffer::getDefaultFixedSampleLocations() const 2325 { 2326 return mState.getDefaultFixedSampleLocations(); 2327 } 2328 2329 GLint Framebuffer::getDefaultLayers() const 2330 { 2331 return mState.getDefaultLayers(); 2332 } 2333 2334 bool Framebuffer::getFlipY() const 2335 { 2336 return mState.getFlipY(); 2337 } 2338 2339 void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth) 2340 { 2341 mState.mDefaultWidth = defaultWidth; 2342 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH); 2343 invalidateCompletenessCache(); 2344 } 2345 2346 void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight) 2347 { 2348 mState.mDefaultHeight = defaultHeight; 2349 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT); 2350 invalidateCompletenessCache(); 2351 } 2352 2353 void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples) 2354 { 2355 mState.mDefaultSamples = defaultSamples; 2356 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES); 2357 invalidateCompletenessCache(); 2358 } 2359 2360 void Framebuffer::setDefaultFixedSampleLocations(const Context *context, 2361 bool defaultFixedSampleLocations) 2362 { 2363 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations; 2364 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS); 2365 invalidateCompletenessCache(); 2366 } 2367 2368 void Framebuffer::setDefaultLayers(GLint defaultLayers) 2369 { 2370 mState.mDefaultLayers = defaultLayers; 2371 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS); 2372 } 2373 2374 void Framebuffer::setFlipY(bool flipY) 2375 { 2376 mState.mFlipY = flipY; 2377 mDirtyBits.set(DIRTY_BIT_FLIP_Y); 2378 invalidateCompletenessCache(); 2379 } 2380 2381 GLsizei Framebuffer::getNumViews() const 2382 { 2383 return mState.getNumViews(); 2384 } 2385 2386 GLint Framebuffer::getBaseViewIndex() const 2387 { 2388 return mState.getBaseViewIndex(); 2389 } 2390 2391 bool Framebuffer::isMultiview() const 2392 { 2393 return mState.isMultiview(); 2394 } 2395 2396 bool Framebuffer::readDisallowedByMultiview() const 2397 { 2398 return (mState.isMultiview() && mState.getNumViews() > 1); 2399 } 2400 2401 angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context, 2402 GLbitfield mask) 2403 { 2404 const auto &glState = context->getState(); 2405 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled()) 2406 { 2407 return angle::Result::Continue; 2408 } 2409 2410 const DepthStencilState &depthStencil = glState.getDepthStencilState(); 2411 2412 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !glState.allActiveDrawBufferChannelsMasked(); 2413 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !depthStencil.isDepthMaskedOut(); 2414 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !depthStencil.isStencilMaskedOut(); 2415 2416 if (!color && !depth && !stencil) 2417 { 2418 return angle::Result::Continue; 2419 } 2420 2421 if (partialClearNeedsInit(context, color, depth, stencil)) 2422 { 2423 ANGLE_TRY(ensureDrawAttachmentsInitialized(context)); 2424 } 2425 2426 // If the impl encounters an error during a a full (non-partial) clear, the attachments will 2427 // still be marked initialized. This simplifies design, allowing this method to be called before 2428 // the clear. 2429 markDrawAttachmentsInitialized(color, depth, stencil); 2430 2431 return angle::Result::Continue; 2432 } 2433 2434 angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context, 2435 GLenum buffer, 2436 GLint drawbuffer) 2437 { 2438 if (!context->isRobustResourceInitEnabled() || 2439 context->getState().isRasterizerDiscardEnabled() || 2440 context->isClearBufferMaskedOut(buffer, drawbuffer)) 2441 { 2442 return angle::Result::Continue; 2443 } 2444 2445 if (partialBufferClearNeedsInit(context, buffer)) 2446 { 2447 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer)); 2448 } 2449 2450 // If the impl encounters an error during a a full (non-partial) clear, the attachments will 2451 // still be marked initialized. This simplifies design, allowing this method to be called before 2452 // the clear. 2453 markBufferInitialized(buffer, drawbuffer); 2454 2455 return angle::Result::Continue; 2456 } 2457 2458 angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context) 2459 { 2460 if (!context->isRobustResourceInitEnabled()) 2461 { 2462 return angle::Result::Continue; 2463 } 2464 2465 // Note: we don't actually filter by the draw attachment enum. Just init everything. 2466 for (size_t bit : mState.mResourceNeedsInit) 2467 { 2468 switch (bit) 2469 { 2470 case DIRTY_BIT_DEPTH_ATTACHMENT: 2471 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment)); 2472 break; 2473 case DIRTY_BIT_STENCIL_ATTACHMENT: 2474 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment)); 2475 break; 2476 default: 2477 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit])); 2478 break; 2479 } 2480 } 2481 2482 mState.mResourceNeedsInit.reset(); 2483 return angle::Result::Continue; 2484 } 2485 2486 angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context) 2487 { 2488 ASSERT(context->isRobustResourceInitEnabled()); 2489 2490 if (mState.mResourceNeedsInit.none()) 2491 { 2492 return angle::Result::Continue; 2493 } 2494 2495 if (mState.mReadBufferState != GL_NONE) 2496 { 2497 if (isDefault()) 2498 { 2499 if (!mState.mDefaultFramebufferReadAttachmentInitialized) 2500 { 2501 ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment)); 2502 mState.mDefaultFramebufferReadAttachmentInitialized = true; 2503 } 2504 } 2505 else 2506 { 2507 size_t readIndex = mState.getReadIndex(); 2508 if (mState.mResourceNeedsInit[readIndex]) 2509 { 2510 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex])); 2511 mState.mResourceNeedsInit.reset(readIndex); 2512 } 2513 } 2514 } 2515 2516 // Conservatively init depth since it can be read by BlitFramebuffer. 2517 if (hasDepth()) 2518 { 2519 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT]) 2520 { 2521 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment)); 2522 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2523 } 2524 } 2525 2526 // Conservatively init stencil since it can be read by BlitFramebuffer. 2527 if (hasStencil()) 2528 { 2529 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT]) 2530 { 2531 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment)); 2532 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2533 } 2534 } 2535 2536 return angle::Result::Continue; 2537 } 2538 2539 void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil) 2540 { 2541 // Mark attachments as initialized. 2542 if (color) 2543 { 2544 for (auto colorIndex : mState.mEnabledDrawBuffers) 2545 { 2546 auto &colorAttachment = mState.mColorAttachments[colorIndex]; 2547 ASSERT(colorAttachment.isAttached()); 2548 colorAttachment.setInitState(InitState::Initialized); 2549 mState.mResourceNeedsInit.reset(colorIndex); 2550 } 2551 } 2552 2553 if (depth && mState.mDepthAttachment.isAttached()) 2554 { 2555 mState.mDepthAttachment.setInitState(InitState::Initialized); 2556 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2557 } 2558 2559 if (stencil && mState.mStencilAttachment.isAttached()) 2560 { 2561 mState.mStencilAttachment.setInitState(InitState::Initialized); 2562 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2563 } 2564 } 2565 2566 void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex) 2567 { 2568 switch (bufferType) 2569 { 2570 case GL_COLOR: 2571 { 2572 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size())); 2573 if (mState.mColorAttachments[bufferIndex].isAttached()) 2574 { 2575 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized); 2576 mState.mResourceNeedsInit.reset(bufferIndex); 2577 } 2578 break; 2579 } 2580 case GL_DEPTH: 2581 { 2582 if (mState.mDepthAttachment.isAttached()) 2583 { 2584 mState.mDepthAttachment.setInitState(InitState::Initialized); 2585 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2586 } 2587 break; 2588 } 2589 case GL_STENCIL: 2590 { 2591 if (mState.mStencilAttachment.isAttached()) 2592 { 2593 mState.mStencilAttachment.setInitState(InitState::Initialized); 2594 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2595 } 2596 break; 2597 } 2598 case GL_DEPTH_STENCIL: 2599 { 2600 if (mState.mDepthAttachment.isAttached()) 2601 { 2602 mState.mDepthAttachment.setInitState(InitState::Initialized); 2603 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2604 } 2605 if (mState.mStencilAttachment.isAttached()) 2606 { 2607 mState.mStencilAttachment.setInitState(InitState::Initialized); 2608 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2609 } 2610 break; 2611 } 2612 default: 2613 UNREACHABLE(); 2614 break; 2615 } 2616 } 2617 2618 Box Framebuffer::getDimensions() const 2619 { 2620 return mState.getDimensions(); 2621 } 2622 2623 Extents Framebuffer::getExtents() const 2624 { 2625 return mState.getExtents(); 2626 } 2627 2628 angle::Result Framebuffer::ensureBufferInitialized(const Context *context, 2629 GLenum bufferType, 2630 GLint bufferIndex) 2631 { 2632 ASSERT(context->isRobustResourceInitEnabled()); 2633 2634 if (mState.mResourceNeedsInit.none()) 2635 { 2636 return angle::Result::Continue; 2637 } 2638 2639 switch (bufferType) 2640 { 2641 case GL_COLOR: 2642 { 2643 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size())); 2644 if (mState.mResourceNeedsInit[bufferIndex]) 2645 { 2646 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex])); 2647 mState.mResourceNeedsInit.reset(bufferIndex); 2648 } 2649 break; 2650 } 2651 case GL_DEPTH: 2652 { 2653 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT]) 2654 { 2655 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment)); 2656 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2657 } 2658 break; 2659 } 2660 case GL_STENCIL: 2661 { 2662 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT]) 2663 { 2664 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment)); 2665 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2666 } 2667 break; 2668 } 2669 case GL_DEPTH_STENCIL: 2670 { 2671 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT]) 2672 { 2673 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment)); 2674 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT); 2675 } 2676 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT]) 2677 { 2678 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment)); 2679 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT); 2680 } 2681 break; 2682 } 2683 default: 2684 UNREACHABLE(); 2685 break; 2686 } 2687 2688 return angle::Result::Continue; 2689 } 2690 2691 bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType) 2692 { 2693 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none()) 2694 { 2695 return false; 2696 } 2697 2698 switch (bufferType) 2699 { 2700 case GL_COLOR: 2701 return partialClearNeedsInit(context, true, false, false); 2702 case GL_DEPTH: 2703 return partialClearNeedsInit(context, false, true, false); 2704 case GL_STENCIL: 2705 return partialClearNeedsInit(context, false, false, true); 2706 case GL_DEPTH_STENCIL: 2707 return partialClearNeedsInit(context, false, true, true); 2708 default: 2709 UNREACHABLE(); 2710 return false; 2711 } 2712 } 2713 2714 PixelLocalStorage &Framebuffer::getPixelLocalStorage(const Context *context) 2715 { 2716 if (!mPixelLocalStorage) 2717 { 2718 mPixelLocalStorage = PixelLocalStorage::Make(context); 2719 } 2720 return *mPixelLocalStorage.get(); 2721 } 2722 2723 std::unique_ptr<PixelLocalStorage> Framebuffer::detachPixelLocalStorage() 2724 { 2725 return std::move(mPixelLocalStorage); 2726 } 2727 } // namespace gl