Convert Z/stencil ops to use cached tiles like colors.
authorBrian <brian.paul@tungstengraphics.com>
Sat, 20 Oct 2007 21:18:02 +0000 (15:18 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Sat, 20 Oct 2007 21:18:02 +0000 (15:18 -0600)
Also, quite a bit of re-org of the tile caches and surface mapping/unmapping.
Leave surfaces mapped between primitives now.

16 files changed:
src/mesa/pipe/softpipe/sp_clear.c
src/mesa/pipe/softpipe/sp_context.c
src/mesa/pipe/softpipe/sp_context.h
src/mesa/pipe/softpipe/sp_draw_arrays.c
src/mesa/pipe/softpipe/sp_flush.c
src/mesa/pipe/softpipe/sp_quad_blend.c
src/mesa/pipe/softpipe/sp_quad_colormask.c
src/mesa/pipe/softpipe/sp_quad_depth_test.c
src/mesa/pipe/softpipe/sp_quad_output.c
src/mesa/pipe/softpipe/sp_quad_stencil.c
src/mesa/pipe/softpipe/sp_state.h
src/mesa/pipe/softpipe/sp_state_surface.c
src/mesa/pipe/softpipe/sp_surface.c
src/mesa/pipe/softpipe/sp_surface.h
src/mesa/pipe/softpipe/sp_tile_cache.c
src/mesa/pipe/softpipe/sp_tile_cache.h

index 46370b4ed9a4deb2834bcde37add49a5787b018d..4f04f8243fa213c3661329f9f5a823f955053a23 100644 (file)
@@ -69,5 +69,7 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps,
    /* XXX skip this fill if we're using tile cache */
    pipe->region_fill(pipe, ps->region, 0, x, y, w, h, clearValue);
 
+#if 0
    sp_clear_tile_cache(sps, clearValue);
+#endif
 }
index 44cc6851053f9a942876ea06d4ce90924afbc87a..87eaf6fb54450f01bde75349c1fa87684e42b4f1 100644 (file)
@@ -39,6 +39,7 @@
 #include "sp_region.h"
 #include "sp_state.h"
 #include "sp_surface.h"
+#include "sp_tile_cache.h"
 #include "sp_tex_layout.h"
 #include "sp_winsys.h"
 
@@ -113,6 +114,9 @@ softpipe_max_texture_size(struct pipe_context *pipe, unsigned textureType,
 }
 
 
+/**
+ * Map any drawing surfaces which aren't already mapped
+ */
 void
 softpipe_map_surfaces(struct softpipe_context *sp)
 {
@@ -120,68 +124,88 @@ softpipe_map_surfaces(struct softpipe_context *sp)
    unsigned i;
 
    for (i = 0; i < sp->framebuffer.num_cbufs; i++) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.cbufs[i]);
-      if (sps->surface.region)
-         pipe->region_map(pipe, sps->surface.region);
+      struct pipe_surface *ps = sp->framebuffer.cbufs[i];
+      if (ps->region && !ps->region->map) {
+         pipe->region_map(pipe, ps->region);
+      }
    }
 
    if (sp->framebuffer.zbuf) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.zbuf);
-      if (sps->surface.region)
-         pipe->region_map(pipe, sps->surface.region);
+      struct pipe_surface *ps = sp->framebuffer.zbuf;
+      if (ps->region && !ps->region->map) {
+         pipe->region_map(pipe, ps->region);
+      }
    }
 
    if (sp->framebuffer.sbuf) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.sbuf);
-      if (sps->surface.region)
-         pipe->region_map(pipe, sps->surface.region);
+      struct pipe_surface *ps = sp->framebuffer.sbuf;
+      if (ps->region && !ps->region->map) {
+         pipe->region_map(pipe, ps->region);
+      }
    }
+}
+
+
+void
+softpipe_map_texture_surfaces(struct softpipe_context *sp)
+{
+   struct pipe_context *pipe = &sp->pipe;
+   uint i;
 
-   /* textures */
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
       struct pipe_mipmap_tree *mt = sp->texture[i];
       if (mt) {
          pipe->region_map(pipe, mt->region);
       }
    }
-
-   /* XXX depth & stencil bufs */
 }
 
 
