/*
* Mesa 3-D graphics library
- * Version: 6.1
+ * Version: 6.3
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
/**
- * 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()
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
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;
format, type, pixels, packing);
if (!success) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
- return;
}
}
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, packing);
}
return;
}
- data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
+ data = validate_pbo_compressed_teximage(ctx, imageSize, data, &ctx->Unpack,
+ "glCompressedTexImage2D");
if (!data)
return;
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, &ctx->Unpack);
}
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;
&ctx->Texture.Unit[ctx->Texture.CurrentUnit],
texObj);
}
+
+ unmap_teximage_pbo(ctx, &ctx->Unpack);
}