// Copyright 2017 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/TextureGL.h"

#include "common/Assert.h"
#include "common/Constants.h"
#include "common/Math.h"
#include "dawn_native/EnumMaskIterator.h"
#include "dawn_native/opengl/BufferGL.h"
#include "dawn_native/opengl/CommandBufferGL.h"
#include "dawn_native/opengl/DeviceGL.h"
#include "dawn_native/opengl/UtilsGL.h"

namespace dawn::native::opengl {

    namespace {

        GLenum TargetForTexture(const TextureDescriptor* descriptor) {
            switch (descriptor->dimension) {
                case wgpu::TextureDimension::e2D:
                    if (descriptor->size.depthOrArrayLayers > 1) {
                        ASSERT(descriptor->sampleCount == 1);
                        return GL_TEXTURE_2D_ARRAY;
                    } else {
                        if (descriptor->sampleCount > 1) {
                            return GL_TEXTURE_2D_MULTISAMPLE;
                        } else {
                            return GL_TEXTURE_2D;
                        }
                    }
                case wgpu::TextureDimension::e3D:
                    return GL_TEXTURE_3D;

                case wgpu::TextureDimension::e1D:
                    break;
            }
            UNREACHABLE();
        }

        GLenum TargetForTextureViewDimension(wgpu::TextureViewDimension dimension,
                                             uint32_t arrayLayerCount,
                                             uint32_t sampleCount) {
            switch (dimension) {
                case wgpu::TextureViewDimension::e2D:
                    return (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
                case wgpu::TextureViewDimension::e2DArray:
                    if (arrayLayerCount == 1) {
                        return (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
                    }
                    ASSERT(sampleCount == 1);
                    return GL_TEXTURE_2D_ARRAY;
                case wgpu::TextureViewDimension::Cube:
                    return GL_TEXTURE_CUBE_MAP;
                case wgpu::TextureViewDimension::CubeArray:
                    return GL_TEXTURE_CUBE_MAP_ARRAY;
                case wgpu::TextureViewDimension::e3D:
                    return GL_TEXTURE_3D;

                case wgpu::TextureViewDimension::e1D:
                case wgpu::TextureViewDimension::Undefined:
                    break;
            }
            UNREACHABLE();
        }

        GLuint GenTexture(const OpenGLFunctions& gl) {
            GLuint handle = 0;
            gl.GenTextures(1, &handle);
            return handle;
        }

        bool UsageNeedsTextureView(wgpu::TextureUsage usage) {
            constexpr wgpu::TextureUsage kUsageNeedingTextureView =
                wgpu::TextureUsage::StorageBinding | wgpu::TextureUsage::TextureBinding;
            return usage & kUsageNeedingTextureView;
        }

        bool RequiresCreatingNewTextureView(const TextureBase* texture,
                                            const TextureViewDescriptor* textureViewDescriptor) {
            if (texture->GetFormat().format != textureViewDescriptor->format) {
                return true;
            }

            if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount) {
                return true;
            }

            if (texture->GetNumMipLevels() != textureViewDescriptor->mipLevelCount) {
                return true;
            }

            if (ToBackend(texture)->GetGLFormat().format == GL_DEPTH_STENCIL &&
                (texture->GetUsage() & wgpu::TextureUsage::TextureBinding) != 0 &&
                textureViewDescriptor->aspect == wgpu::TextureAspect::StencilOnly) {
                // We need a separate view for one of the depth or stencil planes
                // because each glTextureView needs it's own handle to set
                // GL_DEPTH_STENCIL_TEXTURE_MODE. Choose the stencil aspect for the
                // extra handle since it is likely sampled less often.
                return true;
            }

            switch (textureViewDescriptor->dimension) {
                case wgpu::TextureViewDimension::Cube:
                case wgpu::TextureViewDimension::CubeArray:
                    return true;
                default:
                    break;
            }

            return false;
        }

    }  // namespace

    // Texture

