Mesa (master): llvmpipe: reorganize transfer usage

Keith Whitwell keithw at kemper.freedesktop.org
Tue Mar 2 15:04:06 UTC 2010


Module: Mesa
Branch: master
Commit: 5fe2ce28b6e9fba181c13c6f49b57b3dd68fe88e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=5fe2ce28b6e9fba181c13c6f49b57b3dd68fe88e

Author: Keith Whitwell <keithw at vmware.com>
Date:   Tue Mar  2 14:41:35 2010 +0000

llvmpipe: reorganize transfer usage

Move transfer creation and mapping to the "scene" object, and out of
the rasterizer.  The rasterizer operates on already-mapped
framebuffers only, and no longer needs a screen or context pointer.

The scene object has access to a pipe_context, and this reorg prepares
for moving transfer functionality from the screen to the context.

---

 src/gallium/drivers/llvmpipe/lp_context.c   |    2 +-
 src/gallium/drivers/llvmpipe/lp_rast.c      |  310 ++++++++-------------------
 src/gallium/drivers/llvmpipe/lp_rast.h      |   21 +-
 src/gallium/drivers/llvmpipe/lp_rast_priv.h |   50 +++--
 src/gallium/drivers/llvmpipe/lp_scene.c     |  248 +++++++++++++++++-----
 src/gallium/drivers/llvmpipe/lp_scene.h     |   34 +++-
 src/gallium/drivers/llvmpipe/lp_setup.c     |   36 ++--
 src/gallium/drivers/llvmpipe/lp_setup.h     |    2 +-
 8 files changed, 379 insertions(+), 324 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_context.c b/src/gallium/drivers/llvmpipe/lp_context.c
index 9120226..e31ae6a 100644
--- a/src/gallium/drivers/llvmpipe/lp_context.c
+++ b/src/gallium/drivers/llvmpipe/lp_context.c
@@ -183,7 +183,7 @@ llvmpipe_create_context( struct pipe_screen *screen, void *priv )
    if (debug_get_bool_option( "LP_NO_RAST", FALSE ))
       llvmpipe->no_rast = TRUE;
 
