/*
 * Copyright (C) 2016 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 <mutex>
#include <array>
#include <sstream>
#include <algorithm>

#include <gui/Surface.h>
#include <gui/BufferItemConsumer.h>

#include <ui/GraphicBuffer.h>
#include <math/vec4.h>

#include <GLES3/gl3.h>

#include "Hwc2TestBuffer.h"
#include "Hwc2TestLayers.h"

using namespace android;

/* Returns a fence from egl */
typedef void (*FenceCallback)(int32_t fence, void* callbackArgs);

/* Returns fence to fence generator */
static void setFence(int32_t fence, void* fenceGenerator);


/* Used to receive the surfaces and fences from egl. The egl buffers are thrown
 * away. The fences are sent to the requester via a callback */
class Hwc2TestSurfaceManager {
public:
    /* Listens for a new frame, detaches the buffer and returns the fence
     * through saved callback. */
    class BufferListener : public ConsumerBase::FrameAvailableListener {
    public:
        BufferListener(sp<IGraphicBufferConsumer> consumer,
                FenceCallback callback, void* callbackArgs)
            : mConsumer(consumer),
              mCallback(callback),
              mCallbackArgs(callbackArgs) { }

        void onFrameAvailable(const BufferItem& /*item*/)
        {
            BufferItem item;

            if (mConsumer->acquireBuffer(&item, 0))
                return;
            if (mConsumer->detachBuffer(item.mSlot))
                return;

            mCallback(item.mFence->dup(), mCallbackArgs);
        }

    private:
        sp<IGraphicBufferConsumer> mConsumer;
        FenceCallback mCallback;
        void* mCallbackArgs;
    };

    /* Creates a buffer listener that waits on a new frame from the buffer
     * queue. */
    void initialize(const Area& bufferArea, android_pixel_format_t format,
            FenceCallback callback, void* callbackArgs)
    {
        sp<IGraphicBufferProducer> producer;
        sp<IGraphicBufferConsumer> consumer;
        BufferQueue::createBufferQueue(&producer, &consumer);

        consumer->setDefaultBufferSize(bufferArea.width, bufferArea.height);
        consumer->setDefaultBufferFormat(format);

        mBufferItemConsumer = new BufferItemConsumer(consumer, 0);

        mListener = new BufferListener(consumer, callback, callbackArgs);
        mBufferItemConsumer->setFrameAvailableListener(mListener);

        mSurface = new Surface(producer, true);
    }

    /* Used by Egl manager. The surface is never displayed. */
    sp<Surface> getSurface() const
    {
        return mSurface;
    }

private:
    sp<BufferItemConsumer> mBufferItemConsumer;
    sp<BufferListener> mListener;
    /* Used by Egl manager. The surface is never displayed */
    sp<Surface> mSurface;
};


/* Used to generate valid fences. It is not possible to create a dummy sync
 * fence for testing. Egl can generate buffers along with a valid fence.
 * The buffer cannot be guaranteed to be the same format across all devices so
 * a CPU filled buffer is used instead. The Egl fence is used along with the
 * CPU filled buffer. */
class Hwc2TestEglManager {
public:
    Hwc2TestEglManager()
        : mEglDisplay(EGL_NO_DISPLAY),
          mEglSurface(EGL_NO_SURFACE),
          mEglContext(EGL_NO_CONTEXT) { }

    ~Hwc2TestEglManager()
    {
        cleanup();
    }

