summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/backend.h1
-rw-r--r--src/common/surface.c22
-rw-r--r--src/platform/wayland/buffer.c4
3 files changed, 23 insertions, 4 deletions
diff --git a/src/common/backend.h b/src/common/backend.h
index e26f9d2..b111d3e 100644
--- a/src/common/backend.h
+++ b/src/common/backend.h
@@ -38,6 +38,7 @@ struct yasl_surface {
/* CPU canvas returned by yasl_cpu_pixels and copied into each drawn frame. */
uint32_t *canvas;
int canvas_width, canvas_height;
+ struct yasl_private_damage_list cpu_damage;
/* Window values last reported through public WINDOW events. */
struct yasl_private_vector2i reported_size;
uint32_t reported_scale_120, reported_state;
diff --git a/src/common/surface.c b/src/common/surface.c
index fa8ee3d..aeca3d8 100644
--- a/src/common/surface.c
+++ b/src/common/surface.c
@@ -195,8 +195,9 @@ static void draw_canvas(yasl_surface *s, struct yasl_private_frame *frame, void
if (!canvas_fit(s, w, h))
return;
memcpy(frame->target.pixels, s->canvas, (size_t)w * (size_t)h * sizeof(uint32_t));
- struct yasl_private_damage_list damage = {.n = -1};
+ struct yasl_private_damage_list damage = s->cpu_damage.n != 0 ? s->cpu_damage : (struct yasl_private_damage_list){.n = -1};
yasl_private_surface_present(s, &frame->target, &damage);
+ s->cpu_damage = (struct yasl_private_damage_list){0};
}
static void register_surface(yasl_surface *s, unsigned flags, yasl_surface *parent, void *userdata)
{
@@ -279,6 +280,7 @@ yasl_surface *yasl_surface_create(const struct yasl_surface_options *o)
.size = {o->width, o->height},
.flags = flags,
.external_gpu = o->type != YASL_SURFACE_CPU,
+ .tearing = o->tearing,
};
yasl_surface *s = o->type == YASL_SURFACE_GL ? create_gl(&spec, attrs, share)
: yasl_private_surface_create_toplevel(display, &spec);
@@ -936,7 +938,7 @@ uint32_t *yasl_cpu_pixels(yasl_surface *s, int *pw, int *ph)
*ph = s->canvas_height;
return s->canvas;
}
-int yasl_cpu_present(yasl_surface *s)
+int yasl_cpu_present_damage(yasl_surface *s, const struct yasl_damage *damage, int count)
{
if (!yasl_public_connected(s))
return -errno;
@@ -944,9 +946,25 @@ int yasl_cpu_present(yasl_surface *s)
return yasl_public_error(ENOTSUP);
if (!canvas_fit(s, s->size.x, s->size.y))
return -errno;
+ if (damage && count > 0) {
+ s->cpu_damage.n = count <= 16 ? count : 16;
+ for (int i = 0; i < s->cpu_damage.n; i++) {
+ s->cpu_damage.rects[i] = (struct yasl_private_rect2i){
+ .x = damage[i].x, .y = damage[i].y,
+ .width = damage[i].width, .height = damage[i].height,
+ };
+ }
+ } else {
+ s->cpu_damage.n = -1;
+ }
yasl_private_surface_request_frame(s);
+ yasl_private_display_flush(s->display);
return 0;
}
+int yasl_cpu_present(yasl_surface *s)
+{
+ return yasl_cpu_present_damage(s, NULL, 0);
+}
/* OpenGL; these may run on a rendering thread, so they read only immutable or atomic state. */
static bool gl_surface(yasl_surface *s)
diff --git a/src/platform/wayland/buffer.c b/src/platform/wayland/buffer.c
index b68621d..7ff4bd0 100644
--- a/src/platform/wayland/buffer.c
+++ b/src/platform/wayland/buffer.c
@@ -497,7 +497,7 @@ static void commit_buffer(struct wayland_surface *w, int idx)
wp_fifo_v1_wait_barrier(w->fifo);
wp_fifo_v1_set_barrier(w->fifo);
}
- if (w->commit_timer && w->conn->pres_clock_known) {
+ if (w->commit_timer && w->conn->pres_clock_known && w->base.presenter != YASL_PRIVATE_PRESENTER_CPU) {
uint64_t now = yasl_private_loop_now_ns();
uint64_t next = yasl_private_clock_next_present_ns(&w->clock);
bool soon = next > now && next - now < (uint64_t)(w->clock.refresh_ns * 1.5);
@@ -558,7 +558,7 @@ void surface_draw_frame(struct wayland_surface *w)
surface_fail(w);
return;
}
- if (w->closed || !w->cbs->draw || w->frame_cb || !w->want_draw)
+ if (w->closed || !w->cbs->draw || !w->want_draw)
return;
int idx = buffer_pick_free_index(w->buffers, w->cur);