-   llvmpipe->setup = lp_setup_create( screen,
+   llvmpipe->setup = lp_setup_create( &llvmpipe->pipe,
                                       llvmpipe->draw );
    if (!llvmpipe->setup)
       goto fail;
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.c b/src/gallium/drivers/llvmpipe/lp_rast.c
index 82c006d..dd77bb3 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.c
+++ b/src/gallium/drivers/llvmpipe/lp_rast.c
@@ -42,114 +42,60 @@
 #include "lp_scene.h"
 
 
-/**
- * Begin the rasterization phase.
- * Map the framebuffer surfaces.  Initialize the 'rast' state.
+/* Begin rasterizing a scene:
  */
 static boolean
 lp_rast_begin( struct lp_rasterizer *rast,
-               const struct pipe_framebuffer_state *fb,
-               boolean write_color,
-               boolean write_zstencil )
+               struct lp_scene *scene )
 {
-   struct pipe_screen *screen = rast->screen;
-   struct pipe_surface *cbuf, *zsbuf;
+   const struct pipe_framebuffer_state *fb = &scene->fb;
+   boolean write_color = fb->nr_cbufs != 0;
+   boolean write_zstencil = fb->zsbuf != NULL;
    int i;
 
-   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
+   rast->curr_scene = scene;
 
-   util_copy_framebuffer_state(&rast->state.fb, fb);
+   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
 
+   rast->state.nr_cbufs = scene->fb.nr_cbufs;
    rast->state.write_zstencil = write_zstencil;
    rast->state.write_color = write_color;
-
-   rast->check_for_clipped_tiles = (fb->width % TILE_SIZE != 0 ||
-                                    fb->height % TILE_SIZE != 0);
-
    
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
-      cbuf = rast->state.fb.cbufs[i];
-      if (cbuf) {
-	 rast->cbuf_transfer[i] = screen->get_tex_transfer(rast->screen,
-							   cbuf->texture,
-							   cbuf->face,
-							   cbuf->level,
-							   cbuf->zslice,
-							   PIPE_TRANSFER_READ_WRITE,
-							   0, 0,
-							   cbuf->width, 
-							   cbuf->height);
-	 if (!rast->cbuf_transfer[i])
-	    goto fail;
-
-	 rast->cbuf_map[i] = screen->transfer_map(rast->screen, 
-						  rast->cbuf_transfer[i]);
-	 if (!rast->cbuf_map[i])
-	    goto fail;
-      }
+   for (i = 0; i < rast->state.nr_cbufs; i++) {
+      rast->cbuf[i].map = scene->cbuf_map[i];
+      rast->cbuf[i].format = scene->cbuf_transfer[i]->texture->format;
+      rast->cbuf[i].width = scene->cbuf_transfer[i]->width;
+      rast->cbuf[i].height = scene->cbuf_transfer[i]->height;
+      rast->cbuf[i].stride = scene->cbuf_transfer[i]->stride;
    }
 
-   zsbuf = rast->state.fb.zsbuf;
-   if (zsbuf) {
-      rast->zsbuf_transfer = screen->get_tex_transfer(rast->screen,
-                                                      zsbuf->texture,
-                                                      zsbuf->face,
-                                                      zsbuf->level,
-                                                      zsbuf->zslice,
-                                                      PIPE_TRANSFER_READ_WRITE,
-                                                      0, 0,
-                                                      zsbuf->width,
-						      zsbuf->height);
-      if (!rast->zsbuf_transfer)
-         goto fail;
-
-      rast->zsbuf_map = screen->transfer_map(rast->screen, 
-                                            rast->zsbuf_transfer);
-      if (!rast->zsbuf_map)
-	 goto fail;
+   if (write_zstencil) {
+      rast->zsbuf.map = scene->zsbuf_map;
+      rast->zsbuf.stride = scene->zsbuf_transfer->stride;
+      rast->zsbuf.blocksize = 
+         util_format_get_blocksize(scene->zsbuf_transfer->texture->format);
    }
 
+   lp_scene_bin_iter_begin( scene );
+   
    return TRUE;
-
-fail:
-   /* Unmap and release transfers?
-    */
-   return FALSE;
 }
 
 
-/**
- * Finish the rasterization phase.
- * Unmap framebuffer surfaces.
- */
 static void
 lp_rast_end( struct lp_rasterizer *rast )
 {
-   struct pipe_screen *screen = rast->screen;
-   unsigned i;
-
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
-      if (rast->cbuf_map[i]) 
-	 screen->transfer_unmap(screen, rast->cbuf_transfer[i]);
-
-      if (rast->cbuf_transfer[i])
-	 screen->tex_transfer_destroy(rast->cbuf_transfer[i]);
-
-      rast->cbuf_transfer[i] = NULL;
-      rast->cbuf_map[i] = NULL;
-   }
+   int i;
 
-   if (rast->zsbuf_map) 
-      screen->transfer_unmap(screen, rast->zsbuf_transfer);
+   lp_scene_reset( rast->curr_scene );
 
-   if (rast->zsbuf_transfer)
-      screen->tex_transfer_destroy(rast->zsbuf_transfer);
+   for (i = 0; i < rast->state.nr_cbufs; i++)
+      rast->cbuf[i].map = NULL;
 
-   rast->zsbuf_transfer = NULL;
-   rast->zsbuf_map = NULL;
+   rast->zsbuf.map = NULL;
+   rast->curr_scene = NULL;
 }
 
-
 /**
  * Begining rasterization of a tile.
  * \param x  window X position of the tile, in pixels
@@ -189,7 +135,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
        clear_color[1] == clear_color[2] &&
        clear_color[2] == clear_color[3]) {
       /* clear to grayscale value {x, x, x, x} */
-      for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+      for (i = 0; i < rast->state.nr_cbufs; i++) {
 	 memset(color_tile[i], clear_color[0], TILE_SIZE * TILE_SIZE * 4);
       }
    }