    Texture::Texture(Device* device, const TextureDescriptor* descriptor)
        : Texture(device, descriptor, GenTexture(device->gl), TextureState::OwnedInternal) {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;

        uint32_t width = GetWidth();
        uint32_t height = GetHeight();
        uint32_t levels = GetNumMipLevels();
        uint32_t arrayLayers = GetArrayLayers();
        uint32_t sampleCount = GetSampleCount();

        const GLFormat& glFormat = GetGLFormat();

        gl.BindTexture(mTarget, mHandle);

        // glTextureView() requires the value of GL_TEXTURE_IMMUTABLE_FORMAT for origtexture to be
        // GL_TRUE, so the storage of the texture must be allocated with glTexStorage*D.
        // https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTextureView.xhtml
        switch (GetDimension()) {
            case wgpu::TextureDimension::e2D:
                if (arrayLayers > 1) {
                    ASSERT(!IsMultisampledTexture());
                    gl.TexStorage3D(mTarget, levels, glFormat.internalFormat, width, height,
                                    arrayLayers);
                } else {
                    if (IsMultisampledTexture()) {
                        gl.TexStorage2DMultisample(mTarget, sampleCount, glFormat.internalFormat,
                                                   width, height, true);
                    } else {
                        gl.TexStorage2D(mTarget, levels, glFormat.internalFormat, width, height);
                    }
                }
                break;
            case wgpu::TextureDimension::e3D:
                ASSERT(!IsMultisampledTexture());
                ASSERT(arrayLayers == 1);
                gl.TexStorage3D(mTarget, levels, glFormat.internalFormat, width, height,
                                GetDepth());
                break;

            case wgpu::TextureDimension::e1D:
                UNREACHABLE();
        }

        // The texture is not complete if it uses mipmapping and not all levels up to
        // MAX_LEVEL have been defined.
        gl.TexParameteri(mTarget, GL_TEXTURE_MAX_LEVEL, levels - 1);

        if (GetDevice()->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
            GetDevice()->ConsumedError(
                ClearTexture(GetAllSubresources(), TextureBase::ClearValue::NonZero));
        }
    }

    Texture::Texture(Device* device,
                     const TextureDescriptor* descriptor,
                     GLuint handle,
                     TextureState state)
        : TextureBase(device, descriptor, state), mHandle(handle) {
        mTarget = TargetForTexture(descriptor);
    }

    Texture::~Texture() {
    }

    void Texture::DestroyImpl() {
        TextureBase::DestroyImpl();
        if (GetTextureState() == TextureState::OwnedInternal) {
            ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
            mHandle = 0;
        }
    }

    GLuint Texture::GetHandle() const {
        return mHandle;
    }

    GLenum Texture::GetGLTarget() const {
        return mTarget;
    }

    const GLFormat& Texture::GetGLFormat() const {
        return ToBackend(GetDevice())->GetGLFormat(GetFormat());
    }

