// 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 <limits>
#include <utility>

#include "dawn/common/Assert.h"
#include "dawn/common/Constants.h"
#include "dawn/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::e1D:
        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:
            ASSERT(descriptor->sampleCount == 1);
            return GL_TEXTURE_3D;
    }
    UNREACHABLE();
}

GLenum TargetForTextureViewDimension(wgpu::TextureViewDimension dimension,
                                     uint32_t arrayLayerCount,
                                     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) {
                ASSERT(arrayLayerCount == 1);
                return GL_TEXTURE_2D_MULTISAMPLE;
            }
            ASSERT(sampleCount == 1);
            return GL_TEXTURE_2D_ARRAY;
        case wgpu::TextureViewDimension::Cube:
            ASSERT(sampleCount == 1);
            ASSERT(arrayLayerCount == 6);
            return GL_TEXTURE_CUBE_MAP;
        case wgpu::TextureViewDimension::CubeArray:
            ASSERT(sampleCount == 1);
            ASSERT(arrayLayerCount % 6 == 0);
            return GL_TEXTURE_CUBE_MAP_ARRAY;
        case wgpu::TextureViewDimension::e3D:
            return GL_TEXTURE_3D;

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

bool RequiresCreatingNewTextureView(const TextureBase* texture,
                                    const TextureViewDescriptor* textureViewDescriptor) {
    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 (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;
}

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_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:
            UNREACHABLE();
    }
}

}  // namespace

// Texture

// static
ResultOrError<Ref<Texture>> Texture::Create(Device* device, const 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 TextureDescriptor* descriptor)
    : Texture(device, descriptor, 0, TextureState::OwnedInternal) {
    const OpenGLFunctions& gl = device->GetGL();

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

    const GLFormat& glFormat = GetGLFormat();

    gl.BindTexture(mTarget, mHandle);

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

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

void Texture::Touch() {
    mGenID++;
}

uint32_t Texture::GetGenID() const {
    return mGenID;
}

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) {
        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) {
    // TODO(crbug.com/dawn/850): initialize the textures with compressed formats.
    if (GetFormat().isCompressed) {
        return {};
    }

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

            gl.Enable(GL_SCISSOR_TEST);
            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};

            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);
                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::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)
                                                     .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 = GetMipLevelSingleSubresourcePhysicalSize(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);
        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);

            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();
    }
    Touch();
    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 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 (!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 {
            // Simulate glTextureView() with texture-to-texture copies.
            mUseCopy = true;
            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 {
    ASSERT(mHandle != 0);
    return mHandle;
}

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

void TextureView::BindToFramebuffer(GLenum target, GLenum attachment) {
    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();
        arrayLayer = GetBaseArrayLayer();
    }

    ASSERT(handle != 0);
    if (textarget == GL_TEXTURE_2D_ARRAY || textarget == GL_TEXTURE_3D) {
        gl.FramebufferTextureLayer(target, attachment, handle, mipLevel, arrayLayer);
    } else {
        gl.FramebufferTexture2D(target, attachment, textarget, handle, mipLevel);
    }
}

void TextureView::CopyIfNeeded() {
    if (!mUseCopy) {
        return;
    }

    const Texture* texture = ToBackend(GetTexture());
    if (mGenID == texture->GetGenID()) {
        return;
    }

    Device* device = ToBackend(GetDevice());
    const OpenGLFunctions& gl = device->GetGL();
    uint32_t srcLevel = GetBaseMipLevel();
    uint32_t numLevels = GetLevelCount();

    uint32_t width = texture->GetWidth() >> srcLevel;
    uint32_t height = texture->GetHeight() >> srcLevel;
    Extent3D size{width, height, GetLayerCount()};

    if (mHandle == 0) {
        gl.GenTextures(1, &mHandle);
        gl.BindTexture(mTarget, mHandle);
        AllocateTexture(gl, mTarget, texture->GetSampleCount(), numLevels, GetInternalFormat(),
                        size);
        mOwnsHandle = true;
    }

    Origin3D src{0, 0, GetBaseArrayLayer()};
    Origin3D dst{0, 0, 0};
    for (GLuint level = 0; level < numLevels; ++level) {
        CopyImageSubData(gl, GetAspects(), texture->GetHandle(), texture->GetGLTarget(),
                         srcLevel + level, src, mHandle, mTarget, level, dst, size);
    }

    mGenID = texture->GetGenID();
}

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
