Mesa (lp-surface-tiling): llvmpipe: fix cube mapping

Brian Paul brianp at kemper.freedesktop.org
Thu Apr 8 18:21:11 UTC 2010


Module: Mesa
Branch: lp-surface-tiling
Commit: 792c93171ec075664f55720ffed397ac2834a4fc
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=792c93171ec075664f55720ffed397ac2834a4fc

Author: Brian Paul <brianp at vmware.com>
Date:   Thu Apr  8 10:49:01 2010 -0600

llvmpipe: fix cube mapping

---

 src/gallium/drivers/llvmpipe/lp_surface.c |   10 ++-
 src/gallium/drivers/llvmpipe/lp_texture.c |  133 ++++++++++++++++++++++-------
 src/gallium/drivers/llvmpipe/lp_texture.h |    9 ++-
 3 files changed, 115 insertions(+), 37 deletions(-)

diff --git a/src/gallium/drivers/llvmpipe/lp_surface.c b/src/gallium/drivers/llvmpipe/lp_surface.c
index 038fe30..0c4c649 100644
--- a/src/gallium/drivers/llvmpipe/lp_surface.c
+++ b/src/gallium/drivers/llvmpipe/lp_surface.c
@@ -130,8 +130,14 @@ lp_surface_copy(struct pipe_context *pipe,
 
       /* copy */
       {
-         ubyte *src_linear_ptr = src_tex->linear[src->face][src->level].data;
-         ubyte *dst_linear_ptr = dst_tex->linear[dst->face][dst->level].data;
+         const ubyte *src_linear_ptr
+            = llvmpipe_get_texture_image_address(src_tex, src->face,
+                                                 src->level,
+                                                 LP_TEX_LAYOUT_LINEAR);
+         ubyte *dst_linear_ptr
+            = llvmpipe_get_texture_image_address(dst_tex, dst->face,
+                                                 dst->level,
+                                                 LP_TEX_LAYOUT_LINEAR);
 
          util_copy_rect(dst_linear_ptr, format,
                         dst_tex->stride[dst->level],
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c
index b40372f..8e8b81b 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.c
+++ b/src/gallium/drivers/llvmpipe/lp_texture.c
@@ -189,23 +189,21 @@ llvmpipe_texture_destroy(struct pipe_texture *pt)
    }
    else {
       /* regular texture */
-      uint face, level;
+      uint level;
 
-      for (face = 0; face < Elements(lpt->linear); face++) {
-         for (level = 0; level < Elements(lpt->linear[0]); level++) {
-            if (lpt->linear[face][level].data) {
-               align_free(lpt->linear[face][level].data);
-               lpt->linear[face][level].data = NULL;
-            }
+      /* free linear image data */
+      for (level = 0; level < Elements(lpt->linear); level++) {
+         if (lpt->linear[level].data) {
+            align_free(lpt->linear[level].data);
+            lpt->linear[level].data = NULL;
          }
       }
 
-      for (face = 0; face < Elements(lpt->tiled); face++) {
-         for (level = 0; level < Elements(lpt->tiled[0]); level++) {
-            if (lpt->tiled[face][level].data) {
-               align_free(lpt->tiled[face][level].data);
-               lpt->tiled[face][level].data = NULL;
-            }
+      /* free tiled image data */
+      for (level = 0; level < Elements(lpt->tiled); level++) {
+         if (lpt->tiled[level].data) {
+            align_free(lpt->tiled[level].data);
+            lpt->tiled[level].data = NULL;
          }
       }
    }
@@ -261,7 +259,7 @@ llvmpipe_texture_map(struct pipe_texture *texture,
       map = winsys->displaytarget_map(winsys, lpt->dt, dt_usage);
 
       /* install this linear image in texture data structure */
-      lpt->linear[face][level].data = map;
+      lpt->linear[level].data = map;
    }
    else {
       /* regular texture */
@@ -563,14 +561,16 @@ llvmpipe_transfer_unmap(struct pipe_context *pipe,
 
 
 /**
- * Compute size (in bytes) need to store a texture image / mipmap level.
+ * Compute size (in bytes) need to store a texture image / mipmap level,
+ * for just one cube face.
  */
 static unsigned
-tex_image_size(const struct llvmpipe_texture *lpt, unsigned level,
-               enum lp_texture_layout layout)
+tex_image_face_size(const struct llvmpipe_texture *lpt, unsigned level,
+                    enum lp_texture_layout layout)
 {
-   enum pipe_format format = layout == LP_TEX_LAYOUT_LINEAR
-      ? lpt->base.format : PIPE_FORMAT_A8R8G8B8_UNORM;
+   /* for tiled layout, force a 32bpp format */
+   enum pipe_format format = layout == LP_TEX_LAYOUT_TILED
+      ? PIPE_FORMAT_B8G8R8A8_UNORM : lpt->base.format;
    const unsigned height = u_minify(lpt->base.height0, level);
    const unsigned depth = u_minify(lpt->base.depth0, level);
    const unsigned nblocksy =
@@ -578,12 +578,25 @@ tex_image_size(const struct llvmpipe_texture *lpt, unsigned level,
    const unsigned buffer_size =
       nblocksy * lpt->stride[level] *
       (lpt->base.target == PIPE_TEXTURE_3D ? depth : 1);
-
    return buffer_size;
 }
 
 
 /**
+ * Compute size (in bytes) need to store a texture image / mipmap level,
+ * including all cube faces.
+ */
+static unsigned
+tex_image_size(const struct llvmpipe_texture *lpt, unsigned level,
+               enum lp_texture_layout layout)
+{
+   const unsigned buf_size = tex_image_face_size(lpt, level, layout);
+   const unsigned num_faces = lpt->base.target == PIPE_TEXTURE_CUBE ? 6 : 1;
+   return buf_size * num_faces;
+}
+
+
+/**
  * This function encapsulates some complicated logic for determining
  * how to convert a tile of image data from linear layout to tiled
  * layout, or vice versa.
@@ -642,6 +655,34 @@ layout_logic(enum lp_texture_layout cur_layout,
 }
 
 
+/**
+ * Return pointer to a texture image.  No tiled/linear conversion is done.
+ */
+void *
+llvmpipe_get_texture_image_address(struct llvmpipe_texture *lpt,
+                                   unsigned face, unsigned level,
+                                   enum lp_texture_layout layout)
+{
+   struct llvmpipe_texture_image *img;
+   unsigned face_offset;
+
+   if (layout == LP_TEX_LAYOUT_LINEAR) {
+      img = &lpt->linear[level];
+   }
+   else {
+      assert (layout == LP_TEX_LAYOUT_TILED);
+      img = &lpt->tiled[level];
+   }
+
+   if (face > 0)
+      face_offset = face * tex_image_face_size(lpt, level, layout);
+   else
+      face_offset = 0;
+
+   return (ubyte *) img->data + face_offset;
+}
+
+
 
 /**
  * Return pointer to texture image data (either linear or tiled layout).
@@ -668,6 +709,7 @@ llvmpipe_get_texture_image(struct llvmpipe_texture *lpt,
    const unsigned height = u_minify(lpt->base.height0, level);
    const unsigned width_t = align(width, TILE_SIZE) / TILE_SIZE;
    const unsigned height_t = align(height, TILE_SIZE) / TILE_SIZE;
+   enum lp_texture_layout other_layout;
 
    assert(layout == LP_TEX_LAYOUT_NONE ||
           layout == LP_TEX_LAYOUT_TILED ||
@@ -678,17 +720,19 @@ llvmpipe_get_texture_image(struct llvmpipe_texture *lpt,
           usage == LP_TEX_USAGE_WRITE_ALL);
 
    if (lpt->dt) {
-      assert(lpt->linear[face][level].data);
+      assert(lpt->linear[level].data);
    }
 
    /* which is target?  which is other? */
    if (layout == LP_TEX_LAYOUT_LINEAR) {
-      target_img = &lpt->linear[face][level];
-      other_img = &lpt->tiled[face][level];
+      target_img = &lpt->linear[level];
+      other_img = &lpt->tiled[level];
+      other_layout = LP_TEX_LAYOUT_TILED;
    }
    else {
-      target_img = &lpt->tiled[face][level];
-      other_img = &lpt->linear[face][level];
+      target_img = &lpt->tiled[level];
+      other_img = &lpt->linear[level];
+      other_layout = LP_TEX_LAYOUT_LINEAR;
    }
 
    target_data = target_img->data;
@@ -701,6 +745,16 @@ llvmpipe_get_texture_image(struct llvmpipe_texture *lpt,
       target_data = target_img->data;
    }
 
+   if (face > 0) {
+      unsigned offset = face * tex_image_face_size(lpt, level, layout);
+      if (target_data) {
+         target_data = (uint8_t *) target_data + offset;
+      }
+      if (other_data) {
+         other_data = (uint8_t *) other_data + offset;
+      }
+   }
+
    if (layout == LP_TEX_LAYOUT_NONE) {
       /* just allocating memory */
       return target_data;
@@ -783,7 +837,8 @@ llvmpipe_set_texture_tile_layout(struct llvmpipe_texture *lpt,
 /**
  * Get pointer to a linear image where the tile at (x,y) is known to be
  * in linear layout.
- * \return pointer to start of image (not the tile)
+ * Conversion from tiled to linear will be done if necessary.
+ * \return pointer to start of image/face (not the tile)
  */
 ubyte *
 llvmpipe_get_texture_tile_linear(struct llvmpipe_texture *lpt,
@@ -791,8 +846,8 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_texture *lpt,
                                  enum lp_texture_usage usage,
                                  unsigned x, unsigned y)
 {
-   struct llvmpipe_texture_image *tiled_img = &lpt->tiled[face][level];
-   struct llvmpipe_texture_image *linear_img = &lpt->linear[face][level];
+   struct llvmpipe_texture_image *tiled_img = &lpt->tiled[level];
+   struct llvmpipe_texture_image *linear_img = &lpt->linear[level];
    enum lp_texture_layout cur_layout, new_layout;
    const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
    boolean convert;
@@ -820,7 +875,14 @@ llvmpipe_get_texture_tile_linear(struct llvmpipe_texture *lpt,
    if (new_layout != cur_layout)
       llvmpipe_set_texture_tile_layout(lpt, face, level, tx, ty, new_layout);
 
-   return linear_img->data;
+   if (face > 0) {
+      unsigned offset
+         = face * tex_image_face_size(lpt, level, LP_TEX_LAYOUT_LINEAR);
+      return (ubyte *) linear_img->data + offset;
+   }
+   else {
+      return linear_img->data;
+   }
 }
 
 
@@ -835,8 +897,8 @@ llvmpipe_get_texture_tile(struct llvmpipe_texture *lpt,
                           unsigned x, unsigned y)
 {
    const unsigned width = u_minify(lpt->base.width0, level);
-   struct llvmpipe_texture_image *tiled_img = &lpt->tiled[face][level];
-   struct llvmpipe_texture_image *linear_img = &lpt->linear[face][level];
+   struct llvmpipe_texture_image *tiled_img = &lpt->tiled[level];
+   struct llvmpipe_texture_image *linear_img = &lpt->linear[level];
    enum lp_texture_layout cur_layout, new_layout;
    const unsigned tx = x / TILE_SIZE, ty = y / TILE_SIZE;
    boolean convert;
@@ -864,7 +926,7 @@ llvmpipe_get_texture_tile(struct llvmpipe_texture *lpt,
 
    /* compute, return address of the 64x64 tile */
    {
-      unsigned tiles_per_row, tile_offset;
+      unsigned tiles_per_row, tile_offset, face_offset;
 
       tiles_per_row = align(width, TILE_SIZE) / TILE_SIZE;
 
@@ -874,7 +936,12 @@ llvmpipe_get_texture_tile(struct llvmpipe_texture *lpt,
       tile_offset *= TILE_SIZE * TILE_SIZE * 4;
 
       assert(tiled_img->data);
-      return (ubyte *) tiled_img->data + tile_offset;
+
+      face_offset = (face > 0)
+         ? (face * tex_image_face_size(lpt, level, LP_TEX_LAYOUT_TILED))
+         : 0;
+
+      return (ubyte *) tiled_img->data + face_offset + tile_offset;
    }
 }
 
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.h b/src/gallium/drivers/llvmpipe/lp_texture.h
index 47c9212..bac4ff6 100644
--- a/src/gallium/drivers/llvmpipe/lp_texture.h
+++ b/src/gallium/drivers/llvmpipe/lp_texture.h
@@ -95,8 +95,8 @@ struct llvmpipe_texture
    /**
     * Malloc'ed data for regular textures, or a mapping to dt above.
     */
-   struct llvmpipe_texture_image tiled[PIPE_TEX_FACE_MAX][LP_MAX_TEXTURE_LEVELS];
-   struct llvmpipe_texture_image linear[PIPE_TEX_FACE_MAX][LP_MAX_TEXTURE_LEVELS];
+   struct llvmpipe_texture_image tiled[LP_MAX_TEXTURE_LEVELS];
+   struct llvmpipe_texture_image linear[LP_MAX_TEXTURE_LEVELS];
 
    /** per-tile layout info */
    enum lp_texture_layout *layout[PIPE_TEX_FACE_MAX][LP_MAX_TEXTURE_LEVELS];
@@ -162,6 +162,11 @@ llvmpipe_texture_unmap(struct pipe_texture *texture,
                        unsigned zslice);
 
 void *
+llvmpipe_get_texture_image_address(struct llvmpipe_texture *lpt,
+                                   unsigned face, unsigned level,
+                                   enum lp_texture_layout layout);
+
+void *
 llvmpipe_get_texture_image(struct llvmpipe_texture *texture,
                            unsigned face, unsigned level,
                            enum lp_texture_usage usage,




More information about the mesa-commit mailing list