tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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