/*
 * 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.
 */
#pragma once

#include <system/graphics.h>
#include <system/window.h>
#include <ui/BufferQueueDefs.h>
#include <ui/PixelFormat.h>
#include <vulkan/vulkan.h>

#include <SkRefCnt.h>
#include <SkSize.h>

#include "IRenderPipeline.h"

class SkSurface;

namespace android {
namespace uirenderer {
namespace renderthread {

class VulkanManager;

class VulkanSurface {
public:
    static VulkanSurface* Create(ANativeWindow* window, ColorMode colorMode, SkColorType colorType,
                                 sk_sp<SkColorSpace> colorSpace, GrContext* grContext,
                                 const VulkanManager& vkManager, uint32_t extraBuffers);
    ~VulkanSurface();

    sk_sp<SkSurface> getCurrentSkSurface() {
        return mCurrentBufferInfo ? mCurrentBufferInfo->skSurface : nullptr;
    }
    const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }

private:
    /*
     * All structs/methods in this private section are specifically for use by the VulkanManager
     *
     */
    friend VulkanManager;
    struct NativeBufferInfo {
        sk_sp<SkSurface> skSurface;
        sp<ANativeWindowBuffer> buffer;
        // The fence is only valid when the buffer is dequeued, and should be
        // -1 any other time. When valid, we own the fd, and must ensure it is
        // closed: either by closing it explicitly when queueing the buffer,
        // or by passing ownership e.g. to ANativeWindow::cancelBuffer().
        int dequeue_fence = -1;
        bool dequeued = false;
        uint32_t lastPresentedCount = 0;
        bool hasValidContents = false;
    };

    NativeBufferInfo* dequeueNativeBuffer();
    NativeBufferInfo* getCurrentBufferInfo() { return mCurrentBufferInfo; }
    bool presentCurrentBuffer(const SkRect& dirtyRect, int semaphoreFd);

    // The width and height are are the logical width and height for when submitting draws to the
    // surface. In reality if the window is rotated the underlying window may have the width and
    // height swapped.
    int logicalWidth() const { return mWindowInfo.size.width(); }
    int logicalHeight() const { return mWindowInfo.size.height(); }
    int getCurrentBuffersAge();

private:
    /*
     * All code below this line while logically available to VulkanManager should not be treated
     * as private to this class.
     *
     */

    // How many buffers we want to be able to use ourselves. We want 1 in active rendering with
    // 1 more queued, so 2. This will be added to NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, which is
    // how many buffers the consumer needs (eg, 1 for SurfaceFlinger), getting to a typically
    // triple-buffered queue as a result.
    static constexpr uint32_t sTargetBufferCount = 2;

    struct WindowInfo {
        SkISize size;
        PixelFormat pixelFormat;
        android_dataspace dataspace;
        int transform;
        size_t bufferCount;
        uint64_t windowUsageFlags;

        // size of the ANativeWindow if the inverse of transform requires us to swap width/height
        SkISize actualSize;
        // transform to be applied to the SkSurface to map the coordinates to the provided transform
        SkMatrix preTransform;
    };

    VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrContext* grContext);
    static bool InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
                                           SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
                                           const VulkanManager& vkManager, uint32_t extraBuffers,
                                           WindowInfo* outWindowInfo);
    static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
    void releaseBuffers();

    // TODO: Just use a vector?
    NativeBufferInfo mNativeBuffers[android::BufferQueueDefs::NUM_BUFFER_SLOTS];

    sp<ANativeWindow> mNativeWindow;
    WindowInfo mWindowInfo;
    GrContext* mGrContext;

    uint32_t mPresentCount = 0;
    NativeBufferInfo* mCurrentBufferInfo = nullptr;
};

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