llvmpipe: raise dirty flag on transfers to bound constbuf
[mesa.git] / src / gallium / drivers / llvmpipe / lp_texture.c
index d236bad69d187edbd15f20c981c5375c9bc6bc57..f78cd60b37c8160a501505ef325aae32994be63c 100644 (file)
@@ -49,6 +49,7 @@
 #include "lp_tile_image.h"
 #include "lp_texture.h"
 #include "lp_setup.h"
+#include "lp_state.h"
 
 #include "state_tracker/sw_winsys.h"
 
@@ -56,6 +57,7 @@
 #ifdef DEBUG
 static struct llvmpipe_resource resource_list;
 #endif
+static unsigned id_counter = 0;
 
 
 static INLINE boolean
@@ -66,6 +68,7 @@ resource_is_texture(const struct pipe_resource *resource)
       return FALSE;
    case PIPE_TEXTURE_1D:
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_3D:
    case PIPE_TEXTURE_CUBE:
       return TRUE;
@@ -184,8 +187,8 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen,
     */
    const unsigned width = align(lpr->base.width0, TILE_SIZE);
    const unsigned height = align(lpr->base.height0, TILE_SIZE);
-   const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
-   const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
+   const unsigned width_t = width / TILE_SIZE;
+   const unsigned height_t = height / TILE_SIZE;
 
    lpr->tiles_per_row[0] = width_t;
    lpr->tiles_per_image[0] = width_t * height_t;
