/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * 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 "VulkanSurface.h"

#include <SkSurface.h>
#include <gui/TraceUtils.h>
#include <include/android/SkSurfaceAndroid.h>
#include <include/gpu/ganesh/GrDirectContext.h>

#include <algorithm>

#include "VulkanManager.h"
#include "utils/Color.h"

namespace android {
namespace uirenderer {
namespace renderthread {

static constexpr auto P3_XRB = static_cast<android_dataspace>(
        ADATASPACE_STANDARD_DCI_P3 | ADATASPACE_TRANSFER_SRGB | ADATASPACE_RANGE_EXTENDED);

static int InvertTransform(int transform) {
    switch (transform) {
        case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
            return ANATIVEWINDOW_TRANSFORM_ROTATE_270;
        case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
            return ANATIVEWINDOW_TRANSFORM_ROTATE_180;
        case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
            return ANATIVEWINDOW_TRANSFORM_ROTATE_90;
        default:
            return 0;
    }
}

static SkMatrix GetPreTransformMatrix(SkISize windowSize, int transform) {
    const int width = windowSize.width();
    const int height = windowSize.height();

    switch (transform) {
        case 0:
            return SkMatrix::I();
        case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
            return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
        case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
            return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
        case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
            return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
        default:
            LOG_ALWAYS_FATAL("Unsupported Window Transform (%d)", transform);
    }
    return SkMatrix::I();
}

static SkM44 GetPixelSnapMatrix(SkISize windowSize, int transform) {
    // Small (~1/16th) nudge to ensure that pixel-aligned non-AA'd draws fill the
    // desired fragment
    static const SkScalar kOffset = 0.063f;
    SkMatrix preRotation = GetPreTransformMatrix(windowSize, transform);
    SkMatrix invert;
    LOG_ALWAYS_FATAL_IF(!preRotation.invert(&invert));
    return SkM44::Translate(kOffset, kOffset)
            .postConcat(SkM44(preRotation))
            .preConcat(SkM44(invert));
}

static bool ConnectAndSetWindowDefaults(ANativeWindow* window) {
    ATRACE_CALL();

    int err = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
    if (err != 0) {
        ALOGE("native_window_api_connect failed: %s (%d)", strerror(-err), err);
        return false;
    }

    // this will match what we do on GL so pick that here.
    err = window->setSwapInterval(window, 1);
    if (err != 0) {
        ALOGE("native_window->setSwapInterval(1) failed: %s (%d)", strerror(-err), err);
        return false;
    }

    err = native_window_set_shared_buffer_mode(window, false);
    if (err != 0) {
        ALOGE("native_window_set_shared_buffer_mode(false) failed: %s (%d)", strerror(-err), err);
        return false;
    }

    err = native_window_set_auto_refresh(window, false);
    if (err != 0) {
        ALOGE("native_window_set_auto_refresh(false) failed: %s (%d)", strerror(-err), err);
        return false;
    }

    err = native_window_set_scaling_mode(window, NATIVE_WINDOW_SCALING_MODE_FREEZE);
    if (err != 0) {
        ALOGE("native_window_set_scaling_mode(NATIVE_WINDOW_SCALING_MODE_FREEZE) failed: %s (%d)",
              strerror(-err), err);
        return false;
    }

    // Let consumer drive the size of the buffers.
    err = native_window_set_buffers_dimensions(window, 0, 0);
    if (err != 0) {
        ALOGE("native_window_set_buffers_dimensions(0,0) failed: %s (%d)", strerror(-err), err);
        return false;
    }

    // Enable auto prerotation, so when buffer size is driven by the consumer
    // and the transform hint specifies a 90 or 270 degree rotation, the width
    // and height used for buffer pre-allocation and dequeueBuffer will be
    // additionally swapped.
    err = native_window_set_auto_prerotation(window, true);
    if (err != 0) {
        ALOGE("VulkanSurface::UpdateWindow() native_window_set_auto_prerotation failed: %s (%d)",
              strerror(-err), err);
        return false;
    }

    return true;
}

VulkanSurface* VulkanSurface::Create(ANativeWindow* window, ColorMode colorMode,
                                     SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
                                     GrDirectContext* grContext, const VulkanManager& vkManager,
                                     uint32_t extraBuffers) {
    // Connect and set native window to default configurations.
    if (!ConnectAndSetWindowDefaults(window)) {
        return nullptr;
    }

    // Initialize WindowInfo struct.
    WindowInfo windowInfo;
    if (!InitializeWindowInfoStruct(window, colorMode, colorType, colorSpace, vkManager,
                                    extraBuffers, &windowInfo)) {
        return nullptr;
    }

    // Now we attempt to modify the window.
    if (!UpdateWindow(window, windowInfo)) {
        return nullptr;
    }

    return new VulkanSurface(window, windowInfo, grContext);
}

bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
                                               SkColorType colorType,
                                               sk_sp<SkColorSpace> colorSpace,
                                               const VulkanManager& vkManager,
                                               uint32_t extraBuffers, WindowInfo* outWindowInfo) {
    ATRACE_CALL();

    int width, height;
    int err = window->query(window, NATIVE_WINDOW_DEFAULT_WIDTH, &width);
    if (err != 0 || width < 0) {
        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, width);
        return false;
    }
    err = window->query(window, NATIVE_WINDOW_DEFAULT_HEIGHT, &height);
    if (err != 0 || height < 0) {
        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, height);
        return false;
    }
    outWindowInfo->size = SkISize::Make(width, height);

    int query_value;
    err = window->query(window, NATIVE_WINDOW_TRANSFORM_HINT, &query_value);
    if (err != 0 || query_value < 0) {
        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
        return false;
    }
    outWindowInfo->transform = query_value;

    outWindowInfo->actualSize = outWindowInfo->size;
    if (outWindowInfo->transform & ANATIVEWINDOW_TRANSFORM_ROTATE_90) {
        outWindowInfo->actualSize.set(outWindowInfo->size.height(), outWindowInfo->size.width());
    }

    outWindowInfo->preTransform =
            GetPreTransformMatrix(outWindowInfo->size, outWindowInfo->transform);
    outWindowInfo->pixelSnapMatrix =
            GetPixelSnapMatrix(outWindowInfo->size, outWindowInfo->transform);

    err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
    if (err != 0 || query_value < 0) {
        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
        return false;
    }
    outWindowInfo->bufferCount =
            static_cast<uint32_t>(query_value) + sTargetBufferCount + extraBuffers;

    err = window->query(window, NATIVE_WINDOW_MAX_BUFFER_COUNT, &query_value);
    if (err != 0 || query_value < 0) {
        ALOGE("window->query failed: %s (%d) value=%d", strerror(-err), err, query_value);
        return false;
    }
    if (outWindowInfo->bufferCount > static_cast<uint32_t>(query_value)) {
        // Application must settle for fewer images than desired:
        outWindowInfo->bufferCount = static_cast<uint32_t>(query_value);
    }

    outWindowInfo->bufferFormat = ColorTypeToBufferFormat(colorType);
    outWindowInfo->colorspace = colorSpace;
    outWindowInfo->colorMode = colorMode;

    if (colorMode == ColorMode::Hdr || colorMode == ColorMode::Hdr10) {
        outWindowInfo->dataspace = P3_XRB;
    } else {
        outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
    }
    LOG_ALWAYS_FATAL_IF(
            outWindowInfo->dataspace == HAL_DATASPACE_UNKNOWN && colorType != kAlpha_8_SkColorType,
            "Unsupported colorspace");

    VkFormat vkPixelFormat;
    switch (colorType) {
        case kRGBA_8888_SkColorType:
            vkPixelFormat = VK_FORMAT_R8G8B8A8_UNORM;
            break;
        case kRGBA_F16_SkColorType:
            vkPixelFormat = VK_FORMAT_R16G16B16A16_SFLOAT;
            break;
        case kRGBA_1010102_SkColorType:
            vkPixelFormat = VK_FORMAT_A2B10G10R10_UNORM_PACK32;
            break;
        case kAlpha_8_SkColorType:
            vkPixelFormat = VK_FORMAT_R8_UNORM;
            break;
        default:
            LOG_ALWAYS_FATAL("Unsupported colorType: %d", (int)colorType);
    }

    LOG_ALWAYS_FATAL_IF(nullptr == vkManager.mGetPhysicalDeviceImageFormatProperties2,
                        "vkGetPhysicalDeviceImageFormatProperties2 is missing");
    VkPhysicalDeviceExternalImageFormatInfo externalImageFormatInfo;
    externalImageFormatInfo.sType =
            VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_IMAGE_FORMAT_INFO;
    externalImageFormatInfo.pNext = nullptr;
    externalImageFormatInfo.handleType =
            VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID;

