Очистка при выходе из приложения OpenGL - PullRequest
8 голосов
/ 22 апреля 2010

У меня есть приложение OSX OpenGL, которое я пытаюсь изменить. Когда я создаю приложение в целом вызывается множество функций инициализации, включая методы, в которых я могу указать свои собственные обработчики мыши и клавиатуры и т. д. Например:

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);

В какой-то момент я передаю управление glutMainLoop, и мое приложение запускается. В процессе работы я создаю целую кучу объектов. Я хотел бы убрать это. Можно ли как-то сказать GLUT, чтобы он вызывал метод очистки перед его завершением?

Ответы [ 5 ]

10 голосов
/ 12 октября 2011

В freeglut, если вы вызываете это:

glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_CONTINUE_EXECUTION)

Перед входом в основной цикл, затем, когда окно закроется, функция основного цикла вернется и вы сможете выполнить очистку.Стоит отметить, что на этом этапе контекст GL уже уничтожен, поэтому вы не можете выполнять какие-либо операции GL.

4 голосов
/ 22 апреля 2010

Я впадал в это время от времени, пытаясь играть с GLUT. Я перепробовал все, что мог, включая выход IIRC glutMainLoop через исключение, перехваченное в основной функции, но ...

При использовании glutMainLoop

Мое решение заключалось в следующем: создайте глобальный Context объект, который будет владельцем всех ваших ресурсов, и освободите эти ресурсы в деструкторе.

Этот глобальный Context деструктор объекта будет вызван сразу после выхода из основного.

Важно Context - это глобальная переменная, а не переменная, объявленная в основной функции, потому что по причине, которая все еще ускользает от меня (я все еще не вижу интереса к этому варианту реализации), glutMainLoop не будет вернуться.

В моей Linux-системе (Ubuntu) деструктор вызывается правильно. Я полагаю, что это должно работать одинаково и на Windows и MacOS.

Обратите внимание, что это C ++ версия решения atexit() Франциско Сото, без возможных ограничений.

Использование glutMainLoopEvent

Очевидно, в некоторых реализациях есть glutMainLoopEvent, который можно использовать вместо вызова glutMainLoop.

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

glutMainLoopEvent разрешит только ожидающие события, а затем вернет. Таким образом, вы должны предоставить цикл событий (конструкция for(;;)) вокруг вызова к glutMainLoopEvent, но таким образом вы можете работать с GLUT и по-прежнему иметь контроль над циклом событий и освобождать свои ресурсы при необходимости.

3 голосов
/ 22 апреля 2010

Если вы используете C / C ++, возможно, вы можете использовать atexit () call?

0 голосов
/ 23 июля 2014

Я закончил тем, что использовал ответ paercebal выше, вместе с его предыдущей попыткой использовать блок try / catch вокруг glutMainLoop (). Зачем? Потому что я хотел очистить правильно, независимо от того, как это было выключено. Глобальный объект Context будет уничтожен должным образом, если приложение завершится корректно, что и происходит, если вы закроете приложение, закрыв окно (или выйдя из приложения в OS X). Но если вы нажмете ctrl-C в терминале, где он был запущен (или отправите SIGINT), очистка не произойдет. Чтобы справиться с этим, я добавил в свой код следующее:

static bool exitFlag = false;

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

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

А затем в main ():

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

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

Это не самый красивый бит кода, но он обрабатывает оба случая правильного выхода из программы.

Один улов (без каламбура) - любой код, который вы поместите после блока catch (), не будет вызываться, если вы закроете окно или выйдите из приложения обычным образом. Вы должны поместить свой код очистки в глобальный объект Context, как показано в ответе paercebal. Все, что делает этот код - позволяет использовать сигнал SIGINT для выхода из glutMainLoop ().

Я думаю, что настоящий урок в том, что для чего-то действительно сложного, GLUT просто не собирается его сокращать.

0 голосов
/ 22 апреля 2010

Как правило, вам не нужно это делать; просто выход из приложения разрушит все ресурсы, которые вы выделили. Даже если вы захватили экран, он должен вернуться в нормальное состояние.

...