gallium/util: add 1d/2d mipmap generation support
[mesa.git] / src / gallium / auxiliary / util / u_gen_mipmap.c
index e47928b43986215417ef7433b5e939f3e1cfb734..3698be77b2e91e2fa058a5782a3926c5e5a244c2 100644 (file)
 #include "pipe/p_context.h"
 #include "util/u_debug.h"
 #include "pipe/p_defines.h"
-#include "pipe/p_inlines.h"
+#include "util/u_inlines.h"
 #include "pipe/p_shader_tokens.h"
 #include "pipe/p_state.h"
 
+#include "util/u_format.h"
 #include "util/u_memory.h"
 #include "util/u_draw_quad.h"
 #include "util/u_gen_mipmap.h"
 #include "util/u_simple_shaders.h"
+#include "util/u_math.h"
+#include "util/u_texture.h"
+#include "util/u_half.h"
+#include "util/u_surface.h"
 
 #include "cso_cache/cso_context.h"
 
@@ -58,11 +63,13 @@ struct gen_mipmap_state
    struct pipe_depth_stencil_alpha_state depthstencil;
    struct pipe_rasterizer_state rasterizer;
    struct pipe_sampler_state sampler;
+   struct pipe_clip_state clip;
+   struct pipe_vertex_element velem[2];
 
    void *vs;
-   void *fs;
+   void *fs1d, *fs2d, *fs3d, *fsCube, *fs1da, *fs2da;
 
-   struct pipe_buffer *vbuf;  /**< quad vertices */
+   struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
 
    float vertices[4][2][4];   /**< vertex/texcoords for quad */
@@ -84,24 +91,7 @@ enum dtype
 };
 
 
-typedef ushort half_float;
-
-
-static half_float
-float_to_half(float f)
-{
-   /* XXX fix this */
-   return 0;
-}
-
-static float
-half_to_float(half_float h)
-{
-   /* XXX fix this */
-   return 0.0f;
-}
-
-
+typedef uint16_t half_float;
 
 
 /**
@@ -140,7 +130,7 @@ half_to_float(half_float h)
                                 rowC[j][e], rowC[k][e], \
                                 rowD[j][e], rowD[k][e]); \
    } while(0)
-   
+
 #define FILTER_F_3D(e) \
    do { \
       dst[i][e] = (rowA[j][e] + rowA[k][e] \
@@ -151,15 +141,15 @@ half_to_float(half_float h)
 
 #define FILTER_HF_3D(e) \
    do { \
-      const float aj = half_to_float(rowA[j][e]); \
-      const float ak = half_to_float(rowA[k][e]); \
-      const float bj = half_to_float(rowB[j][e]); \
-      const float bk = half_to_float(rowB[k][e]); \
-      const float cj = half_to_float(rowC[j][e]); \
-      const float ck = half_to_float(rowC[k][e]); \
-      const float dj = half_to_float(rowD[j][e]); \
-      const float dk = half_to_float(rowD[k][e]); \
-      dst[i][e] = float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
+      const float aj = util_half_to_float(rowA[j][e]); \
+      const float ak = util_half_to_float(rowA[k][e]); \
+      const float bj = util_half_to_float(rowB[j][e]); \
+      const float bk = util_half_to_float(rowB[k][e]); \
+      const float cj = util_half_to_float(rowC[j][e]); \
+      const float ck = util_half_to_float(rowC[k][e]); \
+      const float dj = util_half_to_float(rowD[j][e]); \
+      const float dk = util_half_to_float(rowD[k][e]); \
+      dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
                                       * 0.125F); \
    } while(0)
 /*@}*/
@@ -338,8 +328,7 @@ do_row(enum dtype datatype, uint comps, int srcWidth,
       }
    }
 
