// 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->GetGL();
    gl.DeleteTextures(1, &mBackTexture);
    gl.DeleteFramebuffers(1, &mBackFBO);
}

void NativeSwapChainImpl::Init(DawnWSIContextGL* /*context*/) {
    const OpenGLFunctions& gl = mDevice->GetGL();
    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->GetGL();
    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->GetGL();
    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
