MetaCursorSprite: Put renderer specific code in the renderer
There were lots of code handling the native renderer specific cases; move these parts to the renderer. Note that this causes the X11 case to always generate the texture which is a waste of memory, but his regression will be fixed in a following commit. The lazy loading of the texture was removed because it was eventually always loaded anyway indirectly by the renderer to calculate the current rect. https://bugzilla.gnome.org/show_bug.cgi?id=744932
This commit is contained in:
parent
165050f8f9
commit
d3fdaa3232
5 changed files with 295 additions and 230 deletions
|
@ -181,3 +181,28 @@ meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer)
|
|||
|
||||
return &priv->current_rect;
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
void
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
struct wl_resource *buffer)
|
||||
{
|
||||
|
||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
|
||||
|
||||
if (renderer_class->realize_cursor_from_wl_buffer)
|
||||
renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer);
|
||||
|
||||
if (renderer_class->realize_cursor_from_xcursor)
|
||||
renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image);
|
||||
}
|
||||
|
|
|
@ -26,6 +26,10 @@
|
|||
#define META_CURSOR_RENDERER_H
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <X11/Xcursor/Xcursor.h>
|
||||
#ifdef HAVE_WAYLAND
|
||||
#include <wayland-server.h>
|
||||
#endif
|
||||
|
||||
#include <meta/screen.h>
|
||||
#include "meta-cursor.h"
|
||||
|
@ -39,6 +43,14 @@ struct _MetaCursorRendererClass
|
|||
GObjectClass parent_class;
|
||||
|
||||
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
|
||||
#ifdef HAVE_WAYLAND
|
||||
void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
struct wl_resource *buffer);
|
||||
#endif
|
||||
void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
XcursorImage *xc_image);
|
||||
};
|
||||
|
||||
GType meta_cursor_renderer_get_type (void) G_GNUC_CONST;
|
||||
|
@ -55,4 +67,14 @@ void meta_cursor_renderer_force_update (MetaCursorRenderer *renderer);
|
|||
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||
const MetaRectangle * meta_cursor_renderer_get_rect (MetaCursorRenderer *renderer);
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
struct wl_resource *buffer);
|
||||
#endif
|
||||
|
||||
void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
XcursorImage *xc_image);
|
||||
|
||||
#endif /* META_CURSOR_RENDERER_H */
|
||||
|
|
|
@ -29,11 +29,6 @@
|
|||
#include "screen-private.h"
|
||||
#include "meta-backend-private.h"
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
#include <gbm.h>
|
||||
#include "backends/native/meta-cursor-renderer-native.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <X11/cursorfont.h>
|
||||
|
@ -48,10 +43,6 @@ typedef struct
|
|||
{
|
||||
CoglTexture2D *texture;
|
||||
int hot_x, hot_y;
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *bo;
|
||||
#endif
|
||||
} MetaCursorImage;
|
||||
|
||||
struct _MetaCursorSprite
|
||||
|
@ -74,11 +65,6 @@ meta_cursor_image_free (MetaCursorImage *image)
|
|||
{
|
||||
if (image->texture)
|
||||
cogl_object_unref (image->texture);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
if (image->bo)
|
||||
gbm_bo_destroy (image->bo);
|
||||
#endif
|
||||
}
|
||||
|
||||
static const char *
|
||||
|
@ -144,81 +130,13 @@ load_cursor_on_client (MetaCursor cursor)
|
|||
meta_prefs_get_cursor_size ());
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
get_hardware_cursor_size (uint64_t *cursor_width, uint64_t *cursor_height)
|
||||
meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
MetaCursorImage *image = &self->image;
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
{
|
||||
meta_cursor_renderer_native_get_cursor_size (META_CURSOR_RENDERER_NATIVE (renderer), cursor_width, cursor_height);
|
||||
return;
|
||||
}
|
||||
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static void
|
||||
meta_cursor_image_load_gbm_buffer (struct gbm_device *gbm,
|
||||
MetaCursorImage *image,
|
||||
uint8_t *pixels,
|
||||
uint width,
|
||||
uint height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
{
|
||||
uint64_t cursor_width, cursor_height;
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width > cursor_width || height > cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
|
||||
(unsigned int)cursor_width, (unsigned int)cursor_height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm_device_is_format_supported (gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
||||
{
|
||||
uint8_t buf[4 * cursor_width * cursor_height];
|
||||
uint i;
|
||||
|
||||
image->bo = gbm_bo_create (gbm, cursor_width, cursor_height,
|
||||
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
|
||||
|
||||
gbm_bo_write (image->bo, buf, cursor_width * cursor_height * 4);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
static struct gbm_device *
|
||||
get_gbm_device (void)
|
||||
{
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend);
|
||||
|
||||
if (META_IS_CURSOR_RENDERER_NATIVE (renderer))
|
||||
return meta_cursor_renderer_native_get_gbm_device (META_CURSOR_RENDERER_NATIVE (renderer));
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
uint width, height, rowstride;
|
||||
CoglPixelFormat cogl_format;
|
||||
ClutterBackend *clutter_backend;
|
||||
|
@ -246,15 +164,7 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
|||
(uint8_t *) xc_image->pixels,
|
||||
NULL);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
width, height, rowstride,
|
||||
GBM_FORMAT_ARGB8888);
|
||||
#endif
|
||||
meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
|
||||
}
|
||||
|
||||
static XcursorImage *
|
||||
|
@ -278,7 +188,7 @@ meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
|
|||
|
||||
meta_cursor_image_free (&self->image);
|
||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
||||
meta_cursor_image_load_from_xcursor_image (&self->image, image);
|
||||
meta_cursor_sprite_load_from_xcursor_image (self, image);
|
||||
}
|
||||
|
||||
guint
|
||||
|
@ -297,36 +207,22 @@ meta_cursor_sprite_is_animated (MetaCursorSprite *self)
|
|||
self->xcursor_images->nimage > 1);
|
||||
}
|
||||
|
||||
static void
|
||||
load_cursor_image (MetaCursorSprite *self)
|
||||
{
|
||||
XcursorImage *image;
|
||||
|
||||
/* Either cursors are loaded from X cursors or buffers. Since
|
||||
* buffers are converted over immediately, we can make sure to
|
||||
* load this directly. */
|
||||
g_assert (self->cursor != META_CURSOR_NONE);
|
||||
|
||||
if (!self->xcursor_images)
|
||||
{
|
||||
self->current_frame = 0;
|
||||
self->xcursor_images = load_cursor_on_client (self->cursor);
|
||||
if (!self->xcursor_images)
|
||||
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
|
||||
}
|
||||
|
||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
||||
meta_cursor_image_load_from_xcursor_image (&self->image, image);
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
meta_cursor_sprite_from_theme (MetaCursor cursor)
|
||||
{
|
||||
MetaCursorSprite *self;
|
||||
XcursorImage *image;
|
||||
|
||||
self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
||||
|
||||
self->cursor = cursor;
|
||||
self->current_frame = 0;
|
||||
self->xcursor_images = load_cursor_on_client (self->cursor);
|
||||
if (!self->xcursor_images)
|
||||
meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
|
||||
|
||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
||||
meta_cursor_sprite_load_from_xcursor_image (self, image);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -351,11 +247,15 @@ meta_cursor_sprite_from_texture (CoglTexture2D *texture,
|
|||
|
||||
#ifdef HAVE_WAYLAND
|
||||
static void
|
||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
meta_cursor_sprite_load_from_buffer (MetaCursorSprite *self,
|
||||
struct wl_resource *buffer,
|
||||
int hot_x,
|
||||
int hot_y)
|
||||
{
|
||||
MetaCursorImage *image = &self->image;
|
||||
MetaBackend *meta_backend = meta_get_backend ();
|
||||
MetaCursorRenderer *renderer =
|
||||
meta_backend_get_cursor_renderer (meta_backend);
|
||||
ClutterBackend *backend;
|
||||
CoglContext *cogl_context;
|
||||
|
||||
|
@ -367,76 +267,7 @@ meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
|||
|
||||
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_device *gbm = get_gbm_device ();
|
||||
if (gbm)
|
||||
{
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
|
||||
height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
|
||||
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#else
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
meta_cursor_image_load_gbm_buffer (gbm,
|
||||
image,
|
||||
(uint8_t *) wl_shm_buffer_get_data (shm_buffer),
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is bigger than cursor theme
|
||||
size, so themed cursors must be padded with transparent pixels to fill the
|
||||
overlay. This is trivial if we have CPU access to the data, but it's not
|
||||
possible if the buffer is in GPU memory (and possibly tiled too), so if we
|
||||
don't get the right size, we fallback to GL.
|
||||
*/
|
||||
get_hardware_cursor_size (&cursor_width, &cursor_height);
|
||||
|
||||
if (width != cursor_width || height != cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
image->bo = gbm_bo_import (gbm, GBM_BO_IMPORT_WL_BUFFER, buffer, GBM_BO_USE_CURSOR);
|
||||
if (!image->bo)
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
meta_cursor_renderer_realize_cursor_from_wl_buffer (renderer, self, buffer);
|
||||
}
|
||||
|
||||
MetaCursorSprite *
|
||||
|
@ -448,7 +279,7 @@ meta_cursor_sprite_from_buffer (struct wl_resource *buffer,
|
|||
|
||||
self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
||||
|
||||
meta_cursor_image_load_from_buffer (&self->image, buffer, hot_x, hot_y);
|
||||
meta_cursor_sprite_load_from_buffer (self, buffer, hot_x, hot_y);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
@ -459,9 +290,6 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
|||
int *hot_x,
|
||||
int *hot_y)
|
||||
{
|
||||
if (!self->image.texture)
|
||||
load_cursor_image (self);
|
||||
|
||||
if (hot_x)
|
||||
*hot_x = self->image.hot_x;
|
||||
if (hot_y)
|
||||
|
@ -470,29 +298,33 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
|||
return COGL_TEXTURE (self->image.texture);
|
||||
}
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *
|
||||
meta_cursor_sprite_get_gbm_bo (MetaCursorSprite *self,
|
||||
int *hot_x,
|
||||
int *hot_y)
|
||||
{
|
||||
if (!self->image.bo)
|
||||
load_cursor_image (self);
|
||||
|
||||
if (hot_x)
|
||||
*hot_x = self->image.hot_x;
|
||||
if (hot_y)
|
||||
*hot_y = self->image.hot_y;
|
||||
return self->image.bo;
|
||||
}
|
||||
#endif
|
||||
|
||||
MetaCursor
|
||||
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
|
||||
{
|
||||
return self->cursor;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
|
||||
int *hot_x,
|
||||
int *hot_y)
|
||||
{
|
||||
*hot_x = self->image.hot_x;
|
||||
*hot_y = self->image.hot_y;
|
||||
}
|
||||
|
||||
guint
|
||||
meta_cursor_sprite_get_width (MetaCursorSprite *self)
|
||||
{
|
||||
return cogl_texture_get_width (COGL_TEXTURE (self->image.texture));
|
||||
}
|
||||
|
||||
guint
|
||||
meta_cursor_sprite_get_height (MetaCursorSprite *self)
|
||||
{
|
||||
return cogl_texture_get_height (COGL_TEXTURE (self->image.texture));
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_sprite_init (MetaCursorSprite *self)
|
||||
{
|
||||
|
|
|
@ -54,11 +54,13 @@ CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
|||
int *hot_x,
|
||||
int *hot_y);
|
||||
|
||||
#ifdef HAVE_NATIVE_BACKEND
|
||||
struct gbm_bo *meta_cursor_sprite_get_gbm_bo (MetaCursorSprite *self,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
#endif
|
||||
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
|
||||
int *hot_x,
|
||||
int *hot_y);
|
||||
|
||||
guint meta_cursor_sprite_get_width (MetaCursorSprite *self);
|
||||
|
||||
guint meta_cursor_sprite_get_height (MetaCursorSprite *self);
|
||||
|
||||
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self);
|
||||
void meta_cursor_sprite_tick_frame (MetaCursorSprite *self);
|
||||
|
|
|
@ -26,9 +26,11 @@
|
|||
|
||||
#include "meta-cursor-renderer-native.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <gbm.h>
|
||||
#include <xf86drm.h>
|
||||
|
||||
#include <meta/util.h>
|
||||
#include "meta-monitor-manager-private.h"
|
||||
|
||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||
|
@ -38,6 +40,8 @@
|
|||
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
#endif
|
||||
|
||||
static GQuark quark_cursor_sprite = 0;
|
||||
|
||||
struct _MetaCursorRendererNativePrivate
|
||||
{
|
||||
gboolean has_hw_cursor;
|
||||
|
@ -70,6 +74,28 @@ meta_cursor_renderer_native_finalize (GObject *object)
|
|||
G_OBJECT_CLASS (meta_cursor_renderer_native_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static struct gbm_bo *
|
||||
get_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite)
|
||||
{
|
||||
return g_object_get_qdata (G_OBJECT (cursor_sprite), quark_cursor_sprite);
|
||||
}
|
||||
|
||||
static void
|
||||
cursor_gbm_bo_free (gpointer data)
|
||||
{
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
gbm_bo_destroy ((struct gbm_bo *)data);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite, struct gbm_bo *bo)
|
||||
{
|
||||
g_object_set_qdata_full (G_OBJECT (cursor_sprite), quark_cursor_sprite,
|
||||
bo, cursor_gbm_bo_free);
|
||||
}
|
||||
|
||||
static void
|
||||
set_crtc_cursor (MetaCursorRendererNative *native,
|
||||
MetaCRTC *crtc,
|
||||
|
@ -89,9 +115,10 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
|||
union gbm_bo_handle handle;
|
||||
int hot_x, hot_y;
|
||||
|
||||
bo = meta_cursor_sprite_get_gbm_bo (cursor_sprite, &hot_x, &hot_y);
|
||||
|
||||
bo = get_cursor_sprite_gbm_bo (cursor_sprite);
|
||||
handle = gbm_bo_get_handle (bo);
|
||||
meta_cursor_sprite_get_hotspot (cursor_sprite, &hot_x, &hot_y);
|
||||
|
||||
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
|
||||
}
|
||||
|
@ -147,7 +174,7 @@ should_have_hw_cursor (MetaCursorRenderer *renderer)
|
|||
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
|
||||
|
||||
if (cursor_sprite)
|
||||
return (meta_cursor_sprite_get_gbm_bo (cursor_sprite, NULL, NULL) != NULL);
|
||||
return (get_cursor_sprite_gbm_bo (cursor_sprite) != NULL);
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -219,6 +246,165 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
|||
return priv->has_hw_cursor;
|
||||
}
|
||||
|
||||
static void
|
||||
get_hardware_cursor_size (MetaCursorRendererNative *native,
|
||||
uint64_t *width, uint64_t *height)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv =
|
||||
meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
*width = priv->cursor_width;
|
||||
*height = priv->cursor_height;
|
||||
}
|
||||
|
||||
static void
|
||||
load_cursor_sprite_gbm_buffer (MetaCursorRendererNative *native,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
uint8_t *pixels,
|
||||
uint width,
|
||||
uint height,
|
||||
int rowstride,
|
||||
uint32_t gbm_format)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv =
|
||||
meta_cursor_renderer_native_get_instance_private (native);
|
||||
uint64_t cursor_width, cursor_height;
|
||||
|
||||
get_hardware_cursor_size (native, &cursor_width, &cursor_height);
|
||||
|
||||
if (width > cursor_width || height > cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid theme cursor size (must be at most %ux%u)\n",
|
||||
(unsigned int)cursor_width, (unsigned int)cursor_height);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gbm_device_is_format_supported (priv->gbm, gbm_format,
|
||||
GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE))
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
uint8_t buf[4 * cursor_width * cursor_height];
|
||||
uint i;
|
||||
|
||||
bo = gbm_bo_create (priv->gbm, cursor_width, cursor_height,
|
||||
gbm_format, GBM_BO_USE_CURSOR | GBM_BO_USE_WRITE);
|
||||
|
||||
memset (buf, 0, sizeof(buf));
|
||||
for (i = 0; i < height; i++)
|
||||
memcpy (buf + i * 4 * cursor_width, pixels + i * rowstride, width * 4);
|
||||
|
||||
gbm_bo_write (bo, buf, cursor_width * cursor_height * 4);
|
||||
|
||||
set_cursor_sprite_gbm_bo (cursor_sprite, bo);
|
||||
}
|
||||
else
|
||||
meta_warning ("HW cursor for format %d not supported\n", gbm_format);
|
||||
}
|
||||
|
||||
#ifdef HAVE_WAYLAND
|
||||
static void
|
||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
struct wl_resource *buffer)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
MetaCursorRendererNativePrivate *priv =
|
||||
meta_cursor_renderer_native_get_instance_private (native);
|
||||
uint32_t gbm_format;
|
||||
uint64_t cursor_width, cursor_height;
|
||||
uint width, height;
|
||||
|
||||
width = meta_cursor_sprite_get_width (cursor_sprite);
|
||||
height = meta_cursor_sprite_get_height (cursor_sprite);
|
||||
|
||||
struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer);
|
||||
if (shm_buffer)
|
||||
{
|
||||
int rowstride = wl_shm_buffer_get_stride (shm_buffer);
|
||||
uint8_t *buffer_data;
|
||||
|
||||
wl_shm_buffer_begin_access (shm_buffer);
|
||||
|
||||
switch (wl_shm_buffer_get_format (shm_buffer))
|
||||
{
|
||||
#if G_BYTE_ORDER == G_BIG_ENDIAN
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#else
|
||||
case WL_SHM_FORMAT_ARGB8888:
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
break;
|
||||
case WL_SHM_FORMAT_XRGB8888:
|
||||
gbm_format = GBM_FORMAT_XRGB8888;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
g_warn_if_reached ();
|
||||
gbm_format = GBM_FORMAT_ARGB8888;
|
||||
}
|
||||
|
||||
buffer_data = wl_shm_buffer_get_data (shm_buffer);
|
||||
load_cursor_sprite_gbm_buffer (native,
|
||||
cursor_sprite,
|
||||
buffer_data,
|
||||
width, height, rowstride,
|
||||
gbm_format);
|
||||
|
||||
wl_shm_buffer_end_access (shm_buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct gbm_bo *bo;
|
||||
|
||||
/* HW cursors have a predefined size (at least 64x64), which usually is
|
||||
* bigger than cursor theme size, so themed cursors must be padded with
|
||||
* transparent pixels to fill the overlay. This is trivial if we have CPU
|
||||
* access to the data, but it's not possible if the buffer is in GPU
|
||||
* memory (and possibly tiled too), so if we don't get the right size, we
|
||||
* fallback to GL. */
|
||||
get_hardware_cursor_size (native, &cursor_width, &cursor_height);
|
||||
|
||||
if (width != cursor_width || height != cursor_height)
|
||||
{
|
||||
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
|
||||
return;
|
||||
}
|
||||
|
||||
bo = gbm_bo_import (priv->gbm,
|
||||
GBM_BO_IMPORT_WL_BUFFER,
|
||||
buffer,
|
||||
GBM_BO_USE_CURSOR);
|
||||
if (!bo)
|
||||
{
|
||||
meta_warning ("Importing HW cursor from wl_buffer failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
set_cursor_sprite_gbm_bo (cursor_sprite, bo);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer,
|
||||
MetaCursorSprite *cursor_sprite,
|
||||
XcursorImage *xc_image)
|
||||
{
|
||||
MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer);
|
||||
|
||||
load_cursor_sprite_gbm_buffer (native,
|
||||
cursor_sprite,
|
||||
(uint8_t *) xc_image->pixels,
|
||||
xc_image->width,
|
||||
xc_image->height,
|
||||
xc_image->width * 4,
|
||||
GBM_FORMAT_ARGB8888);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
||||
{
|
||||
|
@ -227,6 +413,14 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
|||
|
||||
object_class->finalize = meta_cursor_renderer_native_finalize;
|
||||
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
|
||||
#ifdef HAVE_WAYLAND
|
||||
renderer_class->realize_cursor_from_wl_buffer =
|
||||
meta_cursor_renderer_native_realize_cursor_from_wl_buffer;
|
||||
#endif
|
||||
renderer_class->realize_cursor_from_xcursor =
|
||||
meta_cursor_renderer_native_realize_cursor_from_xcursor;
|
||||
|
||||
quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native");
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -279,16 +473,6 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
|
|||
return priv->gbm;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_get_cursor_size (MetaCursorRendererNative *native,
|
||||
uint64_t *width, uint64_t *height)
|
||||
{
|
||||
MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native);
|
||||
|
||||
*width = priv->cursor_width;
|
||||
*height = priv->cursor_height;
|
||||
}
|
||||
|
||||
void
|
||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue