// Copyright 2020 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/Surface.h"

#include <memory>
#include <string>
#include <utility>

#include "dawn/common/Platform.h"
#include "dawn/native/ChainUtils.h"
#include "dawn/native/Device.h"
#include "dawn/native/Instance.h"
#include "dawn/native/SwapChain.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/native/utils/WGPUHelpers.h"

#if DAWN_PLATFORM_IS(WINDOWS)
#include "dawn/common/windows_with_undefs.h"
#endif  // DAWN_PLATFORM_IS(WINDOWS)

#if defined(DAWN_USE_WINDOWS_UI)
#include <windows.ui.core.h>
#include <windows.ui.xaml.controls.h>
#endif  // defined(DAWN_USE_WINDOWS_UI)

#if defined(DAWN_USE_X11)
#include "dawn/common/xlib_with_undefs.h"
#include "dawn/native/X11Functions.h"
#endif  // defined(DAWN_USE_X11)

namespace dawn::native {

absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
    Surface::Type value,
    const absl::FormatConversionSpec& spec,
    absl::FormatSink* s) {
    switch (value) {
        case Surface::Type::AndroidWindow:
            s->Append("AndroidWindow");
            break;
        case Surface::Type::MetalLayer:
            s->Append("MetalLayer");
            break;
        case Surface::Type::WaylandSurface:
            s->Append("WaylandSurface");
            break;
        case Surface::Type::WindowsHWND:
            s->Append("WindowsHWND");
            break;
        case Surface::Type::WindowsCoreWindow:
            s->Append("WindowsCoreWindow");
            break;
        case Surface::Type::WindowsSwapChainPanel:
            s->Append("WindowsSwapChainPanel");
            break;
        case Surface::Type::XlibWindow:
            s->Append("XlibWindow");
            break;
    }
    return {true};
}

#if defined(DAWN_ENABLE_BACKEND_METAL)
bool InheritsFromCAMetalLayer(void* obj);
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

