/*
 * Copyright 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.
 */

#ifndef ANDROID_HW_EMU_HWC2_H
#define ANDROID_HW_EMU_HWC2_H

#define HWC2_INCLUDE_STRINGIFICATION
#define HWC2_USE_CPP11
#include <hardware/hwcomposer2.h>
#undef HWC2_INCLUDE_STRINGIFICATION
#undef HWC2_USE_CPP11
#include <utils/Thread.h>

#include <android-base/unique_fd.h>
#include <atomic>
#include <map>
#include <memory>
#include <mutex>
#include <numeric>
#include <sstream>
#include <vector>
#include <unordered_set>
#include <unordered_map>
#include <set>

#include <cutils/native_handle.h>

#include "HostConnection.h"

namespace android {

class EmuHWC2 : public hwc2_device_t {
public:
    EmuHWC2();
    int populatePrimary();
    int populateSecondaryDisplays();

private:
    static inline EmuHWC2* getHWC2(hwc2_device_t* device) {
        return static_cast<EmuHWC2*>(device);
    }

    static int closeHook(hw_device_t* device) {
        EmuHWC2 *ctx = reinterpret_cast<EmuHWC2*>(device);
        delete ctx;
        return 0;
    }

    // getCapabilities
    void doGetCapabilities(uint32_t* outCount, int32_t* outCapabilities);
    static void getCapabilitiesHook(hwc2_device_t* device, uint32_t* outCount,
                                int32_t* outCapabilities) {
        getHWC2(device)->doGetCapabilities(outCount, outCapabilities);
    }

    // getFunction
    hwc2_function_pointer_t doGetFunction(HWC2::FunctionDescriptor descriptor);
    static hwc2_function_pointer_t getFunctionHook(hwc2_device_t* device,
            int32_t desc) {
        auto descriptor = static_cast<HWC2::FunctionDescriptor>(desc);
        return getHWC2(device)->doGetFunction(descriptor);
    }

    // Device functions
    HWC2::Error createVirtualDisplay(uint32_t width, uint32_t height,
            int32_t* format, hwc2_display_t* outDisplay);
    static int32_t createVirtualDisplayHook(hwc2_device_t* device,
            uint32_t width, uint32_t height, int32_t* format,
            hwc2_display_t* outDisplay) {
        auto error = getHWC2(device)->createVirtualDisplay(width, height,
                format, outDisplay);
        return static_cast<int32_t>(error);
    }

    HWC2::Error destroyVirtualDisplay(hwc2_display_t display);
    static int32_t destroyVirtualDisplayHook(hwc2_device_t* device,
            hwc2_display_t display) {
        auto error = getHWC2(device)->destroyVirtualDisplay(display);
        return static_cast<int32_t>(error);
    }

    std::string mDumpString;
    void dump(uint32_t* outSize, char* outBuffer);
    static void dumpHook(hwc2_device_t* device, uint32_t* outSize,
            char* outBuffer) {
        getHWC2(device)->dump(outSize, outBuffer);
    }

    uint32_t getMaxVirtualDisplayCount();
    static uint32_t getMaxVirtualDisplayCountHook(hwc2_device_t* device) {
        return getHWC2(device)->getMaxVirtualDisplayCount();
    }

    HWC2::Error registerCallback(HWC2::Callback descriptor,
            hwc2_callback_data_t callbackData, hwc2_function_pointer_t pointer);
    static int32_t registerCallbackHook(hwc2_device_t* device,
            int32_t intDesc, hwc2_callback_data_t callbackData,
            hwc2_function_pointer_t pointer) {
        auto descriptor = static_cast<HWC2::Callback>(intDesc);
        auto error = getHWC2(device)->registerCallback(descriptor,
                callbackData, pointer);
        return static_cast<int32_t>(error);
    }

    class Layer;
    class SortLayersByZ {
    public:
        bool operator()(const std::shared_ptr<Layer>& lhs,
                    const std::shared_ptr<Layer>& rhs) const;
    };

    // SurfaceFlinger sets the ColorBuffer and its Fence handler for each
    // layer. This class is a container for these two.
    class FencedBuffer {
        public:
            FencedBuffer() : mBuffer(nullptr) {}

            void setBuffer(buffer_handle_t buffer) { mBuffer = buffer; }
            void setFence(int fenceFd) {
                mFence = std::make_shared<base::unique_fd>(fenceFd);
            }

            buffer_handle_t getBuffer() const { return mBuffer; }
            int getFence() const { return mFence ? dup(mFence->get()) : -1; }

        private:
            buffer_handle_t mBuffer;
            std::shared_ptr<base::unique_fd> mFence;
    };

