// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "dawn/native/opengl/TextureGL.h"

#include <limits>
#include <utility>

#include "dawn/common/Assert.h"
#include "dawn/common/Constants.h"
#include "dawn/common/Math.h"
#include "dawn/native/ChainUtils.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 TargetForTextureViewDimension(wgpu::TextureViewDimension dimension, uint32_t sampleCount) {
    switch (dimension) {
        case wgpu::TextureViewDimension::e1D:
        case wgpu::TextureViewDimension::e2D:
            return (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D;
        case wgpu::TextureViewDimension::e2DArray:
            if (sampleCount > 1) {
                return GL_TEXTURE_2D_MULTISAMPLE;
            }
            DAWN_ASSERT(sampleCount == 1);
            return GL_TEXTURE_2D_ARRAY;
        case wgpu::TextureViewDimension::Cube:
            DAWN_ASSERT(sampleCount == 1);
            return GL_TEXTURE_CUBE_MAP;
        case wgpu::TextureViewDimension::CubeArray:
            DAWN_ASSERT(sampleCount == 1);
            return GL_TEXTURE_CUBE_MAP_ARRAY;
        case wgpu::TextureViewDimension::e3D:
            DAWN_ASSERT(sampleCount == 1);
            return GL_TEXTURE_3D;

        case wgpu::TextureViewDimension::Undefined:
        default:
            DAWN_UNREACHABLE();
    }
}

bool RequiresCreatingNewTextureView(
    const TextureBase* texture,
    const UnpackedPtr<TextureViewDescriptor>& textureViewDescriptor) {
    // Compatibility mode validation should prevent the need for creation of
    // new texture views.
    if (ToBackend(texture->GetDevice())->IsCompatibilityMode()) {
        return false;
    }

    constexpr wgpu::TextureUsage kShaderUsageNeedsView =
        wgpu::TextureUsage::StorageBinding | wgpu::TextureUsage::TextureBinding;
    constexpr wgpu::TextureUsage kUsageNeedsView =
        kShaderUsageNeedsView | wgpu::TextureUsage::RenderAttachment;
    if ((texture->GetInternalUsage() & kUsageNeedsView) == 0) {
        return false;
    }

    if (texture->GetFormat().format != textureViewDescriptor->format &&
        !texture->GetFormat().HasDepthOrStencil()) {
        // Color format reinterpretation required. Note: Depth/stencil formats don't support
        // reinterpretation.
        return true;
    }

    // Reinterpretation not required. Now, we only need a new view if the view dimension or
    // set of subresources for the shader is different from the base texture.
    if ((texture->GetInternalUsage() & kShaderUsageNeedsView) == 0) {
        return false;
    }

    if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount ||
        (texture->GetArrayLayers() == 1 && texture->GetDimension() == wgpu::TextureDimension::e2D &&
         textureViewDescriptor->dimension == wgpu::TextureViewDimension::e2DArray)) {
        // If the view has a different number of array layers, we need a new view.
        // And, if the original texture is a 2D texture with one array layer, we need a new
        // view to view it as a 2D array texture.
        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;
    }

    return false;
}

void AllocateTexture(const OpenGLFunctions& gl,
                     GLenum target,
                     GLsizei samples,
                     GLuint levels,
                     GLenum internalFormat,
                     const Extent3D& size) {
    // 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 (target) {
        case GL_TEXTURE_2D_ARRAY:
        case GL_TEXTURE_CUBE_MAP_ARRAY:
        case GL_TEXTURE_3D:
            gl.TexStorage3D(target, levels, internalFormat, size.width, size.height,
                            size.depthOrArrayLayers);
            break;
        case GL_TEXTURE_2D:
        case GL_TEXTURE_CUBE_MAP:
            gl.TexStorage2D(target, levels, internalFormat, size.width, size.height);
            break;
        case GL_TEXTURE_2D_MULTISAMPLE:
            gl.TexStorage2DMultisample(target, samples, internalFormat, size.width, size.height,
                                       true);
            break;
        default:
            DAWN_UNREACHABLE();
    }
}

}  // namespace

// Texture

// static
ResultOrError<Ref<Texture>> Texture::Create(Device* device,
                                            const UnpackedPtr<TextureDescriptor>& descriptor) {
    Ref<Texture> texture = AcquireRef(new Texture(device, descriptor));
    if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
        DAWN_TRY(
            texture->ClearTexture(texture->GetAllSubresources(), TextureBase::ClearValue::NonZero));
    }
    return std::move(texture);
}

Texture::Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor)
    : Texture(device, descriptor, 0) {
    const OpenGLFunctions& gl = device->GetGL();

    gl.GenTextures(1, &mHandle);
    mOwnsHandle = true;
    uint32_t levels = GetNumMipLevels();

    const GLFormat& glFormat = GetGLFormat();

    gl.BindTexture(mTarget, mHandle);

    AllocateTexture(gl, mTarget, GetSampleCount(), levels, glFormat.internalFormat, GetBaseSize());

    // 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);
}

Texture::Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor, GLuint handle)
    : TextureBase(device, descriptor), mHandle(handle) {
    mTarget = TargetForTextureViewDimension(GetCompatibilityTextureBindingViewDimension(),
                                            descriptor->sampleCount);
}

Texture::~Texture() {}

void Texture::DestroyImpl() {
    TextureBase::DestroyImpl();
    if (mOwnsHandle) {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();
        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) {
    Device* device = ToBackend(GetDevice());
    const OpenGLFunctions& gl = device->GetGL();

    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)) {
            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 {
                    DAWN_UNREACHABLE();
                }
            };

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

            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 {
                DAWN_UNREACHABLE();
            }

            for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
                 ++level) {
                switch (GetDimension()) {
                    case wgpu::TextureDimension::e1D:
                    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::e3D:
                    case wgpu::TextureDimension::Undefined:
                        DAWN_UNREACHABLE();
                }
            }

            gl.Enable(GL_SCISSOR_TEST);
            gl.DeleteFramebuffers(1, &framebuffer);
        } else {
            DAWN_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;
            DAWN_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};

            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 = GetMipLevelSingleSubresourcePhysicalSize(level, Aspect::Color);
                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 TextureComponentType::Float: {
                                gl.ClearBufferfv(GL_COLOR, 0,
                                                 clearValue == TextureBase::ClearValue::Zero
                                                     ? kClearColorDataFloat0.data()
                                                     : kClearColorDataFloat1.data());
                                break;
                            }
                            case TextureComponentType::Uint: {
                                gl.ClearBufferuiv(GL_COLOR, 0,
                                                  clearValue == TextureBase::ClearValue::Zero
                                                      ? kClearColorDataUint0.data()
                                                      : kClearColorDataUint1.data());
                                break;
                            }
                            case TextureComponentType::Sint: {
                                gl.ClearBufferiv(GL_COLOR, 0,
                                                 reinterpret_cast<const GLint*>(
                                                     clearValue == TextureBase::ClearValue::Zero
                                                         ? kClearColorDataUint0.data()
                                                         : kClearColorDataUint1.data()));
                                break;
                            }
                        }
                    };

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

                    } else {
                        DAWN_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 {
        DAWN_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;
        DAWN_ASSERT(kTextureBytesPerRowAlignment % blockInfo.byteSize == 0);

        Extent3D largestMipSize =
            GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, Aspect::Color);
        uint32_t bytesPerRow =
            Align((largestMipSize.width / blockInfo.width) * blockInfo.byteSize, 4);

        // Make sure that we are not rounding
        DAWN_ASSERT(bytesPerRow % blockInfo.byteSize == 0);
        DAWN_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);
        DAWN_TRY(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 = GetMipLevelSingleSubresourcePhysicalSize(level, Aspect::Color);

            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(gl, textureCopy, 0, dataLayout, mipSize);
            }
        }
        gl.BindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
    }
    if (clearValue == TextureBase::ClearValue::Zero) {
        SetIsSubresourceContentInitialized(true, range);
        device->IncrementLazyClearCountForTesting();
    }
    return {};
}

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

