[RFCv2 3/9] gl-renderer: Add optional support for desktop OpenGL.

John Kåre Alsaker john.kare.alsaker at gmail.com
Fri Nov 16 18:23:54 PST 2012


This adds support for desktop OpenGL which can be enabled by with
./configure --enable-opengl.

Most of the differences in API between OpenGL and OpenGL ES is hidden by
the new gl_renderer fields.

It also accesses GLES2 extensions by including GLES2/gl2platform.h directly.
---
 configure.ac         | 13 +++++++++-
 src/Makefile.am      |  4 +--
 src/compositor-rpi.c |  2 +-
 src/compositor.h     |  1 +
 src/gl-internal.h    |  7 +++---
 src/gl-renderer.c    | 69 +++++++++++++++++++++++++++++++++++-----------------
 src/gl-renderer.h    | 19 +++++++++++++++
 src/gl-shaders.c     |  5 ++--
 8 files changed, 89 insertions(+), 31 deletions(-)

diff --git a/configure.ac b/configure.ac
index 7329c06..df43c75 100644
--- a/configure.ac
+++ b/configure.ac
@@ -34,7 +34,18 @@ AC_CHECK_HEADERS([execinfo.h])
 AC_CHECK_FUNCS([mkostemp strchrnul])
 
 PKG_CHECK_MODULES(COMPOSITOR,
-		  [wayland-server egl >= 7.10 glesv2 xkbcommon pixman-1])
+		  [wayland-server egl >= 7.10 xkbcommon pixman-1])
+
+
+AC_ARG_ENABLE(opengl, [  --enable-opengl],,
+		  enable_opengl=no)
+AM_CONDITIONAL(ENABLE_OPENGL, test x$enable_opengl = xyes)
+if test x$enable_opengl = xyes; then
+  PKG_CHECK_MODULES([OPENGL], gl)
+  AC_DEFINE([BUILD_OPENGL], [1], [Build using desktop OpenGL])
+else
+  PKG_CHECK_MODULES([OPENGL], glesv2)
+fi
 
 
 AC_ARG_ENABLE(setuid-install, [  --enable-setuid-install],,
diff --git a/src/Makefile.am b/src/Makefile.am
index 0c315cd..bea769c 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -7,8 +7,8 @@ AM_CPPFLAGS =					\
 	-DLIBEXECDIR='"$(libexecdir)"'
 
 weston_LDFLAGS = -export-dynamic
-weston_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS)
-weston_LDADD = $(COMPOSITOR_LIBS) $(DLOPEN_LIBS) -lm ../shared/libshared.la
+weston_CFLAGS = $(GCC_CFLAGS) $(COMPOSITOR_CFLAGS) $(OPENGL_CFLAGS)
+weston_LDADD = $(COMPOSITOR_LIBS) $(OPENGL_LIBS) $(DLOPEN_LIBS) -lm ../shared/libshared.la
 
 weston_SOURCES =				\
 	git-version.h				\
diff --git a/src/compositor-rpi.c b/src/compositor-rpi.c
index 339032a..d3ae952 100644
--- a/src/compositor-rpi.c
+++ b/src/compositor-rpi.c
@@ -1457,7 +1457,7 @@ rpi_compositor_create(struct wl_display *display, int argc, char *argv[],
 		EGL_GREEN_SIZE, 1,
 		EGL_BLUE_SIZE, 1,
 		EGL_ALPHA_SIZE, 0,
-		EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+		EGL_RENDERABLE_TYPE, GL_EGL_OPENGL_BIT,
 		EGL_NONE
 	};
 
diff --git a/src/compositor.h b/src/compositor.h
index e5c579b..a5dd3c6 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -24,6 +24,7 @@
 #ifndef _WAYLAND_SYSTEM_COMPOSITOR_H_
 #define _WAYLAND_SYSTEM_COMPOSITOR_H_
 
+#include <config.h>
 #include <pixman.h>
 #include <xkbcommon/xkbcommon.h>
 #include <wayland-server.h>
diff --git a/src/gl-internal.h b/src/gl-internal.h
index 994c139..83b351f 100644
--- a/src/gl-internal.h
+++ b/src/gl-internal.h
@@ -24,9 +24,6 @@
 #ifndef _GL_INTERNAL_H_
 #define _GL_INTERNAL_H_
 
-#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
-
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
@@ -106,6 +103,10 @@ struct gl_renderer {
 		int32_t width, height;
 	} border;
 
+	GLenum bgra_internal_format, bgra_format;
+	GLenum rgba16_internal_format;
+	GLenum short_type;
+
 	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d;
 	PFNEGLCREATEIMAGEKHRPROC create_image;
 	PFNEGLDESTROYIMAGEKHRPROC destroy_image;
