ilo: fix textureSize() for single-layered array textures
[mesa.git] / src / gallium / drivers / llvmpipe / lp_scene.c
index 2a26896e628c7a8aab7b9489cc8cb4e999e251ab..771ad085a120138a03b639dbd483cdb01ba3c2d8 100644 (file)
@@ -58,10 +58,27 @@ lp_scene_create( struct pipe_context *pipe )
       return NULL;
 
    scene->pipe = pipe;
-   scene->data.head = &scene->data.first;
+
+   scene->data.head =
+      CALLOC_STRUCT(data_block);
 
    pipe_mutex_init(scene->mutex);
 
+#ifdef DEBUG
+   /* Do some scene limit sanity checks here */
+   {
+      size_t maxBins = TILES_X * TILES_Y;
+      size_t maxCommandBytes = sizeof(struct cmd_block) * maxBins;
+      size_t maxCommandPlusData = maxCommandBytes + DATA_BLOCK_SIZE;
+      /* We'll need at least one command block per bin.  Make sure that's
+       * less than the max allowed scene size.
+       */
+      assert(maxCommandBytes < LP_SCENE_MAX_SIZE);
+      /* We'll also need space for at least one other data block */
+      assert(maxCommandPlusData <= LP_SCENE_MAX_SIZE);
+   }
+#endif
+
    return scene;
 }
 
@@ -72,8 +89,10 @@ lp_scene_create( struct pipe_context *pipe )
 void
 lp_scene_destroy(struct lp_scene *scene)
 {
+   lp_fence_reference(&scene->fence, NULL);
    pipe_mutex_destroy(scene->mutex);
-   assert(scene->data.head == &scene->data.first);
+   assert(scene->data.head->next == NULL);
+   FREE(scene->data.head);
    FREE(scene);
 }
 
@@ -118,6 +137,7 @@ lp_scene_bin_reset(struct lp_scene *scene, unsigned x, unsigned y)
 {
    struct cmd_bin *bin = lp_scene_get_bin(scene, x, y);
 
+   bin->last_state = NULL;
    bin->head = bin->tail;
    if (bin->tail) {
       bin->tail->next = NULL;
@@ -133,32 +153,37 @@ lp_scene_begin_rasterization(struct lp_scene *scene)
    int i;
 
    //LP_DBG(DEBUG_RAST, "%s\n", __FUNCTION__);
-   
+
    for (i = 0; i < scene->fb.nr_cbufs; i++) {
       struct pipe_surface *cbuf = scene->fb.cbufs[i];
-      scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
-                                                        cbuf->level);
-
-      scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
-                                                  cbuf->face,
-                                                  cbuf->level,
-                                                  cbuf->zslice,
-                                                  LP_TEX_USAGE_READ_WRITE,
-                                                  LP_TEX_LAYOUT_LINEAR);
+      if (llvmpipe_resource_is_texture(cbuf->texture)) {
+         scene->cbufs[i].stride = llvmpipe_resource_stride(cbuf->texture,
+                                                           cbuf->u.tex.level);
+
+         scene->cbufs[i].map = llvmpipe_resource_map(cbuf->texture,
+                                                     cbuf->u.tex.level,
+                                                     cbuf->u.tex.first_layer,
+                                                     LP_TEX_USAGE_READ_WRITE);
+      }
+      else {
+         struct llvmpipe_resource *lpr = llvmpipe_resource(cbuf->texture);
+         unsigned pixstride = util_format_get_blocksize(cbuf->format);
+         scene->cbufs[i].stride = cbuf->texture->width0;
+         scene->cbufs[i].map = lpr->data;
+         scene->cbufs[i].map += cbuf->u.buf.first_element * pixstride;
+      }
    }
 
    if (fb->zsbuf) {
       struct pipe_surface *zsbuf = scene->fb.zsbuf;
-      scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->level);
+      scene->zsbuf.stride = llvmpipe_resource_stride(zsbuf->texture, zsbuf->u.tex.level);
       scene->zsbuf.blocksize = 
          util_format_get_blocksize(zsbuf->texture->format);
 
       scene->zsbuf.map = llvmpipe_resource_map(zsbuf->texture,
-                                               zsbuf->face,
-                                               zsbuf->level,
-                                               zsbuf->zslice,
-                                               LP_TEX_USAGE_READ_WRITE,
-                                               LP_TEX_LAYOUT_NONE);
+                                               zsbuf->u.tex.level,
+                                               zsbuf->u.tex.first_layer,
+                                               LP_TEX_USAGE_READ_WRITE);
    }
 }
 
@@ -177,10 +202,11 @@ lp_scene_end_rasterization(struct lp_scene *scene )
    for (i = 0; i < scene->fb.nr_cbufs; i++) {
       if (scene->cbufs[i].map) {
          struct pipe_surface *cbuf = scene->fb.cbufs[i];
-         llvmpipe_resource_unmap(cbuf->texture,
-                                 cbuf->face,
-                                 cbuf->level,
-                                 cbuf->zslice);
+         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;
       }
    }
