Commit 7a6b71ef authored by Brian Paul's avatar Brian Paul

Implementation of GL_EXT_pixel_buffer_object extension.

Note: extension may not be finalized yet - subject to change!
Note: implementation not fully suitable for h/w implementation yet.
parent 5498e8b9
......@@ -843,6 +843,12 @@ xmesa_DrawPixels_8R8G8B( GLcontext *ctx,
int srcX = unpack->SkipPixels;
int srcY = unpack->SkipRows;
int rowLength = unpack->RowLength ? unpack->RowLength : width;
pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
format, type, (GLvoid *) pixels);
if (!pixels)
return;
if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
/* This is a little tricky since all coordinates up to now have
* been in the OpenGL bottom-to-top orientation. X is top-to-bottom
......@@ -918,6 +924,12 @@ xmesa_DrawPixels_5R6G5B( GLcontext *ctx,
int srcX = unpack->SkipPixels;
int srcY = unpack->SkipRows;
int rowLength = unpack->RowLength ? unpack->RowLength : width;
pixels = _swrast_validate_pbo_access(unpack, width, height, 1,
format, type, (GLvoid *) pixels);
if (!pixels)
return;
if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) {
/* This is a little tricky since all coordinates up to now have
* been in the OpenGL bottom-to-top orientation. X is top-to-bottom
......
......@@ -28,6 +28,7 @@
#include "attrib.h"
#include "blend.h"
#include "buffers.h"
#include "bufferobj.h"
#include "colormac.h"
#include "colortab.h"
#include "context.h"
......@@ -1191,6 +1192,10 @@ _mesa_PushClientAttrib(GLbitfield mask)
if (mask & GL_CLIENT_PIXEL_STORE_BIT) {
struct gl_pixelstore_attrib *attr;
#if FEATURE_EXT_pixel_buffer_object
ctx->Pack.BufferObj->RefCount++;
ctx->Unpack.BufferObj->RefCount++;
#endif
/* packing attribs */
attr = MALLOC_STRUCT( gl_pixelstore_attrib );
MEMCPY( attr, &ctx->Pack, sizeof(struct gl_pixelstore_attrib) );
......@@ -1244,11 +1249,25 @@ _mesa_PopClientAttrib(void)
while (attr) {
switch (attr->kind) {
case GL_CLIENT_PACK_BIT:
#if FEATURE_EXT_pixel_buffer_object
ctx->Pack.BufferObj->RefCount--;
if (ctx->Pack.BufferObj->RefCount <= 0) {
_mesa_remove_buffer_object( ctx, ctx->Pack.BufferObj );
(*ctx->Driver.DeleteBuffer)( ctx, ctx->Pack.BufferObj );
}
#endif
MEMCPY( &ctx->Pack, attr->data,
sizeof(struct gl_pixelstore_attrib) );
ctx->NewState |= _NEW_PACKUNPACK;
break;
case GL_CLIENT_UNPACK_BIT:
#if FEATURE_EXT_pixel_buffer_object
ctx->Unpack.BufferObj->RefCount--;
if (ctx->Unpack.BufferObj->RefCount <= 0) {
_mesa_remove_buffer_object( ctx, ctx->Unpack.BufferObj );
(*ctx->Driver.DeleteBuffer)( ctx, ctx->Unpack.BufferObj );
}
#endif
MEMCPY( &ctx->Unpack, attr->data,
sizeof(struct gl_pixelstore_attrib) );
ctx->NewState |= _NEW_PACKUNPACK;
......
......@@ -33,6 +33,7 @@
#include "glheader.h"
#include "hash.h"
#include "imports.h"
#include "image.h"
#include "context.h"
#include "bufferobj.h"
......@@ -60,6 +61,12 @@ buffer_object_get_target( GLcontext *ctx, GLenum target, const char * str )
case GL_ELEMENT_ARRAY_BUFFER_ARB:
bufObj = ctx->Array.ElementArrayBufferObj;
break;
case GL_PIXEL_PACK_BUFFER_EXT:
bufObj = ctx->Pack.BufferObj;
break;
case GL_PIXEL_UNPACK_BUFFER_EXT:
bufObj = ctx->Unpack.BufferObj;
break;
default:
_mesa_error(ctx, GL_INVALID_ENUM, "gl%s(target)", str);
return NULL;
......@@ -358,6 +365,59 @@ _mesa_init_buffer_objects( GLcontext *ctx )
}
/**
* When we're about to read pixel data out of a PBO (via glDrawPixels,
* glTexImage, etc) or write data into a PBO (via glReadPixels,
* glGetTexImage, etc) we call this function to check that we're not
* going to read out of bounds.
*
* \param ctx the rendering context
* \param width width of image to read/write
* \param height height of image to read/write
* \param depth depth of image to read/write
* \param format format of image to read/write
* \param type datatype of image to read/write
* \param ptr the user-provided pointer/offset
* \return GL_TRUE if the PBO access is OK, GL_FALSE if the access would
* go out of bounds.
*/
GLboolean
_mesa_validate_pbo_access(const struct gl_pixelstore_attrib *pack,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *ptr)
{
GLvoid *start, *end;
ASSERT(pack->BufferObj->Name != 0);
if (pack->BufferObj->Size == 0)
/* no buffer! */
return GL_FALSE;
/* get address of first pixel we'll read */
start = _mesa_image_address(pack, ptr, width, height,
format, type, 0, 0, 0);
/* get address just past the last pixel we'll read */
end = _mesa_image_address(pack, ptr, width, height,
format, type, depth-1, height-1, width);
if ((const GLubyte *) start > (const GLubyte *) pack->BufferObj->Size) {
/* This will catch negative values / wrap-around */
return GL_FALSE;
}
if ((const GLubyte *) end > (const GLubyte *) pack->BufferObj->Size) {
/* Image read goes beyond end of buffer */
return GL_FALSE;
}
/* OK! */
return GL_TRUE;
}
/**********************************************************************/
/* API Functions */
......@@ -407,6 +467,15 @@ _mesa_BindBufferARB(GLenum target, GLuint buffer)
case GL_ELEMENT_ARRAY_BUFFER_ARB:
ctx->Array.ElementArrayBufferObj = newBufObj;
break;
case GL_PIXEL_PACK_BUFFER_EXT:
ctx->Pack.BufferObj = newBufObj;
break;
case GL_PIXEL_UNPACK_BUFFER_EXT:
ctx->Unpack.BufferObj = newBufObj;
break;
default:
_mesa_problem(ctx, "Bad target in _mesa_BindBufferARB");
return;
}
/* Pass BindBuffer call to device driver */
......@@ -504,6 +573,13 @@ _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids)
_mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 );
}
if (ctx->Pack.BufferObj == bufObj) {
_mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 );
}
if (ctx->Unpack.BufferObj == bufObj) {
_mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 );
}
/* decrement refcount and delete if <= 0 */
bufObj->DeletePending = GL_TRUE;
bufObj->RefCount--;
......
/*
* Mesa 3-D graphics library
* Version: 5.1
* Version: 6.1
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
......@@ -75,6 +74,11 @@ _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access,
struct gl_buffer_object * bufObj );
extern GLboolean
_mesa_validate_pbo_access(const struct gl_pixelstore_attrib *pack,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *ptr);
/*
* API functions
......
......@@ -270,6 +270,7 @@
#define FEATURE_ARB_vertex_program _HAVE_FULL_GL
#define FEATURE_ARB_fragment_program _HAVE_FULL_GL
#define FEATURE_ARB_occlusion_query _HAVE_FULL_GL
#define FEATURE_EXT_pixel_buffer_object _HAVE_FULL_GL
#define FEATURE_MESA_program_debug _HAVE_FULL_GL
#define FEATURE_NV_fence _HAVE_FULL_GL
#define FEATURE_NV_fragment_program _HAVE_FULL_GL
......
This diff is collapsed.
/*
* Mesa 3-D graphics library
* Version: 6.0.1
* Version: 6.1
*
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
......@@ -32,6 +32,7 @@
#include "state.h"
#include "mtypes.h"
#if _HAVE_FULL_GL
/*
......@@ -58,7 +59,7 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
if (ctx->RenderMode==GL_RENDER) {
GLint x, y;
if (!pixels || !ctx->Current.RasterPosValid) {
if (!ctx->Current.RasterPosValid) {
return;
}
......@@ -93,6 +94,7 @@ _mesa_DrawPixels( GLsizei width, GLsizei height,
}
}
void GLAPIENTRY
_mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
GLenum type )
......@@ -148,7 +150,7 @@ _mesa_CopyPixels( GLint srcx, GLint srcy, GLsizei width, GLsizei height,
}
}
#endif
#endif /* _HAVE_FULL_GL */
......@@ -165,11 +167,6 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
return;
}
if (!pixels) {
_mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" );
return;
}
if (ctx->NewState)
_mesa_update_state(ctx);
......@@ -179,8 +176,6 @@ _mesa_ReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
void GLAPIENTRY
_mesa_Bitmap( GLsizei width, GLsizei height,
GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove,
......@@ -206,18 +201,16 @@ _mesa_Bitmap( GLsizei width, GLsizei height,
}
if (ctx->RenderMode==GL_RENDER) {
if (bitmap) {
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
/* Truncate, to satisfy conformance tests (matches SGI's OpenGL). */
GLint x = IFLOOR(ctx->Current.RasterPos[0] - xorig);
GLint y = IFLOOR(ctx->Current.RasterPos[1] - yorig);
if (ctx->NewState) {
_mesa_update_state(ctx);
}
ctx->OcclusionResult = GL_TRUE;
ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
if (ctx->NewState) {
_mesa_update_state(ctx);
}
ctx->OcclusionResult = GL_TRUE;
ctx->Driver.Bitmap( ctx, x, y, width, height, &ctx->Unpack, bitmap );
}
#if _HAVE_FULL_GL
else if (ctx->RenderMode==GL_FEEDBACK) {
......
......@@ -83,6 +83,7 @@ static const struct {
{ OFF, "GL_EXT_multi_draw_arrays", F(EXT_multi_draw_arrays) },
{ ON, "GL_EXT_packed_pixels", F(EXT_packed_pixels) },
{ OFF, "GL_EXT_paletted_texture", F(EXT_paletted_texture) },
{ OFF, "GL_EXT_pixel_buffer_object", F(EXT_pixel_buffer_object) },
{ OFF, "GL_EXT_point_parameters", F(EXT_point_parameters) },
{ ON, "GL_EXT_polygon_offset", F(EXT_polygon_offset) },
{ ON, "GL_EXT_rescale_normal", F(EXT_rescale_normal) },
......@@ -195,6 +196,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
ctx->Extensions.EXT_histogram = GL_TRUE;
ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
ctx->Extensions.EXT_paletted_texture = GL_TRUE;
#if FEATURE_EXT_pixel_buffer_object
ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
#endif
ctx->Extensions.EXT_point_parameters = GL_TRUE;
ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
ctx->Extensions.EXT_secondary_color = GL_TRUE;
......
......@@ -1609,6 +1609,16 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
*params = INT_TO_BOOL(ctx->Array.ElementArrayBufferObj->Name);
break;
#endif
#if FEATURE_EXT_pixel_buffer_object
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_B(EXT_pixel_buffer_object, pname);
*params = INT_TO_BOOL(ctx->Pack.BufferObj->Name);
break;
case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_B(EXT_pixel_buffer_object, pname);
*params = INT_TO_BOOL(ctx->Unpack.BufferObj->Name);
break;
#endif
#if FEATURE_ARB_fragment_program
case GL_FRAGMENT_PROGRAM_ARB:
......@@ -3149,6 +3159,16 @@ _mesa_GetDoublev( GLenum pname, GLdouble *params )
*params = (GLdouble) ctx->Array.ElementArrayBufferObj->Name;
break;
#endif
#if FEATURE_EXT_pixel_buffer_object
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_D(EXT_pixel_buffer_object, pname);
*params = (GLdouble) ctx->Pack.BufferObj->Name;
break;
case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_D(EXT_pixel_buffer_object, pname);
*params = (GLdouble) ctx->Unpack.BufferObj->Name;
break;
#endif
#if FEATURE_ARB_fragment_program
case GL_FRAGMENT_PROGRAM_ARB:
......@@ -4665,6 +4685,16 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
*params = (GLfloat) ctx->Array.ElementArrayBufferObj->Name;
break;
#endif
#if FEATURE_EXT_pixel_buffer_object
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_F(EXT_pixel_buffer_object, pname);
*params = (GLfloat) ctx->Pack.BufferObj->Name;
break;
case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_F(EXT_pixel_buffer_object, pname);
*params = (GLfloat) ctx->Unpack.BufferObj->Name;
break;
#endif
#if FEATURE_ARB_fragment_program
case GL_FRAGMENT_PROGRAM_ARB:
......@@ -6219,6 +6249,16 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
*params = (GLint) ctx->Array.ElementArrayBufferObj->Name;
break;
#endif
#if FEATURE_EXT_pixel_buffer_object
case GL_PIXEL_PACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_I(EXT_pixel_buffer_object, pname);
*params = (GLint) ctx->Pack.BufferObj->Name;
break;
case GL_PIXEL_UNPACK_BUFFER_BINDING_EXT:
CHECK_EXTENSION_I(EXT_pixel_buffer_object, pname);
*params = (GLint) ctx->Unpack.BufferObj->Name;
break;
#endif
#if FEATURE_ARB_fragment_program
case GL_FRAGMENT_PROGRAM_ARB:
......
......@@ -211,6 +211,14 @@ typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESC
#include <GL/internal/glcore.h>
/* XXX temporary hack */
#ifndef GL_PIXEL_PACK_BUFFER_EXT
#define GL_PIXEL_PACK_BUFFER_EXT 0x88EB
#define GL_PIXEL_UNPACK_BUFFER_EXT 0x88EC
#define GL_PIXEL_PACK_BUFFER_BINDING_EXT 0x88ED
#define GL_PIXEL_UNPACK_BUFFER_BINDING_EXT 0x88EF
#endif
/* Disable unreachable code warnings for Watcom C++ */
#ifdef __WATCOMC__
......
......@@ -5,9 +5,9 @@
/*
* Mesa 3-D graphics library
* Version: 5.1
* Version: 6.1
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
* Copyright (C) 1999-2004 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
......@@ -29,6 +29,7 @@
#include "glheader.h"
#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
#include "image.h"
......@@ -43,27 +44,6 @@
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
/**
* Image packing parameters for Mesa's internal images.
*
* _mesa_unpack_image() returns image data in this format. When we execute
* image commands (glDrawPixels(), glTexImage(), etc) from within display lists
* we have to be sure to set the current unpacking parameters to these values!
*/
const struct gl_pixelstore_attrib _mesa_native_packing = {
1, /* Alignment */
0, /* RowLength */
0, /* SkipPixels */
0, /* SkipRows */
0, /* ImageHeight */
0, /* SkipImages */
GL_FALSE, /* SwapBytes */
GL_FALSE, /* LsbFirst */
GL_FALSE, /* ClientStorage */
GL_FALSE /* Invert */
};
/**
* Flip the 8 bits in each byte of the given array.
*
......@@ -3974,9 +3954,11 @@ _mesa_pack_depth_span( const GLcontext *ctx, GLuint n, GLvoid *dest,
}
/*
* Unpack image data. Apply byteswapping, byte flipping (bitmap).
* Return all image data in a contiguous block.
/**
* Unpack image data. Apply byte swapping, byte flipping (bitmap).
* Return all image data in a contiguous block. This is used when we
* compile glDrawPixels, glTexImage, etc into a display list. We
* need a copy of the data in a standard format.
*/
void *
_mesa_unpack_image( GLsizei width, GLsizei height, GLsizei depth,
......
......@@ -35,9 +35,6 @@
#include "mtypes.h"
extern const struct gl_pixelstore_attrib _mesa_native_packing;
extern void
_mesa_swap2( GLushort *p, GLuint n );
......
......@@ -1319,17 +1319,18 @@ struct gl_attrib_node {
/**
* GL_ARB_vertex_buffer_object buffer object
* GL_ARB_vertex/pixel_buffer_object buffer object
*/
struct gl_buffer_object {
GLint RefCount;
GLuint Name;
GLenum Usage;
GLenum Access;
GLvoid *Pointer; /**< Only valid while buffer is mapped */
GLuint Size; /**< Size of data array in bytes */
GLubyte *Data; /**< The storage */
GLboolean DeletePending; /**< Deleted by user? */
GLvoid *Pointer; /**< Only valid while buffer is mapped */
GLuint Size; /**< Size of storage in bytes */
GLubyte *Data; /**< Location of storage either in RAM or VRAM. */
GLboolean OnCard; /**< Is buffer in VRAM? (hardware drivers) */
GLboolean DeletePending; /**< Deleted by user but RefCount > 0? */
};
......@@ -1348,6 +1349,7 @@ struct gl_pixelstore_attrib {
GLboolean LsbFirst;
GLboolean ClientStorage; /**< GL_APPLE_client_storage */
GLboolean Invert; /**< GL_MESA_pack_invert */
struct gl_buffer_object *BufferObj; /**< GL_ARB_pixel_buffer_object */
};
......@@ -1518,7 +1520,7 @@ enum register_file
PROGRAM_NAMED_PARAM,
PROGRAM_STATE_VAR,
PROGRAM_WRITE_ONLY,
PROGRAM_ADDRESS
PROGRAM_ADDRESS
};
......@@ -1852,6 +1854,7 @@ struct gl_extensions
GLboolean EXT_multi_draw_arrays;
GLboolean EXT_paletted_texture;
GLboolean EXT_packed_pixels;
GLboolean EXT_pixel_buffer_object;
GLboolean EXT_point_parameters;
GLboolean EXT_polygon_offset;
GLboolean EXT_rescale_normal;
......@@ -2264,6 +2267,7 @@ struct __GLcontextRec {
struct gl_array_attrib Array; /**< Vertex arrays */
struct gl_pixelstore_attrib Pack; /**< Pixel packing */
struct gl_pixelstore_attrib Unpack; /**< Pixel unpacking */
struct gl_pixelstore_attrib DefaultPacking; /**< Default params */
struct gl_evaluators EvalMap; /**< All evaluators */
struct gl_feedback Feedback; /**< Feedback */
......
......@@ -24,6 +24,7 @@
#include "glheader.h"
#include "imports.h"
#include "image.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
......@@ -1682,7 +1683,8 @@ void _mesa_update_pixel( GLcontext *ctx, GLuint new_state )
/***** Initialization *****/
/**********************************************************************/
void _mesa_init_pixel( GLcontext * ctx )
void
_mesa_init_pixel( GLcontext * ctx )
{
int i;
......@@ -1774,6 +1776,9 @@ void _mesa_init_pixel( GLcontext * ctx )
ctx->Pack.LsbFirst = GL_FALSE;
ctx->Pack.ClientStorage = GL_FALSE;
ctx->Pack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
ctx->Pack.BufferObj = ctx->Array.NullBufferObj;
#endif
ctx->Unpack.Alignment = 4;
ctx->Unpack.RowLength = 0;
ctx->Unpack.ImageHeight = 0;
......@@ -1784,6 +1789,29 @@ void _mesa_init_pixel( GLcontext * ctx )
ctx->Unpack.LsbFirst = GL_FALSE;
ctx->Unpack.ClientStorage = GL_FALSE;
ctx->Unpack.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
ctx->Unpack.BufferObj = ctx->Array.NullBufferObj;
#endif
/*
* _mesa_unpack_image() returns image data in this format. When we
* execute image commands (glDrawPixels(), glTexImage(), etc) from
* within display lists we have to be sure to set the current
* unpacking parameters to these values!
*/
ctx->DefaultPacking.Alignment = 1;
ctx->DefaultPacking.RowLength = 0;
ctx->DefaultPacking.SkipPixels = 0;
ctx->DefaultPacking.SkipRows = 0;
ctx->DefaultPacking.ImageHeight = 0;
ctx->DefaultPacking.SkipImages = 0;
ctx->DefaultPacking.SwapBytes = GL_FALSE;
ctx->DefaultPacking.LsbFirst = GL_FALSE;
ctx->DefaultPacking.ClientStorage = GL_FALSE;
ctx->DefaultPacking.Invert = GL_FALSE;
#if FEATURE_EXT_pixel_buffer_object
ctx->DefaultPacking.BufferObj = ctx->Array.NullBufferObj;
#endif
if (ctx->Visual.doubleBufferMode) {
ctx->Pixel.ReadBuffer = GL_BACK;
......
......@@ -52,6 +52,7 @@
#include "glheader.h"
#include "bufferobj.h"
#include "colormac.h"
#include "context.h"
#include "convolve.h"
......@@ -391,7 +392,7 @@ transfer_teximage(GLcontext *ctx, GLuint dimensions,
_mesa_pack_rgba_span_float(ctx, convWidth,
(const GLfloat (*)[4]) srcf,
texDestFormat, CHAN_TYPE,
dest, &_mesa_native_packing,
dest, &ctx->DefaultPacking,
transferOps
& IMAGE_POST_CONVOLUTION_BITS);
srcf += convWidth * 4;
......@@ -519,7 +520,7 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
srcFormat = baseInternalFormat;
srcType = CHAN_TYPE;
srcAddr = tmpImage;
srcPacking = &_mesa_native_packing;
srcPacking = &ctx->DefaultPacking;
freeSourceData = GL_TRUE;
transferOps = 0; /* image transfer ops were completed */
}
......@@ -611,7 +612,7 @@ _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
srcFormat = tmpFormat;
srcType = CHAN_TYPE;
srcAddr = tmpImage;
srcPacking = &_mesa_native_packing;
srcPacking = &ctx->DefaultPacking;
freeSourceData = GL_TRUE;
}
......@@ -740,6 +741,58 @@ transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions,
}
/**
* 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.
*/
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 )
{
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);
}
/* bad access! */
return NULL;
}
/**
* 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.
*/
static const GLvoid *
validate_pbo_compressed_teximage(GLsizei imageSize, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing)
{
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);
}
}
/*
* This is the software fallback for Driver.TexImage1D()
......@@ -785,6 +838,7 @@ _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
return;
}
pixels = validate_pbo_teximage(width, 1, 1, format, type, pixels, packing);
if (!pixels)
return;
......@@ -862,6 +916,8 @@ _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
return;
}
pixels = validate_pbo_teximage(width, height, 1,
format, type, pixels, packing);
if (!pixels)
return;
......@@ -934,6 +990,8 @@ _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
return;
}
pixels = validate_pbo_teximage(width, height, depth,
format, type, pixels, packing);
if (!pixels)
return;
......@@ -980,6 +1038,11 @@ _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);
if (!pixels)
return;
if (texImage->IsCompressed) {
GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
texImage->Width);
......@@ -1029,6 +1092,11 @@ _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);
if (!pixels)
return;
if (texImage->IsCompressed) {
GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
texImage->Width);
......@@ -1113,8 +1181,6 @@ _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
}
/*
* Fallback for Driver.CompressedTexImage1D()
*/
......@@ -1167,6 +1233,10 @@ _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
return;
}
data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack);
if (!data)
return;
/* copy the data */
ASSERT(texImage->CompressedSize == (GLuint) imageSize);
MEMCPY(texImage->Data, data, imageSize);
......@@ -1231,6 +1301,10 @@ _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
ASSERT((xoffset & 3) == 0);
ASSERT((yoffset & 3) == 0);