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;
|
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
|
#define META_CURSOR_RENDERER_H
|
||||||
|
|
||||||
#include <glib-object.h>
|
#include <glib-object.h>
|
||||||
|
#include <X11/Xcursor/Xcursor.h>
|
||||||
|
#ifdef HAVE_WAYLAND
|
||||||
|
#include <wayland-server.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <meta/screen.h>
|
#include <meta/screen.h>
|
||||||
#include "meta-cursor.h"
|
#include "meta-cursor.h"
|
||||||
|
@ -39,6 +43,14 @@ struct _MetaCursorRendererClass
|
||||||
GObjectClass parent_class;
|
GObjectClass parent_class;
|
||||||
|
|
||||||
gboolean (* update_cursor) (MetaCursorRenderer *renderer);
|
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;
|
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);
|
MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer);
|
||||||
const MetaRectangle * meta_cursor_renderer_get_rect (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 */
|
#endif /* META_CURSOR_RENDERER_H */
|
||||||
|
|
|
@ -29,11 +29,6 @@
|
||||||
#include "screen-private.h"
|
#include "screen-private.h"
|
||||||
#include "meta-backend-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 <string.h>
|
||||||
|
|
||||||
#include <X11/cursorfont.h>
|
#include <X11/cursorfont.h>
|
||||||
|
@ -48,10 +43,6 @@ typedef struct
|
||||||
{
|
{
|
||||||
CoglTexture2D *texture;
|
CoglTexture2D *texture;
|
||||||
int hot_x, hot_y;
|
int hot_x, hot_y;
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
|
||||||
struct gbm_bo *bo;
|
|
||||||
#endif
|
|
||||||
} MetaCursorImage;
|
} MetaCursorImage;
|
||||||
|
|
||||||
struct _MetaCursorSprite
|
struct _MetaCursorSprite
|
||||||
|
@ -74,11 +65,6 @@ meta_cursor_image_free (MetaCursorImage *image)
|
||||||
{
|
{
|
||||||
if (image->texture)
|
if (image->texture)
|
||||||
cogl_object_unref (image->texture);
|
cogl_object_unref (image->texture);
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
|
||||||
if (image->bo)
|
|
||||||
gbm_bo_destroy (image->bo);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
|
@ -144,81 +130,13 @@ load_cursor_on_client (MetaCursor cursor)
|
||||||
meta_prefs_get_cursor_size ());
|
meta_prefs_get_cursor_size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
|
||||||
static void
|
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 ();
|
MetaBackend *meta_backend = meta_get_backend ();
|
||||||
MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_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;
|
uint width, height, rowstride;
|
||||||
CoglPixelFormat cogl_format;
|
CoglPixelFormat cogl_format;
|
||||||
ClutterBackend *clutter_backend;
|
ClutterBackend *clutter_backend;
|
||||||
|
@ -246,15 +164,7 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image,
|
||||||
(uint8_t *) xc_image->pixels,
|
(uint8_t *) xc_image->pixels,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static XcursorImage *
|
static XcursorImage *
|
||||||
|
@ -278,7 +188,7 @@ meta_cursor_sprite_tick_frame (MetaCursorSprite *self)
|
||||||
|
|
||||||
meta_cursor_image_free (&self->image);
|
meta_cursor_image_free (&self->image);
|
||||||
image = meta_cursor_sprite_get_current_frame_image (self);
|
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
|
guint
|
||||||
|
@ -297,36 +207,22 @@ meta_cursor_sprite_is_animated (MetaCursorSprite *self)
|
||||||
self->xcursor_images->nimage > 1);
|
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 *
|
MetaCursorSprite *
|
||||||
meta_cursor_sprite_from_theme (MetaCursor cursor)
|
meta_cursor_sprite_from_theme (MetaCursor cursor)
|
||||||
{
|
{
|
||||||
MetaCursorSprite *self;
|
MetaCursorSprite *self;
|
||||||
|
XcursorImage *image;
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
||||||
|
|
||||||
self->cursor = cursor;
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -351,11 +247,15 @@ meta_cursor_sprite_from_texture (CoglTexture2D *texture,
|
||||||
|
|
||||||
#ifdef HAVE_WAYLAND
|
#ifdef HAVE_WAYLAND
|
||||||
static void
|
static void
|
||||||
meta_cursor_image_load_from_buffer (MetaCursorImage *image,
|
meta_cursor_sprite_load_from_buffer (MetaCursorSprite *self,
|
||||||
struct wl_resource *buffer,
|
struct wl_resource *buffer,
|
||||||
int hot_x,
|
int hot_x,
|
||||||
int hot_y)
|
int hot_y)
|
||||||
{
|
{
|
||||||
|
MetaCursorImage *image = &self->image;
|
||||||
|
MetaBackend *meta_backend = meta_get_backend ();
|
||||||
|
MetaCursorRenderer *renderer =
|
||||||
|
meta_backend_get_cursor_renderer (meta_backend);
|
||||||
ClutterBackend *backend;
|
ClutterBackend *backend;
|
||||||
CoglContext *cogl_context;
|
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);
|
image->texture = cogl_wayland_texture_2d_new_from_buffer (cogl_context, buffer, NULL);
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
meta_cursor_renderer_realize_cursor_from_wl_buffer (renderer, self, buffer);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MetaCursorSprite *
|
MetaCursorSprite *
|
||||||
|
@ -448,7 +279,7 @@ meta_cursor_sprite_from_buffer (struct wl_resource *buffer,
|
||||||
|
|
||||||
self = g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -459,9 +290,6 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
||||||
int *hot_x,
|
int *hot_x,
|
||||||
int *hot_y)
|
int *hot_y)
|
||||||
{
|
{
|
||||||
if (!self->image.texture)
|
|
||||||
load_cursor_image (self);
|
|
||||||
|
|
||||||
if (hot_x)
|
if (hot_x)
|
||||||
*hot_x = self->image.hot_x;
|
*hot_x = self->image.hot_x;
|
||||||
if (hot_y)
|
if (hot_y)
|
||||||
|
@ -470,29 +298,33 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
||||||
return COGL_TEXTURE (self->image.texture);
|
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
|
MetaCursor
|
||||||
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
|
meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self)
|
||||||
{
|
{
|
||||||
return self->cursor;
|
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
|
static void
|
||||||
meta_cursor_sprite_init (MetaCursorSprite *self)
|
meta_cursor_sprite_init (MetaCursorSprite *self)
|
||||||
{
|
{
|
||||||
|
|
|
@ -54,11 +54,13 @@ CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self,
|
||||||
int *hot_x,
|
int *hot_x,
|
||||||
int *hot_y);
|
int *hot_y);
|
||||||
|
|
||||||
#ifdef HAVE_NATIVE_BACKEND
|
void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self,
|
||||||
struct gbm_bo *meta_cursor_sprite_get_gbm_bo (MetaCursorSprite *self,
|
int *hot_x,
|
||||||
int *hot_x,
|
int *hot_y);
|
||||||
int *hot_y);
|
|
||||||
#endif
|
guint meta_cursor_sprite_get_width (MetaCursorSprite *self);
|
||||||
|
|
||||||
|
guint meta_cursor_sprite_get_height (MetaCursorSprite *self);
|
||||||
|
|
||||||
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self);
|
gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self);
|
||||||
void meta_cursor_sprite_tick_frame (MetaCursorSprite *self);
|
void meta_cursor_sprite_tick_frame (MetaCursorSprite *self);
|
||||||
|
|
|
@ -26,9 +26,11 @@
|
||||||
|
|
||||||
#include "meta-cursor-renderer-native.h"
|
#include "meta-cursor-renderer-native.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
#include <gbm.h>
|
#include <gbm.h>
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
|
|
||||||
|
#include <meta/util.h>
|
||||||
#include "meta-monitor-manager-private.h"
|
#include "meta-monitor-manager-private.h"
|
||||||
|
|
||||||
#ifndef DRM_CAP_CURSOR_WIDTH
|
#ifndef DRM_CAP_CURSOR_WIDTH
|
||||||
|
@ -38,6 +40,8 @@
|
||||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static GQuark quark_cursor_sprite = 0;
|
||||||
|
|
||||||
struct _MetaCursorRendererNativePrivate
|
struct _MetaCursorRendererNativePrivate
|
||||||
{
|
{
|
||||||
gboolean has_hw_cursor;
|
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);
|
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
|
static void
|
||||||
set_crtc_cursor (MetaCursorRendererNative *native,
|
set_crtc_cursor (MetaCursorRendererNative *native,
|
||||||
MetaCRTC *crtc,
|
MetaCRTC *crtc,
|
||||||
|
@ -89,9 +115,10 @@ set_crtc_cursor (MetaCursorRendererNative *native,
|
||||||
union gbm_bo_handle handle;
|
union gbm_bo_handle handle;
|
||||||
int hot_x, hot_y;
|
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);
|
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,
|
drmModeSetCursor2 (priv->drm_fd, crtc->crtc_id, handle.u32,
|
||||||
priv->cursor_width, priv->cursor_height, hot_x, hot_y);
|
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);
|
MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer);
|
||||||
|
|
||||||
if (cursor_sprite)
|
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
|
else
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -219,6 +246,165 @@ meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer)
|
||||||
return priv->has_hw_cursor;
|
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
|
static void
|
||||||
meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass)
|
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;
|
object_class->finalize = meta_cursor_renderer_native_finalize;
|
||||||
renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor;
|
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
|
static void
|
||||||
|
@ -279,16 +473,6 @@ meta_cursor_renderer_native_get_gbm_device (MetaCursorRendererNative *native)
|
||||||
return priv->gbm;
|
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
|
void
|
||||||
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue