swrast: Use fixed-function processing instead _TexEnvProgram for DrawPixels
[mesa.git] / src / mesa / swrast / s_texture.c
index 7e3fc2806d9061a9610e477a641b5b621409aab6..337a52f32a049dec412475b7821e6cef3fca3e25 100644 (file)
@@ -67,17 +67,56 @@ _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
                                    gl_format format, GLsizei width,
                                    GLsizei height, GLsizei depth)
 {
+   struct swrast_texture_image *swImg = swrast_texture_image(texImage);
    GLuint bytes = _mesa_format_image_size(format, width, height, depth);
+   GLuint i;
 
    /* This _should_ be true (revisit if these ever fail) */
    assert(texImage->Width == width);
    assert(texImage->Height == height);
    assert(texImage->Depth == depth);
 
-   assert(!texImage->Data);
-   texImage->Data = _mesa_align_malloc(bytes, 512);
+   assert(!swImg->Buffer);
+   swImg->Buffer = _mesa_align_malloc(bytes, 512);
+   if (!swImg->Buffer)
+      return GL_FALSE;
 
-   return texImage->Data != NULL;
+   /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
+   swImg->RowStride = width;
+
+   /* Allocate the ImageOffsets array and initialize to typical values.
+    * We allocate the array for 1D/2D textures too in order to avoid special-
+    * case code in the texstore routines.
+    */
+   swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
+   if (!swImg->ImageOffsets)
+      return GL_FALSE;
+
+   for (i = 0; i < depth; i++) {
+      swImg->ImageOffsets[i] = i * width * height;
+   }
+
+   if ((width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
+       (height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
+       (depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
+      swImg->_IsPowerOfTwo = GL_TRUE;
+   else
+      swImg->_IsPowerOfTwo = GL_FALSE;
+
+   /* Compute Width/Height/DepthScale for mipmap lod computation */
+   if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
+      /* scale = 1.0 since texture coords directly map to texels */
+      swImg->WidthScale = 1.0;
+      swImg->HeightScale = 1.0;
+      swImg->DepthScale = 1.0;
+   }
+   else {
+      swImg->WidthScale = (GLfloat) texImage->Width;
+      swImg->HeightScale = (GLfloat) texImage->Height;
+      swImg->DepthScale = (GLfloat) texImage->Depth;
+   }
+
+   return GL_TRUE;
 }
 
 
@@ -88,11 +127,16 @@ void
 _swrast_free_texture_image_buffer(struct gl_context *ctx,
                                   struct gl_texture_image *texImage)
 {
-   if (texImage->Data && !texImage->IsClientData) {
-      _mesa_align_free(texImage->Data);
+   struct swrast_texture_image *swImage = swrast_texture_image(texImage);
+   if (swImage->Buffer) {
+      _mesa_align_free(swImage->Buffer);
+      swImage->Buffer = NULL;
    }
 
-   texImage->Data = NULL;
+   if (swImage->ImageOffsets) {
+      free(swImage->ImageOffsets);
+      swImage->ImageOffsets = NULL;
+   }
 }
 
 
@@ -134,6 +178,7 @@ _swrast_map_teximage(struct gl_context *ctx,
                      GLubyte **mapOut,
                      GLint *rowStrideOut)
 {
+   struct swrast_texture_image *swImage = swrast_texture_image(texImage);
    GLubyte *map;
    GLint stride, texelSize;
    GLuint bw, bh;
@@ -144,9 +189,16 @@ _swrast_map_teximage(struct gl_context *ctx,
    stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
 
-   assert(texImage->Data);
+   assert(x % bw == 0);
+   assert(y % bh == 0);
 
-   map = texImage->Data;
+   if (!swImage->Buffer) {
+      /* probably ran out of memory when allocating tex mem */
+      *mapOut = NULL;
+      return;
+   }
+      
+   map = swImage->Buffer;
 
    if (texImage->TexObject->Target == GL_TEXTURE_3D ||
        texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
@@ -156,6 +208,13 @@ _swrast_map_teximage(struct gl_context *ctx,
                                                  1);
       assert(slice < texImage->Depth);
       map += slice * sliceSize;
+   } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
+      GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
+                                                 texImage->Width,
+                                                 1,
+                                                 1);
+      assert(slice < texImage->Height);
+      map += slice * sliceSize;
    }
 
    /* apply x/y offset to map address */
@@ -172,3 +231,169 @@ _swrast_unmap_teximage(struct gl_context *ctx,
 {
    /* nop */
 }
+
+
+void
+_swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
+{
+   const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
+   GLuint face, level;
+
+   for (face = 0; face < faces; face++) {
+      for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
+         struct gl_texture_image *texImage = texObj->Image[face][level];
+         if (texImage) {
+            struct swrast_texture_image *swImage =
+               swrast_texture_image(texImage);
+
+            /* XXX we'll eventually call _swrast_map_teximage() here */
+            swImage->Data = swImage->Buffer;
+         }
+      }
+   }
+}
+
+
+void
+_swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
+{
+   const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
+   GLuint face, level;
+
+   for (face = 0; face < faces; face++) {
+      for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
+         struct gl_texture_image *texImage = texObj->Image[face][level];
+         if (texImage) {
+            struct swrast_texture_image *swImage
+               = swrast_texture_image(texImage);
+
+            /* XXX we'll eventually call _swrast_unmap_teximage() here */
+            swImage->Data = NULL;
+         }
+      }
+   }
+}
+
+
+/**
+ * Map all textures for reading prior to software rendering.
+ */
+void
+_swrast_map_textures(struct gl_context *ctx)
+{
+   GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
+
+   /* loop over enabled texture units */
+   while (enabledUnits) {
+      GLuint unit = ffs(enabledUnits) - 1;
+      struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+      
+      _swrast_map_texture(ctx, texObj);
+
+      enabledUnits &= ~(1 << unit);
+   }
+}
+
+
+/**
+ * Unmap all textures for reading prior to software rendering.
+ */
+void
+_swrast_unmap_textures(struct gl_context *ctx)
+{
+   GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
+
+   /* loop over enabled texture units */
+   while (enabledUnits) {
+      GLuint unit = ffs(enabledUnits) - 1;
+      struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
+      
+      _swrast_unmap_texture(ctx, texObj);
+
+      enabledUnits &= ~(1 << unit);
+   }
+}
+
+
+/**
+ * Map or unmap any textures that we may be rendering to as renderbuffers.
+ */
+static void
+map_unmap_renderbuffers(struct gl_context *ctx,
+                        struct gl_framebuffer *fb,
+                        GLboolean map)
+{
+   GLuint i;
+
+   for (i = 0; i < Elements(fb->Attachment); i++) {
+      struct gl_texture_object *texObj = fb->Attachment[i].Texture;
+      if (texObj) {
+         const GLuint level = fb->Attachment[i].TextureLevel;
+         const GLuint face = fb->Attachment[i].CubeMapFace;
+         struct gl_texture_image *texImage = texObj->Image[face][level];
+         if (texImage) {
+            struct swrast_texture_image *swImage
+               = swrast_texture_image(texImage);
+
+            if (map) {
+               /* XXX we'll eventually call _swrast_map_teximage() here */
+               swImage->Data = swImage->Buffer;
+            }
+            else {
+               /* XXX we'll eventually call _swrast_unmap_teximage() here */
+               swImage->Data = NULL;
+            }
+         }
+      }
+   }
+}
+
+
+void
+_swrast_map_renderbuffers(struct gl_context *ctx)
+{
+   map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_TRUE);
+   if (ctx->ReadBuffer != ctx->DrawBuffer)
+      map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_TRUE);
+}
+
+
+void
+_swrast_unmap_renderbuffers(struct gl_context *ctx)
+{
+   map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_FALSE);
+   if (ctx->ReadBuffer != ctx->DrawBuffer)
+      map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_FALSE);
+}
+
+
+
+/**
+ * Called via ctx->Driver.AllocTextureStorage()
+ * Just have to allocate memory for the texture images.
+ */
+GLboolean
+_swrast_AllocTextureStorage(struct gl_context *ctx,
+                            struct gl_texture_object *texObj,
+                            GLsizei levels, GLsizei width,
+                            GLsizei height, GLsizei depth)
+{
+   const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
+   GLint face, level;
+
+   for (face = 0; face < numFaces; face++) {
+      for (level = 0; level < levels; level++) {
+         struct gl_texture_image *texImage = texObj->Image[face][level];
+         if (!_swrast_alloc_texture_image_buffer(ctx, texImage,
+                                                 texImage->TexFormat,
+                                                 texImage->Width,
+                                                 texImage->Height,
+                                                 texImage->Depth)) {
+            return GL_FALSE;
+         }
+      }
+   }
+
+   return GL_TRUE;
+}
+