// TextureView

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

    // Texture could be destroyed by the time we make a view.
    if (GetTexture()->IsDestroyed()) {
        return;
    }

    if (!RequiresCreatingNewTextureView(texture, descriptor)) {
        mHandle = ToBackend(texture)->GetHandle();
    } else {
        const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();
        if (gl.IsAtLeastGL(4, 3)) {
            gl.GenTextures(1, &mHandle);
            const Texture* textureGL = ToBackend(texture);
            gl.TextureView(mHandle, mTarget, textureGL->GetHandle(), GetInternalFormat(),
                           descriptor->baseMipLevel, descriptor->mipLevelCount,
                           descriptor->baseArrayLayer, descriptor->arrayLayerCount);
            mOwnsHandle = true;
        } else {
            mHandle = 0;
        }
    }
}

TextureView::~TextureView() {}

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

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

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

void TextureView::BindToFramebuffer(GLenum target, GLenum attachment, GLuint depthSlice) {
    DAWN_ASSERT(depthSlice <
                static_cast<GLuint>(GetSingleSubresourceVirtualSize().depthOrArrayLayers));

    const OpenGLFunctions& gl = ToBackend(GetDevice())->GetGL();

    // Use the base texture where possible to minimize the amount of copying required on GLES.
    bool useOwnView = GetFormat().format != GetTexture()->GetFormat().format &&
                      !GetTexture()->GetFormat().HasDepthOrStencil();

    GLuint handle, textarget, mipLevel, arrayLayer;
    if (useOwnView) {
        // Use our own texture handle and target which points to a subset of the texture's
        // subresources.
        handle = GetHandle();
        textarget = GetGLTarget();
        mipLevel = 0;
        arrayLayer = 0;
    } else {
        // Use the texture's handle and target, with the view's base mip level and base array

        handle = ToBackend(GetTexture())->GetHandle();
        textarget = ToBackend(GetTexture())->GetGLTarget();
        mipLevel = GetBaseMipLevel();
        // We have validated that the depthSlice in render pass's colorAttachments must be undefined
        // for 2d RTVs, which value is set to 0. For 3d RTVs, the baseArrayLayer must be 0. So here
        // we can simply use baseArrayLayer + depthSlice to specify the slice in RTVs without
        // checking the view's dimension.
        arrayLayer = GetBaseArrayLayer() + depthSlice;
    }

    DAWN_ASSERT(handle != 0);

    switch (textarget) {
        case GL_TEXTURE_2D_ARRAY:
        case GL_TEXTURE_CUBE_MAP_ARRAY:
        case GL_TEXTURE_3D:
            gl.FramebufferTextureLayer(target, attachment, handle, mipLevel, arrayLayer);
            break;
        case GL_TEXTURE_CUBE_MAP: {
            GLenum cubeTexTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + arrayLayer;
            gl.FramebufferTexture2D(target, attachment, cubeTexTarget, handle, mipLevel);
            break;
        }
        default:
            gl.FramebufferTexture2D(target, attachment, textarget, handle, mipLevel);
            break;
    }
}

GLenum TextureView::GetInternalFormat() const {
    // Depth/stencil don't support reinterpretation, and the aspect is specified at
    // bind time. In that case, we use the base texture format.
    const Format& format =
        GetFormat().HasDepthOrStencil() ? GetTexture()->GetFormat() : GetFormat();
    const GLFormat& glFormat = ToBackend(GetDevice())->GetGLFormat(format);
    return glFormat.internalFormat;
}

}  // namespace dawn::native::opengl