    typedef struct compose_layer {
        uint32_t cbHandle;
        hwc2_composition_t composeMode;
        hwc_rect_t displayFrame;
        hwc_frect_t crop;
        int32_t blendMode;
        float alpha;
        hwc_color_t color;
        hwc_transform_t transform;
    } ComposeLayer;
    typedef struct compose_device {
        uint32_t version;
        uint32_t targetHandle;
        uint32_t numLayers;
        struct compose_layer layer[0];
    } ComposeDevice;
    typedef struct compose_device_v2 {
        uint32_t version;
        uint32_t displayId;
        uint32_t targetHandle;
        uint32_t numLayers;
        struct compose_layer layer[0];
    } ComposeDevice_v2;

    class ComposeMsg {
    public:
        ComposeMsg(uint32_t layerCnt = 0) :
          mData(sizeof(ComposeDevice) + layerCnt * sizeof(ComposeLayer))
        {
            mComposeDevice = reinterpret_cast<ComposeDevice*>(mData.data());
            mLayerCnt = layerCnt;
        }

        ComposeDevice* get() { return mComposeDevice; }

        uint32_t getLayerCnt() { return mLayerCnt; }

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

    class ComposeMsg_v2 {
    public:
        ComposeMsg_v2(uint32_t layerCnt = 0) :
          mData(sizeof(ComposeDevice_v2) + layerCnt * sizeof(ComposeLayer))
        {
            mComposeDevice = reinterpret_cast<ComposeDevice_v2*>(mData.data());
            mLayerCnt = layerCnt;
        }

        ComposeDevice_v2* get() { return mComposeDevice; }

        uint32_t getLayerCnt() { return mLayerCnt; }

    private:
        std::vector<uint8_t> mData;
        uint32_t mLayerCnt;
        ComposeDevice_v2* mComposeDevice;
    };

    class Display {
    public:
        Display(EmuHWC2& device, HWC2::DisplayType type, int width, int height);
        ~Display();
        hwc2_display_t getId() const {return mId;}

        // HWC2 Display functions
        HWC2::Error acceptChanges();
        HWC2::Error createLayer(hwc2_layer_t* outLayerId);
        HWC2::Error destroyLayer(hwc2_layer_t layerId);
        HWC2::Error getActiveConfig(hwc2_config_t* outConfigId);
        HWC2::Error getDisplayAttribute(hwc2_config_t configId,
                int32_t attribute, int32_t* outValue);
        HWC2::Error getChangedCompositionTypes(uint32_t* outNumElements,
                hwc2_layer_t* outLayers, int32_t* outTypes);
        HWC2::Error getColorModes(uint32_t* outNumModes, int32_t* outModes);
        HWC2::Error getConfigs(uint32_t* outNumConfigs,
                hwc2_config_t* outConfigIds);
        HWC2::Error getDozeSupport(int32_t* outSupport);
        HWC2::Error getHdrCapabilities(uint32_t* outNumTypes,
                int32_t* outTypes, float* outMaxLuminance,
                float* outMaxAverageLuminance, float* outMinLuminance);
        HWC2::Error getName(uint32_t* outSize, char* outName);
        HWC2::Error getReleaseFences(uint32_t* outNumElements,
                hwc2_layer_t* outLayers, int32_t* outFences);
        HWC2::Error getRequests(int32_t* outDisplayRequests,
                uint32_t* outNumElements, hwc2_layer_t* outLayers,
                int32_t* outLayerRequests);
        HWC2::Error getType(int32_t* outType);
        HWC2::Error present(int32_t* outRetireFence);
        HWC2::Error setActiveConfig(hwc2_config_t configId);
        HWC2::Error setClientTarget(buffer_handle_t target,
                int32_t acquireFence, int32_t dataspace,
                hwc_region_t damage);
        HWC2::Error setColorMode(int32_t mode);
        HWC2::Error setColorTransform(const float* matrix,
                int32_t hint);
        HWC2::Error setOutputBuffer(buffer_handle_t buffer,
                int32_t releaseFence);
        HWC2::Error setPowerMode(int32_t mode);
        HWC2::Error setVsyncEnabled(int32_t enabled);
        HWC2::Error validate(uint32_t* outNumTypes,
                uint32_t* outNumRequests);
        HWC2::Error updateLayerZ(hwc2_layer_t layerId, uint32_t z);
        HWC2::Error getClientTargetSupport(uint32_t width, uint32_t height,
                 int32_t format, int32_t dataspace);
        // 2.3 required functions
        HWC2::Error getDisplayIdentificationData(uint8_t* outPort,
                 uint32_t* outDataSize, uint8_t* outData);
        HWC2::Error getDisplayCapabilities(uint32_t* outNumCapabilities,
                 uint32_t* outCapabilities);
        HWC2::Error getDisplayBrightnessSupport(bool *out_support);
        HWC2::Error setDisplayBrightness(float brightness);