    int initialize(sp<Surface> surface)
    {
        mSurface = surface;

        mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
        if (mEglDisplay == EGL_NO_DISPLAY) return false;

        EGLint major;
        EGLint minor;
        if (!eglInitialize(mEglDisplay, &major, &minor)) {
            ALOGW("Could not initialize EGL");
            return false;
        }

        /* We're going to use a 1x1 pbuffer surface later on
         * The configuration distance doesn't really matter for what we're
         * trying to do */
        EGLint configAttrs[] = {
                EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
                EGL_RED_SIZE, 8,
                EGL_GREEN_SIZE, 8,
                EGL_BLUE_SIZE, 8,
                EGL_ALPHA_SIZE, 0,
                EGL_DEPTH_SIZE, 24,
                EGL_STENCIL_SIZE, 0,
                EGL_NONE
        };

        EGLConfig configs[1];
        EGLint configCnt;
        if (!eglChooseConfig(mEglDisplay, configAttrs, configs, 1,
                &configCnt)) {
            ALOGW("Could not select EGL configuration");
            eglReleaseThread();
            eglTerminate(mEglDisplay);
            return false;
        }

        if (configCnt <= 0) {
            ALOGW("Could not find EGL configuration");
            eglReleaseThread();
            eglTerminate(mEglDisplay);
            return false;
        }

        /* These objects are initialized below but the default "null" values are
         * used to cleanup properly at any point in the initialization sequence */
        EGLint attrs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
        mEglContext = eglCreateContext(mEglDisplay, configs[0], EGL_NO_CONTEXT,
                attrs);
        if (mEglContext == EGL_NO_CONTEXT) {
            ALOGW("Could not create EGL context");
            cleanup();
            return false;
        }

        EGLint surfaceAttrs[] = { EGL_NONE };
        mEglSurface = eglCreateWindowSurface(mEglDisplay, configs[0],
                mSurface.get(), surfaceAttrs);
        if (mEglSurface == EGL_NO_SURFACE) {
            ALOGW("Could not create EGL surface");
            cleanup();
            return false;
        }

        if (!eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
            ALOGW("Could not change current EGL context");
            cleanup();
            return false;
        }

        return true;
    }

    void makeCurrent() const
    {
        eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext);
    }

    void present() const
    {
        eglSwapBuffers(mEglDisplay, mEglSurface);
    }

private:
    void cleanup()
    {
        if (mEglDisplay == EGL_NO_DISPLAY)
            return;
        if (mEglSurface != EGL_NO_SURFACE)
            eglDestroySurface(mEglDisplay, mEglSurface);
        if (mEglContext != EGL_NO_CONTEXT)
            eglDestroyContext(mEglDisplay, mEglContext);

        eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
                EGL_NO_CONTEXT);
        eglReleaseThread();
        eglTerminate(mEglDisplay);
    }

    sp<Surface> mSurface;
    EGLDisplay mEglDisplay;
    EGLSurface mEglSurface;
    EGLContext mEglContext;
};


static const std::array<vec2, 4> triangles = {{
    {  1.0f,  1.0f },
    { -1.0f,  1.0f },
    {  1.0f, -1.0f },
    { -1.0f, -1.0f },
}};

class Hwc2TestFenceGenerator {
public:

    Hwc2TestFenceGenerator()
    {
        mSurfaceManager.initialize({1, 1}, HAL_PIXEL_FORMAT_RGBA_8888,
                setFence, this);

        if (!mEglManager.initialize(mSurfaceManager.getSurface()))
            return;

        mEglManager.makeCurrent();

        glClearColor(0.0, 0.0, 0.0, 1.0);
        glEnableVertexAttribArray(0);
    }

    ~Hwc2TestFenceGenerator()
    {
        if (mFence >= 0)
            close(mFence);
        mFence = -1;

        mEglManager.makeCurrent();
    }

    /* It is not possible to simply generate a fence. The easiest way is to
     * generate a buffer using egl and use the associated fence. The buffer
     * cannot be guaranteed to be a certain format across all devices using this
     * method. Instead the buffer is generated using the CPU */
    int32_t get()
    {
        if (mFence >= 0) {
            return dup(mFence);
        }

        std::unique_lock<std::mutex> lock(mMutex);

        /* If the pending is still set to false and times out, we cannot recover.
         * Set an error and return */
        while (mPending != false) {
            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
                return -ETIME;
        }

        /* Generate a fence. The fence will be returned through the setFence
         * callback */
        mEglManager.makeCurrent();

        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, triangles.data());
        glClear(GL_COLOR_BUFFER_BIT);

        mEglManager.present();

        /* Wait for the setFence callback */
        while (mPending != true) {
            if (mCv.wait_for(lock, std::chrono::seconds(2)) == std::cv_status::timeout)
                return -ETIME;
        }

        mPending = false;

        return dup(mFence);
    }

    /* Callback that sets the fence */
    void set(int32_t fence)
    {
        mFence = fence;
        mPending = true;

        mCv.notify_all();
    }

