|
|
|
@ -26,9 +26,6 @@ |
|
|
|
#include "qapi/error.h" |
|
|
|
#include "sysemu/sysemu.h" |
|
|
|
#include "dbus.h" |
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
#include <pixman.h> |
|
|
|
#endif |
|
|
|
#ifdef G_OS_UNIX |
|
|
|
#include <gio/gunixfdlist.h> |
|
|
|
#endif |
|
|
|
@ -41,6 +38,7 @@ |
|
|
|
#include "ui/shader.h" |
|
|
|
#include "ui/egl-helpers.h" |
|
|
|
#include "ui/egl-context.h" |
|
|
|
#include "ui/qemu-pixman.h" |
|
|
|
#endif |
|
|
|
#include "trace.h" |
|
|
|
|
|
|
|
@ -62,9 +60,11 @@ struct _DBusDisplayListener { |
|
|
|
|
|
|
|
QemuDBusDisplay1Listener *proxy; |
|
|
|
|
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
/* Keep track of the damage region */ |
|
|
|
pixman_region32_t gl_damage; |
|
|
|
#else |
|
|
|
int gl_damage; |
|
|
|
#endif |
|
|
|
|
|
|
|
DisplayChangeListener dcl; |
|
|
|
@ -545,6 +545,7 @@ static void dbus_gl_refresh(DisplayChangeListener *dcl) |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
int n_rects = pixman_region32_n_rects(&ddl->gl_damage); |
|
|
|
|
|
|
|
for (int i = 0; i < n_rects; i++) { |
|
|
|
@ -555,6 +556,13 @@ static void dbus_gl_refresh(DisplayChangeListener *dcl) |
|
|
|
box->x2 - box->x1, box->y2 - box->y1); |
|
|
|
} |
|
|
|
pixman_region32_clear(&ddl->gl_damage); |
|
|
|
#else |
|
|
|
if (ddl->gl_damage) { |
|
|
|
dbus_call_update_gl(dcl, 0, 0, |
|
|
|
surface_width(ddl->ds), surface_height(ddl->ds)); |
|
|
|
ddl->gl_damage = 0; |
|
|
|
} |
|
|
|
#endif |
|
|
|
} |
|
|
|
#endif /* OPENGL */ |
|
|
|
|
|
|
|
@ -569,20 +577,64 @@ static void dbus_gl_gfx_update(DisplayChangeListener *dcl, |
|
|
|
{ |
|
|
|
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); |
|
|
|
|
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
pixman_region32_t rect_region; |
|
|
|
pixman_region32_init_rect(&rect_region, x, y, w, h); |
|
|
|
pixman_region32_union(&ddl->gl_damage, &ddl->gl_damage, &rect_region); |
|
|
|
pixman_region32_fini(&rect_region); |
|
|
|
#else |
|
|
|
ddl->gl_damage++; |
|
|
|
#endif |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
static void dbus_gfx_update_sub(DBusDisplayListener *ddl, |
|
|
|
int x, int y, int w, int h) |
|
|
|
{ |
|
|
|
pixman_image_t *img; |
|
|
|
size_t stride; |
|
|
|
GVariant *v_data; |
|
|
|
|
|
|
|
/* make a copy, since gvariant only handles linear data */ |
|
|
|
stride = w * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(surface_format(ddl->ds)), 8); |
|
|
|
img = pixman_image_create_bits(surface_format(ddl->ds), |
|
|
|
w, h, NULL, stride); |
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
pixman_image_composite(PIXMAN_OP_SRC, ddl->ds->image, NULL, img, |
|
|
|
x, y, 0, 0, 0, 0, w, h); |
|
|
|
#else |
|
|
|
{ |
|
|
|
uint8_t *src = (uint8_t *)pixman_image_get_data(ddl->ds->image); |
|
|
|
uint8_t *dst = (uint8_t *)pixman_image_get_data(img); |
|
|
|
int bp = PIXMAN_FORMAT_BPP(surface_format(ddl->ds)) / 8; |
|
|
|
int hh; |
|
|
|
|
|
|
|
for (hh = 0; hh < h; hh++) { |
|
|
|
memcpy(&dst[stride * hh], |
|
|
|
&src[surface_stride(ddl->ds) * (hh + y) + x * bp], |
|
|
|
stride); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
v_data = g_variant_new_from_data( |
|
|
|
G_VARIANT_TYPE("ay"), |
|
|
|
pixman_image_get_data(img), |
|
|
|
pixman_image_get_stride(img) * h, |
|
|
|
TRUE, |
|
|
|
(GDestroyNotify)pixman_image_unref, |
|
|
|
img); |
|
|
|
qemu_dbus_display1_listener_call_update(ddl->proxy, |
|
|
|
x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img), |
|
|
|
v_data, |
|
|
|
G_DBUS_CALL_FLAGS_NONE, |
|
|
|
DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL); |
|
|
|
} |
|
|
|
|
|
|
|
static void dbus_gfx_update(DisplayChangeListener *dcl, |
|
|
|
int x, int y, int w, int h) |
|
|
|
{ |
|
|
|
DBusDisplayListener *ddl = container_of(dcl, DBusDisplayListener, dcl); |
|
|
|
pixman_image_t *img; |
|
|
|
GVariant *v_data; |
|
|
|
size_t stride; |
|
|
|
|
|
|
|
assert(ddl->ds); |
|
|
|
|
|
|
|
@ -619,25 +671,7 @@ static void dbus_gfx_update(DisplayChangeListener *dcl, |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
/* make a copy, since gvariant only handles linear data */ |
|
|
|
stride = w * DIV_ROUND_UP(PIXMAN_FORMAT_BPP(surface_format(ddl->ds)), 8); |
|
|
|
img = pixman_image_create_bits(surface_format(ddl->ds), |
|
|
|
w, h, NULL, stride); |
|
|
|
pixman_image_composite(PIXMAN_OP_SRC, ddl->ds->image, NULL, img, |
|
|
|
x, y, 0, 0, 0, 0, w, h); |
|
|
|
|
|
|
|
v_data = g_variant_new_from_data( |
|
|
|
G_VARIANT_TYPE("ay"), |
|
|
|
pixman_image_get_data(img), |
|
|
|
pixman_image_get_stride(img) * h, |
|
|
|
TRUE, |
|
|
|
(GDestroyNotify)pixman_image_unref, |
|
|
|
img); |
|
|
|
qemu_dbus_display1_listener_call_update(ddl->proxy, |
|
|
|
x, y, w, h, pixman_image_get_stride(img), pixman_image_get_format(img), |
|
|
|
v_data, |
|
|
|
G_DBUS_CALL_FLAGS_NONE, |
|
|
|
DBUS_DEFAULT_TIMEOUT, NULL, NULL, NULL); |
|
|
|
dbus_gfx_update_sub(ddl, x, y, w, h); |
|
|
|
} |
|
|
|
|
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
@ -751,8 +785,10 @@ dbus_display_listener_dispose(GObject *object) |
|
|
|
g_clear_object(&ddl->map_proxy); |
|
|
|
g_clear_object(&ddl->d3d11_proxy); |
|
|
|
g_clear_pointer(&ddl->peer_process, CloseHandle); |
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
pixman_region32_fini(&ddl->gl_damage); |
|
|
|
#endif |
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
egl_fb_destroy(&ddl->fb); |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
@ -787,7 +823,7 @@ dbus_display_listener_class_init(DBusDisplayListenerClass *klass) |
|
|
|
static void |
|
|
|
dbus_display_listener_init(DBusDisplayListener *ddl) |
|
|
|
{ |
|
|
|
#ifdef CONFIG_OPENGL |
|
|
|
#ifdef CONFIG_PIXMAN |
|
|
|
pixman_region32_init(&ddl->gl_damage); |
|
|
|
#endif |
|
|
|
} |
|
|
|
|