cursor: Refactor code to load cursor images out

We're going to make MetaCursorReference specialized and per-backend soon.
This commit is contained in:
Jasper St. Pierre 2014-03-31 17:13:03 -04:00
parent 78dbf8cb56
commit da27735265

View File

@ -190,19 +190,19 @@ load_cursor_on_client (MetaDisplay *display,
return image; return image;
} }
static MetaCursorReference * static void
meta_cursor_reference_from_xcursor_image (MetaCursorTracker *tracker, meta_cursor_image_load_from_xcursor_image (MetaCursorTracker *tracker,
XcursorImage *image) MetaCursorImage *image,
XcursorImage *xc_image)
{ {
int width, height, rowstride; int width, height, rowstride;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
uint32_t gbm_format; uint32_t gbm_format;
ClutterBackend *clutter_backend; ClutterBackend *clutter_backend;
CoglContext *cogl_context; CoglContext *cogl_context;
MetaCursorReference *self;
width = image->width; width = xc_image->width;
height = image->height; height = xc_image->height;
rowstride = width * 4; rowstride = width * 4;
gbm_format = GBM_FORMAT_ARGB8888; gbm_format = GBM_FORMAT_ARGB8888;
@ -212,26 +212,24 @@ meta_cursor_reference_from_xcursor_image (MetaCursorTracker *tracker,
cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
#endif #endif
self = g_slice_new0 (MetaCursorReference); image->hot_x = xc_image->xhot;
self->ref_count = 1; image->hot_y = xc_image->yhot;
self->image.hot_x = image->xhot;
self->image.hot_y = image->yhot;
clutter_backend = clutter_get_default_backend (); clutter_backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (clutter_backend); cogl_context = clutter_backend_get_cogl_context (clutter_backend);
self->image.texture = cogl_texture_2d_new_from_data (cogl_context, image->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height, width, height,
cogl_format, cogl_format,
rowstride, rowstride,
(uint8_t*)image->pixels, (uint8_t*)xc_image->pixels,
NULL); NULL);
if (tracker->gbm) if (tracker->gbm)
{ {
if (width > 64 || height > 64) if (width > 64 || height > 64)
{ {
meta_warning ("Invalid theme cursor size (must be at most 64x64)\n"); meta_warning ("Invalid theme cursor size (must be at most 64x64)\n");
goto out; return;
} }
if (gbm_device_is_format_supported (tracker->gbm, gbm_format, if (gbm_device_is_format_supported (tracker->gbm, gbm_format,
@ -240,21 +238,18 @@ meta_cursor_reference_from_xcursor_image (MetaCursorTracker *tracker,
uint32_t buf[64 * 64]; uint32_t buf[64 * 64];
int i; int i;
self->image.bo = gbm_bo_create (tracker->gbm, 64, 64, image->bo = gbm_bo_create (tracker->gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
memcpy (buf + i * 64, image->pixels + i * width, width * 4); memcpy (buf + i * 64, xc_image->pixels + i * width, width * 4);
gbm_bo_write (self->image.bo, buf, 64 * 64 * 4); gbm_bo_write (image->bo, buf, 64 * 64 * 4);
} }
else else
meta_warning ("HW cursor for format %d not supported\n", gbm_format); meta_warning ("HW cursor for format %d not supported\n", gbm_format);
} }
out:
return self;
} }
MetaCursorReference * MetaCursorReference *
@ -271,29 +266,29 @@ meta_cursor_reference_from_theme (MetaCursorTracker *tracker,
if (!image) if (!image)
return NULL; return NULL;
self = meta_cursor_reference_from_xcursor_image (tracker, image); self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_xcursor_image (tracker, &self->image, image);
XcursorImageDestroy (image); XcursorImageDestroy (image);
return self; return self;
} }
MetaCursorReference * static void
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker, meta_cursor_image_load_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer, MetaCursorImage *image,
int hot_x, struct wl_resource *buffer,
int hot_y) int hot_x,
int hot_y)
{ {
ClutterBackend *backend; ClutterBackend *backend;
CoglContext *cogl_context; CoglContext *cogl_context;
MetaCursorReference *self;
CoglPixelFormat cogl_format; CoglPixelFormat cogl_format;
struct wl_shm_buffer *shm_buffer; struct wl_shm_buffer *shm_buffer;
uint32_t gbm_format; uint32_t gbm_format;
self = g_slice_new0 (MetaCursorReference); image->hot_x = hot_x;
self->ref_count = 1; image->hot_y = hot_y;
self->image.hot_x = hot_x;
self->image.hot_y = hot_y;
backend = clutter_get_default_backend (); backend = clutter_get_default_backend ();
cogl_context = clutter_backend_get_cogl_context (backend); cogl_context = clutter_backend_get_cogl_context (backend);
@ -332,17 +327,17 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
gbm_format = GBM_FORMAT_ARGB8888; gbm_format = GBM_FORMAT_ARGB8888;
} }
self->image.texture = cogl_texture_2d_new_from_data (cogl_context, image->texture = cogl_texture_2d_new_from_data (cogl_context,
width, height, width, height,
cogl_format, cogl_format,
rowstride, rowstride,
wl_shm_buffer_get_data (shm_buffer), wl_shm_buffer_get_data (shm_buffer),
NULL); NULL);
if (width > 64 || height > 64) if (width > 64 || height > 64)
{ {
meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n"); meta_warning ("Invalid cursor size (must be at most 64x64), falling back to software (GL) cursors\n");
return self; return;
} }
if (tracker->gbm) if (tracker->gbm)
@ -354,15 +349,15 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
uint8_t buf[4 * 64 * 64]; uint8_t buf[4 * 64 * 64];
int i; int i;
self->image.bo = gbm_bo_create (tracker->gbm, 64, 64, image->bo = gbm_bo_create (tracker->gbm, 64, 64,
gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE); gbm_format, GBM_BO_USE_CURSOR_64X64 | GBM_BO_USE_WRITE);
data = wl_shm_buffer_get_data (shm_buffer); data = wl_shm_buffer_get_data (shm_buffer);
memset (buf, 0, sizeof(buf)); memset (buf, 0, sizeof(buf));
for (i = 0; i < height; i++) for (i = 0; i < height; i++)
memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width); memcpy (buf + i * 4 * 64, data + i * rowstride, 4 * width);
gbm_bo_write (self->image.bo, buf, 64 * 64 * 4); gbm_bo_write (image->bo, buf, 64 * 64 * 4);
} }
else else
meta_warning ("HW cursor for format %d not supported\n", gbm_format); meta_warning ("HW cursor for format %d not supported\n", gbm_format);
@ -372,9 +367,9 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
{ {
int width, height; int width, height;
self->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);
width = cogl_texture_get_width (COGL_TEXTURE (self->image.texture)); width = cogl_texture_get_width (COGL_TEXTURE (image->texture));
height = cogl_texture_get_height (COGL_TEXTURE (self->image.texture)); height = cogl_texture_get_height (COGL_TEXTURE (image->texture));
/* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses /* HW cursors must be 64x64, but 64x64 is huge, and no cursor theme actually uses
that, so themed cursors must be padded with transparent pixels to fill the that, so themed cursors must be padded with transparent pixels to fill the
@ -385,17 +380,30 @@ meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
if (width != 64 || height != 64) if (width != 64 || height != 64)
{ {
meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n"); meta_warning ("Invalid cursor size (must be 64x64), falling back to software (GL) cursors\n");
return self; return;
} }
if (tracker->gbm) if (tracker->gbm)
{ {
self->image.bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER, image->bo = gbm_bo_import (tracker->gbm, GBM_BO_IMPORT_WL_BUFFER,
buffer, GBM_BO_USE_CURSOR_64X64); buffer, GBM_BO_USE_CURSOR_64X64);
if (!self->image.bo) if (!image->bo)
meta_warning ("Importing HW cursor from wl_buffer failed\n"); meta_warning ("Importing HW cursor from wl_buffer failed\n");
} }
} }
}
MetaCursorReference *
meta_cursor_reference_from_buffer (MetaCursorTracker *tracker,
struct wl_resource *buffer,
int hot_x,
int hot_y)
{
MetaCursorReference *self;
self = g_slice_new0 (MetaCursorReference);
self->ref_count = 1;
meta_cursor_image_load_from_buffer (tracker, &self->image, buffer, hot_x, hot_y);
return self; return self;
} }