-#if 0
-   else if (datatype == HALF_DTYPE_FLOAT && comps == 4) {
+   else if (datatype == DTYPE_HALF_FLOAT && comps == 4) {
       uint i, j, k, comp;
       const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
       const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
@@ -348,11 +337,11 @@ do_row(enum dtype datatype, uint comps, int srcWidth,
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 4; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -365,11 +354,11 @@ do_row(enum dtype datatype, uint comps, int srcWidth,
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 3; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -382,11 +371,11 @@ do_row(enum dtype datatype, uint comps, int srcWidth,
            i++, j += colStride, k += colStride) {
          for (comp = 0; comp < 2; comp++) {
             float aj, ak, bj, bk;
-            aj = half_to_float(rowA[j][comp]);
-            ak = half_to_float(rowA[k][comp]);
-            bj = half_to_float(rowB[j][comp]);
-            bk = half_to_float(rowB[k][comp]);
-            dst[i][comp] = float_to_half((aj + ak + bj + bk) * 0.25F);
+            aj = util_half_to_float(rowA[j][comp]);
+            ak = util_half_to_float(rowA[k][comp]);
+            bj = util_half_to_float(rowB[j][comp]);
+            bk = util_half_to_float(rowB[k][comp]);
+            dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
          }
       }
    }
@@ -398,14 +387,13 @@ do_row(enum dtype datatype, uint comps, int srcWidth,
       for (i = j = 0, k = k0; i < (uint) dstWidth;
            i++, j += colStride, k += colStride) {
          float aj, ak, bj, bk;
-         aj = half_to_float(rowA[j]);
-         ak = half_to_float(rowA[k]);
-         bj = half_to_float(rowB[j]);
-         bk = half_to_float(rowB[k]);
-         dst[i] = float_to_half((aj + ak + bj + bk) * 0.25F);
+         aj = util_half_to_float(rowA[j]);
+         ak = util_half_to_float(rowA[k]);
+         bj = util_half_to_float(rowB[j]);
+         bk = util_half_to_float(rowB[k]);
+         dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
       }
    }
-#endif
 
    else if (datatype == DTYPE_UINT && comps == 1) {
       uint i, j, k;
@@ -919,29 +907,30 @@ format_to_type_comps(enum pipe_format pformat,
 {
    /* XXX I think this could be implemented in terms of the pf_*() functions */
    switch (pformat) {
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
    case PIPE_FORMAT_B8G8R8A8_UNORM:
    case PIPE_FORMAT_B8G8R8X8_UNORM:
-   case PIPE_FORMAT_R8G8B8A8_SRGB:
-   case PIPE_FORMAT_R8G8B8X8_SRGB:
-   case PIPE_FORMAT_A8R8G8B8_SRGB:
-   case PIPE_FORMAT_X8R8G8B8_SRGB:
+   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_A8B8G8R8_SRGB:
+   case PIPE_FORMAT_X8B8G8R8_SRGB:
    case PIPE_FORMAT_B8G8R8A8_SRGB:
    case PIPE_FORMAT_B8G8R8X8_SRGB:
+   case PIPE_FORMAT_A8R8G8B8_SRGB:
+   case PIPE_FORMAT_X8R8G8B8_SRGB:
    case PIPE_FORMAT_R8G8B8_SRGB:
       *datatype = DTYPE_UBYTE;
       *comps = 4;
       return;
-   case PIPE_FORMAT_A1R5G5B5_UNORM:
+   case PIPE_FORMAT_B5G5R5X1_UNORM:
+   case PIPE_FORMAT_B5G5R5A1_UNORM:
       *datatype = DTYPE_USHORT_1_5_5_5_REV;
       *comps = 4;
       return;
-   case PIPE_FORMAT_A4R4G4B4_UNORM:
+   case PIPE_FORMAT_B4G4R4A4_UNORM:
       *datatype = DTYPE_USHORT_4_4_4_4;
       *comps = 4;
       return;
-   case PIPE_FORMAT_R5G6B5_UNORM:
+   case PIPE_FORMAT_B5G6R5_UNORM:
       *datatype = DTYPE_USHORT_5_6_5;
       *comps = 3;
       return;
@@ -952,8 +941,8 @@ format_to_type_comps(enum pipe_format pformat,
       *datatype = DTYPE_UBYTE;
       *comps = 1;
       return;
-   case PIPE_FORMAT_A8L8_UNORM:
-   case PIPE_FORMAT_A8L8_SRGB:
+   case PIPE_FORMAT_L8A8_UNORM:
+   case PIPE_FORMAT_L8A8_SRGB:
       *datatype = DTYPE_UBYTE;
       *comps = 2;
       return;
@@ -995,7 +984,7 @@ reduce_2d(enum pipe_format pformat,
 {
    enum dtype datatype;
    uint comps;
-   const int bpt = pf_get_size(pformat);
+   const int bpt = util_format_get_blocksize(pformat);
    const ubyte *srcA, *srcB;
    ubyte *dst;
    int row;
@@ -1030,32 +1019,34 @@ reduce_2d(enum pipe_format pformat,
 static void
 reduce_3d(enum pipe_format pformat,
           int srcWidth, int srcHeight, int srcDepth,
-          int srcRowStride, const ubyte *srcPtr,
+          int srcRowStride, int srcImageStride, const ubyte *srcPtr,
           int dstWidth, int dstHeight, int dstDepth,
-          int dstRowStride, ubyte *dstPtr)
+          int dstRowStride, int dstImageStride, ubyte *dstPtr)
 {
-   const int bpt = pf_get_size(pformat);
-   const int border = 0;
+   const int bpt = util_format_get_blocksize(pformat);
    int img, row;
-   int bytesPerSrcImage, bytesPerDstImage;
-   int bytesPerSrcRow, bytesPerDstRow;
    int srcImageOffset, srcRowOffset;
    enum dtype datatype;
    uint comps;
 
    format_to_type_comps(pformat, &datatype, &comps);
 
-   bytesPerSrcImage = srcWidth * srcHeight * bpt;
-   bytesPerDstImage = dstWidth * dstHeight * bpt;
+   /* XXX I think we should rather assert those strides */
+   if (!srcImageStride)
+      srcImageStride = srcWidth * srcHeight * bpt;
+   if (!dstImageStride)
+      dstImageStride = dstWidth * dstHeight * bpt;
 
-   bytesPerSrcRow = srcWidth * bpt;
-   bytesPerDstRow = dstWidth * bpt;
+   if (!srcRowStride)
+      srcRowStride = srcWidth * bpt;
+   if (!dstRowStride)
+      dstRowStride = dstWidth * bpt;
 
    /* Offset between adjacent src images to be averaged together */
-   srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
+   srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride;
 
    /* Offset between adjacent src rows to be averaged together */
-   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
+   srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
 
    /*
     * Need to average together up to 8 src pixels for each dest pixel.
@@ -1066,21 +1057,18 @@ reduce_3d(enum pipe_format pformat,
     */
 
    /*
-   _mesa_printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
+   printf("mip3d %d x %d x %d  ->  %d x %d x %d\n",
           srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
    */
 
    for (img = 0; img < dstDepth; img++) {
-      /* first source image pointer, skipping border */
+      /* first source image pointer */
       const ubyte *imgSrcA = srcPtr
-         + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
-         + img * (bytesPerSrcImage + srcImageOffset);
-      /* second source image pointer, skipping border */
+         + img * (srcImageStride + srcImageOffset);
+      /* second source image pointer */
       const ubyte *imgSrcB = imgSrcA + srcImageOffset;
-      /* address of the dest image, skipping border */
-      ubyte *imgDst = dstPtr
-         + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
-         + img * bytesPerDstImage;
+      /* address of the dest image */
+      ubyte *imgDst = dstPtr + img * dstImageStride;
 
       /* setup the four source row pointers and the dest row pointer */
       const ubyte *srcImgARowA = imgSrcA;
@@ -1096,11 +1084,11 @@ reduce_3d(enum pipe_format pformat,
                    dstWidth, dstImgRow);
 
          /* advance to next rows */
-         srcImgARowA += bytesPerSrcRow + srcRowOffset;
-         srcImgARowB += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowA += bytesPerSrcRow + srcRowOffset;
-         srcImgBRowB += bytesPerSrcRow + srcRowOffset;
-         dstImgRow += bytesPerDstRow;
+         srcImgARowA += srcRowStride + srcRowOffset;
+         srcImgARowB += srcRowStride + srcRowOffset;
+         srcImgBRowA += srcRowStride + srcRowOffset;
+         srcImgBRowB += srcRowStride + srcRowOffset;
+         dstImgRow += dstImageStride;
       }
    }
 }
@@ -1110,152 +1098,154 @@ reduce_3d(enum pipe_format pformat,
 
 static void
 make_1d_mipmap(struct gen_mipmap_state *ctx,
-               struct pipe_texture *pt,
-               uint face, uint baseLevel, uint lastLevel)
+               struct pipe_resource *pt,
+               uint layer, uint baseLevel, uint lastLevel)
 {
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   const uint zslice = 0;
    uint dstLevel;
 
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       void *srcMap, *dstMap;
-      
-      srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
-                                          PIPE_TRANSFER_READ, 0, 0,
-                                          pt->width[srcLevel],
-                                          pt->height[srcLevel]);
-      dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
-                                          PIPE_TRANSFER_WRITE, 0, 0,
-                                          pt->width[dstLevel],
-                                          pt->height[dstLevel]);
-
-      srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
-      dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+      srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
+                                   PIPE_TRANSFER_READ, 0, 0,
+                                   u_minify(pt->width0, srcLevel),
+                                   u_minify(pt->height0, srcLevel));
+      dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   u_minify(pt->width0, dstLevel),
+                                   u_minify(pt->height0, dstLevel));
+
+      srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
+      dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
 
       reduce_1d(pt->format,
-                srcTrans->width, srcMap,
-                dstTrans->width, dstMap);
+                srcTrans->box.width, srcMap,
+                dstTrans->box.width, dstMap);
 
-      screen->transfer_unmap(screen, srcTrans);
-      screen->transfer_unmap(screen, dstTrans);
+      pipe->transfer_unmap(pipe, srcTrans);
+      pipe->transfer_unmap(pipe, dstTrans);
 
-      screen->tex_transfer_destroy(srcTrans);
-      screen->tex_transfer_destroy(dstTrans);
+      pipe->transfer_destroy(pipe, srcTrans);
+      pipe->transfer_destroy(pipe, dstTrans);
    }
 }
 
 
 static void
 make_2d_mipmap(struct gen_mipmap_state *ctx,
-               struct pipe_texture *pt,
-               uint face, uint baseLevel, uint lastLevel)
+               struct pipe_resource *pt,
+               uint layer, uint baseLevel, uint lastLevel)
 {
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   const uint zslice = 0;
    uint dstLevel;
-   
-   assert(pt->block.width == 1);
-   assert(pt->block.height == 1);
+
+   assert(util_format_get_blockwidth(pt->format) == 1);
+   assert(util_format_get_blockheight(pt->format) == 1);
 
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       ubyte *srcMap, *dstMap;
-      
-      srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
-                                          PIPE_TRANSFER_READ, 0, 0,
-                                          pt->width[srcLevel],
-                                          pt->height[srcLevel]);
-      dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
-                                          PIPE_TRANSFER_WRITE, 0, 0,
-                                          pt->width[dstLevel],
-                                          pt->height[dstLevel]);
-
-      srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
-      dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+
+      srcTrans = pipe_get_transfer(pipe, pt, srcLevel, layer,
+                                   PIPE_TRANSFER_READ, 0, 0,
+                                   u_minify(pt->width0, srcLevel),
+                                   u_minify(pt->height0, srcLevel));
+      dstTrans = pipe_get_transfer(pipe, pt, dstLevel, layer,
+                                   PIPE_TRANSFER_WRITE, 0, 0,
+                                   u_minify(pt->width0, dstLevel),
+                                   u_minify(pt->height0, dstLevel));
+
+      srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
+      dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
 
       reduce_2d(pt->format,
-                srcTrans->width, srcTrans->height,
+                srcTrans->box.width, srcTrans->box.height,
                 srcTrans->stride, srcMap,
-                dstTrans->width, dstTrans->height,
+                dstTrans->box.width, dstTrans->box.height,
                 dstTrans->stride, dstMap);
 
-      screen->transfer_unmap(screen, srcTrans);
-      screen->transfer_unmap(screen, dstTrans);
+      pipe->transfer_unmap(pipe, srcTrans);
+      pipe->transfer_unmap(pipe, dstTrans);
 
-      screen->tex_transfer_destroy(srcTrans);
-      screen->tex_transfer_destroy(dstTrans);
+      pipe->transfer_destroy(pipe, srcTrans);
+      pipe->transfer_destroy(pipe, dstTrans);
    }
 }
 
 
+/* XXX looks a bit more like it could work now but need to test */
 static void
 make_3d_mipmap(struct gen_mipmap_state *ctx,
-               struct pipe_texture *pt,
+               struct pipe_resource *pt,
                uint face, uint baseLevel, uint lastLevel)
 {
-#if 0
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
-   uint dstLevel, zslice = 0;
+   uint dstLevel;
+   struct pipe_box src_box, dst_box;
+
+   assert(util_format_get_blockwidth(pt->format) == 1);
+   assert(util_format_get_blockheight(pt->format) == 1);
 
-   assert(pt->block.width == 1);
-   assert(pt->block.height == 1);
+   src_box.x = src_box.y = src_box.z = 0;
+   dst_box.x = dst_box.y = dst_box.z = 0;
 
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
       struct pipe_transfer *srcTrans, *dstTrans;
       ubyte *srcMap, *dstMap;
-      
-      srcTrans = screen->get_tex_transfer(screen, pt, face, srcLevel, zslice,
-                                          PIPE_TRANSFER_READ, 0, 0,
-                                          pt->width[srcLevel],
-                                          pt->height[srcLevel]);
-      dstTrans = screen->get_tex_transfer(screen, pt, face, dstLevel, zslice,
-                                          PIPE_TRANSFER_WRITE, 0, 0,
-                                          pt->width[dstLevel],
-                                          pt->height[dstLevel]);
-
-      srcMap = (ubyte *) screen->transfer_map(screen, srcTrans);
-      dstMap = (ubyte *) screen->transfer_map(screen, dstTrans);
+      struct pipe_box src_box, dst_box;
+      src_box.width = u_minify(pt->width0, srcLevel);
+      src_box.height = u_minify(pt->height0, srcLevel);
+      src_box.depth = u_minify(pt->depth0, srcLevel);
+      dst_box.width = u_minify(pt->width0, dstLevel);
+      dst_box.height = u_minify(pt->height0, dstLevel);
+      dst_box.depth = u_minify(pt->depth0, dstLevel);
+
+      srcTrans = pipe->get_transfer(pipe, pt, srcLevel,
+                                    PIPE_TRANSFER_READ,
+                                    &src_box);
+      dstTrans = pipe->get_transfer(pipe, pt, dstLevel,
+                                    PIPE_TRANSFER_WRITE,
+                                    &dst_box);
+
+      srcMap = (ubyte *) pipe->transfer_map(pipe, srcTrans);
+      dstMap = (ubyte *) pipe->transfer_map(pipe, dstTrans);
 
       reduce_3d(pt->format,
-                srcTrans->width, srcTrans->height,
-                srcTrans->stride, srcMap,
-                dstTrans->width, dstTrans->height,
-                dstTrans->stride, dstMap);
+                srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth,
+                srcTrans->stride, srcTrans->layer_stride, srcMap,
+                dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth,
+                dstTrans->stride, dstTrans->layer_stride, dstMap);
 
