// 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 "SampleApplication.h"

#include "aemu/base/GLObjectCounter.h"
#include "aemu/base/synchronization/ConditionVariable.h"
#include "aemu/base/synchronization/Lock.h"
#include "aemu/base/system/System.h"
#include "aemu/base/threads/FunctorThread.h"
#include "aemu/base/testing/TestSystem.h"
#include "host-common/GraphicsAgentFactory.h"
#include "host-common/multi_display_agent.h"
#include "host-common/MultiDisplay.h"
#include "host-common/opengl/misc.h"
#include "Standalone.h"

#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES3/gl3.h>

namespace gfxstream {

using android::base::AutoLock;
using android::base::ConditionVariable;
using android::base::FunctorThread;
using android::base::Lock;
using android::base::MessageChannel;
using android::base::TestSystem;
using gl::EmulatedEglFenceSync;
using gl::GLESApi;
using gl::GLESApi_3_0;
using gl::GLESApi_CM;

// Class holding the persistent test window.
class TestWindow {
public:
    TestWindow() {
        window = CreateOSWindow();
    }

    ~TestWindow() {
        if (window) {
            window->destroy();
        }
    }

    void setRect(int xoffset, int yoffset, int width, int height) {
        if (mFirstResize) {
            initializeWithRect(xoffset, yoffset, width, height);
        } else {
            resizeWithRect(xoffset, yoffset, width, height);
        }
    }

    // Check on initialization if windows are available.
    bool initializeWithRect(int xoffset, int yoffset, int width, int height) {
        if (!window->initialize("libOpenglRender test", width, height)) {
            window->destroy();
            window = nullptr;
            return false;
        }
        window->setVisible(true);
        window->setPosition(xoffset, yoffset);
        window->messageLoop();
        mFirstResize = false;
        return true;
    }

    void resizeWithRect(int xoffset, int yoffset, int width, int height) {
        if (!window) return;

        window->setPosition(xoffset, yoffset);
        window->resize(width, height);
        window->messageLoop();
    }

    OSWindow* window = nullptr;
private:
    bool mFirstResize = true;
};

static TestWindow* sTestWindow() {
    static TestWindow* w = new TestWindow;
    return w;
}

bool shouldUseHostGpu() {
    bool useHost = android::base::getEnvironmentVariable("ANDROID_EMU_TEST_WITH_HOST_GPU") == "1";

    // Also set the global emugl renderer accordingly.
    if (useHost) {
        emugl::setRenderer(SELECTED_RENDERER_HOST);
    } else {
        emugl::setRenderer(SELECTED_RENDERER_SWIFTSHADER_INDIRECT);
    }

    return useHost;
}

bool shouldUseWindow() {
    bool useWindow = android::base::getEnvironmentVariable("ANDROID_EMU_TEST_WITH_WINDOW") == "1";
    return useWindow;
}

OSWindow* createOrGetTestWindow(int xoffset, int yoffset, int width, int height) {
    if (!shouldUseWindow()) return nullptr;

    sTestWindow()->setRect(xoffset, yoffset, width, height);
    return sTestWindow()->window;
}

class Vsync {
public:
    Vsync(int refreshRate = 60) :
        mRefreshRate(refreshRate),
        mRefreshIntervalUs(1000000ULL / mRefreshRate),
        mThread([this] {
            while (true) {
                if (mShouldStop) return 0;
                android::base::sleepUs(mRefreshIntervalUs);
                AutoLock lock(mLock);
                mSync = 1;
                mCv.signal();
            }
            return 0;
        }) {
        mThread.start();
    }

    ~Vsync() {
        mShouldStop = true;
    }

    void waitUntilNextVsync() {
        AutoLock lock(mLock);
        mSync = 0;
        while (!mSync) {
            mCv.wait(&mLock);
        }
    }

private:
    int mShouldStop = false;
    int mRefreshRate = 60;
    uint64_t mRefreshIntervalUs;
    volatile int mSync = 0;

    Lock mLock;
    ConditionVariable mCv;

    FunctorThread mThread;
};

// app -> SF queue: separate storage, bindTexture blits
// SF queue -> HWC: shared storage
class ColorBufferQueue { // Note: we could have called this BufferQueue but there is another
                         // class of name BufferQueue that does something totally different

  public:
    static constexpr int kCapacity = 3;
    class Item {
      public:
        Item(unsigned int cb = 0, EmulatedEglFenceSync* s = nullptr)
            : colorBuffer(cb), sync(s) { }
        unsigned int colorBuffer = 0;
        EmulatedEglFenceSync* sync = nullptr;
    };

    ColorBufferQueue() = default;

    void queueBuffer(const Item& item) {
        mQueue.send(item);
    }

    void dequeueBuffer(Item* outItem) {
        mQueue.receive(outItem);
    }

  private:
    MessageChannel<Item, kCapacity> mQueue;
};

class AutoComposeDevice {
public:
    AutoComposeDevice(uint32_t targetCb, uint32_t layerCnt = 2) :
      mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer))
    {
        mComposeDevice = reinterpret_cast<ComposeDevice*>(mData.data());
        mComposeDevice->version = 1;
        mComposeDevice->targetHandle = targetCb;
        mComposeDevice->numLayers = layerCnt;
    }

    ComposeDevice* get() {
        return mComposeDevice;
    }

    uint32_t getSize() {
        return mData.size();
    }

    void configureLayer(uint32_t layerId, unsigned int cb,
                        hwc2_composition_t composeMode,
                        hwc_rect_t displayFrame,
                        hwc_frect_t crop,
                        hwc2_blend_mode_t blendMode,
                        float alpha,
                        hwc_color_t color
                        ) {
        mComposeDevice->layer[layerId].cbHandle = cb;
        mComposeDevice->layer[layerId].composeMode = composeMode;
        mComposeDevice->layer[layerId].displayFrame = displayFrame;
        mComposeDevice->layer[layerId].crop = crop;
        mComposeDevice->layer[layerId].blendMode = blendMode;
        mComposeDevice->layer[layerId].alpha = alpha;
        mComposeDevice->layer[layerId].color = color;
        mComposeDevice->layer[layerId].transform = HWC_TRANSFORM_FLIP_H;
    }

private:
    std::vector<uint8_t> mData;
    ComposeDevice* mComposeDevice;
};

extern "C" const QAndroidMultiDisplayAgent* const gMockQAndroidMultiDisplayAgent;

// SampleApplication implementation/////////////////////////////////////////////
SampleApplication::SampleApplication(int windowWidth, int windowHeight, int refreshRate, GLESApi glVersion, bool compose) :
    mWidth(windowWidth), mHeight(windowHeight), mRefreshRate(refreshRate), mIsCompose(compose) {

    // setupStandaloneLibrarySearchPaths();
    emugl::setGLObjectCounter(android::base::GLObjectCounter::get());
    emugl::set_emugl_window_operations(*getGraphicsAgents()->emu);;
    emugl::set_emugl_multi_display_operations(*getGraphicsAgents()->multi_display);
    gl::LazyLoadedEGLDispatch::get();
    if (glVersion == GLESApi_CM) gl::LazyLoadedGLESv1Dispatch::get();
    gl::LazyLoadedGLESv2Dispatch::get();

    bool useHostGpu = shouldUseHostGpu();
    mWindow = createOrGetTestWindow(mXOffset, mYOffset, mWidth, mHeight);
    mUseSubWindow = mWindow != nullptr;

    FrameBuffer::initialize(
            mWidth, mHeight,
            mUseSubWindow,
            !useHostGpu /* egl2egl */);
    mFb = FrameBuffer::getFB();

    if (mUseSubWindow) {
        mFb->setupSubWindow(
            (FBNativeWindowType)(uintptr_t)
            mWindow->getFramebufferNativeWindow(),
            0, 0,
            mWidth, mHeight, mWidth, mHeight,
            mWindow->getDevicePixelRatio(), 0, false, false);
        mWindow->messageLoop();
    }

    mRenderThreadInfo.reset(new RenderThreadInfo());
    mRenderThreadInfo->initGl();

    mColorBuffer = mFb->createColorBuffer(mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE);
    mContext = mFb->createEmulatedEglContext(0, 0, glVersion);
    mSurface = mFb->createEmulatedEglWindowSurface(0, mWidth, mHeight);

    mFb->bindContext(mContext, mSurface, mSurface);
    mFb->setEmulatedEglWindowSurfaceColorBuffer(mSurface, mColorBuffer);

    if (mIsCompose && mTargetCb == 0) {
        mTargetCb = mFb->createColorBuffer(mFb->getWidth(),
                                           mFb->getHeight(),
                                           GL_RGBA,
                                           FRAMEWORK_FORMAT_GL_COMPATIBLE);
        mFb->openColorBuffer(mTargetCb);
    }
 }

