我能否在创建X11窗口后使其具备OpenGL功能?

7
我希望能够仅给出窗口ID,即可渲染到一个X Window上。
在这种情况下,我已经通过gtk在python中创建了一个窗口。
我可以获得 gtk.Drawable 的窗口ID,并将其传递到我的C Python模块中,但是我能否进行OpenGL调用来渲染它?
我知道有gtkglext,但如果可能的话,我不想使用它。
更新1:
好吧,现在(显然)你只需使用正确的标志对具有父窗口ID的 XCreateWindow 进行操作,并呈现OpenGL调用。
唯一的问题是,如果窗口中没有多个小部件,则无法使其正常工作,否则似乎xid表示覆盖整个顶级窗口的窗口。 不确定如何纠正此问题。
更新2:
原来,如果您拥有与toplevel相同大小的gl窗口,则toplevel窗口将在gl窗口切换缓冲区之前不会接收到暴露事件。 您只需要不断交换缓冲区,问题就会得到解决。
更新3:

回答@babele的评论:

这个页面在Python GTK文档中说明了如何从现有的xid创建一个GTK窗口。之后,您只需要记得为该窗口继续调用glXSwapBuffers(如果它是一个OpenGL缓冲窗口,否则当您使用window_foreign_new时它应该可以正常工作)。

因此,整个过程如下:

  1. 创建一个gtk小部件,其中包含您的OpenGL窗口(DrawingArea是一个不错的选择 - 您不能使用标签,因为它没有自己的xid)
  2. 获取小部件的gtk.gdk.Window(docs
  3. 从gtk.gdk.Window获取xid(将此窗口称为W1)
  4. 将其传递给您的C / C ++代码
  5. 将支持opengl的窗口(W2)创建为W1的子项
  6. 将W2的xid传回python
  7. 使用W2的xid调用window_foreign_new以创建新的gtk.gdk.window对象
  8. 每次在W2上调用glXSwapBuffers时,gtk应该能够响应暴露事件。
如果W2完全覆盖了W1,那么在W2的缓冲区被交换之前,W1将不会接收到事件。如果W1是顶层窗口,则特别令人困惑,因为可能什么也不会显示在屏幕上(窗口在那里,但看起来像它后面的任何东西),直到它被绘制出来,这将不会发生直到它获得曝光事件。
此外,请注意您必须手动管理W2的调整大小,方法是连接到gtk resize事件。您可以通过连接到 this signal,然后在处理程序中调用this function并将结果传递给您的c / c ++模块,在那里您可以相应地调整W2的大小。建议request a minimum size

我已经找到了一种方法,可以让gtk管理手动使用XCreateWindow创建的窗口。请问能否详细解释一下如何实现呢?我正在寻找类似的代码片段,但是找不到任何东西...只有一个粗略的概述:) 谢谢! - user373149
1个回答

7
您不需要创建一个新的窗口,只需将现有窗口传递给glXMakeCurrent()即可。
在您当前的设置中,您需要执行以下操作:
  1. 使用XGetWindowAttributes()检索窗口创建时使用的视觉效果
  2. 使用该视觉效果来创建glXCreateContext()
  3. 使用该上下文和窗口id来进行glXMakeCurrent()
然而,这是反过来做的,强制OpenGL使用用于CreateWindow的视觉效果。这通常可以工作,因为默认的视觉效果具有合理的GLX属性,但正确的应用程序将使用所需的GLX属性进行glXChooseVisual,并使用该视觉效果来创建窗口。

XSetWindowAttributes怎么样?可以将窗口的Visual更改为适当的OpenGL Visual吗?这样行得通吗? - Loomchild
1
XChangeWindowAttributes无法更改窗口的Visual。您需要创建具有所需Visual的窗口。 - Nathan Kidd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接