OpenGL: drawing a triangle

Hello,

I am able to draw a triangle with OpenGL and Freeglut:

#include <GL/gl.h> /* for glClear */
#include <GL/freeglut.h> /* for glutInit */
#include <stdio.h> /* for printf */
static void display()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
	glColor3f(1, 0, 0); /* color:    red          */
	glVertex2i(-1, -1); /* position: left/bottom  */
	glColor3f(0, 1, 0); /* color:    green        */
	glVertex2i(0, 1);   /* position: center/top   */
	glColor3f(0, 0, 1); /* color:    blue         */
	glVertex2i(1, -1);  /* position: right/bottom */
	glEnd();
	glFlush();
}
static void key(unsigned char key, int x, int y)
{
	switch(key)
	{
		case 'q':
			glutLeaveMainLoop();
			break;
		default:
			break;
	}
}
int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutCreateWindow("freeglut test");
	glutDisplayFunc(display);
	glutKeyboardFunc(key);
	printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
	printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
	printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
	printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
	glutMainLoop();
	return 0;
}

The triangle is shown:

Also, I am able to draw a triangle with OpenGL and SDL2:

#include <GL/gl.h> /* for glClear */
#include <SDL.h> /* for SDL_Init */
static void display(SDL_Window *window)
{
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
	glColor3f(1, 0, 0); /* color:    red          */
	glVertex2i(-1, -1); /* position: left/bottom  */
	glColor3f(0, 1, 0); /* color:    green        */
	glVertex2i(0, 1);   /* position: center/top   */
	glColor3f(0, 0, 1); /* color:    blue         */
	glVertex2i(1, -1);  /* position: right/bottom */
	glEnd();
	glFlush();
	SDL_GL_SwapWindow(window);
}
static int key(int *loop)
{
	SDL_Event event = {0};
	while(SDL_PollEvent(&event))
	{
		switch(event.type)
		{
			case SDL_KEYDOWN:
				switch(event.key.keysym.sym)
				{
					case SDLK_ESCAPE:
					case SDLK_q:
						*loop = 0;
				}
				break;
			case SDL_WINDOWEVENT:
				switch(event.window.event)
				{
					case SDL_WINDOWEVENT_CLOSE:
						*loop = 0;
				}
		}
	}
	return 0;
}
int main()
{
	SDL_Window *window = NULL;
	SDL_GLContext glcontext = NULL;
	int loop = 1;
	if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO) != 0)
	{
		SDL_Log("Unable to initialize SDL: %s", SDL_GetError());
		return 1;
	}
	window = SDL_CreateWindow("sdl2 test", 0, 0, 300, 300, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
	glcontext = SDL_GL_CreateContext(window);
	printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
	printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
	printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
	printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
	while(loop)
	{
		key(&loop);
		display(window);
	}
	SDL_GL_DeleteContext(glcontext);
	SDL_Quit();
	return 0;
}

The triangle is shown:
[new users can’t upload more than one image so you can’t see it]

However, I am unable to draw a triangle with OpenGL and Gtk3:

#include <gtk/gtk.h>
#include <GL/gl.h>
static gboolean on_realize(GtkGLArea *area, GdkGLContext *context)
{
	printf("on_realize: start\n");
	gtk_gl_area_make_current(GTK_GL_AREA(area));
	if(gtk_gl_area_get_error(area) != NULL)
	{
		printf("on_realize: error: gtk_gl_area_make_current\n");
		return FALSE;
	}
	printf("GL_VENDOR: %s\n", glGetString(GL_VENDOR));
	printf("GL_RENDERER: %s\n", glGetString(GL_RENDERER));
	printf("GL_VERSION: %s\n", glGetString(GL_VERSION));
	printf("GL_SHADING_LANGUAGE_VERSION: %s\n", glGetString(GL_SHADING_LANGUAGE_VERSION));
	printf("on_realize: end\n");
	return TRUE;
}
static gboolean on_render(GtkGLArea *area, GdkGLContext *context)
{
	printf("on_render: start\n");
	glClear(GL_COLOR_BUFFER_BIT);
	glBegin(GL_TRIANGLES);
	glColor3f(1, 0, 0); // color:    red
	glVertex2i(-1, -1); // position: left/bottom
	glColor3f(0, 1, 0); // color:    green 
	glVertex2i(0, 1);   // position: center/top 
	glColor3f(0, 0, 1); // color:    blue
	glVertex2i(1, -1);  // position: right/bottom
	glEnd();
	glFlush();
	printf("on_render: end\n");
	return TRUE;
}
int main(int argc, char **argv)
{
	// declare
	GtkWidget *window = NULL;
	GtkWidget *area = NULL;
	// init
	gtk_init(&argc, &argv);
	// new
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	area = gtk_gl_area_new();
	// connect
	g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
	g_signal_connect(area, "realize", G_CALLBACK(on_realize), NULL);
	g_signal_connect(area, "render", G_CALLBACK(on_render), NULL);
	// set
	gtk_window_set_title(GTK_WINDOW(window), "Window");
	gtk_window_set_default_size(GTK_WINDOW(window), 200, 200);
	// add
	gtk_container_add(GTK_CONTAINER(window), area);
	// show
	gtk_widget_show_all(window);
	// loop
	gtk_main();
	return 0;
}

The triangle is not shown and I only see the black color:
[new users can’t upload more than one image so you can’t see it]

As you can see, the code is more or less the same with Freeglut, SDL2 and Gtk3 so I am not sure why it is not working with Gtk3.

Am I missing something please?

Thank you.
Best regards.

You are using legacy GL 2 calls. GTK defaults to modern GL 3.2+ contexts, which means deprecated API like glBegin and friends have been removed.

An example of how to draw with modern GL is available here: GitHub - ebassi/glarea-example: Example of GtkGLArea use

Yes, I confirm that I am using legacy GL 2 calls.
But there are two profiles in OpenGL:

  1. The Core profile (removing deprecated API)
  2. The Compatibility profile (keeping deprecated API)

I edited my previous code so now it is printing the profile used at runtime.
Result:

  1. For Freeglut: GL_VERSION: 4.6 (Compatibility Profile) Mesa 20.1.4
  2. For SDL: GL_VERSION: 4.6 (Compatibility Profile) Mesa 20.1.4
  3. For GTK: GL_VERSION: 4.6 (Core Profile) Mesa 20.1.4

So, I confirm that GTK sets the default profile to Core whereas Freeglut and SDL set the default profile to Compatibility.
Even if GTK sets the default profile to Core, there is probably a way to switch between Core and Compatibility profiles at runtime.
For example, with SDL you can switch to the profile you want (Core or Compatibility) with SDL_GL_SetAttribute: SDL_GLprofile - SDL Wiki (but in practice it does not work on my machine, I am stuck in the default Compatibility profile)

GL 2 has two main advantages even if it is obsolete:

  1. It is faster to write code because you don’t need to write your own shaders
  2. It is compatible with old and recent hardware

Thus I really would like to switch for testing purposes from Core to Compatibility profile so I can quickly test legacy GL 2 code in GTK.
You said that deprecated API has been removed but when I look in the source code of GTK, I can find that there are still some pieces of code to support legacy GL 2:

$ grep -r 'legacy' /usr/include/gtk-3.0/
/usr/include/gtk-3.0/gdk/gdkglcontext.h:gboolean                gdk_gl_context_is_legacy                (GdkGLContext  *context);
$ grep -r 'gl_context_is_legacy'
NEWS: - gdk_gl_context_is_legacy
docs/reference/gdk/gdk3-sections.txt:gdk_gl_context_is_legacy
docs/reference/gdk/html/api-index-full.html:<a class="link" href="GdkGLContext.html#gdk-gl-context-is-legacy" title="gdk_gl_context_is_legacy ()">gdk_gl_context_is_legacy</a>, function in <a class="link" href="GdkGLContext.html" title="GdkGLContext">GdkGLContext</a>
docs/reference/gdk/html/GdkGLContext.html:<a class="link" href="GdkGLContext.html#gdk-gl-context-is-legacy" title="gdk_gl_context_is_legacy ()">gdk_gl_context_is_legacy</a> <span class="c_punctuation">()</span>
docs/reference/gdk/html/GdkGLContext.html:<a name="gdk-gl-context-is-legacy"></a><h3>gdk_gl_context_is_legacy ()</h3>
docs/reference/gdk/html/GdkGLContext.html:gdk_gl_context_is_legacy (<em class="parameter"><code><a class="link" href="GdkGLContext.html" title="GdkGLContext"><span class="type">GdkGLContext</span></a> *context</code></em>);</pre>
docs/reference/gdk/html/gdk3.devhelp2:    <keyword type="function" name="gdk_gl_context_is_legacy ()" link="GdkGLContext.html#gdk-gl-context-is-legacy" since="3.20"/>
tests/testglarea.c:      if (!gdk_gl_context_is_legacy (context))
gdk/x11/gdkglcontext-x11.c:  if (share != NULL && gdk_gl_context_is_legacy (share))
gdk/gdkglcontext.h:gboolean                gdk_gl_context_is_legacy                (GdkGLContext  *context);
gdk/wayland/gdkglcontext-wayland.c:               (share != NULL && gdk_gl_context_is_legacy (share));
gdk/win32/gdkglcontext-win32.c:  if (share != NULL && gdk_gl_context_is_legacy (share))
gdk/gdkglcontext.c: * gdk_gl_context_is_legacy:
gdk/gdkglcontext.c:gdk_gl_context_is_legacy (GdkGLContext *context)
$ grep -r 'OPENGL_COMPATIBILITY_PROFILE'
gdk/wayland/gdkglcontext-wayland.c:                           ? EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR
gdk/wayland/gdkglcontext-wayland.c:      context_attribs[1] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR;

Are you sure that it is not possible to go back to Compatibility profile at runtime using GTK3?

The legacy support in GTK is there only as a fallback, to support platforms and GL drivers that only provide GL2 contexts. You cannot specify that you want a legacy context programmatically.

OK thanks for the explanations and have a nice day.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.