//
// Copyright 2024 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.
//
// SurfaceWgpu.cpp:
//    Implements the class methods for SurfaceWgpu.
//

#include "libANGLE/renderer/wgpu/SurfaceWgpu.h"

#include "common/debug.h"

#include "libANGLE/Display.h"
#include "libANGLE/Surface.h"
#include "libANGLE/renderer/wgpu/DisplayWgpu.h"
#include "libANGLE/renderer/wgpu/FramebufferWgpu.h"

namespace rx
{

constexpr wgpu::TextureUsage kSurfaceTextureUsage =
    wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment |
    wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;

SurfaceWgpu::SurfaceWgpu(const egl::SurfaceState &surfaceState) : SurfaceImpl(surfaceState) {}

SurfaceWgpu::~SurfaceWgpu() {}

angle::Result SurfaceWgpu::createDepthStencilAttachment(uint32_t width,
                                                        uint32_t height,
                                                        const webgpu::Format &webgpuFormat,
                                                        wgpu::Device &device,
                                                        AttachmentImage *outDepthStencilAttachment)
{
    wgpu::TextureDescriptor desc = outDepthStencilAttachment->texture.createTextureDescriptor(
        kSurfaceTextureUsage, wgpu::TextureDimension::e2D, {width, height, 1},
        webgpuFormat.getActualWgpuTextureFormat(), 1, 1);

    constexpr uint32_t level = 0;
    constexpr uint32_t layer = 0;

    ANGLE_TRY(outDepthStencilAttachment->texture.initImage(webgpuFormat.getIntendedFormatID(),
                                                           webgpuFormat.getActualImageFormatID(),
                                                           device, gl::LevelIndex(level), desc));

    wgpu::TextureView view;
    ANGLE_TRY(
        outDepthStencilAttachment->texture.createTextureView(gl::LevelIndex(level), layer, view));
    outDepthStencilAttachment->renderTarget.set(
        &outDepthStencilAttachment->texture, view, webgpu::LevelIndex(level), layer,
        outDepthStencilAttachment->texture.toWgpuTextureFormat());
    return angle::Result::Continue;
}

OffscreenSurfaceWgpu::OffscreenSurfaceWgpu(const egl::SurfaceState &surfaceState)
    : SurfaceWgpu(surfaceState),
      mWidth(surfaceState.attributes.getAsInt(EGL_WIDTH, 0)),
      mHeight(surfaceState.attributes.getAsInt(EGL_HEIGHT, 0))
{}

OffscreenSurfaceWgpu::~OffscreenSurfaceWgpu() {}

egl::Error OffscreenSurfaceWgpu::initialize(const egl::Display *display)
{
    return angle::ResultToEGL(initializeImpl(display));
}

egl::Error OffscreenSurfaceWgpu::swap(const gl::Context *context)
{
    UNREACHABLE();
    return egl::NoError();
}

egl::Error OffscreenSurfaceWgpu::bindTexImage(const gl::Context *context,
                                              gl::Texture *texture,
                                              EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error OffscreenSurfaceWgpu::releaseTexImage(const gl::Context *context, EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

void OffscreenSurfaceWgpu::setSwapInterval(const egl::Display *display, EGLint interval) {}

EGLint OffscreenSurfaceWgpu::getWidth() const
{
    return mWidth;
}

EGLint OffscreenSurfaceWgpu::getHeight() const
{
    return mHeight;
}

EGLint OffscreenSurfaceWgpu::getSwapBehavior() const
{
    return EGL_BUFFER_DESTROYED;
}

angle::Result OffscreenSurfaceWgpu::initializeContents(const gl::Context *context,
                                                       GLenum binding,
                                                       const gl::ImageIndex &imageIndex)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

egl::Error OffscreenSurfaceWgpu::attachToFramebuffer(const gl::Context *context,
                                                     gl::Framebuffer *framebuffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error OffscreenSurfaceWgpu::detachFromFramebuffer(const gl::Context *context,
                                                       gl::Framebuffer *framebuffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

angle::Result OffscreenSurfaceWgpu::getAttachmentRenderTarget(
    const gl::Context *context,
    GLenum binding,
    const gl::ImageIndex &imageIndex,
    GLsizei samples,
    FramebufferAttachmentRenderTarget **rtOut)
{
    if (binding == GL_BACK)
    {
        *rtOut = &mColorAttachment.renderTarget;
    }
    else
    {
        ASSERT(binding == GL_DEPTH || binding == GL_STENCIL || binding == GL_DEPTH_STENCIL);
        *rtOut = &mDepthStencilAttachment.renderTarget;
    }

    return angle::Result::Continue;
}

angle::Result OffscreenSurfaceWgpu::initializeImpl(const egl::Display *display)
{
    DisplayWgpu *displayWgpu = webgpu::GetImpl(display);
    wgpu::Device &device     = displayWgpu->getDevice();

    const egl::Config *config = mState.config;

    if (config->renderTargetFormat != GL_NONE)
    {
        const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->renderTargetFormat);
        wgpu::TextureDescriptor desc       = mColorAttachment.texture.createTextureDescriptor(
            kSurfaceTextureUsage, wgpu::TextureDimension::e2D,
            {static_cast<uint32_t>(mWidth), static_cast<uint32_t>(mHeight), 1},
            webgpuFormat.getActualWgpuTextureFormat(), 1, 1);

        constexpr uint32_t level = 0;
        constexpr uint32_t layer = 0;

        ANGLE_TRY(mColorAttachment.texture.initImage(webgpuFormat.getIntendedFormatID(),
                                                     webgpuFormat.getActualImageFormatID(), device,
                                                     gl::LevelIndex(level), desc));

        wgpu::TextureView view;
        ANGLE_TRY(mColorAttachment.texture.createTextureView(gl::LevelIndex(level), layer, view));
        mColorAttachment.renderTarget.set(&mColorAttachment.texture, view,
                                          webgpu::LevelIndex(level), layer,
                                          mColorAttachment.texture.toWgpuTextureFormat());
    }

    if (config->depthStencilFormat != GL_NONE)
    {
        const webgpu::Format &webgpuFormat = displayWgpu->getFormat(config->depthStencilFormat);
        ANGLE_TRY(createDepthStencilAttachment(static_cast<uint32_t>(mWidth),
                                               static_cast<uint32_t>(mHeight), webgpuFormat, device,
                                               &mDepthStencilAttachment));
    }

    return angle::Result::Continue;
}

WindowSurfaceWgpu::WindowSurfaceWgpu(const egl::SurfaceState &surfaceState,
                                     EGLNativeWindowType window)
    : SurfaceWgpu(surfaceState), mNativeWindow(window)
{}

WindowSurfaceWgpu::~WindowSurfaceWgpu() {}

egl::Error WindowSurfaceWgpu::initialize(const egl::Display *display)
{
    return angle::ResultToEGL(initializeImpl(display));
}

void WindowSurfaceWgpu::destroy(const egl::Display *display)
{
    mSurface   = nullptr;
    mColorAttachment.renderTarget.reset();
    mColorAttachment.texture.resetImage();
    mDepthStencilAttachment.renderTarget.reset();
    mDepthStencilAttachment.texture.resetImage();
}

egl::Error WindowSurfaceWgpu::swap(const gl::Context *context)
{
    return angle::ResultToEGL(swapImpl(context));
}

egl::Error WindowSurfaceWgpu::bindTexImage(const gl::Context *context,
                                           gl::Texture *texture,
                                           EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

egl::Error WindowSurfaceWgpu::releaseTexImage(const gl::Context *context, EGLint buffer)
{
    UNIMPLEMENTED();
    return egl::NoError();
}

void WindowSurfaceWgpu::setSwapInterval(const egl::Display *display, EGLint interval)
{
    UNIMPLEMENTED();
}

EGLint WindowSurfaceWgpu::getWidth() const
{
    return mCurrentSurfaceSize.width;
}

EGLint WindowSurfaceWgpu::getHeight() const
{
    return mCurrentSurfaceSize.height;
}

EGLint WindowSurfaceWgpu::getSwapBehavior() const
{
    UNIMPLEMENTED();
    return 0;
}

angle::Result WindowSurfaceWgpu::initializeContents(const gl::Context *context,
                                                    GLenum binding,
                                                    const gl::ImageIndex &imageIndex)
{
    UNIMPLEMENTED();
    return angle::Result::Continue;
}

egl::Error WindowSurfaceWgpu::attachToFramebuffer(const gl::Context *context,
                                                  gl::Framebuffer *framebuffer)
{
    return egl::NoError();
}

egl::Error WindowSurfaceWgpu::detachFromFramebuffer(const gl::Context *context,
                                                    gl::Framebuffer *framebuffer)
{
    return egl::NoError();
}

angle::Result WindowSurfaceWgpu::getAttachmentRenderTarget(
    const gl::Context *context,
    GLenum binding,
    const gl::ImageIndex &imageIndex,
    GLsizei samples,
    FramebufferAttachmentRenderTarget **rtOut)
{
    if (binding == GL_BACK)
    {
        *rtOut = &mColorAttachment.renderTarget;
    }
    else
    {
        ASSERT(binding == GL_DEPTH || binding == GL_STENCIL || binding == GL_DEPTH_STENCIL);
        *rtOut = &mDepthStencilAttachment.renderTarget;
    }

    return angle::Result::Continue;
}

angle::Result WindowSurfaceWgpu::initializeImpl(const egl::Display *display)
{
    DisplayWgpu *displayWgpu = webgpu::GetImpl(display);
    wgpu::Adapter &adapter   = displayWgpu->getAdapter();

    ANGLE_TRY(createWgpuSurface(display, &mSurface));

    gl::Extents size;
    ANGLE_TRY(getCurrentWindowSize(display, &size));

    wgpu::SurfaceCapabilities surfaceCapabilities;
    wgpu::Status getCapabilitiesStatus = mSurface.GetCapabilities(adapter, &surfaceCapabilities);
    if (getCapabilitiesStatus != wgpu::Status::Success)
    {
        ERR() << "wgpu::Surface::GetCapabilities failed: "
              << gl::FmtHex(static_cast<uint32_t>(getCapabilitiesStatus));
        return angle::Result::Stop;
    }

    const egl::Config *config = mState.config;
    ASSERT(config->renderTargetFormat != GL_NONE);
    mSurfaceTextureFormat = &displayWgpu->getFormat(config->renderTargetFormat);
    ASSERT(std::find(surfaceCapabilities.formats,
                     surfaceCapabilities.formats + surfaceCapabilities.formatCount,
                     mSurfaceTextureFormat->getActualWgpuTextureFormat()) !=
           (surfaceCapabilities.formats + surfaceCapabilities.formatCount));

    mSurfaceTextureUsage = wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc |
                           wgpu::TextureUsage::CopyDst;
    ASSERT((surfaceCapabilities.usages & mSurfaceTextureUsage) == mSurfaceTextureUsage);

    // Default to the always supported Fifo present mode. Use Mailbox if it's available.
    mPresentMode = wgpu::PresentMode::Fifo;
    for (size_t i = 0; i < surfaceCapabilities.presentModeCount; i++)
    {
        if (surfaceCapabilities.presentModes[i] == wgpu::PresentMode::Mailbox)
        {
            mPresentMode = wgpu::PresentMode::Mailbox;
        }
    }

    if (config->depthStencilFormat != GL_NONE)
    {
        mDepthStencilFormat = &displayWgpu->getFormat(config->depthStencilFormat);
    }
    else
    {
        mDepthStencilFormat = nullptr;
    }

    ANGLE_TRY(configureSurface(display, size));
    ANGLE_TRY(updateCurrentTexture(display));

    return angle::Result::Continue;
}

angle::Result WindowSurfaceWgpu::swapImpl(const gl::Context *context)
{
    const egl::Display *display = context->getDisplay();
    ContextWgpu *contextWgpu    = webgpu::GetImpl(context);

    ANGLE_TRY(contextWgpu->flush(webgpu::RenderPassClosureReason::EGLSwapBuffers));

    mSurface.Present();

    gl::Extents size;
    ANGLE_TRY(getCurrentWindowSize(display, &size));
    if (size != mCurrentSurfaceSize)
    {
        ANGLE_TRY(configureSurface(display, size));
    }

    ANGLE_TRY(updateCurrentTexture(display));

    return angle::Result::Continue;
}

angle::Result WindowSurfaceWgpu::configureSurface(const egl::Display *display,
                                                  const gl::Extents &size)
{
    DisplayWgpu *displayWgpu = webgpu::GetImpl(display);
    wgpu::Device &device     = displayWgpu->getDevice();

    ASSERT(mSurfaceTextureFormat != nullptr);

    wgpu::SurfaceConfiguration surfaceConfig = {};
    surfaceConfig.device                     = device;
    surfaceConfig.format                     = mSurfaceTextureFormat->getActualWgpuTextureFormat();
    surfaceConfig.usage                      = mSurfaceTextureUsage;
    surfaceConfig.width                      = size.width;
    surfaceConfig.height                     = size.height;
    surfaceConfig.presentMode                = mPresentMode;

    mSurface.Configure(&surfaceConfig);

    if (mDepthStencilFormat)
    {
        ANGLE_TRY(createDepthStencilAttachment(
            static_cast<uint32_t>(size.width), static_cast<uint32_t>(size.height),
            *mDepthStencilFormat, device, &mDepthStencilAttachment));
    }

    mCurrentSurfaceSize = size;
    return angle::Result::Continue;
}

angle::Result WindowSurfaceWgpu::updateCurrentTexture(const egl::Display *display)
{
    wgpu::SurfaceTexture texture;
    mSurface.GetCurrentTexture(&texture);
    if (texture.status != wgpu::SurfaceGetCurrentTextureStatus::SuccessOptimal &&
        texture.status != wgpu::SurfaceGetCurrentTextureStatus::SuccessSuboptimal)
    {
        ERR() << "wgpu::Surface::GetCurrentTexture failed: "
              << gl::FmtHex(static_cast<uint32_t>(texture.status));
        return angle::Result::Stop;
    }

    wgpu::TextureFormat wgpuFormat = texture.texture.GetFormat();
    angle::FormatID angleFormat    = webgpu::GetFormatIDFromWgpuTextureFormat(wgpuFormat);

    ANGLE_TRY(mColorAttachment.texture.initExternal(angleFormat, angleFormat, texture.texture));

    wgpu::TextureView view;
    ANGLE_TRY(mColorAttachment.texture.createTextureView(gl::LevelIndex(0), 0, view));

    mColorAttachment.renderTarget.set(&mColorAttachment.texture, view, webgpu::LevelIndex(0), 0,
                                      wgpuFormat);

    return angle::Result::Continue;
}

}  // namespace rx
