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:
Jonas Ådahl
2015-03-11 11:16:58 +08:00
parent 165050f8f9
commit d3fdaa3232
5 changed files with 295 additions and 230 deletions

View File

@ -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)
{