+/**
+ * Unmap any mapped drawing surfaces
+ */
 void
 softpipe_unmap_surfaces(struct softpipe_context *sp)
 {
    struct pipe_context *pipe = &sp->pipe;
-   unsigned i;
+   uint i;
+
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+      sp_flush_tile_cache(sp->cbuf_cache[i]);
+   sp_flush_tile_cache(sp->zbuf_cache);
+   sp_flush_tile_cache(sp->sbuf_cache);
 
    for (i = 0; i < sp->framebuffer.num_cbufs; i++) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.cbufs[i]);
-      if (sps->surface.region)
-         pipe->region_unmap(pipe, sps->surface.region);
+      struct pipe_surface *ps = sp->framebuffer.cbufs[i];
+      if (ps->region)
+         pipe->region_unmap(pipe, ps->region);
    }
 
    if (sp->framebuffer.zbuf) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.zbuf);
-      if (sps->surface.region)
-         pipe->region_unmap(pipe, sps->surface.region);
+      struct pipe_surface *ps = sp->framebuffer.zbuf;
+      if (ps->region)
+         pipe->region_unmap(pipe, ps->region);
    }
 
-   if (sp->framebuffer.sbuf) {
-      struct softpipe_surface *sps = softpipe_surface(sp->framebuffer.sbuf);
-      if (sps->surface.region)
-         pipe->region_unmap(pipe, sps->surface.region);
+   if (sp->framebuffer.sbuf && sp->framebuffer.sbuf != sp->framebuffer.zbuf) {
+      struct pipe_surface *ps = sp->framebuffer.sbuf;
+      if (ps->region)
+         pipe->region_unmap(pipe, ps->region);
    }
+}
 
-   /* textures */
+
+void
+softpipe_unmap_texture_surfaces(struct softpipe_context *sp)
+{
+   struct pipe_context *pipe = &sp->pipe;
+   uint i;
    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
       struct pipe_mipmap_tree *mt = sp->texture[i];
       if (mt) {
          pipe->region_unmap(pipe, mt->region);
       }
    }
-
-   /* XXX depth & stencil bufs */
 }
 
 
@@ -248,6 +272,7 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
                                      struct softpipe_winsys *softpipe_winsys )
 {
    struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
+   uint i;
 
 #if defined(__i386__) || defined(__386__)
    softpipe->use_sse = getenv("GALLIUM_SSE") != NULL;
@@ -355,5 +380,10 @@ struct pipe_context *softpipe_create( struct pipe_winsys *pipe_winsys,
    sp_init_region_functions(softpipe);
    sp_init_surface_functions(softpipe);
 
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+      softpipe->cbuf_cache[i] = sp_create_tile_cache();
+   softpipe->zbuf_cache = sp_create_tile_cache();
+   softpipe->sbuf_cache_sep = sp_create_tile_cache();
+
    return &softpipe->pipe;
 }
index 4f429e8139795071359e17aebbabf5c22db61a0b..ea05f80d59ab22cf248a812e8b00aa2233398cdd 100644 (file)
@@ -44,6 +44,7 @@ struct softpipe_surface;
 struct softpipe_winsys;
 struct draw_context;
 struct draw_stage;
+struct softpipe_tile_cache;
 
 
 #define SP_NEW_VIEWPORT      0x1
@@ -155,6 +156,13 @@ struct softpipe_context {
 
    struct pipe_surface *cbuf;      /**< current color buffer (one of cbufs) */
 
+   struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
+   struct softpipe_tile_cache *zbuf_cache;
+   /** Stencil buffer cache, for stencil separate from Z */
+   struct softpipe_tile_cache *sbuf_cache_sep;
+   /** This either points to zbuf_cache or sbuf_cache_sep */
+   struct softpipe_tile_cache *sbuf_cache;
+
    int use_sse : 1;
 };
 
index 405659fb464255e27fa2ed89648db7ad7305e1c1..64a4fbe333e0b9b74cf1728029ed3b2ba958678f 100644 (file)
@@ -113,7 +113,7 @@ softpipe_draw_elements(struct pipe_context *pipe,
       softpipe_update_derived( sp );
 
    softpipe_map_surfaces(sp);
-
+   softpipe_map_texture_surfaces(sp);
    softpipe_map_constant_buffers(sp);
 
    /*
@@ -184,7 +184,8 @@ softpipe_draw_elements(struct pipe_context *pipe,
    }
 
 
-   softpipe_unmap_surfaces(sp);
+   /* Note: leave drawing surfaces mapped */
+   softpipe_unmap_texture_surfaces(sp);
    softpipe_unmap_constant_buffers(sp);
 
    return TRUE;
index d4eada822876e9d0aebeb6369bbe701efedc9f61..f2186dbb65304c67c66a09dfedb5d3403c59523f 100644 (file)
@@ -54,10 +54,14 @@ softpipe_flush( struct pipe_context *pipe,
     * - flush the render cache
     */
 
-   for (i = 0; i < softpipe->framebuffer.num_cbufs; i++) {
-      struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.cbufs[i]);
-      if (sps)
-         sp_flush_tile_cache(sps);
-   }
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
+      if (softpipe->cbuf_cache[i])
+         sp_flush_tile_cache(softpipe->cbuf_cache[i]);
+
+   if (softpipe->zbuf_cache)
+      sp_flush_tile_cache(softpipe->zbuf_cache);
+
+   if (softpipe->sbuf_cache)
+      sp_flush_tile_cache(softpipe->sbuf_cache);
 }
 
index 43294e4cd4df2f469151b51834c4b95f64b99fd2..5787b89588d499bf5a5432aa42c28d8fa80cc459 100644 (file)
@@ -101,14 +101,13 @@ static void
 logicop_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
    float dest[4][QUAD_SIZE];
    ubyte src[4][4], dst[4][4], res[4][4];
    uint *src4 = (uint *) src;
    uint *dst4 = (uint *) dst;
    uint *res4 = (uint *) res;
    struct softpipe_cached_tile *
-      tile = sp_get_cached_tile(sps, quad->x0, quad->y0);
+      tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0);
    uint i, j;
 
    /* get/swizzle dest colors */