    VkPhysicalDeviceImageFormatInfo2 imageFormatInfo;
    imageFormatInfo.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2;
    imageFormatInfo.pNext = &externalImageFormatInfo;
    imageFormatInfo.format = vkPixelFormat;
    imageFormatInfo.type = VK_IMAGE_TYPE_2D;
    imageFormatInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    // Currently Skia requires the images to be color attachments and support all transfer
    // operations.
    imageFormatInfo.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT |
                            VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    imageFormatInfo.flags = 0;

    VkAndroidHardwareBufferUsageANDROID hwbUsage;
    hwbUsage.sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_USAGE_ANDROID;
    hwbUsage.pNext = nullptr;

    VkImageFormatProperties2 imgFormProps;
    imgFormProps.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
    imgFormProps.pNext = &hwbUsage;

    VkResult res = vkManager.mGetPhysicalDeviceImageFormatProperties2(
            vkManager.mPhysicalDevice, &imageFormatInfo, &imgFormProps);
    if (VK_SUCCESS != res) {
        ALOGE("Failed to query GetPhysicalDeviceImageFormatProperties2");
        return false;
    }

    uint64_t consumerUsage;
    err = native_window_get_consumer_usage(window, &consumerUsage);
    if (err != 0) {
        ALOGE("native_window_get_consumer_usage failed: %s (%d)", strerror(-err), err);
        return false;
    }
    outWindowInfo->windowUsageFlags = consumerUsage | hwbUsage.androidHardwareBufferUsage;

    return true;
}

bool VulkanSurface::UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo) {
    ATRACE_CALL();

    int err = native_window_set_buffers_format(window, windowInfo.bufferFormat);
    if (err != 0) {
        ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_format(%d) failed: %s (%d)",
              windowInfo.bufferFormat, strerror(-err), err);
        return false;
    }

    err = native_window_set_buffers_data_space(window, windowInfo.dataspace);
    if (err != 0) {
        ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_data_space(%d) "
              "failed: %s (%d)",
              windowInfo.dataspace, strerror(-err), err);
        return false;
    }

    // native_window_set_buffers_transform() expects the transform the app is requesting that
    // the compositor perform during composition. With native windows, pre-transform works by
    // rendering with the same transform the compositor is applying (as in Vulkan), but
    // then requesting the inverse transform, so that when the compositor does
    // it's job the two transforms cancel each other out and the compositor ends
    // up applying an identity transform to the app's buffer.
    err = native_window_set_buffers_transform(window, InvertTransform(windowInfo.transform));
    if (err != 0) {
        ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_transform(%d) "
              "failed: %s (%d)",
              windowInfo.transform, strerror(-err), err);
        return false;
    }

    // If bufferCount == 1 then we're in shared buffer mode and we cannot actually call
    // set_buffer_count, it'll just fail.
    if (windowInfo.bufferCount > 1) {
        err = native_window_set_buffer_count(window, windowInfo.bufferCount);
        if (err != 0) {
            ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffer_count(%zu) failed: %s "
                  "(%d)",
                  windowInfo.bufferCount, strerror(-err), err);
            return false;
        }
    }

    err = native_window_set_usage(window, windowInfo.windowUsageFlags);
    if (err != 0) {
        ALOGE("VulkanSurface::UpdateWindow() native_window_set_usage failed: %s (%d)",
              strerror(-err), err);
        return false;
    }

    return true;
}

VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
                             GrDirectContext* grContext)
        : mNativeWindow(window), mWindowInfo(windowInfo), mGrContext(grContext) {}

VulkanSurface::~VulkanSurface() {
    releaseBuffers();

    // release the native window to be available for use by other clients
    int err = native_window_api_disconnect(mNativeWindow.get(), NATIVE_WINDOW_API_EGL);
    ALOGW_IF(err != 0, "native_window_api_disconnect failed: %s (%d)", strerror(-err), err);
}

