pbo.c revision 01e04c3f
13464ebd5Sriastradh/* 23464ebd5Sriastradh * Mesa 3-D graphics library 33464ebd5Sriastradh * 43464ebd5Sriastradh * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 53464ebd5Sriastradh * Copyright (C) 2009-2011 VMware, Inc. All Rights Reserved. 63464ebd5Sriastradh * 73464ebd5Sriastradh * Permission is hereby granted, free of charge, to any person obtaining a 83464ebd5Sriastradh * copy of this software and associated documentation files (the "Software"), 93464ebd5Sriastradh * to deal in the Software without restriction, including without limitation 103464ebd5Sriastradh * the rights to use, copy, modify, merge, publish, distribute, sublicense, 113464ebd5Sriastradh * and/or sell copies of the Software, and to permit persons to whom the 123464ebd5Sriastradh * Software is furnished to do so, subject to the following conditions: 133464ebd5Sriastradh * 143464ebd5Sriastradh * The above copyright notice and this permission notice shall be included 153464ebd5Sriastradh * in all copies or substantial portions of the Software. 163464ebd5Sriastradh * 173464ebd5Sriastradh * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 183464ebd5Sriastradh * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 193464ebd5Sriastradh * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 243464ebd5Sriastradh */ 253464ebd5Sriastradh 263464ebd5Sriastradh 273464ebd5Sriastradh/** 283464ebd5Sriastradh * \file pbo.c 293464ebd5Sriastradh * \brief Functions related to Pixel Buffer Objects. 303464ebd5Sriastradh */ 313464ebd5Sriastradh 323464ebd5Sriastradh 333464ebd5Sriastradh 3401e04c3fSmrg#include "errors.h" 353464ebd5Sriastradh#include "glheader.h" 363464ebd5Sriastradh#include "bufferobj.h" 37af69d88dSmrg#include "glformats.h" 383464ebd5Sriastradh#include "image.h" 393464ebd5Sriastradh#include "imports.h" 403464ebd5Sriastradh#include "mtypes.h" 413464ebd5Sriastradh#include "pbo.h" 423464ebd5Sriastradh 433464ebd5Sriastradh 443464ebd5Sriastradh 453464ebd5Sriastradh/** 463464ebd5Sriastradh * When we're about to read pixel data out of a PBO (via glDrawPixels, 473464ebd5Sriastradh * glTexImage, etc) or write data into a PBO (via glReadPixels, 483464ebd5Sriastradh * glGetTexImage, etc) we call this function to check that we're not 493464ebd5Sriastradh * going to read/write out of bounds. 503464ebd5Sriastradh * 513464ebd5Sriastradh * XXX This would also be a convenient time to check that the PBO isn't 523464ebd5Sriastradh * currently mapped. Whoever calls this function should check for that. 533464ebd5Sriastradh * Remember, we can't use a PBO when it's mapped! 543464ebd5Sriastradh * 553464ebd5Sriastradh * If we're not using a PBO, this is a no-op. 563464ebd5Sriastradh * 573464ebd5Sriastradh * \param width width of image to read/write 583464ebd5Sriastradh * \param height height of image to read/write 593464ebd5Sriastradh * \param depth depth of image to read/write 603464ebd5Sriastradh * \param format format of image to read/write 613464ebd5Sriastradh * \param type datatype of image to read/write 623464ebd5Sriastradh * \param clientMemSize the maximum number of bytes to read/write 633464ebd5Sriastradh * \param ptr the user-provided pointer/offset 643464ebd5Sriastradh * \return GL_TRUE if the buffer access is OK, GL_FALSE if the access would 653464ebd5Sriastradh * go out of bounds. 663464ebd5Sriastradh */ 673464ebd5SriastradhGLboolean 683464ebd5Sriastradh_mesa_validate_pbo_access(GLuint dimensions, 693464ebd5Sriastradh const struct gl_pixelstore_attrib *pack, 703464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 713464ebd5Sriastradh GLenum format, GLenum type, GLsizei clientMemSize, 723464ebd5Sriastradh const GLvoid *ptr) 733464ebd5Sriastradh{ 74af69d88dSmrg /* unsigned, to detect overflow/wrap-around */ 75af69d88dSmrg uintptr_t start, end, offset, size; 763464ebd5Sriastradh 773464ebd5Sriastradh /* If no PBO is bound, 'ptr' is a pointer to client memory containing 783464ebd5Sriastradh 'clientMemSize' bytes. 793464ebd5Sriastradh If a PBO is bound, 'ptr' is an offset into the bound PBO. 803464ebd5Sriastradh In that case 'clientMemSize' is ignored: we just use the PBO's size. 813464ebd5Sriastradh */ 823464ebd5Sriastradh if (!_mesa_is_bufferobj(pack->BufferObj)) { 833464ebd5Sriastradh offset = 0; 8401e04c3fSmrg size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize; 853464ebd5Sriastradh } else { 86af69d88dSmrg offset = (uintptr_t)ptr; 87af69d88dSmrg size = pack->BufferObj->Size; 883464ebd5Sriastradh /* The ARB_pixel_buffer_object spec says: 893464ebd5Sriastradh * "INVALID_OPERATION is generated by ColorTable, ColorSubTable, 903464ebd5Sriastradh * ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D, 913464ebd5Sriastradh * TexImage1D, TexImage2D, TexImage3D, TexSubImage1D, 923464ebd5Sriastradh * TexSubImage2D, TexSubImage3D, and DrawPixels if the current 933464ebd5Sriastradh * PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data 943464ebd5Sriastradh * parameter is not evenly divisible into the number of basic machine 953464ebd5Sriastradh * units needed to store in memory a datum indicated by the type 963464ebd5Sriastradh * parameter." 973464ebd5Sriastradh */ 983464ebd5Sriastradh if (type != GL_BITMAP && 99af69d88dSmrg (offset % _mesa_sizeof_packed_type(type))) 1003464ebd5Sriastradh return GL_FALSE; 1013464ebd5Sriastradh } 1023464ebd5Sriastradh 103af69d88dSmrg if (size == 0) 1043464ebd5Sriastradh /* no buffer! */ 1053464ebd5Sriastradh return GL_FALSE; 1063464ebd5Sriastradh 10701e04c3fSmrg /* If the size of the image is zero then no pixels are accessed so we 10801e04c3fSmrg * don't need to check anything else. 10901e04c3fSmrg */ 11001e04c3fSmrg if (width == 0 || height == 0 || depth == 0) 11101e04c3fSmrg return GL_TRUE; 11201e04c3fSmrg 1133464ebd5Sriastradh /* get the offset to the first pixel we'll read/write */ 114af69d88dSmrg start = _mesa_image_offset(dimensions, pack, width, height, 115af69d88dSmrg format, type, 0, 0, 0); 1163464ebd5Sriastradh 1173464ebd5Sriastradh /* get the offset to just past the last pixel we'll read/write */ 118af69d88dSmrg end = _mesa_image_offset(dimensions, pack, width, height, 119af69d88dSmrg format, type, depth-1, height-1, width); 1203464ebd5Sriastradh 121af69d88dSmrg start += offset; 122af69d88dSmrg end += offset; 123af69d88dSmrg 124af69d88dSmrg if (start > size) { 1253464ebd5Sriastradh /* This will catch negative values / wrap-around */ 1263464ebd5Sriastradh return GL_FALSE; 1273464ebd5Sriastradh } 128af69d88dSmrg if (end > size) { 1293464ebd5Sriastradh /* Image read/write goes beyond end of buffer */ 1303464ebd5Sriastradh return GL_FALSE; 1313464ebd5Sriastradh } 1323464ebd5Sriastradh 1333464ebd5Sriastradh /* OK! */ 1343464ebd5Sriastradh return GL_TRUE; 1353464ebd5Sriastradh} 1363464ebd5Sriastradh 1373464ebd5Sriastradh 1383464ebd5Sriastradh/** 1393464ebd5Sriastradh * For commands that read from a PBO (glDrawPixels, glTexImage, 1403464ebd5Sriastradh * glPolygonStipple, etc), if we're reading from a PBO, map it read-only 1413464ebd5Sriastradh * and return the pointer into the PBO. If we're not reading from a 1423464ebd5Sriastradh * PBO, return \p src as-is. 1433464ebd5Sriastradh * If non-null return, must call _mesa_unmap_pbo_source() when done. 1443464ebd5Sriastradh * 1453464ebd5Sriastradh * \return NULL if error, else pointer to start of data 1463464ebd5Sriastradh */ 1473464ebd5Sriastradhconst GLvoid * 1483464ebd5Sriastradh_mesa_map_pbo_source(struct gl_context *ctx, 1493464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack, 1503464ebd5Sriastradh const GLvoid *src) 1513464ebd5Sriastradh{ 1523464ebd5Sriastradh const GLubyte *buf; 1533464ebd5Sriastradh 1543464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 1553464ebd5Sriastradh /* unpack from PBO */ 156af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 157af69d88dSmrg unpack->BufferObj->Size, 158af69d88dSmrg GL_MAP_READ_BIT, 159af69d88dSmrg unpack->BufferObj, 160af69d88dSmrg MAP_INTERNAL); 1613464ebd5Sriastradh if (!buf) 1623464ebd5Sriastradh return NULL; 1633464ebd5Sriastradh 1643464ebd5Sriastradh buf = ADD_POINTERS(buf, src); 1653464ebd5Sriastradh } 1663464ebd5Sriastradh else { 1673464ebd5Sriastradh /* unpack from normal memory */ 1683464ebd5Sriastradh buf = src; 1693464ebd5Sriastradh } 1703464ebd5Sriastradh 1713464ebd5Sriastradh return buf; 1723464ebd5Sriastradh} 1733464ebd5Sriastradh 1743464ebd5Sriastradh/** 17501e04c3fSmrg * Perform PBO validation for read operations with uncompressed textures. 17601e04c3fSmrg * If any GL errors are detected, false is returned, otherwise returns true. 1773464ebd5Sriastradh * \sa _mesa_validate_pbo_access 1783464ebd5Sriastradh */ 17901e04c3fSmrgbool 18001e04c3fSmrg_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions, 18101e04c3fSmrg const struct gl_pixelstore_attrib *unpack, 18201e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 18301e04c3fSmrg GLenum format, GLenum type, 18401e04c3fSmrg GLsizei clientMemSize, 18501e04c3fSmrg const GLvoid *ptr, const char *where) 1863464ebd5Sriastradh{ 18701e04c3fSmrg assert(dimensions == 1 || dimensions == 2 || dimensions == 3); 1883464ebd5Sriastradh 1893464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 1903464ebd5Sriastradh format, type, clientMemSize, ptr)) { 1913464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 1923464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 19301e04c3fSmrg "%s(out of bounds PBO access)", 19401e04c3fSmrg where); 1953464ebd5Sriastradh } else { 1963464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 1973464ebd5Sriastradh "%s(out of bounds access: bufSize (%d) is too small)", 1983464ebd5Sriastradh where, clientMemSize); 1993464ebd5Sriastradh } 20001e04c3fSmrg return false; 2013464ebd5Sriastradh } 2023464ebd5Sriastradh 2033464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 2043464ebd5Sriastradh /* non-PBO access: no further validation to be done */ 20501e04c3fSmrg return true; 2063464ebd5Sriastradh } 2073464ebd5Sriastradh 208af69d88dSmrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 2093464ebd5Sriastradh /* buffer is already mapped - that's an error */ 21001e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", 21101e04c3fSmrg where); 21201e04c3fSmrg return false; 21301e04c3fSmrg } 21401e04c3fSmrg 21501e04c3fSmrg return true; 21601e04c3fSmrg} 21701e04c3fSmrg 21801e04c3fSmrg/** 21901e04c3fSmrg * Perform PBO validation for read operations with compressed textures. 22001e04c3fSmrg * If any GL errors are detected, false is returned, otherwise returns true. 22101e04c3fSmrg */ 22201e04c3fSmrgbool 22301e04c3fSmrg_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions, 22401e04c3fSmrg const struct gl_pixelstore_attrib *unpack, 22501e04c3fSmrg GLsizei imageSize, const GLvoid *pixels, 22601e04c3fSmrg const char *where) 22701e04c3fSmrg{ 22801e04c3fSmrg if (!_mesa_is_bufferobj(unpack->BufferObj)) { 22901e04c3fSmrg /* not using a PBO */ 23001e04c3fSmrg return true; 23101e04c3fSmrg } 23201e04c3fSmrg 23301e04c3fSmrg if ((const GLubyte *) pixels + imageSize > 23401e04c3fSmrg ((const GLubyte *) 0) + unpack->BufferObj->Size) { 23501e04c3fSmrg /* out of bounds read! */ 23601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)", 23701e04c3fSmrg where); 23801e04c3fSmrg return false; 23901e04c3fSmrg } 24001e04c3fSmrg 24101e04c3fSmrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 24201e04c3fSmrg /* buffer is already mapped - that's an error */ 24301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", 24401e04c3fSmrg where); 24501e04c3fSmrg return false; 24601e04c3fSmrg } 24701e04c3fSmrg 24801e04c3fSmrg return true; 24901e04c3fSmrg} 25001e04c3fSmrg 25101e04c3fSmrg/** 25201e04c3fSmrg * Perform PBO-read mapping. 25301e04c3fSmrg * If any GL errors are detected, they'll be recorded and NULL returned. 25401e04c3fSmrg * \sa _mesa_validate_pbo_source 25501e04c3fSmrg * \sa _mesa_map_pbo_source 25601e04c3fSmrg * A call to this function should have a matching call to 25701e04c3fSmrg * _mesa_unmap_pbo_source(). 25801e04c3fSmrg */ 25901e04c3fSmrgconst GLvoid * 26001e04c3fSmrg_mesa_map_validate_pbo_source(struct gl_context *ctx, 26101e04c3fSmrg GLuint dimensions, 26201e04c3fSmrg const struct gl_pixelstore_attrib *unpack, 26301e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 26401e04c3fSmrg GLenum format, GLenum type, 26501e04c3fSmrg GLsizei clientMemSize, 26601e04c3fSmrg const GLvoid *ptr, const char *where) 26701e04c3fSmrg{ 26801e04c3fSmrg if (!_mesa_validate_pbo_source(ctx, dimensions, unpack, 26901e04c3fSmrg width, height, depth, format, type, 27001e04c3fSmrg clientMemSize, ptr, where)) { 27101e04c3fSmrg return NULL; 2723464ebd5Sriastradh } 2733464ebd5Sriastradh 2743464ebd5Sriastradh ptr = _mesa_map_pbo_source(ctx, unpack, ptr); 2753464ebd5Sriastradh return ptr; 2763464ebd5Sriastradh} 2773464ebd5Sriastradh 2783464ebd5Sriastradh 2793464ebd5Sriastradh/** 2803464ebd5Sriastradh * Counterpart to _mesa_map_pbo_source() 2813464ebd5Sriastradh */ 2823464ebd5Sriastradhvoid 2833464ebd5Sriastradh_mesa_unmap_pbo_source(struct gl_context *ctx, 2843464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack) 2853464ebd5Sriastradh{ 28601e04c3fSmrg assert(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ 2873464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 288af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 2893464ebd5Sriastradh } 2903464ebd5Sriastradh} 2913464ebd5Sriastradh 2923464ebd5Sriastradh 2933464ebd5Sriastradh/** 2943464ebd5Sriastradh * For commands that write to a PBO (glReadPixels, glGetColorTable, etc), 2953464ebd5Sriastradh * if we're writing to a PBO, map it write-only and return the pointer 2963464ebd5Sriastradh * into the PBO. If we're not writing to a PBO, return \p dst as-is. 2973464ebd5Sriastradh * If non-null return, must call _mesa_unmap_pbo_dest() when done. 2983464ebd5Sriastradh * 2993464ebd5Sriastradh * \return NULL if error, else pointer to start of data 3003464ebd5Sriastradh */ 3013464ebd5Sriastradhvoid * 3023464ebd5Sriastradh_mesa_map_pbo_dest(struct gl_context *ctx, 3033464ebd5Sriastradh const struct gl_pixelstore_attrib *pack, 3043464ebd5Sriastradh GLvoid *dest) 3053464ebd5Sriastradh{ 3063464ebd5Sriastradh void *buf; 3073464ebd5Sriastradh 3083464ebd5Sriastradh if (_mesa_is_bufferobj(pack->BufferObj)) { 3093464ebd5Sriastradh /* pack into PBO */ 310af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 311af69d88dSmrg pack->BufferObj->Size, 312af69d88dSmrg GL_MAP_WRITE_BIT, 313af69d88dSmrg pack->BufferObj, 314af69d88dSmrg MAP_INTERNAL); 3153464ebd5Sriastradh if (!buf) 3163464ebd5Sriastradh return NULL; 3173464ebd5Sriastradh 3183464ebd5Sriastradh buf = ADD_POINTERS(buf, dest); 3193464ebd5Sriastradh } 3203464ebd5Sriastradh else { 3213464ebd5Sriastradh /* pack to normal memory */ 3223464ebd5Sriastradh buf = dest; 3233464ebd5Sriastradh } 3243464ebd5Sriastradh 3253464ebd5Sriastradh return buf; 3263464ebd5Sriastradh} 3273464ebd5Sriastradh 3283464ebd5Sriastradh 3293464ebd5Sriastradh/** 3303464ebd5Sriastradh * Combine PBO-write validation and mapping. 3313464ebd5Sriastradh * If any GL errors are detected, they'll be recorded and NULL returned. 3323464ebd5Sriastradh * \sa _mesa_validate_pbo_access 3333464ebd5Sriastradh * \sa _mesa_map_pbo_dest 3343464ebd5Sriastradh * A call to this function should have a matching call to 3353464ebd5Sriastradh * _mesa_unmap_pbo_dest(). 3363464ebd5Sriastradh */ 3373464ebd5SriastradhGLvoid * 3383464ebd5Sriastradh_mesa_map_validate_pbo_dest(struct gl_context *ctx, 339af69d88dSmrg GLuint dimensions, 340af69d88dSmrg const struct gl_pixelstore_attrib *unpack, 341af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 342af69d88dSmrg GLenum format, GLenum type, GLsizei clientMemSize, 343af69d88dSmrg GLvoid *ptr, const char *where) 3443464ebd5Sriastradh{ 34501e04c3fSmrg assert(dimensions == 1 || dimensions == 2 || dimensions == 3); 3463464ebd5Sriastradh 3473464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 3483464ebd5Sriastradh format, type, clientMemSize, ptr)) { 3493464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 3503464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 3513464ebd5Sriastradh "%s(out of bounds PBO access)", where); 3523464ebd5Sriastradh } else { 3533464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 3543464ebd5Sriastradh "%s(out of bounds access: bufSize (%d) is too small)", 3553464ebd5Sriastradh where, clientMemSize); 3563464ebd5Sriastradh } 3573464ebd5Sriastradh return NULL; 3583464ebd5Sriastradh } 3593464ebd5Sriastradh 3603464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 3613464ebd5Sriastradh /* non-PBO access: no further validation to be done */ 3623464ebd5Sriastradh return ptr; 3633464ebd5Sriastradh } 3643464ebd5Sriastradh 365af69d88dSmrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 3663464ebd5Sriastradh /* buffer is already mapped - that's an error */ 3673464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); 3683464ebd5Sriastradh return NULL; 3693464ebd5Sriastradh } 3703464ebd5Sriastradh 3713464ebd5Sriastradh ptr = _mesa_map_pbo_dest(ctx, unpack, ptr); 3723464ebd5Sriastradh return ptr; 3733464ebd5Sriastradh} 3743464ebd5Sriastradh 3753464ebd5Sriastradh 3763464ebd5Sriastradh/** 3773464ebd5Sriastradh * Counterpart to _mesa_map_pbo_dest() 3783464ebd5Sriastradh */ 3793464ebd5Sriastradhvoid 3803464ebd5Sriastradh_mesa_unmap_pbo_dest(struct gl_context *ctx, 3813464ebd5Sriastradh const struct gl_pixelstore_attrib *pack) 3823464ebd5Sriastradh{ 38301e04c3fSmrg assert(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ 3843464ebd5Sriastradh if (_mesa_is_bufferobj(pack->BufferObj)) { 385af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); 3863464ebd5Sriastradh } 3873464ebd5Sriastradh} 3883464ebd5Sriastradh 3893464ebd5Sriastradh 3903464ebd5Sriastradh/** 3913464ebd5Sriastradh * Check if an unpack PBO is active prior to fetching a texture image. 3923464ebd5Sriastradh * If so, do bounds checking and map the buffer into main memory. 3933464ebd5Sriastradh * Any errors detected will be recorded. 3943464ebd5Sriastradh * The caller _must_ call _mesa_unmap_teximage_pbo() too! 3953464ebd5Sriastradh */ 3963464ebd5Sriastradhconst GLvoid * 3973464ebd5Sriastradh_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, 3983464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 3993464ebd5Sriastradh GLenum format, GLenum type, const GLvoid *pixels, 4003464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack, 4013464ebd5Sriastradh const char *funcName) 4023464ebd5Sriastradh{ 4033464ebd5Sriastradh GLubyte *buf; 4043464ebd5Sriastradh 4053464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 4063464ebd5Sriastradh /* no PBO */ 4073464ebd5Sriastradh return pixels; 4083464ebd5Sriastradh } 4093464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 410af69d88dSmrg format, type, INT_MAX, pixels)) { 411af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", 412af69d88dSmrg funcName, dimensions); 4133464ebd5Sriastradh return NULL; 4143464ebd5Sriastradh } 4153464ebd5Sriastradh 416af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 417af69d88dSmrg unpack->BufferObj->Size, 418af69d88dSmrg GL_MAP_READ_BIT, 419af69d88dSmrg unpack->BufferObj, 420af69d88dSmrg MAP_INTERNAL); 4213464ebd5Sriastradh if (!buf) { 422af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, 423af69d88dSmrg dimensions); 4243464ebd5Sriastradh return NULL; 4253464ebd5Sriastradh } 4263464ebd5Sriastradh 4273464ebd5Sriastradh return ADD_POINTERS(buf, pixels); 4283464ebd5Sriastradh} 4293464ebd5Sriastradh 4303464ebd5Sriastradh 4313464ebd5Sriastradh/** 4323464ebd5Sriastradh * Check if an unpack PBO is active prior to fetching a compressed texture 4333464ebd5Sriastradh * image. 4343464ebd5Sriastradh * If so, do bounds checking and map the buffer into main memory. 4353464ebd5Sriastradh * Any errors detected will be recorded. 4363464ebd5Sriastradh * The caller _must_ call _mesa_unmap_teximage_pbo() too! 4373464ebd5Sriastradh */ 4383464ebd5Sriastradhconst GLvoid * 4393464ebd5Sriastradh_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, 440af69d88dSmrg GLuint dimensions, GLsizei imageSize, 441af69d88dSmrg const GLvoid *pixels, 4423464ebd5Sriastradh const struct gl_pixelstore_attrib *packing, 4433464ebd5Sriastradh const char *funcName) 4443464ebd5Sriastradh{ 4453464ebd5Sriastradh GLubyte *buf; 4463464ebd5Sriastradh 44701e04c3fSmrg if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing, 44801e04c3fSmrg imageSize, pixels, funcName)) { 44901e04c3fSmrg /* error is already set during validation */ 45001e04c3fSmrg return NULL; 45101e04c3fSmrg } 45201e04c3fSmrg 4533464ebd5Sriastradh if (!_mesa_is_bufferobj(packing->BufferObj)) { 4543464ebd5Sriastradh /* not using a PBO - return pointer unchanged */ 4553464ebd5Sriastradh return pixels; 4563464ebd5Sriastradh } 4573464ebd5Sriastradh 458af69d88dSmrg buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, 459af69d88dSmrg packing->BufferObj->Size, 460af69d88dSmrg GL_MAP_READ_BIT, 461af69d88dSmrg packing->BufferObj, 462af69d88dSmrg MAP_INTERNAL); 46301e04c3fSmrg 46401e04c3fSmrg /* Validation above already checked that PBO is not mapped, so buffer 46501e04c3fSmrg * should not be null. 46601e04c3fSmrg */ 46701e04c3fSmrg assert(buf); 4683464ebd5Sriastradh 4693464ebd5Sriastradh return ADD_POINTERS(buf, pixels); 4703464ebd5Sriastradh} 4713464ebd5Sriastradh 4723464ebd5Sriastradh 4733464ebd5Sriastradh/** 4743464ebd5Sriastradh * This function must be called after either of the validate_pbo_*_teximage() 4753464ebd5Sriastradh * functions. It unmaps the PBO buffer if it was mapped earlier. 4763464ebd5Sriastradh */ 4773464ebd5Sriastradhvoid 4783464ebd5Sriastradh_mesa_unmap_teximage_pbo(struct gl_context *ctx, 4793464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack) 4803464ebd5Sriastradh{ 4813464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 482af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 4833464ebd5Sriastradh } 4843464ebd5Sriastradh} 485