summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrendan Shanks <bshanks@codeweavers.com>2019-11-01 12:22:53 -0700
committerFrediano Ziglio <freddy77@gmail.com>2020-04-28 09:07:35 +0100
commit97517317bdc39899214cb988f5d3f4ad260f6ac3 (patch)
treec521972942bab59d4cfe2dabaa46aa2bd27ec16c
parent46635721179839e3d3194c4c971e479333782a62 (diff)
Add full-screen scan triggered by constant, untrusted damage reports
This goes further than commit cb122392 by forcing a whole screen scan, looking for changes. This improves the feel of using a session with mutter, which is quite noticeable in a terminal window. Acked-by: Frediano Ziglio <fziglio@redhat.com>
-rw-r--r--src/display.c62
-rw-r--r--src/display.h2
-rw-r--r--src/scan.c32
-rw-r--r--src/scan.h2
4 files changed, 94 insertions, 4 deletions
diff --git a/src/display.c b/src/display.c
index 8757c2f..5c54143 100644
--- a/src/display.c
+++ b/src/display.c
@@ -149,7 +149,7 @@ static void handle_damage_notify(display_t *display, xcb_damage_notify_event_t *
scanner_push(&display->session->scanner, DAMAGE_SCAN_REPORT,
p[i].x1, p[i].y1, p[i].x2 - p[i].x1, p[i].y2 - p[i].y1);
} else {
- scanner_push(&display->session->scanner, PERIODIC_SCAN_REQUEST, 0, 0, 0, 0);
+ scanner_push(&display->session->scanner, FULLSCREEN_SCAN_REQUEST, 0, 0, 0, 0);
}
pixman_region_clear(damage_region);
@@ -601,6 +601,66 @@ void display_copy_image_into_fullscreen(display_t *d, shm_image_t *shmi, int x,
}
}
+int display_scan_whole_screen(display_t *d, int num_vertical_tiles, int num_horizontal_tiles,
+ int tiles[][num_horizontal_tiles], int *tiles_changed_in_row)
+{
+ int ret;
+ int len;
+ int h_tile, v_tile, y;
+ shm_image_t *fullscreen_new;
+
+ memset(tiles, 0, sizeof(**tiles) * num_vertical_tiles * num_horizontal_tiles);
+ fullscreen_new = create_shm_image(d, 0, 0);
+ if (!fullscreen_new)
+ return 0;
+
+ ret = read_shm_image(d, fullscreen_new, 0, 0);
+ if (ret == 0) {
+ for (v_tile = 0; v_tile < num_vertical_tiles; v_tile++) {
+ /* Note that integer math and multiplying first is important;
+ especially in the case where our screen height is not a
+ multiple of 32 */
+ int ystart = (v_tile * d->fullscreen->h) / num_vertical_tiles;
+ int yend = ((v_tile + 1) * d->fullscreen->h) / num_vertical_tiles;
+ for (y = ystart; y < yend; y++) {
+ if (y >= d->fullscreen->h)
+ continue;
+
+ uint32_t *old = ((uint32_t *) d->fullscreen->segment.shmaddr) +
+ (y * d->fullscreen->w);
+ uint32_t *new = ((uint32_t *) fullscreen_new->segment.shmaddr) +
+ (y * fullscreen_new->w);
+ if (memcmp(old, new, sizeof(*old) * d->fullscreen->w) == 0)
+ continue;
+
+ len = d->fullscreen->w / num_horizontal_tiles;
+ for (h_tile = 0; h_tile < num_horizontal_tiles; h_tile++, old += len, new += len) {
+ if (h_tile == num_horizontal_tiles - 1)
+ len = d->fullscreen->w - (h_tile * len);
+ if (memcmp(old, new, sizeof(*old) * len)) {
+ ret++;
+ tiles[v_tile][h_tile]++;
+ tiles_changed_in_row[v_tile]++;
+ }
+ }
+ }
+#if defined(DEBUG_SCANLINES)
+ fprintf(stderr, "%d: ", v_tile);
+ for (h_tile = 0; h_tile < num_horizontal_tiles; h_tile++)
+ fprintf(stderr, "%c", tiles[v_tile][h_tile] ? 'X' : '-');
+ fprintf(stderr, "\n");
+ fflush(stderr);
+#endif
+ }
+ }
+
+ /* We've just read the full screen; may as well use it */
+ destroy_shm_image(d, d->fullscreen);
+ d->fullscreen = fullscreen_new;
+
+ return ret;
+}
+
void destroy_shm_image(display_t *d, shm_image_t *shmi)
{
diff --git a/src/display.h b/src/display.h
index f4cabc0..9e5cdf4 100644
--- a/src/display.h
+++ b/src/display.h
@@ -86,6 +86,8 @@ int display_start_event_thread(display_t *d);
void display_stop_event_thread(display_t *d);
int display_find_changed_tiles(display_t *d, int row, int *tiles, int tiles_across);
void display_copy_image_into_fullscreen(display_t *d, shm_image_t *shmi, int x, int y);
+int display_scan_whole_screen(display_t *d, int num_vertical_tiles, int num_horizontal_tiles,
+ int tiles[][num_horizontal_tiles], int *tiles_changed_in_row);
shm_image_t *create_shm_image(display_t *d, unsigned int w, unsigned int h);
int read_shm_image(display_t *d, shm_image_t *shmi, int x, int y);
diff --git a/src/scan.c b/src/scan.c
index 1c5927e..fcd472d 100644
--- a/src/scan.c
+++ b/src/scan.c
@@ -348,6 +348,34 @@ static void scanner_periodic(scanner_t *scanner)
g_mutex_unlock(scanner->session->lock);
}
+static void scan_full_screen(scanner_t *scanner)
+{
+ int num_vertical_tiles;
+ int rc;
+
+ g_mutex_lock(scanner->session->lock);
+ num_vertical_tiles = scanner->session->display.fullscreen->h / NUM_SCANLINES;
+ if (scanner->session->display.fullscreen->h % NUM_SCANLINES)
+ num_vertical_tiles++;
+
+ int tiles_changed_in_row[num_vertical_tiles];
+ int tiles_changed[num_vertical_tiles][NUM_HORIZONTAL_TILES];
+
+ memset(tiles_changed_in_row, 0, sizeof(tiles_changed_in_row));
+
+ rc = display_scan_whole_screen(&scanner->session->display,
+ num_vertical_tiles, NUM_HORIZONTAL_TILES,
+ tiles_changed, tiles_changed_in_row);
+ if (rc < 0) {
+ g_mutex_unlock(scanner->session->lock);
+ return;
+ }
+
+ grow_changed_tiles(scanner, tiles_changed_in_row, tiles_changed, num_vertical_tiles);
+ push_changed_tiles(scanner, tiles_changed_in_row, tiles_changed, num_vertical_tiles);
+ g_mutex_unlock(scanner->session->lock);
+}
+
#if ! GLIB_CHECK_VERSION(2, 31, 18)
static gpointer g_async_queue_timeout_pop(GAsyncQueue *queue, guint64 t)
{
@@ -370,9 +398,9 @@ static void *scanner_run(void *opaque)
continue;
}
- if (r->type == PERIODIC_SCAN_REQUEST) {
+ if (r->type == FULLSCREEN_SCAN_REQUEST) {
free_queue_item(r);
- scanner_periodic(scanner);
+ scan_full_screen(scanner);
continue;
}
diff --git a/src/scan.h b/src/scan.h
index 69991fe..8d92ba3 100644
--- a/src/scan.h
+++ b/src/scan.h
@@ -30,7 +30,7 @@ typedef enum {
DAMAGE_SCAN_REPORT,
SCANLINE_SCAN_REPORT,
EXIT_SCAN_REPORT,
- PERIODIC_SCAN_REQUEST,
+ FULLSCREEN_SCAN_REQUEST,
} scan_type_t;
struct session_struct;