ResultOrError<UnpackedPtr<SurfaceDescriptor>> ValidateSurfaceDescriptor(
    InstanceBase* instance,
    const SurfaceDescriptor* rawDescriptor) {
    DAWN_INVALID_IF(rawDescriptor->nextInChain == nullptr,
                    "Surface cannot be created with %s. nextInChain is not specified.",
                    rawDescriptor);
    UnpackedPtr<SurfaceDescriptor> descriptor;
    DAWN_TRY_ASSIGN(descriptor, ValidateAndUnpack(rawDescriptor));

    wgpu::SType type;
    DAWN_TRY_ASSIGN(
        type, (descriptor.ValidateBranches<
                  Branch<SurfaceSourceAndroidNativeWindow>, Branch<SurfaceSourceMetalLayer>,
                  Branch<SurfaceSourceWindowsHWND>, Branch<SurfaceDescriptorFromWindowsCoreWindow>,
                  Branch<SurfaceDescriptorFromWindowsSwapChainPanel>,
                  Branch<SurfaceSourceXlibWindow>, Branch<SurfaceSourceWaylandSurface>>()));
    switch (type) {
#if DAWN_PLATFORM_IS(ANDROID)
        case wgpu::SType::SurfaceSourceAndroidNativeWindow: {
            auto* subDesc = descriptor.Get<SurfaceSourceAndroidNativeWindow>();
            DAWN_ASSERT(subDesc != nullptr);
            DAWN_INVALID_IF(subDesc->window == nullptr, "Android window is not set.");
            return descriptor;
        }
#endif  // DAWN_PLATFORM_IS(ANDROID)
#if defined(DAWN_ENABLE_BACKEND_METAL)
        case wgpu::SType::SurfaceSourceMetalLayer: {
            auto* subDesc = descriptor.Get<SurfaceSourceMetalLayer>();
            DAWN_ASSERT(subDesc != nullptr);
            // Check that the layer is a CAMetalLayer (or a derived class).
            DAWN_INVALID_IF(!InheritsFromCAMetalLayer(subDesc->layer),
                            "Layer must be a CAMetalLayer");
            return descriptor;
        }
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)
#if DAWN_PLATFORM_IS(WIN32)
        case wgpu::SType::SurfaceSourceWindowsHWND: {
            auto* subDesc = descriptor.Get<SurfaceSourceWindowsHWND>();
            DAWN_ASSERT(subDesc != nullptr);
            DAWN_INVALID_IF(IsWindow(static_cast<HWND>(subDesc->hwnd)) == 0, "Invalid HWND");
            return descriptor;
        }
#endif  // DAWN_PLATFORM_IS(WIN32)
#if defined(DAWN_USE_WINDOWS_UI)
        case wgpu::SType::SurfaceDescriptorFromWindowsCoreWindow: {
            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsCoreWindow>();
            DAWN_ASSERT(subDesc != nullptr);
            // Validate the coreWindow by query for ICoreWindow interface
            ComPtr<ABI::Windows::UI::Core::ICoreWindow> coreWindow;
            DAWN_INVALID_IF(subDesc->coreWindow == nullptr ||
                                FAILED(static_cast<IUnknown*>(subDesc->coreWindow)
                                           ->QueryInterface(IID_PPV_ARGS(&coreWindow))),
                            "Invalid CoreWindow");
            return descriptor;
        }
        case wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel: {
            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsSwapChainPanel>();
            DAWN_ASSERT(subDesc != nullptr);
            // Validate the swapChainPanel by querying for ISwapChainPanel interface
            ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> swapChainPanel;
            DAWN_INVALID_IF(subDesc->swapChainPanel == nullptr ||
                                FAILED(static_cast<IUnknown*>(subDesc->swapChainPanel)
                                           ->QueryInterface(IID_PPV_ARGS(&swapChainPanel))),
                            "Invalid SwapChainPanel");
            return descriptor;
        }
#endif  // defined(DAWN_USE_WINDOWS_UI)
#if defined(DAWN_USE_WAYLAND)
        case wgpu::SType::SurfaceSourceWaylandSurface: {
            auto* subDesc = descriptor.Get<SurfaceSourceWaylandSurface>();
            DAWN_ASSERT(subDesc != nullptr);
            // Unfortunately we can't check the validity of wayland objects. Only that they
            // aren't nullptr.
            DAWN_INVALID_IF(subDesc->display == nullptr, "Wayland display is nullptr.");
            DAWN_INVALID_IF(subDesc->surface == nullptr, "Wayland surface is nullptr.");
            return descriptor;
        }
#endif  // defined(DAWN_USE_WAYLAND)
#if defined(DAWN_USE_X11)
        case wgpu::SType::SurfaceSourceXlibWindow: {
            auto* subDesc = descriptor.Get<SurfaceSourceXlibWindow>();
            DAWN_ASSERT(subDesc != nullptr);
            // Check the validity of the window by calling a getter function on the window that
            // returns a status code. If the window is bad the call return a status of zero. We
            // need to set a temporary X11 error handler while doing this because the default
            // X11 error handler exits the program on any error.
            const X11Functions* x11 = instance->GetOrLoadX11Functions();
            DAWN_INVALID_IF(!x11->IsX11Loaded(), "Couldn't load libX11.");

            XErrorHandler oldErrorHandler =
                x11->xSetErrorHandler([](Display*, XErrorEvent*) { return 0; });
            XWindowAttributes attributes;
            int status =
                x11->xGetWindowAttributes(reinterpret_cast<Display*>(subDesc->display),
                                          static_cast<Window>(subDesc->window), &attributes);
            x11->xSetErrorHandler(oldErrorHandler);

            DAWN_INVALID_IF(status == 0, "Invalid X Window");
            return descriptor;
        }
#endif  // defined(DAWN_USE_X11)
        default:
            return DAWN_VALIDATION_ERROR("Unsupported sType (%s)", type);
    }
}

