[cogl/wip/runtime-egl-platform] egl: Split out the KMS winsys as overrides of the EGL winsys
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [cogl/wip/runtime-egl-platform] egl: Split out the KMS winsys as overrides of the EGL winsys
- Date: Fri, 9 Dec 2011 16:16:23 +0000 (UTC)
commit e6b12ae00f263cf6d20e4512f39f39beb795236c
Author: Neil Roberts <neil linux intel com>
Date: Fri Dec 9 16:10:01 2011 +0000
egl: Split out the KMS winsys as overrides of the EGL winsys
Instead of having #ifdefs to hook into the normal EGL winsys, the KMS
winsys now overrides any winsys functions that it wants. Where the
winsys wants to hook into a point within a function provided by the
EGL winsys there is a EGL-platform vtable which gets set on the EGL
renderer data during renderer_connect. The KMS-specific data on all of
the structures is now allocated separately by the KMS winsys and is
pointed to by a new 'platform' pointer in the EGL data.
cogl/Makefile.am | 2 -
cogl/winsys/cogl-winsys-egl-kms-private.h | 2 +
cogl/winsys/cogl-winsys-egl-kms.c | 524 +++++++++++++++++++++++++++++
cogl/winsys/cogl-winsys-egl-private.h | 63 +++-
cogl/winsys/cogl-winsys-egl.c | 325 ++++++------------
cogl/winsys/cogl-winsys-kms.c | 426 -----------------------
cogl/winsys/cogl-winsys-kms.h | 103 ------
7 files changed, 686 insertions(+), 759 deletions(-)
---
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index b62a2a5..c0eac28 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -382,8 +382,6 @@ cogl_sources_c += \
endif
if SUPPORT_EGL_PLATFORM_KMS
cogl_sources_c += \
- $(srcdir)/winsys/cogl-winsys-kms.c \
- $(srcdir)/winsys/cogl-winsys-kms.h \
$(srcdir)/winsys/cogl-winsys-egl-kms.c \
$(srcdir)/winsys/cogl-winsys-egl-kms-private.h
endif
diff --git a/cogl/winsys/cogl-winsys-egl-kms-private.h b/cogl/winsys/cogl-winsys-egl-kms-private.h
index 0dec2d9..a4992a3 100644
--- a/cogl/winsys/cogl-winsys-egl-kms-private.h
+++ b/cogl/winsys/cogl-winsys-egl-kms-private.h
@@ -19,6 +19,8 @@
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*
+ * Authors:
+ * Neil Roberts <neil linux intel com>
*/
#ifndef __COGL_WINSYS_EGL_KMS_PRIVATE_H
diff --git a/cogl/winsys/cogl-winsys-egl-kms.c b/cogl/winsys/cogl-winsys-egl-kms.c
index 0229e0f..3a4b11b 100644
--- a/cogl/winsys/cogl-winsys-egl-kms.c
+++ b/cogl/winsys/cogl-winsys-egl-kms.c
@@ -21,6 +21,9 @@
*
*
* Authors:
+ * Rob Bradford <rob linux intel com>
+ * Kristian HÃgsberg (from eglkms.c)
+ * Benjamin Franzke (from eglkms.c)
* Robert Bragg <robert linux intel com>
* Neil Roberts <neil linux intel com>
*/
@@ -29,8 +32,515 @@
#include "config.h"
#endif
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+#include <glib.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+
#include "cogl-winsys-egl-kms-private.h"
#include "cogl-winsys-egl-private.h"
+#include "cogl-renderer-private.h"
+#include "cogl-framebuffer-private.h"
+#include "cogl-onscreen-private.h"
+
+static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
+
+typedef struct _CoglRendererKMS
+{
+ int fd;
+ struct gbm_device *gbm;
+} CoglRendererKMS;
+
+typedef struct _CoglDisplayKMS
+{
+ drmModeConnector *connector;
+ drmModeEncoder *encoder;
+ drmModeModeInfo mode;
+ drmModeCrtcPtr saved_crtc;
+ int width, height;
+} CoglDisplayKMS;
+
+typedef struct _CoglOnscreenKMS
+{
+ uint32_t fb_id[2];
+ struct gbm_bo *bo[2];
+ unsigned int fb, color_rb[2], depth_rb;
+ EGLImageKHR image[2];
+ int current_frame;
+} CoglOnscreenKMS;
+
+static const char device_name[] = "/dev/dri/card0";
+
+static void
+_cogl_winsys_renderer_disconnect (CoglRenderer *renderer)
+{
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+
+ eglTerminate (egl_renderer->edpy);
+
+ g_slice_free (CoglRendererKMS, kms_renderer);
+ g_slice_free (CoglRendererEGL, egl_renderer);
+}
+
+static gboolean
+_cogl_winsys_renderer_connect (CoglRenderer *renderer,
+ GError **error)
+{
+ CoglRendererEGL *egl_renderer;
+ CoglRendererKMS *kms_renderer;
+ EGLint major, minor;
+
+ renderer->winsys = g_slice_new0 (CoglRendererEGL);
+ egl_renderer = renderer->winsys;
+
+ egl_renderer->platform_vtable = &_cogl_winsys_egl_vtable;
+ egl_renderer->platform = g_slice_new0 (CoglRendererKMS);
+ kms_renderer = egl_renderer->platform;
+
+ kms_renderer->fd = open (device_name, O_RDWR);
+ if (kms_renderer->fd < 0)
+ {
+ /* Probably permissions error */
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Couldn't open %s", device_name);
+ return FALSE;
+ }
+
+ kms_renderer->gbm = gbm_create_device (kms_renderer->fd);
+ if (kms_renderer->gbm == NULL)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Couldn't create gbm device");
+ goto close_fd;
+ }
+
+ egl_renderer->edpy = eglGetDisplay ((EGLNativeDisplayType)kms_renderer->gbm);
+ if (egl_renderer->edpy == EGL_NO_DISPLAY)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Couldn't get eglDisplay");
+ goto destroy_gbm_device;
+ }
+
+ if (!eglInitialize (egl_renderer->edpy, &major, &minor))
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "Couldn't initialize EGL");
+ goto egl_terminate;
+ }
+
+ _cogl_winsys_egl_check_egl_extensions (renderer);
+
+ return TRUE;
+
+egl_terminate:
+ eglTerminate (egl_renderer->edpy);
+destroy_gbm_device:
+ gbm_device_destroy (kms_renderer->gbm);
+close_fd:
+ close (kms_renderer->fd);
+
+ _cogl_winsys_renderer_disconnect (renderer);
+
+ return FALSE;
+}
+
+static gboolean
+_cogl_winsys_egl_display_setup (CoglDisplay *display,
+ GError **error)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display;
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+ CoglEGLWinsysFeature surfaceless_feature = 0;
+ const char *surfaceless_feature_name = "";
+ drmModeRes *resources;
+ drmModeConnector *connector;
+ drmModeEncoder *encoder;
+ int i;
+
+ kms_display = g_slice_new0 (CoglDisplayKMS);
+ egl_display->platform = kms_display;
+
+ switch (display->renderer->driver)
+ {
+ case COGL_DRIVER_GL:
+ surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_OPENGL;
+ surfaceless_feature_name = "opengl";
+ break;
+ case COGL_DRIVER_GLES1:
+ surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES1;
+ surfaceless_feature_name = "gles1";
+ break;
+ case COGL_DRIVER_GLES2:
+ surfaceless_feature = COGL_EGL_WINSYS_FEATURE_SURFACELESS_GLES2;
+ surfaceless_feature_name = "gles2";
+ break;
+ }
+
+ if (!(egl_renderer->private_features & surfaceless_feature))
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "EGL_KHR_surfaceless_%s extension not available",
+ surfaceless_feature_name);
+ return FALSE;
+ }
+
+ resources = drmModeGetResources (kms_renderer->fd);
+ if (!resources)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "drmModeGetResources failed");
+ return FALSE;
+ }
+
+ for (i = 0; i < resources->count_connectors; i++)
+ {
+ connector = drmModeGetConnector (kms_renderer->fd,
+ resources->connectors[i]);
+ if (connector == NULL)
+ continue;
+
+ if (connector->connection == DRM_MODE_CONNECTED &&
+ connector->count_modes > 0)
+ break;
+
+ drmModeFreeConnector(connector);
+ }
+
+ if (i == resources->count_connectors)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_INIT,
+ "No currently active connector found");
+ return FALSE;
+ }
+
+ for (i = 0; i < resources->count_encoders; i++)
+ {
+ encoder = drmModeGetEncoder (kms_renderer->fd, resources->encoders[i]);
+
+ if (encoder == NULL)
+ continue;
+
+ if (encoder->encoder_id == connector->encoder_id)
+ break;
+
+ drmModeFreeEncoder (encoder);
+ }
+
+ kms_display->saved_crtc = drmModeGetCrtc (kms_renderer->fd,
+ encoder->crtc_id);
+
+ kms_display->connector = connector;
+ kms_display->encoder = encoder;
+ kms_display->mode = connector->modes[0];
+ kms_display->width = kms_display->mode.hdisplay;
+ kms_display->height = kms_display->mode.vdisplay;
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_egl_display_destroy (CoglDisplay *display)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+
+ g_slice_free (CoglDisplayKMS, egl_display->platform);
+}
+
+static gboolean
+_cogl_winsys_egl_try_create_context (CoglDisplay *display,
+ EGLint *attribs,
+ GError **error)
+{
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+
+ egl_display->egl_context = eglCreateContext (egl_renderer->edpy,
+ NULL,
+ EGL_NO_CONTEXT,
+ attribs);
+
+ if (egl_display->egl_context == NULL)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Couldn't create EGL context");
+ return FALSE;
+ }
+
+ if (!eglMakeCurrent (egl_renderer->edpy,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ egl_display->egl_context))
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to make context current");
+ return FALSE;
+ }
+
+ egl_display->egl_surface_width = kms_display->width;
+ egl_display->egl_surface_height = kms_display->height;
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_egl_cleanup_context (CoglDisplay *display)
+{
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+ int ret;
+
+ /* Restore the saved CRTC - this failing should not propagate an error */
+ ret = drmModeSetCrtc (kms_renderer->fd,
+ kms_display->saved_crtc->crtc_id,
+ kms_display->saved_crtc->buffer_id,
+ kms_display->saved_crtc->x, kms_display->saved_crtc->y,
+ &kms_display->connector->connector_id, 1,
+ &kms_display->saved_crtc->mode);
+ if (ret)
+ g_critical (G_STRLOC ": Error restoring saved CRTC");
+
+ drmModeFreeCrtc (kms_display->saved_crtc);
+}
+
+static void
+_cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplayEGL *egl_display = context->display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+ CoglRenderer *renderer = context->display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
+
+ if (drmModeSetCrtc (kms_renderer->fd,
+ kms_display->encoder->crtc_id,
+ kms_onscreen->fb_id[kms_onscreen->current_frame],
+ 0, 0,
+ &kms_display->connector->connector_id,
+ 1,
+ &kms_display->mode) != 0)
+ {
+ g_error (G_STRLOC ": Setting CRTC failed");
+ }
+
+ /* Update frame that we're drawing to be the new one */
+ kms_onscreen->current_frame ^= 1;
+
+ context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb);
+ context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT,
+ kms_onscreen->
+ color_rb[kms_onscreen->current_frame]);
+
+ if (context->glCheckFramebufferStatus (GL_FRAMEBUFFER_EXT) !=
+ GL_FRAMEBUFFER_COMPLETE)
+ {
+ g_error (G_STRLOC ": FBO not complete");
+ }
+}
+
+static gboolean
+_cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
+ GError **error)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+ CoglDisplay *display = context->display;
+ CoglDisplayEGL *egl_display = display->winsys;
+ CoglDisplayKMS *kms_display = egl_display->platform;
+ CoglRenderer *renderer = display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+ CoglOnscreenEGL *egl_onscreen;
+ CoglOnscreenKMS *kms_onscreen;
+ int i;
+
+ _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
+
+ onscreen->winsys = g_slice_new0 (CoglOnscreenEGL);
+ egl_onscreen = onscreen->winsys;
+
+ kms_onscreen = g_slice_new0 (CoglOnscreenKMS);
+ egl_onscreen->platform = kms_onscreen;
+
+ context->glGenRenderbuffers (2, kms_onscreen->color_rb);
+
+ for (i = 0; i < 2; i++)
+ {
+ uint32_t handle, stride;
+
+ kms_onscreen->bo[i] =
+ gbm_bo_create (kms_renderer->gbm,
+ kms_display->mode.hdisplay, kms_display->mode.vdisplay,
+ GBM_BO_FORMAT_XRGB8888,
+ GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ if (!kms_onscreen->bo[i])
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to allocate buffer");
+ return FALSE;
+ }
+
+ kms_onscreen->image[i] =
+ _cogl_egl_create_image (context,
+ EGL_NATIVE_PIXMAP_KHR,
+ kms_onscreen->bo[i],
+ NULL);
+
+ if (kms_onscreen->image[i] == EGL_NO_IMAGE_KHR)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to create EGL image");
+ return FALSE;
+ }
+
+ context->glBindRenderbuffer (GL_RENDERBUFFER_EXT,
+ kms_onscreen->color_rb[i]);
+ context->glEGLImageTargetRenderbufferStorage (GL_RENDERBUFFER,
+ kms_onscreen->image[i]);
+ context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);
+
+ handle = gbm_bo_get_handle (kms_onscreen->bo[i]).u32;
+ stride = gbm_bo_get_pitch (kms_onscreen->bo[i]);
+
+ if (drmModeAddFB (kms_renderer->fd,
+ kms_display->mode.hdisplay,
+ kms_display->mode.vdisplay,
+ 24, 32,
+ stride,
+ handle,
+ &kms_onscreen->fb_id[i]) != 0)
+ {
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_CONTEXT,
+ "Failed to create framebuffer from buffer");
+ return FALSE;
+ }
+ }
+
+ context->glGenFramebuffers (1, &kms_onscreen->fb);
+ context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb);
+
+ context->glGenRenderbuffers (1, &kms_onscreen->depth_rb);
+ context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_onscreen->depth_rb);
+ context->glRenderbufferStorage (GL_RENDERBUFFER_EXT,
+ GL_DEPTH_COMPONENT16,
+ kms_display->mode.hdisplay,
+ kms_display->mode.vdisplay);
+ context->glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);
+
+ context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ kms_onscreen->depth_rb);
+
+ kms_onscreen->current_frame = 0;
+ _cogl_winsys_onscreen_swap_buffers (onscreen);
+
+ _cogl_framebuffer_winsys_update_size (framebuffer,
+ egl_display->egl_surface_width,
+ egl_display->egl_surface_height);
+
+ return TRUE;
+}
+
+static void
+_cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
+{
+ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen);
+ CoglContext *context = framebuffer->context;
+ CoglRenderer *renderer = context->display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+ CoglRendererKMS *kms_renderer = egl_renderer->platform;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglOnscreenKMS *kms_onscreen;
+ int i;
+
+ /* If we never successfully allocated then there's nothing to do */
+ if (egl_onscreen == NULL)
+ return;
+
+ kms_onscreen = egl_onscreen->platform;
+
+ context->glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_onscreen->fb);
+ context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
+ GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT,
+ 0);
+ context->glDeleteRenderbuffers(2, kms_onscreen->color_rb);
+ context->glFramebufferRenderbuffer (GL_FRAMEBUFFER_EXT,
+ GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT,
+ 0);
+ context->glDeleteRenderbuffers(1, &kms_onscreen->depth_rb);
+
+ for (i = 0; i < 2; i++)
+ {
+ drmModeRmFB (kms_renderer->fd, kms_onscreen->fb_id[i]);
+ _cogl_egl_destroy_image (context, kms_onscreen->image[i]);
+ gbm_bo_destroy (kms_onscreen->bo[i]);
+ }
+
+ g_slice_free (CoglOnscreenKMS, kms_onscreen);
+ g_slice_free (CoglOnscreenEGL, onscreen->winsys);
+ onscreen->winsys = NULL;
+}
+
+static void
+_cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
+{
+ CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
+ CoglDisplayEGL *egl_display = context->display->winsys;
+ CoglRenderer *renderer = context->display->renderer;
+ CoglRendererEGL *egl_renderer = renderer->winsys;
+
+ eglMakeCurrent (egl_renderer->edpy,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ egl_display->egl_context);
+}
+
+static void
+_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
+{
+ _cogl_winsys_onscreen_bind (onscreen);
+}
+
+static const CoglWinsysEGLVtable
+_cogl_winsys_egl_vtable =
+ {
+ .display_setup = _cogl_winsys_egl_display_setup,
+ .display_destroy = _cogl_winsys_egl_display_destroy,
+ .try_create_context = _cogl_winsys_egl_try_create_context,
+ .cleanup_context = _cogl_winsys_egl_cleanup_context
+ };
const CoglWinsysVtable *
_cogl_winsys_egl_kms_get_vtable (void)
@@ -48,6 +558,20 @@ _cogl_winsys_egl_kms_get_vtable (void)
vtable.id = COGL_WINSYS_ID_EGL_KMS;
vtable.name = "EGL_KMS";
+ vtable.renderer_connect = _cogl_winsys_renderer_connect;
+ vtable.renderer_disconnect = _cogl_winsys_renderer_disconnect;
+
+ vtable.onscreen_init = _cogl_winsys_onscreen_init;
+ vtable.onscreen_deinit = _cogl_winsys_onscreen_deinit;
+ vtable.onscreen_bind = _cogl_winsys_onscreen_bind;
+
+ /* The KMS winsys doesn't support swap region */
+ vtable.onscreen_swap_region = NULL;
+ vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
+
+ vtable.onscreen_update_swap_throttled =
+ _cogl_winsys_onscreen_update_swap_throttled;
+
vtable_inited = TRUE;
}
diff --git a/cogl/winsys/cogl-winsys-egl-private.h b/cogl/winsys/cogl-winsys-egl-private.h
index 5e3895d..417a2ea 100644
--- a/cogl/winsys/cogl-winsys-egl-private.h
+++ b/cogl/winsys/cogl-winsys-egl-private.h
@@ -28,9 +28,6 @@
#include "cogl-winsys-private.h"
#include "cogl-context.h"
#include "cogl-context-private.h"
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
-#include "cogl-winsys-kms.h"
-#endif
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
#include "cogl-xlib-renderer-private.h"
#include "cogl-xlib-display-private.h"
@@ -40,6 +37,23 @@
#include <wayland-egl.h>
#endif
+typedef struct _CoglWinsysEGLVtable
+{
+ gboolean
+ (* display_setup) (CoglDisplay *display,
+ GError **error);
+ void
+ (* display_destroy) (CoglDisplay *display);
+
+ gboolean
+ (* try_create_context) (CoglDisplay *display,
+ EGLint *attribs,
+ GError **error);
+
+ void
+ (* cleanup_context) (CoglDisplay *display);
+} CoglWinsysEGLVtable;
+
typedef enum _CoglEGLWinsysFeature
{
COGL_EGL_WINSYS_FEATURE_SWAP_REGION =1L<<0,
@@ -72,9 +86,11 @@ typedef struct _CoglRendererEGL
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
gboolean gdl_initialized;
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- CoglRendererKMS kms_renderer;
-#endif
+
+ /* Data specific to the EGL platform */
+ void *platform;
+ /* vtable for platform specific parts */
+ const CoglWinsysEGLVtable *platform_vtable;
/* Function pointers for GLX specific extensions */
#define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d)
@@ -103,9 +119,6 @@ typedef struct _CoglDisplayEGL
struct wl_surface *wayland_surface;
struct wl_egl_window *wayland_egl_native_window;
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- CoglDisplayKMS kms_display;
-#endif
#if defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \
defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) || \
@@ -119,6 +132,9 @@ typedef struct _CoglDisplayEGL
EGLConfig egl_config;
gboolean found_egl_config;
gboolean stencil_disabled;
+
+ /* Platform specific display data */
+ void *platform;
} CoglDisplayEGL;
typedef struct _CoglContextEGL
@@ -126,6 +142,32 @@ typedef struct _CoglContextEGL
EGLSurface current_surface;
} CoglContextEGL;
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+typedef struct _CoglOnscreenXlib
+{
+ Window xwin;
+ gboolean is_foreign_xwin;
+} CoglOnscreenXlib;
+#endif
+
+typedef struct _CoglOnscreenEGL
+{
+#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
+ CoglOnscreenXlib _parent;
+#endif
+
+#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT
+ struct wl_egl_window *wayland_egl_native_window;
+ struct wl_surface *wayland_surface;
+ struct wl_shell_surface *wayland_shell_surface;
+#endif
+
+ EGLSurface egl_surface;
+
+ /* Platform specific data */
+ void *platform;
+} CoglOnscreenEGL;
+
const CoglWinsysVtable *
_cogl_winsys_egl_get_vtable (void);
@@ -141,4 +183,7 @@ _cogl_egl_destroy_image (CoglContext *ctx,
EGLImageKHR image);
#endif
+void
+_cogl_winsys_egl_check_egl_extensions (CoglRenderer *renderer);
+
#endif /* __COGL_WINSYS_EGL_PRIVATE_H */
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index de757c2..7637880 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -62,10 +62,6 @@
#include <android/native_window.h>
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
-#include "cogl-winsys-kms.h"
-#endif
-
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
@@ -82,32 +78,6 @@
#define MAX_EGL_CONFIG_ATTRIBS 30
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
-typedef struct _CoglOnscreenXlib
-{
- Window xwin;
- gboolean is_foreign_xwin;
-} CoglOnscreenXlib;
-#endif
-
-typedef struct _CoglOnscreenEGL
-{
-#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
- CoglOnscreenXlib _parent;
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT
- struct wl_egl_window *wayland_egl_native_window;
- struct wl_surface *wayland_surface;
- struct wl_shell_surface *wayland_shell_surface;
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- CoglOnscreenKMS kms_onscreen;
-#endif
- EGLSurface egl_surface;
-} CoglOnscreenEGL;
-
#ifdef EGL_KHR_image_pixmap
typedef struct _CoglTexturePixmapEGL
{
@@ -264,8 +234,8 @@ display_handle_global_cb (struct wl_display *display,
#endif
/* Updates all the function pointers */
-static void
-check_egl_extensions (CoglRenderer *renderer)
+void
+_cogl_winsys_egl_check_egl_extensions (CoglRenderer *renderer)
{
CoglRendererEGL *egl_renderer = renderer->winsys;
const char *egl_extensions;
@@ -383,15 +353,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
break;
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- case COGL_WINSYS_ID_EGL_KMS:
- if (!_cogl_winsys_kms_connect (&egl_renderer->kms_renderer, error))
- goto error;
- egl_renderer->edpy = egl_renderer->kms_renderer.dpy;
- status = EGL_TRUE;
- break;
-#endif
-
case COGL_WINSYS_ID_EGL_GDL:
case COGL_WINSYS_ID_EGL_ANDROID:
case COGL_WINSYS_ID_EGL_NULL:
@@ -441,7 +402,7 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
}
#endif
- check_egl_extensions (renderer);
+ _cogl_winsys_egl_check_egl_extensions (renderer);
return TRUE;
@@ -461,7 +422,7 @@ update_winsys_features (CoglContext *context, GError **error)
memset (context->winsys_features, 0, sizeof (context->winsys_features));
- check_egl_extensions (renderer);
+ _cogl_winsys_egl_check_egl_extensions (renderer);
if (!_cogl_context_update_features (context, error))
return FALSE;
@@ -624,50 +585,53 @@ try_create_context (CoglDisplay *display,
#endif
const char *error_message;
- egl_attributes_from_framebuffer_config (display,
- &display->onscreen_template->config,
- with_stencil_buffer,
- cfg_attribs);
-
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context == NULL, TRUE);
if (renderer->driver == COGL_DRIVER_GL)
eglBindAPI (EGL_OPENGL_API);
- if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS)
+ if (display->renderer->driver == COGL_DRIVER_GLES2)
{
- edpy = egl_renderer->edpy;
+ attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
+ attribs[1] = 2;
+ attribs[2] = EGL_NONE;
+ }
+ else
+ attribs[0] = EGL_NONE;
- status = eglChooseConfig (edpy,
- cfg_attribs,
- &config, 1,
- &config_count);
- if (status != EGL_TRUE || config_count == 0)
- {
- error_message = "Unable to find a usable EGL configuration";
- goto fail;
- }
+ /* Divert to the platform implementation if one is defined */
+ if (egl_renderer->platform_vtable &&
+ egl_renderer->platform_vtable->try_create_context)
+ return egl_renderer->platform_vtable->
+ try_create_context (display, attribs, error);
- egl_display->egl_config = config;
+ egl_attributes_from_framebuffer_config (display,
+ &display->onscreen_template->config,
+ with_stencil_buffer,
+ cfg_attribs);
- if (display->renderer->driver == COGL_DRIVER_GLES2)
- {
- attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
- attribs[1] = 2;
- attribs[2] = EGL_NONE;
- }
- else
- attribs[0] = EGL_NONE;
+ edpy = egl_renderer->edpy;
- egl_display->egl_context = eglCreateContext (edpy,
- config,
- EGL_NO_CONTEXT,
- attribs);
- if (egl_display->egl_context == EGL_NO_CONTEXT)
- {
- error_message = "Unable to create a suitable EGL context";
- goto fail;
- }
+ status = eglChooseConfig (edpy,
+ cfg_attribs,
+ &config, 1,
+ &config_count);
+ if (status != EGL_TRUE || config_count == 0)
+ {
+ error_message = "Unable to find a usable EGL configuration";
+ goto fail;
+ }
+
+ egl_display->egl_config = config;
+
+ egl_display->egl_context = eglCreateContext (edpy,
+ config,
+ EGL_NO_CONTEXT,
+ attribs);
+ if (egl_display->egl_context == EGL_NO_CONTEXT)
+ {
+ error_message = "Unable to create a suitable EGL context";
+ goto fail;
}
switch (renderer->winsys_vtable->id)
@@ -897,19 +861,6 @@ try_create_context (CoglDisplay *display,
&egl_display->egl_surface_height);
break;
#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- case COGL_WINSYS_ID_EGL_KMS:
- if (!_cogl_winsys_kms_create_context (display->renderer,
- display,
- error))
- return FALSE;
-
- egl_display->egl_surface_width = egl_display->kms_display.width;
- egl_display->egl_surface_height = egl_display->kms_display.height;
- egl_display->egl_context = egl_display->kms_display.egl_context;
- break;
-#endif
}
return TRUE;
@@ -932,21 +883,9 @@ cleanup_context (CoglDisplay *display)
CoglXlibRenderer *xlib_renderer = renderer->winsys;
#endif
-#if defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
- if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_KMS)
- {
- GError *error = NULL;
-
- if (!_cogl_winsys_kms_destroy_context (&egl_renderer->kms_renderer,
- &egl_display->kms_display,
- &error))
- {
- g_critical (G_STRLOC ": Error cleaning up KMS rendering state: %s",
- error->message);
- g_clear_error (&error);
- }
- }
-#endif
+ if (egl_renderer->platform_vtable &&
+ egl_renderer->platform_vtable->cleanup_context)
+ egl_renderer->platform_vtable->cleanup_context (display);
if (egl_display->egl_context != EGL_NO_CONTEXT)
{
@@ -1041,12 +980,17 @@ create_context (CoglDisplay *display, GError **error)
static void
_cogl_winsys_display_destroy (CoglDisplay *display)
{
+ CoglRendererEGL *egl_renderer = display->renderer->winsys;
CoglDisplayEGL *egl_display = display->winsys;
_COGL_RETURN_IF_FAIL (egl_display != NULL);
cleanup_context (display);
+ if (egl_renderer->platform_vtable &&
+ egl_renderer->platform_vtable->display_destroy)
+ egl_renderer->platform_vtable->display_destroy (display);
+
g_slice_free (CoglDisplayEGL, display->winsys);
display->winsys = NULL;
}
@@ -1143,9 +1087,7 @@ _cogl_winsys_display_setup (CoglDisplay *display,
{
CoglDisplayEGL *egl_display;
CoglRenderer *renderer = display->renderer;
-#ifdef COGL_HAS_WAYLAND_EGL_SERVER_SUPPORT
CoglRendererEGL *egl_renderer = renderer->winsys;
-#endif
_COGL_RETURN_VAL_IF_FAIL (display->winsys == NULL, FALSE);
@@ -1168,11 +1110,10 @@ _cogl_winsys_display_setup (CoglDisplay *display,
}
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_KMS &&
- !_cogl_winsys_kms_display_setup (display, error))
+ if (egl_renderer->platform_vtable &&
+ egl_renderer->platform_vtable->display_setup &&
+ !egl_renderer->platform_vtable->display_setup (display, error))
goto error;
-#endif
if (!create_context (display, error))
goto error;
@@ -1237,36 +1178,33 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
_COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
- if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS)
+ egl_attributes_from_framebuffer_config (display,
+ &framebuffer->config,
+ need_stencil,
+ attributes);
+
+ status = eglChooseConfig (egl_renderer->edpy,
+ attributes,
+ &egl_config, 1,
+ &config_count);
+ if (status != EGL_TRUE || config_count == 0)
{
- egl_attributes_from_framebuffer_config (display,
- &framebuffer->config,
- need_stencil,
- attributes);
-
- status = eglChooseConfig (egl_renderer->edpy,
- attributes,
- &egl_config, 1,
- &config_count);
- if (status != EGL_TRUE || config_count == 0)
- {
- g_set_error (error, COGL_WINSYS_ERROR,
- COGL_WINSYS_ERROR_CREATE_ONSCREEN,
- "Failed to find a suitable EGL configuration");
- return FALSE;
- }
+ g_set_error (error, COGL_WINSYS_ERROR,
+ COGL_WINSYS_ERROR_CREATE_ONSCREEN,
+ "Failed to find a suitable EGL configuration");
+ return FALSE;
+ }
- /* Update the real number of samples_per_pixel now that we have
- * found an egl_config... */
- if (framebuffer->config.samples_per_pixel)
- {
- EGLint samples;
- status = eglGetConfigAttrib (egl_renderer->edpy,
- egl_config,
- EGL_SAMPLES, &samples);
- g_return_val_if_fail (status == EGL_TRUE, TRUE);
- framebuffer->samples_per_pixel = samples;
- }
+ /* Update the real number of samples_per_pixel now that we have
+ * found an egl_config... */
+ if (framebuffer->config.samples_per_pixel)
+ {
+ EGLint samples;
+ status = eglGetConfigAttrib (egl_renderer->edpy,
+ egl_config,
+ EGL_SAMPLES, &samples);
+ g_return_val_if_fail (status == EGL_TRUE, TRUE);
+ framebuffer->samples_per_pixel = samples;
}
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
@@ -1449,12 +1387,10 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
#if defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) || \
- defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \
- defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
+ defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT)
case COGL_WINSYS_ID_EGL_NULL:
case COGL_WINSYS_ID_EGL_ANDROID:
case COGL_WINSYS_ID_EGL_GDL:
- case COGL_WINSYS_ID_EGL_KMS:
if (egl_display->have_onscreen)
{
@@ -1464,20 +1400,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
return FALSE;
}
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_KMS)
- {
- CoglContext *context = cogl_framebuffer_get_context (framebuffer);
- if (!_cogl_winsys_kms_onscreen_init (context,
- &egl_renderer->kms_renderer,
- &egl_display->kms_display,
- &egl_onscreen->kms_onscreen,
- error))
- return FALSE;
- }
- else
-#endif
- egl_onscreen->egl_surface = egl_display->egl_surface;
+ egl_onscreen->egl_surface = egl_display->egl_surface;
_cogl_framebuffer_winsys_update_size (framebuffer,
egl_display->egl_surface_width,
@@ -1514,8 +1437,7 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
/* If we never successfully allocated then there's nothing to do */
if (egl_onscreen == NULL)
return;
- if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS &&
- egl_onscreen->egl_surface != EGL_NO_SURFACE)
+ if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
{
if (eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface)
== EGL_FALSE)
@@ -1558,11 +1480,6 @@ _cogl_winsys_onscreen_deinit (CoglOnscreen *onscreen)
}
#endif
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- _cogl_winsys_kms_onscreen_deinit (&egl_renderer->kms_renderer,
- &egl_onscreen->kms_onscreen);
-#endif
-
g_slice_free (CoglOnscreenEGL, onscreen->winsys);
onscreen->winsys = NULL;
}
@@ -1575,15 +1492,6 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
CoglRenderer *renderer = context->display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_KMS)
- {
- _cogl_winsys_kms_bind (&egl_renderer->kms_renderer,
- &egl_display->kms_display);
- return;
- }
-#endif
-
#if defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \
defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) || \
@@ -1647,32 +1555,29 @@ _cogl_winsys_onscreen_swap_region (CoglOnscreen *onscreen,
int *rectangles = g_alloca (sizeof (int) * n_rectangles * 4);
int i;
- if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS)
+ /* eglSwapBuffersRegion expects rectangles relative to the
+ * bottom left corner but we are given rectangles relative to
+ * the top left so we need to flip them... */
+ memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4);
+ for (i = 0; i < n_rectangles; i++)
{
- /* eglSwapBuffersRegion expects rectangles relative to the
- * bottom left corner but we are given rectangles relative to
- * the top left so we need to flip them... */
- memcpy (rectangles, user_rectangles, sizeof (int) * n_rectangles * 4);
- for (i = 0; i < n_rectangles; i++)
- {
- int *rect = &rectangles[4 * i];
- rect[1] = framebuffer_height - rect[1] - rect[3];
- }
-
- /* At least for eglSwapBuffers the EGL spec says that the surface to
- swap must be bound to the current context. It looks like Mesa
- also validates that this is the case for eglSwapBuffersRegion so
- we must bind here too */
- _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER (onscreen),
- COGL_FRAMEBUFFER_STATE_BIND);
-
- if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
- egl_onscreen->egl_surface,
- n_rectangles,
- rectangles) == EGL_FALSE)
- g_warning ("Error reported by eglSwapBuffersRegion");
+ int *rect = &rectangles[4 * i];
+ rect[1] = framebuffer_height - rect[1] - rect[3];
}
+
+ /* At least for eglSwapBuffers the EGL spec says that the surface to
+ swap must be bound to the current context. It looks like Mesa
+ also validates that this is the case for eglSwapBuffersRegion so
+ we must bind here too */
+ _cogl_framebuffer_flush_state (COGL_FRAMEBUFFER (onscreen),
+ COGL_FRAMEBUFFER (onscreen),
+ COGL_FRAMEBUFFER_STATE_BIND);
+
+ if (egl_renderer->pf_eglSwapBuffersRegion (egl_renderer->edpy,
+ egl_onscreen->egl_surface,
+ n_rectangles,
+ rectangles) == EGL_FALSE)
+ g_warning ("Error reported by eglSwapBuffersRegion");
#endif
}
@@ -1703,19 +1608,6 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
CoglRenderer *renderer = context->display->renderer;
CoglRendererEGL *egl_renderer = renderer->winsys;
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- CoglDisplayEGL *egl_display = context->display->winsys;
-#endif
-
-#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
- if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_KMS)
- {
- _cogl_winsys_kms_swap_buffers (&egl_renderer->kms_renderer,
- &egl_display->kms_display,
- &egl_onscreen->kms_onscreen);
- return;
- }
-#endif
/* The specification for EGL (at least in 1.4) says that the surface
needs to be bound to the current context for the swap to work
@@ -1761,18 +1653,13 @@ static void
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
{
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
- CoglRenderer *renderer = context->display->renderer;
-
- if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS)
- {
- CoglContextEGL *egl_context = context->winsys;
- CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
+ CoglContextEGL *egl_context = context->winsys;
+ CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
- if (egl_context->current_surface != egl_onscreen->egl_surface)
- return;
+ if (egl_context->current_surface != egl_onscreen->egl_surface)
+ return;
- egl_context->current_surface = EGL_NO_SURFACE;
- }
+ egl_context->current_surface = EGL_NO_SURFACE;
_cogl_winsys_onscreen_bind (onscreen);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]