2011-12-08 12:24:40 -05:00
|
|
|
/*
|
|
|
|
* 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:
|
2011-12-09 11:10:01 -05:00
|
|
|
* Rob Bradford <rob@linux.intel.com>
|
|
|
|
* Kristian Høgsberg (from eglkms.c)
|
|
|
|
* Benjamin Franzke (from eglkms.c)
|
2011-12-08 12:24:40 -05:00
|
|
|
* Robert Bragg <robert@linux.intel.com>
|
|
|
|
* Neil Roberts <neil@linux.intel.com>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
#include <EGL/egl.h>
|
|
|
|
#include <EGL/eglext.h>
|
|
|
|
#include <drm.h>
|
2011-12-19 12:17:28 -05:00
|
|
|
#include <xf86drm.h>
|
2011-12-09 11:10:01 -05:00
|
|
|
#include <xf86drmMode.h>
|
|
|
|
#include <gbm.h>
|
|
|
|
#include <glib.h>
|
|
|
|
#include <sys/fcntl.h>
|
|
|
|
#include <unistd.h>
|
2011-12-19 12:17:28 -05:00
|
|
|
#include <string.h>
|
2011-12-09 11:10:01 -05:00
|
|
|
|
2011-12-08 12:24:40 -05:00
|
|
|
#include "cogl-winsys-egl-kms-private.h"
|
|
|
|
#include "cogl-winsys-egl-private.h"
|
2011-12-09 11:10:01 -05:00
|
|
|
#include "cogl-renderer-private.h"
|
|
|
|
#include "cogl-framebuffer-private.h"
|
|
|
|
#include "cogl-onscreen-private.h"
|
2012-03-06 13:21:28 -05:00
|
|
|
#include "cogl-kms-renderer.h"
|
2011-12-09 11:10:01 -05:00
|
|
|
|
|
|
|
static const CoglWinsysEGLVtable _cogl_winsys_egl_vtable;
|
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
static const CoglWinsysVtable *parent_vtable;
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
typedef struct _CoglRendererKMS
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct gbm_device *gbm;
|
2011-12-19 12:17:28 -05:00
|
|
|
CoglPollFD poll_fd;
|
2011-12-09 11:10:01 -05:00
|
|
|
} CoglRendererKMS;
|
|
|
|
|
|
|
|
typedef struct _CoglDisplayKMS
|
|
|
|
{
|
|
|
|
drmModeConnector *connector;
|
|
|
|
drmModeEncoder *encoder;
|
|
|
|
drmModeModeInfo mode;
|
|
|
|
drmModeCrtcPtr saved_crtc;
|
|
|
|
int width, height;
|
|
|
|
} CoglDisplayKMS;
|
|
|
|
|
|
|
|
typedef struct _CoglOnscreenKMS
|
|
|
|
{
|
2011-12-19 10:37:26 -05:00
|
|
|
struct gbm_surface *surface;
|
|
|
|
uint32_t current_fb_id;
|
|
|
|
uint32_t next_fb_id;
|
|
|
|
struct gbm_bo *current_bo;
|
|
|
|
struct gbm_bo *next_bo;
|
2011-12-09 11:10:01 -05:00
|
|
|
} 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;
|
|
|
|
|
|
|
|
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 (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
|
|
|
|
goto egl_terminate;
|
|
|
|
|
2011-12-19 12:17:28 -05:00
|
|
|
kms_renderer->poll_fd.fd = kms_renderer->fd;
|
|
|
|
kms_renderer->poll_fd.events = COGL_POLL_FD_EVENT_IN;
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
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;
|
2012-02-23 11:41:27 -05:00
|
|
|
case COGL_DRIVER_ANY:
|
|
|
|
g_return_val_if_reached (FALSE);
|
2011-12-09 11:10:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
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
|
2011-12-19 10:37:26 -05:00
|
|
|
_cogl_winsys_egl_context_created (CoglDisplay *display,
|
|
|
|
GError **error)
|
2011-12-09 11:10:01 -05:00
|
|
|
{
|
|
|
|
CoglRenderer *renderer = display->renderer;
|
|
|
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
|
|
CoglDisplayEGL *egl_display = display->winsys;
|
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
/* Restore the saved CRTC - this failing should not propagate an error */
|
2012-01-23 10:39:10 -05:00
|
|
|
if (kms_display->saved_crtc)
|
|
|
|
{
|
|
|
|
int 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);
|
|
|
|
}
|
2011-12-09 11:10:01 -05:00
|
|
|
}
|
|
|
|
|
2011-12-19 12:17:28 -05:00
|
|
|
static void
|
|
|
|
page_flip_handler (int fd,
|
|
|
|
unsigned int frame,
|
|
|
|
unsigned int sec,
|
|
|
|
unsigned int usec,
|
|
|
|
void *data)
|
|
|
|
{
|
|
|
|
CoglOnscreen *onscreen = data;
|
|
|
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
|
|
CoglOnscreenKMS *kms_onscreen = egl_onscreen->platform;
|
|
|
|
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
|
|
|
CoglRenderer *renderer = context->display->renderer;
|
|
|
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
|
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
|
|
|
|
|
|
if (kms_onscreen->current_fb_id)
|
|
|
|
{
|
|
|
|
drmModeRmFB (kms_renderer->fd,
|
|
|
|
kms_onscreen->current_fb_id);
|
|
|
|
kms_onscreen->current_fb_id = 0;
|
|
|
|
}
|
|
|
|
if (kms_onscreen->current_bo)
|
|
|
|
{
|
|
|
|
gbm_surface_release_buffer (kms_onscreen->surface,
|
|
|
|
kms_onscreen->current_bo);
|
|
|
|
kms_onscreen->current_bo = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
kms_onscreen->current_fb_id = kms_onscreen->next_fb_id;
|
|
|
|
kms_onscreen->next_fb_id = 0;
|
|
|
|
|
|
|
|
kms_onscreen->current_bo = kms_onscreen->next_bo;
|
|
|
|
kms_onscreen->next_bo = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
handle_drm_event (CoglRendererKMS *kms_renderer)
|
|
|
|
{
|
|
|
|
drmEventContext evctx;
|
|
|
|
|
|
|
|
memset (&evctx, 0, sizeof evctx);
|
|
|
|
evctx.version = DRM_EVENT_CONTEXT_VERSION;
|
|
|
|
evctx.page_flip_handler = page_flip_handler;
|
|
|
|
drmHandleEvent (kms_renderer->fd, &evctx);
|
|
|
|
}
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
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;
|
2011-12-19 10:37:26 -05:00
|
|
|
EGLint handle, pitch;
|
2011-12-19 12:17:28 -05:00
|
|
|
|
|
|
|
/* If we already have a pending swap then block until it completes */
|
|
|
|
while (kms_onscreen->next_fb_id != 0)
|
|
|
|
handle_drm_event (kms_renderer);
|
2011-12-19 10:37:26 -05:00
|
|
|
|
|
|
|
/* First chain-up. This will call eglSwapBuffers */
|
|
|
|
parent_vtable->onscreen_swap_buffers (onscreen);
|
|
|
|
|
|
|
|
/* Now we need to set the CRTC to whatever is the front buffer */
|
2011-12-19 12:17:28 -05:00
|
|
|
kms_onscreen->next_bo = gbm_surface_lock_front_buffer (kms_onscreen->surface);
|
2011-12-19 10:37:26 -05:00
|
|
|
|
2011-12-19 12:17:28 -05:00
|
|
|
pitch = gbm_bo_get_pitch (kms_onscreen->next_bo);
|
|
|
|
handle = gbm_bo_get_handle (kms_onscreen->next_bo).u32;
|
2011-12-19 10:37:26 -05:00
|
|
|
|
|
|
|
if (drmModeAddFB (kms_renderer->fd,
|
|
|
|
kms_display->width,
|
|
|
|
kms_display->height,
|
|
|
|
24, /* depth */
|
|
|
|
32, /* bpp */
|
|
|
|
pitch,
|
|
|
|
handle,
|
2011-12-19 12:17:28 -05:00
|
|
|
&kms_onscreen->next_fb_id) == 0)
|
2011-12-09 11:10:01 -05:00
|
|
|
{
|
2011-12-19 12:17:28 -05:00
|
|
|
drmModePageFlip (kms_renderer->fd,
|
|
|
|
kms_display->encoder->crtc_id,
|
|
|
|
kms_onscreen->next_fb_id,
|
|
|
|
DRM_MODE_PAGE_FLIP_EVENT,
|
|
|
|
onscreen);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gbm_surface_release_buffer (kms_onscreen->surface,
|
|
|
|
kms_onscreen->next_bo);
|
|
|
|
kms_onscreen->next_bo = NULL;
|
|
|
|
kms_onscreen->next_fb_id = 0;
|
2011-12-09 11:10:01 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
_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;
|
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
kms_onscreen->surface =
|
|
|
|
gbm_surface_create (kms_renderer->gbm,
|
2011-12-09 11:10:01 -05:00
|
|
|
kms_display->mode.hdisplay,
|
|
|
|
kms_display->mode.vdisplay,
|
2011-12-19 10:37:26 -05:00
|
|
|
GBM_BO_FORMAT_XRGB8888,
|
|
|
|
GBM_BO_USE_SCANOUT |
|
|
|
|
GBM_BO_USE_RENDERING);
|
2011-12-09 11:10:01 -05:00
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
if (!kms_onscreen->surface)
|
|
|
|
{
|
|
|
|
g_set_error (error, COGL_WINSYS_ERROR,
|
|
|
|
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
|
|
|
"Failed to allocate surface");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-12-09 11:10:01 -05:00
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
egl_onscreen->egl_surface =
|
|
|
|
eglCreateWindowSurface (egl_renderer->edpy,
|
|
|
|
egl_display->egl_config,
|
|
|
|
(NativeWindowType) kms_onscreen->surface,
|
|
|
|
NULL);
|
|
|
|
if (egl_onscreen->egl_surface == EGL_NO_SURFACE)
|
|
|
|
{
|
|
|
|
g_set_error (error, COGL_WINSYS_ERROR,
|
|
|
|
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
|
|
|
"Failed to allocate surface");
|
|
|
|
return FALSE;
|
|
|
|
}
|
2011-12-09 11:10:01 -05:00
|
|
|
|
|
|
|
_cogl_framebuffer_winsys_update_size (framebuffer,
|
2011-12-12 16:17:33 -05:00
|
|
|
kms_display->width,
|
|
|
|
kms_display->height);
|
2011-12-09 11:10:01 -05:00
|
|
|
|
|
|
|
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;
|
|
|
|
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
|
|
|
CoglOnscreenKMS *kms_onscreen;
|
|
|
|
|
|
|
|
/* If we never successfully allocated then there's nothing to do */
|
|
|
|
if (egl_onscreen == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
kms_onscreen = egl_onscreen->platform;
|
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
if (egl_onscreen->egl_surface != EGL_NO_SURFACE)
|
2011-12-09 11:10:01 -05:00
|
|
|
{
|
2011-12-19 10:37:26 -05:00
|
|
|
eglDestroySurface (egl_renderer->edpy, egl_onscreen->egl_surface);
|
|
|
|
egl_onscreen->egl_surface = EGL_NO_SURFACE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kms_onscreen->surface)
|
|
|
|
{
|
|
|
|
gbm_surface_destroy (kms_onscreen->surface);
|
|
|
|
kms_onscreen->surface = NULL;
|
2011-12-09 11:10:01 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
g_slice_free (CoglOnscreenKMS, kms_onscreen);
|
|
|
|
g_slice_free (CoglOnscreenEGL, onscreen->winsys);
|
|
|
|
onscreen->winsys = NULL;
|
|
|
|
}
|
|
|
|
|
2011-12-19 12:17:28 -05:00
|
|
|
static void
|
|
|
|
_cogl_winsys_poll_get_info (CoglContext *context,
|
|
|
|
CoglPollFD **poll_fds,
|
|
|
|
int *n_poll_fds,
|
|
|
|
gint64 *timeout)
|
|
|
|
{
|
|
|
|
CoglRenderer *renderer = context->display->renderer;
|
|
|
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
|
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
|
|
|
|
|
|
*poll_fds = &kms_renderer->poll_fd;
|
|
|
|
*n_poll_fds = 1;
|
|
|
|
*timeout = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_cogl_winsys_poll_dispatch (CoglContext *context,
|
|
|
|
const CoglPollFD *poll_fds,
|
|
|
|
int n_poll_fds)
|
|
|
|
{
|
|
|
|
CoglRenderer *renderer = context->display->renderer;
|
|
|
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
|
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < n_poll_fds; i++)
|
|
|
|
if (poll_fds[i].fd == kms_renderer->fd)
|
|
|
|
{
|
|
|
|
if (poll_fds[i].revents)
|
|
|
|
handle_drm_event (kms_renderer);
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
static const CoglWinsysEGLVtable
|
|
|
|
_cogl_winsys_egl_vtable =
|
|
|
|
{
|
|
|
|
.display_setup = _cogl_winsys_egl_display_setup,
|
|
|
|
.display_destroy = _cogl_winsys_egl_display_destroy,
|
2011-12-19 10:37:26 -05:00
|
|
|
.context_created = _cogl_winsys_egl_context_created,
|
2011-12-09 11:10:01 -05:00
|
|
|
.cleanup_context = _cogl_winsys_egl_cleanup_context
|
|
|
|
};
|
2011-12-08 12:24:40 -05:00
|
|
|
|
|
|
|
const CoglWinsysVtable *
|
|
|
|
_cogl_winsys_egl_kms_get_vtable (void)
|
|
|
|
{
|
|
|
|
static gboolean vtable_inited = FALSE;
|
|
|
|
static CoglWinsysVtable vtable;
|
|
|
|
|
|
|
|
if (!vtable_inited)
|
|
|
|
{
|
|
|
|
/* The EGL_KMS winsys is a subclass of the EGL winsys so we
|
|
|
|
start by copying its vtable */
|
|
|
|
|
2011-12-19 10:37:26 -05:00
|
|
|
parent_vtable = _cogl_winsys_egl_get_vtable ();
|
|
|
|
vtable = *parent_vtable;
|
2011-12-08 12:24:40 -05:00
|
|
|
|
|
|
|
vtable.id = COGL_WINSYS_ID_EGL_KMS;
|
|
|
|
vtable.name = "EGL_KMS";
|
|
|
|
|
2011-12-09 11:10:01 -05:00
|
|
|
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;
|
|
|
|
|
|
|
|
/* The KMS winsys doesn't support swap region */
|
|
|
|
vtable.onscreen_swap_region = NULL;
|
|
|
|
vtable.onscreen_swap_buffers = _cogl_winsys_onscreen_swap_buffers;
|
|
|
|
|
2011-12-19 12:17:28 -05:00
|
|
|
vtable.poll_get_info = _cogl_winsys_poll_get_info;
|
|
|
|
vtable.poll_dispatch = _cogl_winsys_poll_dispatch;
|
|
|
|
|
2011-12-08 12:24:40 -05:00
|
|
|
vtable_inited = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return &vtable;
|
|
|
|
}
|
2012-01-23 10:37:51 -05:00
|
|
|
|
|
|
|
int
|
|
|
|
cogl_kms_renderer_get_kms_fd (CoglRenderer *renderer)
|
|
|
|
{
|
|
|
|
_COGL_RETURN_VAL_IF_FAIL (cogl_is_renderer (renderer), -1);
|
|
|
|
|
|
|
|
if (renderer->connected)
|
|
|
|
{
|
|
|
|
CoglRendererEGL *egl_renderer = renderer->winsys;
|
|
|
|
CoglRendererKMS *kms_renderer = egl_renderer->platform;
|
|
|
|
return kms_renderer->fd;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return -1;
|
|
|
|
}
|