Commit 97517317 authored by Brendan Shanks's avatar Brendan Shanks Committed by Frediano Ziglio

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's avatarFrediano Ziglio <fziglio@redhat.com>
parent 46635721
......@@ -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)
{
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment