[cogl/wip/rob/kms-winsys: 2/2] kms: Add first WIP version of "baremetal" backend for EGL on KMS



commit ad7aa7bed79d616889762ef04a18e88754fbb162
Author: Rob Bradford <rob linux intel com>
Date:   Mon Nov 7 17:16:13 2011 +0000

    kms: Add first WIP version of "baremetal" backend for EGL on KMS
    
    To compile this backend - get some dribbly black candles, sacrifice a goat and
    configure with:
    
    ./configure --enable-kms-egl-platform --enable-deprecated \
                --disable-xlib-egl-platform --disable-glx --disable-introspection

 cogl/Makefile.am              |    5 +
 cogl/winsys/cogl-winsys-egl.c |   63 +++++++-
 cogl/winsys/cogl-winsys-kms.c |  337 +++++++++++++++++++++++++++++++++++++++++
 cogl/winsys/cogl-winsys-kms.h |   71 +++++++++
 configure.ac                  |   26 +++
 5 files changed, 498 insertions(+), 4 deletions(-)
---
diff --git a/cogl/Makefile.am b/cogl/Makefile.am
index ae02d86..464a8d0 100644
--- a/cogl/Makefile.am
+++ b/cogl/Makefile.am
@@ -368,6 +368,11 @@ if SUPPORT_EGL_PLATFORM_WAYLAND
 cogl_public_h += \
 	$(srcdir)/cogl-wayland-renderer.h
 endif
+if SUPPORT_EGL_PLATFORM_KMS
+cogl_sources_c += \
+	$(srcdir)/winsys/cogl-winsys-kms.c \
+	$(srcdir)/winsys/cogl-winsys-kms.h
+endif
 if SUPPORT_EGL
 cogl_sources_c += \
        $(srcdir)/winsys/cogl-winsys-egl.c \
diff --git a/cogl/winsys/cogl-winsys-egl.c b/cogl/winsys/cogl-winsys-egl.c
index ec2842b..085e562 100644
--- a/cogl/winsys/cogl-winsys-egl.c
+++ b/cogl/winsys/cogl-winsys-egl.c
@@ -62,7 +62,12 @@
 #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>
 #include <sys/stat.h>
 #include <fcntl.h>
@@ -106,6 +111,9 @@ 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
 
   /* Function pointers for GLX specific extensions */
 #define COGL_WINSYS_FEATURE_BEGIN(a, b, c, d)
@@ -137,8 +145,11 @@ typedef struct _CoglDisplayEGL
   EGLSurface dummy_surface;
 #elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
       defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT) || \
-      defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT)
+      defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT) || \
+      defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
+#ifndef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
   EGLSurface egl_surface;
+#endif
   int egl_surface_width;
   int egl_surface_height;
   gboolean have_onscreen;
@@ -434,6 +445,11 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
 			  &egl_renderer->egl_version_major,
 			  &egl_renderer->egl_version_minor);
 
+#elif defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
+  if (!_cogl_winsys_kms_connect (renderer, &(egl_renderer->kms_renderer), error))
+    goto error;
+  egl_renderer->edpy = egl_renderer->kms_renderer.dpy;
+  status = EGL_TRUE;
 #else
   egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
 
