tor-browser

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

Framebuffer9.cpp (15268B)


      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 // Framebuffer9.cpp: Implements the Framebuffer9 class.
      8 
      9 #include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
     10 
     11 #include "libANGLE/Context.h"
     12 #include "libANGLE/Framebuffer.h"
     13 #include "libANGLE/FramebufferAttachment.h"
     14 #include "libANGLE/Texture.h"
     15 #include "libANGLE/formatutils.h"
     16 #include "libANGLE/renderer/ContextImpl.h"
     17 #include "libANGLE/renderer/d3d/TextureD3D.h"
     18 #include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
     19 #include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
     20 #include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
     21 #include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
     22 #include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
     23 #include "libANGLE/renderer/renderer_utils.h"
     24 
     25 namespace rx
     26 {
     27 Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
     28    : FramebufferD3D(data, renderer), mRenderer(renderer)
     29 {
     30    ASSERT(mRenderer != nullptr);
     31 }
     32 
     33 Framebuffer9::~Framebuffer9() {}
     34 
     35 angle::Result Framebuffer9::discard(const gl::Context *context,
     36                                    size_t count,
     37                                    const GLenum *attachments)
     38 {
     39    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
     40    return angle::Result::Stop;
     41 }
     42 
     43 angle::Result Framebuffer9::invalidate(const gl::Context *context,
     44                                       size_t count,
     45                                       const GLenum *attachments)
     46 {
     47    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
     48    return angle::Result::Stop;
     49 }
     50 
     51 angle::Result Framebuffer9::invalidateSub(const gl::Context *context,
     52                                          size_t count,
     53                                          const GLenum *attachments,
     54                                          const gl::Rectangle &area)
     55 {
     56    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
     57    return angle::Result::Stop;
     58 }
     59 
     60 angle::Result Framebuffer9::clearImpl(const gl::Context *context,
     61                                      const ClearParameters &clearParams)
     62 {
     63    ANGLE_TRY(mRenderer->applyRenderTarget(context, mRenderTargetCache.getColors()[0],
     64                                           mRenderTargetCache.getDepthStencil()));
     65 
     66    const gl::State &glState = context->getState();
     67    float nearZ              = glState.getNearPlane();
     68    float farZ               = glState.getFarPlane();
     69    mRenderer->setViewport(glState.getViewport(), nearZ, farZ, gl::PrimitiveMode::Triangles,
     70                           glState.getRasterizerState().frontFace, true);
     71 
     72    mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());
     73 
     74    mRenderer->clear(clearParams, mRenderTargetCache.getColors()[0],
     75                     mRenderTargetCache.getDepthStencil());
     76    return angle::Result::Continue;
     77 }
     78 
     79 angle::Result Framebuffer9::readPixelsImpl(const gl::Context *context,
     80                                           const gl::Rectangle &area,
     81                                           GLenum format,
     82                                           GLenum type,
     83                                           size_t outputPitch,
     84                                           const gl::PixelPackState &pack,
     85                                           gl::Buffer *packBuffer,
     86                                           uint8_t *pixels)
     87 {
     88    const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
     89    ASSERT(colorbuffer);
     90 
     91    RenderTarget9 *renderTarget = nullptr;
     92    ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget));
     93    ASSERT(renderTarget);
     94 
     95    IDirect3DSurface9 *surface = renderTarget->getSurface();
     96    ASSERT(surface);
     97 
     98    D3DSURFACE_DESC desc;
     99    surface->GetDesc(&desc);
    100 
    101    Context9 *context9 = GetImplAs<Context9>(context);
    102 
    103    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
    104    {
    105        UNIMPLEMENTED();  // FIXME: Requires resolve using StretchRect into non-multisampled render
    106                          // target
    107        SafeRelease(surface);
    108        ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
    109                     "ReadPixels is unimplemented for multisampled framebuffer attachments.");
    110    }
    111 
    112    IDirect3DDevice9 *device = mRenderer->getDevice();
    113    ASSERT(device);
    114 
    115    HRESULT result;
    116    IDirect3DSurface9 *systemSurface = nullptr;
    117    bool directToPixels =
    118        !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
    119        area.x == 0 && area.y == 0 && static_cast<UINT>(area.width) == desc.Width &&
    120        static_cast<UINT>(area.height) == desc.Height && desc.Format == D3DFMT_A8R8G8B8 &&
    121        format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
    122    if (directToPixels)
    123    {
    124        // Use the pixels ptr as a shared handle to write directly into client's memory
    125        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
    126                                                     D3DPOOL_SYSTEMMEM, &systemSurface,
    127                                                     reinterpret_cast<void **>(&pixels));
    128        if (FAILED(result))
    129        {
    130            // Try again without the shared handle
    131            directToPixels = false;
    132        }
    133    }
    134 
    135    if (!directToPixels)
    136    {
    137        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
    138                                                     D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
    139        if (FAILED(result))
    140        {
    141            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
    142            SafeRelease(surface);
    143            ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
    144                         "Failed to allocate internal texture for ReadPixels.");
    145        }
    146    }
    147 
    148    result = device->GetRenderTargetData(surface, systemSurface);
    149    SafeRelease(surface);
    150 
    151    if (FAILED(result))
    152    {
    153        SafeRelease(systemSurface);
    154 
    155        // It turns out that D3D will sometimes produce more error
    156        // codes than those documented.
    157        if (d3d9::isDeviceLostError(result))
    158        {
    159            mRenderer->notifyDeviceLost();
    160        }
    161        else
    162        {
    163            UNREACHABLE();
    164        }
    165 
    166        ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to read internal render target data.");
    167    }
    168 
    169    if (directToPixels)
    170    {
    171        SafeRelease(systemSurface);
    172        return angle::Result::Continue;
    173    }
    174 
    175    RECT rect;
    176    rect.left   = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
    177    rect.top    = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
    178    rect.right  = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
    179    rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
    180 
    181    D3DLOCKED_RECT lock;
    182    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
    183 
    184    if (FAILED(result))
    185    {
    186        UNREACHABLE();
    187        SafeRelease(systemSurface);
    188 
    189        ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to lock internal render target.");
    190    }
    191 
    192    uint8_t *source = static_cast<uint8_t *>(lock.pBits);
    193    int inputPitch  = lock.Pitch;
    194 
    195    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
    196 
    197    gl::FormatType formatType(format, type);
    198 
    199    PackPixelsParams packParams;
    200    packParams.area.x          = rect.left;
    201    packParams.area.y          = rect.top;
    202    packParams.area.width      = rect.right - rect.left;
    203    packParams.area.height     = rect.bottom - rect.top;
    204    packParams.destFormat      = &GetFormatFromFormatType(format, type);
    205    packParams.outputPitch     = static_cast<GLuint>(outputPitch);
    206    packParams.reverseRowOrder = pack.reverseRowOrder;
    207 
    208    PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);
    209 
    210    systemSurface->UnlockRect();
    211    SafeRelease(systemSurface);
    212 
    213    return angle::Result::Continue;
    214 }
    215 
    216 angle::Result Framebuffer9::blitImpl(const gl::Context *context,
    217                                     const gl::Rectangle &sourceArea,
    218                                     const gl::Rectangle &destArea,
    219                                     const gl::Rectangle *scissor,
    220                                     bool blitRenderTarget,
    221                                     bool blitDepth,
    222                                     bool blitStencil,
    223                                     GLenum filter,
    224                                     const gl::Framebuffer *sourceFramebuffer)
    225 {
    226    ASSERT(filter == GL_NEAREST);
    227 
    228    IDirect3DDevice9 *device = mRenderer->getDevice();
    229    ASSERT(device);
    230 
    231    mRenderer->endScene();
    232 
    233    Context9 *context9 = GetImplAs<Context9>(context);
    234 
    235    if (blitRenderTarget)
    236    {
    237        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorAttachment(0);
    238        ASSERT(readBuffer);
    239 
    240        RenderTarget9 *readRenderTarget = nullptr;
    241        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
    242        ASSERT(readRenderTarget);
    243 
    244        const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
    245        ASSERT(drawBuffer);
    246 
    247        RenderTarget9 *drawRenderTarget = nullptr;
    248        ANGLE_TRY(
    249            drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawRenderTarget));
    250        ASSERT(drawRenderTarget);
    251 
    252        // The getSurface calls do an AddRef so save them until after no errors are possible
    253        IDirect3DSurface9 *readSurface = readRenderTarget->getSurface();
    254        ASSERT(readSurface);
    255 
    256        IDirect3DSurface9 *drawSurface = drawRenderTarget->getSurface();
    257        ASSERT(drawSurface);
    258 
    259        gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
    260        gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
    261 
    262        RECT srcRect;
    263        srcRect.left   = sourceArea.x;
    264        srcRect.right  = sourceArea.x + sourceArea.width;
    265        srcRect.top    = sourceArea.y;
    266        srcRect.bottom = sourceArea.y + sourceArea.height;
    267 
    268        RECT dstRect;
    269        dstRect.left   = destArea.x;
    270        dstRect.right  = destArea.x + destArea.width;
    271        dstRect.top    = destArea.y;
    272        dstRect.bottom = destArea.y + destArea.height;
    273 
    274        // Clip the rectangles to the scissor rectangle
    275        if (scissor)
    276        {
    277            if (dstRect.left < scissor->x)
    278            {
    279                srcRect.left += (scissor->x - dstRect.left);
    280                dstRect.left = scissor->x;
    281            }
    282            if (dstRect.top < scissor->y)
    283            {
    284                srcRect.top += (scissor->y - dstRect.top);
    285                dstRect.top = scissor->y;
    286            }
    287            if (dstRect.right > scissor->x + scissor->width)
    288            {
    289                srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
    290                dstRect.right = scissor->x + scissor->width;
    291            }
    292            if (dstRect.bottom > scissor->y + scissor->height)
    293            {
    294                srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
    295                dstRect.bottom = scissor->y + scissor->height;
    296            }
    297        }
    298 
    299        // Clip the rectangles to the destination size
    300        if (dstRect.left < 0)
    301        {
    302            srcRect.left += -dstRect.left;
    303            dstRect.left = 0;
    304        }
    305        if (dstRect.right > dstSize.width)
    306        {
    307            srcRect.right -= (dstRect.right - dstSize.width);
    308            dstRect.right = dstSize.width;
    309        }
    310        if (dstRect.top < 0)
    311        {
    312            srcRect.top += -dstRect.top;
    313            dstRect.top = 0;
    314        }
    315        if (dstRect.bottom > dstSize.height)
    316        {
    317            srcRect.bottom -= (dstRect.bottom - dstSize.height);
    318            dstRect.bottom = dstSize.height;
    319        }
    320 
    321        // Clip the rectangles to the source size
    322        if (srcRect.left < 0)
    323        {
    324            dstRect.left += -srcRect.left;
    325            srcRect.left = 0;
    326        }
    327        if (srcRect.right > srcSize.width)
    328        {
    329            dstRect.right -= (srcRect.right - srcSize.width);
    330            srcRect.right = srcSize.width;
    331        }
    332        if (srcRect.top < 0)
    333        {
    334            dstRect.top += -srcRect.top;
    335            srcRect.top = 0;
    336        }
    337        if (srcRect.bottom > srcSize.height)
    338        {
    339            dstRect.bottom -= (srcRect.bottom - srcSize.height);
    340            srcRect.bottom = srcSize.height;
    341        }
    342 
    343        HRESULT result =
    344            device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
    345 
    346        SafeRelease(readSurface);
    347        SafeRelease(drawSurface);
    348 
    349        ANGLE_TRY_HR(context9, result, "Internal blit failed.");
    350    }
    351 
    352    if (blitDepth || blitStencil)
    353    {
    354        const gl::FramebufferAttachment *readBuffer =
    355            sourceFramebuffer->getDepthOrStencilAttachment();
    356        ASSERT(readBuffer);
    357 
    358        RenderTarget9 *readDepthStencil = nullptr;
    359        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readDepthStencil));
    360        ASSERT(readDepthStencil);
    361 
    362        const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
    363        ASSERT(drawBuffer);
    364 
    365        RenderTarget9 *drawDepthStencil = nullptr;
    366        ANGLE_TRY(
    367            drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawDepthStencil));
    368        ASSERT(drawDepthStencil);
    369 
    370        // The getSurface calls do an AddRef so save them until after no errors are possible
    371        IDirect3DSurface9 *readSurface = readDepthStencil->getSurface();
    372        ASSERT(readDepthStencil);
    373 
    374        IDirect3DSurface9 *drawSurface = drawDepthStencil->getSurface();
    375        ASSERT(drawDepthStencil);
    376 
    377        HRESULT result =
    378            device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);
    379 
    380        SafeRelease(readSurface);
    381        SafeRelease(drawSurface);
    382 
    383        ANGLE_TRY_HR(context9, result, "Internal blit failed.");
    384    }
    385 
    386    return angle::Result::Continue;
    387 }
    388 
    389 const gl::InternalFormat &Framebuffer9::getImplementationColorReadFormat(
    390    const gl::Context *context) const
    391 {
    392    GLenum sizedFormat = mState.getReadAttachment()->getFormat().info->sizedInternalFormat;
    393    const d3d9::TextureFormat &textureFormat = d3d9::GetTextureFormatInfo(sizedFormat);
    394    const d3d9::D3DFormat &d3dFormatInfo     = d3d9::GetD3DFormatInfo(textureFormat.renderFormat);
    395    const angle::Format &angleFormat         = angle::Format::Get(d3dFormatInfo.formatID);
    396    return gl::GetSizedInternalFormatInfo(angleFormat.fboImplementationInternalFormat);
    397 }
    398 
    399 angle::Result Framebuffer9::getSamplePosition(const gl::Context *context,
    400                                              size_t index,
    401                                              GLfloat *xy) const
    402 {
    403    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    404    return angle::Result::Stop;
    405 }
    406 
    407 angle::Result Framebuffer9::syncState(const gl::Context *context,
    408                                      GLenum binding,
    409                                      const gl::Framebuffer::DirtyBits &dirtyBits,
    410                                      gl::Command command)
    411 {
    412    ANGLE_TRY(FramebufferD3D::syncState(context, binding, dirtyBits, command));
    413    ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
    414    return angle::Result::Continue;
    415 }
    416 }  // namespace rx