cursor-renderer/native: Pre-process cursor sprite with Cogl
Instead of using cairo for scaling and rotating cursors before putting them on a plane, use Cogl. For now still download them back to the CPU so we can place them on a dumb buffer, but can explore rendering to a DMA buffer directly as a future improvement. Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3433>
This commit is contained in:
parent
20c7653d49
commit
0bbb78f29e
@ -50,6 +50,7 @@
|
|||||||
#include "backends/native/meta-kms.h"
|
#include "backends/native/meta-kms.h"
|
||||||
#include "backends/native/meta-renderer-native.h"
|
#include "backends/native/meta-renderer-native.h"
|
||||||
#include "backends/native/meta-seat-native.h"
|
#include "backends/native/meta-seat-native.h"
|
||||||
|
#include "common/meta-cogl-drm-formats.h"
|
||||||
#include "core/boxes-private.h"
|
#include "core/boxes-private.h"
|
||||||
#include "meta/boxes.h"
|
#include "meta/boxes.h"
|
||||||
#include "meta/meta-backend.h"
|
#include "meta/meta-backend.h"
|
||||||
@ -756,92 +757,70 @@ load_cursor_sprite_gbm_buffer_for_crtc (MetaCursorRendererNative *native,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cairo_surface_t *
|
static CoglTexture *
|
||||||
scale_and_transform_cursor_sprite_cpu (uint8_t *pixels,
|
scale_and_transform_cursor_sprite_cpu (MetaCursorRendererNative *cursor_renderer_native,
|
||||||
cairo_format_t pixel_format,
|
uint8_t *pixels,
|
||||||
|
CoglPixelFormat pixel_format,
|
||||||
int width,
|
int width,
|
||||||
int height,
|
int height,
|
||||||
int rowstride,
|
int rowstride,
|
||||||
float scale,
|
float scale,
|
||||||
MetaMonitorTransform transform)
|
MetaMonitorTransform transform,
|
||||||
|
GError **error)
|
||||||
{
|
{
|
||||||
cairo_t *cr;
|
MetaCursorRendererNativePrivate *priv =
|
||||||
cairo_surface_t *source_surface;
|
meta_cursor_renderer_native_get_instance_private (cursor_renderer_native);
|
||||||
cairo_surface_t *target_surface;
|
ClutterBackend *clutter_backend =
|
||||||
int image_width;
|
meta_backend_get_clutter_backend (priv->backend);
|
||||||
int image_height;
|
CoglContext *cogl_context = clutter_backend_get_cogl_context (clutter_backend);
|
||||||
|
g_autoptr (CoglTexture) src_texture = NULL;
|
||||||
|
g_autoptr (CoglTexture) dst_texture = NULL;
|
||||||
|
g_autoptr (CoglOffscreen) offscreen = NULL;
|
||||||
|
g_autoptr (CoglPipeline) pipeline = NULL;
|
||||||
|
graphene_matrix_t matrix;
|
||||||
|
MetaMonitorTransform pipeline_transform;
|
||||||
|
int dst_width;
|
||||||
|
int dst_height;
|
||||||
|
|
||||||
image_width = (int) ceilf (width * scale);
|
dst_width = (int) ceilf (width * scale);
|
||||||
image_height = (int) ceilf (height * scale);
|
dst_height = (int) ceilf (height * scale);
|
||||||
|
|
||||||
target_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
|
src_texture = cogl_texture_2d_new_from_data (cogl_context,
|
||||||
image_width,
|
width, height,
|
||||||
image_height);
|
|
||||||
|
|
||||||
cr = cairo_create (target_surface);
|
|
||||||
if (transform != META_MONITOR_TRANSFORM_NORMAL)
|
|
||||||
{
|
|
||||||
cairo_translate (cr, 0.5 * image_width, 0.5 * image_height);
|
|
||||||
switch (transform)
|
|
||||||
{
|
|
||||||
case META_MONITOR_TRANSFORM_90:
|
|
||||||
cairo_rotate (cr, M_PI * 1.5);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_180:
|
|
||||||
cairo_rotate (cr, M_PI);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_270:
|
|
||||||
cairo_rotate (cr, M_PI * 0.5);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED:
|
|
||||||
cairo_scale (cr, -1, 1);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED_90:
|
|
||||||
cairo_scale (cr, -1, 1);
|
|
||||||
cairo_rotate (cr, M_PI * 0.5);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED_180:
|
|
||||||
cairo_scale (cr, -1, 1);
|
|
||||||
cairo_rotate (cr, M_PI);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_FLIPPED_270:
|
|
||||||
cairo_scale (cr, -1, 1);
|
|
||||||
cairo_rotate (cr, M_PI * 1.5);
|
|
||||||
break;
|
|
||||||
case META_MONITOR_TRANSFORM_NORMAL:
|
|
||||||
g_assert_not_reached ();
|
|
||||||
}
|
|
||||||
cairo_translate (cr, -0.5 * image_width, -0.5 * image_height);
|
|
||||||
}
|
|
||||||
cairo_scale (cr, scale, scale);
|
|
||||||
|
|
||||||
source_surface = cairo_image_surface_create_for_data (pixels,
|
|
||||||
pixel_format,
|
pixel_format,
|
||||||
width,
|
rowstride,
|
||||||
height,
|
pixels,
|
||||||
rowstride);
|
error);
|
||||||
|
if (!src_texture)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
cairo_set_source_surface (cr, source_surface, 0, 0);
|
dst_texture = cogl_texture_2d_new_with_format (cogl_context,
|
||||||
cairo_paint (cr);
|
dst_width,
|
||||||
cairo_destroy (cr);
|
dst_height,
|
||||||
cairo_surface_destroy (source_surface);
|
COGL_PIXEL_FORMAT_BGRA_8888_PRE);
|
||||||
|
offscreen = cogl_offscreen_new_with_texture (dst_texture);
|
||||||
|
if (!cogl_framebuffer_allocate (COGL_FRAMEBUFFER (offscreen), error))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return target_surface;
|
pipeline = cogl_pipeline_new (cogl_context);
|
||||||
}
|
|
||||||
|
|
||||||
static cairo_format_t
|
graphene_matrix_init_identity (&matrix);
|
||||||
gbm_format_to_cairo_format (uint32_t gbm_format)
|
pipeline_transform = meta_monitor_transform_invert (transform);
|
||||||
{
|
meta_monitor_transform_transform_matrix (pipeline_transform, &matrix);
|
||||||
switch (gbm_format)
|
cogl_pipeline_set_layer_texture (pipeline, 0, src_texture);
|
||||||
{
|
cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix);
|
||||||
case GBM_FORMAT_XRGB8888:
|
|
||||||
return CAIRO_FORMAT_RGB24;
|
cogl_framebuffer_clear4f (COGL_FRAMEBUFFER (offscreen),
|
||||||
default:
|
COGL_BUFFER_BIT_COLOR,
|
||||||
g_warn_if_reached ();
|
0.0f, 0.0f, 0.0f, 0.0f);
|
||||||
G_GNUC_FALLTHROUGH;
|
cogl_framebuffer_draw_textured_rectangle (COGL_FRAMEBUFFER (offscreen),
|
||||||
case GBM_FORMAT_ARGB8888:
|
pipeline,
|
||||||
return CAIRO_FORMAT_ARGB32;
|
-1.0f, -1.0f,
|
||||||
}
|
1.0f, 1.0f,
|
||||||
|
0.0f, 1.0f,
|
||||||
|
1.0f, 0.0f);
|
||||||
|
|
||||||
|
return COGL_TEXTURE (g_steal_pointer (&dst_texture));
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
@ -862,31 +841,55 @@ load_scaled_and_transformed_cursor_sprite (MetaCursorRendererNative *native,
|
|||||||
relative_transform != META_MONITOR_TRANSFORM_NORMAL ||
|
relative_transform != META_MONITOR_TRANSFORM_NORMAL ||
|
||||||
gbm_format != GBM_FORMAT_ARGB8888)
|
gbm_format != GBM_FORMAT_ARGB8888)
|
||||||
{
|
{
|
||||||
cairo_surface_t *surface;
|
const MetaFormatInfo *format_info;
|
||||||
cairo_format_t cairo_format;
|
g_autoptr (GError) error = NULL;
|
||||||
|
g_autoptr (CoglTexture) texture = NULL;
|
||||||
|
g_autofree uint8_t *cursor_data = NULL;
|
||||||
|
int bpp;
|
||||||
|
int cursor_width, cursor_height, cursor_rowstride;
|
||||||
|
|
||||||
cairo_format = gbm_format_to_cairo_format (gbm_format);
|
format_info = meta_format_info_from_drm_format (gbm_format);
|
||||||
surface = scale_and_transform_cursor_sprite_cpu (data,
|
if (!format_info)
|
||||||
cairo_format,
|
return FALSE;
|
||||||
|
|
||||||
|
texture = scale_and_transform_cursor_sprite_cpu (native,
|
||||||
|
data,
|
||||||
|
format_info->cogl_format,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
rowstride,
|
rowstride,
|
||||||
relative_scale,
|
relative_scale,
|
||||||
relative_transform);
|
relative_transform,
|
||||||
|
&error);
|
||||||
|
if (!texture)
|
||||||
|
{
|
||||||
|
g_warning ("Failed to preprocess cursor sprite: %s",
|
||||||
|
error->message);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bpp =
|
||||||
|
cogl_pixel_format_get_bytes_per_pixel (COGL_PIXEL_FORMAT_BGRA_8888_PRE,
|
||||||
|
0);
|
||||||
|
cursor_width = cogl_texture_get_width (texture);
|
||||||
|
cursor_height = cogl_texture_get_height (texture);
|
||||||
|
cursor_rowstride = cursor_width * bpp;
|
||||||
|
cursor_data = g_malloc (cursor_height * cursor_rowstride);
|
||||||
|
cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_BGRA_8888_PRE,
|
||||||
|
cursor_rowstride,
|
||||||
|
cursor_data);
|
||||||
|
|
||||||
retval =
|
retval =
|
||||||
load_cursor_sprite_gbm_buffer_for_crtc (native,
|
load_cursor_sprite_gbm_buffer_for_crtc (native,
|
||||||
crtc_kms,
|
crtc_kms,
|
||||||
cursor_sprite,
|
cursor_sprite,
|
||||||
cairo_image_surface_get_data (surface),
|
cursor_data,
|
||||||
cairo_image_surface_get_width (surface),
|
cursor_width,
|
||||||
cairo_image_surface_get_width (surface),
|
cursor_height,
|
||||||
cairo_image_surface_get_stride (surface),
|
cursor_rowstride,
|
||||||
relative_scale,
|
relative_scale,
|
||||||
relative_transform,
|
relative_transform,
|
||||||
GBM_FORMAT_ARGB8888);
|
GBM_FORMAT_ARGB8888);
|
||||||
|
|
||||||
cairo_surface_destroy (surface);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user