@@ -220,12 +219,11 @@ static void
 blend_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
    static const float zero[4] = { 0, 0, 0, 0 };
    static const float one[4] = { 1, 1, 1, 1 };
    float source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
    struct softpipe_cached_tile *
-      tile = sp_get_cached_tile(sps, quad->x0, quad->y0);
+      tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0);
    uint i, j;
 
    if (softpipe->blend->logicop_enable) {
index aa69f53580e30085213c28bf26243c088e154ae7..3c0196dd5dcaf6b3a53c574e39bc48201b49c98a 100644 (file)
@@ -47,10 +47,9 @@ static void
 colormask_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
    float dest[4][QUAD_SIZE];
    struct softpipe_cached_tile *
-      tile = sp_get_cached_tile(sps, quad->x0, quad->y0);
+      tile = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0);
    uint i, j;
 
    /* get/swizzle dest colors */
index efd08b981cfb8747ae391c7b006e705d18cf71b1..29231322b8358b43870499194d14280ff778538a 100644 (file)
  * Do depth testing for a quad.
  * Not static since it's used by the stencil code.
  */
+
+/*
+ * To increase efficiency, we should probably have multiple versions
+ * of this function that are specifically for Z16, Z32 and FP Z buffers.
+ * Try to effectively do that with codegen...
+ */
+
 void
 sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
    struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf);
+   const uint format = sps->surface.format;
    unsigned bzzzz[QUAD_SIZE];  /**< Z values fetched from depth buffer */
    unsigned qzzzz[QUAD_SIZE];  /**< Z values from the quad */
    unsigned zmask = 0;
    unsigned j;
