radeon: Implement GL_OES_EGL_image
[mesa.git] / src / mesa / drivers / dri / radeon / radeon_texture.c
index 20a27ad9a70e8994c1b9bdb10e0d12c123a8a5be..8b1e34fe7669cdb122359654fc1d579e8545225d 100644 (file)
 #include "main/glheader.h"
 #include "main/imports.h"
 #include "main/context.h"
-#include "main/convolve.h"
+#include "main/enums.h"
 #include "main/mipmap.h"
 #include "main/texcompress.h"
 #include "main/texstore.h"
 #include "main/teximage.h"
 #include "main/texobj.h"
-#include "main/texgetimage.h"
+#include "drivers/common/meta.h"
 
 #include "xmlpool.h"           /* for symbolic values of enum-type options */
 
@@ -53,6 +53,13 @@ void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
        assert(rowsize <= dststride);
        assert(rowsize <= srcstride);
 
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s dst %p, stride %u, src %p, stride %u, "
+               "numrows %u, rowsize %u.\n",
+               __func__, dst, dststride,
+               src, srcstride,
+               numrows, rowsize);
+
        if (rowsize == srcstride && rowsize == dststride) {
                memcpy(dst, src, numrows*rowsize);
        } else {
@@ -69,7 +76,7 @@ void copy_rows(void* dst, GLuint dststride, const void* src, GLuint srcstride,
 /**
  * Allocate an empty texture image object.
  */
-struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx)
+struct gl_texture_image *radeonNewTextureImage(struct gl_context *ctx)
 {
        return CALLOC(sizeof(radeon_texture_image));
 }
@@ -77,7 +84,7 @@ struct gl_texture_image *radeonNewTextureImage(GLcontext *ctx)
 /**
  * Free memory associated with this texture image.
  */
-void radeonFreeTexImageData(GLcontext *ctx, struct gl_texture_image *timage)
+void radeonFreeTexImageData(struct gl_context *ctx, struct gl_texture_image *timage)
 {
        radeon_texture_image* image = get_radeon_texture_image(timage);
 
@@ -102,8 +109,12 @@ static void teximage_set_map_data(radeon_texture_image *image)
 {
        radeon_mipmap_level *lvl;
 
-       if (!image->mt)
+       if (!image->mt) {
+               radeon_warning("%s(%p) Trying to set map data without miptree.\n",
+                               __func__, image);
+
                return;
+       }
 
        lvl = &image->mt->levels[image->mtlevel];
 
@@ -117,6 +128,10 @@ static void teximage_set_map_data(radeon_texture_image *image)
  */
 void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable)
 {
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(img %p), write_enable %s.\n",
+                       __func__, image,
+                       write_enable ? "true": "false");
        if (image->mt) {
                assert(!image->base.Data);
 
@@ -128,6 +143,9 @@ void radeon_teximage_map(radeon_texture_image *image, GLboolean write_enable)
 
 void radeon_teximage_unmap(radeon_texture_image *image)
 {
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(img %p)\n",
+                       __func__, image);
        if (image->mt) {
                assert(image->base.Data);
 
@@ -136,7 +154,7 @@ void radeon_teximage_unmap(radeon_texture_image *image)
        }
 }
 
-static void map_override(GLcontext *ctx, radeonTexObj *t)
+static void map_override(struct gl_context *ctx, radeonTexObj *t)
 {
        radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
 
@@ -145,7 +163,7 @@ static void map_override(GLcontext *ctx, radeonTexObj *t)
        img->base.Data = t->bo->ptr;
 }
 
-static void unmap_override(GLcontext *ctx, radeonTexObj *t)
+static void unmap_override(struct gl_context *ctx, radeonTexObj *t)
 {
        radeon_texture_image *img = get_radeon_texture_image(t->base.Image[0][0]);
 
@@ -157,20 +175,36 @@ static void unmap_override(GLcontext *ctx, radeonTexObj *t)
 /**
  * Map a validated texture for reading during software rendering.
  */
-void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
+void radeonMapTexture(struct gl_context *ctx, struct gl_texture_object *texObj)
 {
        radeonTexObj* t = radeon_tex_obj(texObj);
        int face, level;
 
-       if (!radeon_validate_texture_miptree(ctx, texObj))
-         return;
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p)\n",
+                       __func__, ctx, texObj);
+
+       if (!radeon_validate_texture_miptree(ctx, texObj)) {
+               radeon_error("%s(%p, tex %p) Failed to validate miptree for "
+                       "sw fallback.\n",
+                       __func__, ctx, texObj);
+               return;
+       }
+
+       if (t->image_override && t->bo) {
+               radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p) Work around for missing miptree in r100.\n",
+                       __func__, ctx, texObj);
 
-       /* for r100 3D sw fallbacks don't have mt */
-       if (t->image_override && t->bo)
                map_override(ctx, t);
+       }
 
