radeon: fix up span function setting
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_texture.c
index beb21e7b431b3f68678cffe1976d0322544e3e7c..63680b495c92cbbe2b566163ddbdcf808d2832e0 100644 (file)
@@ -31,7 +31,9 @@
 #include "main/glheader.h"
 #include "main/imports.h"
 #include "main/context.h"
+#include "main/convolve.h"
 #include "main/mipmap.h"
+#include "main/texcompress.h"
 #include "main/texformat.h"
 #include "main/texstore.h"
 #include "main/teximage.h"
 
 #include "radeon_mipmap_tree.h"
 
+
+static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
+       GLuint numrows, GLuint rowsize)
+{
+       assert(rowsize <= dststride);
+       assert(rowsize <= srcstride);
+
+       if (rowsize == srcstride && rowsize == dststride) {
+               memcpy(dst, src, numrows*rowsize);
+       } else {
+               GLuint i;
+               for(i = 0; i < numrows; ++i) {
+                       memcpy(dst, src, rowsize);
+                       dst += dststride;
+                       src += srcstride;
+               }
+       }
+}
+
 /* textures */
 /**
  * Allocate an empty texture image object.
@@ -453,16 +474,26 @@ static void radeon_teximage(
        radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
        radeonTexObj* t = radeon_tex_obj(texObj);
        radeon_texture_image* image = get_radeon_texture_image(texImage);
+       GLuint dstRowStride;
+       GLint postConvWidth = width;
+       GLint postConvHeight = height;
+       GLuint texelBytes;
 
        radeon_firevertices(rmesa);
 
        t->validated = GL_FALSE;
 
+       if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
+              _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
+                                                 &postConvHeight);
+       }
+
        /* Choose and fill in the texture format for this image */
        texImage->TexFormat = radeonChooseTextureFormat(ctx, internalFormat, format, type);
        _mesa_set_fetch_functions(texImage, dims);
 
        if (texImage->TexFormat->TexelBytes == 0) {
+               texelBytes = 0;
                texImage->IsCompressed = GL_TRUE;
                texImage->CompressedSize =
                        ctx->Driver.CompressedTextureSize(ctx, texImage->Width,
@@ -471,18 +502,40 @@ static void radeon_teximage(
        } else {
                texImage->IsCompressed = GL_FALSE;
                texImage->CompressedSize = 0;
+
+               texelBytes = texImage->TexFormat->TexelBytes;
+               /* Minimum pitch of 32 bytes */
+               if (postConvWidth * texelBytes < 32) {
+                 postConvWidth = 32 / texelBytes;
+                 texImage->RowStride = postConvWidth;
+               }
+               if (!image->mt) {      
+                       assert(texImage->RowStride == postConvWidth);
+               }
        }
 
        /* Allocate memory for image */
        radeonFreeTexImageData(ctx, texImage); /* Mesa core only clears texImage->Data but not image->mt */
 
+       if (t->mt &&
+           t->mt->firstLevel == level &&
+           t->mt->lastLevel == level &&
+           t->mt->target != GL_TEXTURE_CUBE_MAP_ARB &&
+           !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+         radeon_miptree_unreference(t->mt);
+         t->mt = NULL;
+       }
+
        if (!t->mt)
                radeon_try_alloc_miptree(rmesa, t, texImage, face, level);
        if (t->mt && radeon_miptree_matches_image(t->mt, texImage, face, level)) {
+               radeon_mipmap_level *lvl;
                image->mt = t->mt;
                image->mtlevel = level - t->mt->firstLevel;
                image->mtface = face;
                radeon_miptree_reference(t->mt);
+               lvl = &image->mt->levels[image->mtlevel];
+               dstRowStride = lvl->rowstride;
        } else {
                int size;
                if (texImage->IsCompressed) {
@@ -516,6 +569,7 @@ static void radeon_teximage(
                        } else {
                                dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
                        }
+
                        if (!texImage->TexFormat->StoreImage(ctx, dims,
                                                texImage->_BaseFormat,
                                                texImage->TexFormat,
@@ -534,11 +588,11 @@ static void radeon_teximage(
                radeon_generate_mipmap(ctx, texObj->Target, texObj);
        }
 
-       if (pixels) 
-         radeon_teximage_unmap(image);
-
        _mesa_unmap_teximage_pbo(ctx, packing);
 
+       if (pixels)
+         radeon_teximage_unmap(image);
+
 
 }
 
@@ -579,7 +633,7 @@ void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target,
        GLuint face = radeon_face_for_target(target);
 
        radeon_teximage(ctx, 2, face, level, internalFormat, width, height, 1,
-               imageSize, 0, 0, data, 0, texObj, texImage, 1);
+               imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1);
 }
 
 void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
@@ -601,12 +655,13 @@ void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
 static void radeon_texsubimage(GLcontext* ctx, int dims, int level,
                GLint xoffset, GLint yoffset, GLint zoffset,
                GLsizei width, GLsizei height, GLsizei depth,
+               GLsizei imageSize,
                GLenum format, GLenum type,
                const GLvoid * pixels,
                const struct gl_pixelstore_attrib *packing,
                struct gl_texture_object *texObj,
                struct gl_texture_image *texImage,
-                              int compressed)
+               int compressed)
 {
        radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
        radeonTexObj* t = radeon_tex_obj(texObj);
@@ -615,8 +670,13 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, int level,
        radeon_firevertices(rmesa);
 
        t->validated = GL_FALSE;
-       pixels = _mesa_validate_pbo_teximage(ctx, dims,
-               width, height, depth, format, type, pixels, packing, "glTexSubImage1D");
+       if (compressed) {
+               pixels = _mesa_validate_pbo_compressed_teximage(
+                       ctx, imageSize, pixels, packing, "glCompressedTexImage");
+       } else {
+               pixels = _mesa_validate_pbo_teximage(ctx, dims,
+                       width, height, depth, format, type, pixels, packing, "glTexSubImage1D");
+       }
 
        if (pixels) {
                GLint dstRowStride;
@@ -629,15 +689,26 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, int level,
                        dstRowStride = texImage->RowStride * texImage->TexFormat->TexelBytes;
                }
 
-               if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
-                               texImage->TexFormat, texImage->Data,
-                               xoffset, yoffset, zoffset,
-                               dstRowStride,
-                               texImage->ImageOffsets,
-                               width, height, depth,
-                               format, type, pixels, packing))
-                       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
-
+               if (compressed) {
+                       uint32_t srcRowStride, bytesPerRow, rows; 
+                       dstRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, texImage->Width);
+                       srcRowStride = _mesa_compressed_row_stride(texImage->TexFormat->MesaFormat, width);
+                       bytesPerRow = srcRowStride;
+                       rows = height / 4;
+
+                       copy_rows(texImage->Data, dstRowStride,  image->base.Data, srcRowStride, rows,
+                                 bytesPerRow);
+                       
+               } else {
+                       if (!texImage->TexFormat->StoreImage(ctx, dims, texImage->_BaseFormat,
+                                                            texImage->TexFormat, texImage->Data,
+                                                            xoffset, yoffset, zoffset,
+                                                            dstRowStride,
+                                                            texImage->ImageOffsets,
+                                                            width, height, depth,
+                                                            format, type, pixels, packing))
+                               _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
+               }
 
        }
 