-      screen->transfer_unmap(screen, srcTrans);
-      screen->transfer_unmap(screen, dstTrans);
+      pipe->transfer_unmap(pipe, srcTrans);
+      pipe->transfer_unmap(pipe, dstTrans);
 
-      screen->tex_transfer_destroy(srcTrans);
-      screen->tex_transfer_destroy(dstTrans);
+      pipe->transfer_destroy(pipe, srcTrans);
+      pipe->transfer_destroy(pipe, dstTrans);
    }
-#else
-   (void) reduce_3d;
-#endif
 }
 
 
 static void
 fallback_gen_mipmap(struct gen_mipmap_state *ctx,
-                    struct pipe_texture *pt,
-                    uint face, uint baseLevel, uint lastLevel)
+                    struct pipe_resource *pt,
+                    uint layer, uint baseLevel, uint lastLevel)
 {
    switch (pt->target) {
    case PIPE_TEXTURE_1D:
-      make_1d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    case PIPE_TEXTURE_2D:
+   case PIPE_TEXTURE_RECT:
    case PIPE_TEXTURE_CUBE:
-      make_2d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    case PIPE_TEXTURE_3D:
-      make_3d_mipmap(ctx, pt, face, baseLevel, lastLevel);
+      make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
       break;
    default:
       assert(0);
@@ -1284,16 +1274,14 @@ util_create_gen_mipmap(struct pipe_context *pipe,
 
    /* disabled blending/masking */
    memset(&ctx->blend, 0, sizeof(ctx->blend));
-   ctx->blend.colormask = PIPE_MASK_RGBA;
+   ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
 
    /* no-op depth/stencil/alpha */
    memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
 
    /* rasterizer */
    memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
-   ctx->rasterizer.front_winding = PIPE_WINDING_CW;
-   ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
-   ctx->rasterizer.bypass_vs_clip_and_viewport = 1;
+   ctx->rasterizer.cull_face = PIPE_FACE_NONE;
    ctx->rasterizer.gl_rasterization_rules = 1;
 
    /* sampler state */
@@ -1304,6 +1292,15 @@ util_create_gen_mipmap(struct pipe_context *pipe,
    ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
    ctx->sampler.normalized_coords = 1;
 
+   /* vertex elements state */
+   memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
+   for (i = 0; i < 2; i++) {
+      ctx->velem[i].src_offset = i * 4 * sizeof(float);
+      ctx->velem[i].instance_divisor = 0;
+      ctx->velem[i].vertex_buffer_index = 0;
+      ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+   }
+
    /* vertex shader - still needed to specify mapping from fragment
     * shader input semantics to vertex elements 
     */
@@ -1316,7 +1313,19 @@ util_create_gen_mipmap(struct pipe_context *pipe,
    }
 
    /* fragment shader */
-   ctx->fs = util_make_fragment_tex_shader(pipe);
+   ctx->fs1d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_1D,
+                                             TGSI_INTERPOLATE_LINEAR);
+   ctx->fs2d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
+                                             TGSI_INTERPOLATE_LINEAR);
+   ctx->fs3d = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_3D,
+                                               TGSI_INTERPOLATE_LINEAR);
+   ctx->fsCube = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_CUBE,
+                                               TGSI_INTERPOLATE_LINEAR);
+   ctx->fs1da = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_1D_ARRAY,
+                                               TGSI_INTERPOLATE_LINEAR);
+   ctx->fs2da = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D_ARRAY,
+                                               TGSI_INTERPOLATE_LINEAR);
+
 
    /* vertex data that doesn't change */
    for (i = 0; i < 4; i++) {
@@ -1345,8 +1354,8 @@ get_next_slot(struct gen_mipmap_state *ctx)
 
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
-                                     32,
-                                     PIPE_BUFFER_USAGE_VERTEX,
+                                     PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
    
@@ -1357,107 +1366,74 @@ get_next_slot(struct gen_mipmap_state *ctx)
 static unsigned
 set_vertex_data(struct gen_mipmap_state *ctx,
                 enum pipe_texture_target tex_target,
-                uint face, float width, float height)
+                uint layer, float r)
 {
    unsigned offset;
 
    /* vert[0].position */
-   ctx->vertices[0][0][0] = 0.0f; /*x*/
-   ctx->vertices[0][0][1] = 0.0f; /*y*/
+   ctx->vertices[0][0][0] = -1.0f; /*x*/
+   ctx->vertices[0][0][1] = -1.0f; /*y*/
 
    /* vert[1].position */
-   ctx->vertices[1][0][0] = width;
-   ctx->vertices[1][0][1] = 0.0f;
+   ctx->vertices[1][0][0] = 1.0f;
+   ctx->vertices[1][0][1] = -1.0f;
 
    /* vert[2].position */
-   ctx->vertices[2][0][0] = width;
-   ctx->vertices[2][0][1] = height;
+   ctx->vertices[2][0][0] = 1.0f;
+   ctx->vertices[2][0][1] = 1.0f;
 
    /* vert[3].position */
-   ctx->vertices[3][0][0] = 0.0f;
-   ctx->vertices[3][0][1] = height;
+   ctx->vertices[3][0][0] = -1.0f;
+   ctx->vertices[3][0][1] = 1.0f;
 
    /* Setup vertex texcoords.  This is a little tricky for cube maps. */
    if (tex_target == PIPE_TEXTURE_CUBE) {
       static const float st[4][2] = {
          {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
       };
-      float rx, ry, rz;
-      uint i;
-
-      /* loop over quad verts */
-      for (i = 0; i < 4; i++) {
-         /* Compute sc = +/-scale and tc = +/-scale.
-          * Not +/-1 to avoid cube face selection ambiguity near the edges,
-          * though that can still sometimes happen with this scale factor...
-          */
-         const float scale = 0.9999f;
-         const float sc = (2.0f * st[i][0] - 1.0f) * scale;
-         const float tc = (2.0f * st[i][1] - 1.0f) * scale;
-
-         switch (face) {
-         case PIPE_TEX_FACE_POS_X:
-            rx = 1.0f;
-            ry = -tc;
-            rz = -sc;
-            break;
-         case PIPE_TEX_FACE_NEG_X:
-            rx = -1.0f;
-            ry = -tc;
-            rz = sc;
-            break;
-         case PIPE_TEX_FACE_POS_Y:
-            rx = sc;
-            ry = 1.0f;
-            rz = tc;
-            break;
-         case PIPE_TEX_FACE_NEG_Y:
-            rx = sc;
-            ry = -1.0f;
-            rz = -tc;
-            break;
-         case PIPE_TEX_FACE_POS_Z:
-            rx = sc;
-            ry = -tc;
-            rz = 1.0f;
-            break;
-         case PIPE_TEX_FACE_NEG_Z:
-            rx = -sc;
-            ry = -tc;
-            rz = -1.0f;
-            break;
-         default:
-            rx = ry = rz = 0.0f;
-            assert(0);
-         }
 
-         ctx->vertices[i][1][0] = rx; /*s*/
-         ctx->vertices[i][1][1] = ry; /*t*/
-         ctx->vertices[i][1][2] = rz; /*r*/
-      }
+      util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
+                                        &ctx->vertices[0][1][0], 8);
    }
-   else {
-      /* 1D/2D */
+   else if (tex_target == PIPE_TEXTURE_1D_ARRAY) {
+      /* 1D texture array  */
+      ctx->vertices[0][1][0] = 0.0f; /*s*/
+      ctx->vertices[0][1][1] = r; /*t*/
+      ctx->vertices[0][1][2] = 0.0f;    /*r*/
+
+      ctx->vertices[1][1][0] = 1.0f;
+      ctx->vertices[1][1][1] = r;
+      ctx->vertices[1][1][2] = 0.0f;
+
+      ctx->vertices[2][1][0] = 1.0f;
+      ctx->vertices[2][1][1] = r;
+      ctx->vertices[2][1][2] = 0.0f;
+
+      ctx->vertices[3][1][0] = 0.0f;
+      ctx->vertices[3][1][1] = r;
+      ctx->vertices[3][1][2] = 0.0f;
+   } else {
+      /* 1D/2D/3D/2D array */
       ctx->vertices[0][1][0] = 0.0f; /*s*/
       ctx->vertices[0][1][1] = 0.0f; /*t*/
-      ctx->vertices[0][1][2] = 0.0f; /*r*/
+      ctx->vertices[0][1][2] = r;    /*r*/
 
       ctx->vertices[1][1][0] = 1.0f;
       ctx->vertices[1][1][1] = 0.0f;
-      ctx->vertices[1][1][2] = 0.0f;
+      ctx->vertices[1][1][2] = r;
 
       ctx->vertices[2][1][0] = 1.0f;
       ctx->vertices[2][1][1] = 1.0f;
-      ctx->vertices[2][1][2] = 0.0f;
+      ctx->vertices[2][1][2] = r;
 
       ctx->vertices[3][1][0] = 0.0f;
       ctx->vertices[3][1][1] = 1.0f;
-      ctx->vertices[3][1][2] = 0.0f;
+      ctx->vertices[3][1][2] = r;
    }
 
    offset = get_next_slot( ctx );
 
-   pipe_buffer_write_nooverlap(ctx->pipe->screen, ctx->vbuf,
+   pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
                                offset, sizeof(ctx->vertices), ctx->vertices);
 
    return offset;
@@ -1473,10 +1449,15 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
 
+   pipe->delete_fs_state(pipe, ctx->fs2da);
+   pipe->delete_fs_state(pipe, ctx->fs1da);
+   pipe->delete_fs_state(pipe, ctx->fsCube);
+   pipe->delete_fs_state(pipe, ctx->fs3d);
+   pipe->delete_fs_state(pipe, ctx->fs2d);
+   pipe->delete_fs_state(pipe, ctx->fs1d);
    pipe->delete_vs_state(pipe, ctx->vs);
-   pipe->delete_fs_state(pipe, ctx->fs);
 
-   pipe_buffer_reference(&ctx->vbuf, NULL);
+   pipe_resource_reference(&ctx->vbuf, NULL);
 
    FREE(ctx);
 }
@@ -1488,7 +1469,7 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
  */
 void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
 {
-   pipe_buffer_reference(&ctx->vbuf, NULL);
+   pipe_resource_reference(&ctx->vbuf, NULL);
    ctx->vbuf_slot = 0;
 } 
 
@@ -1497,7 +1478,7 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
  * Generate mipmap images.  It's assumed all needed texture memory is
  * already allocated.
  *
- * \param p the texture to generate mipmap levels for
+ * \param psv  the sampler view to the texture to generate mipmap levels for
  * \param face  which cube face to generate mipmaps for (0 for non-cube maps)
  * \param baseLevel  the first mipmap level to use as a src
  * \param lastLevel  the last mipmap level to generate
@@ -1506,14 +1487,15 @@ void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
  */
 void
 util_gen_mipmap(struct gen_mipmap_state *ctx,
-                struct pipe_texture *pt,
+                struct pipe_sampler_view *psv,
                 uint face, uint baseLevel, uint lastLevel, uint filter)
 {
    struct pipe_context *pipe = ctx->pipe;
    struct pipe_screen *screen = pipe->screen;
    struct pipe_framebuffer_state fb;
+   struct pipe_resource *pt = psv->texture;
+   void *fs;
    uint dstLevel;
-   uint zslice = 0;
    uint offset;
 
    /* The texture object should have room for the levels which we're
@@ -1527,9 +1509,33 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    assert(filter == PIPE_TEX_FILTER_LINEAR ||
           filter == PIPE_TEX_FILTER_NEAREST);
 
+   switch (pt->target) {
+   case PIPE_TEXTURE_1D:
+      fs = ctx->fs1d;
+      break;
+   case PIPE_TEXTURE_2D:
+      fs = ctx->fs2d;
+      break;
+   case PIPE_TEXTURE_3D:
+      fs = ctx->fs3d;
+      break;
+   case PIPE_TEXTURE_CUBE:
+      fs = ctx->fsCube;
+      break;
+   case PIPE_TEXTURE_1D_ARRAY:
+      fs = ctx->fs1da;
+      break;
+   case PIPE_TEXTURE_2D_ARRAY:
+      fs = ctx->fs2da;
+      break;
+   default:
+      assert(0);
+      fs = ctx->fs2d;
+   }
+
    /* check if we can render in the texture's format */
-   if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
-                                    PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)) {
+   if (!screen->is_format_supported(screen, psv->format, pt->target,
+                                    pt->nr_samples, PIPE_BIND_RENDER_TARGET, 0)) {
       fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
       return;
    }
@@ -1539,17 +1545,22 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    cso_save_depth_stencil_alpha(ctx->cso);
    cso_save_rasterizer(ctx->cso);
    cso_save_samplers(ctx->cso);
-   cso_save_sampler_textures(ctx->cso);
+   cso_save_fragment_sampler_views(ctx->cso);
    cso_save_framebuffer(ctx->cso);
    cso_save_fragment_shader(ctx->cso);
    cso_save_vertex_shader(ctx->cso);
+   cso_save_viewport(ctx->cso);
+   cso_save_clip(ctx->cso);
+   cso_save_vertex_elements(ctx->cso);
 
    /* bind our state */
    cso_set_blend(ctx->cso, &ctx->blend);
    cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
    cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
+   cso_set_clip(ctx->cso, &ctx->clip);
+   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
 
-   cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+   cso_set_fragment_shader_handle(ctx->cso, fs);
    cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
 
    /* init framebuffer state */
@@ -1566,51 +1577,90 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
     */
    for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
       const uint srcLevel = dstLevel - 1;
-
-      struct pipe_surface *surf = 
-         screen->get_tex_surface(screen, pt, face, dstLevel, zslice,
-                                 PIPE_BUFFER_USAGE_GPU_WRITE);
-
-      /*
-       * Setup framebuffer / dest surface
-       */
-      fb.cbufs[0] = surf;
-      fb.width = pt->width[dstLevel];
-      fb.height = pt->height[dstLevel];
-      cso_set_framebuffer(ctx->cso, &fb);
-
-      /*
-       * Setup sampler state
-       * Note: we should only have to set the min/max LOD clamps to ensure
-       * we grab texels from the right mipmap level.  But some hardware
-       * has trouble with min clamping so we also set the lod_bias to
-       * try to work around that.
-       */
-      ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
-      ctx->sampler.lod_bias = (float) srcLevel;
-      cso_single_sampler(ctx->cso, 0, &ctx->sampler);
-      cso_single_sampler_done(ctx->cso);
-
-      cso_set_sampler_textures(ctx->cso, 1, &pt);
-
-      /* quad coords in window coords (bypassing vs, clip and viewport) */
-      offset = set_vertex_data(ctx,
-                               pt->target,
-                               face,
-                               (float) pt->width[dstLevel],
-                               (float) pt->height[dstLevel]);
-
-      util_draw_vertex_buffer(ctx->pipe, 
-                              ctx->vbuf,
-                              offset,
-                              PIPE_PRIM_TRIANGLE_FAN,
-                              4,  /* verts */
-                              2); /* attribs/vert */
-
-      pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
-      /* need to signal that the texture has changed _after_ rendering to it */
-      pipe_surface_reference( &surf, NULL );
+      struct pipe_viewport_state vp;
+      unsigned nr_layers, layer, i;
+      float rcoord = 0.0f;
+
+      if (pt->target == PIPE_TEXTURE_3D)
+         nr_layers = u_minify(pt->depth0, dstLevel);
+      else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY)
+        nr_layers = pt->array_size;
+      else
+         nr_layers = 1;
+
+      for (i = 0; i < nr_layers; i++) {
+         struct pipe_surface *surf, surf_templ;
+         if (pt->target == PIPE_TEXTURE_3D) {
+            /* in theory with geom shaders and driver with full layer support
+               could do that in one go. */
+            layer = i;
+            /* XXX hmm really? */
+            rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
+         } else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) {
+           layer = i;
+           rcoord = (float)layer;
+        } else
+            layer = face;
+
+         memset(&surf_templ, 0, sizeof(surf_templ));
+         u_surface_default_template(&surf_templ, pt, PIPE_BIND_RENDER_TARGET);
+         surf_templ.u.tex.level = dstLevel;
+         surf_templ.u.tex.first_layer = layer;
+         surf_templ.u.tex.last_layer = layer;
+         surf = pipe->create_surface(pipe, pt, &surf_templ);
+
+         /*
+          * Setup framebuffer / dest surface
+          */
+         fb.cbufs[0] = surf;
+         fb.width = u_minify(pt->width0, dstLevel);
+         fb.height = u_minify(pt->height0, dstLevel);
+         cso_set_framebuffer(ctx->cso, &fb);
+
+         /* viewport */
+         vp.scale[0] = 0.5f * fb.width;
+         vp.scale[1] = 0.5f * fb.height;
+         vp.scale[2] = 1.0f;
+         vp.scale[3] = 1.0f;
+         vp.translate[0] = 0.5f * fb.width;
+         vp.translate[1] = 0.5f * fb.height;
+         vp.translate[2] = 0.0f;
+         vp.translate[3] = 0.0f;
+         cso_set_viewport(ctx->cso, &vp);
+
+         /*
+          * Setup sampler state
+          * Note: we should only have to set the min/max LOD clamps to ensure
+          * we grab texels from the right mipmap level.  But some hardware
+          * has trouble with min clamping so we also set the lod_bias to
+          * try to work around that.
+          */
+         ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
+         ctx->sampler.lod_bias = (float) srcLevel;
+         cso_single_sampler(ctx->cso, 0, &ctx->sampler);
+         cso_single_sampler_done(ctx->cso);
+
+         cso_set_fragment_sampler_views(ctx->cso, 1, &psv);
+
+         /* quad coords in clip coords */
+         offset = set_vertex_data(ctx,
+                                  pt->target,
+                                  face,
+                                  rcoord);
+
+         util_draw_vertex_buffer(ctx->pipe,
+                                 ctx->cso,
+                                 ctx->vbuf,
+                                 offset,
+                                 PIPE_PRIM_TRIANGLE_FAN,
+                                 4,  /* verts */
+                                 2); /* attribs/vert */
+
+         pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+
+         /* need to signal that the texture has changed _after_ rendering to it */
+         pipe_surface_reference( &surf, NULL );
+      }
    }
 
    /* restore state we changed */
@@ -1618,8 +1668,11 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
    cso_restore_depth_stencil_alpha(ctx->cso);
    cso_restore_rasterizer(ctx->cso);
    cso_restore_samplers(ctx->cso);
-   cso_restore_sampler_textures(ctx->cso);
+   cso_restore_fragment_sampler_views(ctx->cso);
    cso_restore_framebuffer(ctx->cso);
    cso_restore_fragment_shader(ctx->cso);
    cso_restore_vertex_shader(ctx->cso);
+   cso_restore_viewport(ctx->cso);
+   cso_restore_clip(ctx->cso);
+   cso_restore_vertex_elements(ctx->cso);
 }