private:

    Hwc2TestSurfaceManager mSurfaceManager;
    Hwc2TestEglManager mEglManager;

    std::mutex mMutex;
    std::condition_variable mCv;

    int32_t mFence = -1;
    bool mPending = false;
};


static void setFence(int32_t fence, void* fenceGenerator)
{
    static_cast<Hwc2TestFenceGenerator*>(fenceGenerator)->set(fence);
}


/* Sets the pixel of a buffer given the location, format, stride and color.
 * Currently only supports RGBA_8888 */
static void setColor(int32_t x, int32_t y,
        android_pixel_format_t format, uint32_t stride, uint8_t* img, uint8_t r,
        uint8_t g, uint8_t b, uint8_t a)
{
       switch (format) {
       case HAL_PIXEL_FORMAT_RGBA_8888:
           img[(y * stride + x) * 4 + 0] = r;
           img[(y * stride + x) * 4 + 1] = g;
           img[(y * stride + x) * 4 + 2] = b;
           img[(y * stride + x) * 4 + 3] = a;
           break;
       default:
           break;
       }
}

Hwc2TestBuffer::Hwc2TestBuffer()
    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }

Hwc2TestBuffer::~Hwc2TestBuffer() = default;

/* When the buffer changes sizes, save the new size and invalidate the current
 * buffer */
void Hwc2TestBuffer::updateBufferArea(const Area& bufferArea)
{
    if (mBufferArea.width == bufferArea.width
            && mBufferArea.height == bufferArea.height)
        return;

    mBufferArea.width = bufferArea.width;
    mBufferArea.height = bufferArea.height;

    mValidBuffer = false;
}

/* Returns a valid buffer handle and fence. The handle is filled using the CPU
 * to ensure the correct format across all devices. The fence is created using
 * egl. */
int Hwc2TestBuffer::get(buffer_handle_t* outHandle, int32_t* outFence)
{
    if (mBufferArea.width == -1 || mBufferArea.height == -1)
        return -EINVAL;

    /* If the current buffer is valid, the previous buffer can be reused.
     * Otherwise, create new buffer */
    if (!mValidBuffer) {
        int ret = generateBuffer();
        if (ret)
            return ret;
    }

    *outFence = mFenceGenerator->get();
    *outHandle = mHandle;

    mValidBuffer = true;

    return 0;
}

/* CPU fills a buffer to guarantee the correct buffer format across all
 * devices */
int Hwc2TestBuffer::generateBuffer()
{
    /* Create new graphic buffer with correct dimensions */
    mGraphicBuffer = new GraphicBuffer(mBufferArea.width, mBufferArea.height,
            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
            "hwc2_test_buffer");
    int ret = mGraphicBuffer->initCheck();
    if (ret) {
        return ret;
    }
    if (!mGraphicBuffer->handle) {
        return -EINVAL;
    }

    /* Locks the buffer for writing */
    uint8_t* img;
    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));

    uint32_t stride = mGraphicBuffer->getStride();

    /* Iterate from the top row of the buffer to the bottom row */
    for (int32_t y = 0; y < mBufferArea.height; y++) {

        /* Will be used as R, G and B values for pixel colors */
        uint8_t max = 255;
        uint8_t min = 0;

        /* Divide the rows into 3 sections. The first section will contain
         * the lighest colors. The last section will contain the darkest
         * colors. */
        if (y < mBufferArea.height * 1.0 / 3.0) {
            min = 255 / 2;
        } else if (y >= mBufferArea.height * 2.0 / 3.0) {
            max = 255 / 2;
        }

        /* Divide the columns into 3 sections. The first section is red,
         * the second is green and the third is blue */
        int32_t x = 0;
        for (; x < mBufferArea.width / 3; x++) {
            setColor(x, y, mFormat, stride, img, max, min, min, 255);
        }

        for (; x < mBufferArea.width * 2 / 3; x++) {
            setColor(x, y, mFormat, stride, img, min, max, min, 255);
        }

        for (; x < mBufferArea.width; x++) {
            setColor(x, y, mFormat, stride, img, min, min, max, 255);
        }
    }

    /* Unlock the buffer for reading */
    mGraphicBuffer->unlock();

    mHandle = mGraphicBuffer->handle;

    return 0;
}


Hwc2TestClientTargetBuffer::Hwc2TestClientTargetBuffer()
    : mFenceGenerator(new Hwc2TestFenceGenerator()) { }