@@ -665,6 +681,7 @@ try_create_context (CoglDisplay *display,
   if (display->renderer->driver == COGL_DRIVER_GL)
     eglBindAPI (EGL_OPENGL_API);
 
+#ifndef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
   status = eglChooseConfig (edpy,
                             cfg_attribs,
                             &config, 1,
@@ -695,6 +712,7 @@ try_create_context (CoglDisplay *display,
       error_message = "Unable to create a suitable EGL context";
       goto fail;
     }
+#endif
 
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
 
@@ -907,6 +925,13 @@ try_create_context (CoglDisplay *display,
                    EGL_HEIGHT,
                    &egl_display->egl_surface_height);
 
+#elif defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
+  if (!_cogl_winsys_kms_create_context (&(egl_renderer->kms_renderer), error))
+    return FALSE;
+
+  egl_display->egl_surface_width = egl_renderer->kms_renderer.width;
+  egl_display->egl_surface_height = egl_renderer->kms_renderer.height;
+  egl_display->egl_context = egl_renderer->kms_renderer.egl_context;
 #else
 #error "Unknown EGL platform"
 #endif
@@ -930,6 +955,15 @@ cleanup_context (CoglDisplay *display)
   CoglXlibDisplay *xlib_display = display->winsys;
   CoglXlibRenderer *xlib_renderer = display->renderer->winsys;
 #endif
+#if defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
+  GError *error = NULL;
+
+  if (!_cogl_winsys_kms_destroy_context (&egl_renderer->kms_renderer, &error))
+    {
+      g_critical (G_STRLOC ": Error cleaning up KMS rendering state: %s", error->message);
+      g_clear_error (&error);
+    }
+#endif
 
   if (egl_display->egl_context != EGL_NO_CONTEXT)
     {
@@ -1181,7 +1215,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
   CoglOnscreenXlib *xlib_onscreen;
   Window xwin;
 #endif
-#ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT
+#if defined (COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT) || \
+    defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
   CoglRendererEGL *egl_renderer = display->renderer->winsys;
 #endif
   CoglOnscreenEGL *egl_onscreen;
@@ -1194,6 +1229,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 
   _COGL_RETURN_VAL_IF_FAIL (egl_display->egl_context, FALSE);
 
+
+#ifndef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
   egl_attributes_from_framebuffer_config (display,
                                           &framebuffer->config,
                                           need_stencil,
@@ -1222,7 +1259,7 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
       g_return_val_if_fail (status == EGL_TRUE, TRUE);
       framebuffer->samples_per_pixel = samples;
     }
-
+#endif
 #ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
 
   /* FIXME: We need to explicitly Select for ConfigureNotify events.
@@ -1384,7 +1421,8 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
 
 #elif 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_GDL_SUPPORT)          || \
+      defined (COGL_HAS_EGL_PLATFORM_KMS_SUPPORT)
   if (egl_display->have_onscreen)
     {
       g_set_error (error, COGL_WINSYS_ERROR,
@@ -1393,7 +1431,9 @@ _cogl_winsys_onscreen_init (CoglOnscreen *onscreen,
       return FALSE;
     }
 
+#ifndef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
   egl_onscreen->egl_surface = egl_display->egl_surface;
+#endif
 
   _cogl_framebuffer_winsys_update_size (framebuffer,
                                         egl_display->egl_surface_width,
@@ -1482,6 +1522,12 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
   CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
   CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
 
+#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
+  _cogl_winsys_kms_bind (&egl_renderer->kms_renderer);
+  return;
+
+#else
+
   if (egl_context->current_surface == egl_onscreen->egl_surface)
     return;
 
@@ -1497,6 +1543,7 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
 #elif defined (COGL_HAS_EGL_PLATFORM_POWERVR_NULL_SUPPORT) || \
       defined (COGL_HAS_EGL_PLATFORM_ANDROID_SUPPORT)      || \
       defined (COGL_HAS_EGL_PLATFORM_GDL_SUPPORT)
+
       return;
 #else
 #error "Unknown EGL platform"
@@ -1515,6 +1562,8 @@ _cogl_winsys_onscreen_bind (CoglOnscreen *onscreen)
     eglSwapInterval (egl_renderer->edpy, 1);
   else
     eglSwapInterval (egl_renderer->edpy, 0);
+
+#endif
 }
 
 static void
@@ -1570,6 +1619,12 @@ _cogl_winsys_onscreen_swap_buffers (CoglOnscreen *onscreen)
   CoglRendererEGL *egl_renderer = context->display->renderer->winsys;
   CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
 
+#ifdef COGL_HAS_EGL_PLATFORM_KMS_SUPPORT
+  _cogl_winsys_kms_swap_buffers (&egl_renderer->kms_renderer);
+  return;
+#endif
+
+
   eglSwapBuffers (egl_renderer->edpy, egl_onscreen->egl_surface);
 
 #ifdef COGL_HAS_EGL_PLATFORM_WAYLAND_SUPPORT
diff --git a/cogl/winsys/cogl-winsys-kms.c b/cogl/winsys/cogl-winsys-kms.c
new file mode 100644
index 0000000..85bd9e5
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-kms.c
@@ -0,0 +1,337 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Some code inspired by mesa demos eglkms.c.
+ *
+ * Authors:
+ *   Rob Bradford <rob linux intel com>
+ *   Kristian HÃgsberg (from eglkms.c)
+ *   Benjamin Franzke (from eglkms.c)
+ */
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "cogl-winsys-kms.h"
+
+static const char device_name[] = "/dev/dri/card0";
+
+static gboolean
+setup_kms (CoglRendererKMS  *kms_renderer,
+           GError          **error)
+{
+  drmModeRes *resources;
+  drmModeConnector *connector;
+  drmModeEncoder *encoder;
+  int i;
+
+  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_renderer->connector = connector;
+  kms_renderer->encoder = encoder;
+  kms_renderer->mode = connector->modes[0];
+
+  return TRUE;
+}
+
+gboolean
+_cogl_winsys_kms_connect (CoglRenderer     *renderer,
+                          CoglRendererKMS  *kms_renderer,
+                          GError          **error)
+{
+  EGLint major, minor;
+
+  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;
+    }
+
+  kms_renderer->dpy = eglGetDisplay (kms_renderer->gbm);
+  if (kms_renderer->dpy == EGL_NO_DISPLAY)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "Couldn't get eglDisplay");
+      goto destroy_gbm_device;
+    }
+
+  if (!eglInitialize (kms_renderer->dpy, &major, &minor))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_INIT,
+                   "Couldn't initialize EGL");
+      goto egl_terminate;
+    }
+
+  if (!setup_kms (kms_renderer, error))
+    {
+      goto egl_terminate;
+    }
+
+  kms_renderer->width = kms_renderer->mode.hdisplay;
+  kms_renderer->height = kms_renderer->mode.vdisplay;
+
+  return TRUE;
+egl_terminate:
+   eglTerminate (kms_renderer->dpy);
+destroy_gbm_device:
+   gbm_device_destroy (kms_renderer->gbm);
+close_fd:
+   close (kms_renderer->fd);
+
+   return FALSE;
+}
+
+gboolean
+_cogl_winsys_kms_create_context (CoglRendererKMS  *kms_renderer,
+                                 GError          **error)
+{
+  int i;
+  kms_renderer->egl_context = eglCreateContext (kms_renderer->dpy, NULL, EGL_NO_CONTEXT, NULL);
+
+  if (kms_renderer->egl_context == NULL)
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Couldn't create EGL context");
+      return FALSE;
+    }
+
+  if (!eglMakeCurrent (kms_renderer->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, kms_renderer->egl_context))
+    {
+      g_set_error (error, COGL_WINSYS_ERROR,
+                   COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                   "Failed to make context current");
+      return FALSE;
+    }
+
+  glGenRenderbuffers (2, kms_renderer->color_rb);
+
+  for (i = 0; i < 2; i++)
+    {
+      uint32_t handle, stride;
+
+      kms_renderer->bo[i] =
+        gbm_bo_create (kms_renderer->gbm,
+                       kms_renderer->mode.hdisplay, kms_renderer->mode.vdisplay,
+                       GBM_BO_FORMAT_XRGB8888,
+                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+      if (!kms_renderer->bo[i])
+        {
+          g_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                       "Failed to allocate buffer");
+          return FALSE;
+        }
+
+      kms_renderer->image[i] = eglCreateImageKHR (kms_renderer->dpy,
+                                                  NULL,
+                                                  EGL_NATIVE_PIXMAP_KHR,
+                                                  kms_renderer->bo[i],
+                                                  NULL);
+      if (kms_renderer->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;
+        }
+
+      glBindRenderbuffer (GL_RENDERBUFFER_EXT, kms_renderer->color_rb[i]);
+      glEGLImageTargetRenderbufferStorageOES (GL_RENDERBUFFER, kms_renderer->image[i]);
+      glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);
+
+      handle = gbm_bo_get_handle (kms_renderer->bo[i]).u32;
+      stride = gbm_bo_get_pitch (kms_renderer->bo[i]);
+
+      if (drmModeAddFB (kms_renderer->fd,
+                         kms_renderer->mode.hdisplay, kms_renderer->mode.vdisplay,
+                         32, 32,
+                         stride,
+                         handle,
+                         &kms_renderer->fb_id[i]) != 0)
+        {
+          g_set_error (error, COGL_WINSYS_ERROR,
+                       COGL_WINSYS_ERROR_CREATE_CONTEXT,
+                       "Failed to create framebuffer from buffer");
+          return FALSE;
+        }
+    }
+
+  glGenFramebuffers (1, &kms_renderer->fb);
+  glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_renderer->fb);
+
+  glGenRenderbuffers(1, &kms_renderer->depth_rb);
+  glBindRenderbuffer(GL_RENDERBUFFER_EXT, kms_renderer->depth_rb);
+  glRenderbufferStorage(GL_RENDERBUFFER_EXT,
+                        GL_DEPTH_COMPONENT,
+                        kms_renderer->mode.hdisplay, kms_renderer->mode.vdisplay);
+  glBindRenderbuffer (GL_RENDERBUFFER_EXT, 0);
+
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+                                GL_DEPTH_ATTACHMENT_EXT,
+                                GL_RENDERBUFFER_EXT,
+                                kms_renderer->depth_rb);
+
+  kms_renderer->saved_crtc = drmModeGetCrtc (kms_renderer->fd, kms_renderer->encoder->crtc_id);
+  kms_renderer->current_frame = 0;
+  _cogl_winsys_kms_swap_buffers (kms_renderer);
+
+  return TRUE;
+}
+
+gboolean
+_cogl_winsys_kms_destroy_context (CoglRendererKMS  *kms_renderer,
+                                  GError          **error)
+{
+  int ret, i;
+
+  /* Restore the saved CRTC - this failing should not propagate an error */
+  ret = drmModeSetCrtc (kms_renderer->fd,
+                        kms_renderer->saved_crtc->crtc_id,
+                        kms_renderer->saved_crtc->buffer_id,
+                        kms_renderer->saved_crtc->x, kms_renderer->saved_crtc->y,
+                        &kms_renderer->connector->connector_id, 1,
+                        &kms_renderer->saved_crtc->mode);
+  if (ret)
+    {
+      g_critical (G_STRLOC ": Error restoring saved CRTC");
+    }
+
+  drmModeFreeCrtc (kms_renderer->saved_crtc);
+
+  glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_renderer->fb);
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+                                GL_COLOR_ATTACHMENT0_EXT,
+                                GL_RENDERBUFFER_EXT,
+                                0);
+  glDeleteRenderbuffers(2, kms_renderer->color_rb);
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+                                GL_DEPTH_ATTACHMENT_EXT,
+                                GL_RENDERBUFFER_EXT,
+                                0);
+  glDeleteRenderbuffers(1, &kms_renderer->depth_rb);
+  /* TODO: Add stencil here */
+
+  for (i = 0; i < 2; i++)
+    {
+      drmModeRmFB (kms_renderer->fd, kms_renderer->fb_id[i]);
+      eglDestroyImageKHR (kms_renderer->dpy, kms_renderer->image[i]);
+      gbm_bo_destroy (kms_renderer->bo[i]);
+    }
+
+  return TRUE;
+}
+
+void
+_cogl_winsys_kms_swap_buffers (CoglRendererKMS *kms_renderer)
+{
+  if (drmModeSetCrtc (kms_renderer->fd,
+                       kms_renderer->encoder->crtc_id,
+                       kms_renderer->fb_id[kms_renderer->current_frame],
+                       0, 0,
+                       &kms_renderer->connector->connector_id,
+                       1,
+                       &kms_renderer->mode) != 0)
+    {
+      g_error (G_STRLOC "Setting CRTC failed");
+    }
+
+  /* Update frame that we're drawing to be the new one */
+  kms_renderer->current_frame ^= 1;
+
+  glBindFramebuffer (GL_FRAMEBUFFER_EXT, kms_renderer->fb);
+  glFramebufferRenderbufferEXT (GL_FRAMEBUFFER_EXT,
+                                GL_COLOR_ATTACHMENT0_EXT,
+                                GL_RENDERBUFFER_EXT,
+                                kms_renderer->color_rb[kms_renderer->current_frame]);
+
+  if (glCheckFramebufferStatusEXT (GL_FRAMEBUFFER_EXT) !=
+      GL_FRAMEBUFFER_COMPLETE)
+    {
+      g_error ("FBO not complete");
+    }
+}
+
+void
+_cogl_winsys_kms_bind (CoglRendererKMS *kms_renderer)
+{
+  eglMakeCurrent (kms_renderer->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, kms_renderer->egl_context);
+}
diff --git a/cogl/winsys/cogl-winsys-kms.h b/cogl/winsys/cogl-winsys-kms.h
new file mode 100644
index 0000000..2d139c5
--- /dev/null
+++ b/cogl/winsys/cogl-winsys-kms.h
@@ -0,0 +1,71 @@
+/*
+ * Cogl
+ *
+ * An object oriented GL/GLES Abstraction/Utility Layer
+ *
+ * Copyright (C) 2011 Intel Corporation.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ *   Rob Bradford <rob linux intel com>
+ */
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <drm.h>
+#include <xf86drmMode.h>
+#include <gbm.h>
+#include <glib.h>
+
+#include "cogl-winsys-private.h"
+
+typedef struct _CoglRendererKMS
+{
+  int fd;
+  struct gbm_device *gbm;
+  EGLDisplay *dpy;
+  EGLContext egl_context;
+
+  drmModeConnector *connector;
+  drmModeEncoder *encoder;
+  drmModeModeInfo mode;
+  uint32_t fb_id[2];
+  struct gbm_bo *bo[2];
+  GLuint fb, color_rb[2], depth_rb;
+  EGLImageKHR image[2];
+
+  gint width, height;
+  gint current_frame;
+  drmModeCrtcPtr saved_crtc;
+} CoglRendererKMS;
+
+gboolean
+_cogl_winsys_kms_connect (CoglRenderer     *renderer,
+                          CoglRendererKMS  *kms_renderer,
+                          GError          **error);
+
+void
+_cogl_winsys_kms_swap_buffers (CoglRendererKMS *kms_renderer);
+
+void
+_cogl_winsys_kms_bind (CoglRendererKMS *kms_renderer);
+
+gboolean
+_cogl_winsys_kms_create_context (CoglRendererKMS  *kms_renderer,
+                                 GError          **error);
+gboolean
+_cogl_winsys_kms_destroy_context (CoglRendererKMS  *kms_renderer,
+                                  GError          **error);
diff --git a/configure.ac b/configure.ac
index e1f760f..50eaa60 100644
--- a/configure.ac
+++ b/configure.ac
@@ -755,6 +755,32 @@ AS_IF([test "x$enable_wayland_egl_platform" == "xyes"],
 AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_WAYLAND,
                [test "x$enable_wayland_egl_platform" = "xyes"])
 
