[英]How to use gtkmm with EGL
我发现这篇博客文章有一个关于如何在 GTK 中使用 EGL 的例子。 但是我在我的项目中使用了 gtkmm,因此我需要找到如何使用它
我需要找到这些功能:
gdk_x11_display_get_xdisplay
gtk_widget_get_display
gdk_x11_window_get_xid
gtk_widget_get_window
gtk_widget_get_allocated_width
gtk_widget_get_allocated_height
在 gtkmm 上。 他们的 gtkmm 可能返回类实例,所以我需要弄清楚如何获取这些类指向的 C 对象
如果我们看一下 GTK 函数,让我们看一个例子:
Display* gdk_x11_display_get_xdisplay ()
它返回一个Display*
。 同时,在用于 Display的gtkmm 中,我们看到gobj()
返回 C 对象GdkDisplay*
:
GdkDisplay* gobj ()
这不是同一个对象。
那么,如何找到这些函数的 gtkmm 版本呢?
更新2:
根据评论中的建议,我做了一个最小的可重现示例:
#include <iostream>
#include <gtkmm.h>
#include <epoxy/gl.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GL/gl.h>
class MyOpenGLArea : public Gtk::Window
{
public:
MyOpenGLArea()
{
set_title("Test");
set_default_size(640, 360);
add(vBox);
glArea.set_hexpand(true);
glArea.set_vexpand(true);
glArea.set_auto_render(true);
vBox.add(glArea);
glArea.signal_realize().connect(sigc::mem_fun(*this, &MyOpenGLArea::realize));
glArea.signal_render().connect(sigc::mem_fun(*this, &MyOpenGLArea::render), false);
glArea.show();
vBox.show();
};
public:
Gtk::GLArea glArea;
Gtk::Box vBox{Gtk::ORIENTATION_VERTICAL, false};
void realize()
{
EGLBoolean eglStatus;
EGLConfig eglConfig;
EGLint n_config;
EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
eglDisplay = eglGetDisplay((EGLNativeDisplayType)gdk_x11_display_get_xdisplay(glArea.get_display()->gobj()));
eglStatus = eglInitialize(eglDisplay, NULL, NULL);
if (!eglStatus)
{
printf("Error at eglInitialize\n");
switch (eglStatus)
{
case EGL_BAD_DISPLAY:
printf("EGL_BAD_DISPLAY\n");
break;
case EGL_NOT_INITIALIZED:
printf("EGL_NOT_INITIALIZED\n");
break;
case EGL_FALSE:
printf("EGL_FALSE\n");
break;
}
}
eglStatus = eglChooseConfig(eglDisplay, context_attribs, &eglConfig, 1, &numConfigs);
if (!eglStatus)
{
printf("Error at eglChooseConfig\n");
switch (eglStatus)
{
case EGL_BAD_DISPLAY:
printf("EGL_BAD_DISPLAY\n");
break;
case EGL_BAD_ATTRIBUTE:
printf("EGL_BAD_ATTRIBUTE\n");
break;
case EGL_NOT_INITIALIZED:
printf("EGL_NOT_INITIALIZED\n");
break;
case EGL_BAD_PARAMETER:
printf("EGL_BAD_PARAMETER\n");
break;
case EGL_FALSE:
printf("EGL_FALSE\n");
break;
}
}
};
virtual bool render(const Glib::RefPtr<Gdk::GLContext> &context)
{
glDraw();
glFinish();
return true;
}
void glDraw()
{
}
private:
EGLDisplay eglDisplay;
EGLSurface eglSurface;
EGLContext eglContext;
int numConfigs;
};
int main(int argc, char **argv)
{
auto app = Gtk::Application::create(argc, argv, "");
MyOpenGLArea myOpenGLArea;
return app->run(myOpenGLArea);
}
这是输出:
libEGL warning: DRI2: failed to authenticate
Error at eglChooseConfig
EGL_FALSE
我得到的显示仍然有问题
根据https://www.bassi.io/articles/2015/02/17/using-opengl-with-gtk/
GTK+ 中的 OpenGL 支持需要核心 GL 配置文件,因此它无法与固定管道 API 一起使用,该 API 在 OpenGL 3.2 及更高版本之前很常见。 这意味着您将无法使用 glRotatef() 或 glBegin()/glEnd() 对之类的 API,或任何此类内容。
因此,您需要切换到使用可编程管道(即着色器,以及所有需要的)以开始使用 Gtk::GLArea 小部件。
我需要找到这些功能:
gdk_x11_display_get_xdisplay gtk_widget_get_display gdk_x11_window_get_xid gtk_widget_get_window gtk_widget_get_allocated_width gtk_widget_get_allocated_height
在 gtkmm 上。
其中一些在 gtkmm 中有很容易找到的包装器。 毕竟,有一个命名系统。 一个名为“ gtk_<thing>_<action>
”的 GTK 函数通常对应于Gtk
命名空间中(大写的) <Thing>
类的<action>
方法——即Gtk::<Thing>::<action>
。
Gtk::Widget::get_display
Gtk::Widget::get_window
Gtk::Widget::get_allocated_width
Gtk::Widget::get_allocated_height
这留下了 X11 交互。 我不知道 GDK 的“x11”部分有 C++ 包装器,因此您可能需要混合使用 C 和 C++ API 。 请注意几个名称相似的类。 例如, Gtk::Window
和Gdk::Window
是不同的类。 此外, Display
(没有命名空间)和GdkDisplay
是不同的类。 (特别是, Display
既不是 GTK 的一部分,也不是 GDK 的一部分;它是 X11 的一部分。)
根据系统应该如何工作(这意味着我还没有测试过),以下几行应该是从 gtkmm 调用 GDK 的 X11 交互功能的一种方式。 这些假设变量已声明为Gtk::GLArea glArea
,例如示例代码中的数据成员。
gdk_x11_display_get_xdisplay(glArea.get_display()->gobj());
gdk_x11_window_get_xid(glArea.get_window()->gobj());
get_display
方法返回一个指向Gdk::Display
的智能指针。 调用指向对象的gobj
方法会给出一个GdkDisplay*
,然后可以将其提供给gdk_x11_display_get_xdisplay
。 类似地, get_window
返回一个指向Gdk::Window
的智能指针,它可以转换为指向gdk_x11_window_get_xid
的 C 对象的gdk_x11_window_get_xid
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.