#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
using namespace glm;
#include <cassert>
#include <iostream>
#include <thread>
#include <mutex>
#include <set>
#include <map>
#include <concepts>
using namespace std;
namespace toz::gl
{
template <typename ENUM>
static constexpr auto enumValue(ENUM e)
{
return static_cast<underlying_type_t<ENUM>>(e);
}
enum class CullFace : GLenum
{
Front = GL_FRONT,
Back = GL_BACK,
};
enum class Key
{
Escape = GLFW_KEY_ESCAPE,
};
class Context
{
protected:
GLFWwindow* window = nullptr;
public:
struct CreateArg
{
const char* title = "";
GLFWmonitor* monitor = nullptr;
Context* shared = nullptr;
};
protected:
Context(uint version, uvec2 size, const CreateArg& args = { })
{
assert(args.title);
assert(version >= 100);
static set<thread::id> invoked;
assert(invoked.emplace(this_thread::get_id()).second);
static struct AllContext
{
AllContext() { glfwInit(); }
~AllContext() { glfwTerminate(); }
} ac;
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, version / 100);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, version % 100 / 10);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(
size.x,
size.y,
args.title,
args.monitor,
args.shared ? args.shared->window : nullptr);
assert(window);
glfwMakeContextCurrent(window);
assert(gladLoadGLLoader((GLADloadproc)glfwGetProcAddress));
}
virtual ~Context()
{
glfwDestroyWindow(window);
}
virtual void init() = 0;
virtual bool update() = 0;
public:
bool keyPressing(int ch)
{
return glfwGetKey(window, ch) == GLFW_PRESS;
}
bool keyPressing(Key key)
{
return keyPressing(enumValue(key));
}
bool shouldClose()
{
return glfwWindowShouldClose(window);
}
void start()
{
thread_local bool invoked = false;
assert(!invoked);
invoked = true;
init();
do
{
glfwPollEvents();
} while (!update());
}
};
struct Function330
{
auto getError()
{
return glGetError();// 110, just for test
}
};
struct Function450 : public Function330
{
void cullFace(CullFace face)
{
glCullFace(enumValue(face));// 110, just for test
}
};
}
using namespace toz::gl;
class App final : public Context, Function450
{
public:
App(uvec2 size, const CreateArg& args = { }) : Context(450, size, args) { }
template <typename... ARG>
static auto create(ARG&&... args)
{
return thread([&] { App(forward<ARG>(args)...).start(); });
}
private:
void init() override
{
};
bool update() override
{
if (keyPressing('A'))
{
cullFace(CullFace::Front);
cout << getError() << endl;
}
if (keyPressing('B'))
{
cullFace(CullFace(998));
cout << getError() << endl;
}
return shouldClose() || keyPressing(Key::Escape);
};
};
int main()
{
auto a = App::create(uvec2{ 800, 600 });
auto b = App::create(uvec2{ 800, 600 });
a.join();
b.join();
}