-       if (!t->mt)
+       /* for r100 3D sw fallbacks don't have mt */
+       if (!t->mt) {
+               radeon_warning("%s(%p, tex %p) No miptree in texture.\n",
+                       __func__, ctx, texObj);
                return;
+       }
 
        radeon_bo_map(t->mt->bo, GL_FALSE);
        for(face = 0; face < t->mt->faces; ++face) {
@@ -179,11 +213,15 @@ void radeonMapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
        }
 }
 
-void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
+void radeonUnmapTexture(struct gl_context *ctx, struct gl_texture_object *texObj)
 {
        radeonTexObj* t = radeon_tex_obj(texObj);
        int face, level;
 
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p)\n",
+                       __func__, ctx, texObj);
+
        if (t->image_override && t->bo)
                unmap_override(ctx, t);
        /* for r100 3D sw fallbacks don't have mt */
@@ -203,13 +241,17 @@ void radeonUnmapTexture(GLcontext *ctx, struct gl_texture_object *texObj)
  * This relies on internal details of _mesa_generate_mipmap, in particular
  * the fact that the memory for recreated texture images is always freed.
  */
-static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
+static void radeon_generate_mipmap(struct gl_context *ctx, GLenum target,
                                   struct gl_texture_object *texObj)
 {
        radeonTexObj* t = radeon_tex_obj(texObj);
        GLuint nr_faces = (t->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
        int i, face;
 
+       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                       "%s(%p, tex %p) Target type %s.\n",
+                       __func__, ctx, texObj,
+                       _mesa_lookup_enum_by_nr(target));
 
        _mesa_generate_mipmap(ctx, target, texObj);
 
@@ -231,14 +273,34 @@ static void radeon_generate_mipmap(GLcontext *ctx, GLenum target,
        
 }
 
-void radeonGenerateMipmap(GLcontext* ctx, GLenum target, struct gl_texture_object *texObj)
+void radeonGenerateMipmap(struct gl_context* ctx, GLenum target, struct gl_texture_object *texObj)
 {
+       radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
+       struct radeon_bo *bo;
        GLuint face = _mesa_tex_target_to_face(target);
        radeon_texture_image *baseimage = get_radeon_texture_image(texObj->Image[face][texObj->BaseLevel]);
+       bo = !baseimage->mt ? baseimage->bo : baseimage->mt->bo;
+
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s(%p, target %s, tex %p)\n",
+               __func__, ctx, _mesa_lookup_enum_by_nr(target),
+               texObj);
+
+       if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+               radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s(%p, tex %p) Trying to generate mipmap for texture "
+                       "in processing by GPU.\n",
+                       __func__, ctx, texObj);
+               radeon_firevertices(rmesa);
+       }
 
-       radeon_teximage_map(baseimage, GL_FALSE);
-       radeon_generate_mipmap(ctx, target, texObj);
-       radeon_teximage_unmap(baseimage);
+       if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) {
+               radeon_teximage_map(baseimage, GL_FALSE);
+               radeon_generate_mipmap(ctx, target, texObj);
+               radeon_teximage_unmap(baseimage);
+       } else {
+               _mesa_meta_GenerateMipmap(ctx, target, texObj);
+       }
 }
 
 
@@ -276,7 +338,7 @@ static gl_format radeonChoose8888TexFormat(radeonContextPtr rmesa,
                return _dri_texformat_argb8888;
 }
 
-gl_format radeonChooseTextureFormat_mesa(GLcontext * ctx,
+gl_format radeonChooseTextureFormat_mesa(struct gl_context * ctx,
                                         GLint internalFormat,
                                         GLenum format,
                                         GLenum type)
@@ -285,7 +347,7 @@ gl_format radeonChooseTextureFormat_mesa(GLcontext * ctx,
                                         type, 0);
 }
 
