Skip to content

Instantly share code, notes, and snippets.

@TheVice
Created August 7, 2016 11:58
Show Gist options
  • Save TheVice/ea39ac0c21c527efe09c5e2399a01092 to your computer and use it in GitHub Desktop.
Save TheVice/ea39ac0c21c527efe09c5e2399a01092 to your computer and use it in GitHub Desktop.
Several GLFW windows in own threads
/*
* The MIT License (MIT)
*
* Copyright (c) 2016 https://github.com/TheVice/
*
*/
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <glm/glm.hpp>
#ifdef WIN32
#include <tchar.h>
#include <windows.h>
#endif
#ifndef _MSC_VER
#include <iostream>
#endif
#include <map>
#include <thread>
#include <sstream>
static std::ostringstream gErrors;
static const glm::vec4 gCornflowerBlue = { 0.392f, 0.584f, 0.929f, 1.0f };
static const GLuint gScreenWidth = 800;
static const GLuint gScreenHeight = 600;
#ifndef NDEBUG
void errorCallback(int aError, const char* aDescription)
{
gErrors << aDescription << " (Error #" << aError << ")" << std::endl;
}
#endif
void InitGlfw()
{
#ifndef NDEBUG
glfwSetErrorCallback(errorCallback);
#endif
if (!glfwInit())
{
gErrors << "glfwInit() failed" << std::endl;
throw std::runtime_error(gErrors.str());
}
}
void InitGlew()
{
const GLenum ret = glewInit();
if (GLEW_OK != ret)
{
gErrors << glewGetErrorString(ret) << std::endl;
gErrors << "glewInit() failed" << std::endl;
throw std::runtime_error(gErrors.str());
}
}
GLFWwindow* CreateWindowGLFW(const char* aTitle, GLFWmonitor* aMonitor, GLFWwindow* aShare)
{
GLFWwindow* window = glfwCreateWindow(gScreenWidth, gScreenHeight, aTitle, aMonitor, aShare);
if (!window)
{
gErrors << "glfwCreateWindow() failed" << std::endl;
throw std::runtime_error(gErrors.str());
}
return window;
}
void ProcessWindow(GLFWwindow* aWindow)
{
glfwMakeContextCurrent(aWindow);
InitGlew();
glViewport(0, 0, gScreenWidth, gScreenHeight);
while (!glfwWindowShouldClose(aWindow))
{
glClearBufferfv(GL_COLOR, 0, &gCornflowerBlue[0]);
//
glfwSwapBuffers(aWindow);
}
}
#ifndef WIN32
int main(int argc, char** argv)
{
(void)argc;
(void)argv;
#else
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdLine, int nCmdShow)
{
(void)hInstance;
(void)hPrevInstance;
(void)lpCmdLine;
(void)nCmdShow;
#endif
InitGlfw();
std::map<GLFWwindow*, std::thread> windowsAndThreads;
//
{
GLFWwindow* window1 = CreateWindowGLFW("First Window", nullptr, nullptr);
GLFWwindow* window2 = CreateWindowGLFW("Second Window", nullptr, window1);
//
std::thread windowThread1(ProcessWindow, window1);
std::thread windowThread2(ProcessWindow, window2);
//
auto windowAndThread = std::make_pair<GLFWwindow*, std::thread>(std::move(window1), std::move(windowThread1));
windowsAndThreads.insert(std::move(windowAndThread));
//
windowAndThread = std::make_pair<GLFWwindow*, std::thread>(std::move(window2), std::move(windowThread2));
windowsAndThreads.insert(std::move(windowAndThread));
}
//
bool shouldClose = false;
while (!shouldClose)
{
for (auto windowAndThread = windowsAndThreads.begin(); windowAndThread != windowsAndThreads.end();)
{
glfwPollEvents();
if (glfwWindowShouldClose(windowAndThread->first))
{
windowAndThread->second.join();
glfwDestroyWindow(windowAndThread->first);
//#if __cplusplus >= 2011103L
windowAndThread = windowsAndThreads.erase(windowAndThread);
//#else
// windowsAndThreads.erase(windowAndThread++);
//#endif
}
else
{
++windowAndThread;
}
}
if (windowsAndThreads.empty())
{
shouldClose = true;
}
}
glfwTerminate();
#ifndef NDEBUG
std::string errors = gErrors.str();
if (!errors.empty())
{
#ifdef _MSC_VER
OutputDebugStringA(errors.c_str());
#else
std::cerr << errors.c_str() << std::endl;
#endif
}
#endif
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment