/*
 * Copyright (C) 2013 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 "RenderProxy.h"

#include <SkBitmap.h>
#include <SkImage.h>
#include <SkPicture.h>
#include <gui/TraceUtils.h>
#include <pthread.h>
#include "utils/Thread.h"

#ifdef __ANDROID__
#include <gui/BLASTBufferQueue.h>
#include <gui/SurfaceControl.h>
#endif

#include <ui/GraphicBufferAllocator.h>

#include "DeferredLayerUpdater.h"
#include "DisplayList.h"
#include "Properties.h"
#include "Readback.h"
#include "Rect.h"
#include "WebViewFunctorManager.h"
#include "renderthread/CanvasContext.h"
#include "renderthread/RenderTask.h"
#include "renderthread/RenderThread.h"
#include "utils/Macros.h"
#include "utils/TimeUtils.h"

namespace android {
namespace uirenderer {
namespace renderthread {

RenderProxy::RenderProxy(bool translucent, RenderNode* rootRenderNode,
                         IContextFactory* contextFactory, bool useIpcCanvas)
        : mRenderThread(RenderThread::getInstance()), mContext(nullptr) {
#ifdef __ANDROID__
    pid_t uiThreadId = pthread_gettid_np(pthread_self());
#else
    pid_t uiThreadId = 0;
#endif
    pid_t renderThreadId = getRenderThreadTid();
    mContext = mRenderThread.queue().runSync([=, this]() -> CanvasContext* {
        CanvasContext* context =
                CanvasContext::create(mRenderThread, translucent, rootRenderNode, contextFactory,
                                      uiThreadId, renderThreadId, useIpcCanvas);
        if (context != nullptr) {
            mRenderThread.queue().post([=] { context->startHintSession(); });
        }
        return context;
    });
    mDrawFrameTask.setContext(&mRenderThread, mContext, rootRenderNode);
}

RenderProxy::~RenderProxy() {
    destroyContext();
}

void RenderProxy::destroyContext() {
    if (mContext) {
        mDrawFrameTask.setContext(nullptr, nullptr, nullptr);
        // This is also a fence as we need to be certain that there are no
        // outstanding mDrawFrame tasks posted before it is destroyed
        mRenderThread.queue().runSync([this]() { delete mContext; });
        mContext = nullptr;
    }
}

void RenderProxy::setSwapBehavior(SwapBehavior swapBehavior) {
    mRenderThread.queue().post([this, swapBehavior]() { mContext->setSwapBehavior(swapBehavior); });
}

bool RenderProxy::loadSystemProperties() {
    return mRenderThread.queue().runSync([this]() -> bool {
        bool needsRedraw = Properties::load();
        if (mContext->profiler().consumeProperties()) {
            needsRedraw = true;
        }
        return needsRedraw;
    });
}

void RenderProxy::setName(const char* name) {
    // block since name/value pointers owned by caller
    // TODO: Support move arguments
    mRenderThread.queue().runSync([this, name]() { mContext->setName(std::string(name)); });
}

void RenderProxy::setHardwareBuffer(AHardwareBuffer* buffer) {
#ifdef __ANDROID__
    if (buffer) {
        AHardwareBuffer_acquire(buffer);
    }
    mRenderThread.queue().post([this, hardwareBuffer = buffer]() mutable {
        mContext->setHardwareBuffer(hardwareBuffer);
        if (hardwareBuffer) {
            AHardwareBuffer_release(hardwareBuffer);
        }
    });
#endif
}

void RenderProxy::setSurface(ANativeWindow* window, bool enableTimeout) {
    if (window) { ANativeWindow_acquire(window); }
    mRenderThread.queue().post([this, win = window, enableTimeout]() mutable {
        mContext->setSurface(win, enableTimeout);
        if (win) { ANativeWindow_release(win); }
    });
}

void RenderProxy::setSurfaceControl(sp<SurfaceControl> surfaceControl) {
#ifdef __ANDROID__
    mRenderThread.queue().post([this, control = std::move(surfaceControl)]() mutable {
        mContext->setSurfaceControl(std::move(control));
    });
#endif
}

/**
 * Sync methods below execute directly on the calling thread, and so
 * setBLASTBufferQueue also does.
 */
void RenderProxy::setBLASTBufferQueue(const sp<BLASTBufferQueue>& bbq) {
#ifdef __ANDROID__
    mContext->setBLASTBufferQueue(std::move(bbq));
#endif
}

