// Copyright 2021 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 "src/dawn/native/ExternalTexture.h"

#include <algorithm>
#include <utility>

#include "dawn/native/ObjectType_autogen.h"
#include "src/dawn/common/ColorSpace.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/Queue.h"
#include "src/dawn/native/Texture.h"
#include "src/dawn/native/dawn_platform.h"
#include "src/dawn/native/utils/WGPUHelpers.h"
#include "src/utils/compiler.h"

namespace dawn::native {

MaybeError ValidateExternalTexturePlane(const TextureViewBase* textureView) {
    DAWN_INVALID_IF(
        (textureView->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
        "The external texture plane (%s) usage (%s) doesn't include the required usage (%s)",
        textureView, textureView->GetUsage(), wgpu::TextureUsage::TextureBinding);

    DAWN_INVALID_IF(textureView->GetDimension() != wgpu::TextureViewDimension::e2D,
                    "The external texture plane (%s) dimension (%s) is not 2D.", textureView,
                    textureView->GetDimension());

    DAWN_INVALID_IF(textureView->GetLevelCount() > 1,
                    "The external texture plane (%s) mip level count (%u) is not 1.", textureView,
                    textureView->GetLevelCount());

    DAWN_INVALID_IF(textureView->GetTexture()->GetSampleCount() != 1,
                    "The external texture plane (%s) sample count (%u) is not one.", textureView,
                    textureView->GetTexture()->GetSampleCount());

    return {};
}

MaybeError ValidateExternalTextureDescriptor(const DeviceBase* device,
                                             const ExternalTextureDescriptor* descriptor) {
    DAWN_ASSERT(descriptor);
    DAWN_ASSERT(descriptor->plane0);

    DAWN_TRY(device->ValidateObject(descriptor->plane0));

    DAWN_INVALID_IF(!descriptor->gamutConversionMatrix,
                    "The gamut conversion matrix must be non-null.");

    DAWN_INVALID_IF(!descriptor->srcTransferFunctionParameters,
                    "The source transfer function parameters must be non-null.");

    DAWN_INVALID_IF(!descriptor->dstTransferFunctionParameters,
                    "The destination transfer function parameters must be non-null.");

    DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane0));

    auto CheckPlaneFormat = [](const DeviceBase* device, const Format& format,
                               uint32_t requiredComponentCount) -> MaybeError {
        DAWN_INVALID_IF(format.aspects != Aspect::Color, "The format (%s) is not a color format.",
                        format.format);

        // The Unorm16FormatsForExternalTexture feature allows using R/RG16Unorm to create
        // ExternalTextures even if they are not filterable float. This is a hack to allow YUV HDR
        // SharedTextureMemory to be used without enabling R/RG16Unorm for anything else.
        bool skipUnorm16 = device->HasFeature(Feature::Unorm16FormatsForExternalTexture) &&
                           (format.format == wgpu::TextureFormat::R16Unorm ||
                            format.format == wgpu::TextureFormat::RG16Unorm);

        if (!skipUnorm16) {
            DAWN_INVALID_IF(!IsSubset(SampleTypeBit::Float,
                                      format.GetAspectInfo(Aspect::Color).supportedSampleTypes),
                            "The format (%s) is not filterable float.", format.format);
        }

        DAWN_INVALID_IF(format.componentCount != requiredComponentCount,
                        "The format (%s) component count (%u) is not %u.", format.format,
                        format.componentCount, requiredComponentCount);
        return {};
    };

