// Copyright (C) 2022 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.

#pragma once

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

#include <array>
#include <memory>
#include <optional>
#include <string>
#include <unordered_set>

#include "BufferGl.h"
#include "ColorBufferGl.h"
#include "Compositor.h"
#include "CompositorGl.h"
#include "ContextHelper.h"
#include "Display.h"
#include "DisplayGl.h"
#include "DisplaySurface.h"
#include "EmulatedEglConfig.h"
#include "EmulatedEglContext.h"
#include "EmulatedEglFenceSync.h"
#include "EmulatedEglImage.h"
#include "EmulatedEglWindowSurface.h"
#include "OpenGLESDispatch/EGLDispatch.h"
#include "OpenGLESDispatch/GLESv2Dispatch.h"
#include "ReadbackWorkerGl.h"
#include "TextureDraw.h"
#include "aemu/base/files/Stream.h"
#include "gfxstream/host/Features.h"

#define EGL_NO_CONFIG ((EGLConfig)0)

namespace gfxstream {
class FrameBuffer;
}  // namespace gfxstream

namespace gfxstream {
namespace gl {

class EmulationGl {
   public:
    static std::unique_ptr<EmulationGl> create(uint32_t width, uint32_t height,
                                               gfxstream::host::FeatureSet features,
                                               bool allowWindowSurface, bool egl2egl);

    ~EmulationGl();

    const EGLDispatch* getEglDispatch();
    const GLESv2Dispatch* getGles2Dispatch();

    GLESDispatchMaxVersion getGlesMaxDispatchVersion() const;

    static const GLint* getGlesMaxContextAttribs();

    bool hasEglExtension(const std::string& ext) const;
    void getEglVersion(EGLint* major, EGLint* minor) const;

    void getGlesVersion(GLint* major, GLint* minor) const;
    const std::string& getGlesVendor() const { return mGlesVendor; }
    const std::string& getGlesRenderer() const { return mGlesRenderer; }
    const std::string& getGlesVersionString() const { return mGlesVersion; }
    const std::string& getGlesExtensionsString() const { return mGlesExtensions; }
    bool isGlesVulkanInteropSupported() const { return mGlesVulkanInteropSupported; }

    bool isMesa() const;

    bool isFastBlitSupported() const;
    void disableFastBlitForTesting();

    bool isAsyncReadbackSupported() const;

    std::unique_ptr<DisplaySurface> createWindowSurface(uint32_t width,
                                                        uint32_t height,
                                                        EGLNativeWindowType window);

    const EmulatedEglConfigList& getEmulationEglConfigs() const { return *mEmulatedEglConfigs; }

    CompositorGl* getCompositor() { return mCompositorGl.get(); }

    DisplayGl* getDisplay() { return mDisplayGl.get(); }

    ReadbackWorkerGl* getReadbackWorker() { return mReadbackWorkerGl.get(); }

    using GlesUuid = std::array<uint8_t, GL_UUID_SIZE_EXT>;
    const std::optional<GlesUuid> getGlesDeviceUuid() const { return mGlesDeviceUuid; }

    std::unique_ptr<BufferGl> createBuffer(uint64_t size, HandleType handle);

    std::unique_ptr<BufferGl> loadBuffer(android::base::Stream* stream);

    bool isFormatSupported(GLenum format);

    std::unique_ptr<ColorBufferGl> createColorBuffer(uint32_t width, uint32_t height,
                                                     GLenum internalFormat,
                                                     FrameworkFormat frameworkFormat,
                                                     HandleType handle);

    std::unique_ptr<ColorBufferGl> loadColorBuffer(android::base::Stream* stream);

    std::unique_ptr<EmulatedEglContext> createEmulatedEglContext(
        uint32_t emulatedEglConfigIndex,
        const EmulatedEglContext* shareContext,
        GLESApi api,
        HandleType handle);

    std::unique_ptr<EmulatedEglContext> loadEmulatedEglContext(
        android::base::Stream* stream);

    std::unique_ptr<EmulatedEglFenceSync> createEmulatedEglFenceSync(
        EGLenum type,
        int destroyWhenSignaled);

    std::unique_ptr<EmulatedEglImage> createEmulatedEglImage(
        EmulatedEglContext* context,
        EGLenum target,
        EGLClientBuffer buffer);

    std::unique_ptr<EmulatedEglWindowSurface> createEmulatedEglWindowSurface(
        uint32_t emulatedConfigIndex,
        uint32_t width,
        uint32_t height,
        HandleType handle);

    std::unique_ptr<EmulatedEglWindowSurface> loadEmulatedEglWindowSurface(
        android::base::Stream* stream,
        const ColorBufferMap& colorBuffers,
        const EmulatedEglContextMap& contexts);

    std::unique_ptr<gfxstream::DisplaySurface> createFakeWindowSurface();

   private:
    // TODO(b/233939967): Remove this after fully transitioning to EmulationGl.
   friend class gfxstream::FrameBuffer;

   EmulationGl() = default;

   ContextHelper* getColorBufferContextHelper();

   gfxstream::host::FeatureSet mFeatures;

   EGLDisplay mEglDisplay = EGL_NO_DISPLAY;
   EGLint mEglVersionMajor = 0;
   EGLint mEglVersionMinor = 0;
   std::string mEglVendor;
   std::unordered_set<std::string> mEglExtensions;
   EGLConfig mEglConfig = EGL_NO_CONFIG;

   // The "global" context that all other contexts are shared with.
   EGLContext mEglContext = EGL_NO_CONTEXT;

   // Used for ColorBuffer ops.
   std::unique_ptr<gfxstream::DisplaySurface> mPbufferSurface;

   // Used for Composition and Display ops.
   std::unique_ptr<gfxstream::DisplaySurface> mWindowSurface;

   GLint mGlesVersionMajor = 0;
   GLint mGlesVersionMinor = 0;
   GLESDispatchMaxVersion mGlesDispatchMaxVersion = GLES_DISPATCH_MAX_VERSION_2;
   std::string mGlesVendor;
   std::string mGlesRenderer;
   std::string mGlesVersion;
   std::string mGlesExtensions;
   std::optional<GlesUuid> mGlesDeviceUuid;
   bool mGlesVulkanInteropSupported = false;

   std::unique_ptr<EmulatedEglConfigList> mEmulatedEglConfigs;

   bool mFastBlitSupported = false;

   std::unique_ptr<CompositorGl> mCompositorGl;
   std::unique_ptr<DisplayGl> mDisplayGl;
   std::unique_ptr<ReadbackWorkerGl> mReadbackWorkerGl;

   std::unique_ptr<TextureDraw> mTextureDraw;

   uint32_t mWidth = 0;
   uint32_t mHeight = 0;
};

}  // namespace gl
}  // namespace gfxstream