SampleApplication::~SampleApplication() {
    if (mFb) {
        if (mTargetCb) {
            mFb->closeColorBuffer(mTargetCb);
        }
        mFb->bindContext(0, 0, 0);
        mFb->closeColorBuffer(mColorBuffer);
        mFb->destroyEmulatedEglWindowSurface(mSurface);
        mFb = nullptr;
        FrameBuffer::finalize();
    }
}

void SampleApplication::rebind() {
    mFb->bindContext(mContext, mSurface, mSurface);
}

void SampleApplication::drawLoop() {
    this->initialize();

    Vsync vsync(mRefreshRate);

    while (true) {
        this->draw();
        mFb->flushEmulatedEglWindowSurfaceColorBuffer(mSurface);
        vsync.waitUntilNextVsync();
        if (mUseSubWindow) {
            mFb->post(mColorBuffer);
            mWindow->messageLoop();
        }
    }
}

EmulatedEglFenceSync* SampleApplication::getFenceSync() {
    uint64_t sync;
    mFb->createEmulatedEglFenceSync(EGL_SYNC_FENCE_KHR, false, &sync);
    return EmulatedEglFenceSync::getFromHandle(sync);
}

void SampleApplication::drawWorkerWithCompose(ColorBufferQueue& app2sfQueue,
                                              ColorBufferQueue& sf2appQueue) {
    ColorBufferQueue::Item appItem = {};
    AutoComposeDevice autoComposeDevice(mTargetCb);
    hwc_rect_t displayFrame = {0, mHeight/2, mWidth, mHeight};
    hwc_frect_t crop = {0.0, 0.0, 0.0, 0.0};
    hwc_color_t color = {200, 0, 0, 255};
    autoComposeDevice.configureLayer(0, 0,
                                     HWC2_COMPOSITION_SOLID_COLOR,
                                     displayFrame,
                                     crop,
                                     HWC2_BLEND_MODE_NONE,
                                     1.0,
                                     color);

    while (true) {
        app2sfQueue.dequeueBuffer(&appItem);
        if (appItem.sync) { appItem.sync->wait(EGL_FOREVER_KHR); }

        hwc_rect_t displayFrame = {0, 0, mWidth, mHeight/2};
        hwc_frect_t crop = {0.0, 0.0, (float)mWidth, (float)mHeight};
        hwc_color_t color = {0, 0, 0, 0};
        autoComposeDevice.configureLayer(1,
                                         appItem.colorBuffer,
                                         HWC2_COMPOSITION_DEVICE,
                                         displayFrame,
                                         crop,
                                         HWC2_BLEND_MODE_PREMULTIPLIED,
                                         0.8,
                                         color);
        mFb->compose(autoComposeDevice.getSize(), autoComposeDevice.get());

        if (appItem.sync) { appItem.sync->decRef(); }
        sf2appQueue.queueBuffer(ColorBufferQueue::Item(appItem.colorBuffer, getFenceSync()));
    }
}