@@ -200,7 +146,7 @@ lp_rast_clear_color(struct lp_rasterizer_task *task,
        * works.
        */
       const unsigned chunk = TILE_SIZE / 4;
-      for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
+      for (i = 0; i < rast->state.nr_cbufs; i++) {
          uint8_t *c = color_tile[i];
          unsigned j;
          for (j = 0; j < 4 * TILE_SIZE; j++) {
@@ -232,17 +178,17 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
    struct lp_rasterizer *rast = task->rast;
    const unsigned tile_x = task->x;
    const unsigned tile_y = task->y;
-   const unsigned height = TILE_SIZE/TILE_VECTOR_HEIGHT;
-   const unsigned width = TILE_SIZE*TILE_VECTOR_HEIGHT;
-   unsigned block_size = util_format_get_blocksize(rast->zsbuf_transfer->texture->format);
+   const unsigned height = TILE_SIZE / TILE_VECTOR_HEIGHT;
+   const unsigned width = TILE_SIZE * TILE_VECTOR_HEIGHT;
+   unsigned block_size = rast->zsbuf.blocksize;
    uint8_t *dst;
-   unsigned dst_stride = rast->zsbuf_transfer->stride*TILE_VECTOR_HEIGHT;
+   unsigned dst_stride = rast->zsbuf.stride * TILE_VECTOR_HEIGHT;
    unsigned i, j;
 
    LP_DBG(DEBUG_RAST, "%s 0x%x\n", __FUNCTION__, arg.clear_zstencil);
 
-   assert(rast->zsbuf_map);
-   if (!rast->zsbuf_map)
+   assert(rast->zsbuf.map);
+   if (!rast->zsbuf.map)
       return;
 
    LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
@@ -278,8 +224,8 @@ lp_rast_clear_zstencil(struct lp_rasterizer_task *task,
       }
       break;
    default:
-         assert(0);
-         break;
+      assert(0);
+      break;
    }
 }
 
@@ -298,25 +244,16 @@ lp_rast_load_color(struct lp_rasterizer_task *task,
 
    LP_DBG(DEBUG_RAST, "%s at %u, %u\n", __FUNCTION__, x, y);
 
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
-      struct pipe_transfer *transfer = rast->cbuf_transfer[i];
-      int w = TILE_SIZE;
-      int h = TILE_SIZE;
-
-      if (x >= transfer->width || y >= transfer->height)
+   for (i = 0; i < rast->state.nr_cbufs; i++) {
+      if (x >= rast->cbuf[i].width || y >= rast->cbuf[i].height)
 	 continue;
 
-      assert(w >= 0);
-      assert(h >= 0);
-      assert(w <= TILE_SIZE);
-      assert(h <= TILE_SIZE);
-
-      lp_tile_read_4ub(transfer->texture->format,
+      lp_tile_read_4ub(rast->cbuf[i].format,
 		       task->tile.color[i],
-		       rast->cbuf_map[i], 
-		       transfer->stride,
+		       rast->cbuf[i].map, 
+		       rast->cbuf[i].stride,
 		       x, y,
-		       w, h);
+		       TILE_SIZE, TILE_SIZE);
 
       LP_COUNT(nr_color_tile_load);
    }
@@ -366,7 +303,7 @@ lp_rast_shade_tile(struct lp_rasterizer_task *task,
          block_offset = ((y / 4) * (16 * 16) + (x / 4) * 16);
 
          /* color buffer */
-         for (i = 0; i < rast->state.fb.nr_cbufs; i++)
+         for (i = 0; i < rast->state.nr_cbufs; i++)
             color[i] = tile->color[i] + 4 * block_offset;
 
          /* depth buffer */
@@ -423,7 +360,7 @@ void lp_rast_shade_quads( struct lp_rasterizer_task *task,
    block_offset = ((iy / 4) * (16 * 16) + (ix / 4) * 16);
 
    /* color buffer */
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++)
+   for (i = 0; i < rast->state.nr_cbufs; i++)
       color[i] = tile->color[i] + 4 * block_offset;
 
    /* depth buffer */
@@ -516,51 +453,33 @@ lp_rast_store_color(struct lp_rasterizer_task *task)
    const unsigned x = task->x, y = task->y;
    unsigned i;
 
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++) {
-      struct pipe_transfer *transfer = rast->cbuf_transfer[i];
-      int w = TILE_SIZE;
-      int h = TILE_SIZE;
-
-      if (x >= transfer->width)
+   for (i = 0; i < rast->state.nr_cbufs; i++) {
+      if (x >= rast->cbuf[i].width)
 	 continue;
 
-      if (y >= transfer->height)
+      if (y >= rast->cbuf[i].height)
 	 continue;
 
-      LP_DBG(DEBUG_RAST, "%s [%u] %d,%d %dx%d\n", __FUNCTION__,
-	     task->thread_index, x, y, w, h);
+      LP_DBG(DEBUG_RAST, "%s [%u] %d,%d\n", __FUNCTION__,
+	     task->thread_index, x, y);
 
       if (LP_DEBUG & DEBUG_SHOW_SUBTILES)
          outline_subtiles(task->tile.color[i]);
       else if (LP_DEBUG & DEBUG_SHOW_TILES)
          outline_tile(task->tile.color[i]);
 
-      lp_tile_write_4ub(transfer->texture->format,
+      lp_tile_write_4ub(rast->cbuf[i].format,
 			task->tile.color[i],
-			rast->cbuf_map[i], 
-			transfer->stride,
+			rast->cbuf[i].map, 
+			rast->cbuf[i].stride,
 			x, y,
-			w, h);
+			TILE_SIZE, TILE_SIZE);
 
       LP_COUNT(nr_color_tile_store);
    }
 }
 
 
-/**
- * Write the rasterizer's tiles to the framebuffer.
- */
-static void
-lp_rast_end_tile(struct lp_rasterizer_task *task)
-{
-   struct lp_rasterizer *rast = task->rast;
-
-   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
-
-   if (rast->state.write_color)
-      lp_rast_store_color(task);
-}
-
 
 /**
  * Signal on a fence.  This is called during bin execution/rasterization.
@@ -586,23 +505,6 @@ lp_rast_fence(struct lp_rasterizer_task *task,
 }
 
 
-/**
- * When all the threads are done rasterizing a scene, one thread will
- * call this function to reset the scene and put it onto the empty queue.
- */
-static void
-release_scene( struct lp_rasterizer *rast,
-	       struct lp_scene *scene )
-{
-   util_unreference_framebuffer_state( &scene->fb );
-
-   lp_scene_reset( scene );
-
-   assert(lp_scene_is_empty(scene));
-
-   lp_scene_enqueue( rast->empty_scenes, scene );
-   rast->curr_scene = NULL;
-}
 
 
 /**
@@ -620,7 +522,7 @@ rasterize_bin(struct lp_rasterizer_task *task,
    struct cmd_block *block;
    unsigned k;
 
-   lp_rast_start_tile( task, x, y );
+   lp_rast_start_tile( task, x * TILE_SIZE, y * TILE_SIZE );
 
    /* simply execute each of the commands in the block list */
    for (block = commands->head; block; block = block->next) {
@@ -629,7 +531,14 @@ rasterize_bin(struct lp_rasterizer_task *task,
       }
    }
 
-   lp_rast_end_tile( task );
+   /* Write the rasterizer's tiles to the framebuffer.
+    */
+   if (task->rast->state.write_color)
+      lp_rast_store_color(task);
+
+   /* Free data for this bin.
+    */
+   lp_scene_bin_reset( task->rast->curr_scene, x, y);
 }
 
 
@@ -714,8 +623,7 @@ is_empty_bin( const struct cmd_bin *bin )
  */
 static void
 rasterize_scene(struct lp_rasterizer_task *task,
-                struct lp_scene *scene,
-                bool write_depth)
+                struct lp_scene *scene)
 {
    /* loop over scene bins, rasterize each */
 #if 0
@@ -724,7 +632,7 @@ rasterize_scene(struct lp_rasterizer_task *task,
       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 * TILE_SIZE, j * TILE_SIZE);
+            rasterize_bin(task, bin, i, j);
          }
       }
    }