MaybeError ValidateSurfaceConfiguration(DeviceBase* device,
                                        const PhysicalDeviceSurfaceCapabilities& capabilities,
                                        const SurfaceConfiguration* config,
                                        const Surface* surface) {
    UnpackedPtr<SurfaceConfiguration> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(config));

    DAWN_TRY(config->device->ValidateIsAlive());

    // Check that config matches capabilities, this implicitly validates the value of the enums.
    DAWN_INVALID_IF(!IsSubset(config->usage, capabilities.usages),
                    "Usages requested (%s) are not supported by the adapter (%s) which supports "
                    "only %s for this surface.",
                    config->usage, config->device->GetAdapter(), capabilities.usages);

    auto formatIt =
        std::find(capabilities.formats.begin(), capabilities.formats.end(), config->format);
    DAWN_INVALID_IF(formatIt == capabilities.formats.end(),
                    "Format (%s) is not supported by the adapter (%s) for this surface.",
                    config->format, config->device->GetAdapter());

    auto presentModeIt = std::find(capabilities.presentModes.begin(),
                                   capabilities.presentModes.end(), config->presentMode);
    DAWN_INVALID_IF(presentModeIt == capabilities.presentModes.end(),
                    "Present mode (%s) is not supported by the adapter (%s) for this surface.",
                    config->presentMode, config->device->GetAdapter());

    auto alphaModeIt = std::find(capabilities.alphaModes.begin(), capabilities.alphaModes.end(),
                                 config->alphaMode);
    DAWN_INVALID_IF(alphaModeIt == capabilities.alphaModes.end(),
                    "Alpha mode (%s) is not supported by the adapter (%s) for this surface.",
                    config->alphaMode, config->device->GetAdapter());

    // Validate the surface would produce valid textures.
    TextureDescriptor textureDesc;
    textureDesc.usage = config->usage;
    textureDesc.size = {config->width, config->height};
    textureDesc.format = config->format;
    textureDesc.dimension = wgpu::TextureDimension::e2D;
    textureDesc.viewFormatCount = config->viewFormatCount;
    textureDesc.viewFormats = config->viewFormats;

    UnpackedPtr<TextureDescriptor> unpackedTextureDesc;
    DAWN_TRY_ASSIGN(unpackedTextureDesc, ValidateAndUnpack(&textureDesc));
    DAWN_TRY_CONTEXT(ValidateTextureDescriptor(device, unpackedTextureDesc),
                     "validating the configuration of %s would produce valid textures", surface);

    return {};
}

class AdapterSurfaceCapCache {
  public:
    template <typename F>
    MaybeError WithAdapterCapabilities(AdapterBase* adapter, const Surface* surface, F f) {
        if (mCachedCapabilitiesAdapter.Promote().Get() != adapter) {
            const PhysicalDeviceBase* physicalDevice = adapter->GetPhysicalDevice();
            DAWN_TRY_ASSIGN(mCachedCapabilities, physicalDevice->GetSurfaceCapabilities(
                                                     adapter->GetInstance(), surface));
            mCachedCapabilitiesAdapter = GetWeakRef(adapter);
        }
        return f(mCachedCapabilities);
    }

  private:
    WeakRef<AdapterBase> mCachedCapabilitiesAdapter = nullptr;
    PhysicalDeviceSurfaceCapabilities mCachedCapabilities;
};

// static
Ref<Surface> Surface::MakeError(InstanceBase* instance) {
    return AcquireRef(new Surface(instance, ErrorMonad::kError));
}

Surface::Surface(InstanceBase* instance, ErrorTag tag) : ErrorMonad(tag), mInstance(instance) {}