void SampleApplication::drawWorker(ColorBufferQueue& app2sfQueue,
                                   ColorBufferQueue& sf2appQueue,
                                   ColorBufferQueue& sf2hwcQueue,
                                   ColorBufferQueue& hwc2sfQueue) {
    RenderThreadInfo* tInfo = new RenderThreadInfo;
    unsigned int sfContext = mFb->createEmulatedEglContext(0, 0, GLESApi_3_0);
    unsigned int sfSurface = mFb->createEmulatedEglWindowSurface(0, mWidth, mHeight);
    mFb->bindContext(sfContext, sfSurface, sfSurface);

    auto gl = getGlDispatch();

    static constexpr char blitVshaderSrc[] = R"(#version 300 es
    precision highp float;
    layout (location = 0) in vec2 pos;
    layout (location = 1) in vec2 texcoord;
    out vec2 texcoord_varying;
    void main() {
        gl_Position = vec4(pos, 0.0, 1.0);
        texcoord_varying = texcoord;
    })";

    static constexpr char blitFshaderSrc[] = R"(#version 300 es
    precision highp float;
    uniform sampler2D tex;
    in vec2 texcoord_varying;
    out vec4 fragColor;
    void main() {
        fragColor = texture(tex, texcoord_varying);
    })";

    GLint blitProgram =
        compileAndLinkShaderProgram(
            blitVshaderSrc, blitFshaderSrc);

    GLint samplerLoc = gl->glGetUniformLocation(blitProgram, "tex");

    GLuint blitVbo;
    gl->glGenBuffers(1, &blitVbo);
    gl->glBindBuffer(GL_ARRAY_BUFFER, blitVbo);
    const float attrs[] = {
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, -1.0f, 1.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 0.0f,
        -1.0f, -1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 1.0f, 0.0f,
        -1.0f, 1.0f, 0.0f, 0.0f,
    };
    gl->glBufferData(GL_ARRAY_BUFFER, sizeof(attrs), attrs, GL_STATIC_DRAW);
    gl->glEnableVertexAttribArray(0);
    gl->glEnableVertexAttribArray(1);

    gl->glVertexAttribPointer(
        0, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat), 0);
    gl->glVertexAttribPointer(
        1, 2, GL_FLOAT, GL_FALSE, 4 * sizeof(GLfloat),
        (GLvoid*)(uintptr_t)(2 * sizeof(GLfloat)));

    GLuint blitTexture;
    gl->glActiveTexture(GL_TEXTURE0);
    gl->glGenTextures(1, &blitTexture);
    gl->glBindTexture(GL_TEXTURE_2D, blitTexture);

    gl->glUseProgram(blitProgram);
    gl->glUniform1i(samplerLoc, 0);

    ColorBufferQueue::Item appItem = {};
    ColorBufferQueue::Item hwcItem = {};

    while (true) {
        hwc2sfQueue.dequeueBuffer(&hwcItem);
        if (hwcItem.sync) { hwcItem.sync->wait(EGL_FOREVER_KHR); }

        mFb->setEmulatedEglWindowSurfaceColorBuffer(sfSurface, hwcItem.colorBuffer);

        {
            app2sfQueue.dequeueBuffer(&appItem);

            mFb->bindColorBufferToTexture(appItem.colorBuffer);

            gl->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

            gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
            gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

            if (appItem.sync) { appItem.sync->wait(EGL_FOREVER_KHR); }

            gl->glDrawArrays(GL_TRIANGLES, 0, 6);

            if (appItem.sync) { appItem.sync->decRef(); }
            sf2appQueue.queueBuffer(ColorBufferQueue::Item(appItem.colorBuffer, getFenceSync()));
        }

        mFb->flushEmulatedEglWindowSurfaceColorBuffer(sfSurface);

        if (hwcItem.sync) { hwcItem.sync->decRef(); }
        sf2hwcQueue.queueBuffer(ColorBufferQueue::Item(hwcItem.colorBuffer, getFenceSync()));
    }
    delete tInfo;
}

