mirror of
https://github.com/brl/mutter.git
synced 2024-11-30 03:50:47 -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
|
* @destroy_child_meta: virtual function that gets called when a child is
|
||||||
* removed; it shuld release all resources held by the record
|
* removed; it shuld release all resources held by the record
|
||||||
* @get_child_meta: return the record for a container child
|
* @get_child_meta: return the record for a container child
|
||||||
* @actor_added: class handler for #ClutterContainer::actor_added
|
* @actor_added: class handler for #ClutterContainer::actor-added
|
||||||
* @actor_removed: class handler for #ClutterContainer::actor_removed
|
* @actor_removed: class handler for #ClutterContainer::actor-removed
|
||||||
* @child_notify: class handler for #ClutterContainer::child-notify
|
* @child_notify: class handler for #ClutterContainer::child-notify
|
||||||
*
|
*
|
||||||
* Base interface for container actors. The @add, @remove and @foreach
|
* Base interface for container actors. The @add, @remove and @foreach
|
||||||
|
@ -111,7 +111,7 @@ static void
|
|||||||
handle_configure (void *data, struct wl_shell *shell,
|
handle_configure (void *data, struct wl_shell *shell,
|
||||||
uint32_t timestamp, uint32_t edges,
|
uint32_t timestamp, uint32_t edges,
|
||||||
struct wl_surface *surface,
|
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;
|
ClutterStageWayland *stage_wayland;
|
||||||
|
|
||||||
@ -123,8 +123,6 @@ handle_configure (void *data, struct wl_shell *shell,
|
|||||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (stage_wayland->wrapper));
|
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.width = width;
|
||||||
stage_wayland->pending_allocation.height = height;
|
stage_wayland->pending_allocation.height = height;
|
||||||
stage_wayland->allocation = stage_wayland->pending_allocation;
|
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,
|
wl_drm_add_listener (backend_wayland->wayland_drm,
|
||||||
&drm_listener, backend_wayland);
|
&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
|
static gboolean
|
||||||
clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
{
|
{
|
||||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||||
EGLBoolean status;
|
EGLBoolean status;
|
||||||
drm_magic_t magic;
|
|
||||||
|
|
||||||
g_atexit (clutter_backend_at_exit);
|
g_atexit (clutter_backend_at_exit);
|
||||||
|
|
||||||
/* TODO: expose environment variable/commandline option for this... */
|
/* 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)
|
if (!backend_wayland->wayland_display)
|
||||||
{
|
{
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
@ -211,53 +306,8 @@ clutter_backend_wayland_post_parse (ClutterBackend *backend,
|
|||||||
/* Process connection events. */
|
/* Process connection events. */
|
||||||
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
|
wl_display_iterate (backend_wayland->wayland_display, WL_DISPLAY_READABLE);
|
||||||
|
|
||||||
backend_wayland->drm_fd = open (backend_wayland->device_name, O_RDWR);
|
if (!try_get_display(backend_wayland, error))
|
||||||
if (backend_wayland->drm_fd < 0)
|
|
||||||
{
|
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
|
||||||
"Failed to open drm device");
|
|
||||||
return FALSE;
|
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);
|
|
||||||
|
|
||||||
status = eglInitialize (backend_wayland->edpy,
|
status = eglInitialize (backend_wayland->edpy,
|
||||||
&backend_wayland->egl_version_major,
|
&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_major,
|
||||||
backend_wayland->egl_version_minor);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -286,20 +382,18 @@ try_create_context (ClutterBackend *backend,
|
|||||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||||
const char *error_message;
|
const char *error_message;
|
||||||
|
|
||||||
eglBindAPI (EGL_OPENGL_API);
|
|
||||||
|
|
||||||
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
||||||
{
|
{
|
||||||
#if defined (HAVE_COGL_GLES2)
|
#if defined(HAVE_COGL_GL)
|
||||||
static const EGLint attribs[] =
|
|
||||||
{ EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
|
||||||
#else
|
|
||||||
static const EGLint *attribs = NULL;
|
static const EGLint *attribs = NULL;
|
||||||
|
#else
|
||||||
|
static const EGLint attribs[] =
|
||||||
|
{ EGL_CONTEXT_CLIENT_VERSION, _COGL_GLES_VERSION, EGL_NONE };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
backend_wayland->egl_context =
|
backend_wayland->egl_context =
|
||||||
eglCreateContext (backend_wayland->edpy,
|
eglCreateContext (backend_wayland->edpy,
|
||||||
NULL,
|
backend_wayland->egl_config,
|
||||||
EGL_NO_CONTEXT,
|
EGL_NO_CONTEXT,
|
||||||
attribs);
|
attribs);
|
||||||
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
if (backend_wayland->egl_context == EGL_NO_CONTEXT)
|
||||||
@ -312,13 +406,13 @@ try_create_context (ClutterBackend *backend,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!eglMakeCurrent (backend_wayland->edpy,
|
if (!eglMakeCurrent (backend_wayland->edpy,
|
||||||
NULL,
|
backend_wayland->egl_surface,
|
||||||
NULL,
|
backend_wayland->egl_surface,
|
||||||
backend_wayland->egl_context))
|
backend_wayland->egl_context))
|
||||||
{
|
{
|
||||||
g_set_error (error, CLUTTER_INIT_ERROR,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
"Unable to MakeCurrent with NULL drawables");
|
"Unable to MakeCurrent");
|
||||||
return FALSE;
|
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
|
static gboolean
|
||||||
clutter_backend_wayland_create_context (ClutterBackend *backend,
|
clutter_backend_wayland_create_context (ClutterBackend *backend,
|
||||||
GError **error)
|
GError **error)
|
||||||
@ -348,16 +450,30 @@ clutter_backend_wayland_create_context (ClutterBackend *backend,
|
|||||||
if (backend_wayland->egl_context != EGL_NO_CONTEXT)
|
if (backend_wayland->egl_context != EGL_NO_CONTEXT)
|
||||||
return TRUE;
|
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);
|
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_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,
|
g_set_error (error, CLUTTER_INIT_ERROR,
|
||||||
CLUTTER_INIT_ERROR_BACKEND,
|
CLUTTER_INIT_ERROR_BACKEND,
|
||||||
"Wayland clients require the "
|
"Could not create dummy surface");
|
||||||
"EGL_KHR_surfaceless_opengl extension");
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
backend_wayland->egl_config = NULL;
|
||||||
|
backend_wayland->egl_surface = EGL_NO_SURFACE;
|
||||||
|
}
|
||||||
|
|
||||||
retry_cookie = 0;
|
retry_cookie = 0;
|
||||||
while (!(status = try_create_context (backend,
|
while (!(status = try_create_context (backend,
|
||||||
@ -541,6 +657,7 @@ _clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass)
|
|||||||
static void
|
static void
|
||||||
_clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland)
|
_clutter_backend_wayland_init (ClutterBackendWayland *backend_wayland)
|
||||||
{
|
{
|
||||||
|
backend_wayland->edpy = EGL_NO_DISPLAY;
|
||||||
backend_wayland->egl_context = EGL_NO_CONTEXT;
|
backend_wayland->egl_context = EGL_NO_CONTEXT;
|
||||||
|
|
||||||
backend_wayland->drm_fd = -1;
|
backend_wayland->drm_fd = -1;
|
||||||
|
@ -57,6 +57,7 @@ struct _ClutterBackendWayland
|
|||||||
EGLDisplay edpy;
|
EGLDisplay edpy;
|
||||||
EGLContext egl_context;
|
EGLContext egl_context;
|
||||||
EGLConfig egl_config;
|
EGLConfig egl_config;
|
||||||
|
EGLSurface egl_surface;
|
||||||
|
|
||||||
gint egl_version_major;
|
gint egl_version_major;
|
||||||
gint egl_version_minor;
|
gint egl_version_minor;
|
||||||
@ -66,11 +67,13 @@ struct _ClutterBackendWayland
|
|||||||
struct wl_compositor *wayland_compositor;
|
struct wl_compositor *wayland_compositor;
|
||||||
struct wl_shell *wayland_shell;
|
struct wl_shell *wayland_shell;
|
||||||
struct wl_drm *wayland_drm;
|
struct wl_drm *wayland_drm;
|
||||||
|
struct wl_shm *wayland_shm;
|
||||||
char *device_name;
|
char *device_name;
|
||||||
int authenticated;
|
int authenticated;
|
||||||
struct wl_output *wayland_output;
|
struct wl_output *wayland_output;
|
||||||
ClutterGeometry screen_allocation;
|
ClutterGeometry screen_allocation;
|
||||||
int drm_fd;
|
int drm_fd;
|
||||||
|
gboolean drm_enabled;
|
||||||
|
|
||||||
PFNEGLGETDRMDISPLAYMESA get_drm_display;
|
PFNEGLGETDRMDISPLAYMESA get_drm_display;
|
||||||
PFNEGLCREATEDRMIMAGEMESA create_drm_image;
|
PFNEGLCREATEDRMIMAGEMESA create_drm_image;
|
||||||
|
@ -28,7 +28,12 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <glib.h>
|
||||||
|
#include <glib/gstdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <wayland-util.h>
|
#include <wayland-util.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
@ -59,14 +64,82 @@ G_DEFINE_TYPE_WITH_CODE (ClutterStageWayland,
|
|||||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_STAGE_WINDOW,
|
||||||
clutter_stage_window_iface_init));
|
clutter_stage_window_iface_init));
|
||||||
|
|
||||||
|
#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 *
|
static ClutterStageWaylandWaylandBuffer *
|
||||||
wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
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)
|
ClutterGeometry *geom)
|
||||||
{
|
{
|
||||||
ClutterBackend *backend = clutter_get_default_backend ();
|
|
||||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
|
||||||
EGLDisplay edpy = clutter_wayland_get_egl_display ();
|
EGLDisplay edpy = clutter_wayland_get_egl_display ();
|
||||||
ClutterStageWaylandWaylandBuffer *buffer;
|
struct wl_visual *visual;
|
||||||
|
EGLint name, stride;
|
||||||
|
ClutterStageWaylandWaylandBufferDRM *buffer;
|
||||||
EGLint image_attribs[] = {
|
EGLint image_attribs[] = {
|
||||||
EGL_WIDTH, 0,
|
EGL_WIDTH, 0,
|
||||||
EGL_HEIGHT, 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_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SCANOUT_MESA,
|
||||||
EGL_NONE
|
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[1] = geom->width;
|
||||||
image_attribs[3] = geom->height;
|
image_attribs[3] = geom->height;
|
||||||
@ -88,26 +159,45 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
|||||||
glBindTexture (GL_TEXTURE_2D, buffer->texture);
|
glBindTexture (GL_TEXTURE_2D, buffer->texture);
|
||||||
backend_wayland->image_target_texture_2d (GL_TEXTURE_2D, buffer->drm_image);
|
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,
|
GL_TEXTURE_2D,
|
||||||
geom->width,
|
geom->width,
|
||||||
geom->height,
|
geom->height,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
COGL_PIXEL_FORMAT_ARGB_8888);
|
VISUAL_ARGB_PRE);
|
||||||
buffer->offscreen = cogl_offscreen_new_to_texture (buffer->tex);
|
|
||||||
|
|
||||||
backend_wayland->export_drm_image (edpy, buffer->drm_image,
|
backend_wayland->export_drm_image (edpy, buffer->drm_image,
|
||||||
&name, NULL, &stride);
|
&name, NULL, &stride);
|
||||||
visual =
|
visual = get_visual (backend_wayland->wayland_display, VISUAL_ARGB_PRE);
|
||||||
wl_display_get_premultiplied_argb_visual (backend_wayland->wayland_display);
|
buffer->buffer.wayland_buffer =
|
||||||
buffer->wayland_buffer =
|
|
||||||
wl_drm_create_buffer (backend_wayland->wayland_drm,
|
wl_drm_create_buffer (backend_wayland->wayland_drm,
|
||||||
name,
|
name,
|
||||||
stage_wayland->allocation.width,
|
geom->width,
|
||||||
stage_wayland->allocation.height,
|
geom->height,
|
||||||
stride, visual);
|
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.x = geom->x;
|
||||||
rect.y = geom->y;
|
rect.y = geom->y;
|
||||||
rect.width = geom->width;
|
rect.width = geom->width;
|
||||||
@ -118,18 +208,42 @@ wayland_create_buffer (ClutterStageWayland *stage_wayland,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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 ();
|
ClutterBackend *backend = clutter_get_default_backend ();
|
||||||
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
ClutterBackendWayland *backend_wayland = CLUTTER_BACKEND_WAYLAND (backend);
|
||||||
EGLDisplay edpy = clutter_wayland_get_egl_display ();
|
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);
|
cogl_handle_unref (buffer->tex);
|
||||||
wl_buffer_destroy (buffer->wayland_buffer);
|
wl_buffer_destroy (buffer->wayland_buffer);
|
||||||
cogl_handle_unref (buffer->offscreen);
|
cogl_handle_unref (buffer->offscreen);
|
||||||
glDeleteTextures (1, &buffer->texture);
|
|
||||||
backend_wayland->destroy_image (edpy, buffer->drm_image);
|
if (buffer->type == BUFFER_TYPE_DRM)
|
||||||
g_slice_free (ClutterStageWaylandWaylandBuffer, buffer);
|
wayland_free_drm_buffer(buffer);
|
||||||
|
else if (buffer->type == BUFFER_TYPE_SHM)
|
||||||
|
wayland_free_shm_buffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -171,7 +285,7 @@ clutter_stage_wayland_realize (ClutterStageWindow *stage_window)
|
|||||||
wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland);
|
wl_surface_set_user_data (stage_wayland->wayland_surface, stage_wayland);
|
||||||
|
|
||||||
stage_wayland->pick_buffer =
|
stage_wayland->pick_buffer =
|
||||||
wayland_create_buffer (stage_wayland, &stage_wayland->allocation);
|
wayland_create_buffer (&stage_wayland->allocation);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -349,6 +463,26 @@ wayland_frame_callback (void *data, uint32_t _time)
|
|||||||
stage_wayland->pending_swaps--;
|
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
|
static void
|
||||||
wayland_swap_buffers (ClutterStageWayland *stage_wayland)
|
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->front_buffer = stage_wayland->back_buffer;
|
||||||
stage_wayland->back_buffer = buffer;
|
stage_wayland->back_buffer = buffer;
|
||||||
|
|
||||||
|
wayland_damage_buffer(stage_wayland->front_buffer);
|
||||||
|
|
||||||
wl_surface_attach (stage_wayland->wayland_surface,
|
wl_surface_attach (stage_wayland->wayland_surface,
|
||||||
stage_wayland->front_buffer->wayland_buffer);
|
stage_wayland->front_buffer->wayland_buffer,
|
||||||
wl_surface_map (stage_wayland->wayland_surface,
|
/* 0,0 here is "relative to the old buffer," not absolute */
|
||||||
stage_wayland->allocation.x,
|
0, 0);
|
||||||
stage_wayland->allocation.y,
|
wl_surface_map_toplevel (stage_wayland->wayland_surface);
|
||||||
stage_wayland->allocation.width,
|
|
||||||
stage_wayland->allocation.height);
|
|
||||||
|
|
||||||
stage_wayland->pending_swaps++;
|
stage_wayland->pending_swaps++;
|
||||||
wl_display_frame_callback (backend_wayland->wayland_display,
|
wl_display_frame_callback (backend_wayland->wayland_display,
|
||||||
@ -506,7 +640,7 @@ _clutter_stage_wayland_redraw (ClutterStageWayland *stage_wayland,
|
|||||||
|
|
||||||
if (!stage_wayland->back_buffer)
|
if (!stage_wayland->back_buffer)
|
||||||
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);
|
cogl_set_framebuffer (stage_wayland->back_buffer->offscreen);
|
||||||
_clutter_stage_maybe_setup_viewport (stage_wayland->wrapper);
|
_clutter_stage_maybe_setup_viewport (stage_wayland->wrapper);
|
||||||
|
@ -51,16 +51,34 @@
|
|||||||
typedef struct _ClutterStageWayland ClutterStageWayland;
|
typedef struct _ClutterStageWayland ClutterStageWayland;
|
||||||
typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass;
|
typedef struct _ClutterStageWaylandClass ClutterStageWaylandClass;
|
||||||
|
|
||||||
|
#define BUFFER_TYPE_DRM 1
|
||||||
|
#define BUFFER_TYPE_SHM 2
|
||||||
|
|
||||||
typedef struct _ClutterStageWaylandWaylandBuffer
|
typedef struct _ClutterStageWaylandWaylandBuffer
|
||||||
{
|
{
|
||||||
EGLImageKHR drm_image;
|
|
||||||
GLuint texture;
|
|
||||||
CoglHandle offscreen;
|
CoglHandle offscreen;
|
||||||
struct wl_buffer *wayland_buffer;
|
struct wl_buffer *wayland_buffer;
|
||||||
cairo_region_t *dirty_region;
|
cairo_region_t *dirty_region;
|
||||||
CoglHandle tex;
|
CoglHandle tex;
|
||||||
|
guint type;
|
||||||
} ClutterStageWaylandWaylandBuffer;
|
} 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
|
struct _ClutterStageWayland
|
||||||
{
|
{
|
||||||
GObject parent_instance;
|
GObject parent_instance;
|
||||||
|
Loading…
Reference in New Issue
Block a user