-   float scale;
-#if 0
-   struct cached_tile *tile = sp_get_cached_tile(softpipe, quad->x0, quad->y0);
-#endif
+   struct softpipe_cached_tile *tile
+      = sp_get_cached_tile(softpipe->zbuf_cache, quad->x0, quad->y0);
 
    assert(sps); /* shouldn't get here if there's no zbuffer */
 
    /*
-    * To increase efficiency, we should probably have multiple versions
-    * of this function that are specifically for Z16, Z32 and FP Z buffers.
-    * Try to effectively do that with codegen...
-    */
-   if (sps->surface.format == PIPE_FORMAT_U_Z16)
-      scale = 65535.0;
-   else if (sps->surface.format == PIPE_FORMAT_S8_Z24)
-      scale = (float) ((1 << 24) - 1);
-   else
-      assert(0);  /* XXX fix this someday */
-
-   /*
-    * Convert quad's float depth values to int depth values.
+    * Convert quad's float depth values to int depth values (qzzzz).
     * If the Z buffer stores integer values, we _have_ to do the depth
     * compares with integers (not floats).  Otherwise, the float->int->float
     * conversion of Z values (which isn't an identity function) will cause
     * Z-fighting errors.
+    *
+    * Also, get the zbuffer values (bzzzz) from the cached tile.
     */
-   for (j = 0; j < QUAD_SIZE; j++) {
-      qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
-   }
-
-#if 0
-   for (j = 0; j < 4; j++) {
-      int x = quad->x0 % TILE_SIZE + (j & 1);
-      int y = quad->y0 % TILE_SIZE + (j >> 1);
-      bzzzz[j] = tile->depth[y][x];
+   switch (format) {
+   case PIPE_FORMAT_U_Z16:
+      {
+         float scale = 65535.0;
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
+         }
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            bzzzz[j] = tile->data.depth16[y][x];
+         }
+      }
+      break;
+   case PIPE_FORMAT_U_Z32:
+      {
+         double scale = (double) (uint) ~0UL;
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
+         }
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            bzzzz[j] = tile->data.depth32[y][x];
+         }
+      }
+      break;
+   case PIPE_FORMAT_S8_Z24:
+      {
+         float scale = (float) ((1 << 24) - 1);
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            qzzzz[j] = (unsigned) (quad->outputs.depth[j] * scale);
+         }
+
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
+         }
+      }
+      break;
+   default:
+      assert(0);
    }
-#else
-   /* get zquad from zbuffer */
-   sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz);
-#endif
 
    switch (softpipe->depth_stencil->depth.func) {
    case PIPE_FUNC_NEVER:
@@ -151,16 +182,34 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
         }
       }
 
-#if 1
-      /* write updated zquad to zbuffer */
-      sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz);
-#else
-      for (j = 0; j < 4; j++) {
-         int x = quad->x0 % TILE_SIZE + (j & 1);
-         int y = quad->y0 % TILE_SIZE + (j >> 1);
-         tile->depth[y][x] = bzzzz[j];
+      /* put updated Z values back into cached tile */
+      switch (format) {
+      case PIPE_FORMAT_U_Z16:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            tile->data.depth16[y][x] = bzzzz[j];
+         }
+         break;
+      case PIPE_FORMAT_U_Z32:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            tile->data.depth32[y][x] = bzzzz[j];
+         }
+         break;
+      case PIPE_FORMAT_S8_Z24:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->x0 % TILE_SIZE + (j & 1);
+            int y = quad->y0 % TILE_SIZE + (j >> 1);
+            uint s8z24 = tile->data.depth32[y][x];
+            s8z24 = (s8z24 & 0xff000000) | bzzzz[j];
+            tile->data.depth32[y][x] = s8z24;
+         }
+         break;
+      default:
+         assert(0);
       }
-#endif
    }
 }
 
index 01ee06a69c1f5c076119cfb09c7abb9ff6b3f604..e86f42be461ee49b8a6abb8d1086ea4dd70254ee 100644 (file)
@@ -42,9 +42,8 @@ static void
 output_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   struct softpipe_surface *sps = softpipe_surface(softpipe->cbuf);
    struct softpipe_cached_tile *tile
-      = sp_get_cached_tile(sps, quad->x0, quad->y0);
+      = sp_get_cached_tile(softpipe->cbuf_cache[0], quad->x0, quad->y0);
    /* in-tile pos: */
    const int itx = quad->x0 % TILE_SIZE;
    const int ity = quad->y0 % TILE_SIZE;
index bf72bb23cd0cf2666ca8a868d7fd5e999969e277..4a3823d646861a10af762207130ef0442edbea5b 100644 (file)
@@ -7,6 +7,7 @@
 #include "sp_context.h"
 #include "sp_headers.h"
 #include "sp_surface.h"