diff --git a/src/gl-renderer.c b/src/gl-renderer.c
index 1a9f782..1956759 100644
--- a/src/gl-renderer.c
+++ b/src/gl-renderer.c
@@ -878,11 +878,12 @@ gl_renderer_read_pixels(struct weston_output *output,
 			       uint32_t x, uint32_t y,
 			       uint32_t width, uint32_t height)
 {
+	struct gl_renderer *gr = get_renderer(output->compositor);
 	GLenum gl_format;
 
 	switch (format) {
 	case PIXMAN_a8r8g8b8:
-		gl_format = GL_BGRA_EXT;
+		gl_format = gr->bgra_format;
 		break;
 	case PIXMAN_a8b8g8r8:
 		gl_format = GL_RGBA;
@@ -928,9 +929,9 @@ gl_renderer_flush_damage(struct weston_surface *surface)
 	glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
 
 	if (!gr->has_unpack_subimage) {
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+		glTexImage2D(GL_TEXTURE_2D, 0, gr->bgra_internal_format,
 			     surface->pitch, surface->buffer->height, 0,
-			     GL_BGRA_EXT, GL_UNSIGNED_BYTE,
+			     gr->bgra_format, GL_UNSIGNED_BYTE,
 			     wl_shm_buffer_get_data(surface->buffer));
 
 		goto done;
@@ -948,7 +949,7 @@ gl_renderer_flush_damage(struct weston_surface *surface)
 				rectangles[i].x1, rectangles[i].y1,
 				rectangles[i].x2 - rectangles[i].x1,
 				rectangles[i].y2 - rectangles[i].y1,
-				GL_BGRA_EXT, GL_UNSIGNED_BYTE, data);
+				gr->bgra_format, GL_UNSIGNED_BYTE, data);
 	}
 #endif
 
@@ -1003,9 +1004,9 @@ gl_renderer_attach(struct weston_surface *es, struct wl_buffer *buffer)
 
 		ensure_textures(gs, 1);
 		glBindTexture(GL_TEXTURE_2D, gs->textures[0]);
-		glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+		glTexImage2D(GL_TEXTURE_2D, 0, gr->bgra_internal_format,
 			     es->pitch, buffer->height, 0,
-			     GL_BGRA_EXT, GL_UNSIGNED_BYTE, NULL);
+			     gr->bgra_format, GL_UNSIGNED_BYTE, NULL);
 		if (wl_shm_buffer_get_format(buffer) == WL_SHM_FORMAT_XRGB8888)
 			gs->input = INPUT_RGBX;
 		else
