glsl_to_tgsi: use swizzle_for_size for src reg in conditional moves
[mesa.git] / src / mesa / state_tracker / st_texture.c
index add6e949dfb68facd7e3c90f8fd1c8ffd9c5d1eb..ffe7e256a56163363605440edfae5f7d68169e16 100644 (file)
@@ -59,15 +59,18 @@ st_texture_create(struct st_context *st,
                  GLuint width0,
                  GLuint height0,
                  GLuint depth0,
+                  GLuint layers,
                   GLuint bind )
 {
    struct pipe_resource pt, *newtex;
    struct pipe_screen *screen = st->pipe->screen;
 
-   assert(target <= PIPE_TEXTURE_CUBE);
+   assert(target < PIPE_MAX_TEXTURE_TYPES);
    assert(width0 > 0);
    assert(height0 > 0);
    assert(depth0 > 0);
+   if (target == PIPE_TEXTURE_CUBE)
+      assert(layers == 6);
 
    DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
        _mesa_lookup_enum_by_nr(target),
@@ -75,7 +78,7 @@ st_texture_create(struct st_context *st,
 
    assert(format);
    assert(screen->is_format_supported(screen, format, target, 0,
-                                      PIPE_BIND_SAMPLER_VIEW, 0));
+                                      PIPE_BIND_SAMPLER_VIEW));
 
    memset(&pt, 0, sizeof(pt));
    pt.target = target;
@@ -84,6 +87,7 @@ st_texture_create(struct st_context *st,
    pt.width0 = width0;
    pt.height0 = height0;
    pt.depth0 = depth0;
+   pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : layers);
    pt.usage = PIPE_USAGE_DEFAULT;
    pt.bind = bind;
    pt.flags = 0;
@@ -96,6 +100,72 @@ st_texture_create(struct st_context *st,
 }
 
 
+/**
+ * In OpenGL the number of 1D array texture layers is the "height" and
+ * the number of 2D array texture layers is the "depth".  In Gallium the
+ * number of layers in an array texture is a separate 'array_size' field.
+ * This function converts dimensions from the former to the later.
+ */
+void
+st_gl_texture_dims_to_pipe_dims(GLenum texture,
+                                GLuint widthIn,
+                                GLuint heightIn,
+                                GLuint depthIn,
+                                GLuint *widthOut,
+                                GLuint *heightOut,
+                                GLuint *depthOut,
+                                GLuint *layersOut)
+{
+   switch (texture) {
+   case GL_TEXTURE_1D:
+      assert(heightIn == 1);
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = 1;
+      *depthOut = 1;
+      *layersOut = 1;
+      break;
+   case GL_TEXTURE_1D_ARRAY:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = 1;
+      *depthOut = 1;
+      *layersOut = heightIn;
+      break;
+   case GL_TEXTURE_2D:
+   case GL_TEXTURE_RECTANGLE:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = 1;
+      break;
+   case GL_TEXTURE_CUBE_MAP:
+      assert(depthIn == 1);
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = 6;
+      break;
+   case GL_TEXTURE_2D_ARRAY:
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = 1;
+      *layersOut = depthIn;
+      break;
+   default:
+      assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
+      /* fall-through */
+   case GL_TEXTURE_3D:
+      *widthOut = widthIn;
+      *heightOut = heightIn;
+      *depthOut = depthIn;
+      *layersOut = 1;
+      break;
+   }
+}
+
+
 /**
  * Check if a texture image can be pulled into a unified mipmap texture.
  */
