[Mesa-dev] [PATCH] mesa: move texrender.c to swrast

Brian Paul brianp at vmware.com
Fri Jun 10 19:37:21 PDT 2011


This stuff is really for software rendering, it's not core Mesa.
A small step toward pushing the FetchTexel() stuff down into swrast.
---
 src/mesa/SConscript                      |    2 +-
 src/mesa/drivers/common/driverfuncs.c    |    5 +-
 src/mesa/drivers/dri/intel/intel_fbo.c   |    8 +-
 src/mesa/drivers/dri/radeon/radeon_fbo.c |    8 +-
 src/mesa/main/texrender.c                |  654 ------------------------------
 src/mesa/main/texrender.h                |   18 -
 src/mesa/sources.mak                     |    2 +-
 src/mesa/swrast/s_texrender.c            |  654 ++++++++++++++++++++++++++++++
 src/mesa/swrast/swrast.h                 |   10 +
 9 files changed, 676 insertions(+), 685 deletions(-)
 delete mode 100644 src/mesa/main/texrender.c
 delete mode 100644 src/mesa/main/texrender.h
 create mode 100644 src/mesa/swrast/s_texrender.c

diff --git a/src/mesa/SConscript b/src/mesa/SConscript
index fdb4d5a..24e2155 100644
--- a/src/mesa/SConscript
+++ b/src/mesa/SConscript
@@ -121,7 +121,6 @@ main_sources = [
     'main/texobj.c',
     'main/texpal.c',
     'main/texparam.c',
-    'main/texrender.c',
     'main/texstate.c',
     'main/texstore.c',
     'main/texturebarrier.c',
@@ -174,6 +173,7 @@ swrast_sources = [
     'swrast/s_stencil.c',
     'swrast/s_texcombine.c',
     'swrast/s_texfilter.c',
+    'swrast/s_texrender.c',
     'swrast/s_triangle.c',
     'swrast/s_zoom.c',
 ]
diff --git a/src/mesa/drivers/common/driverfuncs.c b/src/mesa/drivers/common/driverfuncs.c
index 0dbc7c3..8ab129d 100644
--- a/src/mesa/drivers/common/driverfuncs.c
+++ b/src/mesa/drivers/common/driverfuncs.c
@@ -40,7 +40,6 @@
 #include "main/texstore.h"
 #include "main/bufferobj.h"
 #include "main/fbobject.h"
-#include "main/texrender.h"
 #include "main/samplerobj.h"
 #include "main/syncobj.h"
 #include "main/texturebarrier.h"
@@ -183,8 +182,8 @@ _mesa_init_driver_functions(struct dd_function_table *driver)
 
    driver->NewFramebuffer = _mesa_new_framebuffer;
    driver->NewRenderbuffer = _mesa_new_soft_renderbuffer;
-   driver->RenderTexture = _mesa_render_texture;
-   driver->FinishRenderTexture = _mesa_finish_render_texture;
+   driver->RenderTexture = _swrast_render_texture;
+   driver->FinishRenderTexture = _swrast_finish_render_texture;
    driver->FramebufferRenderbuffer = _mesa_framebuffer_renderbuffer;
    driver->ValidateFramebuffer = _mesa_validate_framebuffer;
 
diff --git a/src/mesa/drivers/dri/intel/intel_fbo.c b/src/mesa/drivers/dri/intel/intel_fbo.c
index 83f622d..8277477 100644
--- a/src/mesa/drivers/dri/intel/intel_fbo.c
+++ b/src/mesa/drivers/dri/intel/intel_fbo.c
@@ -35,7 +35,7 @@
 #include "main/renderbuffer.h"
 #include "main/context.h"
 #include "main/teximage.h"
-#include "main/texrender.h"
+#include "swrast/s_texrender.h"
 #include "drivers/common/meta.h"
 
 #include "intel_context.h"
@@ -557,7 +557,7 @@ intel_render_texture(struct gl_context * ctx,
        * (has a border, width/height 0, etc.)
        */
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
-      _mesa_render_texture(ctx, fb, att);
+      _swrast_render_texture(ctx, fb, att);
       return;
    }
    else if (!irb) {
@@ -568,14 +568,14 @@ intel_render_texture(struct gl_context * ctx,
       }
       else {
          /* fallback to software rendering */
-         _mesa_render_texture(ctx, fb, att);
+         _swrast_render_texture(ctx, fb, att);
          return;
       }
    }
 
    if (!intel_update_wrapper(ctx, irb, newImage)) {
        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
-       _mesa_render_texture(ctx, fb, att);
+       _swrast_render_texture(ctx, fb, att);
        return;
    }
 
diff --git a/src/mesa/drivers/dri/radeon/radeon_fbo.c b/src/mesa/drivers/dri/radeon/radeon_fbo.c
index d3c9257..0986ade 100644
--- a/src/mesa/drivers/dri/radeon/radeon_fbo.c
+++ b/src/mesa/drivers/dri/radeon/radeon_fbo.c
@@ -35,7 +35,7 @@
 #include "main/framebuffer.h"
 #include "main/renderbuffer.h"
 #include "main/context.h"
-#include "main/texrender.h"
+#include "swrast/s_texrender.h"
 #include "drivers/common/meta.h"
 
 #include "radeon_common.h"
@@ -557,7 +557,7 @@ radeon_render_texture(struct gl_context * ctx,
       /* Fallback on drawing to a texture without a miptree.
        */
       _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
-      _mesa_render_texture(ctx, fb, att);
+      _swrast_render_texture(ctx, fb, att);
       return;
    }
    else if (!rrb) {
@@ -568,14 +568,14 @@ radeon_render_texture(struct gl_context * ctx,
       }
       else {
          /* fallback to software rendering */
-         _mesa_render_texture(ctx, fb, att);
+         _swrast_render_texture(ctx, fb, att);
          return;
       }
    }
 
    if (!radeon_update_wrapper(ctx, rrb, newImage)) {
        _mesa_reference_renderbuffer(&att->Renderbuffer, NULL);
-       _mesa_render_texture(ctx, fb, att);
+       _swrast_render_texture(ctx, fb, att);
        return;
    }
 
diff --git a/src/mesa/main/texrender.c b/src/mesa/main/texrender.c
deleted file mode 100644
index a7641a5..0000000
--- a/src/mesa/main/texrender.c
+++ /dev/null
@@ -1,654 +0,0 @@
-
-#include "context.h"
-#include "colormac.h"
-#include "fbobject.h"
-#include "macros.h"
-#include "texfetch.h"
-#include "teximage.h"
-#include "texrender.h"
-#include "renderbuffer.h"
-
-
-/*
- * Render-to-texture code for GL_EXT_framebuffer_object
- */
-
-
-/**
- * Derived from gl_renderbuffer class
- */
-struct texture_renderbuffer
-{
-   struct gl_renderbuffer Base;   /**< Base class object */
-   struct gl_texture_image *TexImage;
-   StoreTexelFunc Store;
-   FetchTexelFuncF Fetchf;
-   GLint Yoffset;                 /**< Layer for 1D array textures. */
-   GLint Zoffset;                 /**< Layer for 2D array textures, or slice
-				   * for 3D textures
-				   */
-};
-
-
-/**
- * Get row of values from the renderbuffer that wraps a texture image.
- */
-static void
-texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                GLint x, GLint y, void *values)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   ASSERT(trb->TexImage->Width == rb->Width);
-   ASSERT(trb->TexImage->Height == rb->Height);
-
-   y += trb->Yoffset;
-
-   if (rb->DataType == CHAN_TYPE) {
-      GLchan *rgbaOut = (GLchan *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat rgba[4];
-         trb->Fetchf(trb->TexImage, x + i, y, z, rgba);
-         UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      GLushort *zValues = (GLushort *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
-         zValues[i] = (GLushort) (flt * 0xffff);
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      GLuint *zValues = (GLuint *) values;
-      /*
-      const GLdouble scale = (GLdouble) 0xffffffff;
-      */
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
-#if 0
-         /* this should work, but doesn't (overflow due to low precision) */
-         zValues[i] = (GLuint) (flt * scale);
-#else
-         /* temporary hack */
-         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
-#endif
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      GLuint *zValues = (GLuint *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
-         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      GLuint *zValues = (GLuint *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
-         zValues[i] = (GLuint) (flt * 0xffffff);
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_get_row");
-   }
-}
-
-
-static void
-texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                   const GLint x[], const GLint y[], void *values)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   if (rb->DataType == CHAN_TYPE) {
-      GLchan *rgbaOut = (GLchan *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat rgba[4];
-         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
-				    z, rgba);
-         UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      GLushort *zValues = (GLushort *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
-				    z, &flt);
-         zValues[i] = (GLushort) (flt * 0xffff);
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      GLuint *zValues = (GLuint *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
-				    z, &flt);
-#if 0
-         zValues[i] = (GLuint) (flt * 0xffffffff);
-#else
-         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
-#endif
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      GLuint *zValues = (GLuint *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
-				    z, &flt);
-         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      GLuint *zValues = (GLuint *) values;
-      for (i = 0; i < count; i++) {
-         GLfloat flt;
-         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
-				    z, &flt);
-         zValues[i] = (GLuint) (flt * 0xffffff);
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_get_values");
-   }
-}
-
-
-/**
- * Put row of values into a renderbuffer that wraps a texture image.
- */
-static void
-texture_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                GLint x, GLint y, const void *values, const GLubyte *mask)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   y += trb->Yoffset;
-
-   if (rb->DataType == CHAN_TYPE) {
-      const GLchan *rgba = (const GLchan *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, rgba);
-         }
-         rgba += 4;
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      const GLushort *zValues = (const GLushort *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
-   }
-}
-
-/**
- * Put row of RGB values into a renderbuffer that wraps a texture image.
- */
-static void
-texture_put_row_rgb(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                GLint x, GLint y, const void *values, const GLubyte *mask)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   y += trb->Yoffset;
-
-   if (rb->DataType == CHAN_TYPE) {
-      const GLchan *rgb = (const GLchan *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, rgb);
-         }
-         rgb += 3;
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      const GLushort *zValues = (const GLushort *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
-   }
-}
-
-
-static void
-texture_put_mono_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                     GLint x, GLint y, const void *value, const GLubyte *mask)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   y += trb->Yoffset;
-
-   if (rb->DataType == CHAN_TYPE) {
-      const GLchan *rgba = (const GLchan *) value;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, rgba);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      const GLushort zValue = *((const GLushort *) value);
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, &zValue);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      const GLuint zValue = *((const GLuint *) value);
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, &zValue);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x + i, y, z, &flt);
-         }
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row");
-   }
-}
-
-
-static void
-texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
-                   const GLint x[], const GLint y[], const void *values,
-                   const GLubyte *mask)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   if (rb->DataType == CHAN_TYPE) {
-      const GLchan *rgba = (const GLchan *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
-         }
-         rgba += 4;
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      const GLushort *zValues = (const GLushort *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      const GLuint *zValues = (const GLuint *) values;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
-         }
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_put_values");
-   }
-}
-
-
-static void
-texture_put_mono_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
-                        GLuint count, const GLint x[], const GLint y[],
-                        const void *value, const GLubyte *mask)
-{
-   const struct texture_renderbuffer *trb
-      = (const struct texture_renderbuffer *) rb;
-   const GLint z = trb->Zoffset;
-   GLuint i;
-
-   if (rb->DataType == CHAN_TYPE) {
-      const GLchan *rgba = (const GLchan *) value;
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT) {
-      const GLuint zValue = *((const GLuint *) value);
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_SHORT) {
-      const GLushort zValue = *((const GLushort *) value);
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
-      const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
-         }
-      }
-   }
-   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
-      const GLuint zValue = *((const GLuint *) value);
-      const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
-      for (i = 0; i < count; i++) {
-         if (!mask || mask[i]) {
-            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
-         }
-      }
-   }
-   else {
-      _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values");
-   }
-}
-
-
-static void
-store_nop(struct gl_texture_image *texImage,
-          GLint col, GLint row, GLint img,
-          const void *texel)
-{
-}
-
-
-static void
-delete_texture_wrapper(struct gl_renderbuffer *rb)
-{
-   ASSERT(rb->RefCount == 0);
-   free(rb);
-}
-
-
-/**
- * This function creates a renderbuffer object which wraps a texture image.
- * The new renderbuffer is plugged into the given attachment point.
- * This allows rendering into the texture as if it were a renderbuffer.
- */
-static void
-wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
-{
-   struct texture_renderbuffer *trb;
-   const GLuint name = 0;
-
-   ASSERT(att->Type == GL_TEXTURE);
-   ASSERT(att->Renderbuffer == NULL);
-
-   trb = CALLOC_STRUCT(texture_renderbuffer);
-   if (!trb) {
-      _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
-      return;
-   }
-
-   /* init base gl_renderbuffer fields */
-   _mesa_init_renderbuffer(&trb->Base, name);
-   /* plug in our texture_renderbuffer-specific functions */
-   trb->Base.Delete = delete_texture_wrapper;
-   trb->Base.AllocStorage = NULL; /* illegal! */
-   trb->Base.GetRow = texture_get_row;
-   trb->Base.GetValues = texture_get_values;
-   trb->Base.PutRow = texture_put_row;
-   trb->Base.PutRowRGB = texture_put_row_rgb;
-   trb->Base.PutMonoRow = texture_put_mono_row;
-   trb->Base.PutValues = texture_put_values;
-   trb->Base.PutMonoValues = texture_put_mono_values;
-
-   /* update attachment point */
-   _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
-}
-
-/**
- * Update the renderbuffer wrapper for rendering to a texture.
- * For example, update the width, height of the RB based on the texture size,
- * update the internal format info, etc.
- */
-static void
-update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
-{
-   struct texture_renderbuffer *trb
-      = (struct texture_renderbuffer *) att->Renderbuffer;
-
-   (void) ctx;
-   ASSERT(trb);
-
-   trb->TexImage = _mesa_get_attachment_teximage(att);
-   ASSERT(trb->TexImage);
-
-   trb->Store = _mesa_get_texel_store_func(trb->TexImage->TexFormat);
-   if (!trb->Store) {
-      /* we'll never draw into some textures (compressed formats) */
-      trb->Store = store_nop;
-   }
-
-   trb->Fetchf = trb->TexImage->FetchTexelf;
-
-   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
-      trb->Yoffset = att->Zoffset;
-      trb->Zoffset = 0;
-   }
-   else {
-      trb->Yoffset = 0;
-      trb->Zoffset = att->Zoffset;
-   }
-
-   trb->Base.Width = trb->TexImage->Width;
-   trb->Base.Height = trb->TexImage->Height;
-   trb->Base.InternalFormat = trb->TexImage->InternalFormat;
-   trb->Base.Format = trb->TexImage->TexFormat;
-
-   /* XXX may need more special cases here */
-   switch (trb->TexImage->TexFormat) {
-   case MESA_FORMAT_Z24_S8:
-      trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
-      trb->Base._BaseFormat = GL_DEPTH_STENCIL;
-      break;
-   case MESA_FORMAT_S8_Z24:
-      trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
-      trb->Base._BaseFormat = GL_DEPTH_STENCIL;
-      break;
-   case MESA_FORMAT_Z24_X8:
-      trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
-      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
-      break;
-   case MESA_FORMAT_X8_Z24:
-      trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
-      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
-      break;
-   case MESA_FORMAT_Z16:
-      trb->Base.DataType = GL_UNSIGNED_SHORT;
-      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
-      break;
-   case MESA_FORMAT_Z32:
-      trb->Base.DataType = GL_UNSIGNED_INT;
-      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
-      break;
-   /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
-   case MESA_FORMAT_SRGB8:
-      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888, _mesa_get_texture_dimensions(att->Texture->Target));
-      trb->Base.DataType = CHAN_TYPE;
-      trb->Base._BaseFormat = GL_RGBA;
-      break;
-   case MESA_FORMAT_SRGBA8:
-      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888, _mesa_get_texture_dimensions(att->Texture->Target));
-      trb->Base.DataType = CHAN_TYPE;
-      trb->Base._BaseFormat = GL_RGBA;
-      break;
-   case MESA_FORMAT_SARGB8:
-      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888, _mesa_get_texture_dimensions(att->Texture->Target));
-      trb->Base.DataType = CHAN_TYPE;
-      trb->Base._BaseFormat = GL_RGBA;
-      break;
-   default:
-      trb->Base.DataType = CHAN_TYPE;
-      trb->Base._BaseFormat = GL_RGBA;
-   }
-   trb->Base.Data = trb->TexImage->Data;
-}
-
-
-
-/**
- * Called when rendering to a texture image begins, or when changing
- * the dest mipmap level, cube face, etc.
- * This is a fallback routine for software render-to-texture.
- *
- * Called via the glRenderbufferTexture1D/2D/3D() functions
- * and elsewhere (such as glTexImage2D).
- *
- * The image we're rendering into is
- * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
- * It'll never be NULL.
- *
- * \param fb  the framebuffer object the texture is being bound to
- * \param att  the fb attachment point of the texture
- *
- * \sa _mesa_framebuffer_renderbuffer
- */
-void
-_mesa_render_texture(struct gl_context *ctx,
-                     struct gl_framebuffer *fb,
-                     struct gl_renderbuffer_attachment *att)
-{
-   (void) fb;
-
-   if (!att->Renderbuffer) {
-      wrap_texture(ctx, att);
-   }
-   update_wrapper(ctx, att);
-}
-
-
-void
-_mesa_finish_render_texture(struct gl_context *ctx,
-                            struct gl_renderbuffer_attachment *att)
-{
-   /* do nothing */
-   /* The renderbuffer texture wrapper will get deleted by the
-    * normal mechanism for deleting renderbuffers.
-    */
-   (void) ctx;
-   (void) att;
-}
diff --git a/src/mesa/main/texrender.h b/src/mesa/main/texrender.h
deleted file mode 100644
index cacd091..0000000
--- a/src/mesa/main/texrender.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef TEXRENDER_H
-#define TEXRENDER_H
-
-struct gl_context;
-struct gl_framebuffer;
-struct gl_renderbuffer_attachment;
-
-extern void
-_mesa_render_texture(struct gl_context *ctx,
-                     struct gl_framebuffer *fb,
-                     struct gl_renderbuffer_attachment *att);
-
-extern void
-_mesa_finish_render_texture(struct gl_context *ctx,
-                            struct gl_renderbuffer_attachment *att);
-
-
-#endif /* TEXRENDER_H */
diff --git a/src/mesa/sources.mak b/src/mesa/sources.mak
index 9b2cb1a..4b2ec08 100644
--- a/src/mesa/sources.mak
+++ b/src/mesa/sources.mak
@@ -92,7 +92,6 @@ MAIN_SOURCES = \
 	main/texobj.c \
 	main/texpal.c \
 	main/texparam.c \
