简体   繁体   English

退出OpenGL应用程序时清理

[英]Cleaning up when exiting an OpenGL app

I have an an OSX OpenGL app I'm trying to modify. 我有一个OSX OpenGL应用程序,我正在尝试修改。 When I create the app a whole bunch of initialisation functions are called -- including methods where I can specify my own mouse and keyboard handlers etc. For example: 当我创建应用程序时,会调用一大堆初始化函数 - 包括我可以指定自己的鼠标和键盘处理程序等的方法。例如:

glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
glutInitWindowPosition(100, 100);
glutInitWindowSize(700, 700);
glutCreateWindow("Map Abstraction");
glutReshapeFunc(resizeWindow);
glutDisplayFunc(renderScene);
glutIdleFunc(renderScene);
glutMouseFunc(mousePressedButton);
glutMotionFunc(mouseMovedButton);
glutKeyboardFunc(keyPressed);

At some point I pass control to glutMainLoop and my application runs. 在某些时候,我将控制传递给glutMainLoop并运行我的应用程序。 In the process of running I create a whole bunch of objects. 在运行过程中,我创建了一大堆对象。 I'd like to clean these up. 我想清理它们。 Is there any way I can tell GLUT to call a cleanup method before it quits? 有什么办法可以告诉GLUT在退出之前调用一个清理方法吗?

In freeglut if you call this: 在freeglut中,如果你这样称呼:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION)

Prior to entering the main loop, then when the window closes the main loop function will return and you can do your cleanup. 在进入主循环之前,当窗口关闭时,主循环功能将返回,您可以进行清理。

It's worth noting that at that stage the GL context has already been destroyed so you can't perform any GL operations. 值得注意的是,在那个阶段,GL上下文已被破坏,因此您无法执行任何GL操作。

I fell for this once in a while, trying to play with GLUT. 我偶尔摔倒了,试着玩GLUT。 I tried everything I could thing of, including IIRC exiting glutMainLoop through an exception catched in the main function but... 我尝试了所有我能做到的事情,包括IIRC通过主要功能中的异常退出glutMainLoop但是......

When using glutMainLoop 使用glutMainLoop

My solution was the following : Create a global Context object, who will be owner of all your resources, and free those resources in the destructor. 我的解决方案如下:创建一个全局Context对象,该对象将是所有资源的所有者,并在析构函数中释放这些资源。

This global Context object destructor will be called immediately after exiting the main. 退出main后将立即调用此全局Context对象析构函数。

It is important Context is a global variable, and not a variable declared in the main function, because for a reason that still escapes me (I still fail to see the interest of this implementation choice), glutMainLoop won't return. 重要的是Context是一个全局变量,而不是在main函数中声明的变量,因为有一个原因仍然让我失望(我仍然没有看到这个实现选择的兴趣),glutMainLoop将不会返回。

In my Linux box (Ubuntu), the destructor is called correctly. 在我的Linux机器(Ubuntu)中,正确调用了析构函数。 I guess it should work the same way on Windows and MacOS, too. 我想它也应该在Windows和MacOS上以相同的方式工作。

Note that this is the C++ version of Francisco Soto's atexit() solution, without the possible limitations. 请注意,这是Francisco Soto的atexit()解决方案的C ++版本,没有可能的限制。

Using glutMainLoopEvent 使用glutMainLoopEvent

Apparently, some implementations have a glutMainLoopEvent which can be used instead of calling glutMainLoop. 显然,一些实现有一个glutMainLoopEvent,可以用来代替调用glutMainLoop。

http://openglut.sourceforge.net/group__mainloop.html#ga1 http://openglut.sourceforge.net/group__mainloop.html#ga1

glutMainLoopEvent will only resolve the pending events, and then return. glutMainLoopEvent只会解决挂起的事件,然后返回。 Thus, you must provide the event loop (the for(;;) construct) around the call to glutMainLoopEvent , but this way, you can work with a GLUT and still have control on the event loop, and free your resources when needed. 因此,您必须围绕对glutMainLoopEvent的调用提供事件循环( for(;;)构造),但这样,您可以使用GLUT并仍然可以控制事件循环,并在需要时释放资源。

如果你使用的是C / C ++,你可以使用atexit()调用吗?

I ended up using paercebal's answer above, along with his previous attempt at using a try/catch block around glutMainLoop() as well. 我最后使用了paercebal的答案,以及他之前尝试在glutMainLoop()周围使用try / catch块。 Why? 为什么? Because I wanted to cleanup properly no matter how it was shutdown. 因为我想要无论如何关闭都要正确清理。 The global Context object will get destroyed properly if the app exits cleanly, which is what happens if you close out the app by closing the window (or quitting the app on OS X). 如果应用程序完全退出,则全局Context对象将被正确销毁,如果您通过关闭窗口(或在OS X上退出应用程序)关闭应用程序,会发生这种情况。 But if you hit ctrl-C in the terminal where it was launched (or send it a SIGINT), the cleanup does not happen. 但是如果你在启动它的终端点击ctrl-C(或发送一个SIGINT),清理就不会发生。 To handle this, I added the following to my code: 为了解决这个问题,我在代码中添加了以下内容:

static bool exitFlag = false;

static void sighandler(int sig) {
  exitFlag = true;
}

static void idleFunc() {
  if(exitFlag) {
    throw NULL;
  }
}

And then in main(): 然后在main()中:

signal(SIGINT, sighandler);
glutIdleFunc(idleFunc);

try {
  glutMainLoop();
} catch(...) {}

This isn't the prettiest bit of code, but it does handle both cases of exiting the program correctly. 这不是最漂亮的代码,但它确实处理了正确退出程序的两种情况。

One catch (no pun intended) -- any code you place after the catch() block will not be called if you close the window/quit the app normally. 一个问题(没有双关语) - 如果关闭窗口/正常退出应用程序,则不会调用catch()块之后放置的任何代码。 You have to place your cleanup code in the global Context object as shown in paercebal's answer. 您必须将清理代码放在全局Context对象中,如paercebal的答案所示。 All this code is doing is allow the SIGINT signal to be used to get out of the glutMainLoop(). 所有这些代码都是允许使用SIGINT信号离开glutMainLoop()。

I think the real lesson here is that for anything really complex, GLUT is just not going to cut it. 我认为这里真正的教训是,对于任何非常复杂的事情,GLUT都不会削减它。

Typically you don't need to do this; 通常你不需要这样做; just exiting the application will tear down any resources you've allocated. 退出应用程序将删除您分配的任何资源。 Even if you've captured the screen, it should go back to normal. 即使您已经捕获了屏幕,它也应该恢复正常。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM