/** * Rasterize/execute all bins within a scene. * Called per thread. */ static void rasterize_scene(struct lp_rasterizer_task *task, struct lp_scene *scene) { task->scene = scene; /* loop over scene bins, rasterize each */ #if 0 { unsigned i, j; for (i = 0; i < scene->tiles_x; i++) { for (j = 0; j < scene->tiles_y; j++) { struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); rasterize_bin(task, bin, i, j); } } } #else { struct cmd_bin *bin; assert(scene); while ((bin = lp_scene_bin_iter_next(scene))) { if (!is_empty_bin( bin )) rasterize_bin(task, bin); } } #endif if (scene->fence) { lp_fence_signal(scene->fence); } task->scene = NULL; }
void lp_debug_draw_bins_by_coverage( struct lp_scene *scene ) { unsigned x, y; unsigned total = 0; unsigned possible = 0; static unsigned long long _total; static unsigned long long _possible; for (x = 0; x < scene->tiles_x; x++) debug_printf("-"); debug_printf("\n"); for (y = 0; y < scene->tiles_y; y++) { for (x = 0; x < scene->tiles_x; x++) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); const char *bits = "0123456789"; struct tile tile; if (bin->head) { //lp_debug_bin(bin); do_debug_bin(&tile, bin, FALSE); total += tile.coverage; possible += 64*64; if (tile.coverage == 64*64) debug_printf("*"); else if (tile.coverage) { int bit = tile.coverage/(64.0*64.0)*10; debug_printf("%c", bits[MIN2(bit,10)]); } else debug_printf("?"); } else { debug_printf(" "); } } debug_printf("|\n"); } for (x = 0; x < scene->tiles_x; x++) debug_printf("-"); debug_printf("\n"); debug_printf("this tile total: %u possible %u: percentage: %f\n", total, possible, total * 100.0 / (float)possible); _total += total; _possible += possible; debug_printf("overall total: %llu possible %llu: percentage: %f\n", _total, _possible, _total * 100.0 / (double)_possible); }
/* Remove all commands from a bin. Tries to reuse some of the memory * allocated to the bin, however. */ void lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); bin->head = bin->tail; if (bin->tail) { bin->tail->next = NULL; bin->tail->count = 0; } }
/** Return number of bytes used for a single bin */ static unsigned lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y ) { struct cmd_bin *bin = lp_scene_get_bin((struct lp_scene *) scene, x, y); const struct cmd_block *cmd; unsigned size = 0; for (cmd = bin->head; cmd; cmd = cmd->next) { size += (cmd->count * (sizeof(uint8_t) + sizeof(union lp_rast_cmd_arg))); } return size; }
void lp_debug_bins( struct lp_scene *scene ) { unsigned x, y; for (y = 0; y < scene->tiles_y; y++) { for (x = 0; x < scene->tiles_x; x++) { struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); if (bin->head) { debug_bin(bin, x, y); } } } }
/** * Check if the scene's bins are all empty. * For debugging purposes. */ boolean lp_scene_is_empty(struct lp_scene *scene ) { unsigned x, y; for (y = 0; y < TILES_Y; y++) { for (x = 0; x < TILES_X; x++) { const struct cmd_bin *bin = lp_scene_get_bin(scene, x, y); if (bin->head) { return FALSE; } } } return TRUE; }
/** * Return pointer to next bin to be rendered. * The lp_scene::curr_x and ::curr_y fields will be advanced. * Multiple rendering threads will call this function to get a chunk * of work (a bin) to work on. */ struct cmd_bin * lp_scene_bin_iter_next( struct lp_scene *scene ) { struct cmd_bin *bin = NULL; pipe_mutex_lock(scene->mutex); if (scene->curr_x < 0) { /* first bin */ scene->curr_x = 0; scene->curr_y = 0; } else if (!next_bin(scene)) { /* no more bins left */ goto end; } bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y); end: /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/ pipe_mutex_unlock(scene->mutex); return bin; }
/** * Free all the temporary data in a scene. */ void lp_scene_end_rasterization(struct lp_scene *scene ) { int i, j; /* Unmap color buffers */ for (i = 0; i < scene->fb.nr_cbufs; i++) { if (scene->cbufs[i].map) { struct pipe_surface *cbuf = scene->fb.cbufs[i]; if (llvmpipe_resource_is_texture(cbuf->texture)) { llvmpipe_resource_unmap(cbuf->texture, cbuf->u.tex.level, cbuf->u.tex.first_layer); } scene->cbufs[i].map = NULL; } } /* Unmap z/stencil buffer */ if (scene->zsbuf.map) { struct pipe_surface *zsbuf = scene->fb.zsbuf; llvmpipe_resource_unmap(zsbuf->texture, zsbuf->u.tex.level, zsbuf->u.tex.first_layer); scene->zsbuf.map = NULL; } /* Reset all command lists: */ for (i = 0; i < scene->tiles_x; i++) { for (j = 0; j < scene->tiles_y; j++) { struct cmd_bin *bin = lp_scene_get_bin(scene, i, j); bin->head = NULL; bin->tail = NULL; bin->last_state = NULL; } } /* If there are any bins which weren't cleared by the loop above, * they will be caught (on debug builds at least) by this assert: */ assert(lp_scene_is_empty(scene)); /* Decrement texture ref counts */ { struct resource_ref *ref; int i, j = 0; for (ref = scene->resources; ref; ref = ref->next) { for (i = 0; i < ref->count; i++) { if (LP_DEBUG & DEBUG_SETUP) debug_printf("resource %d: %p %dx%d sz %d\n", j, (void *) ref->resource[i], ref->resource[i]->width0, ref->resource[i]->height0, llvmpipe_resource_size(ref->resource[i])); j++; pipe_resource_reference(&ref->resource[i], NULL); } } if (LP_DEBUG & DEBUG_SETUP) debug_printf("scene %d resources, sz %d\n", j, scene->resource_reference_size); } /* Free all scene data blocks: */ { struct data_block_list *list = &scene->data; struct data_block *block, *tmp; for (block = list->head->next; block; block = tmp) { tmp = block->next; FREE(block); } list->head->next = NULL; list->head->used = 0; } lp_fence_reference(&scene->fence, NULL); scene->resources = NULL; scene->scene_size = 0; scene->resource_reference_size = 0; scene->has_depthstencil_clear = FALSE; scene->alloc_failed = FALSE; util_unreference_framebuffer_state( &scene->fb ); }