+#include "sp_tile_cache.h"
 #include "sp_quad.h"
 #include "pipe/p_defines.h"
 #include "pipe/p_util.h"
@@ -200,10 +201,13 @@ static void
 stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   struct softpipe_surface *s_surf = softpipe_surface(softpipe->framebuffer.sbuf);
+   struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.sbuf);
    unsigned func, zFailOp, zPassOp, failOp;
    ubyte ref, wrtMask, valMask;
    ubyte stencilVals[QUAD_SIZE];
+   struct softpipe_cached_tile *tile
+      = sp_get_cached_tile(softpipe->sbuf_cache, quad->x0, quad->y0);
+   uint j;
 
    /* choose front or back face function, operator, etc */
    /* XXX we could do these initializations once per primitive */
@@ -226,8 +230,27 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
       valMask = softpipe->depth_stencil->stencil.value_mask[0];
    }
 
-   assert(s_surf); /* shouldn't get here if there's no stencil buffer */
-   s_surf->read_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+   assert(sps); /* shouldn't get here if there's no stencil buffer */
+
+   /* get stencil values from cached tile */
+   switch (sps->surface.format) {
+   case PIPE_FORMAT_S8_Z24:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         int x = quad->x0 % TILE_SIZE + (j & 1);
+         int y = quad->y0 % TILE_SIZE + (j >> 1);
+         stencilVals[j] = tile->data.depth32[y][x] >> 24;
+      }
+      break;
+   case PIPE_FORMAT_U_S8:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         int x = quad->x0 % TILE_SIZE + (j & 1);
+         int y = quad->y0 % TILE_SIZE + (j >> 1);
+         stencilVals[j] = tile->data.stencil8[y][x];
+      }
+      break;
+   default:
+      assert(0);
+   }
 
    /* do the stencil test first */
    {
@@ -242,7 +265,6 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
    }
 
    if (quad->mask) {
-
       /* now the pixels that passed the stencil test are depth tested */
       if (softpipe->depth_stencil->depth.enabled) {
          const unsigned origMask = quad->mask;
@@ -267,7 +289,27 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
 
    }
 
-   s_surf->write_quad_stencil(s_surf, quad->x0, quad->y0, stencilVals);
+   /* put new stencil values into cached tile */
+   switch (sps->surface.format) {
+   case PIPE_FORMAT_S8_Z24:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         int x = quad->x0 % TILE_SIZE + (j & 1);
+         int y = quad->y0 % TILE_SIZE + (j >> 1);
+         uint s8z24 = tile->data.depth32[y][x];
+         s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
+         tile->data.depth32[y][x] = s8z24;
+      }
+      break;
+   case PIPE_FORMAT_U_S8:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         int x = quad->x0 % TILE_SIZE + (j & 1);
+         int y = quad->y0 % TILE_SIZE + (j >> 1);
+         tile->data.stencil8[y][x] = stencilVals[j];
+      }
+      break;
+   default:
+      assert(0);
+   }
 
    if (quad->mask)
       qs->next->run(qs->next, quad);
index f9061e86e5366a0b95381396b448c0adc0d8e876..c194f0ea0db1276566a9118826a0061e7f20620a 100644 (file)
@@ -141,4 +141,10 @@ softpipe_map_surfaces(struct softpipe_context *sp);
 void
 softpipe_unmap_surfaces(struct softpipe_context *sp);
 
+void
+softpipe_map_texture_surfaces(struct softpipe_context *sp);
+
+void
+softpipe_unmap_texture_surfaces(struct softpipe_context *sp);
+
 #endif
index a534ffb2c2e2a7e9da9581a481958ed16133fd00..cd1e75c563a729e70dea0145177333a5d6a09011 100644 (file)
 #include "sp_context.h"
 #include "sp_state.h"
 #include "sp_surface.h"