Surface::Surface(InstanceBase* instance, const UnpackedPtr<SurfaceDescriptor>& descriptor)
    : ErrorMonad(),
      mInstance(instance),
      mCapabilityCache(std::make_unique<AdapterSurfaceCapCache>()) {
    mLabel = std::string(descriptor->label);

    // Type is validated in validation, otherwise this may crash with an assert failure.
    wgpu::SType type =
        descriptor
            .ValidateBranches<
                Branch<SurfaceSourceAndroidNativeWindow>, Branch<SurfaceSourceMetalLayer>,
                Branch<SurfaceSourceWindowsHWND>, Branch<SurfaceDescriptorFromWindowsCoreWindow>,
                Branch<SurfaceDescriptorFromWindowsSwapChainPanel>, Branch<SurfaceSourceXlibWindow>,
                Branch<SurfaceSourceWaylandSurface>>()
            .AcquireSuccess();
    switch (type) {
        case wgpu::SType::SurfaceSourceAndroidNativeWindow: {
            auto* subDesc = descriptor.Get<SurfaceSourceAndroidNativeWindow>();
            mType = Type::AndroidWindow;
            mAndroidNativeWindow = subDesc->window;
            break;
        }
        case wgpu::SType::SurfaceSourceMetalLayer: {
            auto* subDesc = descriptor.Get<SurfaceSourceMetalLayer>();
            mType = Type::MetalLayer;
            mMetalLayer = subDesc->layer;
            break;
        }
        case wgpu::SType::SurfaceSourceWindowsHWND: {
            auto* subDesc = descriptor.Get<SurfaceSourceWindowsHWND>();
            mType = Type::WindowsHWND;
            mHInstance = subDesc->hinstance;
            mHWND = subDesc->hwnd;
            break;
        }
#if defined(DAWN_USE_WINDOWS_UI)
        case wgpu::SType::SurfaceDescriptorFromWindowsCoreWindow: {
            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsCoreWindow>();
            mType = Type::WindowsCoreWindow;
            mCoreWindow = static_cast<IUnknown*>(subDesc->coreWindow);
            break;
        }
        case wgpu::SType::SurfaceDescriptorFromWindowsSwapChainPanel: {
            auto* subDesc = descriptor.Get<SurfaceDescriptorFromWindowsSwapChainPanel>();
            mType = Type::WindowsSwapChainPanel;
            mSwapChainPanel = static_cast<IUnknown*>(subDesc->swapChainPanel);
            break;
        }
#endif  // defined(DAWN_USE_WINDOWS_UI)
        case wgpu::SType::SurfaceSourceWaylandSurface: {
            auto* subDesc = descriptor.Get<SurfaceSourceWaylandSurface>();
            mType = Type::WaylandSurface;
            mWaylandDisplay = subDesc->display;
            mWaylandSurface = subDesc->surface;
            break;
        }
        case wgpu::SType::SurfaceSourceXlibWindow: {
            auto* subDesc = descriptor.Get<SurfaceSourceXlibWindow>();
            mType = Type::XlibWindow;
            mXDisplay = subDesc->display;
            mXWindow = subDesc->window;
            break;
        }
        default:
            DAWN_UNREACHABLE();
    }
}

Surface::~Surface() {
    if (mSwapChain != nullptr) {
        [[maybe_unused]] bool error = mInstance->ConsumedError(Unconfigure());
    }

    if (mRecycledSwapChain != nullptr) {
        mRecycledSwapChain->DetachFromSurface();
        mRecycledSwapChain = nullptr;
    }
}

InstanceBase* Surface::GetInstance() const {
    return mInstance.Get();
}

DeviceBase* Surface::GetCurrentDevice() const {
    return mCurrentDevice.Get();
}

Surface::Type Surface::GetType() const {
    DAWN_ASSERT(!IsError());
    return mType;
}

void* Surface::GetAndroidNativeWindow() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::AndroidWindow);
    return mAndroidNativeWindow;
}

void* Surface::GetMetalLayer() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::MetalLayer);
    return mMetalLayer;
}

void* Surface::GetWaylandDisplay() const {
    DAWN_ASSERT(mType == Type::WaylandSurface);
    return mWaylandDisplay;
}

void* Surface::GetWaylandSurface() const {
    DAWN_ASSERT(mType == Type::WaylandSurface);
    return mWaylandSurface;
}