void VulkanSurface::releaseBuffers() {
    for (uint32_t i = 0; i < mWindowInfo.bufferCount; i++) {
        VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i];

        if (bufferInfo.buffer.get() != nullptr && bufferInfo.dequeued) {
            int err = mNativeWindow->cancelBuffer(mNativeWindow.get(), bufferInfo.buffer.get(),
                                                  bufferInfo.dequeue_fence.release());
            if (err != 0) {
                ALOGE("cancelBuffer[%u] failed during destroy: %s (%d)", i, strerror(-err), err);
            }
            bufferInfo.dequeued = false;
            bufferInfo.dequeue_fence.reset();
        }

        LOG_ALWAYS_FATAL_IF(bufferInfo.dequeued);
        LOG_ALWAYS_FATAL_IF(bufferInfo.dequeue_fence.ok());

        bufferInfo.skSurface.reset();
        bufferInfo.buffer.clear();
        bufferInfo.hasValidContents = false;
        bufferInfo.lastPresentedCount = 0;
    }
}

void VulkanSurface::invalidateBuffers() {
    for (uint32_t i = 0; i < mWindowInfo.bufferCount; i++) {
        VulkanSurface::NativeBufferInfo& bufferInfo = mNativeBuffers[i];
        bufferInfo.hasValidContents = false;
        bufferInfo.lastPresentedCount = 0;
    }
}

VulkanSurface::NativeBufferInfo* VulkanSurface::dequeueNativeBuffer() {
    // Set the mCurrentBufferInfo to invalid in case of error and only reset it to the correct
    // value at the end of the function if everything dequeued correctly.
    mCurrentBufferInfo = nullptr;

    // Query the transform hint synced from the initial Surface connect or last queueBuffer. The
    // auto prerotation on the buffer is based on the same transform hint in use by the producer.
    int transformHint = 0;
    int err =
            mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);

    // Since auto pre-rotation is enabled, dequeueBuffer to get the consumer driven buffer size
    // from ANativeWindowBuffer.
    ANativeWindowBuffer* buffer;
    base::unique_fd fence_fd;
    {
        int rawFd = -1;
        err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &rawFd);
        fence_fd.reset(rawFd);
    }
    if (err != 0) {
        ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
        return nullptr;
    }

    SkISize actualSize = SkISize::Make(buffer->width, buffer->height);
    if (actualSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
        if (actualSize != mWindowInfo.actualSize) {
            // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
            // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
            mWindowInfo.actualSize = actualSize;
            releaseBuffers();
        } else {
            // A change in transform means we need to repaint the entire buffer area as the damage
            // rects have just moved about.
            invalidateBuffers();
        }

        if (transformHint != mWindowInfo.transform) {
            err = native_window_set_buffers_transform(mNativeWindow.get(),
                                                      InvertTransform(transformHint));
            if (err != 0) {
                ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", transformHint,
                      strerror(-err), err);
                mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
                return nullptr;
            }
            mWindowInfo.transform = transformHint;
        }

        mWindowInfo.size = actualSize;
        if (mWindowInfo.transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
            mWindowInfo.size.set(actualSize.height(), actualSize.width());
        }

        mWindowInfo.preTransform = GetPreTransformMatrix(mWindowInfo.size, mWindowInfo.transform);
        mWindowInfo.pixelSnapMatrix = GetPixelSnapMatrix(mWindowInfo.size, mWindowInfo.transform);
    }

    uint32_t idx;
    for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
        if (mNativeBuffers[idx].buffer.get() == buffer) {
            mNativeBuffers[idx].dequeued = true;
            mNativeBuffers[idx].dequeue_fence = std::move(fence_fd);
            break;
        } else if (mNativeBuffers[idx].buffer.get() == nullptr) {
            // increasing the number of buffers we have allocated
            mNativeBuffers[idx].buffer = buffer;
            mNativeBuffers[idx].dequeued = true;
            mNativeBuffers[idx].dequeue_fence = std::move(fence_fd);
            break;
        }
    }
    if (idx == mWindowInfo.bufferCount) {
        ALOGE("dequeueBuffer returned unrecognized buffer");
        mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd.release());
        return nullptr;
    }

    VulkanSurface::NativeBufferInfo* bufferInfo = &mNativeBuffers[idx];

    if (bufferInfo->skSurface.get() == nullptr) {
        SkSurfaceProps surfaceProps;
        if (mWindowInfo.colorMode != ColorMode::Default) {
            surfaceProps = SkSurfaceProps(SkSurfaceProps::kAlwaysDither_Flag | surfaceProps.flags(),
                                          surfaceProps.pixelGeometry());
        }
        bufferInfo->skSurface = SkSurfaces::WrapAndroidHardwareBuffer(
                mGrContext, ANativeWindowBuffer_getHardwareBuffer(bufferInfo->buffer.get()),
                kTopLeft_GrSurfaceOrigin, mWindowInfo.colorspace, &surfaceProps,
                /*from_window=*/true);
        if (bufferInfo->skSurface.get() == nullptr) {
            ALOGE("SkSurfaces::WrapAndroidHardwareBuffer failed");
            mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer,
                                        mNativeBuffers[idx].dequeue_fence.release());
            mNativeBuffers[idx].dequeued = false;
            return nullptr;
        }
    }

    mCurrentBufferInfo = bufferInfo;
    return bufferInfo;
}