+
+AC_ARG_ENABLE(
+  [kms-egl-platform],
+  [AC_HELP_STRING([--enable-kms-egl-platform=@<:@no/yes@:>@], [Enable support for the Wayland egl platform @<:@default=no@:>@])],
+  [],
+  enable_kms_egl_platform=no
+)
+AS_IF([test "x$enable_kms_egl_platform" == "xyes"],
+      [
+        EGL_PLATFORM_COUNT=$((EGL_PLATFORM_COUNT+1))
+        NEED_EGL=yes
+        EGL_PLATFORMS="$EGL_PLATFORMS kms"
+
+        PKG_CHECK_EXISTS([gbm],
+                         [
+                           COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gbm"
+                           COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES libdrm"
+                           COGL_PKG_REQUIRES="$COGL_PKG_REQUIRES gl"
+                         ],
+                         [AC_MSG_ERROR([Unable to locate required kms libraries])])
+
+        COGL_DEFINES_SYMBOLS="$COGL_DEFINES_SYMBOLS COGL_HAS_EGL_PLATFORM_KMS_SUPPORT"
+      ])
+AM_CONDITIONAL(SUPPORT_EGL_PLATFORM_KMS,
+               [test "x$enable_kms_egl_platform" = "xyes"])
+
 AC_ARG_ENABLE(
   [wayland-egl-server],
   [AC_HELP_STRING([--enable-wayland-egl-server=@<:@no/yes@:>@], [Enable server side wayland support @<:@default=no@:>@])],



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]