@@ -189,9 +215,8 @@ lp_scene_end_rasterization(struct lp_scene *scene )
    if (scene->zsbuf.map) {
       struct pipe_surface *zsbuf = scene->fb.zsbuf;
       llvmpipe_resource_unmap(zsbuf->texture,
-                             zsbuf->face,
-                             zsbuf->level,
-                             zsbuf->zslice);
+                              zsbuf->u.tex.level,
+                              zsbuf->u.tex.first_layer);
       scene->zsbuf.map = NULL;
    }
 
@@ -200,7 +225,9 @@ lp_scene_end_rasterization(struct lp_scene *scene )
    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 = bin->tail = NULL;
+         bin->head = NULL;
+         bin->tail = NULL;
+         bin->last_state = NULL;
       }
    }
 
@@ -220,7 +247,7 @@ lp_scene_end_rasterization(struct lp_scene *scene )
             if (LP_DEBUG & DEBUG_SETUP)
                debug_printf("resource %d: %p %dx%d sz %d\n",
                             j,
-                            ref->resource[i],
+                            (void *) ref->resource[i],
                             ref->resource[i]->width0,
                             ref->resource[i]->height0,
                             llvmpipe_resource_size(ref->resource[i]));
@@ -240,14 +267,13 @@ lp_scene_end_rasterization(struct lp_scene *scene )
       struct data_block_list *list = &scene->data;
       struct data_block *block, *tmp;
 
-      for (block = list->head; block; block = tmp) {
+      for (block = list->head->next; block; block = tmp) {
          tmp = block->next;
-         if (block != &list->first)
-            FREE(block);
+        FREE(block);
       }
 
-      list->head = &list->first;
       list->head->next = NULL;
+      list->head->used = 0;
    }
 
    lp_fence_reference(&scene->fence, NULL);
@@ -344,6 +370,7 @@ lp_scene_add_resource_reference(struct lp_scene *scene,
    /* Look at existing resource blocks:
     */
    for (ref = scene->resources; ref; ref = ref->next) {
+      last = &ref->next;
 
       /* Search for this resource:
        */
@@ -351,27 +378,27 @@ lp_scene_add_resource_reference(struct lp_scene *scene,
          if (ref->resource[i] == resource)
             return TRUE;
 
-      /* If the block is half-empty, this is the last block.  Append
-       * the reference here.
-       */
-      if (ref->count < RESOURCE_REF_SZ)
-         goto add_new_ref;
-
-      last = &ref->next;
+      if (ref->count < RESOURCE_REF_SZ) {
+         /* If the block is half-empty, then append the reference here.
+          */
+         break;
+      }
    }
 
-   /* Otherwise, need to create a new block:
+   /* Create a new block if no half-empty block was found.
     */
-   *last = lp_scene_alloc(scene, sizeof(struct resource_ref));
-   if (*last) {
+   if (!ref) {
+      assert(*last == NULL);
+      *last = lp_scene_alloc(scene, sizeof *ref);
+      if (*last == NULL)
+          return FALSE;
+
       ref = *last;
       memset(ref, 0, sizeof *ref);
-      goto add_new_ref;
    }
 
-   return FALSE;
-
-add_new_ref:
+   /* Append the reference to the reference block.
+    */
    pipe_resource_reference(&ref->resource[ref->count++], resource);
    scene->resource_reference_size += llvmpipe_resource_size(resource);
 
@@ -381,7 +408,7 @@ add_new_ref:
     * data.
     */
    if (!initializing_scene &&
-       scene->resource_reference_size < LP_SCENE_MAX_RESOURCE_SIZE)
+       scene->resource_reference_size >= LP_SCENE_MAX_RESOURCE_SIZE)
       return FALSE;
 
    return TRUE;
@@ -441,7 +468,7 @@ lp_scene_bin_iter_begin( struct lp_scene *scene )
  * of work (a bin) to work on.
  */
 struct cmd_bin *
-lp_scene_bin_iter_next( struct lp_scene *scene )
+lp_scene_bin_iter_next( struct lp_scene *scene , int *x, int *y)
 {
    struct cmd_bin *bin = NULL;
 
@@ -458,6 +485,8 @@ lp_scene_bin_iter_next( struct lp_scene *scene )
    }
 
    bin = lp_scene_get_bin(scene, scene->curr_x, scene->curr_y);
+   *x = scene->curr_x;
+   *y = scene->curr_y;
 
 end:
    /*printf("return bin %p at %d, %d\n", (void *) bin, *bin_x, *bin_y);*/
@@ -467,10 +496,11 @@ end:
 
 
 void lp_scene_begin_binning( struct lp_scene *scene,
-                             struct pipe_framebuffer_state *fb )
+                             struct pipe_framebuffer_state *fb, boolean discard )
 {
    assert(lp_scene_is_empty(scene));
 
+   scene->discard = discard;
    util_copy_framebuffer_state(&scene->fb, fb);
 
    scene->tiles_x = align(fb->width, TILE_SIZE) / TILE_SIZE;
@@ -489,5 +519,8 @@ void lp_scene_end_binning( struct lp_scene *scene )
                    scene->scene_size);
       debug_printf("  data size: %u\n",
                    lp_scene_data_size(scene));
+
+      if (0)
+         lp_debug_bins( scene );
    }
 }