        // Read configs from PRIMARY Display
        int populatePrimaryConfigs(int width, int height, int dpiX, int dpiY);
        HWC2::Error populateSecondaryConfigs(uint32_t width, uint32_t height,
                 uint32_t dpi, uint32_t idx);

    private:
        void post(HostConnection *hostCon, ExtendedRCEncoderContext *rcEnc,
                  buffer_handle_t h);

        class Config {
        public:
            Config(Display& display)
              : mDisplay(display),
                mId(0),
                mAttributes() {}

            bool isOnDisplay(const Display& display) const {
                return display.getId() == mDisplay.getId();
            }
            void setAttribute(HWC2::Attribute attribute, int32_t value);
            int32_t getAttribute(HWC2::Attribute attribute) const;
            void setId(hwc2_config_t id) {mId = id; }
            hwc2_config_t getId() const {return mId; }
            std::string toString() const;

        private:
            Display& mDisplay;
            hwc2_config_t mId;
            std::unordered_map<HWC2::Attribute, int32_t> mAttributes;
        };

        // Stores changes requested from the device upon calling prepare().
        // Handles change request to:
        //   - Layer composition type.
        //   - Layer hints.
        class Changes {
            public:
                uint32_t getNumTypes() const {
                    return static_cast<uint32_t>(mTypeChanges.size());
                }

                uint32_t getNumLayerRequests() const {
                    return static_cast<uint32_t>(mLayerRequests.size());
                }

                const std::unordered_map<hwc2_layer_t, HWC2::Composition>&
                        getTypeChanges() const {
                    return mTypeChanges;
                }

                const std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>&
                        getLayerRequests() const {
                    return mLayerRequests;
                }

                void addTypeChange(hwc2_layer_t layerId,
                        HWC2::Composition type) {
                    mTypeChanges.insert({layerId, type});
                }

                void clearTypeChanges() { mTypeChanges.clear(); }

                void addLayerRequest(hwc2_layer_t layerId,
                        HWC2::LayerRequest request) {
                    mLayerRequests.insert({layerId, request});
                }

            private:
                std::unordered_map<hwc2_layer_t, HWC2::Composition>
                        mTypeChanges;
                std::unordered_map<hwc2_layer_t, HWC2::LayerRequest>
                        mLayerRequests;
        };

        // Generate sw vsync signal
        class VsyncThread : public Thread {
        public:
            VsyncThread(Display& display)
              : mDisplay(display) {}
            virtual ~VsyncThread() {}
        private:
            Display& mDisplay;
            bool threadLoop() final;
        };

    private:
        EmuHWC2& mDevice;
        // Display ID generator.
        static std::atomic<hwc2_display_t> sNextId;
        static const uint32_t hostDisplayIdStart = 6;
        const hwc2_display_t mId;
        // emulator side displayId
        uint32_t mHostDisplayId;
        std::string mName;
        HWC2::DisplayType mType;
        HWC2::PowerMode mPowerMode;
        HWC2::Vsync mVsyncEnabled;
        uint32_t mVsyncPeriod;
        VsyncThread mVsyncThread;
        FencedBuffer mClientTarget;
        // Will only be non-null after the Display has been validated and
        // before it has been presented
        std::unique_ptr<Changes> mChanges;
        // All layers this Display is aware of.
        std::multiset<std::shared_ptr<Layer>, SortLayersByZ> mLayers;
        std::vector<hwc2_display_t> mReleaseLayerIds;
        std::vector<int32_t> mReleaseFences;
        std::vector<std::shared_ptr<Config>> mConfigs;
        std::shared_ptr<const Config> mActiveConfig;
        std::set<android_color_mode_t> mColorModes;
        android_color_mode_t mActiveColorMode;
        bool mSetColorTransform;
        // The state of this display should only be modified from
        // SurfaceFlinger's main loop, with the exception of when dump is
        // called. To prevent a bad state from crashing us during a dump
        // call, all public calls into Display must acquire this mutex.
        mutable std::mutex mStateMutex;
        std::unique_ptr<ComposeMsg> mComposeMsg;
        std::unique_ptr<ComposeMsg_v2> mComposeMsg_v2;
        int mSyncDeviceFd;
        const native_handle_t* mTargetCb;
    };

