// 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/UtilsGL.h"

#include "dawn/common/Assert.h"
#include "dawn/native/EnumMaskIterator.h"
#include "dawn/native/opengl/OpenGLFunctions.h"

namespace dawn::native::opengl {

    GLuint ToOpenGLCompareFunction(wgpu::CompareFunction compareFunction) {
        switch (compareFunction) {
            case wgpu::CompareFunction::Never:
                return GL_NEVER;
            case wgpu::CompareFunction::Less:
                return GL_LESS;
            case wgpu::CompareFunction::LessEqual:
                return GL_LEQUAL;
            case wgpu::CompareFunction::Greater:
                return GL_GREATER;
            case wgpu::CompareFunction::GreaterEqual:
                return GL_GEQUAL;
            case wgpu::CompareFunction::NotEqual:
                return GL_NOTEQUAL;
            case wgpu::CompareFunction::Equal:
                return GL_EQUAL;
            case wgpu::CompareFunction::Always:
                return GL_ALWAYS;

            case wgpu::CompareFunction::Undefined:
                break;
        }
        UNREACHABLE();
    }

    GLint GetStencilMaskFromStencilFormat(wgpu::TextureFormat depthStencilFormat) {
        switch (depthStencilFormat) {
            case wgpu::TextureFormat::Depth24PlusStencil8:
            case wgpu::TextureFormat::Depth24UnormStencil8:
            case wgpu::TextureFormat::Depth32FloatStencil8:
            case wgpu::TextureFormat::Stencil8:
                return 0xFF;

            default:
                UNREACHABLE();
        }
    }

    void CopyImageSubData(const OpenGLFunctions& gl,
                          Aspect srcAspects,
                          GLuint srcHandle,
                          GLenum srcTarget,
                          GLint srcLevel,
                          const Origin3D& src,
                          GLuint dstHandle,
                          GLenum dstTarget,
                          GLint dstLevel,
                          const Origin3D& dst,
                          const Extent3D& size) {
        if (gl.IsAtLeastGL(4, 3) || gl.IsAtLeastGLES(3, 2)) {
            gl.CopyImageSubData(srcHandle, srcTarget, srcLevel, src.x, src.y, src.z, dstHandle,
                                dstTarget, dstLevel, dst.x, dst.y, dst.z, size.width, size.height,
                                size.depthOrArrayLayers);
            return;
        }

        GLint prevReadFBO = 0, prevDrawFBO = 0;
        gl.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &prevReadFBO);
        gl.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &prevDrawFBO);

        // Generate temporary framebuffers for the blits.
        GLuint readFBO = 0, drawFBO = 0;
        gl.GenFramebuffers(1, &readFBO);
        gl.GenFramebuffers(1, &drawFBO);
        gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFBO);

        // Reset state that may affect glBlitFramebuffer().
        gl.Disable(GL_SCISSOR_TEST);
        GLenum blitMask = 0;
        if (srcAspects & Aspect::Color) {
            blitMask |= GL_COLOR_BUFFER_BIT;
        }
        if (srcAspects & Aspect::Depth) {
            blitMask |= GL_DEPTH_BUFFER_BIT;
        }
        if (srcAspects & Aspect::Stencil) {
            blitMask |= GL_STENCIL_BUFFER_BIT;
        }

        // Iterate over all layers, doing a single blit for each.
        for (uint32_t layer = 0; layer < size.depthOrArrayLayers; ++layer) {
            // Set attachments for all aspects.
            for (Aspect aspect : IterateEnumMask(srcAspects)) {
                GLenum glAttachment;
                switch (aspect) {
                    case Aspect::Color:
                        glAttachment = GL_COLOR_ATTACHMENT0;
                        break;
                    case Aspect::Depth:
                        glAttachment = GL_DEPTH_ATTACHMENT;
                        break;
                    case Aspect::Stencil:
                        glAttachment = GL_STENCIL_ATTACHMENT;
                        break;
                    case Aspect::CombinedDepthStencil:
                    case Aspect::None:
                    case Aspect::Plane0:
                    case Aspect::Plane1:
                        UNREACHABLE();
                }
                if (srcTarget == GL_TEXTURE_2D) {
                    gl.FramebufferTexture2D(GL_READ_FRAMEBUFFER, glAttachment, srcTarget, srcHandle,
                                            srcLevel);
                } else {
                    gl.FramebufferTextureLayer(GL_READ_FRAMEBUFFER, glAttachment, srcHandle,
                                               srcLevel, src.z + layer);
                }
                if (dstTarget == GL_TEXTURE_2D) {
                    gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, dstTarget, dstHandle,
                                            dstLevel);
                } else if (dstTarget == GL_TEXTURE_CUBE_MAP) {
                    GLenum target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
                    gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, glAttachment, target, dstHandle,
                                            dstLevel);
                } else {
                    gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, glAttachment, dstHandle,
                                               dstLevel, dst.z + layer);
                }
            }
            gl.BlitFramebuffer(src.x, src.y, src.x + size.width, src.y + size.height, dst.x, dst.y,
                               dst.x + size.width, dst.y + size.height, blitMask, GL_NEAREST);
        }
        gl.Enable(GL_SCISSOR_TEST);
        gl.DeleteFramebuffers(1, &readFBO);
        gl.DeleteFramebuffers(1, &drawFBO);
        gl.BindFramebuffer(GL_READ_FRAMEBUFFER, prevReadFBO);
        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, prevDrawFBO);
    }

}  // namespace dawn::native::opengl
