summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/llvmpipe/lp_scene.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_scene.c')
-rw-r--r--src/gallium/drivers/llvmpipe/lp_scene.c248
1 files changed, 199 insertions, 49 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index cba0e21298..72492c0f0c 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.c
+++ b/src/gallium/drivers/llvmpipe/lp_scene.c
@@ -29,44 +29,67 @@
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_simple_list.h"
+#include "util/u_surface.h"
#include "lp_scene.h"
+#include "lp_scene_queue.h"
+#include "lp_debug.h"
struct lp_scene *
-lp_scene_create(void)
+lp_scene_create( struct pipe_context *pipe,
+ struct lp_scene_queue *queue )
{
+ unsigned i, j;
struct lp_scene *scene = CALLOC_STRUCT(lp_scene);
- if (scene)
- lp_scene_init(scene);
+ if (!scene)
+ return NULL;
+
+ scene->pipe = pipe;
+ scene->empty_queue = queue;
+
+ for (i = 0; i < TILES_X; i++) {
+ for (j = 0; j < TILES_Y; j++) {
+ struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
+ bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block);
+ }
+ }
+
+ scene->data.head =
+ scene->data.tail = CALLOC_STRUCT(data_block);
+
+ make_empty_list(&scene->textures);
+
+ pipe_mutex_init(scene->mutex);
+
return scene;
}
+/**
+ * Free all data associated with the given scene, and free(scene).
+ */
void
lp_scene_destroy(struct lp_scene *scene)
{
- lp_scene_reset(scene);
- lp_scene_free_bin_data(scene);
- FREE(scene);
-}
+ unsigned i, j;
+ lp_scene_reset(scene);
-void
-lp_scene_init(struct lp_scene *scene)
-{
- unsigned i, j;
for (i = 0; i < TILES_X; i++)
for (j = 0; j < TILES_Y; j++) {
struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
- bin->commands.head = bin->commands.tail = CALLOC_STRUCT(cmd_block);
+ assert(bin->commands.head == bin->commands.tail);
+ FREE(bin->commands.head);
+ bin->commands.head = NULL;
+ bin->commands.tail = NULL;
}
- scene->data.head =
- scene->data.tail = CALLOC_STRUCT(data_block);
+ FREE(scene->data.head);
+ scene->data.head = NULL;
- make_empty_list(&scene->textures);
+ pipe_mutex_destroy(scene->mutex);
- pipe_mutex_init(scene->mutex);
+ FREE(scene);
}
@@ -92,6 +115,9 @@ lp_scene_is_empty(struct lp_scene *scene )
}
+/* Free data for one particular bin. May be called from the
+ * rasterizer thread(s).
+ */
void
lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y)
{
@@ -115,7 +141,8 @@ lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y)
/**
- * Set scene to empty state.
+ * Free all the temporary data in a scene. May be called from the
+ * rasterizer thread(s).
*/
void
lp_scene_reset(struct lp_scene *scene )
@@ -162,40 +189,8 @@ lp_scene_reset(struct lp_scene *scene )
}
-/**
- * Free all data associated with the given bin, but don't free(scene).
- */
-void
-lp_scene_free_bin_data(struct lp_scene *scene)
-{
- unsigned i, j;
-
- for (i = 0; i < TILES_X; i++)
- for (j = 0; j < TILES_Y; j++) {
- struct cmd_bin *bin = lp_scene_get_bin(scene, i, j);
- /* lp_reset_scene() should have been already called */
- assert(bin->commands.head == bin->commands.tail);
- FREE(bin->commands.head);
- bin->commands.head = NULL;
- bin->commands.tail = NULL;
- }
-
- FREE(scene->data.head);
- scene->data.head = NULL;
-
- pipe_mutex_destroy(scene->mutex);
-}
-
-void
-lp_scene_set_framebuffer_size( struct lp_scene *scene,
- unsigned width, unsigned height )
-{
- assert(lp_scene_is_empty(scene));
- scene->tiles_x = align(width, TILE_SIZE) / TILE_SIZE;
- scene->tiles_y = align(height, TILE_SIZE) / TILE_SIZE;
-}
void
@@ -393,3 +388,158 @@ end:
pipe_mutex_unlock(scene->mutex);
return bin;
}
+
+
+/**
+ * Prepare this scene for the rasterizer.
+ * Map the framebuffer surfaces. Initialize the 'rast' state.
+ */
+static boolean
+lp_scene_map_buffers( struct lp_scene *scene )
+{
+ struct pipe_screen *screen = scene->pipe->screen;
+ struct pipe_surface *cbuf, *zsbuf;
+ int i;
+
+ LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
+
+
+ /* Map all color buffers
+ */
+ for (i = 0; i < scene->fb.nr_cbufs; i++) {
+ cbuf = scene->fb.cbufs[i];
+ if (cbuf) {
+ scene->cbuf_transfer[i] = screen->get_tex_transfer(screen,
+ cbuf->texture,
+ cbuf->face,
+ cbuf->level,
+ cbuf->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0,
+ cbuf->width,
+ cbuf->height);
+ if (!scene->cbuf_transfer[i])
+ goto fail;
+
+ scene->cbuf_map[i] = screen->transfer_map(screen,
+ scene->cbuf_transfer[i]);
+ if (!scene->cbuf_map[i])
+ goto fail;
+ }
+ }
+
+ /* Map the zsbuffer
+ */
+ zsbuf = scene->fb.zsbuf;
+ if (zsbuf) {
+ scene->zsbuf_transfer = screen->get_tex_transfer(screen,
+ zsbuf->texture,
+ zsbuf->face,
+ zsbuf->level,
+ zsbuf->zslice,
+ PIPE_TRANSFER_READ_WRITE,
+ 0, 0,
+ zsbuf->width,
+ zsbuf->height);
+ if (!scene->zsbuf_transfer)
+ goto fail;
+
+ scene->zsbuf_map = screen->transfer_map(screen,
+ scene->zsbuf_transfer);
+ if (!scene->zsbuf_map)
+ goto fail;
+ }
+
+ return TRUE;
+
+fail:
+ /* Unmap and release transfers?
+ */
+ return FALSE;
+}
+
+
+
+/**
+ * Called after rasterizer as finished rasterizing a scene.
+ *
+ * We want to call this from the pipe_context's current thread to
+ * avoid having to have mutexes on the transfer functions.
+ */
+static void
+lp_scene_unmap_buffers( struct lp_scene *scene )
+{
+ struct pipe_screen *screen = scene->pipe->screen;
+ unsigned i;
+
+ for (i = 0; i < scene->fb.nr_cbufs; i++) {
+ if (scene->cbuf_map[i])
+ screen->transfer_unmap(screen, scene->cbuf_transfer[i]);
+
+ if (scene->cbuf_transfer[i])
+ screen->tex_transfer_destroy(scene->cbuf_transfer[i]);
+
+ scene->cbuf_transfer[i] = NULL;
+ scene->cbuf_map[i] = NULL;
+ }
+
+ if (scene->zsbuf_map)
+ screen->transfer_unmap(screen, scene->zsbuf_transfer);
+
+ if (scene->zsbuf_transfer)
+ screen->tex_transfer_destroy(scene->zsbuf_transfer);
+
+ scene->zsbuf_transfer = NULL;
+ scene->zsbuf_map = NULL;
+
+ util_unreference_framebuffer_state( &scene->fb );
+}
+
+
+void lp_scene_begin_binning( struct lp_scene *scene,
+ struct pipe_framebuffer_state *fb )
+{
+ assert(lp_scene_is_empty(scene));
+
+ util_copy_framebuffer_state(&scene->fb, fb);
+
+ scene->tiles_x = align(fb->width, TILE_SIZE) / TILE_SIZE;
+ scene->tiles_y = align(fb->height, TILE_SIZE) / TILE_SIZE;
+}
+
+
+void lp_scene_rasterize( struct lp_scene *scene,
+ struct lp_rasterizer *rast,
+ boolean write_depth )
+{
+ if (0) {
+ unsigned x, y;
+ debug_printf("rasterize scene:\n");
+ debug_printf(" data size: %u\n", lp_scene_data_size(scene));
+ for (y = 0; y < scene->tiles_y; y++) {
+ for (x = 0; x < scene->tiles_x; x++) {
+ debug_printf(" bin %u, %u size: %u\n", x, y,
+ lp_scene_bin_size(scene, x, y));
+ }
+ }
+ }
+
+
+ scene->write_depth = (scene->fb.zsbuf != NULL &&
+ write_depth);
+
+ lp_scene_map_buffers( scene );
+
+ /* Enqueue the scene for rasterization, then immediately wait for
+ * it to finish.
+ */
+ lp_rast_queue_scene( rast, scene );
+
+ /* Currently just wait for the rasterizer to finish. Some
+ * threading interactions need to be worked out, particularly once
+ * transfers become per-context:
+ */
+ lp_rast_finish( rast );
+ lp_scene_unmap_buffers( scene );
+ lp_scene_enqueue( scene->empty_queue, scene );
+}