    if (descriptor->plane1) {
        DAWN_INVALID_IF(
            !descriptor->yuvToRgbConversionMatrix,
            "When more than one plane is set, the YUV-to-RGB conversion matrix must be non-null.");

        DAWN_TRY(device->ValidateObject(descriptor->plane1));
        DAWN_TRY(ValidateExternalTexturePlane(descriptor->plane1));

        // Y + UV case.
        DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane0->GetFormat(), 1),
                         "validating the format of plane 0 (%s)", descriptor->plane0);
        DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane1->GetFormat(), 2),
                         "validating the format of plane 1 (%s)", descriptor->plane1);

    } else if (descriptor->plane0->GetFormat().format == wgpu::TextureFormat::OpaqueYCbCrAndroid) {
        // Special case for OpaqueYCbCrAndroid
        DAWN_INVALID_IF(!device->HasFeature(Feature::OpaqueYCbCrAndroidForExternalTexture),
                        "%s isn't enabled while plane0 (%s) has format %s.",
                        wgpu::FeatureName::OpaqueYCbCrAndroidForExternalTexture, descriptor->plane0,
                        wgpu::TextureFormat::OpaqueYCbCrAndroid);
        DAWN_INVALID_IF(descriptor->plane0->HasYCbCrDescriptor(),
                        "%s was created with a YCbCrVkDescriptor.", descriptor->plane0);

    } else {
        // RGBA case.
        DAWN_TRY_CONTEXT(CheckPlaneFormat(device, descriptor->plane0->GetFormat(), 4),
                         "validating the format of plane 0 (%s)", descriptor->plane0);
    }

    DAWN_INVALID_IF(descriptor->cropSize.width == 0 || descriptor->cropSize.height == 0,
                    "cropSize %s has 0 on width or height.", descriptor->cropSize);

    const Extent3D textureSize = descriptor->plane0->GetSingleSubresourceVirtualSize();
    DAWN_INVALID_IF(descriptor->cropSize.width > textureSize.width ||
                        descriptor->cropSize.height > textureSize.height,
                    "cropSize %s exceeds the texture size, defined by Plane0 size (%u, %u).",
                    descriptor->cropSize, textureSize.width, textureSize.height);
    DAWN_INVALID_IF(descriptor->cropOrigin.x > textureSize.width - descriptor->cropSize.width ||
                        descriptor->cropOrigin.y > textureSize.height - descriptor->cropSize.height,
                    "cropRect[Origin: %s, Size: %s] exceeds plane0's size (%u, %u).",
                    descriptor->cropOrigin, descriptor->cropSize, textureSize.width,
                    textureSize.height);

    DAWN_INVALID_IF(descriptor->apparentSize.width == 0 || descriptor->apparentSize.height == 0,
                    "apparentSize (%u, %u) is empty.", descriptor->apparentSize.width,
                    descriptor->apparentSize.height);
    DAWN_INVALID_IF(descriptor->apparentSize.width > device->GetLimits().v1.maxTextureDimension2D,
                    "apparentSize.width (%u) is larger than maxTextureDimension2D (%u)",
                    descriptor->apparentSize.width, device->GetLimits().v1.maxTextureDimension2D);
    DAWN_INVALID_IF(descriptor->apparentSize.height > device->GetLimits().v1.maxTextureDimension2D,
                    "apparentSize.height (%u) is larger than maxTextureDimension2D (%u)",
                    descriptor->apparentSize.height, device->GetLimits().v1.maxTextureDimension2D);

    return {};
}