    template<typename MF, MF memFunc, typename ...Args>
    static int32_t displayHook(hwc2_device_t* device, hwc2_display_t displayId,
            Args... args) {
        auto display = getHWC2(device)->getDisplay(displayId);
        if (!display) {
            return static_cast<int32_t>(HWC2::Error::BadDisplay);
        }
        auto error = ((*display).*memFunc)(std::forward<Args>(args)...);
        return static_cast<int32_t>(error);
    }

    class Layer {
    public:
        explicit Layer(Display& display);
        Display& getDisplay() const {return mDisplay;}
        hwc2_layer_t getId() const {return mId;}
        bool operator==(const Layer& other) { return mId == other.mId; }
        bool operator!=(const Layer& other) { return !(*this == other); }

        // HWC2 Layer functions
        HWC2::Error setBuffer(buffer_handle_t buffer, int32_t acquireFence);
        HWC2::Error setCursorPosition(int32_t x, int32_t y);
        HWC2::Error setSurfaceDamage(hwc_region_t damage);

        // HWC2 Layer state functions
        HWC2::Error setBlendMode(int32_t mode);
        HWC2::Error setColor(hwc_color_t color);
        HWC2::Error setCompositionType(int32_t type);
        HWC2::Error setDataspace(int32_t dataspace);
        HWC2::Error setDisplayFrame(hwc_rect_t frame);
        HWC2::Error setPlaneAlpha(float alpha);
        HWC2::Error setSidebandStream(const native_handle_t* stream);
        HWC2::Error setSourceCrop(hwc_frect_t crop);
        HWC2::Error setTransform(int32_t transform);
        HWC2::Error setVisibleRegion(hwc_region_t visible);
        HWC2::Error setZ(uint32_t z);

        HWC2::Composition getCompositionType() const {
            return mCompositionType;
        }
        hwc_color_t getColor() {return mColor; }
        uint32_t getZ() {return mZ; }
        std::size_t getNumVisibleRegions() {return mVisibleRegion.size(); }
        FencedBuffer& getLayerBuffer() {return mBuffer; }
        int32_t getBlendMode() {return (int32_t)mBlendMode; }
        float getPlaneAlpha() {return mPlaneAlpha; }
        hwc_frect_t getSourceCrop() {return mSourceCrop; }
        hwc_rect_t getDisplayFrame() {return mDisplayFrame; }
        hwc_transform_t getTransform() {return (hwc_transform_t)mTransform; }
    private:
        static std::atomic<hwc2_layer_t> sNextId;
        const hwc2_layer_t mId;
        Display& mDisplay;
        FencedBuffer mBuffer;
        std::vector<hwc_rect_t> mSurfaceDamage;

        HWC2::BlendMode mBlendMode;
        hwc_color_t mColor;
        HWC2::Composition mCompositionType;
        hwc_rect_t mDisplayFrame;
        float mPlaneAlpha;
        const native_handle_t* mSidebandStream;
        hwc_frect_t mSourceCrop;
        HWC2::Transform mTransform;
        std::vector<hwc_rect_t> mVisibleRegion;
        uint32_t mZ;
    };

    template <typename MF, MF memFunc, typename ...Args>
    static int32_t layerHook(hwc2_device_t* device, hwc2_display_t displayId,
            hwc2_layer_t layerId, Args... args) {
        auto result = getHWC2(device)->getLayer(displayId, layerId);
        auto error = std::get<HWC2::Error>(result);
        if (error == HWC2::Error::None) {
            auto layer = std::get<Layer*>(result);
            error = ((*layer).*memFunc)(std::forward<Args>(args)...);
        }
        return static_cast<int32_t>(error);
    }

    // helpers
    void populateCapabilities();
    Display* getDisplay(hwc2_display_t id);
    std::tuple<Layer*, HWC2::Error> getLayer(hwc2_display_t displayId,
            hwc2_layer_t layerId);

    HWC2::Error initDisplayParameters();
    const native_handle_t* allocateDisplayColorBuffer(int width, int height);
    void freeDisplayColorBuffer(const native_handle_t* h);

    std::unordered_set<HWC2::Capability> mCapabilities;

    // These are potentially accessed from multiple threads, and are protected
    // by this mutex.
    std::mutex mStateMutex;

    struct CallbackInfo {
        hwc2_callback_data_t data;
        hwc2_function_pointer_t pointer;
    };
    std::unordered_map<HWC2::Callback, CallbackInfo> mCallbacks;

    // use map so displays can be pluged in by order of ID, 0, 1, 2, 3, etc.
    std::map<hwc2_display_t, std::shared_ptr<Display>> mDisplays;
    std::unordered_map<hwc2_layer_t, std::shared_ptr<Layer>> mLayers;

    int mDisplayWidth;
    int mDisplayHeight;
    int mDisplayDpiX;
    int mDisplayDpiY;
};

}
#endif