Hwc2TestClientTargetBuffer::~Hwc2TestClientTargetBuffer() { }

/* Generates a client target buffer using the layers assigned for client
 * composition. Takes into account the individual layer properties such as
 * transform, blend mode, source crop, etc. */
int Hwc2TestClientTargetBuffer::get(buffer_handle_t* outHandle,
        int32_t* outFence, const Area& bufferArea,
        const Hwc2TestLayers* testLayers,
        const std::set<hwc2_layer_t>* clientLayers,
        const std::set<hwc2_layer_t>* clearLayers)
{
    /* Create new graphic buffer with correct dimensions */
    mGraphicBuffer = new GraphicBuffer(bufferArea.width, bufferArea.height,
            mFormat, GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_HW_RENDER,
            "hwc2_test_buffer");
    int ret = mGraphicBuffer->initCheck();
    if (ret) {
        return ret;
    }
    if (!mGraphicBuffer->handle) {
        return -EINVAL;
    }

    uint8_t* img;
    mGraphicBuffer->lock(GRALLOC_USAGE_SW_WRITE_OFTEN, (void**)(&img));

    uint32_t stride = mGraphicBuffer->getStride();

    float bWDiv3 = bufferArea.width / 3;
    float bW2Div3 = bufferArea.width * 2 / 3;
    float bHDiv3 = bufferArea.height / 3;
    float bH2Div3 = bufferArea.height * 2 / 3;

    /* Cycle through every pixel in the buffer and determine what color it
     * should be. */
    for (int32_t y = 0; y < bufferArea.height; y++) {
        for (int32_t x = 0; x < bufferArea.width; x++) {

            uint8_t r = 0, g = 0, b = 0;
            float a = 0.0f;

            /* Cycle through each client layer from back to front and
             * update the pixel color. */
            for (auto layer = clientLayers->rbegin();
                    layer != clientLayers->rend(); ++layer) {

                const hwc_rect_t df = testLayers->getDisplayFrame(*layer);

                float dfL = df.left;
                float dfT = df.top;
                float dfR = df.right;
                float dfB = df.bottom;

                /* If the pixel location falls outside of the layer display
                 * frame, skip the layer. */
                if (x < dfL || x >= dfR || y < dfT || y >= dfB)
                    continue;

                /* If the device has requested the layer be clear, clear
                 * the pixel and continue. */
                if (clearLayers->count(*layer) != 0) {
                    r = 0;
                    g = 0;
                    b = 0;
                    a = 0.0f;
                    continue;
                }

                float planeAlpha = testLayers->getPlaneAlpha(*layer);

                /* If the layer is a solid color, fill the color and
                 * continue. */
                if (testLayers->getComposition(*layer)
                        == HWC2_COMPOSITION_SOLID_COLOR) {
                    const auto color = testLayers->getColor(*layer);
                    r = color.r;
                    g = color.g;
                    b = color.b;
                    a = color.a * planeAlpha;
                    continue;
                }

                float xPos = x;
                float yPos = y;

                hwc_transform_t transform = testLayers->getTransform(*layer);

                float dfW = dfR - dfL;
                float dfH = dfB - dfT;

                /* If a layer has a transform, find which location on the
                 * layer will end up in the current pixel location. We
                 * can calculate the color of the current pixel using that
                 * location. */
                if (transform > 0) {
                    /* Change origin to be the center of the layer. */
                    xPos = xPos - dfL - dfW / 2.0;
                    yPos = yPos - dfT - dfH / 2.0;

                    /* Flip Horizontal by reflecting across the y axis. */
                    if (transform & HWC_TRANSFORM_FLIP_H)
                        xPos = -xPos;

                    /* Flip vertical by reflecting across the x axis. */
                    if (transform & HWC_TRANSFORM_FLIP_V)
                        yPos = -yPos;

                    /* Rotate 90 by using a basic linear algebra rotation
                     * and scaling the result so the display frame remains
                     * the same. For example, a buffer of size 100x50 should
                     * rotate 90 degress but remain the same dimension
                     * (100x50) at the end of the transformation. */
                    if (transform & HWC_TRANSFORM_ROT_90) {
                        float tmp = xPos;
                        xPos = -yPos * dfW / dfH;
                        yPos = tmp * dfH / dfW;
                    }

                    /* Change origin back to the top left corner of the
                     * layer. */
                    xPos = xPos + dfL + dfW / 2.0;
                    yPos = yPos + dfT + dfH / 2.0;
                }

                hwc_frect_t sc = testLayers->getSourceCrop(*layer);
                float scL = sc.left, scT = sc.top;

                float dfWDivScW = dfW / (sc.right - scL);
                float dfHDivScH = dfH / (sc.bottom - scT);

                float max = 255, min = 0;

                /* Choose the pixel color. Similar to generateBuffer,
                 * each layer will be divided into 3x3 colors. Because
                 * both the source crop and display frame must be taken into
                 * account, the formulas are more complicated.
                 *
                 * If the source crop and display frame were not taken into
                 * account, we would simply divide the buffer into three
                 * sections by height. Each section would get one color.
                 * For example the formula for the first section would be:
                 *
                 * if (yPos < bufferArea.height / 3)
                 *        //Select first section color
                 *
                 * However the pixel color is chosen based on the source
                 * crop and displayed based on the display frame.
                 *
                 * If the display frame top was 0 and the source crop height
                 * and display frame height were the same. The only factor
                 * would be the source crop top. To calculate the new
                 * section boundary, the section boundary would be moved up
                 * by the height of the source crop top. The formula would
                 * be:
                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top)
                 *        //Select first section color
                 *
                 * If the display frame top could also vary but source crop
                 * and display frame heights were the same, the formula
                 * would be:
                 * if (yPos < (bufferArea.height / 3 - sourceCrop.top
                 *              + displayFrameTop)
                 *        //Select first section color
                 *
                 * If the heights were not the same, the conversion between
                 * the source crop and display frame dimensions must be
                 * taken into account. The formula would be:
                 * if (yPos < ((bufferArea.height / 3) - sourceCrop.top)
                 *              * displayFrameHeight / sourceCropHeight
                 *              + displayFrameTop)
                 *        //Select first section color
                 */
                if (yPos < ((bHDiv3) - scT) * dfHDivScH + dfT) {
                    min = 255 / 2;
                } else if (yPos >= ((bH2Div3) - scT) * dfHDivScH + dfT) {
                    max = 255 / 2;
                }

                uint8_t rCur = min, gCur = min, bCur = min;
                float aCur = 1.0f;

                /* This further divides the color sections from 3 to 3x3.
                 * The math behind it follows the same logic as the previous
                 * comment */
                if (xPos < ((bWDiv3) - scL) * (dfWDivScW) + dfL) {
                    rCur = max;
                } else if (xPos < ((bW2Div3) - scL) * (dfWDivScW) + dfL) {
                    gCur = max;
                } else {
                    bCur = max;
                }


                /* Blend the pixel color with the previous layers' pixel
                 * colors using the plane alpha and blend mode. The final
                 * pixel color is chosen using the plane alpha and blend
                 * mode formulas found in hwcomposer2.h */
                hwc2_blend_mode_t blendMode = testLayers->getBlendMode(*layer);

                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
                    rCur *= planeAlpha;
                    gCur *= planeAlpha;
                    bCur *= planeAlpha;
                }

                aCur *= planeAlpha;

                if (blendMode == HWC2_BLEND_MODE_PREMULTIPLIED) {
                    r = rCur + r * (1.0 - aCur);
                    g = gCur + g * (1.0 - aCur);
                    b = bCur + b * (1.0 - aCur);
                    a = aCur + a * (1.0 - aCur);
                } else if (blendMode == HWC2_BLEND_MODE_COVERAGE) {
                    r = rCur * aCur + r * (1.0 - aCur);
                    g = gCur * aCur + g * (1.0 - aCur);
                    b = bCur * aCur + b * (1.0 - aCur);
                    a = aCur * aCur + a * (1.0 - aCur);
                } else {
                    r = rCur;
                    g = gCur;
                    b = bCur;
                    a = aCur;
                }
            }

            /* Set the pixel color */
            setColor(x, y, mFormat, stride, img, r, g, b, a * 255);
        }
    }

    mGraphicBuffer->unlock();

    *outFence = mFenceGenerator->get();
    *outHandle = mGraphicBuffer->handle;

    return 0;
}