@@ -661,7 +732,7 @@ void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
                         struct gl_texture_object *texObj,
                         struct gl_texture_image *texImage)
 {
-       radeon_texsubimage(ctx, 1, level, xoffset, 0, 0, width, 1, 1,
+       radeon_texsubimage(ctx, 1, level, xoffset, 0, 0, width, 1, 1, 0,
                format, type, pixels, packing, texObj, texImage, 0);
 }
 
@@ -674,8 +745,8 @@ void radeonTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
                         struct gl_texture_object *texObj,
                         struct gl_texture_image *texImage)
 {
-       radeon_texsubimage(ctx, 2, level, xoffset, yoffset, 0, width, height,
-                          1, format, type, pixels, packing, texObj, texImage,
+       radeon_texsubimage(ctx, 2, level, xoffset, yoffset, 0, width, height, 1,
+                          0, format, type, pixels, packing, texObj, texImage,
                           0);
 }
 
@@ -688,7 +759,7 @@ void radeonCompressedTexSubImage2D(GLcontext * ctx, GLenum target,
                                   struct gl_texture_image *texImage)
 {
        radeon_texsubimage(ctx, 2, level, xoffset, yoffset, 0, width, height, 1,
-               format, 0, data, 0, texObj, texImage, 1);
+               imageSize, format, 0, data, &ctx->Unpack, texObj, texImage, 1);
 }
 
 
