gallium/util: add 1d/2d mipmap generation support
[mesa.git] / src / gallium / auxiliary / util / u_gen_mipmap.c
index d4716bffe470009a76140aeff9392accfe46f931..3698be77b2e91e2fa058a5782a3926c5e5a244c2 100644 (file)
@@ -67,7 +67,7 @@ struct gen_mipmap_state
    struct pipe_vertex_element velem[2];
 
    void *vs;
-   void *fs1d, *fs2d, *fs3d, *fsCube;
+   void *fs1d, *fs2d, *fs3d, *fsCube, *fs1da, *fs2da;
 
    struct pipe_resource *vbuf;  /**< quad vertices */
    unsigned vbuf_slot;
@@ -1068,8 +1068,7 @@ reduce_3d(enum pipe_format pformat,
       /* second source image pointer */
       const ubyte *imgSrcB = imgSrcA + srcImageOffset;
       /* address of the dest image */
-      ubyte *imgDst = dstPtr
-         + img * dstImageStride;
+      ubyte *imgDst = dstPtr + img * dstImageStride;
 
       /* setup the four source row pointers and the dest row pointer */
       const ubyte *srcImgARowA = imgSrcA;
@@ -1322,6 +1321,11 @@ util_create_gen_mipmap(struct pipe_context *pipe,
                                                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++) {
@@ -1351,6 +1355,7 @@ get_next_slot(struct gen_mipmap_state *ctx)
    if (!ctx->vbuf) {
       ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
                                      PIPE_BIND_VERTEX_BUFFER,
+                                     PIPE_USAGE_STREAM,
                                      max_slots * sizeof ctx->vertices);
    }
    
@@ -1390,8 +1395,25 @@ set_vertex_data(struct gen_mipmap_state *ctx,
       util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
                                         &ctx->vertices[0][1][0], 8);
    }
-   else {
-      /* 1D/2D/3D */
+   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] = r;    /*r*/
@@ -1427,9 +1449,13 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
 {
    struct pipe_context *pipe = ctx->pipe;
 
-   pipe->delete_vs_state(pipe, ctx->vs);
-   pipe->delete_fs_state(pipe, ctx->fs2d);
+   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_resource_reference(&ctx->vbuf, NULL);
 
@@ -1497,7 +1523,11 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
       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;
@@ -1553,7 +1583,10 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
 
       if (pt->target == PIPE_TEXTURE_3D)
          nr_layers = u_minify(pt->depth0, dstLevel);
-      else nr_layers = 1;
+      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;
@@ -1561,11 +1594,12 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
             /* in theory with geom shaders and driver with full layer support
                could do that in one go. */
             layer = i;
-            offset = 1.0f / (float)(nr_layers * 2);
             /* XXX hmm really? */
             rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
-         }
-         else
+         } 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));
@@ -1614,7 +1648,8 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
                                   face,
                                   rcoord);
 
-         util_draw_vertex_buffer(ctx->pipe, 
+         util_draw_vertex_buffer(ctx->pipe,
+                                 ctx->cso,
                                  ctx->vbuf,
                                  offset,
                                  PIPE_PRIM_TRIANGLE_FAN,