Freeglut error: ERROR: No display callback registered for window 1 when destroyed a window and created a new window - opengl

I want to create the opengGL context using freeglut. I will first decide the which context to by checking the supporting version using glew and some other parameters. I know for glew to work, it needs a opengl context. So I first create a context using glutCreateWindow, then check the supported version and then set the version required using the glutInitContextVersion() and destroy the previous window using glutDestroyWindow and recreate the new window by using glutCreateWindow. I get this error Freeglut error: ERROR: No display callback registered for window 1 (I checked 1 is ID for my previous window which I destroyed) . Following is my code
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(900, 600);
int winID = glutCreateWindow("Rotating Cube"); //winID is 1 here
glewExperimental = GL_TRUE;
glewInit();
//I decide the context on some other parameters also except the supported version reported by glew.
//I have tested this with opengl 3.2 core profile as well.
//This is not working even if I forcefully set the opengl version to 2.0
if (glewIsSupported("GL_VERSION_3_1"))
{
glutInitContextVersion (3, 1);
glutInitContextFlags (GLUT_FORWARD_COMPATIBLE);
//glutInitContextVersion (3, 2);
//glutInitContextFlags (GLUT_CORE_PROFILE);
}
else if (glewIsSupported("GL_VERSION_2_0"))
{
glutInitContextVersion (2, 0);
}
glutDestroyWindow(winID);
winID = glutCreateWindow("Rotating Cube"); //winID is 2 here
glutSetWindow(winID);
glutDisplayFunc(RenderScene);
glutIdleFunc(RenderScene);
glutReshapeFunc(ChangeSize);
glutKeyboardFunc(ProcessNormalKeys);
glutSpecialFunc(ProcessSpecialKeys);
glutMainLoop();
I think I need to do this as a openGL context is always required for glew to work. I already tried setting the display function on first window as well (though I know I am going to destroy it) but that also didn't work. I am setting the current window to new window and then calling the glutMainLoop. So I think this should work
According to answer by rhashimoto, I tried to put the destroy command at different positions
if (g_winID>=0)
{
glutDestroyWindow(g_winID);
g_winID = -1;
}
I put the destroy command at begining of reshape callback
ERROR: No display callback registered for window 1
The I put the destroy command at beginning of display function
ERROR: Function <glutSwapBuffers> called with no current window defined.
If I put this at end of Display callback, it does not give error but the displayed scene is not correct. Somethings are missing from the scene
So is there some specific callback function I need to put this display command? I dont think there is any destroy callback I can set. yes there is glutCloseFunc but I think that is meant to be called when window is being destroyed that is when glutDestroyWindow has been called on window

I think you can argue that this is a FreeGLUT bug, either in the implementation or the documentation. It looks like glutDestroyWindow() needs to be called from a GLUT callback to work properly.
glutDestroyWindow() mainly puts the window on a list to be destroyed, as well as clearing all callbacks (except a destroy callback). This is probably why setting the display function didn't work for you - it was removed when you called glutDestroyWindow().
Windows are actually destroyed at the end of each main loop. So on the first time through the loop, your window still exists. The fact that it has no display callback makes GLUT unhappy.
The best workaround is probably to arrange to call glutDestroyWindow() only via one of the GLUT callbacks. I don't know if this will make the window briefly flash on the screen. My guess is it won't, but it might depend on the platform.

Related

when using ImGui with Glut it does not show any objects

I'm coding a rendering engine in C++ with OpenGL and GLUT and trying to integrate ImGUI into my engine, but I have a problem. it either renders the gui and only the background (no objects), or it only renders the objects and background (no GUI). This code:
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(sizeChange);
glutSpecialUpFunc(releaseKey);
glutSpecialFunc(pressKey);
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsLight();
ImGui_ImplGLUT_Init();
ImGui_ImplGLUT_InstallFuncs();
ImGui_ImplOpenGL2_Init();
creates this:
and this code:
IMGUI_CHECKVERSION();
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
ImGui::StyleColorsLight();
ImGui_ImplGLUT_Init();
ImGui_ImplGLUT_InstallFuncs();
ImGui_ImplOpenGL2_Init();
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutReshapeFunc(sizeChange);
glutSpecialUpFunc(releaseKey);
glutSpecialFunc(pressKey);
creates this:
The problem is that GLUT callback handlers in both of your examples are set both manually (glut...Func) and by ImGui via ImGui_ImplGLUT_InstallFuncs. The latter sets default ImGui handlers for many GLUT callbacks (see the source), in particular glutReshapeFunc is used to set current window resize callback to ImGui_ImplGLUT_ReshapeFunc (source), which sets internal ImGui display size according to given parameters.
When in the second example glutReshapeFunc(sizeChange) gets called, ImGui handler gets unset, so it doesn't get called during window resize (which, in particular, happens also before the first display according to the GLUT documentation), which leaves internal ImGui state not set properly. In the first example, the situation is reversed - your reshape handler sizeChange gets unset and replaced by ImGui one, so initialization and rendering of your cube doesn't go as intended because sizeChange never gets called.
To resolve this, you can omit ImGui_ImplGLUT_InstallFuncs and use your GLUT handlers while, apart from custom logic, calling default ImGui handlers from them if they are present and their functionality is needed (you can see what default handlers exist by inspecting the sources linked above). E.g. you can change sizeChange like this:
void sizeChange(int w, int h)
{
// Your logic
// ...
ImGui_ImplGLUT_ReshapeFunc(w, h);
}
If you want key presses and releases to be registered by ImGui as well as your own code, you may change releaseKey and pressKey in a similar way by adding, respectively, ImGui_ImplGLUT_SpecialUpFunc and ImGui_ImplGLUT_SpecialFunc calls to them.

