//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

// Framebuffer9.cpp: Implements the Framebuffer9 class.

#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"

#include "libANGLE/Context.h"
#include "libANGLE/Framebuffer.h"
#include "libANGLE/FramebufferAttachment.h"
#include "libANGLE/Texture.h"
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/ContextImpl.h"
#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
#include "libANGLE/renderer/renderer_utils.h"

namespace rx
{
Framebuffer9::Framebuffer9(const gl::FramebufferState &data, Renderer9 *renderer)
    : FramebufferD3D(data, renderer), mRenderer(renderer)
{
    ASSERT(mRenderer != nullptr);
}

Framebuffer9::~Framebuffer9() {}

angle::Result Framebuffer9::discard(const gl::Context *context,
                                    size_t count,
                                    const GLenum *attachments)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

angle::Result Framebuffer9::invalidate(const gl::Context *context,
                                       size_t count,
                                       const GLenum *attachments)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

angle::Result Framebuffer9::invalidateSub(const gl::Context *context,
                                          size_t count,
                                          const GLenum *attachments,
                                          const gl::Rectangle &area)
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

angle::Result Framebuffer9::clearImpl(const gl::Context *context,
                                      const ClearParameters &clearParams)
{
    ANGLE_TRY(mRenderer->applyRenderTarget(context, mRenderTargetCache.getColors()[0],
                                           mRenderTargetCache.getDepthStencil()));

    const gl::State &glState = context->getState();
    float nearZ              = glState.getNearPlane();
    float farZ               = glState.getFarPlane();
    mRenderer->setViewport(glState.getViewport(), nearZ, farZ, gl::PrimitiveMode::Triangles,
                           glState.getRasterizerState().frontFace, true);

    mRenderer->setScissorRectangle(glState.getScissor(), glState.isScissorTestEnabled());

    mRenderer->clear(clearParams, mRenderTargetCache.getColors()[0],
                     mRenderTargetCache.getDepthStencil());
    return angle::Result::Continue;
}

angle::Result Framebuffer9::readPixelsImpl(const gl::Context *context,
                                           const gl::Rectangle &area,
                                           GLenum format,
                                           GLenum type,
                                           size_t outputPitch,
                                           const gl::PixelPackState &pack,
                                           uint8_t *pixels)
{
    const gl::FramebufferAttachment *colorbuffer = mState.getColorAttachment(0);
    ASSERT(colorbuffer);

    RenderTarget9 *renderTarget = nullptr;
    ANGLE_TRY(colorbuffer->getRenderTarget(context, 0, &renderTarget));
    ASSERT(renderTarget);

    IDirect3DSurface9 *surface = renderTarget->getSurface();
    ASSERT(surface);

    D3DSURFACE_DESC desc;
    surface->GetDesc(&desc);

    Context9 *context9 = GetImplAs<Context9>(context);

    if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
    {
        UNIMPLEMENTED();  // FIXME: Requires resolve using StretchRect into non-multisampled render
                          // target
        SafeRelease(surface);
        ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
                     "ReadPixels is unimplemented for multisampled framebuffer attachments.");
    }

    IDirect3DDevice9 *device = mRenderer->getDevice();
    ASSERT(device);

    HRESULT result;
    IDirect3DSurface9 *systemSurface = nullptr;
    bool directToPixels =
        !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
        area.x == 0 && area.y == 0 && static_cast<UINT>(area.width) == desc.Width &&
        static_cast<UINT>(area.height) == desc.Height && desc.Format == D3DFMT_A8R8G8B8 &&
        format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
    if (directToPixels)
    {
        // Use the pixels ptr as a shared handle to write directly into client's memory
        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
                                                     D3DPOOL_SYSTEMMEM, &systemSurface,
                                                     reinterpret_cast<void **>(&pixels));
        if (FAILED(result))
        {
            // Try again without the shared handle
            directToPixels = false;
        }
    }

    if (!directToPixels)
    {
        result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
                                                     D3DPOOL_SYSTEMMEM, &systemSurface, nullptr);
        if (FAILED(result))
        {
            ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
            SafeRelease(surface);
            ANGLE_TRY_HR(context9, E_OUTOFMEMORY,
                         "Failed to allocate internal texture for ReadPixels.");
        }
    }

    result = device->GetRenderTargetData(surface, systemSurface);
    SafeRelease(surface);

    if (FAILED(result))
    {
        SafeRelease(systemSurface);

        // It turns out that D3D will sometimes produce more error
        // codes than those documented.
        if (d3d9::isDeviceLostError(result))
        {
            mRenderer->notifyDeviceLost();
        }
        else
        {
            UNREACHABLE();
        }

        ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to read internal render target data.");
    }

    if (directToPixels)
    {
        SafeRelease(systemSurface);
        return angle::Result::Continue;
    }

    RECT rect;
    rect.left   = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
    rect.top    = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
    rect.right  = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
    rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));

    D3DLOCKED_RECT lock;
    result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);

    if (FAILED(result))
    {
        UNREACHABLE();
        SafeRelease(systemSurface);

        ANGLE_TRY_HR(context9, E_OUTOFMEMORY, "Failed to lock internal render target.");
    }

    uint8_t *source = static_cast<uint8_t *>(lock.pBits);
    int inputPitch  = lock.Pitch;

    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);

    gl::FormatType formatType(format, type);

    PackPixelsParams packParams;
    packParams.area.x          = rect.left;
    packParams.area.y          = rect.top;
    packParams.area.width      = rect.right - rect.left;
    packParams.area.height     = rect.bottom - rect.top;
    packParams.destFormat      = &GetFormatFromFormatType(format, type);
    packParams.outputPitch     = static_cast<GLuint>(outputPitch);
    packParams.reverseRowOrder = pack.reverseRowOrder;

    PackPixels(packParams, d3dFormatInfo.info(), inputPitch, source, pixels);

    systemSurface->UnlockRect();
    SafeRelease(systemSurface);

    return angle::Result::Continue;
}

angle::Result Framebuffer9::blitImpl(const gl::Context *context,
                                     const gl::Rectangle &sourceArea,
                                     const gl::Rectangle &destArea,
                                     const gl::Rectangle *scissor,
                                     bool blitRenderTarget,
                                     bool blitDepth,
                                     bool blitStencil,
                                     GLenum filter,
                                     const gl::Framebuffer *sourceFramebuffer)
{
    ASSERT(filter == GL_NEAREST);

    IDirect3DDevice9 *device = mRenderer->getDevice();
    ASSERT(device);

    mRenderer->endScene();

    Context9 *context9 = GetImplAs<Context9>(context);

    if (blitRenderTarget)
    {
        const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorAttachment(0);
        ASSERT(readBuffer);

        RenderTarget9 *readRenderTarget = nullptr;
        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readRenderTarget));
        ASSERT(readRenderTarget);

        const gl::FramebufferAttachment *drawBuffer = mState.getColorAttachment(0);
        ASSERT(drawBuffer);

        RenderTarget9 *drawRenderTarget = nullptr;
        ANGLE_TRY(
            drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawRenderTarget));
        ASSERT(drawRenderTarget);

        // The getSurface calls do an AddRef so save them until after no errors are possible
        IDirect3DSurface9 *readSurface = readRenderTarget->getSurface();
        ASSERT(readSurface);

        IDirect3DSurface9 *drawSurface = drawRenderTarget->getSurface();
        ASSERT(drawSurface);

        gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
        gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);

        RECT srcRect;
        srcRect.left   = sourceArea.x;
        srcRect.right  = sourceArea.x + sourceArea.width;
        srcRect.top    = sourceArea.y;
        srcRect.bottom = sourceArea.y + sourceArea.height;

        RECT dstRect;
        dstRect.left   = destArea.x;
        dstRect.right  = destArea.x + destArea.width;
        dstRect.top    = destArea.y;
        dstRect.bottom = destArea.y + destArea.height;

        // Clip the rectangles to the scissor rectangle
        if (scissor)
        {
            if (dstRect.left < scissor->x)
            {
                srcRect.left += (scissor->x - dstRect.left);
                dstRect.left = scissor->x;
            }
            if (dstRect.top < scissor->y)
            {
                srcRect.top += (scissor->y - dstRect.top);
                dstRect.top = scissor->y;
            }
            if (dstRect.right > scissor->x + scissor->width)
            {
                srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
                dstRect.right = scissor->x + scissor->width;
            }
            if (dstRect.bottom > scissor->y + scissor->height)
            {
                srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
                dstRect.bottom = scissor->y + scissor->height;
            }
        }

        // Clip the rectangles to the destination size
        if (dstRect.left < 0)
        {
            srcRect.left += -dstRect.left;
            dstRect.left = 0;
        }
        if (dstRect.right > dstSize.width)
        {
            srcRect.right -= (dstRect.right - dstSize.width);
            dstRect.right = dstSize.width;
        }
        if (dstRect.top < 0)
        {
            srcRect.top += -dstRect.top;
            dstRect.top = 0;
        }
        if (dstRect.bottom > dstSize.height)
        {
            srcRect.bottom -= (dstRect.bottom - dstSize.height);
            dstRect.bottom = dstSize.height;
        }

        // Clip the rectangles to the source size
        if (srcRect.left < 0)
        {
            dstRect.left += -srcRect.left;
            srcRect.left = 0;
        }
        if (srcRect.right > srcSize.width)
        {
            dstRect.right -= (srcRect.right - srcSize.width);
            srcRect.right = srcSize.width;
        }
        if (srcRect.top < 0)
        {
            dstRect.top += -srcRect.top;
            srcRect.top = 0;
        }
        if (srcRect.bottom > srcSize.height)
        {
            dstRect.bottom -= (srcRect.bottom - srcSize.height);
            srcRect.bottom = srcSize.height;
        }

        HRESULT result =
            device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);

        SafeRelease(readSurface);
        SafeRelease(drawSurface);

        ANGLE_TRY_HR(context9, result, "Internal blit failed.");
    }

    if (blitDepth || blitStencil)
    {
        const gl::FramebufferAttachment *readBuffer =
            sourceFramebuffer->getDepthOrStencilAttachment();
        ASSERT(readBuffer);

        RenderTarget9 *readDepthStencil = nullptr;
        ANGLE_TRY(readBuffer->getRenderTarget(context, 0, &readDepthStencil));
        ASSERT(readDepthStencil);

        const gl::FramebufferAttachment *drawBuffer = mState.getDepthOrStencilAttachment();
        ASSERT(drawBuffer);

        RenderTarget9 *drawDepthStencil = nullptr;
        ANGLE_TRY(
            drawBuffer->getRenderTarget(context, drawBuffer->getSamples(), &drawDepthStencil));
        ASSERT(drawDepthStencil);

        // The getSurface calls do an AddRef so save them until after no errors are possible
        IDirect3DSurface9 *readSurface = readDepthStencil->getSurface();
        ASSERT(readDepthStencil);

        IDirect3DSurface9 *drawSurface = drawDepthStencil->getSurface();
        ASSERT(drawDepthStencil);

        HRESULT result =
            device->StretchRect(readSurface, nullptr, drawSurface, nullptr, D3DTEXF_NONE);

        SafeRelease(readSurface);
        SafeRelease(drawSurface);

        ANGLE_TRY_HR(context9, result, "Internal blit failed.");
    }

    return angle::Result::Continue;
}

GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
{
    RenderTarget9 *renderTarget9         = GetAs<RenderTarget9>(renderTarget);
    const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
    return d3dFormatInfo.info().glInternalFormat;
}

angle::Result Framebuffer9::getSamplePosition(const gl::Context *context,
                                              size_t index,
                                              GLfloat *xy) const
{
    ANGLE_HR_UNREACHABLE(GetImplAs<Context9>(context));
    return angle::Result::Stop;
}

angle::Result Framebuffer9::syncState(const gl::Context *context,
                                      const gl::Framebuffer::DirtyBits &dirtyBits)
{
    ANGLE_TRY(FramebufferD3D::syncState(context, dirtyBits));
    ANGLE_TRY(mRenderTargetCache.update(context, mState, dirtyBits));
    return angle::Result::Continue;
}
}  // namespace rx
