From 7a6b71ef2944bae1718e8167b2faaceb8422071c Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Sat, 13 Mar 2004 18:21:40 +0000 Subject: [PATCH] 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. --- src/mesa/drivers/x11/xm_dd.c | 12 ++++ src/mesa/main/attrib.c | 19 ++++++ src/mesa/main/bufferobj.c | 76 +++++++++++++++++++++ src/mesa/main/bufferobj.h | 10 ++- src/mesa/main/config.h | 1 + src/mesa/main/dlist.c | 124 ++++++++++++++++++++++------------- src/mesa/main/drawpix.c | 33 ++++------ src/mesa/main/extensions.c | 4 ++ src/mesa/main/get.c | 40 +++++++++++ src/mesa/main/glheader.h | 8 +++ src/mesa/main/image.c | 34 +++------- src/mesa/main/image.h | 3 - src/mesa/main/mtypes.h | 16 +++-- src/mesa/main/pixel.c | 30 ++++++++- src/mesa/main/texstore.c | 84 ++++++++++++++++++++++-- src/mesa/swrast/s_bitmap.c | 13 +++- src/mesa/swrast/s_context.c | 23 +++++++ src/mesa/swrast/s_drawpix.c | 21 +++--- src/mesa/swrast/s_imaging.c | 22 ++++--- src/mesa/swrast/s_readpix.c | 22 +++++-- src/mesa/swrast/s_texstore.c | 49 +++++++------- src/mesa/swrast/swrast.h | 6 +- 22 files changed, 486 insertions(+), 164 deletions(-) diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c index f54003bc852..1178b71b74f 100644 --- a/src/mesa/drivers/x11/xm_dd.c +++ b/src/mesa/drivers/x11/xm_dd.c @@ -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 diff --git a/src/mesa/main/attrib.c b/src/mesa/main/attrib.c index e3423c74170..339c40b9bdd 100644 --- a/src/mesa/main/attrib.c +++ b/src/mesa/main/attrib.c @@ -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; diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 882f24526c7..1f9b988d334 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -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--; diff --git a/src/mesa/main/bufferobj.h b/src/mesa/main/bufferobj.h index 236545b9abe..e6bd8b329a7 100644 --- a/src/mesa/main/bufferobj.h +++ b/src/mesa/main/bufferobj.h @@ -1,9 +1,8 @@ - /* * 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 diff --git a/src/mesa/main/config.h b/src/mesa/main/config.h index 6d8952d9af0..74ebb469afa 100644 --- a/src/mesa/main/config.h +++ b/src/mesa/main/config.h @@ -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 diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 3c7fe9c47da..26bf76a0077 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -618,7 +618,11 @@ static GLuint translate_id( GLsizei n, GLenum type, const GLvoid *list ) /***** Public *****/ /**********************************************************************/ -void _mesa_init_lists( void ) +/** + * Do one-time initialiazations for display lists. + */ +void +_mesa_init_lists( void ) { static int init_flag = 0; @@ -789,6 +793,32 @@ void _mesa_init_lists( void ) } + +/** + * Wrapper for _mesa_unpack_image() that handles pixel buffer objects. + * \todo This won't suffice when the PBO is really in VRAM/GPU memory. + */ +static GLvoid * +unpack_image( 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 _mesa_unpack_image(width, height, depth, format, type, + pixels, unpack); + } + else if (_mesa_validate_pbo_access(unpack, width, height, depth, format, + type, pixels)) { + const GLubyte *src = ADD_POINTERS(unpack->BufferObj->Data, pixels); + return _mesa_unpack_image(width, height, depth, format, type, + src, unpack); + } + /* bad access! */ + return NULL; +} + + /* * Allocate space for a display list instruction. * \param opcode - type of instruction @@ -1255,8 +1285,8 @@ static void GLAPIENTRY save_ColorTable( GLenum target, GLenum internalFormat, format, type, table ); } else { - GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, table, - &ctx->Unpack); + GLvoid *image = unpack_image(width, 1, 1, format, type, table, + &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_TABLE, 6 ); @@ -1344,8 +1374,8 @@ static void GLAPIENTRY save_ColorSubTable( GLenum target, GLsizei start, GLsizei const GLvoid *table) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = _mesa_unpack_image(count, 1, 1, format, type, table, - &ctx->Unpack); + GLvoid *image = unpack_image(count, 1, 1, format, type, table, + &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_COLOR_SUB_TABLE, 6 ); @@ -1415,8 +1445,8 @@ save_ConvolutionFilter1D(GLenum target, GLenum internalFormat, GLsizei width, GLenum format, GLenum type, const GLvoid *filter) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, filter, - &ctx->Unpack); + GLvoid *image = unpack_image(width, 1, 1, format, type, filter, + &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_FILTER_1D, 6 ); @@ -1444,8 +1474,8 @@ save_ConvolutionFilter2D(GLenum target, GLenum internalFormat, GLenum type, const GLvoid *filter) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, filter, - &ctx->Unpack); + GLvoid *image = unpack_image(width, height, 1, format, type, filter, + &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_CONVOLUTION_FILTER_2D, 7 ); @@ -1809,8 +1839,8 @@ static void GLAPIENTRY save_DrawPixels( GLsizei width, GLsizei height, const GLvoid *pixels ) { GET_CURRENT_CONTEXT(ctx); - GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, height, 1, format, type, + pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_DRAW_PIXELS, 5 ); @@ -3365,8 +3395,8 @@ static void GLAPIENTRY save_TexImage1D( GLenum target, border, format, type, pixels ); } else { - GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, 1, 1, format, type, + pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE1D, 8 ); @@ -3404,8 +3434,8 @@ static void GLAPIENTRY save_TexImage2D( GLenum target, height, border, format, type, pixels ); } else { - GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, height, 1, format, type, + pixels, &ctx->Unpack); Node *n; ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE2D, 9 ); @@ -3446,8 +3476,8 @@ static void GLAPIENTRY save_TexImage3D( GLenum target, } else { Node *n; - GLvoid *image = _mesa_unpack_image(width, height, depth, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, height, depth, format, type, + pixels, &ctx->Unpack); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_IMAGE3D, 10 ); if (n) { @@ -3479,8 +3509,8 @@ static void GLAPIENTRY save_TexSubImage1D( GLenum target, GLint level, GLint xof { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = _mesa_unpack_image(width, 1, 1, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, 1, 1, format, type, + pixels, &ctx->Unpack); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE1D, 7 ); if (n) { @@ -3510,8 +3540,8 @@ static void GLAPIENTRY save_TexSubImage2D( GLenum target, GLint level, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = _mesa_unpack_image(width, height, 1, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, height, 1, format, type, + pixels, &ctx->Unpack); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE2D, 9 ); if (n) { @@ -3543,8 +3573,8 @@ static void GLAPIENTRY save_TexSubImage3D( GLenum target, GLint level, { GET_CURRENT_CONTEXT(ctx); Node *n; - GLvoid *image = _mesa_unpack_image(width, height, depth, format, type, - pixels, &ctx->Unpack); + GLvoid *image = unpack_image(width, height, depth, format, type, + pixels, &ctx->Unpack); ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); n = ALLOC_INSTRUCTION( ctx, OPCODE_TEX_SUB_IMAGE3D, 11 ); if (n) { @@ -5283,8 +5313,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_BITMAP: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->Bitmap)( (GLsizei) n[1].i, (GLsizei) n[2].i, n[3].f, n[4].f, n[5].f, n[6].f, (const GLubyte *) n[7].data ); ctx->Unpack = save; /* restore */ @@ -5354,8 +5384,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_COLOR_TABLE: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->ColorTable)( n[1].e, n[2].e, n[3].i, n[4].e, n[5].e, n[6].data ); ctx->Unpack = save; /* restore */ @@ -5383,8 +5413,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_COLOR_SUB_TABLE: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->ColorSubTable)( n[1].e, n[2].i, n[3].i, n[4].e, n[5].e, n[6].data ); ctx->Unpack = save; /* restore */ @@ -5392,8 +5422,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_CONVOLUTION_FILTER_1D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->ConvolutionFilter1D)( n[1].e, n[2].i, n[3].i, n[4].e, n[5].e, n[6].data ); ctx->Unpack = save; /* restore */ @@ -5401,8 +5431,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_CONVOLUTION_FILTER_2D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->ConvolutionFilter2D)( n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, n[6].e, n[7].data ); ctx->Unpack = save; /* restore */ @@ -5486,8 +5516,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_DRAW_PIXELS: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->DrawPixels)( n[1].i, n[2].i, n[3].e, n[4].e, n[5].data ); ctx->Unpack = save; /* restore */ @@ -5755,8 +5785,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_IMAGE1D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexImage1D)( n[1].e, /* target */ n[2].i, /* level */ @@ -5771,8 +5801,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_IMAGE2D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexImage2D)( n[1].e, /* target */ n[2].i, /* level */ @@ -5788,8 +5818,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_IMAGE3D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexImage3D)( n[1].e, /* target */ n[2].i, /* level */ @@ -5806,8 +5836,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_SUB_IMAGE1D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexSubImage1D)( n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, n[6].e, n[7].data ); @@ -5816,8 +5846,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_SUB_IMAGE2D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexSubImage2D)( n[1].e, n[2].i, n[3].i, n[4].i, n[5].e, n[6].i, n[7].e, n[8].e, n[9].data ); @@ -5826,8 +5856,8 @@ execute_list( GLcontext *ctx, GLuint list ) break; case OPCODE_TEX_SUB_IMAGE3D: { - struct gl_pixelstore_attrib save = ctx->Unpack; - ctx->Unpack = _mesa_native_packing; + const struct gl_pixelstore_attrib save = ctx->Unpack; + ctx->Unpack = ctx->DefaultPacking; (*ctx->Exec->TexSubImage3D)( n[1].e, n[2].i, n[3].i, n[4].i, n[5].i, n[6].i, n[7].i, n[8].i, n[9].e, n[10].e, diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index 745d7a304d9..fc7dd32b06b 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -1,6 +1,6 @@ /* * 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) { diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index 01810b65b24..2ae48b4edb0 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -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; diff --git a/src/mesa/main/get.c b/src/mesa/main/get.c index 723c48ce3c9..fac3f072bc3 100644 --- a/src/mesa/main/get.c +++ b/src/mesa/main/get.c @@ -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: diff --git a/src/mesa/main/glheader.h b/src/mesa/main/glheader.h index a75c65dd4aa..dd4a404fc83 100644 --- a/src/mesa/main/glheader.h +++ b/src/mesa/main/glheader.h @@ -211,6 +211,14 @@ typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESC #include +/* 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__ diff --git a/src/mesa/main/image.c b/src/mesa/main/image.c index 5c117f6ce6a..d6108659967 100644 --- a/src/mesa/main/image.c +++ b/src/mesa/main/image.c @@ -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, diff --git a/src/mesa/main/image.h b/src/mesa/main/image.h index b3757a30fdc..ffe629e103f 100644 --- a/src/mesa/main/image.h +++ b/src/mesa/main/image.h @@ -35,9 +35,6 @@ #include "mtypes.h" -extern const struct gl_pixelstore_attrib _mesa_native_packing; - - extern void _mesa_swap2( GLushort *p, GLuint n ); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 3ef508b3f83..0dcf54baf72 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -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 */ diff --git a/src/mesa/main/pixel.c b/src/mesa/main/pixel.c index 6800170faae..8e2b55fc347 100644 --- a/src/mesa/main/pixel.c +++ b/src/mesa/main/pixel.c @@ -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; diff --git a/src/mesa/main/texstore.c b/src/mesa/main/texstore.c index 315cd6ca2d3..4ed7d38beb9 100644 --- a/src/mesa/main/texstore.c +++ b/src/mesa/main/texstore.c @@ -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); + data = validate_pbo_compressed_teximage(imageSize, data, &ctx->Unpack); + if (!data) + return; + srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width); src = (const GLubyte *) data; diff --git a/src/mesa/swrast/s_bitmap.c b/src/mesa/swrast/s_bitmap.c index aeacba88eac..6c8f515b626 100644 --- a/src/mesa/swrast/s_bitmap.c +++ b/src/mesa/swrast/s_bitmap.c @@ -1,8 +1,8 @@ /* * 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"), @@ -53,7 +53,14 @@ _swrast_Bitmap( GLcontext *ctx, GLint px, GLint py, struct sw_span span; ASSERT(ctx->RenderMode == GL_RENDER); - ASSERT(bitmap); + + bitmap = _swrast_validate_pbo_access(unpack, width, height, 1, + GL_COLOR_INDEX, GL_BITMAP, + (GLvoid *) bitmap); + if (!bitmap) { + /* XXX GL_INVALID_OPERATION? */ + return; + } RENDER_START(swrast,ctx); diff --git a/src/mesa/swrast/s_context.c b/src/mesa/swrast/s_context.c index 0a81048e6f5..be800d4d594 100644 --- a/src/mesa/swrast/s_context.c +++ b/src/mesa/swrast/s_context.c @@ -27,6 +27,7 @@ */ #include "imports.h" +#include "bufferobj.h" #include "context.h" #include "colormac.h" #include "mtypes.h" @@ -731,3 +732,25 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v ) _mesa_debug(ctx, "\n"); } } + + +/** + * Validate access to a PBO to be sure we're not going to read/write + * out of buffer bounds. + */ +GLvoid * +_swrast_validate_pbo_access(const struct gl_pixelstore_attrib *pack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLvoid *ptr) +{ + if (pack->BufferObj->Name == 0) { + /* no PBO */ + return ptr; + } + else if (_mesa_validate_pbo_access(pack, width, height, depth, format, + type, ptr)) { + return ADD_POINTERS(pack->BufferObj->Data, ptr); + } + /* bad access! */ + return NULL; +} diff --git a/src/mesa/swrast/s_drawpix.c b/src/mesa/swrast/s_drawpix.c index 5b6f9244057..337b5a5bfd4 100644 --- a/src/mesa/swrast/s_drawpix.c +++ b/src/mesa/swrast/s_drawpix.c @@ -1,8 +1,8 @@ /* * 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"), @@ -785,14 +785,14 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, GLint row; GLfloat *dest, *tmpImage; - tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); + tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); return; } - convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); + convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!convImage) { - FREE(tmpImage); + _mesa_free(tmpImage); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glDrawPixels"); return; } @@ -816,10 +816,10 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, ASSERT(ctx->Pixel.Separable2DEnabled); _mesa_convolve_sep_image(ctx, &width, &height, tmpImage, convImage); } - FREE(tmpImage); + _mesa_free(tmpImage); /* continue transfer ops and draw the convolved image */ - unpack = &_mesa_native_packing; + unpack = &ctx->DefaultPacking; pixels = convImage; format = GL_RGBA; type = GL_FLOAT; @@ -887,7 +887,7 @@ draw_rgba_pixels( GLcontext *ctx, GLint x, GLint y, } if (convImage) { - FREE(convImage); + _mesa_free(convImage); } } @@ -910,6 +910,11 @@ _swrast_DrawPixels( GLcontext *ctx, if (swrast->NewState) _swrast_validate_derived( ctx ); + pixels = _swrast_validate_pbo_access(unpack, width, height, 1, + format, type, (GLvoid *) pixels); + if (!pixels) + return; + RENDER_START(swrast,ctx); switch (format) { diff --git a/src/mesa/swrast/s_imaging.c b/src/mesa/swrast/s_imaging.c index b9c413687b1..52c809f7a9b 100644 --- a/src/mesa/swrast/s_imaging.c +++ b/src/mesa/swrast/s_imaging.c @@ -1,9 +1,8 @@ - /* * Mesa 3-D graphics library - * Version: 4.1 + * Version: 6.1 * - * Copyright (C) 1999-2002 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"), @@ -30,6 +29,9 @@ #include "s_context.h" #include "s_span.h" +#include "colortab.h" +#include "convolve.h" + void _swrast_CopyColorTable( GLcontext *ctx, @@ -50,9 +52,10 @@ _swrast_CopyColorTable( GLcontext *ctx, /* Restore reading from draw buffer (the default) */ _swrast_use_draw_buffer(ctx); - glColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data); + _mesa_ColorTable(target, internalformat, width, GL_RGBA, CHAN_TYPE, data); } + void _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, GLint x, GLint y, GLsizei width) @@ -71,7 +74,7 @@ _swrast_CopyColorSubTable( GLcontext *ctx,GLenum target, GLsizei start, /* Restore reading from draw buffer (the default) */ _swrast_use_draw_buffer(ctx); - glColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data); + _mesa_ColorSubTable(target, start, width, GL_RGBA, CHAN_TYPE, data); } @@ -98,8 +101,8 @@ _swrast_CopyConvolutionFilter1D(GLcontext *ctx, GLenum target, _swrast_use_draw_buffer(ctx); /* store as convolution filter */ - glConvolutionFilter1D(target, internalFormat, width, - GL_RGBA, CHAN_TYPE, rgba); + _mesa_ConvolutionFilter1D(target, internalFormat, width, + GL_RGBA, CHAN_TYPE, rgba); } @@ -145,10 +148,11 @@ _swrast_CopyConvolutionFilter2D(GLcontext *ctx, GLenum target, ctx->Unpack.SkipImages = 0; ctx->Unpack.SwapBytes = GL_FALSE; ctx->Unpack.LsbFirst = GL_FALSE; + ctx->Unpack.BufferObj = ctx->Array.NullBufferObj; ctx->NewState |= _NEW_PACKUNPACK; - glConvolutionFilter2D(target, internalFormat, width, height, - GL_RGBA, CHAN_TYPE, rgba); + _mesa_ConvolutionFilter2D(target, internalFormat, width, height, + GL_RGBA, CHAN_TYPE, rgba); ctx->Unpack = packSave; /* restore pixel packing params */ ctx->NewState |= _NEW_PACKUNPACK; diff --git a/src/mesa/swrast/s_readpix.c b/src/mesa/swrast/s_readpix.c index 7c2ce364913..b5ab06e4ba6 100644 --- a/src/mesa/swrast/s_readpix.c +++ b/src/mesa/swrast/s_readpix.c @@ -1,8 +1,8 @@ /* * 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"), @@ -382,14 +382,14 @@ read_rgba_pixels( GLcontext *ctx, GLfloat *dest, *src, *tmpImage, *convImage; GLint row; - tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); + tmpImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!tmpImage) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); return; } - convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat)); + convImage = (GLfloat *) _mesa_malloc(width * height * 4 * sizeof(GLfloat)); if (!convImage) { - FREE(tmpImage); + _mesa_free(tmpImage); _mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels"); return; } @@ -410,7 +410,7 @@ read_rgba_pixels( GLcontext *ctx, _mesa_map_ci_to_rgba_chan(ctx, readWidth, index, rgba); } _mesa_pack_rgba_span_chan(ctx, readWidth, (const GLchan (*)[4]) rgba, - GL_RGBA, GL_FLOAT, dest, &_mesa_native_packing, + GL_RGBA, GL_FLOAT, dest, &ctx->DefaultPacking, transferOps & IMAGE_PRE_CONVOLUTION_BITS); dest += width * 4; } @@ -423,7 +423,7 @@ read_rgba_pixels( GLcontext *ctx, ASSERT(ctx->Pixel.Separable2DEnabled); _mesa_convolve_sep_image(ctx, &readWidth, &height, tmpImage, convImage); } - FREE(tmpImage); + _mesa_free(tmpImage); /* finish transfer ops and pack the resulting image */ src = convImage; @@ -501,6 +501,14 @@ _swrast_ReadPixels( GLcontext *ctx, if (swrast->NewState) _swrast_validate_derived( ctx ); + pixels = _swrast_validate_pbo_access(pack, width, height, 1, + format, type, (GLvoid *) pixels); + + if (!pixels) { + _mesa_error( ctx, GL_INVALID_VALUE, "glReadPixels(pixels)" ); + return; + } + RENDER_START(swrast,ctx); switch (format) { diff --git a/src/mesa/swrast/s_texstore.c b/src/mesa/swrast/s_texstore.c index edf75f61f5e..fa6b74b7451 100644 --- a/src/mesa/swrast/s_texstore.c +++ b/src/mesa/swrast/s_texstore.c @@ -1,9 +1,8 @@ - /* * 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"), @@ -68,7 +67,7 @@ read_color_image( GLcontext *ctx, GLint x, GLint y, GLint stride, i; GLchan *image, *dst; - image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan)); + image = (GLchan *) _mesa_malloc(width * height * 4 * sizeof(GLchan)); if (!image) return NULL; @@ -105,7 +104,7 @@ read_depth_image( GLcontext *ctx, GLint x, GLint y, GLfloat *image, *dst; GLint i; - image = (GLfloat *) MALLOC(width * height * sizeof(GLfloat)); + image = (GLfloat *) _mesa_malloc(width * height * sizeof(GLfloat)); if (!image) return NULL; @@ -171,8 +170,8 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level, (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, width, border, GL_DEPTH_COMPONENT, GL_FLOAT, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } else { /* read RGBA image from framebuffer */ @@ -186,8 +185,8 @@ _swrast_copy_teximage1d( GLcontext *ctx, GLenum target, GLint level, (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, width, border, GL_RGBA, CHAN_TYPE, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } /* GL_SGIS_generate_mipmap */ @@ -230,8 +229,8 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level, (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, width, height, border, GL_DEPTH_COMPONENT, GL_FLOAT, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } else { /* read RGBA image from framebuffer */ @@ -245,8 +244,8 @@ _swrast_copy_teximage2d( GLcontext *ctx, GLenum target, GLint level, (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, width, height, border, GL_RGBA, CHAN_TYPE, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } /* GL_SGIS_generate_mipmap */ @@ -286,8 +285,8 @@ _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level, /* call glTexSubImage1D to redefine the texture */ (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, GL_DEPTH_COMPONENT, GL_FLOAT, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } else { /* read RGBA image from framebuffer */ @@ -300,8 +299,8 @@ _swrast_copy_texsubimage1d( GLcontext *ctx, GLenum target, GLint level, /* now call glTexSubImage1D to do the real work */ (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, GL_RGBA, CHAN_TYPE, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } /* GL_SGIS_generate_mipmap */ @@ -344,8 +343,8 @@ _swrast_copy_texsubimage2d( GLcontext *ctx, (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, width, height, GL_DEPTH_COMPONENT, GL_FLOAT, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } else { /* read RGBA image from framebuffer */ @@ -359,8 +358,8 @@ _swrast_copy_texsubimage2d( GLcontext *ctx, (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, width, height, GL_RGBA, CHAN_TYPE, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } /* GL_SGIS_generate_mipmap */ @@ -403,8 +402,8 @@ _swrast_copy_texsubimage3d( GLcontext *ctx, (*ctx->Driver.TexSubImage3D)(ctx, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_DEPTH_COMPONENT, GL_FLOAT, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } else { /* read RGBA image from framebuffer */ @@ -418,8 +417,8 @@ _swrast_copy_texsubimage3d( GLcontext *ctx, (*ctx->Driver.TexSubImage3D)(ctx, target, level, xoffset, yoffset, zoffset, width, height, 1, GL_RGBA, CHAN_TYPE, image, - &_mesa_native_packing, texObj, texImage); - FREE(image); + &ctx->DefaultPacking, texObj, texImage); + _mesa_free(image); } /* GL_SGIS_generate_mipmap */ diff --git a/src/mesa/swrast/swrast.h b/src/mesa/swrast/swrast.h index 61cc017b85d..e1220cff4e1 100644 --- a/src/mesa/swrast/swrast.h +++ b/src/mesa/swrast/swrast.h @@ -197,6 +197,11 @@ extern void _swrast_print_vertex( GLcontext *ctx, const SWvertex *v ); +extern GLvoid * +_swrast_validate_pbo_access(const struct gl_pixelstore_attrib *pack, + GLsizei width, GLsizei height, GLsizei depth, + GLenum format, GLenum type, GLvoid *ptr); + /* * Imaging fallbacks (a better solution should be found, perhaps * moving all the imaging fallback code to a new module) @@ -252,7 +257,6 @@ _swrast_copy_texsubimage3d(GLcontext *ctx, GLint x, GLint y, GLsizei width, GLsizei height); - /* The driver interface for the software rasterizer. * Unless otherwise noted, all functions are mandatory. */ -- 2.30.2