namespace {
ExternalTextureParams ComputeExternalTextureParams(const ExternalTextureDescriptor* descriptor) {
    using math::Mat3x2f;
    using math::Mat3x3f;
    using math::Vec2f;
    using math::Vec2u;

    ExternalTextureParams params;
    params.numPlanes = descriptor->plane1 == nullptr ? 1 : 2;

    params.doYuvToRgbConversionOnly = descriptor->doYuvToRgbConversionOnly ? 1 : 0;

    // YUV-to-RGB conversion is performed by multiplying the source YUV values with a 3x4 matrix on
    // the right. This is to use 36 bytes of uniform buffer instead of 48 for a 4x3 matrix.

    // TODO(https://crbug.com/496604550): Make the conversion matrix required, users can pass the
    // identity if needed.
    auto yMat = math::Mat3x4f::FromRows({
        {1, 0, 0},
        {0, 1, 0},
        {0, 0, 1},
        {0, 0, 0},
    });
    if (descriptor->yuvToRgbConversionMatrix) {
        const float* yMatIn = descriptor->yuvToRgbConversionMatrix;
        yMat = {
            {yMatIn[0], DAWN_UNSAFE_TODO(yMatIn[1]), DAWN_UNSAFE_TODO(yMatIn[2]),
             DAWN_UNSAFE_TODO(yMatIn[3])},  //
            {DAWN_UNSAFE_TODO(yMatIn[4]), DAWN_UNSAFE_TODO(yMatIn[5]), DAWN_UNSAFE_TODO(yMatIn[6]),
             DAWN_UNSAFE_TODO(yMatIn[7])},  //
            {DAWN_UNSAFE_TODO(yMatIn[8]), DAWN_UNSAFE_TODO(yMatIn[9]), DAWN_UNSAFE_TODO(yMatIn[10]),
             DAWN_UNSAFE_TODO(yMatIn[11])},
        };
    }

    // Vulkan's YCbCr sampling returns components in Cb, Y, Cr, 1 order while yMat expect Y, Cb,
    // Cr, 1. Reorder them by appending a "swizzling" matrix first.
    if (descriptor->plane0->GetTexture()->GetFormat().format ==
        wgpu::TextureFormat::OpaqueYCbCrAndroid) {
        constexpr auto kUndoVulkanSwizzle = math::Mat4x4f::FromRows({
            {0, 0, 1, 0},
            {1, 0, 0, 0},
            {0, 1, 0, 0},
            {0, 0, 0, 1},
        });
        yMat = math::Mul(kUndoVulkanSwizzle, yMat);
    }

    params.yuvToRgbConversionMatrix = yMat;

    // Gamut correction is performed by multiplying a 3x3 matrix passed from Chromium. The
    // matrix was computed by multiplying the appropriate source and destination gamut
    // matrices sourced from ui/gfx/color_space.cc.
    const float* gMat = descriptor->gamutConversionMatrix;
    params.gamutConversionMatrix = {
        {gMat[0], DAWN_UNSAFE_TODO(gMat[1]), DAWN_UNSAFE_TODO(gMat[2])},                    //
        {DAWN_UNSAFE_TODO(gMat[3]), DAWN_UNSAFE_TODO(gMat[4]), DAWN_UNSAFE_TODO(gMat[5])},  //
        {DAWN_UNSAFE_TODO(gMat[6]), DAWN_UNSAFE_TODO(gMat[7]), DAWN_UNSAFE_TODO(gMat[8])}};

    // Gamma decode/encode is performed by the logic:
    //    if (abs(v) < params.D) {
    //        return sign(v) * (params.C * abs(v) + params.F);
    //    }
    //    return pow(A * x + B, G) + E
    //
    // Constants are passed from Chromium and originally sourced from ui/gfx/color_space.cc
    auto ToTransferFunctionParams = [](const float* params) -> TransferFunctionParams {
        TransferFunctionMode mode = TransferFunctionMode::Gamma;

        // TODO(https://crbug.com/496604550): Passing the mode as a negative value for G is a hack.
        // Have a dedicated mode enum at the Dawn API level instead.
        if (params[0] < 0) {
            mode = static_cast<TransferFunctionMode>(static_cast<uint32_t>(-params[0]));
        }

        return {
            .mode = mode,
            .a = DAWN_UNSAFE_TODO(params[1]),
            .b = DAWN_UNSAFE_TODO(params[2]),
            .c = DAWN_UNSAFE_TODO(params[3]),
            .d = DAWN_UNSAFE_TODO(params[4]),
            .e = DAWN_UNSAFE_TODO(params[5]),
            .f = DAWN_UNSAFE_TODO(params[6]),
            // This is the first param for historical reasons.
            // TODO(https://crbug.com/496604550): Make the parameters to Dawn a struct with members
            // in alphabetical order.
            .g = params[0],
        };
    };
    params.srcTransferFunction =
        ToTransferFunctionParams(descriptor->srcTransferFunctionParameters);
    params.dstTransferFunction =
        ToTransferFunctionParams(descriptor->dstTransferFunctionParameters);

    // Configure the HLG OOTF to perform a gamma 1.2 on the Rec2020 luminance.
    // TODO(https://crbug.com/521494707): Make the parameters configurable.
    if (params.srcTransferFunction.mode == TransferFunctionMode::HLG) {
        // The factors to compute Y from RGB are derived from the YCbCr to RGB matrix.
        constexpr math::Vec3f yFactors = kYCbCrToRGB_Rec2020.Inverse().Transposed()[0];
        // Gamma is 1.2, which means that Y is multiplied 0.2 times to the color to achieve a total
        // of 1.2 gamma.
        params.ootfParam = {yFactors[0], yFactors[1], yFactors[2], 0.2};
    }

    // Compute the various transforms and bounds used for sampling and loading operations. They make
    // them appear as if operating on a `apparentSize` texture but instead they are all happening in
    // a transformed and cropped rectangle of the planes. Perform all 2D operations in homogeneous
    // coordinates (in 3D with Z fixed to 1) so that translations can be expressed with matrices.

    // Extract all the relevant sizes as float to avoid extra casts in later computations.
    Extent3D plane0Extent = descriptor->plane0->GetSingleSubresourceVirtualSize();
    Extent3D plane1Extent = {1, 1, 1};
    if (params.numPlanes == 2) {
        plane1Extent = descriptor->plane1->GetSingleSubresourceVirtualSize();
    }
    auto plane0Size = Vec2f(plane0Extent.width, plane0Extent.height);
    auto plane1Size = Vec2f(plane1Extent.width, plane1Extent.height);
    auto cropOrigin = Vec2f(descriptor->cropOrigin.x, descriptor->cropOrigin.y);
    auto cropSize = Vec2f(descriptor->cropSize.width, descriptor->cropSize.height);

    // Offset the coordinates so the center texel is at the origin, so we can apply rotations and
    // y-flips. After translation, coordinates range from [-0.5 .. +0.5] in both U and V.
    Mat3x3f sampleTransform = Mat3x3f::Translation({-0.5, -0.5});

    // The video frame metadata both rotation and mirroring information. The rotation happens before
    // the mirroring when processing the video frame, so do the inverse order when converting UV
    // coordinates.
    if (descriptor->mirrored) {
        sampleTransform = Mul(Mat3x3f::ScaleHomogeneous({-1, 1}), sampleTransform);
    }

    // Apply rotations as needed for the sampling coordinate. This may also rotate the
    // shader-apparent size of the texture.
    Vec2u loadBounds = {descriptor->apparentSize.width - 1, descriptor->apparentSize.height - 1};
    switch (descriptor->rotation) {
        case wgpu::ExternalTextureRotation::Rotate0Degrees:
            break;
        case wgpu::ExternalTextureRotation::Rotate90Degrees:
            std::swap(loadBounds[0], loadBounds[1]);
            sampleTransform = Mul(Mat3x3f({0, -1, 0},  // x -> -y'
                                          {+1, 0, 0},  // y -> x'
                                          {0, 0, 1}),
                                  sampleTransform);
            break;
        case wgpu::ExternalTextureRotation::Rotate180Degrees:
            sampleTransform = Mul(Mat3x3f({-1, 0, 0},  // x -> -x'
                                          {0, -1, 0},  // y -> -y'
                                          {0, 0, 1}),
                                  sampleTransform);
            break;
        case wgpu::ExternalTextureRotation::Rotate270Degrees:
            std::swap(loadBounds[0], loadBounds[1]);
            sampleTransform = Mul(Mat3x3f({0, 1, 0},   // x -> y
                                          {-1, 0, 0},  // y -> -x'
                                          {0, 0, 1}),
                                  sampleTransform);
            break;
    }

    // Offset the coordinates so the bottom-left texel is at origin.
    // After translation, coordinates range from [0 .. 1] in both U and V.
    sampleTransform = Mul(Mat3x3f::Translation({0.5, 0.5}), sampleTransform);

    // Finally, scale and translate based on the crop rect.
    Vec2f rectScale = cropSize / plane0Size;
    Vec2f rectOffset = cropOrigin / plane0Size;

    sampleTransform = Mul(Mat3x3f::ScaleHomogeneous(rectScale), sampleTransform);
    sampleTransform = Mul(Mat3x3f::Translation(rectOffset), sampleTransform);
    params.sampleTransform = Mat3x2f::CropOrExpandFrom(sampleTransform);

    // Compute the load transformation matrix by using toTexels * sampleTransform * toNormalized
    // Note that coords starts from 0 so the max value is size - 1. Note that we use at least 1 for
    // the loadBounds to avoid a division by 0 (since it is not possible to map [0, 0] to [0, 1]).
    // The load coordinate will be set to 0 because of clamping in the shader so it will stay 0
    // after normalization.
    {
        Mat3x3f toTexels = Mat3x3f::ScaleHomogeneous(plane0Size - Vec2f(1, 1));
        Mat3x3f toNormalized =
            Mat3x3f::ScaleHomogeneous(Vec2f(1, 1) / Max(Vec2f(loadBounds), Vec2f(1, 1)));
        Mat3x3f loadTransform = Mul(toTexels, Mul(sampleTransform, toNormalized));

        params.loadTransform = Mat3x2f::CropOrExpandFrom(loadTransform);
    }

    // Compute the clamping for each plane individually: to avoid bleeding of OOB texels due to
    // interpolation we need to offset by a half texel in, which depends on the size of the plane.
    {
        Vec2f plane0HalfTexel = Vec2f(0.5f, 0.5f) / plane0Size;
        Vec2f plane1HalfTexel = Vec2f(0.5f, 0.5f) / plane1Size;

        params.samplePlane0RectMin = rectOffset + plane0HalfTexel;
        params.samplePlane1RectMin = rectOffset + plane1HalfTexel;
        params.samplePlane0RectMax = rectOffset + rectScale - plane0HalfTexel;
        params.samplePlane1RectMax = rectOffset + rectScale - plane1HalfTexel;
    }

    params.plane1CoordFactor = plane1Size / plane0Size;
    params.apparentSize = loadBounds;

    return params;
}
}  // anonymous namespace

ResultOrError<Ref<BufferBase>> MakeParamsBufferForSimpleView(DeviceBase* device,
                                                             Ref<TextureViewBase> textureView) {
    const Extent3D textureSize = textureView->GetSingleSubresourceVirtualSize();
    std::array<float, 12> placeholderConstantArray = {};

    // Make a fake ExternalTextureDescriptor for the view that reuses the code computing uniform
    // parameters passed to the shader.
    ExternalTextureDescriptor desc = {};
    desc.plane0 = textureView.Get();
    desc.cropOrigin = {0, 0};
    desc.cropSize = {textureSize.width, textureSize.height};
    desc.apparentSize = {textureSize.width, textureSize.height};
    desc.doYuvToRgbConversionOnly = true;
    desc.srcTransferFunctionParameters = placeholderConstantArray.data();
    desc.dstTransferFunctionParameters = placeholderConstantArray.data();
    desc.gamutConversionMatrix = placeholderConstantArray.data();

    ExternalTextureParams params = ComputeExternalTextureParams(&desc);
    return utils::CreateBufferFromData(device, "Dawn_Simple_Texture_View_Params_Buffer",
                                       wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst,
                                       {params});
}

// static
ResultOrError<Ref<ExternalTextureBase>> ExternalTextureBase::Create(
    DeviceBase* device,
    const ExternalTextureDescriptor* descriptor) {
    Ref<ExternalTextureBase> externalTexture =
        AcquireRef(new ExternalTextureBase(device, descriptor));
    DAWN_TRY(externalTexture->Initialize(device, descriptor));
    return std::move(externalTexture);
}

ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
                                         const ExternalTextureDescriptor* descriptor)
    : ApiObjectBase(device, descriptor->label), mState(ExternalTextureState::Active) {
    GetObjectTrackingList()->Track(this);
}