-gl_format radeonChooseTextureFormat(GLcontext * ctx,
+gl_format radeonChooseTextureFormat(struct gl_context * ctx,
                                    GLint internalFormat,
                                    GLenum format,
                                    GLenum type, GLboolean fbo)
@@ -297,12 +359,14 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
            (rmesa->texture_depth == DRI_CONF_TEXTURE_DEPTH_FORCE_16);
        (void)format;
 
-#if 0
-       fprintf(stderr, "InternalFormat=%s(%d) type=%s format=%s\n",
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+               "%s InternalFormat=%s(%d) type=%s format=%s\n",
+               __func__,
                _mesa_lookup_enum_by_nr(internalFormat), internalFormat,
                _mesa_lookup_enum_by_nr(type), _mesa_lookup_enum_by_nr(format));
-       fprintf(stderr, "do32bpt=%d force16bpt=%d\n", do32bpt, force16bpt);
-#endif
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+                       "%s do32bpt=%d force16bpt=%d\n",
+                       __func__, do32bpt, force16bpt);
 
        switch (internalFormat) {
        case 4:
@@ -486,7 +550,7 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
        case GL_SRGB8_ALPHA8:
        case GL_COMPRESSED_SRGB:
        case GL_COMPRESSED_SRGB_ALPHA:
-               return MESA_FORMAT_SRGBA8;
+               return MESA_FORMAT_SARGB8;
 
        case GL_SLUMINANCE:
        case GL_SLUMINANCE8:
@@ -498,6 +562,15 @@ gl_format radeonChooseTextureFormat(GLcontext * ctx,
        case GL_COMPRESSED_SLUMINANCE_ALPHA:
                return MESA_FORMAT_SLA8;
 
+       case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
+               return MESA_FORMAT_SRGB_DXT1;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
+               return MESA_FORMAT_SRGBA_DXT1;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
+               return MESA_FORMAT_SRGBA_DXT3;
+       case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
+               return MESA_FORMAT_SRGBA_DXT5;
+
        default:
                _mesa_problem(ctx,
                              "unexpected internalFormat 0x%x in %s",
@@ -551,11 +624,10 @@ static void teximage_assign_miptree(radeonContextPtr rmesa,
        if (!t->mt || !radeon_miptree_matches_image(t->mt, texImage, face, level)) {
                radeon_miptree_unreference(&t->mt);
                radeon_try_alloc_miptree(rmesa, t);
-               if (RADEON_DEBUG & RADEON_TEXTURE) {
-                       fprintf(stderr, "%s: texObj %p, texImage %p, face %d, level %d, "
+               radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                               "%s: texObj %p, texImage %p, face %d, level %d, "
                                "texObj miptree doesn't match, allocated new miptree %p\n",
                                __FUNCTION__, texObj, texImage, face, level, t->mt);
-               }
        }
 
        /* Miptree alocation may have failed,
@@ -564,10 +636,12 @@ static void teximage_assign_miptree(radeonContextPtr rmesa,
                image->mtface = face;
                image->mtlevel = level;
                radeon_miptree_reference(t->mt, &image->mt);
-       }
+       } else
+               radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Failed to allocate miptree.\n", __func__);
 }
 
-static GLuint * allocate_image_offsets(GLcontext *ctx,
+static GLuint * allocate_image_offsets(struct gl_context *ctx,
        unsigned alignedWidth,
        unsigned height,
        unsigned depth)
@@ -575,7 +649,7 @@ static GLuint * allocate_image_offsets(GLcontext *ctx,
        int i;
        GLuint *offsets;
 
-       offsets = _mesa_malloc(depth * sizeof(GLuint)) ;
+       offsets = malloc(depth * sizeof(GLuint)) ;
        if (!offsets) {
                _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex[Sub]Image");
                return NULL;
@@ -591,7 +665,7 @@ static GLuint * allocate_image_offsets(GLcontext *ctx,
 /**
  * Update a subregion of the given texture image.
  */
-static void radeon_store_teximage(GLcontext* ctx, int dims,
+static void radeon_store_teximage(struct gl_context* ctx, int dims,
                GLint xoffset, GLint yoffset, GLint zoffset,
                GLsizei width, GLsizei height, GLsizei depth,
                GLsizei imageSize,
@@ -602,18 +676,22 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
                struct gl_texture_image *texImage,
                int compressed)
 {
+       radeonContextPtr rmesa = RADEON_CONTEXT(ctx);
        radeonTexObj *t = radeon_tex_obj(texObj);
        radeon_texture_image* image = get_radeon_texture_image(texImage);
 
        GLuint dstRowStride;
        GLuint *dstImageOffsets;
 
+       radeon_print(RADEON_TEXTURE, RADEON_TRACE,
+                       "%s(%p, tex %p, image %p) compressed %d\n",
+                       __func__, ctx, texObj, texImage, compressed);
+
        if (image->mt) {
                dstRowStride = image->mt->levels[image->mtlevel].rowstride;
        } else if (t->bo) {
                /* TFP case */
-               /* TODO */
-               assert(0);
+               dstRowStride = get_texture_image_row_stride(rmesa, texImage->TexFormat, width, 0);
        } else {
                dstRowStride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
        }
@@ -624,6 +702,7 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
                unsigned alignedWidth = dstRowStride/_mesa_get_format_bytes(texImage->TexFormat);
                dstImageOffsets = allocate_image_offsets(ctx, alignedWidth, texImage->Height, texImage->Depth);
                if (!dstImageOffsets) {
+                       radeon_warning("%s Failed to allocate dstImaeOffset.\n", __func__);
                        return;
                }
        } else {
@@ -669,7 +748,7 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
        }
 
        if (dims == 3) {
-               _mesa_free(dstImageOffsets);
+               free(dstImageOffsets);
        }
 
        radeon_teximage_unmap(image);
@@ -679,7 +758,7 @@ static void radeon_store_teximage(GLcontext* ctx, int dims,
  * All glTexImage calls go through this function.
  */
 static void radeon_teximage(
-       GLcontext *ctx, int dims,
+       struct gl_context *ctx, int dims,
        GLenum target, GLint level,
        GLint internalFormat,
        GLint width, GLint height, GLint depth,
@@ -693,42 +772,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);
-       GLint postConvWidth = width;
-       GLint postConvHeight = height;
        GLuint face = _mesa_tex_target_to_face(target);
 
+       radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
+                       __func__, dims, texObj, texImage, face, level);
        {
                struct radeon_bo *bo;
                bo = !image->mt ? image->bo : image->mt->bo;
                if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Calling teximage for texture that is "
+                               "queued for GPU processing.\n",
+                               __func__);
                        radeon_firevertices(rmesa);
                }
        }
 
-       if (RADEON_DEBUG & RADEON_TEXTURE) {
-               fprintf(stderr, "radeon_teximage%dd: texObj %p, texImage %p, face %d, level %d\n",
-                               dims, texObj, texImage, face, level);
-       }
 
        t->validated = GL_FALSE;
 
-       if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
-              _mesa_adjust_image_for_convolution(ctx, dims, &postConvWidth,
-                                                 &postConvHeight);
-       }
-
-       if (!_mesa_is_format_compressed(texImage->TexFormat)) {
-               GLuint texelBytes = _mesa_get_format_bytes(texImage->TexFormat);
-               /* Minimum pitch of 32 bytes */
-               if (postConvWidth * texelBytes < 32) {
-                       postConvWidth = 32 / texelBytes;
-                       texImage->RowStride = postConvWidth;
-               }
-               if (!image->mt) {
-                       assert(texImage->RowStride == postConvWidth);
-               }
-       }
-
        /* Mesa core only clears texImage->Data but not image->mt */
        radeonFreeTexImageData(ctx, texImage);
 
@@ -740,11 +803,10 @@ static void radeon_teximage(
                                                                texImage->Height,
                                                                texImage->Depth);
                        texImage->Data = _mesa_alloc_texmemory(size);
-                       if (RADEON_DEBUG & RADEON_TEXTURE) {
-                               fprintf(stderr, "radeon_teximage%dd: texObj %p, texImage %p, "
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                                       "%s %dd: texObj %p, texImage %p, "
                                        " no miptree assigned, using local memory %p\n",
-                                       dims, texObj, texImage, texImage->Data);
-                       }
+                                       __func__, dims, texObj, texImage, texImage->Data);
                }
        }
 
