summaryrefslogtreecommitdiff
path: root/src/drivers
diff options
context:
space:
mode:
authorManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-04-05 23:21:43 +0200
committerManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com>2023-04-05 23:21:43 +0200
commit0c930b9ca31a868679372528954ef5b8e6b83b33 (patch)
treedc73fb5a38ec18880a2ce01b5991791489c2ca5d /src/drivers
parent5cedb9e174dc2c60532def5c1a8ca194b36d454e (diff)
Wayland: limit copied pixels when window update is a region
Diffstat (limited to 'src/drivers')
-rw-r--r--src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H10
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H2
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx35
-rw-r--r--src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx20
4 files changed, 40 insertions, 27 deletions
diff --git a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
index c2a7d4c54..6a782c3c5 100644
--- a/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
+++ b/src/drivers/Cairo/Fl_Cairo_Graphics_Driver.H
@@ -28,12 +28,10 @@ typedef struct _PangoLayout PangoLayout;
typedef struct _PangoContext PangoContext;
typedef struct _PangoFontDescription PangoFontDescription;
-#if USE_PANGO
- struct flCairoRegion {
- int count;
- struct _cairo_rectangle *rects;
- }; // a region is the union of a series of rectangles
-#endif
+struct flCairoRegion {
+ int count;
+ struct _cairo_rectangle *rects;
+}; // a region is the union of a series of rectangles
class Fl_Cairo_Font_Descriptor : public Fl_Font_Descriptor {
public:
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
index d736df9de..5e3b13f8b 100644
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
+++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.H
@@ -78,7 +78,7 @@ public:
void copy_offscreen(int x, int y, int w, int h, Fl_Offscreen osrc, int srcx, int srcy) FL_OVERRIDE;
static struct fl_wld_buffer *create_shm_buffer(int width, int height);
static void buffer_release(struct wld_window *window);
- static void buffer_commit(struct wld_window *window, bool need_damage = true);
+ static void buffer_commit(struct wld_window *window, struct flCairoRegion *r = NULL);
static void cairo_init(struct fl_wld_buffer *buffer, int width, int height, int stride, cairo_format_t format);
void *gc() FL_OVERRIDE;
void gc(void *gc) FL_OVERRIDE;
diff --git a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
index 608a8c004..a7b3610d8 100644
--- a/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Graphics_Driver.cxx
@@ -92,15 +92,44 @@ static void surface_frame_done(void *data, struct wl_callback *cb, uint32_t time
}
-void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window, bool need_damage) {
+// copy pixels in region r from the Cairo surface to the Wayland buffer
+static void copy_region(struct wld_window *window, struct flCairoRegion *r) {
+ struct fl_wld_buffer *buffer = window->buffer;
+ float f = Fl::screen_scale(window->fl_win->screen_num()) *
+ Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale();
+ for (int i = 0; i < r->count; i++) {
+ int left = r->rects[i].x * f;
+ int top = r->rects[i].y * f;
+ int width = r->rects[i].width * f;
+ int height = r->rects[i].height * f;
+ int offset = top * buffer->stride + 4 * left;
+ int W4 = 4 * width;
+ for (int l = 0; l < height; l++) {
+ if (offset + W4 >= buffer->data_size) {
+ W4 = buffer->data_size - offset;
+ if (W4 <= 0) break;
+ }
+ memcpy((uchar*)buffer->data + offset, buffer->draw_buffer + offset, W4);
+ offset += buffer->stride;
+ }
+ wl_surface_damage_buffer(window->wl_surface, left, top, width, height);
+ }
+}
+
+
+void Fl_Wayland_Graphics_Driver::buffer_commit(struct wld_window *window,
+ struct flCairoRegion *r) {
cairo_surface_t *surf = cairo_get_target(window->buffer->cairo_);
cairo_surface_flush(surf);
- memcpy(window->buffer->data, window->buffer->draw_buffer, window->buffer->data_size);
+ if (r) copy_region(window, r);
+ else {
+ memcpy(window->buffer->data, window->buffer->draw_buffer, window->buffer->data_size);
+ wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000);
+ }
wl_surface_attach(window->wl_surface, window->buffer->wl_buffer, 0, 0);
wl_surface_set_buffer_scale(window->wl_surface,
Fl_Wayland_Window_Driver::driver(window->fl_win)->wld_scale());
window->buffer->cb = wl_surface_frame(window->wl_surface);
- if (need_damage) wl_surface_damage_buffer(window->wl_surface, 0, 0, 1000000, 1000000);
wl_callback_add_listener(window->buffer->cb, &surface_frame_listener, window);
wl_surface_commit(window->wl_surface);
window->buffer->draw_buffer_needs_commit = false;
diff --git a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
index d7031ace0..eee7892bf 100644
--- a/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
+++ b/src/drivers/Wayland/Fl_Wayland_Window_Driver.cxx
@@ -395,27 +395,13 @@ void Fl_Wayland_Window_Driver::flush() {
Fl_X *ip = Fl_X::flx(pWindow);
struct flCairoRegion* r = (struct flCairoRegion*)ip->region;
- float f = Fl::screen_scale(pWindow->screen_num()) * wld_scale();
- if (r && window->buffer) {
- for (int i = 0; i < r->count; i++) {
- int left = r->rects[i].x * f;
- int top = r->rects[i].y * f;
- int width = r->rects[i].width * f;
- int height = r->rects[i].height * f;
- wl_surface_damage_buffer(window->wl_surface, left, top, width, height);
-//fprintf(stderr, "damage %dx%d %dx%d\n", left, top, width, height);
- }
- } else {
- wl_surface_damage_buffer(window->wl_surface, 0, 0,
- pWindow->w() * f, pWindow->h() * f);
-//fprintf(stderr, "damage 0x0 %dx%d\n", pWindow->w() * f, pWindow->h() * f);
- }
+ if (!window->buffer) r = NULL;
Fl_Wayland_Window_Driver::in_flush = true;
Fl_Window_Driver::flush();
Fl_Wayland_Window_Driver::in_flush = false;
if (window->buffer->cb) wl_callback_destroy(window->buffer->cb);
- Fl_Wayland_Graphics_Driver::buffer_commit(window, false);
+ Fl_Wayland_Graphics_Driver::buffer_commit(window, r);
}
@@ -667,7 +653,7 @@ static void surface_enter(void *data, struct wl_surface *wl_surface, struct wl_o
window->fl_win->size(window->fl_win->w(), window->fl_win->h());
win_driver->is_a_rescale(false);
} else if (window->buffer) {
- Fl_Wayland_Graphics_Driver::buffer_commit(window, true);
+ Fl_Wayland_Graphics_Driver::buffer_commit(window);
}
if (window->fl_win->as_gl_window())
wl_surface_set_buffer_scale(window->wl_surface, output->wld_scale);