void* Surface::GetHInstance() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::WindowsHWND);
    return mHInstance;
}
void* Surface::GetHWND() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::WindowsHWND);
    return mHWND;
}

IUnknown* Surface::GetCoreWindow() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::WindowsCoreWindow);
#if defined(DAWN_USE_WINDOWS_UI)
    return mCoreWindow.Get();
#else
    return nullptr;
#endif
}

IUnknown* Surface::GetSwapChainPanel() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::WindowsSwapChainPanel);
#if defined(DAWN_USE_WINDOWS_UI)
    return mSwapChainPanel.Get();
#else
    return nullptr;
#endif
}

void* Surface::GetXDisplay() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::XlibWindow);
    return mXDisplay;
}
uint32_t Surface::GetXWindow() const {
    DAWN_ASSERT(!IsError());
    DAWN_ASSERT(mType == Type::XlibWindow);
    return mXWindow;
}

MaybeError Surface::Configure(const SurfaceConfiguration* configIn) {
    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);

    SurfaceConfiguration config = *configIn;
    mCurrentDevice = config.device;  // next errors are routed to the new device

    DAWN_TRY(mCapabilityCache->WithAdapterCapabilities(
        GetCurrentDevice()->GetAdapter(), this,
        [&](const PhysicalDeviceSurfaceCapabilities& caps) -> MaybeError {
            // The auto alphaMode default to alphaModes[0].
            if (config.alphaMode == wgpu::CompositeAlphaMode::Auto) {
                config.alphaMode = caps.alphaModes[0];
            }

            return ValidateSurfaceConfiguration(GetCurrentDevice(), caps, &config, this);
        }));

    // Reuse either the current swapchain, or the recycled swap chain
    SwapChainBase* previousSwapChain = mSwapChain.Get();
    if (previousSwapChain == nullptr && mRecycledSwapChain != nullptr &&
        mRecycledSwapChain->GetDevice() == config.device) {
        previousSwapChain = mRecycledSwapChain.Get();
    }

    {
        auto deviceLock(GetCurrentDevice()->GetScopedLock());
        ResultOrError<Ref<SwapChainBase>> maybeNewSwapChain =
            GetCurrentDevice()->CreateSwapChain(this, previousSwapChain, &config);

        // Don't keep swap chains older than 1 call to Configure
        if (mRecycledSwapChain) {
            mRecycledSwapChain->DetachFromSurface();
            mRecycledSwapChain = nullptr;
        }

        if (mSwapChain && maybeNewSwapChain.IsSuccess()) {
            mSwapChain->DetachFromSurface();
        }
        DAWN_TRY_ASSIGN(mSwapChain, std::move(maybeNewSwapChain));

        mSwapChain->SetIsAttached();
    }

    return {};
}

MaybeError Surface::Unconfigure() {
    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);

    if (mSwapChain != nullptr) {
        if (mRecycledSwapChain != nullptr) {
            mRecycledSwapChain->DetachFromSurface();
            mRecycledSwapChain = nullptr;
        }
        mRecycledSwapChain = mSwapChain;
        mSwapChain = nullptr;
    }

    return {};
}

MaybeError Surface::GetCapabilities(AdapterBase* adapter, SurfaceCapabilities* capabilities) const {
    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);

    DAWN_TRY(mCapabilityCache->WithAdapterCapabilities(
        adapter, this,
        [&capabilities](const PhysicalDeviceSurfaceCapabilities& caps) -> MaybeError {
            capabilities->nextInChain = nullptr;
            capabilities->usages = caps.usages;
            utils::AllocateApiSeqFromStdVector(&capabilities->formats, &capabilities->formatCount,
                                               caps.formats);
            utils::AllocateApiSeqFromStdVector(&capabilities->presentModes,
                                               &capabilities->presentModeCount, caps.presentModes);
            utils::AllocateApiSeqFromStdVector(&capabilities->alphaModes,
                                               &capabilities->alphaModeCount, caps.alphaModes);
            return {};
        }));

    return {};
}

