How to make newly created window render?

cod123 wrote on Sunday, July 12, 2015:

I try to make the program have a fullscreen toggle functionality by pressing a key. If I’m not mistaken, the only way to make a window full screen is to create it using the line

GLFWwindow* newwindow = glfwCreateWindow(width, height, "title", glfwGetPrimaryMonitor(), 0);

So in the keyboard callback function I added the following code

glfwSetWindowShouldClose(oldwindow, GL_TRUE);
//glfwDestroyWindow(oldwindow); // I read somewhere that this line destroy the context as well
GLFWwindow* newwindow = glfwCreateWindow(width, height, "title", glfwGetPrimaryMonitor(), 0);
glfwMakeContextCurrent(newwindow);

But after pressing the key the newly created window pop up and is completely black screen. Do I have to send all the objects’ drawing states from the oldwindow to the newwindow?

arampl wrote on Thursday, July 16, 2015:

Switching to fullscreen and back is a painful process (no matter what library you use).

If you simply destroy your window and create a new one, not only you lose all your states, but you also have to reload all your textures, because you also destroyed OpenGL context. This is how OpenGL itself is organised.

For textures and shaders to survive window recreation you should use context sharing. That way you’ll only need to set OpenGL states again, attach callbacks to newly created window and recreate some other OpenGL things vulnerable to window switching (textures don’t need to be reloaded).

Example code:

#include <stdlib.h>
#include <stdio.h>
#include <GLFW/glfw3.h>

GLFWmonitor	*monitor;
GLFWvidmode	*mode;
GLFWwindow	*window, *mainwindow;

int fullscreen = 0;

void recreate();

static void error(int error, const char* description)
{
	fputs(description, stderr);
}

void key_callback(GLFWwindow* window, int key, int scancode, int action, int mods)
{
   if(key == GLFW_KEY_F4 && action == GLFW_PRESS)
	{
		fullscreen = !fullscreen;
		recreate();
	}
}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glfwSwapBuffers(window);
}

void recreate()
{
	if(fullscreen)
	{
		window = glfwCreateWindow(1920, 1200, "app name", monitor, mainwindow);
		glfwDestroyWindow(mainwindow);
		mainwindow = window;
		glfwMakeContextCurrent(mainwindow);
	}
	else
	{
		window = glfwCreateWindow(800, 600, "app name", NULL, mainwindow);
		glfwDestroyWindow(mainwindow);
		mainwindow = window;
		glfwMakeContextCurrent(mainwindow);
		glfwShowWindow(mainwindow);
	}

	glfwSetKeyCallback(mainwindow, key_callback);
}

int main(int argc, char **argv)
{
	glfwSetErrorCallback(error);

	if(!glfwInit())
		return -1;

	monitor = glfwGetPrimaryMonitor();
	mode = (GLFWvidmode*)glfwGetVideoMode(monitor);

	glfwWindowHint(GLFW_VISIBLE, GL_FALSE);
	mainwindow = glfwCreateWindow(1, 1, "0", NULL, NULL);
	glfwMakeContextCurrent(mainwindow);

	recreate();

	while(!glfwWindowShouldClose(window))
	{
		render();
		glfwPollEvents();
	}

	glfwTerminate();
	return 0;
}