@@ -701,27 +772,10 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
                         struct gl_texture_object *texObj,
                         struct gl_texture_image *texImage)
 {
-       radeon_texsubimage(ctx, 3, level, xoffset, yoffset, zoffset, width, height, depth,
+       radeon_texsubimage(ctx, 3, level, xoffset, yoffset, zoffset, width, height, depth, 0,
                format, type, pixels, packing, texObj, texImage, 0);
 }
 
-static void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
-       GLuint numrows, GLuint rowsize)
-{
-       assert(rowsize <= dststride);
-       assert(rowsize <= srcstride);
-
-       if (rowsize == srcstride && rowsize == dststride) {
-               memcpy(dst, src, numrows*rowsize);
-       } else {
-               GLuint i;
-               for(i = 0; i < numrows; ++i) {
-                       memcpy(dst, src, rowsize);
-                       dst += dststride;
-                       src += srcstride;
-               }
-       }
-}
 
 
 /**
@@ -760,13 +814,22 @@ static void migrate_image_to_miptree(radeon_mipmap_tree *mt, radeon_texture_imag
 
                radeon_miptree_unreference(image->mt);
        } else {
-               uint srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes;
+               uint32_t srcrowstride;
+               uint32_t height;
+               /* need to confirm this value is correct */
+               if (mt->compressed) {
+                       height = image->base.Height / 4;
+                       srcrowstride = image->base.RowStride * mt->bpp;
+               } else {
+                       height = image->base.Height * image->base.Depth;
+                       srcrowstride = image->base.Width * image->base.TexFormat->TexelBytes;
+               }
 
 //             if (mt->tilebits)
 //                     WARN_ONCE("%s: tiling not supported yet", __FUNCTION__);
 
                copy_rows(dest, dstlvl->rowstride, image->base.Data, srcrowstride,
-                       image->base.Height * image->base.Depth, srcrowstride);
+                         height, srcrowstride);
 
                _mesa_free_texmemory(image->base.Data);
                image->base.Data = 0;
@@ -847,3 +910,57 @@ int radeon_validate_texture_miptree(GLcontext * ctx, struct gl_texture_object *t
 
        return GL_TRUE;
 }
+
+
+/**
+ * Need to map texture image into memory before copying image data,
+ * then unmap it.
+ */
+static void
+radeon_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
+                    GLenum format, GLenum type, GLvoid * pixels,
+                    struct gl_texture_object *texObj,
+                    struct gl_texture_image *texImage, int compressed)
+{
+       radeon_texture_image *image = get_radeon_texture_image(texImage);
+
+       if (image->mt) {
+               /* Map the texture image read-only */
+               radeon_teximage_map(image, GL_FALSE);
+       } else {
+               /* Image hasn't been uploaded to a miptree yet */
+               assert(image->base.Data);
+       }
+
+       if (compressed) {
+               _mesa_get_compressed_teximage(ctx, target, level, pixels,
+                                             texObj, texImage);
+       } else {
+               _mesa_get_teximage(ctx, target, level, format, type, pixels,
+                                  texObj, texImage);
+       }
+     
+       if (image->mt) {
+               radeon_teximage_unmap(image);
+       }
+}
+
+void
+radeonGetTexImage(GLcontext * ctx, GLenum target, GLint level,
+                 GLenum format, GLenum type, GLvoid * pixels,
+                 struct gl_texture_object *texObj,
+                 struct gl_texture_image *texImage)
+{
+       radeon_get_tex_image(ctx, target, level, format, type, pixels,
+                            texObj, texImage, 0);
+}
+
+void
+radeonGetCompressedTexImage(GLcontext *ctx, GLenum target, GLint level,
+                           GLvoid *pixels,
+                           struct gl_texture_object *texObj,
+                           struct gl_texture_image *texImage)
+{
+       radeon_get_tex_image(ctx, target, level, 0, 0, pixels,
+                            texObj, texImage, 1);
+}