void SampleApplication::surfaceFlingerComposerLoop() {
    ColorBufferQueue app2sfQueue;
    ColorBufferQueue sf2appQueue;
    ColorBufferQueue sf2hwcQueue;
    ColorBufferQueue hwc2sfQueue;

    std::vector<unsigned int> sfColorBuffers;
    std::vector<unsigned int> hwcColorBuffers;

    for (int i = 0; i < ColorBufferQueue::kCapacity; i++) {
        sfColorBuffers.push_back(mFb->createColorBuffer(mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE));
        hwcColorBuffers.push_back(mFb->createColorBuffer(mWidth, mHeight, GL_RGBA, FRAMEWORK_FORMAT_GL_COMPATIBLE));
    }

    for (int i = 0; i < ColorBufferQueue::kCapacity; i++) {
        mFb->openColorBuffer(sfColorBuffers[i]);
        mFb->openColorBuffer(hwcColorBuffers[i]);
    }

    // prime the queue
    for (int i = 0; i < ColorBufferQueue::kCapacity; i++) {
        sf2appQueue.queueBuffer(ColorBufferQueue::Item(sfColorBuffers[i], nullptr));
        hwc2sfQueue.queueBuffer(ColorBufferQueue::Item(hwcColorBuffers[i], nullptr));
    }

    FunctorThread appThread([&]() {
        RenderThreadInfo* tInfo = new RenderThreadInfo;
        unsigned int appContext = mFb->createEmulatedEglContext(0, 0, GLESApi_3_0);
        unsigned int appSurface = mFb->createEmulatedEglWindowSurface(0, mWidth, mHeight);
        mFb->bindContext(appContext, appSurface, appSurface);

        ColorBufferQueue::Item sfItem = {};

        sf2appQueue.dequeueBuffer(&sfItem);
        mFb->setEmulatedEglWindowSurfaceColorBuffer(appSurface, sfItem.colorBuffer);
        if (sfItem.sync) { sfItem.sync->wait(EGL_FOREVER_KHR); sfItem.sync->decRef(); }

        this->initialize();

        while (true) {
            this->draw();
            mFb->flushEmulatedEglWindowSurfaceColorBuffer(appSurface);
            app2sfQueue.queueBuffer(ColorBufferQueue::Item(sfItem.colorBuffer, getFenceSync()));

            sf2appQueue.dequeueBuffer(&sfItem);
            mFb->setEmulatedEglWindowSurfaceColorBuffer(appSurface, sfItem.colorBuffer);
            if (sfItem.sync) { sfItem.sync->wait(EGL_FOREVER_KHR); sfItem.sync->decRef(); }
        }

        delete tInfo;
    });

    FunctorThread sfThread([&]() {
        if (mIsCompose) {
            drawWorkerWithCompose(app2sfQueue, sf2appQueue);
        }
        else {
            drawWorker(app2sfQueue, sf2appQueue, sf2hwcQueue, hwc2sfQueue);
        }
    });

    sfThread.start();
    appThread.start();

    Vsync vsync(mRefreshRate);
    ColorBufferQueue::Item sfItem = {};
    if (!mIsCompose) {
        while (true) {
            sf2hwcQueue.dequeueBuffer(&sfItem);
            if (sfItem.sync) { sfItem.sync->wait(EGL_FOREVER_KHR); sfItem.sync->decRef(); }
            vsync.waitUntilNextVsync();
            mFb->post(sfItem.colorBuffer);
            if (mUseSubWindow) {
                mWindow->messageLoop();
            }
            hwc2sfQueue.queueBuffer(ColorBufferQueue::Item(sfItem.colorBuffer, getFenceSync()));
        }
    }

    appThread.wait();
    sfThread.wait();
}

void SampleApplication::drawOnce() {
    this->initialize();
    this->draw();
    mFb->flushEmulatedEglWindowSurfaceColorBuffer(mSurface);
    if (mUseSubWindow) {
        mFb->post(mColorBuffer);
        mWindow->messageLoop();
    }
}

const gl::GLESv2Dispatch* SampleApplication::getGlDispatch() {
    return gl::LazyLoadedGLESv2Dispatch::get();
}

bool SampleApplication::isSwANGLE() {
    const char* vendor;
    const char* renderer;
    const char* version;
    mFb->getGLStrings(&vendor, &renderer, &version);
    return strstr(renderer, "ANGLE") && strstr(renderer, "SwiftShader");
}

}  // namespace gfxstream