@@ -736,7 +644,7 @@ rasterize_scene(struct lp_rasterizer_task *task,
       assert(scene);
       while ((bin = lp_scene_bin_iter_next(scene, &x, &y))) {
          if (!is_empty_bin( bin ))
-            rasterize_bin(task, bin, x * TILE_SIZE, y * TILE_SIZE);
+            rasterize_bin(task, bin, x, y);
       }
    }
 #endif
@@ -747,44 +655,20 @@ rasterize_scene(struct lp_rasterizer_task *task,
  * Called by setup module when it has something for us to render.
  */
 void
-lp_rasterize_scene( struct lp_rasterizer *rast,
-                   struct lp_scene *scene,
-                   const struct pipe_framebuffer_state *fb,
-                   bool write_depth )
+lp_rast_queue_scene( struct lp_rasterizer *rast,
+                     struct lp_scene *scene)
 {
-   boolean debug = false;
-
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
-   if (debug) {
-      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));
-         }
-      }
-   }
-
-   /* save framebuffer state in the bin */
-   util_copy_framebuffer_state(&scene->fb, fb);
-   scene->write_depth = write_depth;
-
    if (rast->num_threads == 0) {
       /* no threading */
 
-      lp_rast_begin( rast, fb,
-                     fb->nr_cbufs != 0, /* always write color if cbufs present */
-                     fb->zsbuf != NULL && write_depth );
+      lp_rast_begin( rast, scene );
 
-      lp_scene_bin_iter_begin( scene );
-      rasterize_scene( &rast->tasks[0], scene, write_depth );
+      rasterize_scene( &rast->tasks[0], scene );
 
-      release_scene( rast, scene );
-
-      lp_rast_end( rast );
+      lp_scene_reset( scene );
+      rast->curr_scene = NULL;
    }
    else {
       /* threaded rendering! */
@@ -796,14 +680,26 @@ lp_rasterize_scene( struct lp_rasterizer *rast,
       for (i = 0; i < rast->num_threads; i++) {
          pipe_semaphore_signal(&rast->tasks[i].work_ready);
       }
+   }
+
+   LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
+}
+
+
+void
+lp_rast_finish( struct lp_rasterizer *rast )
+{
+   if (rast->num_threads == 0) {
+      /* nothing to do */
+   }
+   else {
+      int i;
 
       /* wait for work to complete */
       for (i = 0; i < rast->num_threads; i++) {
          pipe_semaphore_wait(&rast->tasks[i].work_done);
       }
    }
-
-   LP_DBG(DEBUG_SETUP, "%s done \n", __FUNCTION__);
 }
 
 
