diff options
-rw-r--r-- | src/display.c | 62 | ||||
-rw-r--r-- | src/display.h | 2 | ||||
-rw-r--r-- | src/scan.c | 32 | ||||
-rw-r--r-- | src/scan.h | 2 |
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); @@ -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; |