-	main/texrender.c \
 	main/texstate.c \
 	main/texstore.c \
 	main/texturebarrier.c \
@@ -145,6 +144,7 @@ SWRAST_SOURCES = \
 	swrast/s_stencil.c \
 	swrast/s_texcombine.c \
 	swrast/s_texfilter.c \
+	swrast/s_texrender.c \
 	swrast/s_triangle.c \
 	swrast/s_zoom.c
 
diff --git a/src/mesa/swrast/s_texrender.c b/src/mesa/swrast/s_texrender.c
new file mode 100644
index 0000000..52d03c9
--- /dev/null
+++ b/src/mesa/swrast/s_texrender.c
@@ -0,0 +1,654 @@
+
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/fbobject.h"
+#include "main/macros.h"
+#include "main/texfetch.h"
+#include "main/teximage.h"
+#include "main/renderbuffer.h"
+#include "swrast/swrast.h"
+
+
+/*
+ * Render-to-texture code for GL_EXT_framebuffer_object
+ */
+
+
+/**
+ * Derived from gl_renderbuffer class
+ */
+struct texture_renderbuffer
+{
+   struct gl_renderbuffer Base;   /**< Base class object */
+   struct gl_texture_image *TexImage;
+   StoreTexelFunc Store;
+   FetchTexelFuncF Fetchf;
+   GLint Yoffset;                 /**< Layer for 1D array textures. */
+   GLint Zoffset;                 /**< Layer for 2D array textures, or slice
+				   * for 3D textures
+				   */
+};
+
+
+/**
+ * Get row of values from the renderbuffer that wraps a texture image.
+ */
+static void
+texture_get_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                GLint x, GLint y, void *values)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   ASSERT(trb->TexImage->Width == rb->Width);
+   ASSERT(trb->TexImage->Height == rb->Height);
+
+   y += trb->Yoffset;
+
+   if (rb->DataType == CHAN_TYPE) {
+      GLchan *rgbaOut = (GLchan *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat rgba[4];
+         trb->Fetchf(trb->TexImage, x + i, y, z, rgba);
+         UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      GLushort *zValues = (GLushort *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
+         zValues[i] = (GLushort) (flt * 0xffff);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      GLuint *zValues = (GLuint *) values;
+      /*
+      const GLdouble scale = (GLdouble) 0xffffffff;
+      */
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
+#if 0
+         /* this should work, but doesn't (overflow due to low precision) */
+         zValues[i] = (GLuint) (flt * scale);
+#else
+         /* temporary hack */
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x + i, y, z, &flt);
+         zValues[i] = (GLuint) (flt * 0xffffff);
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_get_row");
+   }
+}
+
+
+static void
+texture_get_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                   const GLint x[], const GLint y[], void *values)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   if (rb->DataType == CHAN_TYPE) {
+      GLchan *rgbaOut = (GLchan *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat rgba[4];
+         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+				    z, rgba);
+         UNCLAMPED_FLOAT_TO_RGBA_CHAN(rgbaOut + 4 * i, rgba);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      GLushort *zValues = (GLushort *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+				    z, &flt);
+         zValues[i] = (GLushort) (flt * 0xffff);
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+				    z, &flt);
+#if 0
+         zValues[i] = (GLuint) (flt * 0xffffffff);
+#else
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+#endif
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+				    z, &flt);
+         zValues[i] = ((GLuint) (flt * 0xffffff)) << 8;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      GLuint *zValues = (GLuint *) values;
+      for (i = 0; i < count; i++) {
+         GLfloat flt;
+         trb->Fetchf(trb->TexImage, x[i], y[i] + trb->Yoffset,
+				    z, &flt);
+         zValues[i] = (GLuint) (flt * 0xffffff);
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_get_values");
+   }
+}
+
+
+/**
+ * Put row of values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   y += trb->Yoffset;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgba = (const GLchan *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, rgba);
+         }
+         rgba += 4;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+   }
+}
+
+/**
+ * Put row of RGB values into a renderbuffer that wraps a texture image.
+ */
+static void
+texture_put_row_rgb(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                GLint x, GLint y, const void *values, const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   y += trb->Yoffset;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgb = (const GLchan *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, rgb);
+         }
+         rgb += 3;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_row");
+   }
+}
+
+
+static void
+texture_put_mono_row(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                     GLint x, GLint y, const void *value, const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   y += trb->Yoffset;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgba = (const GLchan *) value;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, rgba);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort zValue = *((const GLushort *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint zValue = *((const GLuint *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint zValue = *((const GLuint *) value);
+      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      const GLuint zValue = *((const GLuint *) value);
+      const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x + i, y, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_row");
+   }
+}
+
+
+static void
+texture_put_values(struct gl_context *ctx, struct gl_renderbuffer *rb, GLuint count,
+                   const GLint x[], const GLint y[], const void *values,
+                   const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgba = (const GLchan *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
+         }
+         rgba += 4;
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort *zValues = (const GLushort *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, zValues + i);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] >> 8) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      const GLuint *zValues = (const GLuint *) values;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            GLfloat flt = (GLfloat) ((zValues[i] & 0xffffff) * (1.0 / 0xffffff));
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_values");
+   }
+}
+
+
+static void
+texture_put_mono_values(struct gl_context *ctx, struct gl_renderbuffer *rb,
+                        GLuint count, const GLint x[], const GLint y[],
+                        const void *value, const GLubyte *mask)
+{
+   const struct texture_renderbuffer *trb
+      = (const struct texture_renderbuffer *) rb;
+   const GLint z = trb->Zoffset;
+   GLuint i;
+
+   if (rb->DataType == CHAN_TYPE) {
+      const GLchan *rgba = (const GLchan *) value;
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, rgba);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT) {
+      const GLuint zValue = *((const GLuint *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_SHORT) {
+      const GLushort zValue = *((const GLushort *) value);
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &zValue);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_24_8_EXT) {
+      const GLuint zValue = *((const GLuint *) value);
+      const GLfloat flt = (GLfloat) ((zValue >> 8) * (1.0 / 0xffffff));
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+         }
+      }
+   }
+   else if (rb->DataType == GL_UNSIGNED_INT_8_24_REV_MESA) {
+      const GLuint zValue = *((const GLuint *) value);
+      const GLfloat flt = (GLfloat) ((zValue & 0xffffff) * (1.0 / 0xffffff));
+      for (i = 0; i < count; i++) {
+         if (!mask || mask[i]) {
+            trb->Store(trb->TexImage, x[i], y[i] + trb->Yoffset, z, &flt);
+         }
+      }
+   }
+   else {
+      _mesa_problem(ctx, "invalid rb->DataType in texture_put_mono_values");
+   }
+}
+
+
+static void
+store_nop(struct gl_texture_image *texImage,
+          GLint col, GLint row, GLint img,
+          const void *texel)
+{
+}
+
+
+static void
+delete_texture_wrapper(struct gl_renderbuffer *rb)
+{
+   ASSERT(rb->RefCount == 0);
+   free(rb);
+}
+
+
+/**
+ * This function creates a renderbuffer object which wraps a texture image.
+ * The new renderbuffer is plugged into the given attachment point.
+ * This allows rendering into the texture as if it were a renderbuffer.
+ */
+static void
+wrap_texture(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
+{
+   struct texture_renderbuffer *trb;
+   const GLuint name = 0;
+
+   ASSERT(att->Type == GL_TEXTURE);
+   ASSERT(att->Renderbuffer == NULL);
+
+   trb = CALLOC_STRUCT(texture_renderbuffer);
+   if (!trb) {
+      _mesa_error(ctx, GL_OUT_OF_MEMORY, "wrap_texture");
+      return;
+   }
+
+   /* init base gl_renderbuffer fields */
+   _mesa_init_renderbuffer(&trb->Base, name);
+   /* plug in our texture_renderbuffer-specific functions */
+   trb->Base.Delete = delete_texture_wrapper;
+   trb->Base.AllocStorage = NULL; /* illegal! */
+   trb->Base.GetRow = texture_get_row;
+   trb->Base.GetValues = texture_get_values;
+   trb->Base.PutRow = texture_put_row;
+   trb->Base.PutRowRGB = texture_put_row_rgb;
+   trb->Base.PutMonoRow = texture_put_mono_row;
+   trb->Base.PutValues = texture_put_values;
+   trb->Base.PutMonoValues = texture_put_mono_values;
+
+   /* update attachment point */
+   _mesa_reference_renderbuffer(&att->Renderbuffer, &(trb->Base));
+}
+
+/**
+ * Update the renderbuffer wrapper for rendering to a texture.
+ * For example, update the width, height of the RB based on the texture size,
+ * update the internal format info, etc.
+ */
+static void
+update_wrapper(struct gl_context *ctx, struct gl_renderbuffer_attachment *att)
+{
+   struct texture_renderbuffer *trb
+      = (struct texture_renderbuffer *) att->Renderbuffer;
+
+   (void) ctx;
+   ASSERT(trb);
+
+   trb->TexImage = _mesa_get_attachment_teximage(att);
+   ASSERT(trb->TexImage);
+
+   trb->Store = _mesa_get_texel_store_func(trb->TexImage->TexFormat);
+   if (!trb->Store) {
+      /* we'll never draw into some textures (compressed formats) */
+      trb->Store = store_nop;
+   }
+
+   trb->Fetchf = trb->TexImage->FetchTexelf;
+
+   if (att->Texture->Target == GL_TEXTURE_1D_ARRAY_EXT) {
+      trb->Yoffset = att->Zoffset;
+      trb->Zoffset = 0;
+   }
+   else {
+      trb->Yoffset = 0;
+      trb->Zoffset = att->Zoffset;
+   }
+
+   trb->Base.Width = trb->TexImage->Width;
+   trb->Base.Height = trb->TexImage->Height;
+   trb->Base.InternalFormat = trb->TexImage->InternalFormat;
+   trb->Base.Format = trb->TexImage->TexFormat;
+
+   /* XXX may need more special cases here */
+   switch (trb->TexImage->TexFormat) {
+   case MESA_FORMAT_Z24_S8:
+      trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+      trb->Base._BaseFormat = GL_DEPTH_STENCIL;
+      break;
+   case MESA_FORMAT_S8_Z24:
+      trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
+      trb->Base._BaseFormat = GL_DEPTH_STENCIL;
+      break;
+   case MESA_FORMAT_Z24_X8:
+      trb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT;
+      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   case MESA_FORMAT_X8_Z24:
+      trb->Base.DataType = GL_UNSIGNED_INT_8_24_REV_MESA;
+      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   case MESA_FORMAT_Z16:
+      trb->Base.DataType = GL_UNSIGNED_SHORT;
+      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   case MESA_FORMAT_Z32:
+      trb->Base.DataType = GL_UNSIGNED_INT;
+      trb->Base._BaseFormat = GL_DEPTH_COMPONENT;
+      break;
+   /* SRGB formats pre EXT_framebuffer_sRGB don't do sRGB translations on FBO readback */
+   case MESA_FORMAT_SRGB8:
+      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGB888, _mesa_get_texture_dimensions(att->Texture->Target));
+      trb->Base.DataType = CHAN_TYPE;
+      trb->Base._BaseFormat = GL_RGBA;
+      break;
+   case MESA_FORMAT_SRGBA8:
+      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_RGBA8888, _mesa_get_texture_dimensions(att->Texture->Target));
+      trb->Base.DataType = CHAN_TYPE;
+      trb->Base._BaseFormat = GL_RGBA;
+      break;
+   case MESA_FORMAT_SARGB8:
+      trb->Fetchf = _mesa_get_texel_fetch_func(MESA_FORMAT_ARGB8888, _mesa_get_texture_dimensions(att->Texture->Target));
+      trb->Base.DataType = CHAN_TYPE;
+      trb->Base._BaseFormat = GL_RGBA;
+      break;
+   default:
+      trb->Base.DataType = CHAN_TYPE;
+      trb->Base._BaseFormat = GL_RGBA;
+   }
+   trb->Base.Data = trb->TexImage->Data;
+}
+
+
+
+/**
+ * Called when rendering to a texture image begins, or when changing
+ * the dest mipmap level, cube face, etc.
+ * This is a fallback routine for software render-to-texture.
+ *
+ * Called via the glRenderbufferTexture1D/2D/3D() functions
+ * and elsewhere (such as glTexImage2D).
+ *
+ * The image we're rendering into is
+ * att->Texture->Image[att->CubeMapFace][att->TextureLevel];
+ * It'll never be NULL.
+ *
+ * \param fb  the framebuffer object the texture is being bound to
+ * \param att  the fb attachment point of the texture
+ *
+ * \sa _mesa_framebuffer_renderbuffer
+ */
+void
+_swrast_render_texture(struct gl_context *ctx,
+                       struct gl_framebuffer *fb,
+                       struct gl_renderbuffer_attachment *att)
+{
+   (void) fb;
+
+   if (!att->Renderbuffer) {
+      wrap_texture(ctx, att);
+   }
+   update_wrapper(ctx, att);
+}
+
+
+void
+_swrast_finish_render_texture(struct gl_context *ctx,
+                              struct gl_renderbuffer_attachment *att)
+{
+   /* do nothing */
+   /* The renderbuffer texture wrapper will get deleted by the
+    * normal mechanism for deleting renderbuffers.
+    */
+   (void) ctx;
+   (void) att;
+}
diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h
index 9b88c70..27b74c3 100644
--- a/src/mesa/swrast/swrast.h
+++ b/src/mesa/swrast/swrast.h
@@ -206,6 +206,16 @@ extern void
 _swrast_eject_texture_images(struct gl_context *ctx);
 
 
+extern void
+_swrast_render_texture(struct gl_context *ctx,
+                       struct gl_framebuffer *fb,
+                       struct gl_renderbuffer_attachment *att);
+
+extern void
+_swrast_finish_render_texture(struct gl_context *ctx,
+                              struct gl_renderbuffer_attachment *att);
+
+
 
 /**
  * The driver interface for the software rasterizer.
-- 
1.7.3.4



More information about the mesa-dev mailing list