implement buffer scale
Keep track of the scale of the buffer set by surface.set_buffer_scale. Calculate the height and width of the texture from the buffer depending on the scale when it is attached. Use buffer damage to determine the damage of the buffer when flushing damage. Convert surface damage to buffer damage and union to the surface buffer_damage prior to flushing damage.
This commit is contained in:
parent
e22e443717
commit
f0f190bfa5
|
@ -61,6 +61,7 @@ struct wlr_texture {
|
||||||
bool valid;
|
bool valid;
|
||||||
uint32_t format;
|
uint32_t format;
|
||||||
int width, height;
|
int width, height;
|
||||||
|
int height_from_buffer, width_from_buffer;
|
||||||
struct wl_signal destroy_signal;
|
struct wl_signal destroy_signal;
|
||||||
struct wl_resource *resource;
|
struct wl_resource *resource;
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,8 +14,11 @@ static void surface_attach(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
struct wl_resource *buffer, int32_t sx, int32_t sy) {
|
struct wl_resource *buffer, int32_t sx, int32_t sy) {
|
||||||
struct wlr_surface *surface = wl_resource_get_user_data(resource);
|
struct wlr_surface *surface = wl_resource_get_user_data(resource);
|
||||||
|
int scale = surface->current.scale;
|
||||||
surface->pending.invalid |= WLR_SURFACE_INVALID_BUFFER;
|
surface->pending.invalid |= WLR_SURFACE_INVALID_BUFFER;
|
||||||
surface->pending.buffer = buffer;
|
surface->pending.buffer = buffer;
|
||||||
|
surface->texture->height_from_buffer = surface->texture->height / scale;
|
||||||
|
surface->texture->width_from_buffer = surface->texture->width / scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_damage(struct wl_client *client,
|
static void surface_damage(struct wl_client *client,
|
||||||
|
@ -90,18 +93,59 @@ static void surface_set_input_region(struct wl_client *client,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void wlr_surface_to_buffer_region(struct wlr_surface *surface,
|
||||||
|
pixman_region32_t *surface_region, pixman_region32_t *buffer_region) {
|
||||||
|
pixman_box32_t *src_rects, *dest_rects;
|
||||||
|
int nrects, i;
|
||||||
|
int scale = surface->current.scale;
|
||||||
|
|
||||||
|
src_rects = pixman_region32_rectangles(surface_region, &nrects);
|
||||||
|
dest_rects = malloc(nrects * sizeof(*dest_rects));
|
||||||
|
if (!dest_rects) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < nrects; i++) {
|
||||||
|
dest_rects[i].x1 = src_rects[i].x1 * scale;
|
||||||
|
dest_rects[i].y1 = src_rects[i].y1 * scale;
|
||||||
|
dest_rects[i].x2 = src_rects[i].x2 * scale;
|
||||||
|
dest_rects[i].y2 = src_rects[i].y2 * scale;
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_fini(buffer_region);
|
||||||
|
pixman_region32_init_rects(buffer_region, dest_rects, nrects);
|
||||||
|
free(dest_rects);
|
||||||
|
}
|
||||||
|
|
||||||
static void surface_commit(struct wl_client *client,
|
static void surface_commit(struct wl_client *client,
|
||||||
struct wl_resource *resource) {
|
struct wl_resource *resource) {
|
||||||
struct wlr_surface *surface = wl_resource_get_user_data(resource);
|
struct wlr_surface *surface = wl_resource_get_user_data(resource);
|
||||||
|
surface->current.scale = surface->pending.scale;
|
||||||
|
|
||||||
if ((surface->pending.invalid & WLR_SURFACE_INVALID_BUFFER)) {
|
if ((surface->pending.invalid & WLR_SURFACE_INVALID_BUFFER)) {
|
||||||
surface->current.buffer = surface->pending.buffer;
|
surface->current.buffer = surface->pending.buffer;
|
||||||
}
|
}
|
||||||
if ((surface->pending.invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) {
|
if ((surface->pending.invalid & WLR_SURFACE_INVALID_SURFACE_DAMAGE)) {
|
||||||
// TODO: Sort out buffer damage too
|
|
||||||
pixman_region32_union(&surface->current.surface_damage,
|
pixman_region32_union(&surface->current.surface_damage,
|
||||||
&surface->current.surface_damage,
|
&surface->current.surface_damage,
|
||||||
&surface->pending.surface_damage);
|
&surface->pending.surface_damage);
|
||||||
|
|
||||||
|
pixman_region32_union(&surface->current.buffer_damage,
|
||||||
|
&surface->current.buffer_damage,
|
||||||
|
&surface->pending.buffer_damage);
|
||||||
|
|
||||||
|
pixman_region32_t buffer_damage;
|
||||||
|
wlr_surface_to_buffer_region(surface, &surface->current.surface_damage,
|
||||||
|
&buffer_damage);
|
||||||
|
pixman_region32_union(&surface->current.buffer_damage,
|
||||||
|
&surface->current.buffer_damage, &buffer_damage);
|
||||||
|
|
||||||
|
struct wl_shm_buffer *buffer = wl_shm_buffer_get(surface->current.buffer);
|
||||||
|
pixman_region32_intersect_rect(&surface->current.buffer_damage,
|
||||||
|
&surface->current.buffer_damage, 0, 0,
|
||||||
|
wl_shm_buffer_get_width(buffer),
|
||||||
|
wl_shm_buffer_get_height(buffer));
|
||||||
|
|
||||||
// TODO: Surface sizing is complicated
|
// TODO: Surface sizing is complicated
|
||||||
//pixman_region32_intersect_rect(&surface->current.surface_damage,
|
//pixman_region32_intersect_rect(&surface->current.surface_damage,
|
||||||
// &surface->current.surface_damage,
|
// &surface->current.surface_damage,
|
||||||
|
@ -133,7 +177,7 @@ void wlr_surface_flush_damage(struct wlr_surface *surface) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pixman_region32_t damage = surface->current.surface_damage;
|
pixman_region32_t damage = surface->current.buffer_damage;
|
||||||
if (!pixman_region32_not_empty(&damage)) {
|
if (!pixman_region32_not_empty(&damage)) {
|
||||||
goto release;
|
goto release;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +211,8 @@ static void surface_set_buffer_transform(struct wl_client *client,
|
||||||
static void surface_set_buffer_scale(struct wl_client *client,
|
static void surface_set_buffer_scale(struct wl_client *client,
|
||||||
struct wl_resource *resource,
|
struct wl_resource *resource,
|
||||||
int32_t scale) {
|
int32_t scale) {
|
||||||
wlr_log(L_DEBUG, "TODO: surface set buffer scale");
|
struct wlr_surface *surface = wl_resource_get_user_data(resource);
|
||||||
|
surface->pending.scale = scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void surface_damage_buffer(struct wl_client *client,
|
static void surface_damage_buffer(struct wl_client *client,
|
||||||
|
@ -215,6 +260,8 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
|
||||||
surface->renderer = renderer;
|
surface->renderer = renderer;
|
||||||
surface->texture = wlr_render_texture_init(renderer);
|
surface->texture = wlr_render_texture_init(renderer);
|
||||||
surface->resource = res;
|
surface->resource = res;
|
||||||
|
surface->current.scale = 1;
|
||||||
|
surface->pending.scale = 1;
|
||||||
wl_signal_init(&surface->signals.commit);
|
wl_signal_init(&surface->signals.commit);
|
||||||
wl_list_init(&surface->frame_callback_list);
|
wl_list_init(&surface->frame_callback_list);
|
||||||
wl_resource_set_implementation(res, &surface_interface,
|
wl_resource_set_implementation(res, &surface_interface,
|
||||||
|
|
Loading…
Reference in New Issue