// Copyright 2019 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn_native/opengl/NativeSwapChainImplGL.h"

#include "dawn_native/opengl/DeviceGL.h"

namespace dawn_native::opengl {

    NativeSwapChainImpl::NativeSwapChainImpl(Device* device,
                                             PresentCallback present,
                                             void* presentUserdata)
        : mPresentCallback(present), mPresentUserdata(presentUserdata), mDevice(device) {
    }

    NativeSwapChainImpl::~NativeSwapChainImpl() {
        const OpenGLFunctions& gl = mDevice->gl;
        gl.DeleteTextures(1, &mBackTexture);
        gl.DeleteFramebuffers(1, &mBackFBO);
    }

    void NativeSwapChainImpl::Init(DawnWSIContextGL* /*context*/) {
        const OpenGLFunctions& gl = mDevice->gl;
        gl.GenTextures(1, &mBackTexture);
        gl.BindTexture(GL_TEXTURE_2D, mBackTexture);
        gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

        gl.GenFramebuffers(1, &mBackFBO);
        gl.BindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
        gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                                mBackTexture, 0);
    }

    DawnSwapChainError NativeSwapChainImpl::Configure(WGPUTextureFormat format,
                                                      WGPUTextureUsage usage,
                                                      uint32_t width,
                                                      uint32_t height) {
        if (format != WGPUTextureFormat_RGBA8Unorm) {
            return "unsupported format";
        }
        ASSERT(width > 0);
        ASSERT(height > 0);
        mWidth = width;
        mHeight = height;

        const OpenGLFunctions& gl = mDevice->gl;
        gl.BindTexture(GL_TEXTURE_2D, mBackTexture);
        // Reallocate the texture
        gl.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
                      nullptr);

        return DAWN_SWAP_CHAIN_NO_ERROR;
    }

    DawnSwapChainError NativeSwapChainImpl::GetNextTexture(DawnSwapChainNextTexture* nextTexture) {
        nextTexture->texture.u32 = mBackTexture;
        return DAWN_SWAP_CHAIN_NO_ERROR;
    }

    DawnSwapChainError NativeSwapChainImpl::Present() {
        const OpenGLFunctions& gl = mDevice->gl;
        gl.BindFramebuffer(GL_READ_FRAMEBUFFER, mBackFBO);
        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
        gl.Scissor(0, 0, mWidth, mHeight);
        gl.BlitFramebuffer(0, 0, mWidth, mHeight, 0, mHeight, mWidth, 0, GL_COLOR_BUFFER_BIT,
                           GL_NEAREST);

        mPresentCallback(mPresentUserdata);

        return DAWN_SWAP_CHAIN_NO_ERROR;
    }

    wgpu::TextureFormat NativeSwapChainImpl::GetPreferredFormat() const {
        return wgpu::TextureFormat::RGBA8Unorm;
    }

}  // namespace dawn_native::opengl
