mirror of
https://github.com/brl/mutter.git
synced 2025-02-16 21:34:09 +00:00
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. Reviewed-by: Robert Bragg <robert@linux.intel.com>
This commit is contained in:
parent
93e6e2051f
commit
dd75926c1a
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,507 @@
|
||||
#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;
|
||||
|
||||
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;
|
||||
|
||||
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 +550,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;
|
||||
}
|
||||
|
||||
|
@ -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,8 @@ _cogl_egl_destroy_image (CoglContext *ctx,
|
||||
EGLImageKHR image);
|
||||
#endif
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_egl_renderer_connect_common (CoglRenderer *renderer,
|
||||
GError **error);
|
||||
|
||||
#endif /* __COGL_WINSYS_EGL_PRIVATE_H */
|
||||
|
@ -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
|
||||
{
|
||||
@ -288,6 +258,27 @@ check_egl_extensions (CoglRenderer *renderer)
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_egl_renderer_connect_common (CoglRenderer *renderer,
|
||||
GError **error)
|
||||
{
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
|
||||
if (!eglInitialize (egl_renderer->edpy,
|
||||
&egl_renderer->egl_version_major,
|
||||
&egl_renderer->egl_version_minor))
|
||||
{
|
||||
g_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_INIT,
|
||||
"Couldn't initialize EGL");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
check_egl_extensions (renderer);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
_cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
GError **error)
|
||||
@ -296,7 +287,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
#ifdef COGL_HAS_EGL_PLATFORM_POWERVR_X11_SUPPORT
|
||||
CoglXlibRenderer *xlib_renderer;
|
||||
#endif
|
||||
EGLBoolean status;
|
||||
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
|
||||
gdl_ret_t rc = GDL_SUCCESS;
|
||||
gdl_display_info_t gdl_display_info;
|
||||
@ -321,10 +311,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
|
||||
egl_renderer->edpy =
|
||||
eglGetDisplay ((NativeDisplayType) xlib_renderer->xdpy);
|
||||
|
||||
status = eglInitialize (egl_renderer->edpy,
|
||||
&egl_renderer->egl_version_major,
|
||||
&egl_renderer->egl_version_minor);
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -376,19 +362,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
|
||||
egl_renderer->edpy =
|
||||
eglGetDisplay ((EGLNativeDisplayType)egl_renderer->wayland_display);
|
||||
|
||||
status = eglInitialize (egl_renderer->edpy,
|
||||
&egl_renderer->egl_version_major,
|
||||
&egl_renderer->egl_version_minor);
|
||||
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
|
||||
|
||||
@ -396,20 +369,11 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
case COGL_WINSYS_ID_EGL_ANDROID:
|
||||
case COGL_WINSYS_ID_EGL_NULL:
|
||||
egl_renderer->edpy = eglGetDisplay (EGL_DEFAULT_DISPLAY);
|
||||
|
||||
status = eglInitialize (egl_renderer->edpy,
|
||||
&egl_renderer->egl_version_major,
|
||||
&egl_renderer->egl_version_minor);
|
||||
break;
|
||||
}
|
||||
|
||||
if (status != EGL_TRUE)
|
||||
{
|
||||
g_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_INIT,
|
||||
"Failed to initialize EGL");
|
||||
goto error;
|
||||
}
|
||||
if (!_cogl_winsys_egl_renderer_connect_common (renderer, error))
|
||||
goto error;
|
||||
|
||||
#ifdef COGL_HAS_EGL_PLATFORM_GDL_SUPPORT
|
||||
if (renderer->winsys_vtable->id == COGL_WINSYS_ID_EGL_GDL)
|
||||
@ -441,8 +405,6 @@ _cogl_winsys_renderer_connect (CoglRenderer *renderer,
|
||||
}
|
||||
#endif
|
||||
|
||||
check_egl_extensions (renderer);
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
@ -624,50 +586,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 +862,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 +884,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 +981,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 +1088,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 +1111,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 +1179,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);
|
||||
g_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_ONSCREEN,
|
||||
"Failed to find a suitable EGL configuration");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* 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 +1388,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 +1401,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 +1438,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 +1481,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 +1493,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 +1556,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 +1609,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 +1654,13 @@ static void
|
||||
_cogl_winsys_onscreen_update_swap_throttled (CoglOnscreen *onscreen)
|
||||
{
|
||||
CoglContext *context = COGL_FRAMEBUFFER (onscreen)->context;
|
||||
CoglRenderer *renderer = context->display->renderer;
|
||||
CoglContextEGL *egl_context = context->winsys;
|
||||
CoglOnscreenEGL *egl_onscreen = onscreen->winsys;
|
||||
|
||||
if (renderer->winsys_vtable->id != COGL_WINSYS_ID_EGL_KMS)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
@ -1,426 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "cogl.h"
|
||||
|
||||
#include "cogl-util.h"
|
||||
#include "cogl-winsys-egl-private.h"
|
||||
#include "cogl-winsys-private.h"
|
||||
#include "cogl-feature-private.h"
|
||||
#include "cogl-context-private.h"
|
||||
#include "cogl-framebuffer.h"
|
||||
#include "cogl-onscreen-private.h"
|
||||
#include "cogl-swap-chain-private.h"
|
||||
#include "cogl-renderer-private.h"
|
||||
#include "cogl-private.h"
|
||||
|
||||
#include "cogl-winsys-kms.h"
|
||||
|
||||
static const char device_name[] = "/dev/dri/card0";
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_connect (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 ((EGLNativeDisplayType)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;
|
||||
}
|
||||
|
||||
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_display_setup (CoglDisplay *display, GError **error)
|
||||
{
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglDisplayKMS *kms_display = &egl_display->kms_display;
|
||||
CoglRendererEGL *egl_renderer = display->renderer->winsys;
|
||||
CoglRendererKMS *kms_renderer = &egl_renderer->kms_renderer;
|
||||
CoglEGLWinsysFeature surfaceless_feature = 0;
|
||||
const char *surfaceless_feature_name = "";
|
||||
drmModeRes *resources;
|
||||
drmModeConnector *connector;
|
||||
drmModeEncoder *encoder;
|
||||
int i;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_create_context (CoglRenderer *renderer,
|
||||
CoglDisplay *display,
|
||||
GError **error)
|
||||
{
|
||||
CoglRendererEGL *egl_renderer = renderer->winsys;
|
||||
CoglDisplayEGL *egl_display = display->winsys;
|
||||
CoglRendererKMS *kms_renderer = &egl_renderer->kms_renderer;
|
||||
CoglDisplayKMS *kms_display = &egl_display->kms_display;
|
||||
EGLint attribs[3];
|
||||
|
||||
if (renderer->driver == COGL_DRIVER_GLES2)
|
||||
{
|
||||
attribs[0] = EGL_CONTEXT_CLIENT_VERSION;
|
||||
attribs[1] = 2;
|
||||
attribs[2] = EGL_NONE;
|
||||
}
|
||||
else
|
||||
attribs[0] = EGL_NONE;
|
||||
|
||||
kms_display->egl_context = eglCreateContext (kms_renderer->dpy,
|
||||
NULL,
|
||||
EGL_NO_CONTEXT,
|
||||
attribs);
|
||||
|
||||
if (kms_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 (kms_renderer->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, kms_display->egl_context))
|
||||
{
|
||||
g_set_error (error, COGL_WINSYS_ERROR,
|
||||
COGL_WINSYS_ERROR_CREATE_CONTEXT,
|
||||
"Failed to make context current");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_onscreen_init (CoglContext *context,
|
||||
CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
CoglOnscreenKMS *kms_onscreen,
|
||||
GError **error)
|
||||
{
|
||||
int i;
|
||||
|
||||
kms_onscreen->cogl_context = context;
|
||||
|
||||
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_kms_swap_buffers (kms_renderer, kms_display, kms_onscreen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_winsys_kms_onscreen_deinit (CoglRendererKMS *kms_renderer,
|
||||
CoglOnscreenKMS *kms_onscreen)
|
||||
{
|
||||
int i;
|
||||
|
||||
CoglContext *context = kms_onscreen->cogl_context;
|
||||
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_destroy_context (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
GError **error)
|
||||
{
|
||||
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);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_winsys_kms_swap_buffers (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
CoglOnscreenKMS *kms_onscreen)
|
||||
{
|
||||
CoglContext *context = kms_onscreen->cogl_context;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
_cogl_winsys_kms_bind (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display)
|
||||
{
|
||||
eglMakeCurrent (kms_renderer->dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, kms_display->egl_context);
|
||||
}
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* 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>
|
||||
*/
|
||||
|
||||
#ifndef _COGL_WINSYS_KMS_PRIVATE_H_
|
||||
#define _COGL_WINSYS_KMS_PRIVATE_H_
|
||||
|
||||
#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;
|
||||
} CoglRendererKMS;
|
||||
|
||||
typedef struct _CoglDisplayKMS
|
||||
{
|
||||
EGLContext egl_context;
|
||||
drmModeConnector *connector;
|
||||
drmModeEncoder *encoder;
|
||||
drmModeModeInfo mode;
|
||||
drmModeCrtcPtr saved_crtc;
|
||||
int width, height;
|
||||
} CoglDisplayKMS;
|
||||
|
||||
typedef struct _CoglOnscreenKMS
|
||||
{
|
||||
CoglContext *cogl_context;
|
||||
|
||||
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;
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_connect (CoglRendererKMS *kms_renderer,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_onscreen_init (CoglContext *context,
|
||||
CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
CoglOnscreenKMS *kms_onscreen,
|
||||
GError **error);
|
||||
void
|
||||
_cogl_winsys_kms_onscreen_deinit (CoglRendererKMS *kms_renderer,
|
||||
CoglOnscreenKMS *kms_onscreen);
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_display_setup (CoglDisplay *display,
|
||||
GError **error);
|
||||
|
||||
void
|
||||
_cogl_winsys_kms_swap_buffers (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
CoglOnscreenKMS *kms_onscreen);
|
||||
|
||||
void
|
||||
_cogl_winsys_kms_bind (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display);
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_create_context (CoglRenderer *renderer,
|
||||
CoglDisplay *display,
|
||||
GError **error);
|
||||
|
||||
gboolean
|
||||
_cogl_winsys_kms_destroy_context (CoglRendererKMS *kms_renderer,
|
||||
CoglDisplayKMS *kms_display,
|
||||
GError **error);
|
||||
|
||||
#endif /* _COGL_WINSYS_KMS_PRIVATE_H_ */
|
Loading…
x
Reference in New Issue
Block a user