#ifdef __ANDROID__
void RenderProxy::setCornerRadiiCallback(
        std::function<void(const gui::CornerRadii&)> cornerRadiiCallback) {
    mContext->setCornerRadiiCallback(std::move(cornerRadiiCallback));
}

void RenderProxy::setWaitForBufferReleaseCallback(std::function<void(int64_t)> callback) {
    mContext->setWaitForBufferReleaseCallback(std::move(callback));
}

void RenderProxy::mergeWithNextTransaction(SurfaceComposerClient::Transaction* t,
                                           uint64_t frameNumber) {
    mContext->mergeWithNextTransaction(t, frameNumber);
}

bool RenderProxy::syncNextTransaction(std::function<void(SurfaceComposerClient::Transaction*)> t,
                                      bool acquireSingleBuffer) {
    return mContext->syncNextTransaction(t, acquireSingleBuffer);
}

void RenderProxy::applyPendingTransactions(uint64_t frameNumber) {
    mContext->applyPendingTransactions(frameNumber);
}

void RenderProxy::clearSyncTransaction() {
    mContext->clearSyncTransaction();
}

SurfaceComposerClient::Transaction* RenderProxy::gatherPendingTransactions(uint64_t frameNumber) {
    return mContext->gatherPendingTransactions(frameNumber);
}
#endif

void RenderProxy::updateRenderTargetSize(uint64_t width, uint64_t height) {
    return mRenderThread.queue().post([this, width, height]() {
        mContext->updateRenderTargetSize(width, height);
    });
}

void RenderProxy::allocateBuffers() {
    mRenderThread.queue().post([this]() { mContext->allocateBuffers(); });
}

bool RenderProxy::pause() {
    return mRenderThread.queue().runSync([this]() -> bool { return mContext->pauseSurface(); });
}

void RenderProxy::setStopped(bool stopped) {
    mRenderThread.queue().runSync([this, stopped]() { mContext->setStopped(stopped); });
}

void RenderProxy::setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha) {
    mRenderThread.queue().post(
            [=, this]() { mContext->setLightAlpha(ambientShadowAlpha, spotShadowAlpha); });
}

void RenderProxy::setLightGeometry(const Vector3& lightCenter, float lightRadius) {
    mRenderThread.queue().post(
            [=, this]() { mContext->setLightGeometry(lightCenter, lightRadius); });
}

void RenderProxy::setOpaque(bool opaque) {
    mRenderThread.queue().post([=, this]() { mContext->setOpaque(opaque); });
}

void RenderProxy::setHintSessionEnabled(bool enabled) {
    mRenderThread.queue().post([=, this]() { mContext->setHintSessionEnabled(enabled); });
}

float RenderProxy::setColorMode(ColorMode mode) {
    // We only need to figure out what the renderer supports for HDR, otherwise this can stay
    // an async call since we already know the return value
    if (mode == ColorMode::Hdr || mode == ColorMode::Hdr10) {
        return mRenderThread.queue().runSync(
                [=, this]() -> float { return mContext->setColorMode(mode); });
    } else {
        mRenderThread.queue().post([=, this]() { mContext->setColorMode(mode); });
        return 1.f;
    }
}

void RenderProxy::setRenderSdrHdrRatio(float ratio) {
    mDrawFrameTask.setRenderSdrHdrRatio(ratio);
}

int64_t* RenderProxy::frameInfo() {
    return mDrawFrameTask.frameInfo();
}

void RenderProxy::forceDrawNextFrame() {
    mDrawFrameTask.forceDrawNextFrame();
}

int RenderProxy::syncAndDrawFrame() {
    return mDrawFrameTask.drawFrame();
}

void RenderProxy::destroy() {
    // destroyCanvasAndSurface() needs a fence as when it returns the
    // underlying BufferQueue is going to be released from under
    // the render thread.
    mRenderThread.queue().runSync([this]() { mContext->destroy(); });
}

void RenderProxy::destroyFunctor(int functor) {
    ATRACE_CALL();
    RenderThread& thread = RenderThread::getInstance();
    thread.queue().post([=]() { WebViewFunctorManager::instance().destroyFunctor(functor); });
}

DeferredLayerUpdater* RenderProxy::createTextureLayer() {
    return mRenderThread.queue().runSync([this]() -> auto {
        return mContext->createTextureLayer();
    });
}