+#include "sp_tile_cache.h"
 
 
-/*
+/**
  * XXX this might get moved someday
+ * Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
+ * Here, we map the surfaces and update the tile cache to point to the new
+ * surfaces.
  */
 void
 softpipe_set_framebuffer_state(struct pipe_context *pipe,
                                const struct pipe_framebuffer_state *fb)
 {
-   struct softpipe_context *softpipe = softpipe_context(pipe);
+   struct softpipe_context *sp = softpipe_context(pipe);
+   struct softpipe_surface *sps;
+   uint i;
+
+   for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
+      /* check if changing cbuf */
+      if (sp->framebuffer.cbufs[i] != fb->cbufs[i]) {
+         /* flush old */
+         sp_flush_tile_cache(sp->cbuf_cache[i]);
+         /* unmap old */
+         sps = softpipe_surface(sp->framebuffer.cbufs[i]);
+         if (sps && sps->surface.region)
+            pipe->region_unmap(pipe, sps->surface.region);
+         /* map new */
+         sps = softpipe_surface(fb->cbufs[i]);
+         if (sps)
+            pipe->region_map(pipe, sps->surface.region);
+         /* assign new */
+         sp->framebuffer.cbufs[i] = fb->cbufs[i];
+
+         /* update cache */
+         sp_tile_cache_set_surface(sp->cbuf_cache[i], sps);
+      }
+   }
+
+   sp->framebuffer.num_cbufs = fb->num_cbufs;
+
+   /* zbuf changing? */
+   if (sp->framebuffer.zbuf != fb->zbuf) {
+      /* flush old */
+      sp_flush_tile_cache(sp->zbuf_cache);
+      /* unmap old */
+      sps = softpipe_surface(sp->framebuffer.zbuf);
+      if (sps && sps->surface.region)
+         pipe->region_unmap(pipe, sps->surface.region);
+      if (sp->framebuffer.sbuf == sp->framebuffer.zbuf) {
+         /* combined z/stencil */
+         sp->framebuffer.sbuf = NULL;
+      }
+      /* map new */
+      sps = softpipe_surface(fb->zbuf);
+      if (sps)
+         pipe->region_map(pipe, sps->surface.region);
+      /* assign new */
+      sp->framebuffer.zbuf = fb->zbuf;
+
+      /* update cache */
+      sp_tile_cache_set_surface(sp->zbuf_cache, sps);
+   }
+
+   /* XXX combined depth/stencil here */
+
+   /* sbuf changing? */
+   if (sp->framebuffer.sbuf != fb->sbuf) {
+      /* flush old */
+      sp_flush_tile_cache(sp->sbuf_cache_sep);
+      /* unmap old */
+      sps = softpipe_surface(sp->framebuffer.sbuf);
+      if (sps && sps->surface.region)
+         pipe->region_unmap(pipe, sps->surface.region);
+      /* map new */
+      sps = softpipe_surface(fb->sbuf);
+      if (sps && fb->sbuf != fb->zbuf)
+         pipe->region_map(pipe, sps->surface.region);
+      /* assign new */
+      sp->framebuffer.sbuf = fb->sbuf;
 
-   softpipe->framebuffer = *fb; /* struct copy */
+      /* update cache */
+      if (fb->sbuf != fb->zbuf) {
+         /* separate stencil buf */
+         sp->sbuf_cache = sp->sbuf_cache_sep;
+         sp_tile_cache_set_surface(sp->sbuf_cache, sps);
+      }
+      else {
+         /* combined depth/stencil */
+         sp->sbuf_cache = sp->zbuf_cache;
+         sp_tile_cache_set_surface(sp->sbuf_cache, sps);
+      }
+   }
 
-   softpipe->dirty |= SP_NEW_FRAMEBUFFER;
+   sp->dirty |= SP_NEW_FRAMEBUFFER;
 }
 
 
