Можно ли сделать окно X11 OpenGL способным после его создания? - PullRequest
7 голосов
/ 12 февраля 2010

Я хочу иметь возможность рендеринга в X Window, учитывая только его идентификатор.

В этом случае у меня есть окно, созданное в python с помощью gtk.

Я могу получить идентификатор окна gtk.Drawable и передать его в мой модуль C Python, но могу ли я затем сделать вызовы OpenGL для него?

Мне известно о gtkglext, но я бы не стал его использовать, если это возможно.

Обновление 1:

Хорошо, поэтому (довольно очевидно, теперь, когда я это вижу) Вы просто делаете XCreateWindow с родителем идентификатора окна, который вы получаете из gtk.window.xid, используя правильные флаги для окна opengl, и эй presto.

Единственная проблема в том, что я не могу заставить его работать, если в окне нет нескольких виджетов, в противном случае кажется, что xid представляет окно, которое покрывает все окно верхнего уровня. Не уверен, как это исправить.

Обновление 2: Оказывается, что если у вас есть окно GL того же размера, что и верхний уровень, то окно верхнего уровня не будет получать события экспозиции, пока в окне gl не будут заменены буферы. Вам просто нужно поменяться буферами и все будет хорошо.

Обновление 3:

Чтобы ответить на комментарий @ babele:

На этой странице в документации по Python GTK говорится, как сделать окно GTK из существующего XID. После этого вам просто нужно помнить, чтобы продолжать вызывать glXSwapBuffers для этого окна (если это окно с буферизацией opengl, в противном случае оно должно работать только при использовании window_foreign_new).

Итак, процесс идет:

  1. Создайте виджет gtk, который будет содержать ваше окно OpenGL (a DrawingArea - хороший выбор - вы не можете использовать, например, метку, так как у нее не будет своего собственного xid)
  2. Получить окно виджета gtk.gdk.Window ( документы )
  3. Получить xid из gtk.gdk.Window (вызвать это окно W1)
  4. Передайте его на ваш C / C ++ код
  5. Создайте окно с поддержкой opengl (W2) как дочернее для W1
  6. Передайте xid W2 обратно питону
  7. Используйте window_foreign_new с xid для W2 для создания нового объекта gtk.gdk.window
  8. Каждый раз, когда вы вызываете glXSwapBuffers в W2, gtk должен иметь возможность реагировать на выставленные события.

Один из моментов, который меня действительно поразил, это то, что если W2 покрывает весь W1, то W1 не будет получать события, пока не будут заменены буферы W2. Это особенно сбивает с толку, если W1 является окном верхнего уровня, так как может случиться так, что на вашем экране вообще ничего не появится (окно есть, но выглядит так, как будто оно скрыто за ним, пока оно не будет нарисовано, чего не произойдет, пока оно не появится). получает разоблачающее событие).

Также обратите внимание, что вам придется вручную изменять размер W2, подключаясь к событиям gtk resize. Вы можете сделать это, подключившись к этому сигналу , затем вызвав эту функцию в обработчике и передав результаты в ваш модуль c / c ++, где вы можете соответствующим образом изменить размер W2. Хорошая идея запросить минимальный размер .

1 Ответ

6 голосов
/ 12 февраля 2010

Вам не нужно создавать новое окно, вы передаете существующее окно в glXMakeCurrent ().
В текущей настройке вам необходимо:

  1. XGetWindowAttributes () для извлечения визуала, с которым было создано окно
  2. glXCreateContext () с использованием этого визуального элемента
  3. glXMakeCurrent () используя этот контекст и идентификатор окна

Однако это происходит в обратном направлении, заставляя OpenGL использовать визуал, используемый для CreateWindow. Это часто работает, потому что визуал по умолчанию имеет нормальные свойства GLX, но правильное приложение будет glXChooseVisual с желаемыми свойствами GLX, а затем использует этот визуал для создания окна.

...