    MaybeError Texture::ClearTexture(const SubresourceRange& range,
                                     TextureBase::ClearValue clearValue) {
        // TODO(crbug.com/dawn/850): initialize the textures with compressed formats.
        if (GetFormat().isCompressed) {
            return {};
        }

        Device* device = ToBackend(GetDevice());
        const OpenGLFunctions& gl = device->gl;

        uint8_t clearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0 : 1;
        float fClearColor = (clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f;

        if (GetFormat().isRenderable) {
            if ((range.aspects & (Aspect::Depth | Aspect::Stencil)) != 0) {
                GLfloat depth = fClearColor;
                GLint stencil = clearColor;
                if (range.aspects & Aspect::Depth) {
                    gl.DepthMask(GL_TRUE);
                }
                if (range.aspects & Aspect::Stencil) {
                    gl.StencilMask(GetStencilMaskFromStencilFormat(GetFormat().format));
                }

                auto DoClear = [&](Aspect aspects) {
                    if (aspects == (Aspect::Depth | Aspect::Stencil)) {
                        gl.ClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
                    } else if (aspects == Aspect::Depth) {
                        gl.ClearBufferfv(GL_DEPTH, 0, &depth);
                    } else if (aspects == Aspect::Stencil) {
                        gl.ClearBufferiv(GL_STENCIL, 0, &stencil);
                    } else {
                        UNREACHABLE();
                    }
                };

                GLuint framebuffer = 0;
                gl.GenFramebuffers(1, &framebuffer);
                gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);

                GLenum attachment;
                if (range.aspects == (Aspect::Depth | Aspect::Stencil)) {
                    attachment = GL_DEPTH_STENCIL_ATTACHMENT;
                } else if (range.aspects == Aspect::Depth) {
                    attachment = GL_DEPTH_ATTACHMENT;
                } else if (range.aspects == Aspect::Stencil) {
                    attachment = GL_STENCIL_ATTACHMENT;
                } else {
                    UNREACHABLE();
                }

                for (uint32_t level = range.baseMipLevel;
                     level < range.baseMipLevel + range.levelCount; ++level) {
                    switch (GetDimension()) {
                        case wgpu::TextureDimension::e2D:
                            if (GetArrayLayers() == 1) {
                                Aspect aspectsToClear = Aspect::None;
                                for (Aspect aspect : IterateEnumMask(range.aspects)) {
                                    if (clearValue == TextureBase::ClearValue::Zero &&
                                        IsSubresourceContentInitialized(
                                            SubresourceRange::SingleMipAndLayer(level, 0,
                                                                                aspect))) {
                                        // Skip lazy clears if already initialized.
                                        continue;
                                    }
                                    aspectsToClear |= aspect;
                                }

                                if (aspectsToClear == Aspect::None) {
                                    continue;
                                }

                                gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment,
                                                        GetGLTarget(), GetHandle(),
                                                        static_cast<GLint>(level));
                                DoClear(aspectsToClear);
                            } else {
                                for (uint32_t layer = range.baseArrayLayer;
                                     layer < range.baseArrayLayer + range.layerCount; ++layer) {
                                    Aspect aspectsToClear = Aspect::None;
                                    for (Aspect aspect : IterateEnumMask(range.aspects)) {
                                        if (clearValue == TextureBase::ClearValue::Zero &&
                                            IsSubresourceContentInitialized(
                                                SubresourceRange::SingleMipAndLayer(level, layer,
                                                                                    aspect))) {
                                            // Skip lazy clears if already initialized.
                                            continue;
                                        }
                                        aspectsToClear |= aspect;
                                    }

                                    if (aspectsToClear == Aspect::None) {
                                        continue;
                                    }

                                    gl.FramebufferTextureLayer(
                                        GL_DRAW_FRAMEBUFFER, attachment, GetHandle(),
                                        static_cast<GLint>(level), static_cast<GLint>(layer));
                                    DoClear(aspectsToClear);
                                }
                            }
                            break;

                        case wgpu::TextureDimension::e1D:
                        case wgpu::TextureDimension::e3D:
                            UNREACHABLE();
                    }
                }

                gl.DeleteFramebuffers(1, &framebuffer);
            } else {
                ASSERT(range.aspects == Aspect::Color);

                // For gl.ClearBufferiv/uiv calls
                constexpr std::array<GLuint, 4> kClearColorDataUint0 = {0u, 0u, 0u, 0u};
                constexpr std::array<GLuint, 4> kClearColorDataUint1 = {1u, 1u, 1u, 1u};
                std::array<GLuint, 4> clearColorData;
                clearColorData.fill((clearValue == TextureBase::ClearValue::Zero) ? 0u : 1u);

                // For gl.ClearBufferfv calls
                constexpr std::array<GLfloat, 4> kClearColorDataFloat0 = {0.f, 0.f, 0.f, 0.f};
                constexpr std::array<GLfloat, 4> kClearColorDataFloat1 = {1.f, 1.f, 1.f, 1.f};
                std::array<GLfloat, 4> fClearColorData;
                fClearColorData.fill((clearValue == TextureBase::ClearValue::Zero) ? 0.f : 1.f);

                static constexpr uint32_t MAX_TEXEL_SIZE = 16;
                const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block;
                ASSERT(blockInfo.byteSize <= MAX_TEXEL_SIZE);

                // For gl.ClearTexSubImage calls
                constexpr std::array<GLbyte, MAX_TEXEL_SIZE> kClearColorDataBytes0 = {
                    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
                constexpr std::array<GLbyte, MAX_TEXEL_SIZE> kClearColorDataBytes255 = {
                    -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1};

                wgpu::TextureComponentType baseType =
                    GetFormat().GetAspectInfo(Aspect::Color).baseType;

                const GLFormat& glFormat = GetGLFormat();
                for (uint32_t level = range.baseMipLevel;
                     level < range.baseMipLevel + range.levelCount; ++level) {
                    Extent3D mipSize = GetMipLevelPhysicalSize(level);
                    for (uint32_t layer = range.baseArrayLayer;
                         layer < range.baseArrayLayer + range.layerCount; ++layer) {
                        if (clearValue == TextureBase::ClearValue::Zero &&
                            IsSubresourceContentInitialized(
                                SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
                            // Skip lazy clears if already initialized.
                            continue;
                        }
                        if (gl.IsAtLeastGL(4, 4)) {
                            gl.ClearTexSubImage(mHandle, static_cast<GLint>(level), 0, 0,
                                                static_cast<GLint>(layer), mipSize.width,
                                                mipSize.height, mipSize.depthOrArrayLayers,
                                                glFormat.format, glFormat.type,
                                                clearValue == TextureBase::ClearValue::Zero
                                                    ? kClearColorDataBytes0.data()
                                                    : kClearColorDataBytes255.data());
                            continue;
                        }

                        GLuint framebuffer = 0;
                        gl.GenFramebuffers(1, &framebuffer);
                        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, framebuffer);

                        GLenum attachment = GL_COLOR_ATTACHMENT0;
                        gl.DrawBuffers(1, &attachment);

                        gl.Disable(GL_SCISSOR_TEST);
                        gl.ColorMask(true, true, true, true);

                        auto DoClear = [&]() {
                            switch (baseType) {
                                case wgpu::TextureComponentType::Float: {
                                    gl.ClearBufferfv(GL_COLOR, 0,
                                                     clearValue == TextureBase::ClearValue::Zero
                                                         ? kClearColorDataFloat0.data()
                                                         : kClearColorDataFloat1.data());
                                    break;
                                }
                                case wgpu::TextureComponentType::Uint: {
                                    gl.ClearBufferuiv(GL_COLOR, 0,
                                                      clearValue == TextureBase::ClearValue::Zero
                                                          ? kClearColorDataUint0.data()
                                                          : kClearColorDataUint1.data());
                                    break;
                                }
                                case wgpu::TextureComponentType::Sint: {
                                    gl.ClearBufferiv(GL_COLOR, 0,
                                                     reinterpret_cast<const GLint*>(
                                                         clearValue == TextureBase::ClearValue::Zero
                                                             ? kClearColorDataUint0.data()
                                                             : kClearColorDataUint1.data()));
                                    break;
                                }

                                case wgpu::TextureComponentType::DepthComparison:
                                    UNREACHABLE();
                            }
                        };

                        if (GetArrayLayers() == 1) {
                            switch (GetDimension()) {
                                case wgpu::TextureDimension::e1D:
                                    UNREACHABLE();
                                case wgpu::TextureDimension::e2D:
                                    gl.FramebufferTexture2D(GL_DRAW_FRAMEBUFFER, attachment,
                                                            GetGLTarget(), GetHandle(), level);
                                    DoClear();
                                    break;
                                case wgpu::TextureDimension::e3D:
                                    uint32_t depth =
                                        GetMipLevelVirtualSize(level).depthOrArrayLayers;
                                    for (GLint z = 0; z < static_cast<GLint>(depth); ++z) {
                                        gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment,
                                                                   GetHandle(), level, z);
                                        DoClear();
                                    }
                                    break;
                            }

                        } else {
                            ASSERT(GetDimension() == wgpu::TextureDimension::e2D);
                            gl.FramebufferTextureLayer(GL_DRAW_FRAMEBUFFER, attachment, GetHandle(),
                                                       level, layer);
                            DoClear();
                        }

                        gl.Enable(GL_SCISSOR_TEST);
                        gl.DeleteFramebuffers(1, &framebuffer);
                        gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
                    }
                }
            }
        } else {
            ASSERT(range.aspects == Aspect::Color);

            // create temp buffer with clear color to copy to the texture image
            const TexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(Aspect::Color).block;
            ASSERT(kTextureBytesPerRowAlignment % blockInfo.byteSize == 0);

            Extent3D largestMipSize = GetMipLevelPhysicalSize(range.baseMipLevel);
            uint32_t bytesPerRow =
                Align((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 4);

            // Make sure that we are not rounding
            ASSERT(bytesPerRow % blockInfo.byteSize == 0);
            ASSERT(largestMipSize.height % blockInfo.height == 0);

            uint64_t bufferSize64 = static_cast<uint64_t>(bytesPerRow) *
                                    (largestMipSize.height / blockInfo.height) *
                                    largestMipSize.depthOrArrayLayers;
            if (bufferSize64 > std::numeric_limits<size_t>::max()) {
                return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
            }
            size_t bufferSize = static_cast<size_t>(bufferSize64);

            dawn::native::BufferDescriptor descriptor = {};
            descriptor.mappedAtCreation = true;
            descriptor.usage = wgpu::BufferUsage::CopySrc;
            descriptor.size = bufferSize;

            // We don't count the lazy clear of srcBuffer because it is an internal buffer.
            // TODO(natlee@microsoft.com): use Dynamic Uploader here for temp buffer
            Ref<Buffer> srcBuffer;
            DAWN_TRY_ASSIGN(srcBuffer, Buffer::CreateInternalBuffer(device, &descriptor, false));

            // Fill the buffer with clear color
            memset(srcBuffer->GetMappedRange(0, bufferSize), clearColor, bufferSize);
            srcBuffer->Unmap();

            gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, srcBuffer->GetHandle());
            for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
                 ++level) {
                TextureCopy textureCopy;
                textureCopy.texture = this;
                textureCopy.mipLevel = level;
                textureCopy.origin = {};
                textureCopy.aspect = Aspect::Color;

                TextureDataLayout dataLayout;
                dataLayout.offset = 0;
                dataLayout.bytesPerRow = bytesPerRow;
                dataLayout.rowsPerImage = largestMipSize.height;

                Extent3D mipSize = GetMipLevelPhysicalSize(level);

                for (uint32_t layer = range.baseArrayLayer;
                     layer < range.baseArrayLayer + range.layerCount; ++layer) {
                    if (clearValue == TextureBase::ClearValue::Zero &&
                        IsSubresourceContentInitialized(
                            SubresourceRange::SingleMipAndLayer(level, layer, Aspect::Color))) {
                        // Skip lazy clears if already initialized.
                        continue;
                    }

                    textureCopy.origin.z = layer;
                    DoTexSubImage(ToBackend(GetDevice())->gl, textureCopy, 0, dataLayout, mipSize);
                }
            }
            gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
        }
        if (clearValue == TextureBase::ClearValue::Zero) {
            SetIsSubresourceContentInitialized(true, range);
            device->IncrementLazyClearCountForTesting();
        }
        return {};
    }

    void Texture::EnsureSubresourceContentInitialized(const SubresourceRange& range) {
        if (!GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
            return;
        }
        if (!IsSubresourceContentInitialized(range)) {
            GetDevice()->ConsumedError(ClearTexture(range, TextureBase::ClearValue::Zero));
        }
    }

    // TextureView

    TextureView::TextureView(TextureBase* texture, const TextureViewDescriptor* descriptor)
        : TextureViewBase(texture, descriptor), mOwnsHandle(false) {
        mTarget = TargetForTextureViewDimension(descriptor->dimension, descriptor->arrayLayerCount,
                                                texture->GetSampleCount());

        // Texture could be destroyed by the time we make a view.
        if (GetTexture()->GetTextureState() == Texture::TextureState::Destroyed) {
            return;
        }

        if (!UsageNeedsTextureView(texture->GetUsage())) {
            mHandle = 0;
        } else if (!RequiresCreatingNewTextureView(texture, descriptor)) {
            mHandle = ToBackend(texture)->GetHandle();
        } else {
            // glTextureView() is supported on OpenGL version >= 4.3
            // TODO(crbug.com/dawn/593): support texture view on OpenGL version <= 4.2 and ES
            const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
            mHandle = GenTexture(gl);
            const Texture* textureGL = ToBackend(texture);
            const GLFormat& glFormat = ToBackend(GetDevice())->GetGLFormat(GetFormat());
            gl.TextureView(mHandle, mTarget, textureGL->GetHandle(), glFormat.internalFormat,
                           descriptor->baseMipLevel, descriptor->mipLevelCount,
                           descriptor->baseArrayLayer, descriptor->arrayLayerCount);
            mOwnsHandle = true;
        }
    }

    TextureView::~TextureView() {
    }

    void TextureView::DestroyImpl() {
        TextureViewBase::DestroyImpl();
        if (mOwnsHandle) {
            ToBackend(GetDevice())->gl.DeleteTextures(1, &mHandle);
        }
    }

    GLuint TextureView::GetHandle() const {
        ASSERT(mHandle != 0);
        return mHandle;
    }

    GLenum TextureView::GetGLTarget() const {
        return mTarget;
    }

}  // namespace dawn::native::opengl
