9

I have written the attached example program that uses GTK2 in conjunction with EGL and OpenGL. On my system this works fine. On the PC of friend it only will produce a black window and I cannot put my finger on why this happens. We event straces which libraries get loaded (Which are the same). My PC has a NVIDIA MX150, he has a GTX 1030, he uses Debian Strech and I use Debian buster.

I cannot put my finger on the problem. Anyways, heres the code:

#include <stdio.h>
#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)
{
    printf("REALIZE\n");
    EGLConfig egl_config;
    EGLint n_config;
    EGLint attributes[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
                            EGL_NONE };
    EGLint surf_attrs[] = {
        EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
        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_WINDOW_XID (gtk_widget_get_window (widget)), surf_attrs);
    egl_context = eglCreateContext (egl_display, egl_config, EGL_NO_CONTEXT, NULL);
}

static gboolean on_configure (GtkWidget *widget, GdkEvent *event, gpointer user_data)
{
    gtk_widget_queue_draw(widget);
    return FALSE;
}

static gboolean draw_cb (GtkWidget *widget, GdkEventExpose *expose, gpointer userdata)
{
    printf("DRAW\n");
    eglMakeCurrent (egl_display, egl_surface, egl_surface, egl_context);

    GtkAllocation alloc;
    gtk_widget_get_allocation(widget, &alloc);
    glViewport (0, 0, alloc.width, alloc.height);

    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), "expose-event", G_CALLBACK (draw_cb), NULL);
    g_signal_connect (G_OBJECT (w), "configure-event", G_CALLBACK (on_configure), NULL);
    gtk_widget_show (w);

    gtk_main ();

    return 0;
}
Andreas
  • 5,086
  • 3
  • 16
  • 36
Nidhoegger
  • 4,973
  • 4
  • 36
  • 81
  • Do you want depth test or not? On one hand you clear the GL_DEPTH_BUFFER_BIT, on the other you never enable GL_DEPTH_TEST. Though depth test is supposed to be disabled by default, some drivers think otherwise, and who knows what GTK thinks. Your `glOrtho` put near plane at 0.0, and then you put vertices on 0.0 (`glVertex2f`). With default depth test of GL_LESS nothing will ever be rendered. – Andreas May 14 '19 at 11:42
  • tried enabling depth test and tried removing tha `GL_DEPTH_BUFFER_BIT`, but nothing seems to change :/ – Nidhoegger May 14 '19 at 11:48
  • Fewer words this time; explicitly disable depth test (`glDisable(GL_DEPTH_TEST)`) after `eglMakeCurrent()` – Andreas May 14 '19 at 11:51
  • Nothing changes :( – Nidhoegger May 14 '19 at 11:53
  • 1
    Ok, one less factor to consider. Not seeing any `glGetError` or `eglGetError` in the code. Assert the return of `eglGetError` right after `eglMakeCurrent` and `glGetError()` right before `eglSwapBuffers`. Both should indicate no error if all is well from API usage standpoint. – Andreas May 14 '19 at 11:59
  • ill implement that and get back with the results. In any way, thanks you very much! – Nidhoegger May 14 '19 at 12:02
  • Everything returns `EGL_SUCCESS`, but still only a black screen. – Nidhoegger May 14 '19 at 12:19
  • Ok, got no more ideas based on the code. If possible use a graphics debugger such as CodeXL to step through the graphics calls, analyze the results, and compare OpenGL states between the machines. Maybe some state is enabled when it shouldn't be. Good luck – Andreas May 14 '19 at 12:34
  • What makes me think is that changing the clear color will actually draw a different color than black, so something is working there. Can it be that it draws UNDERNEATH the black value? – Nidhoegger May 14 '19 at 13:49
  • I dont think its a problem with EGL, I get the clearColor on the screen! but nothing else... – Nidhoegger May 14 '19 at 15:12
  • @Nidhoegger It's just a arbitrary guess, but have you tried `glOrtho (0, 100, 0, 100, -1, 1);` – Rabbid76 May 14 '19 at 15:27
  • tried it, does not work either :( I dont know why its only failing on this one PC – Nidhoegger May 14 '19 at 15:30
  • @Nidhoegger Silly question, the graphics driver is up to date, isn't it? – Rabbid76 May 14 '19 at 17:56
  • its the one in debian strech, but up to date... – Nidhoegger May 14 '19 at 17:58
  • I made it work. By using `glGetError` after `glEnd` it suddenly works... What the...? – Nidhoegger May 14 '19 at 17:59
  • @Nidhoegger sounds like the image is properly rendered but not delivered to screen. In that case the issue is in X11 magic, and `XSync(eg_display, False)` after `eglSwapBuffers()` should do the trick. Note how this should not be necessary if you application render in real-time; single frames may be "delayed". – Andreas May 15 '19 at 07:09
  • Hmmm let me say at this point: a am really thankful for all your comments!. The XSync call wont change anything :( – Nidhoegger May 15 '19 at 07:43
  • Does [this sample](https://github.com/hidefromkgb/ogl_stub) work? It uses a slightly different approach to GL, passing it through GTKGLext. – hidefromkgb May 16 '19 at 19:01
  • I did this to NOT use GTKglext. Also GTKGLext uses GLX, not EGL – Nidhoegger May 16 '19 at 20:18
  • @Nidhoegger But still, does GLX-based approach work? This has to be checked to differentiate between an EGL stack problem and a problem in GL itself. – hidefromkgb May 16 '19 at 20:31
  • GLX works. And gtkglext also – Nidhoegger May 16 '19 at 21:15
  • Well this is funny but, for me it only works with gtk2 (shows multi-colored triangle) but not with gtk3 (shows white window). ie. this works: `gcc -D_FORTIFY_SOURCE=2 -O2 $(pkg-config --cflags gtk+-2.0) a.c $(pkg-config --libs gtk+-2.0) $(pkg-config --libs egl) $(pkg-config --libs gl)`(i get REALIZE and two DRAW), with gtk3 I get `(a.out:10983): GLib-GObject-WARNING **: 13:03:14.703: ../glib/gobject/gsignal.c:2523: signal 'expose-event' is invalid for instance '0x5e4b919e22a0' of type 'GtkWindow' REALIZE` aside from the`warning: ‘gtk_widget_set_double_buffered’ is deprecated` at compile time) –  May 20 '19 at 11:05
  • this is not funny in any way as the `expose` event is renamed to `draw` in GTK3. So connecting `expose` instead of `draw` you will never actually draw... – Nidhoegger May 20 '19 at 11:12
  • EGL is not supported on Nvidia GPUs without installing additional software. – Tara May 23 '19 at 03:52
  • why does nvidia provide a sperate EGL lib then? Do you have additional infos on this? – Nidhoegger May 23 '19 at 07:41

0 Answers0