@@ -104,6 +174,8 @@ st_texture_match_image(const struct pipe_resource *pt,
                        const struct gl_texture_image *image,
                        GLuint face, GLuint level)
 {
+   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
+
    /* Images with borders are never pulled into mipmap textures. 
     */
    if (image->Border) 
@@ -114,12 +186,17 @@ st_texture_match_image(const struct pipe_resource *pt,
    if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
       return GL_FALSE;
 
+   st_gl_texture_dims_to_pipe_dims(image->TexObject->Target,
+                                   image->Width, image->Height, image->Depth,
+                                   &ptWidth, &ptHeight, &ptDepth, &ptLayers);
+
    /* Test if this image's size matches what's expected in the
     * established texture.
     */
-   if (image->Width != u_minify(pt->width0, level) ||
-       image->Height != u_minify(pt->height0, level) ||
-       image->Depth != u_minify(pt->depth0, level))
+   if (ptWidth != u_minify(pt->width0, level) ||
+       ptHeight != u_minify(pt->height0, level) ||
+       ptDepth != u_minify(pt->depth0, level) ||
+       ptLayers != pt->array_size)
       return GL_FALSE;
 
    return GL_TRUE;
@@ -136,7 +213,7 @@ st_texture_match_image(const struct pipe_resource *pt,
  */
 GLubyte *
 st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
-                    GLuint zoffset, enum pipe_transfer_usage usage,
+                     GLuint zoffset, enum pipe_transfer_usage usage,
                      GLuint x, GLuint y, GLuint w, GLuint h)
 {
    struct pipe_context *pipe = st->pipe;
@@ -144,9 +221,9 @@ st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
 
    DBG("%s \n", __FUNCTION__);
 
-   stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->face,
-                                                   stImage->level, zoffset,
-                                                   usage, x, y, w, h);
+   stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->level,
+                                         stImage->face + zoffset,
+                                         usage, x, y, w, h);
 
    if (stImage->transfer)
       return pipe_transfer_map(pipe, stImage->transfer);
@@ -211,18 +288,24 @@ st_texture_image_data(struct st_context *st,
                       GLuint src_row_stride, GLuint src_image_stride)
 {
    struct pipe_context *pipe = st->pipe;
-   GLuint depth = u_minify(dst->depth0, level);
    GLuint i;
    const GLubyte *srcUB = src;
    struct pipe_transfer *dst_transfer;
+   GLuint layers;
+
+   if (dst->target == PIPE_TEXTURE_1D_ARRAY ||
+       dst->target == PIPE_TEXTURE_2D_ARRAY)
+      layers = dst->array_size;
+   else
+      layers = u_minify(dst->depth0, level);
 
    DBG("%s\n", __FUNCTION__);
 
-   for (i = 0; i < depth; i++) {
-      dst_transfer = pipe_get_transfer(st->pipe, dst, face, level, i,
-                                                 PIPE_TRANSFER_WRITE, 0, 0,
-                                                 u_minify(dst->width0, level),
-                                                  u_minify(dst->height0, level));
+   for (i = 0; i < layers; i++) {
+      dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i,
+                                       PIPE_TRANSFER_WRITE, 0, 0,
+                                       u_minify(dst->width0, level),
+                                       u_minify(dst->height0, level));
 
       st_surface_data(pipe, dst_transfer,
                      0, 0,                             /* dstx, dsty */
@@ -230,7 +313,7 @@ st_texture_image_data(struct st_context *st,
                      src_row_stride,
                      0, 0,                             /* source x, y */
                      u_minify(dst->width0, level),
-                      u_minify(dst->height0, level));      /* width, height */
+                      u_minify(dst->height0, level));    /* width, height */
 
       pipe->transfer_destroy(pipe, dst_transfer);
 
@@ -245,14 +328,10 @@ st_texture_image_data(struct st_context *st,
 static void
 print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
 {
-   struct pipe_subresource rect;
    struct pipe_transfer *xfer;
    struct pipe_box region;
    ubyte *map;
 
-   rect.face = 0;
-   rect.level = 0;
-
    region.x = src->width0 / 2;
    region.y = src->height0 / 2;
    region.z = 0;
@@ -260,7 +339,7 @@ print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
    region.height = 1;
    region.depth = 1;
 
-   xfer = pipe->get_transfer(pipe, src, rect, PIPE_TRANSFER_READ, &region);
+   xfer = pipe->get_transfer(pipe, src, 0, PIPE_TRANSFER_READ, &region);
    map = pipe->transfer_map(pipe, xfer);
 
    printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
@@ -282,22 +361,26 @@ st_texture_image_copy(struct pipe_context *pipe,
                       struct pipe_resource *src, GLuint srcLevel,
                       GLuint face)
 {
-   GLuint width = u_minify(dst->width0, dstLevel); 
-   GLuint height = u_minify(dst->height0, dstLevel); 
-   GLuint depth = u_minify(dst->depth0, dstLevel); 
-   struct pipe_subresource dstsub, srcsub;
+   GLuint width = u_minify(dst->width0, dstLevel);
+   GLuint height = u_minify(dst->height0, dstLevel);
+   GLuint depth = u_minify(dst->depth0, dstLevel);
+   struct pipe_box src_box;
    GLuint i;
 
    assert(u_minify(src->width0, srcLevel) == width);
    assert(u_minify(src->height0, srcLevel) == height);
    assert(u_minify(src->depth0, srcLevel) == depth);
 
-   dstsub.face = face;
-   dstsub.level = dstLevel;
-   srcsub.face = face;
-   srcsub.level = srcLevel;
+   src_box.x = 0;
+   src_box.y = 0;
+   src_box.width = width;
+   src_box.height = height;
+   src_box.depth = 1;
    /* Loop over 3D image slices */
-   for (i = 0; i < depth; i++) {
+   /* could (and probably should) use "true" 3d box here -
+      but drivers can't quite handle it yet */
+   for (i = face; i < face + depth; i++) {
+      src_box.z = i;
 
       if (0)  {
          print_center_pixel(pipe, src);
@@ -305,12 +388,11 @@ st_texture_image_copy(struct pipe_context *pipe,
 
       pipe->resource_copy_region(pipe,
                                  dst,
-                                 dstsub,
+                                 dstLevel,
                                  0, 0, i,/* destX, Y, Z */
                                  src,
-                                 srcsub,
-                                 0, 0, i,/* srcX, Y, Z */
-                                 width, height);
+                                 srcLevel,
+                                 &src_box);
    }
 }