/*
 * 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 <include/android/SkSurfaceAndroid.h>
#include <GrDirectContext.h>
#include <SkSurface.h>
#include <algorithm>

#include <gui/TraceUtils.h>
#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;
    }

    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 */
