mirror of
https://github.com/brl/mutter.git
synced 2024-11-22 16:10:41 -05:00
Merge remote-tracking branch 'nobled/wayland-fixes2'
* nobled/wayland-fixes2: wayland: fix shm buffers wayland: set renderable type on dummy surface wayland: check for egl extensions explicitly wayland: fall back to shm buffers if drm fails wayland: add shm buffer code wayland: make buffer handling generic wayland: really fix buffer format selection wayland: fix pixel format wayland: clean up buffer creation code wayland: don't require the surfaceless extensions wayland: check for API-specific surfaceless extension wayland: fix GLES context creation wayland: use EGL_NO_SURFACE wayland: update to new api wayland: fix connecting to default socket fix ClutterContainer docs
This commit is contained in:
commit
2abf56fe92
@ -80,8 +80,8 @@ typedef struct _ClutterContainerIface ClutterContainerIface;
|
||||
* @destroy_child_meta: virtual function that gets called when a child is
|
||||
* removed; it shuld release all resources held by the record
|
||||
* @get_child_meta: return the record for a container child
|
||||
* @actor_added: class handler for #ClutterContainer::actor_added
|
||||
* @actor_removed: class handler for #ClutterContainer::actor_removed
|
||||
* @actor_added: class handler for #ClutterContainer::actor-added
|
||||
* @actor_removed: class handler for #ClutterContainer::actor-removed
|
||||
* @child_notify: class handler for #ClutterContainer::child-notify
|
||||
*
|
||||
* Base interface for container actors. The @add, @remove and @foreach
|
||||
|
@ -111,7 +111,7 @@ static void
|
||||
handle_configure (void *data, struct wl_shell *shell,
|
||||
uint32_t timestamp, uint32_t edges,
|
||||
struct wl_surface *surface,
|
||||
int32_t x, int32_t y, int32_t width, int32_t height)
|
||||
int32_t width, int32_t height)
|
||||
{
|
||||
ClutterStageWayland *stage_wayland;
|
||||
|
||||
@ -123,8 +123,6 @@ handle_configure (void *data, struct wl_shell *shell,
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_wayland->wrapper));
|
||||
}
|
||||
|
||||
stage_wayland->pending_allocation.x = x;
|
||||
stage_wayland->pending_allocation.y = y;
|
||||
stage_wayland->pending_allocation.width = width;
|
||||
stage_wayland->pending_allocation.height = height;
|
||||
stage_wayland->allocation = stage_wayland->pending_allocation;
|
||||
@ -177,20 +175,117 @@ display_handle_global (struct wl_display *display,
|
||||
wl_drm_add_listener (backend_wayland->wayland_drm,
|
||||
&drm_listener, backend_wayland);
|
||||
}
|
||||
else if (strcmp (interface, "shm") == 0)
|
||||
{
|
||||
backend_wayland->wayland_shm = wl_shm_create (display, id);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
try_get_display (ClutterBackendWayland *backend_wayland, GError **error)
|
||||
{
|
||||
EGLDisplay edpy = EGL_NO_DISPLAY;
|
||||
int drm_fd;
|
||||
|
||||
drm_fd = open (backend_wayland->device_name, O_RDWR);
|
||||
|
||||
backend_wayland->get_drm_display =
|
||||
(PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA");
|
||||
|
||||
if (backend_wayland->get_drm_display != NULL && drm_fd >= 0)
|
||||
edpy = backend_wayland->get_drm_display (drm_fd);
|
||||
|
||||
if (edpy == EGL_NO_DISPLAY)
|
||||
edpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
|
||||
|
||||
if (edpy == EGL_NO_DISPLAY)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Failed to open EGLDisplay");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
backend_wayland->edpy = edpy;
|
||||
backend_wayland->drm_fd = drm_fd;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
try_enable_drm (ClutterBackendWayland *backend_wayland, GError **error)
|
||||
{
|
||||
drm_magic_t magic;
|
||||
const gchar *exts, *glexts;
|
||||
|
||||
if (backend_wayland->drm_fd < 0)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Failed to open drm device");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
glexts = glGetString(GL_EXTENSIONS);
|
||||
exts = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS);
|
||||
|
||||
if (!_cogl_check_extension ("EGL_KHR_image_base", exts) ||
|
||||
!_cogl_check_extension ("EGL_MESA_drm_image", exts) ||
|
||||
!_cogl_check_extension ("GL_OES_EGL_image", glexts))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Missing EGL extensions");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
backend_wayland->create_drm_image =
|
||||
(PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA");
|
||||
backend_wayland->destroy_image =
|
||||
(PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
|
||||
backend_wayland->export_drm_image =
|
||||
(PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA");
|
||||
backend_wayland->image_target_texture_2d =
|
||||
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
|
||||
|
||||
if (backend_wayland->create_drm_image == NULL ||
|
||||
backend_wayland->destroy_image == NULL ||
|
||||
backend_wayland->export_drm_image == NULL ||
|
||||
backend_wayland->image_target_texture_2d == NULL)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Missing EGL extensions");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (drmGetMagic (backend_wayland->drm_fd, &magic))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Failed to get drm magic");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wl_drm_authenticate (backend_wayland->wayland_drm, magic);
|
||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE);
|
||||
while (!backend_wayland->authenticated)
|
||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
|
||||
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
static gboolean
|
||||
clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
||||
GError **error)
|
||||
{
|
||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||
EGLBoolean status;
|
||||
drm_magic_t magic;
|
||||
|
||||
g_atexit (clutter_backend_at_exit);
|
||||
|
||||
/* TODO: expose environment variable/commandline option for this... */
|
||||
backend_wayland->wayland_display = wl_display_connect ("\0wayland");
|
||||
backend_wayland->wayland_display = wl_display_connect (NULL);
|
||||
if (!backend_wayland->wayland_display)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
@ -211,53 +306,8 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
||||
/* Process connection events. */
|
||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
|
||||
|
||||
backend_wayland->drm_fd = open (backend_wayland->device_name, O_RDWR);
|
||||
if (backend_wayland->drm_fd < 0)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Failed to open drm device");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (drmGetMagic (backend_wayland->drm_fd, &magic))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Failed to get drm magic");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
wl_drm_authenticate (backend_wayland->wayland_drm, magic);
|
||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_WRITABLE);
|
||||
while (!backend_wayland->authenticated)
|
||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
|
||||
|
||||
backend_wayland->get_drm_display =
|
||||
(PFNEGLGETDRMDISPLAYMESA) eglGetProcAddress ("eglGetDRMDisplayMESA");
|
||||
backend_wayland->create_drm_image =
|
||||
(PFNEGLCREATEDRMIMAGEMESA) eglGetProcAddress ("eglCreateDRMImageMESA");
|
||||
backend_wayland->destroy_image =
|
||||
(PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress ("eglDestroyImageKHR");
|
||||
backend_wayland->export_drm_image =
|
||||
(PFNEGLEXPORTDRMIMAGEMESA) eglGetProcAddress ("eglExportDRMImageMESA");
|
||||
backend_wayland->image_target_texture_2d =
|
||||
(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) eglGetProcAddress ("glEGLImageTargetTexture2DOES");
|
||||
|
||||
if (backend_wayland->get_drm_display == NULL ||
|
||||
backend_wayland->create_drm_image == NULL ||
|
||||
backend_wayland->destroy_image == NULL ||
|
||||
backend_wayland->export_drm_image == NULL ||
|
||||
backend_wayland->image_target_texture_2d == NULL)
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Missing EGL extensions");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
backend_wayland->edpy =
|
||||
backend_wayland->get_drm_display (backend_wayland->drm_fd);
|
||||
if (!try_get_display(backend_wayland, error))
|
||||
return FALSE;
|
||||
|
||||
status = eglInitialize (backend_wayland->edpy,
|
||||
&backend_wayland->egl_version_major,
|
||||
@ -274,6 +324,52 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
||||
backend_wayland->egl_version_major,
|
||||
backend_wayland->egl_version_minor);
|
||||
|
||||
backend_wayland->drm_enabled = try_enable_drm(backend_wayland, error);
|
||||
|
||||
if (!backend_wayland->drm_enabled) {
|
||||
if (backend_wayland->wayland_shm == NULL)
|
||||
return FALSE;
|
||||
|
||||
g_debug("Could not enable DRM buffers, falling back to SHM buffers");
|
||||
g_clear_error(error);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#if defined(HAVE_COGL_GL)
|
||||
#define _COGL_RENDERABLE_BIT EGL_OPENGL_BIT
|
||||
#elif defined(HAVE_COGL_GLES2)
|
||||
#define _COGL_GLES_VERSION 2
|
||||
#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES2_BIT
|
||||
#elif defined(HAVE_COGL_GLES)
|
||||
#define _COGL_GLES_VERSION 1
|
||||
#define _COGL_RENDERABLE_BIT EGL_OPENGL_ES_BIT
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
make_dummy_surface (ClutterBackendWayland *backend_wayland)
|
||||
{
|
||||
static const EGLint attrs[] = {
|
||||
EGL_WIDTH, 1,
|
||||
EGL_HEIGHT, 1,
|
||||
EGL_RENDERABLE_TYPE, _COGL_RENDERABLE_BIT,
|
||||
EGL_NONE };
|
||||
EGLint num_configs;
|
||||
|
||||
eglGetConfigs(backend_wayland->edpy,
|
||||
&backend_wayland->egl_config, 1, &num_configs);
|
||||
if (num_configs < 1)
|
||||
return FALSE;
|
||||
|
||||
backend_wayland->egl_surface =
|
||||
eglCreatePbufferSurface(backend_wayland->edpy,
|
||||
backend_wayland->egl_config,
|
||||
attrs);
|
||||
|
||||
if (backend_wayland->egl_surface == EGL_NO_SURFACE)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -286,20 +382,18 @@ try_create_context (ClutterBackend *backend,
|
||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||
const char *error_message;
|
||||
|
||||
eglBindAPI (EGL_OPENGL_API);
|
||||
|
||||
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
||||
{
|
||||
#if defined (HAVE_COGL_GLES2)
|
||||
static const EGLint attribs[] =
|
||||
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||
#else
|
||||
#if defined(HAVE_COGL_GL)
|
||||
static const EGLint *attribs = NULL;
|
||||
#else
|
||||
static const EGLint attribs[] =
|
||||
{ EGL_CONTEXT_CLIENT_VERSION, _COGL_GLES_VERSION, EGL_NONE };
|
||||
#endif
|
||||
|
||||
backend_wayland->egl_context =
|
||||
eglCreateContext (backend_wayland->edpy,
|
||||
NULL,
|
||||
backend_wayland->egl_config,
|
||||
EGL_NO_CONTEXT,
|
||||
attribs);
|
||||
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
||||
@ -312,13 +406,13 @@ try_create_context (ClutterBackend *backend,
|
||||
}
|
||||
|
||||
if (!eglMakeCurrent (backend_wayland->edpy,
|
||||
NULL,
|
||||
NULL,
|
||||
backend_wayland->egl_surface,
|
||||
backend_wayland->egl_surface,
|
||||
backend_wayland->egl_context))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Unable to MakeCurrent with NULL drawables");
|
||||
"Unable to MakeCurrent");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
@ -334,6 +428,14 @@ fail:
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(HAVE_COGL_GL)
|
||||
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_opengl"
|
||||
#elif defined(HAVE_COGL_GLES)
|
||||
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles1"
|
||||
#elif defined(HAVE_COGL_GLES2)
|
||||
#define _COGL_SURFACELESS_EXTENSION "EGL_KHR_surfaceless_gles2"
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
clutter_backend_wayland_create_context (ClutterBackend *backend,
|
||||
GError **error)
|
||||
@ -348,15 +450,29 @@ clutter_backend_wayland_create_context (ClutterBackend *backend,
|
||||
if (backend_wayland->egl_context != EGL_NO_CONTEXT)
|
||||
return TRUE;
|
||||
|
||||
#if defined(HAVE_COGL_GL)
|
||||
eglBindAPI (EGL_OPENGL_API);
|
||||
#else
|
||||
eglBindAPI (EGL_OPENGL_ES_API);
|
||||
#endif
|
||||
egl_extensions = eglQueryString (backend_wayland->edpy, EGL_EXTENSIONS);
|
||||
|
||||
if (!_cogl_check_extension ("EGL_KHR_surfaceless_opengl", egl_extensions))
|
||||
if (!_cogl_check_extension (_COGL_SURFACELESS_EXTENSION, egl_extensions))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Wayland clients require the "
|
||||
"EGL_KHR_surfaceless_opengl extension");
|
||||
return FALSE;
|
||||
g_debug("Could not find the " _COGL_SURFACELESS_EXTENSION
|
||||
" extension; falling back to binding a dummy surface");
|
||||
if (!make_dummy_surface(backend_wayland))
|
||||
{
|
||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||
CLUTTER_INIT_ERROR_BACKEND,
|
||||
"Could not create dummy surface");
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
backend_wayland->egl_config = NULL;
|
||||
backend_wayland->egl_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
|
||||
retry_cookie = 0;
|
||||
@ -541,6 +657,7 @@ _clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass)
|
||||
static void
|
||||
_clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland)
|
||||
{
|
||||
backend_wayland->edpy = EGL_NO_DISPLAY;
|
||||
backend_wayland->egl_context = EGL_NO_CONTEXT;
|
||||
|
||||
backend_wayland->drm_fd = -1;
|
||||
|
@ -57,6 +57,7 @@ struct _ClutterBackendWayland
|
||||
EGLDisplay edpy;
|
||||
EGLContext egl_context;
|
||||
EGLConfig egl_config;
|
||||
EGLSurface egl_surface;
|
||||
|
||||
gint egl_version_major;
|
||||
gint egl_version_minor;
|
||||
@ -66,11 +67,13 @@ struct _ClutterBackendWayland
|
||||
struct wl_compositor *wayland_compositor;
|
||||
struct wl_shell *wayland_shell;
|
||||
struct wl_drm *wayland_drm;
|
||||
struct wl_shm *wayland_shm;
|
||||
char *device_name;
|
||||
int authenticated;
|
||||
struct wl_output *wayland_output;
|
||||
ClutterGeometry screen_allocation;
|
||||
int drm_fd;
|
||||
gboolean drm_enabled;
|
||||
|
||||
PFNEGLGETDRMDISPLAYMESA get_drm_display;
|
||||
PFNEGLCREATEDRMIMAGEMESA create_drm_image;
|
||||
|
@ -28,7 +28,12 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <glib.h>
|
||||
#include <glib/gstdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-util.h>
|
||||
#include <wayland-client.h>
|
||||
#include <xf86drm.h>
|
||||
@ -59,14 +64,82 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||
clutter_stage_window_iface_init));
|
||||
|
||||
static ClutterStageWaylandWaylandBuffer *
|
||||
wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
||||
ClutterGeometry *geom)
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_ARGB_8888_PRE
|
||||
#define VISUAL_ARGB COGL_PIXEL_FORMAT_ARGB_8888
|
||||
#define VISUAL_RGB COGL_PIXEL_FORMAT_RGB_888
|
||||
#elif G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define VISUAL_ARGB_PRE COGL_PIXEL_FORMAT_BGRA_8888_PRE
|
||||
#define VISUAL_ARGB COGL_PIXEL_FORMAT_BGRA_8888
|
||||
#define VISUAL_RGB COGL_PIXEL_FORMAT_BGR_888
|
||||
#endif
|
||||
|
||||
static struct wl_visual *
|
||||
get_visual (struct wl_display *display, CoglPixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case VISUAL_ARGB_PRE:
|
||||
return wl_display_get_premultiplied_argb_visual (display);
|
||||
case VISUAL_ARGB:
|
||||
return wl_display_get_argb_visual (display);
|
||||
case VISUAL_RGB:
|
||||
return wl_display_get_rgb_visual (display);
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
static ClutterStageWaylandWaylandBuffer *
|
||||
wayland_create_shm_buffer (ClutterBackendWayland *backend_wayland,
|
||||
ClutterGeometry *geom)
|
||||
{
|
||||
ClutterStageWaylandWaylandBufferSHM *buffer;
|
||||
struct wl_visual *visual;
|
||||
CoglHandle tex;
|
||||
CoglTextureFlags flags = COGL_TEXTURE_NONE; /* XXX: tweak flags? */
|
||||
CoglPixelFormat format = VISUAL_ARGB_PRE;
|
||||
int fd;
|
||||
gchar tmp[] = "/tmp/clutter-wayland-shm-XXXXXX";
|
||||
|
||||
buffer = g_slice_new (ClutterStageWaylandWaylandBufferSHM);
|
||||
|
||||
buffer->buffer.type = BUFFER_TYPE_SHM;
|
||||
|
||||
tex = cogl_texture_new_with_size ((unsigned int)geom->width,
|
||||
(unsigned int)geom->height,
|
||||
flags, format);
|
||||
buffer->format = format;
|
||||
buffer->stride = cogl_texture_get_rowstride(tex);
|
||||
buffer->size = cogl_texture_get_data(tex, format, buffer->stride, NULL);
|
||||
buffer->buffer.tex = tex;
|
||||
|
||||
fd = g_mkstemp_full(tmp, O_RDWR, 0600);
|
||||
ftruncate(fd, buffer->size);
|
||||
buffer->data = mmap(NULL, buffer->size, PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, fd, 0);
|
||||
|
||||
g_unlink(tmp);
|
||||
|
||||
visual = get_visual (backend_wayland->wayland_display, format);
|
||||
|
||||
buffer->buffer.wayland_buffer =
|
||||
wl_shm_create_buffer (backend_wayland->wayland_shm,
|
||||
fd,
|
||||
geom->width,
|
||||
geom->height,
|
||||
buffer->stride, visual);
|
||||
close(fd);
|
||||
return &buffer->buffer;
|
||||
}
|
||||
|
||||
static ClutterStageWaylandWaylandBuffer *
|
||||
wayland_create_drm_buffer (ClutterBackendWayland *backend_wayland,
|
||||
ClutterGeometry *geom)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||
EGLDisplay edpy = clutter_wayland_get_egl_display ();
|
||||
ClutterStageWaylandWaylandBuffer *buffer;
|
||||
struct wl_visual *visual;
|
||||
EGLint name, stride;
|
||||
ClutterStageWaylandWaylandBufferDRM *buffer;
|
||||
EGLint image_attribs[] = {
|
||||
EGL_WIDTH, 0,
|
||||
EGL_HEIGHT, 0,
|
||||
@ -74,12 +147,10 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
||||
EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA,
|
||||
EGL_NONE
|
||||
};
|
||||
struct wl_visual *visual;
|
||||
EGLint name;
|
||||
EGLint stride;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
buffer = g_slice_new (ClutterStageWaylandWaylandBuffer);
|
||||
buffer = g_slice_new (ClutterStageWaylandWaylandBufferDRM);
|
||||
|
||||
buffer->buffer.type = BUFFER_TYPE_DRM;
|
||||
|
||||
image_attribs[1] = geom->width;
|
||||
image_attribs[3] = geom->height;
|
||||
@ -88,26 +159,45 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
||||
glBindTexture (GL_TEXTURE_2D, buffer->texture);
|
||||
backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image);
|
||||
|
||||
buffer->tex = cogl_texture_new_from_foreign (buffer->texture,
|
||||
buffer->buffer.tex = cogl_texture_new_from_foreign (buffer->texture,
|
||||
GL_TEXTURE_2D,
|
||||
geom->width,
|
||||
geom->height,
|
||||
0,
|
||||
0,
|
||||
COGL_PIXEL_FORMAT_ARGB_8888);
|
||||
buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex);
|
||||
VISUAL_ARGB_PRE);
|
||||
|
||||
backend_wayland->export_drm_image (edpy, buffer->drm_image,
|
||||
&name, NULL, &stride);
|
||||
visual =
|
||||
wl_display_get_premultiplied_argb_visual (backend_wayland->wayland_display);
|
||||
buffer->wayland_buffer =
|
||||
visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE);
|
||||
buffer->buffer.wayland_buffer =
|
||||
wl_drm_create_buffer (backend_wayland->wayland_drm,
|
||||
name,
|
||||
stage_wayland->allocation.width,
|
||||
stage_wayland->allocation.height,
|
||||
geom->width,
|
||||
geom->height,
|
||||
stride, visual);
|
||||
|
||||
return &buffer->buffer;
|
||||
}
|
||||
|
||||
static ClutterStageWaylandWaylandBuffer *
|
||||
wayland_create_buffer (ClutterGeometry *geom)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||
ClutterStageWaylandWaylandBuffer *buffer;
|
||||
cairo_rectangle_int_t rect;
|
||||
|
||||
if (backend_wayland->drm_enabled &&
|
||||
backend_wayland->wayland_drm != NULL)
|
||||
buffer = wayland_create_drm_buffer (backend_wayland, geom);
|
||||
else if (backend_wayland->wayland_shm != NULL)
|
||||
buffer = wayland_create_shm_buffer (backend_wayland, geom);
|
||||
else
|
||||
return NULL;
|
||||
|
||||
buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex);
|
||||
|
||||
rect.x = geom->x;
|
||||
rect.y = geom->y;
|
||||
rect.width = geom->width;
|
||||
@ -118,18 +208,42 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer)
|
||||
wayland_free_shm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer)
|
||||
{
|
||||
ClutterStageWaylandWaylandBufferSHM *buffer;
|
||||
|
||||
buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer;
|
||||
|
||||
munmap(buffer->data, buffer->size);
|
||||
g_slice_free (ClutterStageWaylandWaylandBufferSHM, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_free_drm_buffer (ClutterStageWaylandWaylandBuffer *generic_buffer)
|
||||
{
|
||||
ClutterBackend *backend = clutter_get_default_backend ();
|
||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||
EGLDisplay edpy = clutter_wayland_get_egl_display ();
|
||||
ClutterStageWaylandWaylandBufferDRM *buffer;
|
||||
|
||||
buffer = (ClutterStageWaylandWaylandBufferDRM *)generic_buffer;
|
||||
|
||||
glDeleteTextures (1, &buffer->texture);
|
||||
backend_wayland->destroy_image (edpy, buffer->drm_image);
|
||||
g_slice_free (ClutterStageWaylandWaylandBufferDRM, buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_free_buffer (ClutterStageWaylandWaylandBuffer *buffer)
|
||||
{
|
||||
cogl_handle_unref (buffer->tex);
|
||||
wl_buffer_destroy (buffer->wayland_buffer);
|
||||
cogl_handle_unref (buffer->offscreen);
|
||||
glDeleteTextures (1, &buffer->texture);
|
||||
backend_wayland->destroy_image (edpy, buffer->drm_image);
|
||||
g_slice_free (ClutterStageWaylandWaylandBuffer, buffer);
|
||||
|
||||
if (buffer->type == BUFFER_TYPE_DRM)
|
||||
wayland_free_drm_buffer(buffer);
|
||||
else if (buffer->type == BUFFER_TYPE_SHM)
|
||||
wayland_free_shm_buffer(buffer);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -171,7 +285,7 @@ clutter_stage_wayland_realize (ClutterStageWindow *stage_window)
|
||||
wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland);
|
||||
|
||||
stage_wayland->pick_buffer =
|
||||
wayland_create_buffer (stage_wayland, &stage_wayland->allocation);
|
||||
wayland_create_buffer (&stage_wayland->allocation);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@ -349,6 +463,26 @@ wayland_frame_callback (void *data, uint32_t _time)
|
||||
stage_wayland->pending_swaps--;
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_damage_buffer(ClutterStageWaylandWaylandBuffer *generic_buffer)
|
||||
{
|
||||
ClutterStageWaylandWaylandBufferSHM *buffer;
|
||||
int size;
|
||||
|
||||
if (generic_buffer->type != BUFFER_TYPE_SHM)
|
||||
return;
|
||||
|
||||
buffer = (ClutterStageWaylandWaylandBufferSHM *)generic_buffer;
|
||||
|
||||
size = cogl_texture_get_data(buffer->buffer.tex, buffer->format,
|
||||
buffer->stride, NULL);
|
||||
g_assert(size == (int)buffer->size);
|
||||
|
||||
(void) cogl_texture_get_data(buffer->buffer.tex, buffer->format,
|
||||
buffer->stride, buffer->data);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
wayland_swap_buffers (ClutterStageWayland *stage_wayland)
|
||||
{
|
||||
@ -360,13 +494,13 @@ wayland_swap_buffers (ClutterStageWayland *stage_wayland)
|
||||
stage_wayland->front_buffer = stage_wayland->back_buffer;
|
||||
stage_wayland->back_buffer = buffer;
|
||||
|
||||
wayland_damage_buffer(stage_wayland->front_buffer);
|
||||
|
||||
wl_surface_attach (stage_wayland->wayland_surface,
|
||||
stage_wayland->front_buffer->wayland_buffer);
|
||||
wl_surface_map (stage_wayland->wayland_surface,
|
||||
stage_wayland->allocation.x,
|
||||
stage_wayland->allocation.y,
|
||||
stage_wayland->allocation.width,
|
||||
stage_wayland->allocation.height);
|
||||
stage_wayland->front_buffer->wayland_buffer,
|
||||
/* 0,0 here is "relative to the old buffer," not absolute */
|
||||
0, 0);
|
||||
wl_surface_map_toplevel (stage_wayland->wayland_surface);
|
||||
|
||||
stage_wayland->pending_swaps++;
|
||||
wl_display_frame_callback (backend_wayland->wayland_display,
|
||||
@ -506,7 +640,7 @@ _clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland,
|
||||
|
||||
if (!stage_wayland->back_buffer)
|
||||
stage_wayland->back_buffer =
|
||||
wayland_create_buffer (stage_wayland, &stage_wayland->allocation);
|
||||
wayland_create_buffer (&stage_wayland->allocation);
|
||||
|
||||
cogl_set_framebuffer (stage_wayland->back_buffer->offscreen);
|
||||
_clutter_stage_maybe_setup_viewport (stage_wayland->wrapper);
|
||||
|
@ -51,16 +51,34 @@
|
||||
typedef struct _ClutterStageWayland ClutterStageWayland;
|
||||
typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass;
|
||||
|
||||
#define BUFFER_TYPE_DRM 1
|
||||
#define BUFFER_TYPE_SHM 2
|
||||
|
||||
typedef struct _ClutterStageWaylandWaylandBuffer
|
||||
{
|
||||
EGLImageKHR drm_image;
|
||||
GLuint texture;
|
||||
CoglHandle offscreen;
|
||||
struct wl_buffer *wayland_buffer;
|
||||
cairo_region_t *dirty_region;
|
||||
CoglHandle tex;
|
||||
guint type;
|
||||
} ClutterStageWaylandWaylandBuffer;
|
||||
|
||||
typedef struct _ClutterStageWaylandWaylandBufferDRM
|
||||
{
|
||||
ClutterStageWaylandWaylandBuffer buffer;
|
||||
EGLImageKHR drm_image;
|
||||
GLuint texture;
|
||||
} ClutterStageWaylandWaylandBufferDRM;
|
||||
|
||||
typedef struct _ClutterStageWaylandWaylandBufferSHM
|
||||
{
|
||||
ClutterStageWaylandWaylandBuffer buffer;
|
||||
CoglPixelFormat format;
|
||||
guint8 *data;
|
||||
size_t size;
|
||||
unsigned int stride;
|
||||
} ClutterStageWaylandWaylandBufferSHM;
|
||||
|
||||
struct _ClutterStageWayland
|
||||
{
|
||||
GObject parent_instance;
|
||||
|
Loading…
Reference in New Issue
Block a user