bool VulkanSurface::presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd) {
    if (!dirtyRect.isEmpty()) {

        // native_window_set_surface_damage takes a rectangle in prerotated space
        // with a bottom-left origin. That is, top > bottom.
        // The dirtyRect is also in prerotated space, so we just need to switch it to
        // a bottom-left origin space.

        SkIRect irect;
        dirtyRect.roundOut(&irect);
        android_native_rect_t aRect;
        aRect.left = irect.left();
        aRect.top = logicalHeight() - irect.top();
        aRect.right = irect.right();
        aRect.bottom = logicalHeight() - irect.bottom();

        int err = native_window_set_surface_damage(mNativeWindow.get(), &aRect, 1);
        ALOGE_IF(err != 0, "native_window_set_surface_damage failed: %s (%d)", strerror(-err), err);
    }

    LOG_ALWAYS_FATAL_IF(!mCurrentBufferInfo);
    VulkanSurface::NativeBufferInfo& currentBuffer = *mCurrentBufferInfo;
    // queueBuffer always closes fence, even on error
    int queuedFd = (semaphoreFd != -1) ? semaphoreFd : currentBuffer.dequeue_fence.release();
    int err = mNativeWindow->queueBuffer(mNativeWindow.get(), currentBuffer.buffer.get(), queuedFd);

    currentBuffer.dequeued = false;
    if (err != 0) {
        ALOGE("queueBuffer failed: %s (%d)", strerror(-err), err);
        // cancelBuffer takes ownership of the fence
        mNativeWindow->cancelBuffer(mNativeWindow.get(), currentBuffer.buffer.get(),
                                    currentBuffer.dequeue_fence.release());
    } else {
        currentBuffer.hasValidContents = true;
        currentBuffer.lastPresentedCount = mPresentCount;
        mPresentCount++;
    }

    currentBuffer.dequeue_fence.reset();

    return err == 0;
}

int VulkanSurface::getCurrentBuffersAge() {
    LOG_ALWAYS_FATAL_IF(!mCurrentBufferInfo);
    VulkanSurface::NativeBufferInfo& currentBuffer = *mCurrentBufferInfo;
    return currentBuffer.hasValidContents ? (mPresentCount - currentBuffer.lastPresentedCount) : 0;
}

void VulkanSurface::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
    mWindowInfo.colorspace = std::move(colorSpace);
    for (int i = 0; i < kNumBufferSlots; i++) {
        mNativeBuffers[i].skSurface.reset();
    }

    if (mWindowInfo.colorMode == ColorMode::Hdr || mWindowInfo.colorMode == ColorMode::Hdr10) {
        mWindowInfo.dataspace = P3_XRB;
    } else {
        mWindowInfo.dataspace = ColorSpaceToADataSpace(
                mWindowInfo.colorspace.get(), BufferFormatToColorType(mWindowInfo.bufferFormat));
    }
    LOG_ALWAYS_FATAL_IF(mWindowInfo.dataspace == HAL_DATASPACE_UNKNOWN &&
                                mWindowInfo.bufferFormat != AHARDWAREBUFFER_FORMAT_R8_UNORM,
                        "Unsupported colorspace");

    if (mNativeWindow) {
        int err = ANativeWindow_setBuffersDataSpace(mNativeWindow.get(), mWindowInfo.dataspace);
        if (err != 0) {
            ALOGE("VulkanSurface::setColorSpace() native_window_set_buffers_data_space(%d) "
                  "failed: %s (%d)",
                  mWindowInfo.dataspace, strerror(-err), err);
        }
    }
}

} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
