I’m using gtk + egl to draw something, the gl area is constructed by custom widget type and child gdk window and EGL context(i want to add a menubar also, so gl area can only be a child window).
it works fine when i open the window and resize it, but the screen turns broken/black when i maximize/restore the window.
here is my testing code:
#include <EGL/egl.h>
#include <GL/gl.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
struct _GlView {
GtkWidget parent_instance;
};
struct _GlViewClass {
GtkWidgetClass parent_class;
};
typedef struct _GlViewClass GlViewClass;
typedef struct _GlView GlView;
G_DEFINE_TYPE(GlView, gl_view, GTK_TYPE_WIDGET)
static void gl_view_init(GlView *widget) {}
static void gl_view_size_allocate(GtkWidget *widget,
GtkAllocation *allocation) {
gtk_widget_set_allocation(widget, allocation);
}
static void gl_view_class_init(GlViewClass *klass) {
GTK_WIDGET_CLASS(klass)->size_allocate = gl_view_size_allocate;
}
GtkWidget *gl_view_new() {
return (GtkWidget *)g_object_new(gl_view_get_type(), NULL);
}
static EGLDisplay *egl_display;
static EGLSurface *egl_surface;
static EGLContext *egl_context;
static void realize_cb(GtkWidget *view) {
GtkAllocation allocation;
gtk_widget_get_allocation(view, &allocation);
GdkWindowAttr window_attributes;
window_attributes.window_type = GDK_WINDOW_CHILD;
window_attributes.x = allocation.x;
window_attributes.y = allocation.y;
window_attributes.width = allocation.width;
window_attributes.height = allocation.height;
window_attributes.wclass = GDK_INPUT_OUTPUT;
window_attributes.event_mask =
gtk_widget_get_events(view) | GDK_EXPOSURE_MASK |
GDK_POINTER_MOTION_MASK | GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK | GDK_SMOOTH_SCROLL_MASK |
GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK;
gint window_attributes_mask = GDK_WA_X | GDK_WA_Y;
GdkWindow *viewWindow =
gdk_window_new(gtk_widget_get_parent_window(view), &window_attributes,
window_attributes_mask);
gtk_widget_register_window(view, viewWindow);
gtk_widget_set_window(view, viewWindow);
gdk_window_show(viewWindow);
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(view)));
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(viewWindow), NULL);
egl_context = eglCreateContext(egl_display, egl_config, EGL_NO_CONTEXT, NULL);
}
static void size_allocate_cb(GtkWidget *widget, GdkRectangle *rect,
void *userdata) {
gdk_window_move_resize(gtk_widget_get_window(widget), rect->x, rect->y,
rect->width, rect->height);
}
static gboolean draw_cb(GtkWidget *widget, void *cr, gpointer userdata) {
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;
GtkWidget *view;
gtk_init(&argc, &argv);
w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
view = gl_view_new();
gtk_container_add(GTK_CONTAINER(w), view);
gtk_widget_set_double_buffered(view, FALSE);
gtk_widget_set_has_window(view, FALSE);
g_signal_connect(G_OBJECT(view), "realize", G_CALLBACK(realize_cb), NULL);
g_signal_connect(G_OBJECT(view), "size-allocate",
G_CALLBACK(size_allocate_cb), NULL);
g_signal_connect(G_OBJECT(view), "draw", G_CALLBACK(draw_cb), NULL);
gtk_widget_show_all(w);
gtk_main();
return 0;
}
compile:
cc `pkg-config --cflags --libs gtk+-3.0 egl gl` -Wno-deprecated-declarations test.c -o test