How to check window is open via openGL or Glut

I have seen a method in SFML called isOpen which checks if the window is open.
Is there any similar equivalent in openGL or GLUT which checks if the window is open?
OpenGL render to a framebuffer attached to an OpenGL rendering context. The rendering context may have been created from a window connecting the (default) framebuffer to the window, but this is out of scope for the OpenGL spec.
As for GLUT you can use glutSetWindow to set the window id you want to check whether or not it exist, and then do glutGetWindow. If it returns the window id previously set the window exist. If not, glutSetWindow obviously failed because the window does not exist.
Whether or not this is true seems implementation dependent, but I doubt anyone would be stupid enough to not implement error handling in such a trivial case.

closing multiple GLUT windows independently

In my GLUT program i have created two windows. when i try to close one window entire program shuts down. can anyone tell how to avoid it.
My code to create window is as follows
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100,100);
glutInitWindowSize(ww,wh);
window1 = glutCreateWindow("sample");
glutReshapeFunc(changeSize);
glutIdleFunc(renderScene);
glutDisplayFunc(renderScene);
window3 = glutCreateWindow("sample2");
glutReshapeFunc(changeSize);
glutDisplayFunc(renderScene2);
glutIdleFunc(renderScene2);
glutMouseFunc(mouse);
glutPostRedisplay();
glutMainLoop();
return 1;
}
I don't recall GLUT being able to close windows independently in the same thread, like that. As you only use a single glutMainLoop() call to get them going, thereby when the main loop is killed for one window, it's killed for all of them.
You could try creating the windows in their own Thread. That might work, but I'm not entirely sure.
Something else you could try, is to use GLFW instead, using GLFW, you need to create the main loop etc, yourself. Bottom line, that's much easier to use and it gives you a lot more control, over your OpenGL programs. Also if you don't already have it, you should get something like GLEW.
You've just left the capabilities of GLUT with this demand. But you're lucky: GLUT =/= OpenGL and there are many other frameworks that will satisfy your needs. How about you take a look at Qt, which offers you not only a runtime environment and a OpenGL widget, but also a large set of widgets to draw UI elements with.

Trouble initializing shaders before resize on wxGLCanvas

wxGLCanvas seems to hate OpenGL shaders, by not providing an initialization callback function like the one in Qt; Making me unable to create the shaders even after creating the context myself in the constructor, like so:
m_context = new wxGLContext(this);
Also tried:
SetCurrent(*m_current);
Still no luck and GLEW keeps throwing "Missing GL Version" which indicates that the context has not been created (from Google).
I have tried:
Using WX_EVT() for show and activate events, still no luck.
Initializing shaders in the resize event, still no luck.
Is there any way to make wxGLCanvas call my initialization function before anything else?
There is no specific method to initialize OpenGL that gets called before everything else, but after the window was shown, in wxWidgets. You can roll your own with a member variable that indicates whether OpenGL has been initialized, and doing your initialization in the Paint event handler if the variable is false.
In my experience it is safest to issue all OpenGL commands only in the Paint event handler, so in your Size event handler, you should save the new viewport size and update the projection matrix in your Paint handler (or just query the viewport size using wxGLCanvas' GetClientRect() method).
In the examples in http://wiki.wxwidgets.org/WxGLCanvas it is suggested that you do the initialization on the paint event (EVT_PAINT(BasicGLPane::render)), as said by Kristian Duske in the comments above.
Instead you can initialize OpenGL in any other place, you just have to show the wxwidget window or frame first (e.g. frame->Show() ).
I do this:
initialize wxGLCanvas (in my case with a wxFrame frame as parent)
canvas = new Canvas( (wxFrame*) frame, args);
show window
frame->Show()
Now call your custom OpenGL initialization method in the canvas class (only once):
set context
wxGLCanvas::SetCurrent(*m_context);
initialize glew:
glewExperimental = GL_TRUE;
GLenum err = glewInit();
After this I compile the shaders etc.
In the paint event then only do the drawing: glDrawArrays() and SwapBuffers()

glGenFramebuffers makes program fail to run

I have reinstalled devcpp 4.9.9.2 on windows xp virtualbox and installed glut and glew.
My original program just used glut, and shows some spheres bouncing around a room. My problem is that once I add in the line
glGenFramebuffers(1, &myBuffer);
my program fails to run. It compiles just fine. But when I run it says "Ass1.exe has encountered a problem and needs to close. We are sorry for the inconvenience.".
If I comment out this line then it works just fine, with balls bouncing around. The glGenFramebuffers is at the bottom of my setup method.
Here is a link to my code. https://dl.dropboxusercontent.com/u/13330596/Exercise1.cpp
This is the code just before I now call glewInit();
// Initialize GLUT.
glutInit(&argc, argv);
// Set display mode with an RGB colour buffer, double buffering and a depth buffer..
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH );
// Set OpenGL window size
glutInitWindowSize(1000, 1000);
// Set position of OpenGL window upper-left corner
glutInitWindowPosition(100, 100);
// Create OpenGL window with title
glutCreateWindow("Dissertation");
glewInit();
You must call glewInit(); before you can use extended functionality. Probably you didn't so the functions pointers are still null pointer. glewInit must be called after a context has been created and bound. In the case of using GLUT this is right after glutCreateWindow(…);