// Error external texture cannot be used in bind group.
ExternalTextureBase::ExternalTextureBase(DeviceBase* device,
                                         ObjectBase::ErrorTag tag,
                                         StringView label)
    : ApiObjectBase(device, tag, label), mState(ExternalTextureState::Destroyed) {}

ExternalTextureBase::~ExternalTextureBase() = default;

MaybeError ExternalTextureBase::Initialize(DeviceBase* device,
                                           const ExternalTextureDescriptor* descriptor) {
    // Store any passed in TextureViews associated with individual planes.
    mTextureViews[0] = descriptor->plane0;

    if (descriptor->plane1) {
        mViewCount = 2;
        mTextureViews[1] = descriptor->plane1;
    } else {
        mViewCount = 1;
        DAWN_TRY_ASSIGN(mTextureViews[1],
                        device->GetOrCreatePlaceholderTextureViewForExternalTexture());
    }

    // We must create a buffer to store parameters needed by a shader that operates on this
    // external texture.
    ExternalTextureParams params = ComputeExternalTextureParams(descriptor);
    DAWN_TRY_ASSIGN(mParamsBuffer,
                    utils::CreateBufferFromData(
                        device, "Dawn_External_Texture_Params_Buffer",
                        wgpu::BufferUsage::Uniform | wgpu::BufferUsage::CopyDst, {params}));

    return {};
}

