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:
@ -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)
|
||||
{
|
||||
|
Reference in New Issue
Block a user