@@ -1229,10 +1230,10 @@ gl_renderer_set_border(struct weston_compositor *ec, int32_t width, int32_t heig
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
 
-	glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT,
+	glTexImage2D(GL_TEXTURE_2D, 0, gr->bgra_internal_format,
 		     width,
 		     height,
-		     0, GL_BGRA_EXT, GL_UNSIGNED_BYTE,
+		     0, gr->bgra_format, GL_UNSIGNED_BYTE,
 		     data);
 
 	wl_list_for_each(output, &ec->output_list, link)
@@ -1366,7 +1367,7 @@ WL_EXPORT const EGLint gl_renderer_opaque_attribs[] = {
 	EGL_GREEN_SIZE, 1,
 	EGL_BLUE_SIZE, 1,
 	EGL_ALPHA_SIZE, 0,
-	EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+	EGL_RENDERABLE_TYPE, GL_EGL_OPENGL_BIT,
 	EGL_NONE
 };
 
@@ -1376,7 +1377,7 @@ WL_EXPORT const EGLint gl_renderer_alpha_attribs[] = {
 	EGL_GREEN_SIZE, 1,
 	EGL_BLUE_SIZE, 1,
 	EGL_ALPHA_SIZE, 1,
-	EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+	EGL_RENDERABLE_TYPE, GL_EGL_OPENGL_BIT,
 	EGL_NONE
 };
 
@@ -1452,19 +1453,49 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	const char *extensions;
 	EGLBoolean ret;
 
+#ifdef BUILD_OPENGL
+	static const EGLint context_attribs[] = {
+		EGL_CONTEXT_MAJOR_VERSION_KHR, 2,
+		EGL_CONTEXT_MINOR_VERSION_KHR, 0,
+		EGL_NONE
+	};
+
+	gr->bgra_internal_format = GL_RGBA;
+	gr->bgra_format = GL_BGRA;
+	gr->short_type = GL_UNSIGNED_SHORT;
+	gr->rgba16_internal_format = GL_RGBA16;
+#else
 	static const EGLint context_attribs[] = {
 		EGL_CONTEXT_CLIENT_VERSION, 2,
 		EGL_NONE
 	};
 
-	if (!eglBindAPI(EGL_OPENGL_ES_API)) {
-		weston_log("failed to bind EGL_OPENGL_ES_API\n");
+	gr->bgra_internal_format = GL_BGRA_EXT;
+	gr->bgra_format = GL_BGRA_EXT;
+	gr->short_type = GL_UNSIGNED_BYTE;
+	gr->rgba16_internal_format = GL_RGBA;
+#endif
+
+	if (!eglBindAPI(OPENGL_ES_VER ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) {
+		weston_log("failed to bind OpenGL API");
 		print_egl_error_state();
 		return -1;
 	}
 
 	log_egl_config_info(gr->egl_display, gr->egl_config);
 
+	extensions =
+		(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
+	if (!extensions) {
+		weston_log("Retrieving EGL extension string failed.\n");
+		return -1;
+	}
+
+	if (!OPENGL_ES_VER && !strstr(extensions, "EGL_KHR_create_context")) {
+		weston_log("EGL_KHR_create_context required to create OpenGL context\n");
+		return -1;
+	}
+
 	gr->egl_context = eglCreateContext(gr->egl_display, gr->egl_config,
 					   EGL_NO_CONTEXT, context_attribs);
 	if (gr->egl_context == NULL) {
@@ -1494,13 +1525,16 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	gr->query_buffer =
 		(void *) eglGetProcAddress("eglQueryWaylandBufferWL");
 
+	if (strstr(extensions, "EGL_WL_bind_wayland_display"))
+		gr->has_bind_display = 1;
+
 	extensions = (const char *) glGetString(GL_EXTENSIONS);
 	if (!extensions) {
 		weston_log("Retrieving GL extension string failed.\n");
 		return -1;
 	}
 
-	if (!strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
+	if (OPENGL_ES_VER && !strstr(extensions, "GL_EXT_texture_format_BGRA8888")) {
 		weston_log("GL_EXT_texture_format_BGRA8888 not available\n");
 		return -1;
 	}
@@ -1516,15 +1550,6 @@ gl_renderer_setup(struct weston_compositor *ec, EGLSurface egl_surface)
 	if (strstr(extensions, "GL_OES_EGL_image_external"))
 		gr->has_egl_image_external = 1;
 
-	extensions =
-		(const char *) eglQueryString(gr->egl_display, EGL_EXTENSIONS);
-	if (!extensions) {
-		weston_log("Retrieving EGL extension string failed.\n");
-		return -1;
-	}
-
-	if (strstr(extensions, "EGL_WL_bind_wayland_display"))
-		gr->has_bind_display = 1;
 	if (gr->has_bind_display) {
 		ret = gr->bind_display(gr->egl_display, ec->wl_display);
 		if (!ret)
diff --git a/src/gl-renderer.h b/src/gl-renderer.h
index 7494cff..10bc542 100644
--- a/src/gl-renderer.h
+++ b/src/gl-renderer.h
@@ -22,6 +22,25 @@
 
 #include  "compositor.h"
 
+#ifdef BUILD_OPENGL
+
+#define OPENGL_ES_VER 0
+#define GL_GLEXT_PROTOTYPES
+#define GL_EGL_OPENGL_BIT EGL_OPENGL_BIT
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <GLES2/gl2platform.h>
+
+#else
+
+#define OPENGL_ES_VER 2
+#define GL_EGL_OPENGL_BIT EGL_OPENGL_ES2_BIT
+#include <GLES2/gl2.h>
+
+#endif
+
+#include <GLES2/gl2ext.h>
 #include <EGL/egl.h>
 
 extern const EGLint gl_renderer_opaque_attribs[];
diff --git a/src/gl-shaders.c b/src/gl-shaders.c
index 060a87d..32bb70d 100644
--- a/src/gl-shaders.c
+++ b/src/gl-shaders.c
@@ -423,8 +423,9 @@ create_shader_permutation(struct gl_renderer *renderer,
 
 	shader_builder_init(&sb);
 
-	append(&sb.global, "precision mediump float;\n" \
-		"varying vec2 texture_coord;\n" \
+	if (OPENGL_ES_VER)
+		append(&sb.global, "precision mediump float;\n");
+	append(&sb.global, "varying vec2 texture_coord;\n" \
 		"uniform float alpha;\n");
 
 	append(&sb.body, "void main()\n{\n");
-- 
1.8.0



More information about the wayland-devel mailing list