intel: added fast memcpy path for glGetTexImage()
authorBrian Paul <brianp@vmware.com>
Thu, 29 Oct 2009 16:50:10 +0000 (10:50 -0600)
committerBrian Paul <brianp@vmware.com>
Thu, 29 Oct 2009 16:50:26 +0000 (10:50 -0600)
src/mesa/drivers/dri/intel/intel_tex_image.c

index 7e57e99be6317a0e88aef8cc18e1132603ad3d75..0199837cbe478d513bc73a87916d29f90df342d5 100644 (file)
@@ -6,6 +6,7 @@
 #include "main/bufferobj.h"
 #include "main/convolve.h"
 #include "main/context.h"
+#include "main/image.h"
 #include "main/texcompress.h"
 #include "main/texstore.h"
 #include "main/texgetimage.h"
@@ -618,6 +619,100 @@ intelCompressedTexImage2D( GLcontext *ctx, GLenum target, GLint level,
 }
 
 
+/**
+ * Try to use memcpy() to do a glGetTexImage().
+ * \return GL_TRUE if done, GL_FALSE otherwise
+ */
+static GLboolean
+memcpy_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)
+{
+   GLboolean memCopy = GL_FALSE;
+
+   /* Texture image should have been mapped already */
+   assert(texImage->Data);
+
+   /*
+    * Check if the src/dst formats are compatible.
+    * Also note that GL's pixel transfer ops don't apply to glGetTexImage()
+    * so we don't have to worry about those.
+    */
+   if ((texObj->Target == GL_TEXTURE_1D ||
+        texObj->Target == GL_TEXTURE_2D ||
+        texObj->Target == GL_TEXTURE_RECTANGLE ||
+        (texObj->Target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
+         texObj->Target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))) {
+      if (texImage->TexFormat == MESA_FORMAT_ARGB8888 &&
+          format == GL_BGRA &&
+          type == GL_UNSIGNED_BYTE &&
+          _mesa_little_endian()) {
+         memCopy = GL_TRUE;
+      }
+      else if (texImage->TexFormat == MESA_FORMAT_AL88 &&
+               format == GL_LUMINANCE_ALPHA &&
+               type == GL_UNSIGNED_BYTE &&
+               _mesa_little_endian()) {
+         memCopy = GL_TRUE;
+      }
+      else if (texImage->TexFormat == MESA_FORMAT_L8 &&
+               format == GL_LUMINANCE &&
+               type == GL_UNSIGNED_BYTE) {
+         memCopy = GL_TRUE;
+      }
+      else if (texImage->TexFormat == MESA_FORMAT_A8 &&
+               format == GL_ALPHA &&
+               type == GL_UNSIGNED_BYTE) {
+         memCopy = GL_TRUE;
+      }
+   }
+
+   if (memCopy) {
+      struct gl_pixelstore_attrib *pack = &ctx->Pack;
+
+      if (_mesa_is_bufferobj(pack->BufferObj)) {
+         /* Packing texture image into a PBO */
+         GLubyte *buf = (GLubyte *)
+            ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
+                                  GL_WRITE_ONLY_ARB, pack->BufferObj);
+         if (!buf) {
+            /* out of memory or other unexpected error */
+            _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage(map PBO failed)");
+            return GL_TRUE; /* failed, but done */
+         }
+         pixels = ADD_POINTERS(buf, pixels);
+      }
+
+      {
+         const GLuint bpp = _mesa_get_format_bytes(texImage->TexFormat);
+         const GLuint bytesPerRow = texImage->Width * bpp;
+         GLubyte *dst =
+            _mesa_image_address2d(&ctx->Pack, pixels, texImage->Width,
+                                  texImage->Height, format, type, 0, 0);
+         const GLint dstRowStride =
+            _mesa_image_row_stride(&ctx->Pack, texImage->Width, format, type);
+         const GLubyte *src = texImage->Data;
+         const GLint srcRowStride = texImage->RowStride * bpp;
+         GLuint row;
+
+         printf("Fast getteximage!\n");
+         for (row = 0; row < texImage->Height; row++) {
+            memcpy(dst, src, bytesPerRow);
+            dst += dstRowStride;
+            src += srcRowStride;
+         }         
+      }
+
+      if (_mesa_is_bufferobj(pack->BufferObj)) {
+         ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj);
+      }
+   }
+
+   return memCopy;
+}
+
+
 /**
  * Need to map texture image into memory before copying image data,
  * then unmap it.
@@ -667,9 +762,13 @@ intel_get_tex_image(GLcontext * ctx, GLenum target, GLint level,
    if (compressed) {
       _mesa_get_compressed_teximage(ctx, target, level, pixels,
                                    texObj, texImage);
-   } else {
-      _mesa_get_teximage(ctx, target, level, format, type, pixels,
-                        texObj, texImage);
+   }
+   else {
+      if (!memcpy_get_tex_image(ctx, target, level, format, type, pixels,
+                                texObj, texImage)) {
+         _mesa_get_teximage(ctx, target, level, format, type, pixels,
+                            texObj, texImage);
+      }
    }