void APISurfaceCapabilitiesFreeMembers(WGPUSurfaceCapabilities capabilities) {
    utils::FreeApiSeq(&capabilities.formats, &capabilities.formatCount);
    utils::FreeApiSeq(&capabilities.presentModes, &capabilities.presentModeCount);
    utils::FreeApiSeq(&capabilities.alphaModes, &capabilities.alphaModeCount);
}

MaybeError Surface::GetCurrentTexture(SurfaceTexture* surfaceTexture) const {
    surfaceTexture->texture = nullptr;
    surfaceTexture->suboptimal = false;

    surfaceTexture->status = wgpu::SurfaceGetCurrentTextureStatus::Error;
    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);

    surfaceTexture->status = wgpu::SurfaceGetCurrentTextureStatus::DeviceLost;
    DAWN_TRY(GetCurrentDevice()->ValidateIsAlive());

    // Set an error status that will be overwritten if there is a success or some other more
    // specific error.
    surfaceTexture->status = wgpu::SurfaceGetCurrentTextureStatus::Error;

    auto deviceLock(GetCurrentDevice()->GetScopedLock());
    DAWN_TRY_ASSIGN(*surfaceTexture, mSwapChain->GetCurrentTexture());

    return {};
}

MaybeError Surface::Present() {
    DAWN_INVALID_IF(IsError(), "%s is invalid.", this);
    DAWN_INVALID_IF(!mSwapChain.Get(), "%s is not configured.", this);

    auto deviceLock(GetCurrentDevice()->GetScopedLock());
    DAWN_TRY(mSwapChain->Present());

    return {};
}

const std::string& Surface::GetLabel() const {
    return mLabel;
}

void Surface::APIConfigure(const SurfaceConfiguration* config) {
    MaybeError maybeError = Configure(config);
    if (!GetCurrentDevice()) {
        [[maybe_unused]] bool error = mInstance->ConsumedError(std::move(maybeError));
    } else {
        [[maybe_unused]] bool error = GetCurrentDevice()->ConsumedError(
            std::move(maybeError), "calling %s.Configure().", this);
    }
}

wgpu::Status Surface::APIGetCapabilities(AdapterBase* adapter,
                                         SurfaceCapabilities* capabilities) const {
    MaybeError maybeError = GetCapabilities(adapter, capabilities);
    if (!GetCurrentDevice()) {
        return mInstance->ConsumedError(std::move(maybeError)) ? wgpu::Status::Error
                                                               : wgpu::Status::Success;
    } else {
        return GetCurrentDevice()->ConsumedError(std::move(maybeError), "calling %s.Configure().",
                                                 this)
                   ? wgpu::Status::Error
                   : wgpu::Status::Success;
    }
}

void Surface::APIGetCurrentTexture(SurfaceTexture* surfaceTexture) const {
    MaybeError maybeError = GetCurrentTexture(surfaceTexture);
    if (!GetCurrentDevice()) {
        [[maybe_unused]] bool error = mInstance->ConsumedError(std::move(maybeError));
    } else {
        [[maybe_unused]] bool error = GetCurrentDevice()->ConsumedError(std::move(maybeError));
    }
}

void Surface::APIPresent() {
    MaybeError maybeError = Present();
    if (!GetCurrentDevice()) {
        [[maybe_unused]] bool error = mInstance->ConsumedError(std::move(maybeError));
    } else {
        [[maybe_unused]] bool error = GetCurrentDevice()->ConsumedError(std::move(maybeError));
    }
}

void Surface::APIUnconfigure() {
    MaybeError maybeError = Unconfigure();
    if (!GetCurrentDevice()) {
        [[maybe_unused]] bool error = mInstance->ConsumedError(std::move(maybeError));
    } else {
        [[maybe_unused]] bool error = GetCurrentDevice()->ConsumedError(std::move(maybeError));
    }
}

void Surface::APISetLabel(StringView label) {
    mLabel = utils::NormalizeMessageString(label);
}

}  // namespace dawn::native