index 8aad5f6c13e65dd0fb9de810195630fda048c616..fb8c8d082659088fff9fea70be82e64ae93207eb 100644 (file)
 #else
 #define CLIP_TILE \
    do { \
+      if (x >= ps->width) \
+         return; \
+      if (y >= ps->height) \
+         return; \
       if (x + w > ps->width) \
          w = ps->width - x; \
       if (y + h > ps->height) \
@@ -907,13 +911,16 @@ put_tile_raw32(struct pipe_surface *ps,
    unsigned i;
    unsigned w0 = w;
 
+   assert(w < 1000);
    assert(ps->region->map);
    assert(ps->format == PIPE_FORMAT_S8_Z24 ||
           ps->format == PIPE_FORMAT_U_Z32);
 
+   assert(w < 1000);
    CLIP_TILE;
 
    for (i = 0; i < h; i++) {
+   assert(w < 1000);
       memcpy(dst, pSrc, w * sizeof(uint));
       dst += ps->region->pitch;
       pSrc += w0;
@@ -980,8 +987,6 @@ put_tile_raw16(struct pipe_surface *ps,
 void
 softpipe_init_surface_funcs(struct softpipe_surface *sps)
 {
-   sps->tc = sp_create_tile_cache();
-
    assert(sps->surface.format);
 
    switch (sps->surface.format) {
index 431303553fb055428f38c9efa75a9655010bb86f..522f7612ab90473622155bfcadd48f41746c503b 100644 (file)
@@ -46,8 +46,6 @@ struct softpipe_tile_cache;
 struct softpipe_surface {
    struct pipe_surface surface;
 
-   struct softpipe_tile_cache *tc;
-
    /**
     * Functions for read/writing surface data
     */
index 2ecdfc89e4230f9b009a56758a5cfcc277f71fa8..74bd4a3d11c74d3888f640c5d40e37f15ebfc399 100644 (file)
@@ -48,6 +48,7 @@
 
 struct softpipe_tile_cache
 {
+   struct softpipe_surface *surface;  /**< the surface we're caching */
    struct softpipe_cached_tile entries[NUM_ENTRIES];
    uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
 };
@@ -115,45 +116,64 @@ sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
 }
 
 
+void
+sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
+                          struct softpipe_surface *sps)
+{
+   tc->surface = sps;
+}
+
+
+
 
 void
-sp_flush_tile_cache(struct softpipe_surface *sps)
+sp_flush_tile_cache(struct softpipe_tile_cache *tc)
 {
-   struct softpipe_tile_cache *tc = sps->tc;
-   /*
-   struct softpipe_surface *zsurf = softpipe_surface(softpipe->zbuf);
-   */
+   struct pipe_surface *ps = &tc->surface->surface;
+   boolean is_depth_stencil;
    int inuse = 0, pos;
 
+   if (!ps || !ps->region || !ps->region->map)
+      return;
+
+   is_depth_stencil = (ps->format == PIPE_FORMAT_S8_Z24 ||
+                       ps->format == PIPE_FORMAT_U_Z16 ||
+                       ps->format == PIPE_FORMAT_U_Z32 ||
+                       ps->format == PIPE_FORMAT_U_S8);
+
    for (pos = 0; pos < NUM_ENTRIES; pos++) {
       struct softpipe_cached_tile *tile = tc->entries + pos;
       if (tile->x >= 0) {
-         sps->surface.put_tile(&sps->surface,
-                               tile->x,
-                               tile->y,
-                               TILE_SIZE, TILE_SIZE,
-                               (float *) tile->data.color);
-         /*
-         sps->surface.put_tile(&zsurf->surface,
-                               tile->x,
-                               tile->y,
-                               TILE_SIZE, TILE_SIZE,
-                               (float *) tile->depth);
-         */
+         if (is_depth_stencil) {
+            ps->put_tile_raw(ps,
+                             tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+                             tile->data.depth32);
+         }
+         else {
+            ps->put_tile(ps,
+                         tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+                         (float *) tile->data.color);
+         }
 
          tile->x = tile->y = -1;  /* mark as empty */
          inuse++;
       }
    }
-
-   /*printf("flushed tiles in use: %d\n", inuse);*/
+   /*
+   printf("flushed tiles in use: %d\n", inuse);
+   */
 }
 
 
 struct softpipe_cached_tile *
-sp_get_cached_tile(struct softpipe_surface *sps, int x, int y)
+sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y)
 {
-   struct softpipe_tile_cache *tc = sps->tc;
+   struct pipe_surface *ps = &tc->surface->surface;
+   boolean is_depth_stencil
+      = (ps->format == PIPE_FORMAT_S8_Z24 ||
+         ps->format == PIPE_FORMAT_U_Z16 ||
+         ps->format == PIPE_FORMAT_U_Z32 ||
+         ps->format == PIPE_FORMAT_U_S8);
 
    /* tile pos in framebuffer: */
    const int tile_x = x & ~(TILE_SIZE - 1);
@@ -176,13 +196,22 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y)
 
       if (tile->x != -1) {
          /* put dirty tile back in framebuffer */
-         sps->surface.put_tile(&sps->surface, tile->x, tile->y,
-                               TILE_SIZE, TILE_SIZE, (float *) tile->data.color);
+         if (is_depth_stencil) {
+            ps->put_tile_raw(ps,
+                             tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+                             tile->data.depth32);
+         }
+         else {
+            ps->put_tile(ps,
+                         tile->x, tile->y, TILE_SIZE, TILE_SIZE,
+                         (float *) tile->data.color);
+         }
       }
 
-      if (is_clear_flag_set(tc->clear_flags, x, y)) {
-         printf("clear tile\n");
+      if (0/*is_clear_flag_set(tc->clear_flags, x, y)*/) {
+         /* don't get tile from framebuffer, just clear it */
 #if 0
+         printf("clear tile\n");
          uint i, j;
          for (i = 0; i < TILE_SIZE; i++) {
             for (j = 0; j < TILE_SIZE; j++) {
@@ -192,14 +221,24 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y)
                tile->data.color[i][j][3] = 0.5;
             }
          }
+#else
+         (void) is_clear_flag_set;
 #endif
          memset(tile->data.color, 0, sizeof(tile->data.color));
          clear_clear_flag(tc->clear_flags, x, y);
       }
       else {
          /* get new tile from framebuffer */
-         sps->surface.get_tile(&sps->surface, tile_x, tile_y,
-                               TILE_SIZE, TILE_SIZE, (float *) tile->data.color);
+         if (is_depth_stencil) {
+            ps->get_tile_raw(ps,
+                             tile_x, tile_y, TILE_SIZE, TILE_SIZE,
+                             tile->data.depth32);
+         }
+         else {
+            ps->get_tile(ps,
+                         tile_x, tile_y, TILE_SIZE, TILE_SIZE,
+                         (float *) tile->data.color);
+         }
       }
 
       tile->x = tile_x;
@@ -211,8 +250,8 @@ sp_get_cached_tile(struct softpipe_surface *sps, int x, int y)
 
 
 void
-sp_clear_tile_cache(struct softpipe_surface *sps, unsigned clearval)
+sp_clear_tile_cache(struct softpipe_tile_cache *tc, unsigned clearval)
 {
    (void) clearval; /* XXX use this */
-   memset(sps->tc->clear_flags, 255, sizeof(sps->tc->clear_flags));
+   memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
 }
index 4248361f99db3a0e53425e936c2b902589f08fef..80bcac6904dcbcb9429827a8e57d55790c937e0f 100644 (file)
@@ -36,6 +36,9 @@ struct softpipe_context;
 struct softpipe_tile_cache;
 
 
+/**
+ * Cache tile size (width and height). This needs to be a power of two.
+ */
 #define TILE_SIZE 64
 
 
@@ -45,7 +48,9 @@ struct softpipe_cached_tile
    int x, y;         /** pos of tile in window coords */
    union {
       float color[TILE_SIZE][TILE_SIZE][4];
-      uint depth[TILE_SIZE][TILE_SIZE];
+      uint depth32[TILE_SIZE][TILE_SIZE];
+      ushort depth16[TILE_SIZE][TILE_SIZE];
+      ubyte stencil8[TILE_SIZE][TILE_SIZE];
    } data;
 };
 
@@ -57,13 +62,17 @@ extern void
 sp_destroy_tile_cache(struct softpipe_tile_cache *tc);
 
 extern void
-sp_flush_tile_cache(struct softpipe_surface *sps);
+sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
+                          struct softpipe_surface *sps);
 
 extern void
-sp_clear_tile_cache(struct softpipe_surface *sps, unsigned clearval);
+sp_flush_tile_cache(struct softpipe_tile_cache *tc);
+
+extern void
+sp_clear_tile_cache(struct softpipe_tile_cache *tc, unsigned clearval);
 
 extern struct softpipe_cached_tile *
-sp_get_cached_tile(struct softpipe_surface *sps, int x, int y);
+sp_get_cached_tile(struct softpipe_tile_cache *tc, int x, int y);
 
 
 #endif /* SP_TILE_CACHE_H */