mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/spice
synced 2026-08-11 11:26:33 +00:00
server/red_worker: add ref counting to RedDrawable
introduces ref_red_drawable and put_red_drawable (rename from free_red_drawable) RedDrawable is already references by Drawable and RedGlzDrawable, with a hack to NULL the drawable field in RedGlzDrawable to indicate RedGlzDrawable is the last reference holder. Using an explicit reference count instead.
This commit is contained in:
parent
74ce23a0e8
commit
67671b2609
@ -24,6 +24,7 @@
|
||||
#include "red_memslots.h"
|
||||
|
||||
typedef struct RedDrawable {
|
||||
int refs;
|
||||
QXLReleaseInfo *release_info;
|
||||
uint32_t surface_id;
|
||||
uint8_t effect;
|
||||
|
||||
@ -1655,7 +1655,14 @@ static inline void set_surface_release_info(RedWorker *worker, uint32_t surface_
|
||||
}
|
||||
}
|
||||
|
||||
static inline void free_red_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id,
|
||||
static RedDrawable *ref_red_drawable(RedDrawable *drawable)
|
||||
{
|
||||
drawable->refs++;
|
||||
return drawable;
|
||||
}
|
||||
|
||||
|
||||
static inline void put_red_drawable(RedWorker *worker, RedDrawable *drawable, uint32_t group_id,
|
||||
SpiceImage *self_bitmap)
|
||||
{
|
||||
QXLReleaseInfoExt release_info_ext;
|
||||
@ -1663,6 +1670,10 @@ static inline void free_red_drawable(RedWorker *worker, RedDrawable *drawable, u
|
||||
if (self_bitmap) {
|
||||
red_put_image(self_bitmap);
|
||||
}
|
||||
if (--drawable->refs) {
|
||||
return;
|
||||
}
|
||||
|
||||
release_info_ext.group_id = group_id;
|
||||
release_info_ext.info = drawable->release_info;
|
||||
worker->qxl->st->qif->release_resource(worker->qxl, release_info_ext);
|
||||
@ -1707,7 +1718,6 @@ static void remove_drawable_dependencies(RedWorker *worker, Drawable *drawable)
|
||||
|
||||
static inline void release_drawable(RedWorker *worker, Drawable *drawable)
|
||||
{
|
||||
int glz_count = 0;
|
||||
RingItem *item, *next;
|
||||
|
||||
if (!--drawable->refs) {
|
||||
@ -1723,12 +1733,9 @@ static inline void release_drawable(RedWorker *worker, Drawable *drawable)
|
||||
RING_FOREACH_SAFE(item, next, &drawable->glz_ring) {
|
||||
SPICE_CONTAINEROF(item, RedGlzDrawable, drawable_link)->drawable = NULL;
|
||||
ring_remove(item);
|
||||
glz_count++;
|
||||
}
|
||||
if (!glz_count) { // no reference to the qxl drawable left
|
||||
free_red_drawable(worker, drawable->red_drawable,
|
||||
drawable->group_id, drawable->self_bitmap);
|
||||
}
|
||||
put_red_drawable(worker, drawable->red_drawable,
|
||||
drawable->group_id, drawable->self_bitmap);
|
||||
free_drawable(worker, drawable);
|
||||
}
|
||||
}
|
||||
@ -3638,7 +3645,7 @@ static Drawable *get_drawable(RedWorker *worker, uint8_t effect, RedDrawable *re
|
||||
drawable->tree_item.base.type = TREE_ITEM_TYPE_DRAWABLE;
|
||||
region_init(&drawable->tree_item.base.rgn);
|
||||
drawable->tree_item.effect = effect;
|
||||
drawable->red_drawable = red_drawable;
|
||||
drawable->red_drawable = ref_red_drawable(red_drawable);
|
||||
drawable->group_id = group_id;
|
||||
|
||||
drawable->surface_id = red_drawable->surface_id;
|
||||
@ -4661,6 +4668,14 @@ static int red_process_cursor(RedWorker *worker, uint32_t max_pipe_size, int *ri
|
||||
return n;
|
||||
}
|
||||
|
||||
static RedDrawable *red_drawable_new(void)
|
||||
{
|
||||
RedDrawable * red = spice_new0(RedDrawable, 1);
|
||||
|
||||
red->refs = 1;
|
||||
return red;
|
||||
}
|
||||
|
||||
static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int *ring_is_empty)
|
||||
{
|
||||
QXLCommandExt ext_cmd;
|
||||
@ -4693,11 +4708,13 @@ static int red_process_commands(RedWorker *worker, uint32_t max_pipe_size, int *
|
||||
worker->repoll_cmd_ring = 0;
|
||||
switch (ext_cmd.cmd.type) {
|
||||
case QXL_CMD_DRAW: {
|
||||
RedDrawable *drawable = spice_new0(RedDrawable, 1);
|
||||
RedDrawable *drawable = red_drawable_new(); // returns with 1 ref
|
||||
|
||||
red_get_drawable(&worker->mem_slots, ext_cmd.group_id,
|
||||
drawable, ext_cmd.cmd.data, ext_cmd.flags);
|
||||
red_process_drawable(worker, drawable, ext_cmd.group_id);
|
||||
// release the red_drawable
|
||||
put_red_drawable(worker, drawable, ext_cmd.group_id, NULL);
|
||||
break;
|
||||
}
|
||||
case QXL_CMD_UPDATE: {
|
||||
@ -5037,7 +5054,7 @@ static RedGlzDrawable *red_display_get_glz_drawable(DisplayChannelClient *dcc, D
|
||||
ret = spice_new(RedGlzDrawable, 1);
|
||||
|
||||
ret->dcc = dcc;
|
||||
ret->red_drawable = drawable->red_drawable;
|
||||
ret->red_drawable = ref_red_drawable(drawable->red_drawable);
|
||||
ret->drawable = drawable;
|
||||
ret->group_id = drawable->group_id;
|
||||
ret->self_bitmap = drawable->self_bitmap;
|
||||
@ -5105,10 +5122,9 @@ static void red_display_free_glz_drawable_instance(DisplayChannelClient *dcc,
|
||||
|
||||
if (drawable) {
|
||||
ring_remove(&glz_drawable->drawable_link);
|
||||
} else { // no reference to the qxl drawable left
|
||||
free_red_drawable(worker, glz_drawable->red_drawable,
|
||||
glz_drawable->group_id, glz_drawable->self_bitmap);
|
||||
}
|
||||
put_red_drawable(worker, glz_drawable->red_drawable,
|
||||
glz_drawable->group_id, glz_drawable->self_bitmap);
|
||||
|
||||
if (ring_item_is_linked(&glz_drawable->link)) {
|
||||
ring_remove(&glz_drawable->link);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user