@@ -210,7 +213,6 @@ static struct pipe_resource *
 llvmpipe_resource_create(struct pipe_screen *_screen,
                          const struct pipe_resource *templat)
 {
-   static unsigned id_counter = 0;
    struct llvmpipe_screen *screen = llvmpipe_screen(_screen);
    struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
    if (!lpr)
@@ -446,6 +448,10 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
 {
    struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys;
    struct llvmpipe_resource *lpr = CALLOC_STRUCT(llvmpipe_resource);
+   unsigned width, height, width_t, height_t;
+
+   /* XXX Seems like from_handled depth textures doesn't work that well */
+
    if (!lpr)
       return NULL;
 
@@ -453,6 +459,25 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
    pipe_reference_init(&lpr->base.reference, 1);
    lpr->base.screen = screen;
 
+   width = align(lpr->base.width0, TILE_SIZE);
+   height = align(lpr->base.height0, TILE_SIZE);
+   width_t = width / TILE_SIZE;
+   height_t = height / TILE_SIZE;
+
+   /*
+    * Looks like unaligned displaytargets work just fine,
+    * at least sampler/render ones.
+    */
+#if 0
+   assert(lpr->base.width0 == width);
+   assert(lpr->base.height0 == height);
+#endif
+
+   lpr->tiles_per_row[0] = width_t;
+   lpr->tiles_per_image[0] = width_t * height_t;
+   lpr->num_slices_faces[0] = 1;
+   lpr->img_stride[0] = 0;
+
    lpr->dt = winsys->displaytarget_from_handle(winsys,
                                                template,
                                                whandle,
@@ -460,6 +485,17 @@ llvmpipe_resource_from_handle(struct pipe_screen *screen,
    if (!lpr->dt)
       goto fail;
 
+   lpr->layout[0] = alloc_layout_array(1, lpr->base.width0, lpr->base.height0);
+
+   assert(lpr->layout[0]);
+   assert(lpr->layout[0][0] == LP_TEX_LAYOUT_NONE);
+
+   lpr->id = id_counter++;
+
+#ifdef DEBUG
+   insert_at_tail(&resource_list, lpr);
+#endif
+
    return &lpr->base;
 
  fail:
@@ -531,6 +567,7 @@ llvmpipe_get_transfer(struct pipe_context *pipe,
                      unsigned usage,
                      const struct pipe_box *box)
 {
+   struct llvmpipe_context *llvmpipe = llvmpipe_context(pipe);
    struct llvmpipe_resource *lprex = llvmpipe_resource(resource);
    struct llvmpipe_transfer *lpr;
 
@@ -549,7 +586,8 @@ llvmpipe_get_transfer(struct pipe_context *pipe,
                                    0, /* flush_flags */
                                    read_only,
                                    TRUE, /* cpu_access */
-                                   do_not_block)) {
+                                   do_not_block,
+                                   __FUNCTION__)) {
          /*
           * It would have blocked, but state tracker requested no to.
           */
@@ -558,6 +596,9 @@ llvmpipe_get_transfer(struct pipe_context *pipe,
       }
    }
 
+   if (resource == llvmpipe->constants[PIPE_SHADER_FRAGMENT][0])
+      llvmpipe->dirty |= LP_NEW_CONSTANTS;
+
    lpr = CALLOC_STRUCT(llvmpipe_transfer);
    if (lpr) {
       struct pipe_transfer *pt = &lpr->base;
@@ -1208,6 +1249,94 @@ llvmpipe_get_texture_tile(struct llvmpipe_resource *lpr,
 }
 
 
+/**
+ * Get pointer to tiled data for rendering.
+ * \return pointer to the tiled data at the given tile position
+ */
+void
+llvmpipe_unswizzle_cbuf_tile(struct llvmpipe_resource *lpr,
+                             unsigned face_slice, unsigned level,
+                             unsigned x, unsigned y,
+                             uint8_t *tile)
+{
+   struct llvmpipe_texture_image *linear_img = &lpr->linear[level];
+   const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
+   uint8_t *linear_image;
+
+   assert(x % TILE_SIZE == 0);
+   assert(y % TILE_SIZE == 0);
+
+   if (!linear_img->data) {
+      /* allocate memory for the linear image now */
+      alloc_image_data(lpr, level, LP_TEX_LAYOUT_LINEAR);
+   }
+
+   /* compute address of the slice/face of the image that contains the tile */
+   linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
+                                                     LP_TEX_LAYOUT_LINEAR);
+
+   {
+      uint ii = x, jj = y;
+      uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE;
+      uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4;
+      
+      /* Note that lp_tiled_to_linear expects the tile parameter to
+       * point at the first tile in a whole-image sized array.  In
+       * this code, we have only a single tile and have to do some
+       * pointer arithmetic to figure out where the "image" would have
+       * started.
+       */
+      lp_tiled_to_linear(tile - byte_offset, linear_image,
+                         x, y, TILE_SIZE, TILE_SIZE,
+                         lpr->base.format,
+                         lpr->row_stride[level],
+                         1);       /* tiles per row */
+   }
+
+   llvmpipe_set_texture_tile_layout(lpr, face_slice, level, tx, ty,
+                                    LP_TEX_LAYOUT_LINEAR);
+}
+
+
+/**
+ * Get pointer to tiled data for rendering.
+ * \return pointer to the tiled data at the given tile position
+ */
+void
+llvmpipe_swizzle_cbuf_tile(struct llvmpipe_resource *lpr,
+                           unsigned face_slice, unsigned level,
+                           unsigned x, unsigned y,
+                           uint8_t *tile)
+{
+   uint8_t *linear_image;
+
+   assert(x % TILE_SIZE == 0);
+   assert(y % TILE_SIZE == 0);
+
+   /* compute address of the slice/face of the image that contains the tile */
+   linear_image = llvmpipe_get_texture_image_address(lpr, face_slice, level,
+                                                     LP_TEX_LAYOUT_LINEAR);
+
+   if (linear_image) {
+      uint ii = x, jj = y;
+      uint tile_offset = jj / TILE_SIZE + ii / TILE_SIZE;
+      uint byte_offset = tile_offset * TILE_SIZE * TILE_SIZE * 4;
+
+      /* Note that lp_linear_to_tiled expects the tile parameter to
+       * point at the first tile in a whole-image sized array.  In
+       * this code, we have only a single tile and have to do some
+       * pointer arithmetic to figure out where the "image" would have
+       * started.
+       */
+      lp_linear_to_tiled(linear_image, tile - byte_offset,
+                         x, y, TILE_SIZE, TILE_SIZE,
+                         lpr->base.format,
+                         lpr->row_stride[level],
+                         1);       /* tiles per row */
+   }
+}
+
+
 /**
  * Return size of resource in bytes
  */