gl-renderer: Build as a loadable module

The time spent loading EGL and GLES libraries from disk can be a
considerable hit in some embedded use cases. If Weston is compiled
with EGL support, the binary will depend on those libraries, even if
a software renderer is in use.

This patch splits the GL renderer into a separate loadable module,
and moves the dependency on EGL and GLES to it. The backends still
need the EGL headers for the native types and EGLint. The function
load_module() is renamed to weston_load_module() and exported, so
that it can be used by the backends.

The gl renderer interface is changed so that there is only one symbol
that needs to be dlsym()'d. This symbol contains pointers to all the
functions and data necessary to interact with the renderer. As a side
effect, this change simplifies gl-renderer.h a great deal.
diff --git a/src/compositor-drm.c b/src/compositor-drm.c
index ad5a2c3..25c34f8 100644
--- a/src/compositor-drm.c
+++ b/src/compositor-drm.c
@@ -33,6 +33,7 @@
 #include <linux/vt.h>
 #include <assert.h>
 #include <sys/mman.h>
+#include <dlfcn.h>
 #include <time.h>
 
 #include <xf86drm.h>
@@ -194,6 +195,8 @@
 	uint32_t formats[];
 };
 
+static struct gl_renderer_interface *gl_renderer;
+
 static const char default_seat[] = "seat0";
 
 static void
@@ -1101,7 +1104,7 @@
 	if (c->use_pixman) {
 		drm_output_fini_pixman(output);
 	} else {
-		gl_renderer_output_destroy(output_base);
+		gl_renderer->output_destroy(output_base);
 		gbm_surface_destroy(output->surface);
 	}
 
@@ -1192,7 +1195,7 @@
 			return -1;
 		}
 	} else {
-		gl_renderer_output_destroy(&output->base);
+		gl_renderer->output_destroy(&output->base);
 		gbm_surface_destroy(output->surface);
 
 		if (drm_output_init_egl(output, ec) < 0) {
@@ -1262,14 +1265,26 @@
 {
 	EGLint format;
 
+	gl_renderer = weston_load_module("gl-renderer.so",
+					 "gl_renderer_interface");
+	if (!gl_renderer)
+		return -1;
+
+	/* GBM will load a dri driver, but even though they need symbols from
+	 * libglapi, in some version of Mesa they are not linked to it. Since
+	 * only the gl-renderer module links to it, the call above won't make
+	 * these symbols globally available, and loading the DRI driver fails.
+	 * Workaround this by dlopen()'ing libglapi with RTLD_GLOBAL. */
+	dlopen("libglapi.so.0", RTLD_LAZY | RTLD_GLOBAL);
+
 	ec->gbm = gbm_create_device(ec->drm.fd);
 
 	if (!ec->gbm)
 		return -1;
 
 	format = ec->format;
-	if (gl_renderer_create(&ec->base, ec->gbm,
-			       gl_renderer_opaque_attribs, &format) < 0) {
+	if (gl_renderer->create(&ec->base, ec->gbm,
+			       gl_renderer->opaque_attribs, &format) < 0) {
 		gbm_device_destroy(ec->gbm);
 		return -1;
 	}
@@ -1471,7 +1486,7 @@
 		return -1;
 	}
 
-	if (gl_renderer_output_create(&output->base, output->surface) < 0) {
+	if (gl_renderer->output_create(&output->base, output->surface) < 0) {
 		weston_log("failed to create gl renderer output state\n");
 		gbm_surface_destroy(output->surface);
 		return -1;