aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Crisci <tony@dubstepdish.com>2017-09-24 18:24:48 -0400
committerTony Crisci <tony@dubstepdish.com>2017-09-30 08:55:40 -0400
commit86bc4840a069480cfcc71e38bc959d8133b2d7c6 (patch)
tree93fcaae1e23a29195a289105f388a52a3ddba71c
parent5cbb4f5ca036deb29f2712414d2bd054c6eec4d7 (diff)
subsurface commit and render
-rw-r--r--include/wlr/types/wlr_surface.h26
-rw-r--r--types/wlr_surface.c414
-rw-r--r--types/wlr_xdg_shell_v6.c8
3 files changed, 318 insertions, 130 deletions
diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h
index 07f19b67..c9abf042 100644
--- a/include/wlr/types/wlr_surface.h
+++ b/include/wlr/types/wlr_surface.h
@@ -18,6 +18,8 @@ struct wlr_frame_callback {
#define WLR_SURFACE_INVALID_INPUT_REGION 16
#define WLR_SURFACE_INVALID_TRANSFORM 32
#define WLR_SURFACE_INVALID_SCALE 64
+#define WLR_SURFACE_INVALID_SUBSURFACE_POSITION 128
+#define WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST 256
struct wlr_surface_state {
uint32_t invalid;
@@ -29,6 +31,12 @@ struct wlr_surface_state {
int32_t scale;
int width, height;
int buffer_width, buffer_height;
+
+ struct {
+ int32_t x, y;
+ } subsurface_position;
+
+ struct wl_list frame_callback_list; // wl_surface.frame
};
struct wlr_subsurface {
@@ -36,25 +44,19 @@ struct wlr_subsurface {
struct wlr_surface *surface;
struct wlr_surface *parent;
- struct wlr_surface_state cached;
-
- struct {
- int32_t x, y;
- } position;
-
- struct {
- int32_t x, y;
- bool set;
- } pending_position;
+ struct wlr_surface_state *cached;
+ bool has_cache;
bool synchronized;
+
+ struct wl_list parent_link;
};
struct wlr_surface {
struct wl_resource *resource;
struct wlr_renderer *renderer;
struct wlr_texture *texture;
- struct wlr_surface_state current, pending;
+ struct wlr_surface_state *current, *pending;
const char *role; // the lifetime-bound role or null
float buffer_to_surface_matrix[16];
@@ -66,13 +68,13 @@ struct wlr_surface {
struct wl_signal destroy;
} signals;
- struct wl_list frame_callback_list; // wl_surface.frame
// destroy listener used by compositor
struct wl_listener compositor_listener;
void *compositor_data;
// subsurface properties
struct wlr_subsurface *subsurface;
+ struct wl_list subsurface_list; // wlr_subsurface::parent_link
void *data;
};
diff --git a/types/wlr_surface.c b/types/wlr_surface.c
index 7ae22eaa..99e6b6dd 100644
--- a/types/wlr_surface.c
+++ b/types/wlr_surface.c
@@ -16,8 +16,9 @@ static void surface_attach(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *buffer, int32_t sx, int32_t sy) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
- surface->pending.invalid |= WLR_SURFACE_INVALID_BUFFER;
- surface->pending.buffer = buffer;
+
+ surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER;
+ surface->pending->buffer = buffer;
}
static void surface_damage(struct wl_client *client,
@@ -27,9 +28,9 @@ static void surface_damage(struct wl_client *client,
if (width < 0 || height < 0) {
return;
}
- surface->pending.invalid |= WLR_SURFACE_INVALID_SURFACE_DAMAGE;
- pixman_region32_union_rect(&surface->pending.surface_damage,
- &surface->pending.surface_damage,
+ surface->pending->invalid |= WLR_SURFACE_INVALID_SURFACE_DAMAGE;
+ pixman_region32_union_rect(&surface->pending->surface_damage,
+ &surface->pending->surface_damage,
x, y, width, height);
}
@@ -61,22 +62,24 @@ static void surface_frame(struct wl_client *client,
wl_resource_set_implementation(cb->resource,
NULL, cb, destroy_frame_callback);
- wl_list_insert(surface->frame_callback_list.prev, &cb->link);
+ wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link);
+
+ surface->pending->invalid |= WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST;
}
static void surface_set_opaque_region(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *region_resource) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
- if ((surface->pending.invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) {
- pixman_region32_clear(&surface->pending.opaque);
+ if ((surface->pending->invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) {
+ pixman_region32_clear(&surface->pending->opaque);
}
- surface->pending.invalid |= WLR_SURFACE_INVALID_OPAQUE_REGION;
+ surface->pending->invalid |= WLR_SURFACE_INVALID_OPAQUE_REGION;
if (region_resource) {
pixman_region32_t *region = wl_resource_get_user_data(region_resource);
- pixman_region32_copy(&surface->pending.opaque, region);
+ pixman_region32_copy(&surface->pending->opaque, region);
} else {
- pixman_region32_clear(&surface->pending.opaque);
+ pixman_region32_clear(&surface->pending->opaque);
}
}
@@ -84,28 +87,28 @@ static void surface_set_input_region(struct wl_client *client,
struct wl_resource *resource,
struct wl_resource *region_resource) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
- if ((surface->pending.invalid & WLR_SURFACE_INVALID_INPUT_REGION)) {
- pixman_region32_clear(&surface->pending.input);
+ if ((surface->pending->invalid & WLR_SURFACE_INVALID_INPUT_REGION)) {
+ pixman_region32_clear(&surface->pending->input);
}
- surface->pending.invalid |= WLR_SURFACE_INVALID_INPUT_REGION;
+ surface->pending->invalid |= WLR_SURFACE_INVALID_INPUT_REGION;
if (region_resource) {
pixman_region32_t *region = wl_resource_get_user_data(region_resource);
- pixman_region32_copy(&surface->pending.input, region);
+ pixman_region32_copy(&surface->pending->input, region);
} else {
- pixman_region32_init_rect(&surface->pending.input,
+ pixman_region32_init_rect(&surface->pending->input,
INT32_MIN, INT32_MIN, UINT32_MAX, UINT32_MAX);
}
}
-static void wlr_surface_update_size(struct wlr_surface *surface) {
- int scale = surface->current.scale;
- enum wl_output_transform transform = surface->current.transform;
+static void wlr_surface_update_size(struct wlr_surface *surface, struct wlr_surface_state *current) {
+ int scale = current->scale;
+ enum wl_output_transform transform = current->transform;
- wlr_texture_get_buffer_size(surface->texture, surface->current.buffer,
- &surface->current.buffer_width, &surface->current.buffer_height);
+ wlr_texture_get_buffer_size(surface->texture, current->buffer,
+ &current->buffer_width, &current->buffer_height);
- int _width = surface->current.buffer_width / scale;
- int _height = surface->current.buffer_height / scale;
+ int _width = current->buffer_width / scale;
+ int _height = current->buffer_height / scale;
if (transform == WL_OUTPUT_TRANSFORM_90 ||
transform == WL_OUTPUT_TRANSFORM_270 ||
@@ -116,17 +119,18 @@ static void wlr_surface_update_size(struct wlr_surface *surface) {
_height = tmp;
}
- surface->current.width = _width;
- surface->current.height = _height;
+ wl_list_init(&current->frame_callback_list);
+
+ current->width = _width;
+ current->height = _height;
}
-static void wlr_surface_to_buffer_region(struct wlr_surface *surface,
- pixman_region32_t *surface_region, pixman_region32_t *buffer_region,
+static void wlr_surface_to_buffer_region(int scale,
+ enum wl_output_transform transform, pixman_region32_t *surface_region,
+ pixman_region32_t *buffer_region,
int width, int height) {
pixman_box32_t *src_rects, *dest_rects;
int nrects, i;
- int scale = surface->current.scale;
- enum wl_output_transform transform = surface->current.transform;
src_rects = pixman_region32_rectangles(surface_region, &nrects);
dest_rects = malloc(nrects * sizeof(*dest_rects));
@@ -202,45 +206,129 @@ static void wlr_surface_to_buffer_region(struct wlr_surface *surface,
free(dest_rects);
}
+/**
+ * Append pending state to current state and clear pending state.
+ */
+static void wlr_surface_move_state(struct wlr_surface *surface, struct wlr_surface_state *pending,
+ struct wlr_surface_state *current) {
+ bool update_damage = false;
+ bool update_size = false;
+
+ if ((pending->invalid & WLR_SURFACE_INVALID_SCALE)) {
+ current->scale = pending->scale;
+ update_size = true;
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_TRANSFORM)) {
+ current->transform = pending->transform;
+ update_size = true;
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_BUFFER)) {
+ if (current->buffer) {
+ wl_resource_post_event(current->buffer, WL_BUFFER_RELEASE);
+ }
+
+ current->buffer = pending->buffer;
+ pending->buffer = NULL;
+ update_size = true;
+ }
+ if (update_size) {
+ wlr_surface_update_size(surface, current);
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) {
+ pixman_region32_union(&current->surface_damage,
+ &current->surface_damage,
+ &pending->surface_damage);
+ pixman_region32_intersect_rect(&current->surface_damage,
+ &current->surface_damage, 0, 0, current->width,
+ current->height);
+
+ pixman_region32_clear(&pending->surface_damage);
+ update_damage = true;
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_BUFFER_DAMAGE)) {
+ pixman_region32_union(&current->buffer_damage,
+ &current->buffer_damage,
+ &pending->buffer_damage);
+
+ pixman_region32_clear(&pending->buffer_damage);
+ update_damage = true;
+ }
+ if (update_damage) {
+ pixman_region32_t buffer_damage;
+ pixman_region32_init(&buffer_damage);
+ wlr_surface_to_buffer_region(current->scale, current->transform,
+ &current->surface_damage, &buffer_damage, current->width,
+ current->height);
+ pixman_region32_union(&current->buffer_damage,
+ &current->buffer_damage, &buffer_damage);
+ pixman_region32_fini(&buffer_damage);
+
+ pixman_region32_intersect_rect(&current->buffer_damage,
+ &current->buffer_damage, 0, 0,
+ current->buffer_width, current->buffer_height);
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) {
+ // TODO: process buffer
+ pixman_region32_clear(&pending->opaque);
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_INPUT_REGION)) {
+ // TODO: process buffer
+ pixman_region32_clear(&pending->input);
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_SUBSURFACE_POSITION)) {
+ current->subsurface_position.x = pending->subsurface_position.x;
+ current->subsurface_position.y = pending->subsurface_position.y;
+ pending->subsurface_position.x = 0;
+ pending->subsurface_position.y = 0;
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST)) {
+ wl_list_insert_list(&current->frame_callback_list, &pending->frame_callback_list);
+ wl_list_init(&pending->frame_callback_list);
+ }
+
+ current->invalid |= pending->invalid;
+ pending->invalid = 0;
+}
+
static void wlr_surface_commit_state(struct wlr_surface *surface,
struct wlr_surface_state *pending) {
bool update_size = false;
bool update_damage = false;
if ((pending->invalid & WLR_SURFACE_INVALID_SCALE)) {
- surface->current.scale = pending->scale;
+ surface->current->scale = pending->scale;
update_size = true;
}
if ((pending->invalid & WLR_SURFACE_INVALID_TRANSFORM)) {
- surface->current.transform = pending->transform;
+ surface->current->transform = pending->transform;
update_size = true;
}
if ((pending->invalid & WLR_SURFACE_INVALID_BUFFER)) {
- surface->current.buffer = pending->buffer;
+ surface->current->buffer = pending->buffer;
update_size = true;
}
if (update_size) {
- int32_t oldw = surface->current.buffer_width;
- int32_t oldh = surface->current.buffer_height;
- wlr_surface_update_size(surface);
+ int32_t oldw = surface->current->buffer_width;
+ int32_t oldh = surface->current->buffer_height;
+ wlr_surface_update_size(surface, surface->current);
- surface->reupload_buffer = oldw != surface->current.buffer_width ||
- oldh != surface->current.buffer_height;
+ surface->reupload_buffer = oldw != surface->current->buffer_width ||
+ oldh != surface->current->buffer_height;
}
if ((pending->invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) {
- pixman_region32_union(&surface->current.surface_damage,
- &surface->current.surface_damage,
+ pixman_region32_union(&surface->current->surface_damage,
+ &surface->current->surface_damage,
&pending->surface_damage);
- pixman_region32_intersect_rect(&surface->current.surface_damage,
- &surface->current.surface_damage, 0, 0, surface->current.width,
- surface->current.height);
+ pixman_region32_intersect_rect(&surface->current->surface_damage,
+ &surface->current->surface_damage, 0, 0, surface->current->width,
+ surface->current->height);
pixman_region32_clear(&pending->surface_damage);
update_damage = true;
}
if ((pending->invalid & WLR_SURFACE_INVALID_BUFFER_DAMAGE)) {
- pixman_region32_union(&surface->current.buffer_damage,
- &surface->current.buffer_damage,
+ pixman_region32_union(&surface->current->buffer_damage,
+ &surface->current->buffer_damage,
&pending->buffer_damage);
pixman_region32_clear(&pending->buffer_damage);
@@ -249,15 +337,16 @@ static void wlr_surface_commit_state(struct wlr_surface *surface,
if (update_damage) {
pixman_region32_t buffer_damage;
pixman_region32_init(&buffer_damage);
- wlr_surface_to_buffer_region(surface, &surface->current.surface_damage,
- &buffer_damage, surface->current.width, surface->current.height);
- pixman_region32_union(&surface->current.buffer_damage,
- &surface->current.buffer_damage, &buffer_damage);
+ wlr_surface_to_buffer_region(surface->current->scale,
+ surface->current->transform, &surface->current->surface_damage,
+ &buffer_damage, surface->current->width, surface->current->height);
+ pixman_region32_union(&surface->current->buffer_damage,
+ &surface->current->buffer_damage, &buffer_damage);
pixman_region32_fini(&buffer_damage);
- pixman_region32_intersect_rect(&surface->current.buffer_damage,
- &surface->current.buffer_damage, 0, 0,
- surface->current.buffer_width, surface->current.buffer_height);
+ pixman_region32_intersect_rect(&surface->current->buffer_damage,
+ &surface->current->buffer_damage, 0, 0,
+ surface->current->buffer_width, surface->current->buffer_height);
}
if ((pending->invalid & WLR_SURFACE_INVALID_OPAQUE_REGION)) {
// TODO: process buffer
@@ -267,31 +356,114 @@ static void wlr_surface_commit_state(struct wlr_surface *surface,
// TODO: process buffer
pixman_region32_clear(&pending->input);
}
+ if ((pending->invalid & WLR_SURFACE_INVALID_SUBSURFACE_POSITION)) {
+ surface->current->subsurface_position.x = pending->subsurface_position.x;
+ surface->current->subsurface_position.y = pending->subsurface_position.y;
+ }
+ if ((pending->invalid & WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST)) {
+ wl_list_insert_list(&surface->current->frame_callback_list, &pending->frame_callback_list);
+ wl_list_init(&pending->frame_callback_list);
+ }
pending->invalid = 0;
// TODO: add the invalid bitfield to this callback
wl_signal_emit(&surface->signals.commit, surface);
}
+static bool wlr_subsurface_is_synchronized(struct wlr_subsurface *subsurface) {
+ while (subsurface) {
+ if (subsurface->synchronized) {
+ return true;
+ }
+
+ if (!subsurface->parent) {
+ return false;
+ }
+
+ subsurface = subsurface->parent->subsurface;
+ }
+
+ return false;
+}
+
+/**
+ * Recursive function to commit the effectively synchronized children.
+ */
+static void wlr_subsurface_parent_commit(struct wlr_subsurface *subsurface,
+ bool synchronized) {
+ struct wlr_surface *surface = subsurface->surface;
+ if (synchronized || subsurface->synchronized) {
+
+ if (subsurface->has_cache) {
+ wlr_surface_move_state(surface, subsurface->cached, surface->pending);
+ wlr_surface_flush_damage(surface);
+ wlr_surface_commit_state(surface, surface->pending);
+ subsurface->has_cache = false;
+ subsurface->cached->invalid = 0;
+ }
+
+ struct wlr_subsurface *tmp;
+ wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
+ wlr_subsurface_parent_commit(tmp, true);
+ }
+ }
+}
+
+static void wlr_subsurface_commit(struct wlr_subsurface *subsurface) {
+ struct wlr_surface *surface = subsurface->surface;
+
+ if (wlr_subsurface_is_synchronized(subsurface)) {
+ wlr_surface_move_state(surface, surface->pending, subsurface->cached);
+ subsurface->has_cache = true;
+ } else {
+ if (subsurface->has_cache) {
+ wlr_surface_move_state(surface, subsurface->cached, surface->pending);
+ wlr_surface_commit_state(surface, surface->pending);
+ wlr_surface_flush_damage(surface);
+ subsurface->has_cache = false;
+
+ } else {
+ wlr_surface_commit_state(surface, surface->pending);
+ }
+
+ struct wlr_subsurface *tmp;
+ wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
+ wlr_subsurface_parent_commit(tmp, false);
+ }
+ }
+
+}
+
static void surface_commit(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
+ struct wlr_subsurface *subsurface = surface->subsurface;
- wlr_surface_commit_state(surface, &surface->pending);
+ if (subsurface) {
+ wlr_subsurface_commit(subsurface);
+ return;
+ }
+
+ wlr_surface_commit_state(surface, surface->pending);
+
+ struct wlr_subsurface *tmp;
+ wl_list_for_each(tmp, &surface->subsurface_list, parent_link) {
+ wlr_subsurface_parent_commit(tmp, false);
+ }
}
void wlr_surface_flush_damage(struct wlr_surface *surface) {
- if (!surface->current.buffer) {
+ if (!surface->current->buffer) {
if (surface->texture->valid) {
// TODO: Detach buffers
}
return;
}
- struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current.buffer);
+ struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current->buffer);
if (!buffer) {
if (wlr_renderer_buffer_is_drm(surface->renderer,
- surface->pending.buffer)) {
- wlr_texture_upload_drm(surface->texture, surface->pending.buffer);
+ surface->pending->buffer)) {
+ wlr_texture_upload_drm(surface->texture, surface->pending->buffer);
goto release;
} else {
wlr_log(L_INFO, "Unknown buffer handle attached");
@@ -303,7 +475,7 @@ void wlr_surface_flush_damage(struct wlr_surface *surface) {
if (surface->reupload_buffer) {
wlr_texture_upload_shm(surface->texture, format, buffer);
} else {
- pixman_region32_t damage = surface->current.buffer_damage;
+ pixman_region32_t damage = surface->current->buffer_damage;
if (!pixman_region32_not_empty(&damage)) {
goto release;
}
@@ -322,26 +494,26 @@ void wlr_surface_flush_damage(struct wlr_surface *surface) {
}
release:
- pixman_region32_clear(&surface->current.surface_damage);
- pixman_region32_clear(&surface->current.buffer_damage);
+ pixman_region32_clear(&surface->current->surface_damage);
+ pixman_region32_clear(&surface->current->buffer_damage);
- wl_resource_post_event(surface->current.buffer, WL_BUFFER_RELEASE);
- surface->current.buffer = NULL;
+ wl_resource_post_event(surface->current->buffer, WL_BUFFER_RELEASE);
+ surface->current->buffer = NULL;
}
static void surface_set_buffer_transform(struct wl_client *client,
struct wl_resource *resource, int transform) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
- surface->pending.invalid |= WLR_SURFACE_INVALID_TRANSFORM;
- surface->pending.transform = transform;
+ surface->pending->invalid |= WLR_SURFACE_INVALID_TRANSFORM;
+ surface->pending->transform = transform;
}
static void surface_set_buffer_scale(struct wl_client *client,
struct wl_resource *resource,
int32_t scale) {
struct wlr_surface *surface = wl_resource_get_user_data(resource);
- surface->pending.invalid |= WLR_SURFACE_INVALID_SCALE;
- surface->pending.scale = scale;
+ surface->pending->invalid |= WLR_SURFACE_INVALID_SCALE;
+ surface->pending->scale = scale;
}
static void surface_damage_buffer(struct wl_client *client,
@@ -352,9 +524,9 @@ static void surface_damage_buffer(struct wl_client *client,
if (width < 0 || height < 0) {
return;
}
- surface->pending.invalid |= WLR_SURFACE_INVALID_BUFFER_DAMAGE;
- pixman_region32_union_rect(&surface->pending.buffer_damage,
- &surface->pending.buffer_damage,
+ surface->pending->invalid |= WLR_SURFACE_INVALID_BUFFER_DAMAGE;
+ pixman_region32_union_rect(&surface->pending->buffer_damage,
+ &surface->pending->buffer_damage,
x, y, width, height);
}
@@ -371,31 +543,58 @@ const struct wl_surface_interface surface_interface = {
.damage_buffer = surface_damage_buffer
};
-static void destroy_surface(struct wl_resource *resource) {
- struct wlr_surface *surface = wl_resource_get_user_data(resource);
- wl_signal_emit(&surface->signals.destroy, surface);
-
- wlr_texture_destroy(surface->texture);
- struct wlr_frame_callback *cb, *next;
- wl_list_for_each_safe(cb, next, &surface->frame_callback_list, link) {
- wl_resource_destroy(cb->resource);
- }
- pixman_region32_fini(&surface->pending.surface_damage);
- pixman_region32_fini(&surface->pending.buffer_damage);
- pixman_region32_fini(&surface->pending.opaque);
- pixman_region32_fini(&surface->pending.input);
-
- free(surface);
-}
-
-void wlr_surface_state_init(struct wlr_surface_state *state) {
+static struct wlr_surface_state *wlr_surface_state_create() {
+ struct wlr_surface_state *state = calloc(1, sizeof(struct wlr_surface_state));
state->scale = 1;
state->transform = WL_OUTPUT_TRANSFORM_NORMAL;
+ wl_list_init(&state->frame_callback_list);
+
pixman_region32_init(&state->surface_damage);
pixman_region32_init(&state->buffer_damage);
pixman_region32_init(&state->opaque);
pixman_region32_init(&state->input);
+
+ return state;
+}
+
+static void wlr_surface_state_destroy(struct wlr_surface_state *current) {
+ struct wlr_frame_callback *cb, *tmp;
+ wl_list_for_each_safe(cb, tmp, &current->frame_callback_list, link) {
+ wl_resource_destroy(cb->resource);
+ }
+
+ pixman_region32_fini(&current->surface_damage);
+ pixman_region32_fini(&current->buffer_damage);
+ pixman_region32_fini(&current->opaque);
+ pixman_region32_fini(&current->input);
+
+ free(current);
+}
+
+void wlr_subsurface_destroy(struct wlr_subsurface *subsurface) {
+ wlr_surface_state_destroy(subsurface->cached);
+ wl_list_remove(&subsurface->parent_link);
+ wl_resource_set_user_data(subsurface->resource, NULL);
+ if (subsurface->surface) {
+ subsurface->surface->subsurface = NULL;
+ }
+ free(subsurface);
+}
+
+static void destroy_surface(struct wl_resource *resource) {
+ struct wlr_surface *surface = wl_resource_get_user_data(resource);
+ wl_signal_emit(&surface->signals.destroy, surface);
+
+ if (surface->subsurface) {
+ wlr_subsurface_destroy(surface->subsurface);
+ }
+
+ wlr_texture_destroy(surface->texture);
+ wlr_surface_state_destroy(surface->pending);
+ wlr_surface_state_destroy(surface->current);
+
+ free(surface);
}
struct wlr_surface *wlr_surface_create(struct wl_resource *res,
@@ -410,12 +609,12 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
surface->texture = wlr_render_texture_create(renderer);
surface->resource = res;
- wlr_surface_state_init(&surface->current);
- wlr_surface_state_init(&surface->pending);
+ surface->current = wlr_surface_state_create();
+ surface->pending = wlr_surface_state_create();
wl_signal_init(&surface->signals.commit);
wl_signal_init(&surface->signals.destroy);
- wl_list_init(&surface->frame_callback_list);
+ wl_list_init(&surface->subsurface_list);
wl_resource_set_implementation(res, &surface_interface,
surface, destroy_surface);
return surface;
@@ -425,8 +624,8 @@ void wlr_surface_get_matrix(struct wlr_surface *surface,
float (*matrix)[16],
const float (*projection)[16],
const float (*transform)[16]) {
- int width = surface->texture->width / surface->current.scale;
- int height = surface->texture->height / surface->current.scale;
+ int width = surface->texture->width / surface->current->scale;
+ int height = surface->texture->height / surface->current->scale;
float scale[16];
wlr_matrix_identity(matrix);
if (transform) {
@@ -458,26 +657,6 @@ int wlr_surface_set_role(struct wlr_surface *surface, const char *role,
return -1;
}
-void wlr_subsurface_destroy(struct wlr_subsurface *subsurface) {
- wlr_log(L_DEBUG, "TODO: wlr subsurface destroy");
-}
-
-static bool wlr_subsurface_is_synchronized(struct wlr_subsurface *subsurface) {
- while (subsurface) {
- if (subsurface->synchronized) {
- return true;
- }
-
- if (!subsurface->parent) {
- return false;
- }
-
- subsurface = subsurface->parent->subsurface;
- }
-
- return false;
-}
-
static void subsurface_resource_destroy(struct wl_resource *resource) {
struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
@@ -494,9 +673,12 @@ static void subsurface_destroy(struct wl_client *client,
static void subsurface_set_position(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_subsurface *subsurface = wl_resource_get_user_data(resource);
- subsurface->pending_position.set = true;
- subsurface->pending_position.x = x;
- subsurface->pending_position.y = y;
+ struct wlr_surface *surface = subsurface->surface;
+
+ surface->pending->invalid |= WLR_SURFACE_INVALID_SUBSURFACE_POSITION;
+
+ surface->pending->subsurface_position.x = x;
+ surface->pending->subsurface_position.y = y;
}
static void subsurface_place_above(struct wl_client *client,
@@ -527,6 +709,7 @@ static void subsurface_set_desync(struct wl_client *client,
if (!wlr_subsurface_is_synchronized(subsurface)) {
// TODO: do a synchronized commit to flush the cache
+ wlr_subsurface_parent_commit(subsurface, true);
}
}
}
@@ -549,9 +732,12 @@ void wlr_surface_make_subsurface(struct wlr_surface *surface,
if (!subsurface) {
return;
}
+ subsurface->cached = wlr_surface_state_create();
subsurface->surface = surface;
subsurface->parent = parent;
+ subsurface->synchronized = true;
+ wl_list_insert(&parent->subsurface_list, &subsurface->parent_link);
struct wl_client *client = wl_resource_get_client(surface->resource);
diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c
index a7450add..9f623420 100644
--- a/types/wlr_xdg_shell_v6.c
+++ b/types/wlr_xdg_shell_v6.c
@@ -496,7 +496,7 @@ static void wlr_xdg_surface_v6_toplevel_committed(
struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- if (!surface->surface->current.buffer && !surface->toplevel_state->added) {
+ if (!surface->surface->current->buffer && !surface->toplevel_state->added) {
// on the first commit, send a configure request to tell the client it
// is added
wlr_xdg_surface_v6_schedule_configure(surface, true);
@@ -504,7 +504,7 @@ static void wlr_xdg_surface_v6_toplevel_committed(
return;
}
- if (!surface->surface->current.buffer) {
+ if (!surface->surface->current->buffer) {
return;
}
@@ -516,7 +516,7 @@ static void handle_wlr_surface_committed(struct wl_listener *listener,
struct wlr_xdg_surface_v6 *surface =
wl_container_of(listener, surface, surface_commit_listener);
- if (surface->surface->current.buffer && !surface->configured) {
+ if (surface->surface->current->buffer && !surface->configured) {
wl_resource_post_error(surface->resource,
ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
"xdg_surface has never been configured");
@@ -580,7 +580,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
&zxdg_surface_v6_interface, wl_resource_get_version(client_resource),
id);
- if (surface->surface->current.buffer != NULL) {
+ if (surface->surface->current->buffer != NULL) {
wl_resource_post_error(surface->resource,
ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
"xdg_surface must not have a buffer at creation");