softpipe: increase MAX_WIDTH/HEIGTH 4096 to match max texture size
[mesa.git] / src / gallium / drivers / softpipe / sp_tile_cache.c
index 1117c0ad4c7a364c02020df17a784db24e144c05..a524275a71c599dd41b9b2a84e28c1c8f1bb7924 100644 (file)
  **************************************************************************/
 
 /**
- * Framebuffer/surface tile caching.
+ * Texture tile caching.
  *
  * Author:
  *    Brian Paul
  */
 
-#include "pipe/p_util.h"
 #include "pipe/p_inlines.h"
-#include "util/p_tile.h"
+#include "util/u_memory.h"
+#include "util/u_tile.h"
 #include "sp_context.h"
 #include "sp_surface.h"
+#include "sp_texture.h"
 #include "sp_tile_cache.h"
 
-#define NUM_ENTRIES 32
+#define NUM_ENTRIES 50
 
 
 /** XXX move these */
-#define MAX_WIDTH 2048
-#define MAX_HEIGHT 2048
+#define MAX_WIDTH 4096
+#define MAX_HEIGHT 4096
 
 
 struct softpipe_tile_cache
 {
+   struct pipe_screen *screen;
    struct pipe_surface *surface;  /**< the surface we're caching */
-   void *surface_map;
+   struct pipe_transfer *transfer;
+   void *transfer_map;
    struct pipe_texture *texture;  /**< if caching a texture */
    struct softpipe_cached_tile entries[NUM_ENTRIES];
    uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
-   float clear_color[4];
-   uint clear_val;
-   boolean depth_stencil; /** Is the surface a depth/stencil format? */
+   float clear_color[4];  /**< for color bufs */
+   uint clear_val;        /**< for z+stencil, or packed color clear value */
+   boolean depth_stencil; /**< Is the surface a depth/stencil format? */
 
-   struct pipe_surface *tex_surf;
-   void *tex_surf_map;
+   struct pipe_transfer *tex_trans;
+   void *tex_trans_map;
    int tex_face, tex_level, tex_z;
 
    struct softpipe_cached_tile tile;  /**< scratch tile for clears */
@@ -109,13 +112,14 @@ clear_clear_flag(uint *bitvec, int x, int y)
    
 
 struct softpipe_tile_cache *
-sp_create_tile_cache(void)
+sp_create_tile_cache( struct pipe_screen *screen )
 {
    struct softpipe_tile_cache *tc;
    uint pos;
 
    tc = CALLOC_STRUCT( softpipe_tile_cache );
    if (tc) {
+      tc->screen = screen;
       for (pos = 0; pos < NUM_ENTRIES; pos++) {
          tc->entries[pos].x =
          tc->entries[pos].y = -1;
@@ -128,16 +132,19 @@ sp_create_tile_cache(void)
 void
 sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
 {
+   struct pipe_screen *screen;
    uint pos;
 
    for (pos = 0; pos < NUM_ENTRIES; pos++) {
       /*assert(tc->entries[pos].x < 0);*/
    }
-   if (tc->surface) {
-      pipe_surface_reference(&tc->surface, NULL);
+   if (tc->transfer) {
+      screen = tc->transfer->texture->screen;
+      screen->tex_transfer_destroy(tc->transfer);
    }
-   if (tc->tex_surf) {
-      pipe_surface_reference(&tc->tex_surf, NULL);
+   if (tc->tex_trans) {
+      screen = tc->tex_trans->texture->screen;
+      screen->tex_transfer_destroy(tc->tex_trans);
    }
 
    FREE( tc );
@@ -153,19 +160,35 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
 {
    assert(!tc->texture);
 
-   if (tc->surface_map) {
-      /*assert(tc->surface != ps);*/
-      pipe_surface_unmap(tc->surface);
-      tc->surface_map = NULL;
+   if (tc->transfer) {
+      struct pipe_screen *screen = tc->transfer->texture->screen;
+
+      if (ps == tc->surface)
+         return;
+
+      if (tc->transfer_map) {
+         screen->transfer_unmap(screen, tc->transfer);
+         tc->transfer_map = NULL;
+      }
+
+      screen->tex_transfer_destroy(tc->transfer);
+      tc->transfer = NULL;
    }
 
-   pipe_surface_reference(&tc->surface, ps);
+   tc->surface = ps;
 
    if (ps) {
-      if (tc->surface_map)
-        tc->surface_map = pipe_surface_map(ps);
+      struct pipe_screen *screen = ps->texture->screen;
+
+      tc->transfer = screen->get_tex_transfer(screen, ps->texture, ps->face,
+                                              ps->level, ps->zslice,
+                                              PIPE_TRANSFER_READ_WRITE,
+                                              0, 0, ps->width, ps->height);
 
       tc->depth_stencil = (ps->format == PIPE_FORMAT_S8Z24_UNORM ||
+                           ps->format == PIPE_FORMAT_X8Z24_UNORM ||
+                           ps->format == PIPE_FORMAT_Z24S8_UNORM ||
+                           ps->format == PIPE_FORMAT_Z24X8_UNORM ||
                            ps->format == PIPE_FORMAT_Z16_UNORM ||
                            ps->format == PIPE_FORMAT_Z32_UNORM ||
                            ps->format == PIPE_FORMAT_S8_UNORM);
@@ -174,7 +197,7 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
 
 
 /**
- * Return the surface being cached.
+ * Return the transfer being cached.
  */
 struct pipe_surface *
 sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
@@ -184,27 +207,27 @@ sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
 
 
 void
-sp_tile_cache_map_surfaces(struct softpipe_tile_cache *tc)
+sp_tile_cache_map_transfers(struct softpipe_tile_cache *tc)
 {
-   if (tc->surface && !tc->surface_map)
-      tc->surface_map = pipe_surface_map(tc->surface);
+   if (tc->transfer && !tc->transfer_map)
+      tc->transfer_map = tc->screen->transfer_map(tc->screen, tc->transfer);
 
-   if (tc->tex_surf && !tc->tex_surf_map)
-      tc->tex_surf_map = pipe_surface_map(tc->tex_surf);
+   if (tc->tex_trans && !tc->tex_trans_map)
+      tc->tex_trans_map = tc->screen->transfer_map(tc->screen, tc->tex_trans);
 }
 
 
 void
-sp_tile_cache_unmap_surfaces(struct softpipe_tile_cache *tc)
+sp_tile_cache_unmap_transfers(struct softpipe_tile_cache *tc)
 {
-   if (tc->surface_map) {
-      pipe_surface_unmap(tc->surface);
-      tc->surface_map = NULL;
+   if (tc->transfer_map) {
+      tc->screen->transfer_unmap(tc->screen, tc->transfer);
+      tc->transfer_map = NULL;
    }
 
-   if (tc->tex_surf_map) {
-      pipe_surface_unmap(tc->tex_surf);
-      tc->tex_surf_map = NULL;
+   if (tc->tex_trans_map) {
+      tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+      tc->tex_trans_map = NULL;
    }
 }
 
@@ -219,15 +242,21 @@ sp_tile_cache_set_texture(struct pipe_context *pipe,
 {
    uint i;
 
-   assert(!tc->surface);
+   assert(!tc->transfer);
 
    pipe_texture_reference(&tc->texture, texture);
 
-   if (tc->tex_surf_map) {
-      pipe_surface_unmap(tc->tex_surf);
-      tc->tex_surf_map = NULL;
+   if (tc->tex_trans) {
+      struct pipe_screen *screen = tc->tex_trans->texture->screen;
+
+      if (tc->tex_trans_map) {
+         screen->transfer_unmap(screen, tc->tex_trans);
+         tc->tex_trans_map = NULL;
+      }
+
+      screen->tex_transfer_destroy(tc->tex_trans);
+      tc->tex_trans = NULL;
    }
-   pipe_surface_reference(&tc->tex_surf, NULL);
 
    /* mark as entries as invalid/empty */
    /* XXX we should try to avoid this when the teximage hasn't changed */
@@ -318,20 +347,20 @@ static void
 sp_tile_cache_flush_clear(struct pipe_context *pipe,
                           struct softpipe_tile_cache *tc)
 {
-   struct pipe_surface *ps = tc->surface;
-   const uint w = tc->surface->width;
-   const uint h = tc->surface->height;
+   struct pipe_transfer *pt = tc->transfer;
+   const uint w = tc->transfer->width;
+   const uint h = tc->transfer->height;
    uint x, y;
    uint numCleared = 0;
 
    /* clear the scratch tile to the clear value */
-   clear_tile(&tc->tile, ps->format, tc->clear_val);
+   clear_tile(&tc->tile, pt->format, tc->clear_val);
 
    /* push the tile to all positions marked as clear */
    for (y = 0; y < h; y += TILE_SIZE) {
       for (x = 0; x < w; x += TILE_SIZE) {
          if (is_clear_flag_set(tc->clear_flags, x, y)) {
-            pipe_put_tile_raw(pipe, ps,
+            pipe_put_tile_raw(pt,
                               x, y, TILE_SIZE, TILE_SIZE,
                               tc->tile.data.color32, 0/*STRIDE*/);
 
@@ -349,29 +378,28 @@ sp_tile_cache_flush_clear(struct pipe_context *pipe,
 
 
 /**
- * Flush the tile cache: write all dirty tiles back to the surface.
+ * Flush the tile cache: write all dirty tiles back to the transfer.
  * any tiles "flagged" as cleared will be "really" cleared.
  */
 void
 sp_flush_tile_cache(struct softpipe_context *softpipe,
                     struct softpipe_tile_cache *tc)
 {
-   struct pipe_context *pipe = &softpipe->pipe;
-   struct pipe_surface *ps = tc->surface;
+   struct pipe_transfer *pt = tc->transfer;
    int inuse = 0, pos;
 
-   if (ps && ps->buffer) {
-      /* caching a drawing surface */
+   if (pt) {
+      /* caching a drawing transfer */
       for (pos = 0; pos < NUM_ENTRIES; pos++) {
          struct softpipe_cached_tile *tile = tc->entries + pos;
          if (tile->x >= 0) {
             if (tc->depth_stencil) {
-               pipe_put_tile_raw(pipe, ps,
+               pipe_put_tile_raw(pt,
                                  tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                                  tile->data.depth32, 0/*STRIDE*/);
             }
             else {
-               pipe_put_tile_rgba(pipe, ps,
+               pipe_put_tile_rgba(pt,
                                   tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                                   (float *) tile->data.color);
             }
@@ -406,8 +434,7 @@ struct softpipe_cached_tile *
 sp_get_cached_tile(struct softpipe_context *softpipe,
                    struct softpipe_tile_cache *tc, int x, int y)
 {
-   struct pipe_context *pipe = &softpipe->pipe;
-   struct pipe_surface *ps = tc->surface;
+   struct pipe_transfer *pt = tc->transfer;
 
    /* tile pos in framebuffer: */
    const int tile_x = x & ~(TILE_SIZE - 1);
@@ -423,12 +450,12 @@ sp_get_cached_tile(struct softpipe_context *softpipe,
       if (tile->x != -1) {
          /* put dirty tile back in framebuffer */
          if (tc->depth_stencil) {
-            pipe_put_tile_raw(pipe, ps,
+            pipe_put_tile_raw(pt,
                               tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                               tile->data.depth32, 0/*STRIDE*/);
          }
          else {
-            pipe_put_tile_rgba(pipe, ps,
+            pipe_put_tile_rgba(pt,
                                tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                                (float *) tile->data.color);
          }
@@ -440,22 +467,22 @@ sp_get_cached_tile(struct softpipe_context *softpipe,
       if (is_clear_flag_set(tc->clear_flags, x, y)) {
          /* don't get tile from framebuffer, just clear it */
          if (tc->depth_stencil) {
-            clear_tile(tile, ps->format, tc->clear_val);
+            clear_tile(tile, pt->format, tc->clear_val);
          }
          else {
-            clear_tile_rgba(tile, ps->format, tc->clear_color);
+            clear_tile_rgba(tile, pt->format, tc->clear_color);
          }
          clear_clear_flag(tc->clear_flags, x, y);
       }
       else {
-         /* get new tile data from surface */
+         /* get new tile data from transfer */
          if (tc->depth_stencil) {
-            pipe_get_tile_raw(pipe, ps,
+            pipe_get_tile_raw(pt,
                               tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                               tile->data.depth32, 0/*STRIDE*/);
          }
          else {
-            pipe_get_tile_rgba(pipe, ps,
+            pipe_get_tile_rgba(pt,
                                tile->x, tile->y, TILE_SIZE, TILE_SIZE,
                                (float *) tile->data.color);
          }
@@ -476,7 +503,7 @@ sp_get_cached_tile(struct softpipe_context *softpipe,
 static INLINE uint
 tex_cache_pos(int x, int y, int z, int face, int level)
 {
-   uint entry = x + y * 5 + z * 4 + face + level;
+   uint entry = x + y * 9 + z * 3 + face + level * 7;
    return entry % NUM_ENTRIES;
 }
 
@@ -486,11 +513,11 @@ tex_cache_pos(int x, int y, int z, int face, int level)
  * Tiles are read-only and indexed with more params.
  */
 const struct softpipe_cached_tile *
-sp_get_cached_tile_tex(struct pipe_context *pipe,
+sp_get_cached_tile_tex(struct softpipe_context *sp,
                        struct softpipe_tile_cache *tc, int x, int y, int z,
                        int face, int level)
 {
-   struct pipe_screen *screen = pipe->screen;
+   struct pipe_screen *screen = sp->pipe.screen;
    /* tile pos in framebuffer: */
    const int tile_x = x & ~(TILE_SIZE - 1);
    const int tile_y = y & ~(TILE_SIZE - 1);
@@ -499,6 +526,19 @@ sp_get_cached_tile_tex(struct pipe_context *pipe,
                                   face, level);
    struct softpipe_cached_tile *tile = tc->entries + pos;
 
+   if (tc->texture) {
+      struct softpipe_texture *spt = softpipe_texture(tc->texture);
+      if (spt->modified) {
+         /* texture was modified, invalidate all cached tiles */
+         uint p;
+         for (p = 0; p < NUM_ENTRIES; p++) {
+            tile = tc->entries + p;
+            tile->x = -1;
+         }
+         spt->modified = FALSE;
+      }
+   }
+
    if (tile_x != tile->x ||
        tile_y != tile->y ||
        z != tile->z ||
@@ -506,26 +546,40 @@ sp_get_cached_tile_tex(struct pipe_context *pipe,
        level != tile->level) {
       /* cache miss */
 
-      /* check if we need to get a new surface */
-      if (!tc->tex_surf ||
+#if 0
+      printf("miss at %u  x=%d y=%d z=%d face=%d level=%d\n", pos,
+             x/TILE_SIZE, y/TILE_SIZE, z, face, level);
+#endif
+      /* check if we need to get a new transfer */
+      if (!tc->tex_trans ||
           tc->tex_face != face ||
           tc->tex_level != level ||
           tc->tex_z != z) {
-         /* get new surface (view into texture) */
+         /* get new transfer (view into texture) */
+
+         if (tc->tex_trans) {
+            if (tc->tex_trans_map) {
+               tc->screen->transfer_unmap(tc->screen, tc->tex_trans);
+               tc->tex_trans_map = NULL;
+            }
 
-        if (tc->tex_surf_map)
-            pipe_surface_unmap(tc->tex_surf);
+            screen->tex_transfer_destroy(tc->tex_trans);
+            tc->tex_trans = NULL;
+         }
 
-         tc->tex_surf = screen->get_tex_surface(screen, tc->texture, face, level, z);
-         tc->tex_surf_map = pipe_surface_map(tc->tex_surf);
+         tc->tex_trans = screen->get_tex_transfer(screen, tc->texture, face, level, z, 
+                                                  PIPE_TRANSFER_READ, 0, 0,
+                                                  tc->texture->width[level],
+                                                  tc->texture->height[level]);
+         tc->tex_trans_map = screen->transfer_map(screen, tc->tex_trans);
 
          tc->tex_face = face;
          tc->tex_level = level;
          tc->tex_z = z;
       }
 
-      /* get tile from the surface (view into texture) */
-      pipe_get_tile_rgba(pipe, tc->tex_surf,
+      /* get tile from the transfer (view into texture) */
+      pipe_get_tile_rgba(tc->tex_trans,
                          tile_x, tile_y, TILE_SIZE, TILE_SIZE,
                          (float *) tile->data.color);
       tile->x = tile_x;
@@ -545,40 +599,17 @@ sp_get_cached_tile_tex(struct pipe_context *pipe,
  * Save the color and set a 'clearflag' for each tile of the screen.
  */
 void
-sp_tile_cache_clear(struct softpipe_tile_cache *tc, uint clearValue)
+sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba,
+                    uint clearValue)
 {
-   uint r, g, b, a;
    uint pos;
 
-   tc->clear_val = clearValue;
-
-   switch (tc->surface->format) {
-   case PIPE_FORMAT_R8G8B8A8_UNORM:
-      r = (clearValue >> 24) & 0xff;
-      g = (clearValue >> 16) & 0xff;
-      b = (clearValue >>  8) & 0xff;
-      a = (clearValue      ) & 0xff;
-      break;
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-      r = (clearValue >> 16) & 0xff;
-      g = (clearValue >>  8) & 0xff;
-      b = (clearValue      ) & 0xff;
-      a = (clearValue >> 24) & 0xff;
-      break;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
-      r = (clearValue >>  8) & 0xff;
-      g = (clearValue >> 16) & 0xff;
-      b = (clearValue >> 24) & 0xff;
-      a = (clearValue      ) & 0xff;
-      break;
-   default:
-      r = g = b = a = 0;
-   }
+   tc->clear_color[0] = rgba[0];
+   tc->clear_color[1] = rgba[1];
+   tc->clear_color[2] = rgba[2];
+   tc->clear_color[3] = rgba[3];
 
-   tc->clear_color[0] = r / 255.0f;
-   tc->clear_color[1] = g / 255.0f;
-   tc->clear_color[2] = b / 255.0f;
-   tc->clear_color[3] = a / 255.0f;
+   tc->clear_val = clearValue;
 
 #if TILE_CLEAR_OPTIMIZATION
    /* set flags to indicate all the tiles are cleared */