/*
 * Copyright (C) 2018 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 "VkInteropFunctorDrawable.h"
#include <private/hwui/DrawGlInfo.h>

#include <utils/Color.h>
#include <utils/Trace.h>
#include <utils/TraceUtils.h>
#include <thread>
#include "renderthread/EglManager.h"
#include "thread/ThreadBase.h"
#include "utils/TimeUtils.h"

#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <GLES3/gl3.h>

#include <utils/GLUtils.h>

namespace android {
namespace uirenderer {
namespace skiapipeline {

static renderthread::EglManager sEglManager;

// ScopedDrawRequest makes sure a GL thread is started and EGL context is initialized on it.
class ScopedDrawRequest {
public:
    ScopedDrawRequest() { beginDraw(); }

private:
    void beginDraw() {
        if (!sEglManager.hasEglContext()) {
            sEglManager.initialize();
        }
    }
};

void VkInteropFunctorDrawable::vkInvokeFunctor(Functor* functor) {
    ScopedDrawRequest _drawRequest{};
    EGLDisplay display = sEglManager.eglDisplay();
    DrawGlInfo::Mode mode = DrawGlInfo::kModeProcessNoContext;
    if (display != EGL_NO_DISPLAY) {
        mode = DrawGlInfo::kModeProcess;
    }
    (*functor)(mode, nullptr);
}

#define FENCE_TIMEOUT 2000000000

void VkInteropFunctorDrawable::onDraw(SkCanvas* canvas) {
    ATRACE_CALL();

    if (canvas->getGrContext() == nullptr) {
        SkDEBUGF(("Attempting to draw VkInteropFunctor into an unsupported surface"));
        return;
    }

    ScopedDrawRequest _drawRequest{};

    SkImageInfo surfaceInfo = canvas->imageInfo();

    if (!mFrameBuffer.get() || mFBInfo != surfaceInfo) {
        // Buffer will be used as an OpenGL ES render target.
        mFrameBuffer = new GraphicBuffer(
                // TODO: try to reduce the size of the buffer: possibly by using clip bounds.
                static_cast<uint32_t>(surfaceInfo.width()),
                static_cast<uint32_t>(surfaceInfo.height()),
                ColorTypeToPixelFormat(surfaceInfo.colorType()),
                GraphicBuffer::USAGE_HW_TEXTURE | GraphicBuffer::USAGE_SW_WRITE_NEVER |
                        GraphicBuffer::USAGE_SW_READ_NEVER | GraphicBuffer::USAGE_HW_RENDER,
                std::string("VkInteropFunctorDrawable::onDraw pid [") + std::to_string(getpid()) +
                        "]");
        status_t error = mFrameBuffer->initCheck();
        if (error < 0) {
            ALOGW("VkInteropFunctorDrawable::onDraw() failed in GraphicBuffer.create()");
            return;
        }

        mFBInfo = surfaceInfo;
    }

    // TODO: Synchronization is needed on mFrameBuffer to guarantee that the previous Vulkan
    // TODO: draw command has completed.
    // TODO: A simple but inefficient way is to flush and issue a QueueWaitIdle call. See
    // TODO: GrVkGpu::destroyResources() for example.
    {
        ATRACE_FORMAT("WebViewDraw_%dx%d", mFBInfo.width(), mFBInfo.height());
        EGLDisplay display = sEglManager.eglDisplay();
        LOG_ALWAYS_FATAL_IF(display == EGL_NO_DISPLAY, "Failed to get EGL_DEFAULT_DISPLAY! err=%s",
                            uirenderer::renderthread::EglManager::eglErrorString());
        // We use an EGLImage to access the content of the GraphicBuffer
        // The EGL image is later bound to a 2D texture
        EGLClientBuffer clientBuffer = (EGLClientBuffer)mFrameBuffer->getNativeBuffer();
        AutoEglImage autoImage(display, clientBuffer);
        if (autoImage.image == EGL_NO_IMAGE_KHR) {
            ALOGW("Could not create EGL image, err =%s",
                  uirenderer::renderthread::EglManager::eglErrorString());
            return;
        }

        AutoSkiaGlTexture glTexture;
        glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, autoImage.image);
        GL_CHECKPOINT(MODERATE);

        glBindTexture(GL_TEXTURE_2D, 0);

        DrawGlInfo info;
        SkMatrix44 mat4(canvas->getTotalMatrix());
        SkIRect clipBounds = canvas->getDeviceClipBounds();

        info.clipLeft = clipBounds.fLeft;
        info.clipTop = clipBounds.fTop;
        info.clipRight = clipBounds.fRight;
        info.clipBottom = clipBounds.fBottom;
        info.isLayer = true;
        info.width = mFBInfo.width();
        info.height = mFBInfo.height();
        mat4.asColMajorf(&info.transform[0]);

        glViewport(0, 0, info.width, info.height);

        AutoGLFramebuffer glFb;
        // Bind texture to the frame buffer.
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                               glTexture.mTexture, 0);
        if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
            ALOGE("Failed framebuffer check for created target buffer: %s",
                  GLUtils::getGLFramebufferError());
            return;
        }

        glDisable(GL_STENCIL_TEST);
        glDisable(GL_SCISSOR_TEST);
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT);

        if (mAnyFunctor.index() == 0) {
            std::get<0>(mAnyFunctor).handle->drawGl(info);
        } else {
            (*(std::get<1>(mAnyFunctor).functor))(DrawGlInfo::kModeDraw, &info);
        }

        EGLSyncKHR glDrawFinishedFence =
                eglCreateSyncKHR(eglGetCurrentDisplay(), EGL_SYNC_FENCE_KHR, NULL);
        LOG_ALWAYS_FATAL_IF(glDrawFinishedFence == EGL_NO_SYNC_KHR,
                            "Could not create sync fence %#x", eglGetError());
        glFlush();
        // TODO: export EGLSyncKHR in file descr
        // TODO: import file desc in Vulkan Semaphore
        // TODO: instead block the GPU: probably by using external Vulkan semaphore.
        // Block the CPU until the glFlush finish.
        EGLint waitStatus = eglClientWaitSyncKHR(display, glDrawFinishedFence, 0, FENCE_TIMEOUT);
        LOG_ALWAYS_FATAL_IF(waitStatus != EGL_CONDITION_SATISFIED_KHR,
                            "Failed to wait for the fence %#x", eglGetError());
        eglDestroySyncKHR(display, glDrawFinishedFence);
    }

    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrcOver);
    canvas->save();
    // The size of the image matches the size of the canvas. We've used the matrix already, while
    // drawing into the offscreen surface, so we need to reset it here.
    canvas->resetMatrix();

    auto functorImage = SkImage::MakeFromAHardwareBuffer(
            reinterpret_cast<AHardwareBuffer*>(mFrameBuffer.get()), kPremul_SkAlphaType, nullptr,
            kBottomLeft_GrSurfaceOrigin);
    canvas->drawImage(functorImage, 0, 0, &paint);
    canvas->restore();
}

VkInteropFunctorDrawable::~VkInteropFunctorDrawable() {
    if (auto lp = std::get_if<LegacyFunctor>(&mAnyFunctor)) {
        if (lp->listener) {
            ScopedDrawRequest _drawRequest{};
            lp->listener->onGlFunctorReleased(lp->functor);
        }
    }
}

void VkInteropFunctorDrawable::syncFunctor(const WebViewSyncData& data) const {
    ScopedDrawRequest _drawRequest{};
    FunctorDrawable::syncFunctor(data);
}

}  // namespace skiapipeline
}  // namespace uirenderer
}  // namespace android