const std::array<Ref<TextureViewBase>, kMaxPlanesPerFormat>& ExternalTextureBase::GetTextureViews()
    const {
    return mTextureViews;
}

MaybeError ExternalTextureBase::ValidateCanUseInSubmitNow() const {
    DAWN_ASSERT(!IsError());
    DAWN_INVALID_IF(mState != ExternalTextureState::Active,
                    "External texture %s used in a submit is not active.", this);

    for (uint32_t i = 0; i < kMaxPlanesPerFormat; ++i) {
        if (mTextureViews[i] != nullptr) {
            DAWN_TRY_CONTEXT(mTextureViews[i]->GetTexture()->ValidateCanUseInSubmitNow(),
                             "Validate plane %u of %s can be used in a submit.", i, this);
        }
    }
    return {};
}

MaybeError ExternalTextureBase::ValidateRefresh() {
    DAWN_TRY(GetDevice()->ValidateObject(this));
    DAWN_INVALID_IF(mState == ExternalTextureState::Destroyed, "%s is destroyed.", this);
    return {};
}

MaybeError ExternalTextureBase::ValidateExpire() {
    DAWN_TRY(GetDevice()->ValidateObject(this));
    DAWN_INVALID_IF(mState != ExternalTextureState::Active, "%s is not active.", this);
    return {};
}

void ExternalTextureBase::APIRefresh() {
    if (GetDevice()->ConsumedError(ValidateRefresh(), "calling %s.Refresh()", this)) {
        return;
    }
    mState = ExternalTextureState::Active;
}

void ExternalTextureBase::APIExpire() {
    if (GetDevice()->ConsumedError(ValidateExpire(), "calling %s.Expire()", this)) {
        return;
    }
    mState = ExternalTextureState::Expired;
}

void ExternalTextureBase::APIDestroy() {
    Destroy();
}

void ExternalTextureBase::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    mState = ExternalTextureState::Destroyed;
}

// static
Ref<ExternalTextureBase> ExternalTextureBase::MakeError(DeviceBase* device, StringView label) {
    return AcquireRef(new ExternalTextureBase(device, ObjectBase::kError, label));
}

BufferBase* ExternalTextureBase::GetParamsBuffer() const {
    DAWN_ASSERT(!IsError());
    return mParamsBuffer.Get();
}

bool ExternalTextureBase::HasSingleView() const {
    DAWN_ASSERT(!IsError());
    return mViewCount == 1;
}

ObjectType ExternalTextureBase::GetType() const {
    return ObjectType::ExternalTexture;
}

}  // namespace dawn::native
