簡體   English   中英

如何在 EGL 中使用 gtkmm

[英]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* 同時,在用於 Displaygtkmm 中,我們看到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>

這留下了 X11 交互。 我不知道 GDK 的“x11”部分有 C++ 包裝器,因此您可能需要混合使用 C 和 C++ API 請注意幾個名稱相似的類。 例如, Gtk::WindowGdk::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM