http://www.tuicool.com/articles/2iQ3Ify
Using EGL with GTK+
I recently needed to port some code from GTK+ OpenGL code from GLX to EGL and I couldn't find any examples of how to do this. So to seed the Internet here is what I found out.
This is the simplest example I could make to show how to do this. In real life you probably want to do a lot more error checking. This will only work with X11; for other systems you will need to use equivalent methods in gdk/gdkwayland.h etc. For anything modern you should probably use OpenGL ES instead of OpenGL - to do this you'll need to change the attributes to eglChooseConfig and use EGL_OPENGL_ES_API in eglBindAPI.
Compile with:
gcc -g -Wall egl.c -o egl pkg-config --cflags --libs `gtk+-3.0 gdk-x11-3.0` -lEGL -lGL
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include <EGL/egl.h>
#include <GL/gl.h>
static EGLDisplay *egl_display;
static EGLSurface *egl_surface;
static EGLContext *egl_context;
static void realize_cb (GtkWidget *widget)
{
EGLConfig egl_config;
EGLint n_config;
EGLint attributes[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
EGL_NONE };
egl_display = eglGetDisplay ((EGLNativeDisplayType) gdk_x11_display_get_xdisplay (gtk_widget_get_display (widget)));
eglInitialize (egl_display, NULL, NULL);
eglChooseConfig (egl_display, attributes, &egl_config, 1, &n_config);
eglBindAPI (EGL_OPENGL_API);
egl_surface = eglCreateWindowSurface (egl_display, egl_config, gdk_x11_window_get_xid (gtk_widget_get_window (widget)), NULL);
egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, NULL);
}
static gboolean draw_cb (GtkWidget *widget)
{
eglMakeCurrent (egl_display, egl_surface, egl_surface, egl_context);
glViewport (0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget));
glClearColor (0, 0, 0, 1);
glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode (GL_PROJECTION);
glLoadIdentity ();
glOrtho (0, 100, 0, 100, 0, 1);
glBegin (GL_TRIANGLES);
glColor3f (1, 0, 0);
glVertex2f (50, 10);
glColor3f (0, 1, 0);
glVertex2f (90, 90);
glColor3f (0, 0, 1);
glVertex2f (10, 90);
glEnd ();
eglSwapBuffers (egl_display, egl_surface);
return TRUE;
}
int main (int argc, char **argv)
{
GtkWidget *w;
gtk_init (&argc, &argv);
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_double_buffered (GTK_WIDGET (w), FALSE);
g_signal_connect (G_OBJECT (w), "realize", G_CALLBACK (realize_cb), NULL);
g_signal_connect (G_OBJECT (w), "draw", G_CALLBACK (draw_cb), NULL);
gtk_widget_show (w);
gtk_main ();
return 0;
}
gulong g_signal_connect( gpointer *object,
const gchar *name,
GCallback func,
gpointer func_data );
第一个参数是要发出信号的构件,第二个参数是你想要连接的信号的名称,第三个参数是信号被捕获时所要调用的函数,第四个参数是你想传递给这个函数的数据。
void callback_func( GtkWidget *widget, gpointer callback_data ); |
第一个参数是一个指向发出信号的构件的指针,第二个参数是一个指向数据的指针,就是上面 g_signal_connect() 函数的最后一个参数传进来的数据。
注意上面回调函数的声明只是一般的形式,有些构件的特殊信号会用不同的调用参数。