Map/Unmap PBO as needed so that the texstore routines can work with
authorBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Oct 2004 16:18:07 +0000 (16:18 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Sun, 31 Oct 2004 16:18:07 +0000 (16:18 +0000)
hardware-based PBOs in the future.

src/mesa/main/texstore.c

index 8c33a0fd18c6299bf755e1dc934bcdcfd9e349c7..2ca9b5941ad4de56b2a893183e40924b2764d2cc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.1
+ * Version:  6.3
  *
  * Copyright (C) 1999-2004  Brian Paul   All Rights Reserved.
  *
@@ -1789,57 +1789,91 @@ _mesa_texstore_rgba_float16(STORE_PARAMS)
 
 
 /**
- * Validate acces to a PBO for texture data.
- *
- * \todo If the PBO is really resident in VRAM, this won't work; the
- * device driver should check for that and do the right thing.
+ * Check if an unpack PBO is active prior to fetching a texture image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call unmap_teximage_pbo() too!
  */
 static const GLvoid *
-validate_pbo_teximage( GLsizei width, GLsizei height, GLsizei depth,
-                       GLenum format, GLenum type, const GLvoid *pixels,
-                       const struct gl_pixelstore_attrib *unpack )
+validate_pbo_teximage(GLcontext *ctx,
+                      GLsizei width, GLsizei height, GLsizei depth,
+                      GLenum format, GLenum type, const GLvoid *pixels,
+                      const struct gl_pixelstore_attrib *unpack,
+                      const char *funcName)
 {
+   GLubyte *buf;
+
    if (unpack->BufferObj->Name == 0) {
       /* no PBO */
       return pixels;
    }
-   else if (_mesa_validate_pbo_access(unpack, width, height, depth, format,
-                                      type, pixels)) {
-      return ADD_POINTERS(unpack->BufferObj->Data, pixels);
+   if (!_mesa_validate_pbo_access(unpack, width, height, depth, format,
+                                  type, pixels)) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
+      return NULL;
+   }
+
+   buf = ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                               GL_READ_ONLY_ARB, unpack->BufferObj);
+   if (!buf) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+      return NULL;
    }
-   /* bad access! */
-   return NULL;
+
+   return ADD_POINTERS(buf, pixels);
 }
 
 
 /**
- * Validate that unpacking compressed texture image data from a PBO
- * won't go out of bounds.
- *
- * \todo If the PBO is really resident in VRAM, this won't work; the
- * device driver should check for that and do the right thing.
+ * Check if an unpack PBO is active prior to fetching a compressed texture
+ * image.
+ * If so, do bounds checking and map the buffer into main memory.
+ * Any errors detected will be recorded.
+ * The caller _must_ call unmap_teximage_pbo() too!
  */
 static const GLvoid *
-validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels,
-                               const struct gl_pixelstore_attrib *packing)
+validate_pbo_compressed_teximage(GLcontext *ctx,
+                                 GLsizei imageSize, const GLvoid *pixels,
+                                 const struct gl_pixelstore_attrib *packing,
+                                 const char *funcName)
 {
+   GLubyte *buf;
+
    if (packing->BufferObj->Name == 0) {
       /* not using a PBO - return pointer unchanged */
       return pixels;
    }
-   else {
-      /* using a PBO */
-      if ((const GLubyte *) pixels + imageSize >
-          (const GLubyte *) packing->BufferObj->Size) {
-         /* out of bounds read! */
-         return NULL;
-      }
-      /* OK! */
-      return ADD_POINTERS(packing->BufferObj->Data, pixels);
+   if ((const GLubyte *) pixels + imageSize >
+       (const GLubyte *) packing->BufferObj->Size) {
+      /* out of bounds read! */
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
+      return NULL;
+   }
+
+   buf = ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                               GL_READ_ONLY_ARB, packing->BufferObj);
+   if (!buf) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
+      return NULL;
    }
+
+   return ADD_POINTERS(buf, pixels);
 }
 
 
+/**
+ * This function must be called after either of the validate_pbo_*_teximage()
+ * functions.  It unmaps the PBO buffer if it was mapped earlier.
+ */
+static void
+unmap_teximage_pbo(GLcontext *ctx, const struct gl_pixelstore_attrib *unpack)
+{
+   if (unpack->BufferObj->Name) {
+      ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
+                              unpack->BufferObj);
+   }
+}
+
 
 /*
  * This is the software fallback for Driver.TexImage1D()
@@ -1881,7 +1915,8 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, 1, 1, format, type, pixels,
+                                  packing, "glTexImage1D");
    if (!pixels)
       return;
 
@@ -1898,7 +1933,6 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
-         return;
       }
    }
 
@@ -1908,6 +1942,8 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -1958,8 +1994,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, height, 1,
-                                  format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, height, 1, format, type, pixels,
+                                  packing, "glTexImage2D");
    if (!pixels)
       return;
 
@@ -1982,7 +2018,6 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
-         return;
       }
    }
 
@@ -1992,6 +2027,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2033,8 +2070,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   pixels = validate_pbo_teximage(width, height, depth,
-                                  format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, height, depth, format, type,
+                                  pixels, packing, "glTexImage3D");
    if (!pixels)
       return;
 
@@ -2060,7 +2097,6 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
-         return;
       }
    }
 
@@ -2070,6 +2106,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2087,8 +2125,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, 1, 1,
-                                  format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, 1, 1, format, type, pixels,
+                                  packing, "glTexSubImage1D");
    if (!pixels)
       return;
 
@@ -2105,7 +2143,6 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
-         return;
       }
    }
 
@@ -2115,6 +2152,8 @@ _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2132,8 +2171,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, height, 1,
-                                  format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, height, 1, format, type, pixels,
+                                  packing, "glTexSubImage2D");
    if (!pixels)
       return;
 
@@ -2157,7 +2196,6 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
-         return;
       }
    }
 
@@ -2167,6 +2205,8 @@ _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2183,8 +2223,8 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                           struct gl_texture_object *texObj,
                           struct gl_texture_image *texImage)
 {
-   pixels = validate_pbo_teximage(width, height, depth,
-                                  format, type, pixels, packing);
+   pixels = validate_pbo_teximage(ctx, width, height, depth, format, type,
+                                  pixels, packing, "glTexSubImage3D");
    if (!pixels)
       return;
 
@@ -2210,7 +2250,6 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                                                 format, type, pixels, packing);
       if (!success) {
          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
-         return;
       }
    }
 
@@ -2220,6 +2259,8 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, packing);
 }
 
 
@@ -2284,7 +2325,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
       return;
    }
 
-   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
+   data = validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+                                           "glCompressedTexImage2D");
    if (!data)
       return;
 
@@ -2298,6 +2340,8 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, &ctx->Unpack);
 }
 
 
@@ -2375,7 +2419,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
    ASSERT((xoffset & 3) == 0);
    ASSERT((yoffset & 3) == 0);
 
-   data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
+   data = validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+                                           "glCompressedTexSubImage2D");
    if (!data)
       return;
 
@@ -2404,6 +2449,8 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
                             &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
                             texObj);
    }
+
+   unmap_teximage_pbo(ctx, &ctx->Unpack);
 }