void RenderProxy::buildLayer(RenderNode* node) {
    mRenderThread.queue().runSync([&]() { mContext->buildLayer(node); });
}

bool RenderProxy::copyLayerInto(DeferredLayerUpdater* layer, SkBitmap& bitmap) {
    ATRACE_NAME("RenderProxy#copyLayerInto readback");
    auto& thread = RenderThread::getInstance();
    return thread.queue().runSync([&]() -> bool {
        return thread.readback().copyLayerInto(layer, &bitmap) == CopyResult::Success;
    });
}

void RenderProxy::pushLayerUpdate(DeferredLayerUpdater* layer) {
    mDrawFrameTask.pushLayerUpdate(layer);
}

void RenderProxy::cancelLayerUpdate(DeferredLayerUpdater* layer) {
    mDrawFrameTask.removeLayerUpdate(layer);
}

void RenderProxy::detachSurfaceTexture(DeferredLayerUpdater* layer) {
#ifdef __ANDROID__
    return mRenderThread.queue().runSync([&]() { layer->detachSurfaceTexture(); });
#endif
}

void RenderProxy::destroyHardwareResources() {
    return mRenderThread.queue().runSync([&]() { mContext->destroyHardwareResources(); });
}

void RenderProxy::trimMemory(int level) {
    // Avoid creating a RenderThread to do a trimMemory.
    if (RenderThread::hasInstance()) {
        RenderThread& thread = RenderThread::getInstance();
        const auto trimLevel = static_cast<TrimLevel>(level);
        thread.queue().post([&thread, trimLevel]() { thread.trimMemory(trimLevel); });
    }
}

void RenderProxy::trimCaches(int level) {
    // Avoid creating a RenderThread to do a trimMemory.
    if (RenderThread::hasInstance()) {
        RenderThread& thread = RenderThread::getInstance();
        const auto trimLevel = static_cast<CacheTrimLevel>(level);
        thread.queue().post([&thread, trimLevel]() { thread.trimCaches(trimLevel); });
    }
}

void RenderProxy::purgeCaches() {
    if (RenderThread::hasInstance()) {
        RenderThread& thread = RenderThread::getInstance();
        thread.queue().post([&thread]() {
            if (thread.getGrContext()) {
                thread.cacheManager().trimMemory(TrimLevel::COMPLETE);
            }
        });
    }
}

void RenderProxy::overrideProperty(const char* name, const char* value) {
    // expensive, but block here since name/value pointers owned by caller
    RenderThread::getInstance().queue().runSync(
            [&]() { Properties::overrideProperty(name, value); });
}

void RenderProxy::fence() {
    mRenderThread.queue().runSync([]() {});
}

int RenderProxy::maxTextureSize() {
    static int maxTextureSize = RenderThread::getInstance().queue().runSync(
            []() { return DeviceInfo::get()->maxTextureSize(); });
    return maxTextureSize;
}

void RenderProxy::stopDrawing() {
    mRenderThread.queue().runSync([this]() { mContext->stopDrawing(); });
}

void RenderProxy::notifyFramePending() {
    mRenderThread.queue().post([this]() { mContext->notifyFramePending(); });
}

void RenderProxy::notifyCallbackPending() {
    mRenderThread.queue().post([this]() { mContext->sendCpuLoadResetHint(); });
}

void RenderProxy::notifyExpensiveFrame() {
    mRenderThread.queue().post([this]() { mContext->sendCpuLoadIncreaseHint(); });
}

void RenderProxy::notifyGpuLoadUp() {
    mRenderThread.queue().post([this]() { mContext->sendGpuLoadIncreaseHint(); });
}

void RenderProxy::dumpProfileInfo(int fd, int dumpFlags) {
    mRenderThread.queue().runSync([&]() {
        std::lock_guard lock(mRenderThread.getJankDataMutex());
        mContext->profiler().dumpData(fd);
        if (dumpFlags & DumpFlags::FrameStats) {
            mContext->dumpFrames(fd);
        }
        if (dumpFlags & DumpFlags::JankStats) {
            mRenderThread.globalProfileData()->dump(fd);
        }
        if (dumpFlags & DumpFlags::Reset) {
            mContext->resetFrameStats();
        }
    });
}

void RenderProxy::resetProfileInfo() {
    mRenderThread.queue().runSync([this]() {
        std::lock_guard lock(mRenderThread.getJankDataMutex());
        mContext->resetFrameStats();
    });
}