@@ -771,7 +833,7 @@ static void radeon_teximage(
        _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
-void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
                      GLint internalFormat,
                      GLint width, GLint border,
                      GLenum format, GLenum type, const GLvoid * pixels,
@@ -783,7 +845,7 @@ void radeonTexImage1D(GLcontext * ctx, GLenum target, GLint level,
                0, format, type, pixels, packing, texObj, texImage, 0);
 }
 
-void radeonTexImage2D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
                           GLint internalFormat,
                           GLint width, GLint height, GLint border,
                           GLenum format, GLenum type, const GLvoid * pixels,
@@ -796,7 +858,7 @@ void radeonTexImage2D(GLcontext * ctx, GLenum target, GLint level,
                0, format, type, pixels, packing, texObj, texImage, 0);
 }
 
-void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target,
+void radeonCompressedTexImage2D(struct gl_context * ctx, GLenum target,
                                     GLint level, GLint internalFormat,
                                     GLint width, GLint height, GLint border,
                                     GLsizei imageSize, const GLvoid * data,
@@ -807,7 +869,7 @@ void radeonCompressedTexImage2D(GLcontext * ctx, GLenum target,
                imageSize, 0, 0, data, &ctx->Unpack, texObj, texImage, 1);
 }
 
-void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexImage3D(struct gl_context * ctx, GLenum target, GLint level,
                      GLint internalFormat,
                      GLint width, GLint height, GLint depth,
                      GLint border,
@@ -823,7 +885,7 @@ void radeonTexImage3D(GLcontext * ctx, GLenum target, GLint level,
 /**
  * All glTexSubImage calls go through this function.
  */
-static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int level,
+static void radeon_texsubimage(struct gl_context* ctx, int dims, GLenum target, int level,
                GLint xoffset, GLint yoffset, GLint zoffset,
                GLsizei width, GLsizei height, GLsizei depth,
                GLsizei imageSize,
@@ -838,18 +900,22 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve
        radeonTexObj* t = radeon_tex_obj(texObj);
        radeon_texture_image* image = get_radeon_texture_image(texImage);
 
+       radeon_print(RADEON_TEXTURE, RADEON_NORMAL,
+                       "%s %dd: texObj %p, texImage %p, face %d, level %d\n",
+                       __func__, dims, texObj, texImage,
+                       _mesa_tex_target_to_face(target), level);
        {
                struct radeon_bo *bo;
                bo = !image->mt ? image->bo : image->mt->bo;
                if (bo && radeon_bo_is_referenced_by_cs(bo, rmesa->cmdbuf.cs)) {
+                       radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                               "%s Calling texsubimage for texture that is "
+                               "queued for GPU processing.\n",
+                               __func__);
                        radeon_firevertices(rmesa);
                }
        }
 
-       if (RADEON_DEBUG & RADEON_TEXTURE) {
-               fprintf(stderr, "radeon_texsubimage%dd: texObj %p, texImage %p, face %d, level %d\n",
-                               dims, texObj, texImage, _mesa_tex_target_to_face(target), level);
-       }
 
        t->validated = GL_FALSE;
        if (compressed) {
@@ -873,7 +939,7 @@ static void radeon_texsubimage(GLcontext* ctx, int dims, GLenum target, int leve
        _mesa_unmap_teximage_pbo(ctx, packing);
 }
 
-void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
                         GLint xoffset,
                         GLsizei width,
                         GLenum format, GLenum type,
@@ -886,7 +952,7 @@ void radeonTexSubImage1D(GLcontext * ctx, GLenum target, GLint level,
                format, type, pixels, packing, texObj, texImage, 0);
 }
 
-void radeonTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
                         GLint xoffset, GLint yoffset,
                         GLsizei width, GLsizei height,
                         GLenum format, GLenum type,
@@ -900,7 +966,7 @@ void radeonTexSubImage2D(GLcontext * ctx, GLenum target, GLint level,
                           0);
 }
 
-void radeonCompressedTexSubImage2D(GLcontext * ctx, GLenum target,
+void radeonCompressedTexSubImage2D(struct gl_context * ctx, GLenum target,
                                   GLint level, GLint xoffset,
                                   GLint yoffset, GLsizei width,
                                   GLsizei height, GLenum format,
@@ -913,7 +979,7 @@ void radeonCompressedTexSubImage2D(GLcontext * ctx, GLenum target,
 }
 
 
-void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
+void radeonTexSubImage3D(struct gl_context * ctx, GLenum target, GLint level,
                         GLint xoffset, GLint yoffset, GLint zoffset,
                         GLsizei width, GLsizei height, GLsizei depth,
                         GLenum format, GLenum type,
@@ -926,57 +992,82 @@ void radeonTexSubImage3D(GLcontext * ctx, GLenum target, GLint level,
                format, type, pixels, packing, texObj, texImage, 0);
 }
 
-/**
- * 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)
+unsigned radeonIsFormatRenderable(gl_format mesa_format)
 {
-       radeon_texture_image *image = get_radeon_texture_image(texImage);
+       if (mesa_format == _dri_texformat_argb8888 || mesa_format == _dri_texformat_rgb565 ||
+               mesa_format == _dri_texformat_argb1555 || mesa_format == _dri_texformat_argb4444)
+               return 1;
 
-       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);
+       switch (mesa_format)
+       {
+               case MESA_FORMAT_Z16:
+               case MESA_FORMAT_S8_Z24:
+                       return 1;
+               default:
+                       return 0;
        }
+}
 
-       if (compressed) {
-               /* FIXME: this can't work for small textures (mips) which
-                        use different hw stride */
-               _mesa_get_compressed_teximage(ctx, target, level, pixels,
-                                             texObj, texImage);
-       } else {
-               _mesa_get_teximage(ctx, target, level, format, type, pixels,
-                                  texObj, texImage);
+#if FEATURE_OES_EGL_image
+void radeon_image_target_texture_2d(struct gl_context *ctx, GLenum target,
+                                   struct gl_texture_object *texObj,
+                                   struct gl_texture_image *texImage,
+                                   GLeglImageOES image_handle)
+{
+       radeonContextPtr radeon = RADEON_CONTEXT(ctx);
+       radeonTexObj *t = radeon_tex_obj(texObj);
+       radeon_texture_image *radeonImage = get_radeon_texture_image(texImage);
+       __DRIscreen *screen;
+       __DRIimage *image;
+
+       screen = radeon->dri.screen;
+       image = screen->dri2.image->lookupEGLImage(screen, image_handle,
+                                                  screen->loaderPrivate);
+       if (image == NULL)
+               return;
+
+       radeonFreeTexImageData(ctx, texImage);
+
+       texImage->Width = image->width;
+       texImage->Height = image->height;
+       texImage->Depth = 1;
+       texImage->_BaseFormat = GL_RGBA;
+       texImage->TexFormat = image->format;
+       texImage->RowStride = image->pitch;
+       texImage->InternalFormat = image->internal_format;
+
+       if(t->mt)
+       {
+               radeon_miptree_unreference(&t->mt);
+               t->mt = NULL;
        }
-     
-       if (image->mt) {
-               radeon_teximage_unmap(image);
+
+       /* NOTE: The following is *very* ugly and will probably break. But
+          I don't know how to deal with it, without creating a whole new
+          function like radeon_miptree_from_bo() so I'm going with the
+          easy but error-prone way. */
+
+       radeon_try_alloc_miptree(radeon, t);
+
+       radeonImage->mtface = _mesa_tex_target_to_face(target);
+       radeonImage->mtlevel = 0;
+       radeon_miptree_reference(t->mt, &radeonImage->mt);
+
+       if (t->mt == NULL)
+       {
+               radeon_print(RADEON_TEXTURE, RADEON_VERBOSE,
+                            "%s Failed to allocate miptree.\n", __func__);
+               return;
        }
-}
 
-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);
-}
+       /* Particularly ugly: this is guaranteed to break, if image->bo is
+          not of the required size for a miptree. */
+       radeon_bo_unref(t->mt->bo);
+       radeon_bo_ref(image->bo);
+       t->mt->bo = image->bo;
 
-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);
+       if (!radeon_miptree_matches_image(t->mt, &radeonImage->base,
+                                         radeonImage->mtface, 0))
+               fprintf(stderr, "miptree doesn't match image\n");
 }
+#endif