@@ -834,19 +730,8 @@ static PIPE_THREAD_ROUTINE( thread_func, init_data )
           *  - get next scene to rasterize
           *  - map the framebuffer surfaces
           */
-         const struct pipe_framebuffer_state *fb;
-         boolean write_depth;
-
-         rast->curr_scene = lp_scene_dequeue( rast->full_scenes, TRUE );
-
-         lp_scene_bin_iter_begin( rast->curr_scene );
-
-         fb = &rast->curr_scene->fb;
-         write_depth = rast->curr_scene->write_depth;
-
-         lp_rast_begin( rast, fb,
-                        fb->nr_cbufs != 0,
-                        fb->zsbuf != NULL && write_depth );
+         lp_rast_begin( rast, 
+                        lp_scene_dequeue( rast->full_scenes, TRUE ) );
       }
 
       /* Wait for all threads to get here so that threads[1+] don't
@@ -857,25 +742,23 @@ static PIPE_THREAD_ROUTINE( thread_func, init_data )
       /* do work */
       if (debug)
          debug_printf("thread %d doing work\n", task->thread_index);
+
       rasterize_scene(task,
-                      rast->curr_scene, 
-                      rast->curr_scene->write_depth);
+                      rast->curr_scene);
       
       /* wait for all threads to finish with this scene */
       pipe_barrier_wait( &rast->barrier );
 
+      /* XXX: shouldn't be necessary:
+       */
       if (task->thread_index == 0) {
-         /* thread[0]:
-          * - release the scene object
-          * - unmap the framebuffer surfaces
-          */
-         release_scene( rast, rast->curr_scene );
          lp_rast_end( rast );
       }
 
       /* signal done with work */
       if (debug)
          debug_printf("thread %d done working\n", task->thread_index);
+
       pipe_semaphore_signal(&task->work_done);
    }
 
@@ -918,7 +801,7 @@ create_rast_threads(struct lp_rasterizer *rast)
  *               processing them.
  */
 struct lp_rasterizer *
-lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
+lp_rast_create( void )
 {
    struct lp_rasterizer *rast;
    unsigned i, cbuf;
@@ -927,9 +810,6 @@ lp_rast_create( struct pipe_screen *screen, struct lp_scene_queue *empty )
    if(!rast)
       return NULL;
 
-   rast->screen = screen;
-
-   rast->empty_scenes = empty;
    rast->full_scenes = lp_scene_queue_create();
 
    for (i = 0; i < Elements(rast->tasks); i++) {
@@ -957,8 +837,6 @@ void lp_rast_destroy( struct lp_rasterizer *rast )
 {
    unsigned i, cbuf;
 
-   util_unreference_framebuffer_state(&rast->state.fb);
-
    for (i = 0; i < Elements(rast->tasks); i++) {
       for (cbuf = 0; cbuf < PIPE_MAX_COLOR_BUFS; cbuf++ )
 	 align_free(rast->tasks[i].tile.color[cbuf]);
diff --git a/src/gallium/drivers/llvmpipe/lp_rast.h b/src/gallium/drivers/llvmpipe/lp_rast.h
index 1ed2700..d91c45e 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast.h
@@ -43,10 +43,8 @@
 
 struct lp_rasterizer;
 struct lp_scene;
-struct lp_scene_queue;
 struct lp_fence;
 struct cmd_bin;
-struct pipe_screen;
 
 /** For sub-pixel positioning */
 #define FIXED_ORDER 4
@@ -129,18 +127,21 @@ struct lp_rast_triangle {
 
 
 
-struct lp_rasterizer *lp_rast_create( struct pipe_screen *screen,
-                                      struct lp_scene_queue *empty );
+struct lp_rasterizer *
+lp_rast_create( void );
 
-void lp_rast_destroy( struct lp_rasterizer * );
+void
+lp_rast_destroy( struct lp_rasterizer * );
 
-unsigned lp_rast_get_num_threads( struct lp_rasterizer * );
+unsigned
+lp_rast_get_num_threads( struct lp_rasterizer * );
 
-void lp_rasterize_scene( struct lp_rasterizer *rast,
-			 struct lp_scene *scene,
-			 const struct pipe_framebuffer_state *fb,
-			 bool write_depth );
+void 
+lp_rast_queue_scene( struct lp_rasterizer *rast,
+                     struct lp_scene *scene );
 
+void
+lp_rast_finish( struct lp_rasterizer *rast );
 
 
 union lp_rast_cmd_arg {
diff --git a/src/gallium/drivers/llvmpipe/lp_rast_priv.h b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
index abc5a9a..39bf2c2 100644
--- a/src/gallium/drivers/llvmpipe/lp_rast_priv.h
+++ b/src/gallium/drivers/llvmpipe/lp_rast_priv.h
@@ -38,8 +38,6 @@
 #define MAX_THREADS 8  /* XXX probably temporary here */
 
 
-struct pipe_transfer;
-struct pipe_screen;
 struct lp_rasterizer;
 
 
@@ -82,20 +80,26 @@ struct lp_rasterizer_task
  */
 struct lp_rasterizer
 {
-   boolean clipped_tile;
-   boolean check_for_clipped_tiles;
    boolean exit_flag;
 
    /* Framebuffer stuff
     */
-   struct pipe_screen *screen;
-   struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
-   struct pipe_transfer *zsbuf_transfer;
-   void *cbuf_map[PIPE_MAX_COLOR_BUFS];
-   uint8_t *zsbuf_map;
+   struct {
+      void *map;
+      unsigned stride;
+      unsigned width;
+      unsigned height;
+      enum pipe_format format;
+   } cbuf[PIPE_MAX_COLOR_BUFS];
+
+   struct {
+      uint8_t *map;
+      unsigned stride;
+      unsigned blocksize;
+   } zsbuf;
 
    struct {
-      struct pipe_framebuffer_state fb;
+      unsigned nr_cbufs;
       boolean write_color;
       boolean write_zstencil;
       unsigned clear_color;
@@ -105,7 +109,14 @@ struct lp_rasterizer
 
    /** The incoming queue of scenes ready to rasterize */
    struct lp_scene_queue *full_scenes;
-   /** The outgoing queue of processed scenes to return to setup modulee */
+
+   /**
+    * The outgoing queue of processed scenes to return to setup module
+    *
+    * XXX: while scenes are per-context but the rasterizer is
+    * (potentially) shared, these empty scenes should be returned to
+    * the context which created them rather than retained here.
+    */
    struct lp_scene_queue *empty_scenes;
 
    /** The scene currently being rasterized by the threads */
@@ -137,17 +148,18 @@ lp_rast_depth_pointer( struct lp_rasterizer *rast,
                        unsigned x, unsigned y )
 {
    void * depth;
+
    assert((x % TILE_VECTOR_WIDTH) == 0);
    assert((y % TILE_VECTOR_HEIGHT) == 0);
-   if(!rast->zsbuf_map)
+
+   if (!rast->zsbuf.map)
       return NULL;
-   assert(rast->zsbuf_transfer);
-   depth = rast->zsbuf_map +
-           y*rast->zsbuf_transfer->stride +
-           TILE_VECTOR_HEIGHT*x*util_format_get_blocksize(rast->zsbuf_transfer->texture->format);
-#ifdef DEBUG
+
+   depth = (rast->zsbuf.map +
+            rast->zsbuf.stride * y +
+            rast->zsbuf.blocksize * x * TILE_VECTOR_HEIGHT);
+
    assert(lp_check_alignment(depth, 16));
-#endif
    return depth;
 }
 
@@ -175,7 +187,7 @@ lp_rast_shade_quads_all( struct lp_rasterizer_task *task,
    block_offset = (iy / 4) * (16 * 16) + (ix / 4) * 16;
 
    /* color buffer */
-   for (i = 0; i < rast->state.fb.nr_cbufs; i++)
+   for (i = 0; i < rast->state.nr_cbufs; i++)
       color[i] = tile->color[i] + 4 * block_offset;
 
    depth = lp_rast_depth_pointer(rast, x, y);
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.c b/src/gallium/drivers/llvmpipe/lp_scene.c
index cba0e21..72492c0 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 );
+}
diff --git a/src/gallium/drivers/llvmpipe/lp_scene.h b/src/gallium/drivers/llvmpipe/lp_scene.h
index 8d725cd..739ac22 100644
--- a/src/gallium/drivers/llvmpipe/lp_scene.h
+++ b/src/gallium/drivers/llvmpipe/lp_scene.h
@@ -39,6 +39,7 @@
 #include "lp_tile_soa.h"
 #include "lp_rast.h"
 
+struct lp_scene_queue;
 
 /* We're limited to 2K by 2K for 32bit fixed point rasterization.
  * Will need a 64-bit version for larger framebuffers.
@@ -112,8 +113,14 @@ struct texture_ref {
  * scenes:
  */
 struct lp_scene {
-   struct cmd_bin tile[TILES_X][TILES_Y];
-   struct data_block_list data;
+   struct pipe_context *pipe;
+   struct pipe_transfer *cbuf_transfer[PIPE_MAX_COLOR_BUFS];
+   struct pipe_transfer *zsbuf_transfer;
+
+   /* Scene's buffers are mapped at the time the scene is enqueued:
+    */
+   void *cbuf_map[PIPE_MAX_COLOR_BUFS];
+   uint8_t *zsbuf_map;
 
    /** the framebuffer to render the scene into */
    struct pipe_framebuffer_state fb;
@@ -131,25 +138,28 @@ struct lp_scene {
 
    int curr_x, curr_y;  /**< for iterating over bins */
    pipe_mutex mutex;
+
+   /* Where to place this scene once it has been rasterized:
+    */
+   struct lp_scene_queue *empty_queue;
+
+   struct cmd_bin tile[TILES_X][TILES_Y];
+   struct data_block_list data;
 };
 
 
 
-struct lp_scene *lp_scene_create(void);
+struct lp_scene *lp_scene_create(struct pipe_context *pipe,
+                                 struct lp_scene_queue *empty_queue);
 
 void lp_scene_destroy(struct lp_scene *scene);
 
 
-void lp_scene_init(struct lp_scene *scene);
 
 boolean lp_scene_is_empty(struct lp_scene *scene );
 
 void lp_scene_reset(struct lp_scene *scene );
 
-void lp_scene_free_bin_data(struct lp_scene *scene);
-
-void lp_scene_set_framebuffer_size( struct lp_scene *scene,
-                                  unsigned width, unsigned height );
 
 void lp_bin_new_data_block( struct data_block_list *list );
 
@@ -296,5 +306,13 @@ lp_scene_bin_iter_begin( struct lp_scene *scene );
 struct cmd_bin *
 lp_scene_bin_iter_next( struct lp_scene *scene, int *bin_x, int *bin_y );
 
+void
+lp_scene_rasterize( struct lp_scene *scene,
+                    struct lp_rasterizer *rast,
+                    boolean write_depth );
+
+void
+lp_scene_begin_binning( struct lp_scene *scene,
+                        struct pipe_framebuffer_state *fb );
 
 #endif /* LP_BIN_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.c b/src/gallium/drivers/llvmpipe/lp_setup.c
index 3aec9de..aebed85 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.c
+++ b/src/gallium/drivers/llvmpipe/lp_setup.c
@@ -66,11 +66,8 @@ lp_setup_get_current_scene(struct setup_context *setup)
 
       assert(lp_scene_is_empty(setup->scene));
 
-      if(0)lp_scene_reset( setup->scene ); /* XXX temporary? */
-
-      lp_scene_set_framebuffer_size(setup->scene,
-                                    setup->fb.width, 
-                                    setup->fb.height);
+      lp_scene_begin_binning(setup->scene,
+                             &setup->fb );
    }
    return setup->scene;
 }
@@ -135,13 +132,12 @@ static void reset_context( struct setup_context *setup )
 /** Rasterize all scene's bins */
 static void
 lp_setup_rasterize_scene( struct setup_context *setup,
-			 boolean write_depth )
+                          boolean write_depth )
 {
    struct lp_scene *scene = lp_setup_get_current_scene(setup);
 
-   lp_rasterize_scene(setup->rast,
-                      scene,
-                      &setup->fb,
+   lp_scene_rasterize(scene,
+                      setup->rast,
                       write_depth);
 
    reset_context( setup );
@@ -246,19 +242,16 @@ void
 lp_setup_bind_framebuffer( struct setup_context *setup,
                            const struct pipe_framebuffer_state *fb )
 {
-   struct lp_scene *scene = lp_setup_get_current_scene(setup);
-
    LP_DBG(DEBUG_SETUP, "%s\n", __FUNCTION__);
 
+   /* Flush any old scene.
+    */
    set_scene_state( setup, SETUP_FLUSHED );
 
-   /* re-get scene pointer, may have a new scene after flushing */
-   (void) scene;
-   scene = lp_setup_get_current_scene(setup);
-
+   /* Set new state.  This will be picked up later when we next need a
+    * scene.
+    */
    util_copy_framebuffer_state(&setup->fb, fb);
-
-   lp_scene_set_framebuffer_size(scene, setup->fb.width, setup->fb.height);
 }
 
 
@@ -683,7 +676,7 @@ lp_setup_destroy( struct setup_context *setup )
  * it.
  */
 struct setup_context *
-lp_setup_create( struct pipe_screen *screen,
+lp_setup_create( struct pipe_context *pipe,
                  struct draw_context *draw )
 {
    unsigned i;
@@ -698,7 +691,9 @@ lp_setup_create( struct pipe_screen *screen,
    if (!setup->empty_scenes)
       goto fail;
 
-   setup->rast = lp_rast_create( screen, setup->empty_scenes );
+   /* XXX: move this to the screen and share between contexts:
+    */
+   setup->rast = lp_rast_create();
    if (!setup->rast) 
       goto fail;
 
@@ -711,7 +706,8 @@ lp_setup_create( struct pipe_screen *screen,
 
    /* create some empty scenes */
    for (i = 0; i < MAX_SCENES; i++) {
-      setup->scenes[i] = lp_scene_create();
+      setup->scenes[i] = lp_scene_create( pipe, setup->empty_scenes );
+
       lp_scene_enqueue(setup->empty_scenes, setup->scenes[i]);
    }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_setup.h b/src/gallium/drivers/llvmpipe/lp_setup.h
index 0e155a7..17c112b 100644
--- a/src/gallium/drivers/llvmpipe/lp_setup.h
+++ b/src/gallium/drivers/llvmpipe/lp_setup.h
@@ -62,7 +62,7 @@ struct lp_fragment_shader;
 struct lp_jit_context;
 
 struct setup_context *
-lp_setup_create( struct pipe_screen *screen,
+lp_setup_create( struct pipe_context *pipe,
                  struct draw_context *draw );
 
 void




More information about the mesa-commit mailing list