//
// Copyright 2016 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// gl_raii:
//   Helper methods for containing GL objects like buffers and textures.

#ifndef ANGLE_TESTS_GL_RAII_H_
#define ANGLE_TESTS_GL_RAII_H_

#include <functional>

#include "util/shader_utils.h"

namespace angle
{

// This is a bit of hack to work around a bug in MSVS intellisense, and make it very easy to
// use the correct function pointer type without worrying about the various definitions of
// GL_APICALL.
using GLGen    = decltype(glGenBuffers);
using GLDelete = decltype(glDeleteBuffers);

class GLWrapper : angle::NonCopyable
{
  public:
    GLWrapper(GLGen *genFunc, GLDelete *deleteFunc) : mGenFunc(genFunc), mDeleteFunc(deleteFunc) {}
    ~GLWrapper() { (*mDeleteFunc)(1, &mHandle); }

    // The move-constructor and move-assignment operators are necessary so that the data within a
    // GLWrapper object can be relocated.
    GLWrapper(GLWrapper &&rht)
        : mGenFunc(rht.mGenFunc), mDeleteFunc(rht.mDeleteFunc), mHandle(rht.mHandle)
    {
        rht.mHandle = 0u;
    }
    GLWrapper &operator=(GLWrapper &&rht)
    {
        if (this != &rht)
        {
            mGenFunc    = rht.mGenFunc;
            mDeleteFunc = rht.mDeleteFunc;
            std::swap(mHandle, rht.mHandle);
        }
        return *this;
    }

    void reset()
    {
        if (mHandle != 0u)
        {
            (*mDeleteFunc)(1, &mHandle);
            mHandle = 0u;
        }
    }

    GLuint get()
    {
        if (!mHandle)
        {
            (*mGenFunc)(1, &mHandle);
        }
        return mHandle;
    }

    operator GLuint() { return get(); }

  private:
    GLGen *mGenFunc;
    GLDelete *mDeleteFunc;
    GLuint mHandle = 0u;
};

class GLVertexArray : public GLWrapper
{
  public:
    GLVertexArray() : GLWrapper(&glGenVertexArrays, &glDeleteVertexArrays) {}
};
class GLBuffer : public GLWrapper
{
  public:
    GLBuffer() : GLWrapper(&glGenBuffers, &glDeleteBuffers) {}
};
class GLTexture : public GLWrapper
{
  public:
    GLTexture() : GLWrapper(&glGenTextures, &glDeleteTextures) {}
};
class GLFramebuffer : public GLWrapper
{
  public:
    GLFramebuffer() : GLWrapper(&glGenFramebuffers, &glDeleteFramebuffers) {}
};
class GLMemoryObject : public GLWrapper
{
  public:
    GLMemoryObject() : GLWrapper(&glCreateMemoryObjectsEXT, &glDeleteMemoryObjectsEXT) {}
};
class GLRenderbuffer : public GLWrapper
{
  public:
    GLRenderbuffer() : GLWrapper(&glGenRenderbuffers, &glDeleteRenderbuffers) {}
};
class GLSampler : public GLWrapper
{
  public:
    GLSampler() : GLWrapper(&glGenSamplers, &glDeleteSamplers) {}
};
class GLSemaphore : public GLWrapper
{
  public:
    GLSemaphore() : GLWrapper(&glGenSemaphoresEXT, &glDeleteSemaphoresEXT) {}
};
class GLTransformFeedback : public GLWrapper
{
  public:
    GLTransformFeedback() : GLWrapper(&glGenTransformFeedbacks, &glDeleteTransformFeedbacks) {}
};
class GLProgramPipeline : public GLWrapper
{
  public:
    GLProgramPipeline() : GLWrapper(&glGenProgramPipelines, &glDeleteProgramPipelines) {}
};
class GLQueryEXT : public GLWrapper
{
  public:
    GLQueryEXT() : GLWrapper(&glGenQueriesEXT, &glDeleteQueriesEXT) {}
};

class GLShader : angle::NonCopyable
{
  public:
    GLShader() = delete;
    explicit GLShader(GLenum shaderType) { mHandle = glCreateShader(shaderType); }

    ~GLShader() { glDeleteShader(mHandle); }

    GLuint get() { return mHandle; }

    operator GLuint() { return get(); }

  private:
    GLuint mHandle;
};

// Prefer ANGLE_GL_PROGRAM for local variables.
class GLProgram
{
  public:
    GLProgram() : mHandle(0) {}

    ~GLProgram() { glDeleteProgram(mHandle); }

    void makeEmpty() { mHandle = glCreateProgram(); }

    void makeCompute(const char *computeShader) { mHandle = CompileComputeProgram(computeShader); }

    void makeRaster(const char *vertexShader, const char *fragmentShader)
    {
        mHandle = CompileProgram(vertexShader, fragmentShader);
    }

    void makeRaster(const char *vertexShader,
                    const char *geometryShader,
                    const char *fragmentShader)
    {
        mHandle = CompileProgramWithGS(vertexShader, geometryShader, fragmentShader);
    }

    void makeRasterWithTransformFeedback(const char *vertexShader,
                                         const char *fragmentShader,
                                         const std::vector<std::string> &tfVaryings,
                                         GLenum bufferMode)
    {
        mHandle = CompileProgramWithTransformFeedback(vertexShader, fragmentShader, tfVaryings,
                                                      bufferMode);
    }

    void makeBinaryOES(const std::vector<uint8_t> &binary, GLenum binaryFormat)
    {
        mHandle = LoadBinaryProgramOES(binary, binaryFormat);
    }

    void makeBinaryES3(const std::vector<uint8_t> &binary, GLenum binaryFormat)
    {
        mHandle = LoadBinaryProgramES3(binary, binaryFormat);
    }

    bool valid() const { return mHandle != 0; }

    GLuint get() { return mHandle; }

    operator GLuint() { return get(); }

  private:
    GLuint mHandle;
};

#define ANGLE_GL_EMPTY_PROGRAM(name) \
    GLProgram name;                  \
    name.makeEmpty();                \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_PROGRAM(name, vertex, fragment) \
    GLProgram name;                              \
    name.makeRaster(vertex, fragment);           \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_PROGRAM_WITH_GS(name, vertex, geometry, fragment) \
    GLProgram name;                                                \
    name.makeRaster(vertex, geometry, fragment);                   \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(name, vertex, fragment, tfVaryings, bufferMode) \
    GLProgram name;                                                                         \
    name.makeRasterWithTransformFeedback(vertex, fragment, tfVaryings, bufferMode);         \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_COMPUTE_PROGRAM(name, compute) \
    GLProgram name;                             \
    name.makeCompute(compute);                  \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_BINARY_OES_PROGRAM(name, binary, binaryFormat) \
    GLProgram name;                                             \
    name.makeBinaryOES(binary, binaryFormat);                   \
    ASSERT_TRUE(name.valid())

#define ANGLE_GL_BINARY_ES3_PROGRAM(name, binary, binaryFormat) \
    GLProgram name;                                             \
    name.makeBinaryES3(binary, binaryFormat);                   \
    ASSERT_TRUE(name.valid())

}  // namespace angle

#endif  // ANGLE_TESTS_GL_RAII_H_