uint32_t RenderProxy::frameTimePercentile(int percentile) {
    return mRenderThread.queue().runSync([&]() -> auto {
        std::lock_guard lock(mRenderThread.globalProfileData().getDataMutex());
        return mRenderThread.globalProfileData()->findPercentile(percentile);
    });
}

void RenderProxy::dumpGraphicsMemory(int fd, bool includeProfileData, bool resetProfile) {
    if (RenderThread::hasInstance()) {
        auto& thread = RenderThread::getInstance();
        thread.queue().runSync([&]() {
            thread.dumpGraphicsMemory(fd, includeProfileData);
            if (resetProfile) {
                thread.globalProfileData()->reset();
            }
        });
    }
#ifdef __ANDROID__
    if (!Properties::isolatedProcess) {
        std::string grallocInfo;
        GraphicBufferAllocator::getInstance().dump(grallocInfo);
        dprintf(fd, "%s\n", grallocInfo.c_str());
    }
#endif
}

void RenderProxy::getMemoryUsage(size_t* cpuUsage, size_t* gpuUsage) {
    if (RenderThread::hasInstance()) {
        auto& thread = RenderThread::getInstance();
        thread.queue().runSync([&]() { thread.getMemoryUsage(cpuUsage, gpuUsage); });
    }
}

void RenderProxy::setProcessStatsBuffer(int fd) {
    auto& rt = RenderThread::getInstance();
    rt.queue().post([&rt, fd = dup(fd)]() {
        rt.globalProfileData().switchStorageToAshmem(fd);
        close(fd);
    });
}

void RenderProxy::rotateProcessStatsBuffer() {
    auto& rt = RenderThread::getInstance();
    rt.queue().post([&rt]() { rt.globalProfileData().rotateStorage(); });
}

int RenderProxy::getRenderThreadTid() {
#ifdef __ANDROID__
    return mRenderThread.getTid();
#else
    return 0;
#endif
}

void RenderProxy::addRenderNode(RenderNode* node, bool placeFront) {
    mRenderThread.queue().post([=, this]() { mContext->addRenderNode(node, placeFront); });
}

void RenderProxy::removeRenderNode(RenderNode* node) {
    mRenderThread.queue().post([=, this]() { mContext->removeRenderNode(node); });
}

void RenderProxy::drawRenderNode(RenderNode* node) {
    mRenderThread.queue().runSync([=, this]() { mContext->prepareAndDraw(node); });
}

void RenderProxy::setContentDrawBounds(int left, int top, int right, int bottom) {
    mDrawFrameTask.setContentDrawBounds(left, top, right, bottom);
}

void RenderProxy::setHardwareBufferRenderParams(const HardwareBufferRenderParams& params) {
    mDrawFrameTask.setHardwareBufferRenderParams(params);
}

void RenderProxy::setPictureCapturedCallback(
        const std::function<void(sk_sp<SkPicture>&&)>& callback) {
    mRenderThread.queue().post(
            [this, cb = callback]() { mContext->setPictureCapturedCallback(cb); });
}

void RenderProxy::setASurfaceTransactionCallback(
        const std::function<bool(int64_t, int64_t, int64_t)>& callback) {
    mRenderThread.queue().post(
            [this, cb = callback]() { mContext->setASurfaceTransactionCallback(cb); });
}

void RenderProxy::setPrepareSurfaceControlForWebviewCallback(
        const std::function<void()>& callback) {
    mRenderThread.queue().post(
            [this, cb = callback]() { mContext->setPrepareSurfaceControlForWebviewCallback(cb); });
}

void RenderProxy::setFrameCallback(
        std::function<std::function<void(bool)>(int32_t, int64_t)>&& callback) {
    mDrawFrameTask.setFrameCallback(std::move(callback));
}

void RenderProxy::setFrameCommitCallback(std::function<void(bool)>&& callback) {
    mDrawFrameTask.setFrameCommitCallback(std::move(callback));
}

void RenderProxy::setFrameCompleteCallback(std::function<void()>&& callback) {
    mDrawFrameTask.setFrameCompleteCallback(std::move(callback));
}

void RenderProxy::addFrameMetricsObserver(sp<FrameMetricsObserver>&& observer) {
    mRenderThread.queue().post([this, observer = std::move(observer)]() mutable {
        mContext->addFrameMetricsObserver(std::move(observer));
    });
}

void RenderProxy::removeFrameMetricsObserver(sp<FrameMetricsObserver>&& observer) {
    mRenderThread.queue().post([this, observer = std::move(observer)]() {
        mContext->removeFrameMetricsObserver(observer);
    });
}

void RenderProxy::setForceDark(ForceDarkType type) {
    mRenderThread.queue().post([this, type]() { mContext->setForceDark(type); });
}

void RenderProxy::setDrawingEnabled(bool enabled) {
    mRenderThread.queue().post([this, enabled]() { mContext->setDrawingEnabled(enabled); });
}

void RenderProxy::copySurfaceInto(ANativeWindow* window, std::shared_ptr<CopyRequest>&& request) {
    auto& thread = RenderThread::getInstance();
    ANativeWindow_acquire(window);
    thread.queue().post([&thread, window, request = std::move(request)] {
        thread.readback().copySurfaceInto(window, request);
        ANativeWindow_release(window);
    });
}

void RenderProxy::prepareToDraw(Bitmap& bitmap) {
    // If we haven't spun up a hardware accelerated window yet, there's no
    // point in precaching these bitmaps as it can't impact jank.
    // We also don't know if we even will spin up a hardware-accelerated
    // window or not.
    if (!RenderThread::hasInstance()) return;
    RenderThread* renderThread = &RenderThread::getInstance();
    bitmap.ref();
    auto task = [renderThread, &bitmap]() {
        CanvasContext::prepareToDraw(*renderThread, &bitmap);
        bitmap.unref();
    };
    nsecs_t lastVsync = renderThread->timeLord().latestVsync();
    nsecs_t estimatedNextVsync = lastVsync + renderThread->timeLord().frameIntervalNanos();
    nsecs_t timeToNextVsync = estimatedNextVsync - systemTime(SYSTEM_TIME_MONOTONIC);
    // We expect the UI thread to take 4ms and for RT to be active from VSYNC+4ms to
    // VSYNC+12ms or so, so aim for the gap during which RT is expected to
    // be idle
    // TODO: Make this concept a first-class supported thing? RT could use
    // knowledge of pending draws to better schedule this task
    if (timeToNextVsync > -6_ms && timeToNextVsync < 1_ms) {
        renderThread->queue().postAt(estimatedNextVsync + 8_ms, task);
    } else {
        renderThread->queue().post(task);
    }
}

int RenderProxy::copyHWBitmapInto(Bitmap* hwBitmap, SkBitmap* bitmap) {
    ATRACE_NAME("RenderProxy#copyHWBitmapInto readback");
    RenderThread& thread = RenderThread::getInstance();
    if (RenderThread::isCurrent()) {
        // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
        return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap);
    } else {
        return thread.queue().runSync(
                [&]() -> int { return (int)thread.readback().copyHWBitmapInto(hwBitmap, bitmap); });
    }
}

int RenderProxy::copyImageInto(const sk_sp<SkImage>& image, SkBitmap* bitmap) {
    ATRACE_NAME("RenderProxy#copyImageInto readback");
    RenderThread& thread = RenderThread::getInstance();
    if (RenderThread::isCurrent()) {
        // TODO: fix everything that hits this. We should never be triggering a readback ourselves.
        return (int)thread.readback().copyImageInto(image, bitmap);
    } else {
        return thread.queue().runSync(
                [&]() -> int { return (int)thread.readback().copyImageInto(image, bitmap); });
    }
}

void RenderProxy::disableVsync() {
    Properties::disableVsync = true;
}

int RenderProxy::preload() {
    // Create RenderThread object and start the thread. Then preload Vulkan/EGL driver.
    auto& thread = RenderThread::getInstance();
    thread.queue().post([&thread]() { thread.preload(); });
#ifdef __ANDROID__
    return thread.getTid();
#else
    return 0;
#endif
}

void RenderProxy::setRtAnimationsEnabled(bool enabled) {
    if (RenderThread::hasInstance()) {
        RenderThread::getInstance().queue().post(
                [enabled]() { Properties::enableRTAnimations = enabled; });
    } else {
        Properties::enableRTAnimations = enabled;
    }
}

void RenderProxy::setRtAnimationsEnabledForContext(bool enabled) {
    if (RenderThread::hasInstance()) {
        RenderThread& thread = RenderThread::getInstance();
        thread.queue().post(
                [this, enabled]() { mContext->setRtAnimationsEnabled(enabled); });
    }
}

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