tor-browser

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

Framebuffer11.cpp (18105B)


      1 //
      2 // Copyright 2014 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 // Framebuffer11.cpp: Implements the Framebuffer11 class.
      8 
      9 #include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
     10 
     11 #include "common/bitset_utils.h"
     12 #include "common/debug.h"
     13 #include "libANGLE/Context.h"
     14 #include "libANGLE/Framebuffer.h"
     15 #include "libANGLE/FramebufferAttachment.h"
     16 #include "libANGLE/Texture.h"
     17 #include "libANGLE/renderer/d3d/TextureD3D.h"
     18 #include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
     19 #include "libANGLE/renderer/d3d/d3d11/Clear11.h"
     20 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
     21 #include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
     22 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
     23 #include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
     24 #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
     25 #include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
     26 
     27 using namespace angle;
     28 
     29 namespace rx
     30 {
     31 
     32 namespace
     33 {
     34 angle::Result MarkAttachmentsDirty(const gl::Context *context,
     35                                   const gl::FramebufferAttachment *attachment)
     36 {
     37    if (attachment->type() == GL_TEXTURE)
     38    {
     39        gl::Texture *texture = attachment->getTexture();
     40 
     41        TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
     42 
     43        TextureStorage *texStorage = nullptr;
     44        ANGLE_TRY(textureD3D->getNativeTexture(context, &texStorage));
     45 
     46        if (texStorage)
     47        {
     48            TextureStorage11 *texStorage11 = GetAs<TextureStorage11>(texStorage);
     49            ASSERT(texStorage11);
     50 
     51            texStorage11->markLevelDirty(attachment->mipLevel());
     52        }
     53    }
     54 
     55    return angle::Result::Continue;
     56 }
     57 
     58 UINT GetAttachmentLayer(const gl::FramebufferAttachment *attachment)
     59 {
     60    if (attachment->type() == GL_TEXTURE &&
     61        attachment->getTexture()->getType() == gl::TextureType::_3D)
     62    {
     63        return attachment->layer();
     64    }
     65    return 0;
     66 }
     67 
     68 }  // anonymous namespace
     69 
     70 Framebuffer11::Framebuffer11(const gl::FramebufferState &data, Renderer11 *renderer)
     71    : FramebufferD3D(data, renderer), mRenderer(renderer)
     72 {
     73    ASSERT(mRenderer != nullptr);
     74 }
     75 
     76 Framebuffer11::~Framebuffer11() {}
     77 
     78 angle::Result Framebuffer11::markAttachmentsDirty(const gl::Context *context) const
     79 {
     80    const auto &colorAttachments = mState.getColorAttachments();
     81    for (size_t drawBuffer : mState.getEnabledDrawBuffers())
     82    {
     83        const gl::FramebufferAttachment &colorAttachment = colorAttachments[drawBuffer];
     84        ASSERT(colorAttachment.isAttached());
     85        ANGLE_TRY(MarkAttachmentsDirty(context, &colorAttachment));
     86    }
     87 
     88    const gl::FramebufferAttachment *dsAttachment = mState.getDepthOrStencilAttachment();
     89    if (dsAttachment)
     90    {
     91        ANGLE_TRY(MarkAttachmentsDirty(context, dsAttachment));
     92    }
     93 
     94    return angle::Result::Continue;
     95 }
     96 
     97 angle::Result Framebuffer11::clearImpl(const gl::Context *context,
     98                                       const ClearParameters &clearParams)
     99 {
    100    Clear11 *clearer = mRenderer->getClearer();
    101 
    102    const gl::FramebufferAttachment *colorAttachment = mState.getFirstColorAttachment();
    103    if (clearParams.scissorEnabled == true && colorAttachment != nullptr &&
    104        UsePresentPathFast(mRenderer, colorAttachment))
    105    {
    106        // If the current framebuffer is using the default colorbuffer, and present path fast is
    107        // active, and the scissor rect is enabled, then we should invert the scissor rect
    108        // vertically
    109        ClearParameters presentPathFastClearParams = clearParams;
    110        gl::Extents framebufferSize                = colorAttachment->getSize();
    111        presentPathFastClearParams.scissor.y       = framebufferSize.height -
    112                                               presentPathFastClearParams.scissor.y -
    113                                               presentPathFastClearParams.scissor.height;
    114        ANGLE_TRY(clearer->clearFramebuffer(context, presentPathFastClearParams, mState));
    115    }
    116    else
    117    {
    118        ANGLE_TRY(clearer->clearFramebuffer(context, clearParams, mState));
    119    }
    120 
    121    ANGLE_TRY(markAttachmentsDirty(context));
    122 
    123    return angle::Result::Continue;
    124 }
    125 
    126 angle::Result Framebuffer11::invalidate(const gl::Context *context,
    127                                        size_t count,
    128                                        const GLenum *attachments)
    129 {
    130    return invalidateBase(context, count, attachments, false);
    131 }
    132 
    133 angle::Result Framebuffer11::discard(const gl::Context *context,
    134                                     size_t count,
    135                                     const GLenum *attachments)
    136 {
    137    return invalidateBase(context, count, attachments, true);
    138 }
    139 
    140 angle::Result Framebuffer11::invalidateBase(const gl::Context *context,
    141                                            size_t count,
    142                                            const GLenum *attachments,
    143                                            bool useEXTBehavior) const
    144 {
    145    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
    146 
    147    if (!deviceContext1)
    148    {
    149        // DiscardView() is only supported on ID3D11DeviceContext1
    150        return angle::Result::Continue;
    151    }
    152 
    153    bool foundDepth   = false;
    154    bool foundStencil = false;
    155 
    156    for (size_t i = 0; i < count; ++i)
    157    {
    158        switch (attachments[i])
    159        {
    160            // Handle depth and stencil attachments. Defer discarding until later.
    161            case GL_DEPTH_STENCIL_ATTACHMENT:
    162                foundDepth   = true;
    163                foundStencil = true;
    164                break;
    165            case GL_DEPTH_EXT:
    166            case GL_DEPTH_ATTACHMENT:
    167                foundDepth = true;
    168                break;
    169            case GL_STENCIL_EXT:
    170            case GL_STENCIL_ATTACHMENT:
    171                foundStencil = true;
    172                break;
    173            default:
    174            {
    175                // Handle color attachments
    176                ASSERT((attachments[i] >= GL_COLOR_ATTACHMENT0 &&
    177                        attachments[i] <= GL_COLOR_ATTACHMENT15) ||
    178                       (attachments[i] == GL_COLOR));
    179 
    180                size_t colorIndex =
    181                    (attachments[i] == GL_COLOR ? 0u : (attachments[i] - GL_COLOR_ATTACHMENT0));
    182                const gl::FramebufferAttachment *colorAttachment =
    183                    mState.getColorAttachment(colorIndex);
    184                if (colorAttachment)
    185                {
    186                    ANGLE_TRY(invalidateAttachment(context, colorAttachment));
    187                }
    188                break;
    189            }
    190        }
    191    }
    192 
    193    bool discardDepth   = false;
    194    bool discardStencil = false;
    195 
    196    // The D3D11 renderer uses the same view for depth and stencil buffers, so we must be careful.
    197    if (useEXTBehavior)
    198    {
    199        // In the extension, if the app discards only one of the depth and stencil attachments, but
    200        // those are backed by the same packed_depth_stencil buffer, then both images become
    201        // undefined.
    202        discardDepth = foundDepth;
    203 
    204        // Don't bother discarding the stencil buffer if the depth buffer will already do it
    205        discardStencil = foundStencil && (!discardDepth || mState.getDepthAttachment() == nullptr);
    206    }
    207    else
    208    {
    209        // In ES 3.0.4, if a specified attachment has base internal format DEPTH_STENCIL but the
    210        // attachments list does not include DEPTH_STENCIL_ATTACHMENT or both DEPTH_ATTACHMENT and
    211        // STENCIL_ATTACHMENT, then only the specified portion of every pixel in the subregion of
    212        // pixels of the DEPTH_STENCIL buffer may be invalidated, and the other portion must be
    213        // preserved.
    214        discardDepth = (foundDepth && foundStencil) ||
    215                       (foundDepth && (mState.getStencilAttachment() == nullptr));
    216        discardStencil = (foundStencil && (mState.getDepthAttachment() == nullptr));
    217    }
    218 
    219    if (discardDepth && mState.getDepthAttachment())
    220    {
    221        ANGLE_TRY(invalidateAttachment(context, mState.getDepthAttachment()));
    222    }
    223 
    224    if (discardStencil && mState.getStencilAttachment())
    225    {
    226        ANGLE_TRY(invalidateAttachment(context, mState.getStencilAttachment()));
    227    }
    228 
    229    return angle::Result::Continue;
    230 }
    231 
    232 angle::Result Framebuffer11::invalidateSub(const gl::Context *context,
    233                                           size_t count,
    234                                           const GLenum *attachments,
    235                                           const gl::Rectangle &area)
    236 {
    237    // A no-op implementation conforms to the spec, so don't call UNIMPLEMENTED()
    238    return angle::Result::Continue;
    239 }
    240 
    241 angle::Result Framebuffer11::invalidateAttachment(const gl::Context *context,
    242                                                  const gl::FramebufferAttachment *attachment) const
    243 {
    244    ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
    245    ASSERT(deviceContext1);
    246    ASSERT(attachment && attachment->isAttached());
    247 
    248    RenderTarget11 *renderTarget = nullptr;
    249    ANGLE_TRY(attachment->getRenderTarget(context, 0, &renderTarget));
    250    const auto &rtv = renderTarget->getRenderTargetView();
    251 
    252    if (rtv.valid())
    253    {
    254        deviceContext1->DiscardView(rtv.get());
    255    }
    256 
    257    return angle::Result::Continue;
    258 }
    259 
    260 angle::Result Framebuffer11::readPixelsImpl(const gl::Context *context,
    261                                            const gl::Rectangle &area,
    262                                            GLenum format,
    263                                            GLenum type,
    264                                            size_t outputPitch,
    265                                            const gl::PixelPackState &pack,
    266                                            gl::Buffer *packBuffer,
    267                                            uint8_t *pixels)
    268 {
    269    const gl::FramebufferAttachment *readAttachment = mState.getReadPixelsAttachment(format);
    270    ASSERT(readAttachment);
    271 
    272    if (packBuffer != nullptr)
    273    {
    274        Buffer11 *packBufferStorage      = GetImplAs<Buffer11>(packBuffer);
    275        const angle::Format &angleFormat = GetFormatFromFormatType(format, type);
    276        PackPixelsParams packParams(area, angleFormat, static_cast<GLuint>(outputPitch),
    277                                    pack.reverseRowOrder, packBuffer,
    278                                    reinterpret_cast<ptrdiff_t>(pixels));
    279 
    280        return packBufferStorage->packPixels(context, *readAttachment, packParams);
    281    }
    282 
    283    return mRenderer->readFromAttachment(context, *readAttachment, area, format, type,
    284                                         static_cast<GLuint>(outputPitch), pack, pixels);
    285 }
    286 
    287 angle::Result Framebuffer11::blitImpl(const gl::Context *context,
    288                                      const gl::Rectangle &sourceArea,
    289                                      const gl::Rectangle &destArea,
    290                                      const gl::Rectangle *scissor,
    291                                      bool blitRenderTarget,
    292                                      bool blitDepth,
    293                                      bool blitStencil,
    294                                      GLenum filter,
    295                                      const gl::Framebuffer *sourceFramebuffer)
    296 {
    297    if (blitRenderTarget)
    298    {
    299        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorAttachment();
    300        ASSERT(readBuffer);
    301 
    302        RenderTargetD3D *readRenderTarget = nullptr;
    303        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
    304        ASSERT(readRenderTarget);
    305 
    306        const auto &colorAttachments = mState.getColorAttachments();
    307        const auto &drawBufferStates = mState.getDrawBufferStates();
    308        UINT readLayer               = GetAttachmentLayer(readBuffer);
    309 
    310        for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size();
    311             colorAttachment++)
    312        {
    313            const gl::FramebufferAttachment &drawBuffer = colorAttachments[colorAttachment];
    314 
    315            if (drawBuffer.isAttached() && drawBufferStates[colorAttachment] != GL_NONE)
    316            {
    317                RenderTargetD3D *drawRenderTarget = nullptr;
    318                ANGLE_TRY(drawBuffer.getRenderTarget(
    319                    context, drawBuffer.getRenderToTextureSamples(), &drawRenderTarget));
    320                ASSERT(drawRenderTarget);
    321 
    322                const bool invertColorSource   = UsePresentPathFast(mRenderer, readBuffer);
    323                gl::Rectangle actualSourceArea = sourceArea;
    324                if (invertColorSource)
    325                {
    326                    RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
    327                    actualSourceArea.y      = readRenderTarget11->getHeight() - sourceArea.y;
    328                    actualSourceArea.height = -sourceArea.height;
    329                }
    330 
    331                const bool invertColorDest   = UsePresentPathFast(mRenderer, &drawBuffer);
    332                gl::Rectangle actualDestArea = destArea;
    333                UINT drawLayer               = GetAttachmentLayer(&drawBuffer);
    334 
    335                const auto &surfaceTextureOffset = mState.getSurfaceTextureOffset();
    336                actualDestArea.x                 = actualDestArea.x + surfaceTextureOffset.x;
    337                actualDestArea.y                 = actualDestArea.y + surfaceTextureOffset.y;
    338 
    339                if (invertColorDest)
    340                {
    341                    RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
    342                    actualDestArea.y      = drawRenderTarget11->getHeight() - destArea.y;
    343                    actualDestArea.height = -destArea.height;
    344                }
    345 
    346                ANGLE_TRY(mRenderer->blitRenderbufferRect(context, actualSourceArea, actualDestArea,
    347                                                          readLayer, drawLayer, readRenderTarget,
    348                                                          drawRenderTarget, filter, scissor,
    349                                                          blitRenderTarget, false, false));
    350            }
    351        }
    352    }
    353 
    354    if (blitDepth || blitStencil)
    355    {
    356        const gl::FramebufferAttachment *readBuffer =
    357            sourceFramebuffer->getDepthOrStencilAttachment();
    358        ASSERT(readBuffer);
    359        RenderTargetD3D *readRenderTarget = nullptr;
    360        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
    361        ASSERT(readRenderTarget);
    362 
    363        const bool invertSource        = UsePresentPathFast(mRenderer, readBuffer);
    364        gl::Rectangle actualSourceArea = sourceArea;
    365        if (invertSource)
    366        {
    367            RenderTarget11 *readRenderTarget11 = GetAs<RenderTarget11>(readRenderTarget);
    368            actualSourceArea.y                 = readRenderTarget11->getHeight() - sourceArea.y;
    369            actualSourceArea.height            = -sourceArea.height;
    370        }
    371 
    372        const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
    373        ASSERT(drawBuffer);
    374        RenderTargetD3D *drawRenderTarget = nullptr;
    375        ANGLE_TRY(drawBuffer->getRenderTarget(context, drawBuffer->getRenderToTextureSamples(),
    376                                              &drawRenderTarget));
    377        ASSERT(drawRenderTarget);
    378 
    379        bool invertDest              = UsePresentPathFast(mRenderer, drawBuffer);
    380        gl::Rectangle actualDestArea = destArea;
    381        if (invertDest)
    382        {
    383            RenderTarget11 *drawRenderTarget11 = GetAs<RenderTarget11>(drawRenderTarget);
    384            actualDestArea.y                   = drawRenderTarget11->getHeight() - destArea.y;
    385            actualDestArea.height              = -destArea.height;
    386        }
    387 
    388        ANGLE_TRY(mRenderer->blitRenderbufferRect(context, actualSourceArea, actualDestArea, 0, 0,
    389                                                  readRenderTarget, drawRenderTarget, filter,
    390                                                  scissor, false, blitDepth, blitStencil));
    391    }
    392 
    393    ANGLE_TRY(markAttachmentsDirty(context));
    394    return angle::Result::Continue;
    395 }
    396 
    397 const gl::InternalFormat &Framebuffer11::getImplementationColorReadFormat(
    398    const gl::Context *context) const
    399 {
    400    Context11 *context11             = GetImplAs<Context11>(context);
    401    const Renderer11DeviceCaps &caps = context11->getRenderer()->getRenderer11DeviceCaps();
    402    GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
    403    const angle::Format &angleFormat = d3d11::Format::Get(sizedFormat, caps).format();
    404    return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
    405 }
    406 
    407 angle::Result Framebuffer11::syncState(const gl::Context *context,
    408                                       GLenum binding,
    409                                       const gl::Framebuffer::DirtyBits &dirtyBits,
    410                                       gl::Command command)
    411 {
    412    ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
    413    ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits, command));
    414 
    415    // Call this last to allow the state manager to take advantage of the cached render targets.
    416    mRenderer->getStateManager()->invalidateRenderTarget();
    417 
    418    // Call this to syncViewport for framebuffer default parameters.
    419    if (mState.getDefaultWidth() != 0 || mState.getDefaultHeight() != 0)
    420    {
    421        mRenderer->getStateManager()->invalidateViewport(context);
    422    }
    423 
    424    return angle::Result::Continue;
    425 }
    426 
    427 angle::Result Framebuffer11::getSamplePosition(const gl::Context *context,
    428                                               size_t index,
    429                                               GLfloat *xy) const
    430 {
    431    const gl::FramebufferAttachment *attachment = mState.getFirstNonNullAttachment();
    432    ASSERT(attachment);
    433    GLsizei sampleCount = attachment->getSamples();
    434 
    435    rx::GetSamplePosition(sampleCount, index, xy);
    436    return angle::Result::Continue;
    437 }
    438 
    439 RenderTarget11 *Framebuffer11::getFirstRenderTarget() const
    440 {
    441    for (auto *renderTarget : mRenderTargetCache.getColors())
    442    {
    443        if (renderTarget)
    444        {
    445            return renderTarget;
    446        }
    447    }
    448 
    449    return mRenderTargetCache.getDepthStencil();
    450 }
    451 
    452 }  // namespace rx