llvmpipe: Do unswizzling in parallel when flushing for transfers.
[mesa.git] / src / gallium / drivers / llvmpipe / lp_scene.c
index 182e7cb2303b9d44df469bee1ab83388d6153a43..845c175cf2ecc0780e508339d4b3c2b93c40afe8 100644 (file)
  *
  **************************************************************************/
 
+#include "util/u_framebuffer.h"
 #include "util/u_math.h"
 #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"
 
 
+/** List of texture references */
+struct texture_ref {
+   struct pipe_resource *texture;
+   struct texture_ref *prev, *next;  /**< linked list w/ u_simple_list.h */
+};
+
+
+
+/**
+ * Create a new scene object.
+ * \param queue  the queue to put newly rendered/emptied scenes into
+ */
 struct lp_scene *
 lp_scene_create( struct pipe_context *pipe,
                  struct lp_scene_queue *queue )
@@ -57,7 +68,7 @@ lp_scene_create( struct pipe_context *pipe,
    scene->data.head =
       scene->data.tail = CALLOC_STRUCT(data_block);
 
-   make_empty_list(&scene->textures);
+   make_empty_list(&scene->resources);
 
    pipe_mutex_init(scene->mutex);
 
@@ -66,7 +77,7 @@ lp_scene_create( struct pipe_context *pipe,
 
 
 /**
- * Free all data associated with the given scene, and free(scene).
+ * Free all data associated with the given scene, and the scene itself.
  */
 void
 lp_scene_destroy(struct lp_scene *scene)
@@ -178,17 +189,19 @@ lp_scene_reset(struct lp_scene *scene )
    /* Release texture refs
     */
    {
-      struct texture_ref *ref, *next, *ref_list = &scene->textures;
+      struct resource_ref *ref, *next, *ref_list = &scene->resources;
       for (ref = ref_list->next; ref != ref_list; ref = next) {
          next = next_elem(ref);
-         pipe_resource_reference(&ref->texture, NULL);
+         pipe_resource_reference(&ref->resource, NULL);
          FREE(ref);
       }
       make_empty_list(ref_list);
    }
 
+   scene->scene_size = 0;
+
    scene->has_color_clear = FALSE;
-   scene->has_depth_clear = FALSE;
+   scene->has_depthstencil_clear = FALSE;
 }
 
 
@@ -196,29 +209,38 @@ lp_scene_reset(struct lp_scene *scene )
 
 
 
-void
+struct cmd_block *
 lp_bin_new_cmd_block( struct cmd_block_list *list )
 {
    struct cmd_block *block = MALLOC_STRUCT(cmd_block);
-   list->tail->next = block;
-   list->tail = block;
-   block->next = NULL;
-   block->count = 0;
+   if (block) {
+      list->tail->next = block;
+      list->tail = block;
+      block->next = NULL;
+      block->count = 0;
+   }
+   return block;
 }
 
 
-void
+struct data_block *
 lp_bin_new_data_block( struct data_block_list *list )
 {
    struct data_block *block = MALLOC_STRUCT(data_block);
-   list->tail->next = block;
-   list->tail = block;
-   block->next = NULL;
-   block->used = 0;
+   if (block) {
+      list->tail->next = block;
+      list->tail = block;
+      block->next = NULL;
+      block->used = 0;
+   }
+   return block;
 }
 
 
-/** Return number of bytes used for all bin data within a scene */
+/**
+ * Return number of bytes used for all bin data within a scene.
+ * This does not include resources (textures) referenced by the scene.
+ */
 unsigned
 lp_scene_data_size( const struct lp_scene *scene )
 {
@@ -247,32 +269,34 @@ lp_scene_bin_size( const struct lp_scene *scene, unsigned x, unsigned y )
 
 
 /**
- * Add a reference to a texture by the scene.
+ * Add a reference to a resource by the scene.
  */
 void
-lp_scene_texture_reference( struct lp_scene *scene,
-                            struct pipe_resource *texture )
+lp_scene_add_resource_reference(struct lp_scene *scene,
+                                struct pipe_resource *resource)
 {
-   struct texture_ref *ref = CALLOC_STRUCT(texture_ref);
+   struct resource_ref *ref = CALLOC_STRUCT(resource_ref);
    if (ref) {
-      struct texture_ref *ref_list = &scene->textures;
-      pipe_resource_reference(&ref->texture, texture);
+      struct resource_ref *ref_list = &scene->resources;
+      pipe_resource_reference(&ref->resource, resource);
       insert_at_tail(ref_list, ref);
    }
+
+   scene->scene_size += llvmpipe_resource_size(resource);
 }
 
 
 /**
- * Does this scene have a reference to the given texture?
+ * Does this scene have a reference to the given resource?
  */
 boolean
-lp_scene_is_resource_referenced( const struct lp_scene *scene,
-                                const struct pipe_resource *texture )
+lp_scene_is_resource_referenced(const struct lp_scene *scene,
+                                const struct pipe_resource *resource)
 {
-   const struct texture_ref *ref_list = &scene->textures;
-   const struct texture_ref *ref;
+   const struct resource_ref *ref_list = &scene->resources;
+   const struct resource_ref *ref;
    foreach (ref, ref_list) {
-      if (ref->texture == texture)
+      if (ref->resource == resource)
          return TRUE;
    }
    return FALSE;
@@ -393,61 +417,6 @@ end:
 }
 
 
-
-/**
- * Prepare this scene for the rasterizer.
- * Map the framebuffer surfaces.  Initialize the 'rast' state.
- */
-static boolean
-lp_scene_map_buffers( struct lp_scene *scene )
-{
-   LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
-
-   /* XXX framebuffer surfaces are no longer mapped here */
-   /* XXX move all map/unmap stuff into rast module... */
-
-   return TRUE;
-}
-
-
-
-/**
- * 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 )
-{
-#if 0
-   unsigned i;
-
-   for (i = 0; i < scene->fb.nr_cbufs; i++) {
-      if (scene->cbuf_map[i]) {
-         struct pipe_surface *cbuf = scene->fb.cbufs[i];
-         llvmpipe_resource_unmap(cbuf->texture,
-                                cbuf->face,
-                                cbuf->level,
-                                cbuf->zslice);
-         scene->cbuf_map[i] = NULL;
-      }
-   }
-
-   if (scene->zsbuf_map) {
-      struct pipe_surface *zsbuf = scene->fb.zsbuf;
-      llvmpipe_resource_unmap(zsbuf->texture,
-                             zsbuf->face,
-                             zsbuf->level,
-                             zsbuf->zslice);
-      scene->zsbuf_map = NULL;
-   }
-#endif
-
-   util_unreference_framebuffer_state( &scene->fb );
-}
-
-
 void lp_scene_begin_binning( struct lp_scene *scene,
                              struct pipe_framebuffer_state *fb )
 {
@@ -464,8 +433,7 @@ void lp_scene_begin_binning( struct lp_scene *scene,
 
 
 void lp_scene_rasterize( struct lp_scene *scene,
-                         struct lp_rasterizer *rast,
-                         boolean write_depth )
+                         struct lp_rasterizer *rast )
 {
    if (0) {
       unsigned x, y;
@@ -479,11 +447,6 @@ void lp_scene_rasterize( struct lp_scene *scene,
       }
    }
 
-   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.
     */
@@ -494,6 +457,9 @@ void lp_scene_rasterize( struct lp_scene *scene,
     * transfers become per-context:
     */
    lp_rast_finish( rast );
-   lp_scene_unmap_buffers( scene );
+
+   util_unreference_framebuffer_state( &scene->fb );
+
+   /* put scene into the empty list */
    lp_scene_enqueue( scene->empty_queue, scene );
 }