pbo.c revision af69d88d
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 343464ebd5Sriastradh#include "glheader.h" 353464ebd5Sriastradh#include "bufferobj.h" 36af69d88dSmrg#include "glformats.h" 373464ebd5Sriastradh#include "image.h" 383464ebd5Sriastradh#include "imports.h" 393464ebd5Sriastradh#include "mtypes.h" 403464ebd5Sriastradh#include "pbo.h" 413464ebd5Sriastradh 423464ebd5Sriastradh 433464ebd5Sriastradh 443464ebd5Sriastradh/** 453464ebd5Sriastradh * When we're about to read pixel data out of a PBO (via glDrawPixels, 463464ebd5Sriastradh * glTexImage, etc) or write data into a PBO (via glReadPixels, 473464ebd5Sriastradh * glGetTexImage, etc) we call this function to check that we're not 483464ebd5Sriastradh * going to read/write out of bounds. 493464ebd5Sriastradh * 503464ebd5Sriastradh * XXX This would also be a convenient time to check that the PBO isn't 513464ebd5Sriastradh * currently mapped. Whoever calls this function should check for that. 523464ebd5Sriastradh * Remember, we can't use a PBO when it's mapped! 533464ebd5Sriastradh * 543464ebd5Sriastradh * If we're not using a PBO, this is a no-op. 553464ebd5Sriastradh * 563464ebd5Sriastradh * \param width width of image to read/write 573464ebd5Sriastradh * \param height height of image to read/write 583464ebd5Sriastradh * \param depth depth of image to read/write 593464ebd5Sriastradh * \param format format of image to read/write 603464ebd5Sriastradh * \param type datatype of image to read/write 613464ebd5Sriastradh * \param clientMemSize the maximum number of bytes to read/write 623464ebd5Sriastradh * \param ptr the user-provided pointer/offset 633464ebd5Sriastradh * \return GL_TRUE if the buffer access is OK, GL_FALSE if the access would 643464ebd5Sriastradh * go out of bounds. 653464ebd5Sriastradh */ 663464ebd5SriastradhGLboolean 673464ebd5Sriastradh_mesa_validate_pbo_access(GLuint dimensions, 683464ebd5Sriastradh const struct gl_pixelstore_attrib *pack, 693464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 703464ebd5Sriastradh GLenum format, GLenum type, GLsizei clientMemSize, 713464ebd5Sriastradh const GLvoid *ptr) 723464ebd5Sriastradh{ 73af69d88dSmrg /* unsigned, to detect overflow/wrap-around */ 74af69d88dSmrg uintptr_t start, end, offset, size; 753464ebd5Sriastradh 763464ebd5Sriastradh /* If no PBO is bound, 'ptr' is a pointer to client memory containing 773464ebd5Sriastradh 'clientMemSize' bytes. 783464ebd5Sriastradh If a PBO is bound, 'ptr' is an offset into the bound PBO. 793464ebd5Sriastradh In that case 'clientMemSize' is ignored: we just use the PBO's size. 803464ebd5Sriastradh */ 813464ebd5Sriastradh if (!_mesa_is_bufferobj(pack->BufferObj)) { 823464ebd5Sriastradh offset = 0; 83af69d88dSmrg size = clientMemSize; 843464ebd5Sriastradh } else { 85af69d88dSmrg offset = (uintptr_t)ptr; 86af69d88dSmrg size = pack->BufferObj->Size; 873464ebd5Sriastradh /* The ARB_pixel_buffer_object spec says: 883464ebd5Sriastradh * "INVALID_OPERATION is generated by ColorTable, ColorSubTable, 893464ebd5Sriastradh * ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D, 903464ebd5Sriastradh * TexImage1D, TexImage2D, TexImage3D, TexSubImage1D, 913464ebd5Sriastradh * TexSubImage2D, TexSubImage3D, and DrawPixels if the current 923464ebd5Sriastradh * PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data 933464ebd5Sriastradh * parameter is not evenly divisible into the number of basic machine 943464ebd5Sriastradh * units needed to store in memory a datum indicated by the type 953464ebd5Sriastradh * parameter." 963464ebd5Sriastradh */ 973464ebd5Sriastradh if (type != GL_BITMAP && 98af69d88dSmrg (offset % _mesa_sizeof_packed_type(type))) 993464ebd5Sriastradh return GL_FALSE; 1003464ebd5Sriastradh } 1013464ebd5Sriastradh 102af69d88dSmrg if (size == 0) 1033464ebd5Sriastradh /* no buffer! */ 1043464ebd5Sriastradh return GL_FALSE; 1053464ebd5Sriastradh 1063464ebd5Sriastradh /* get the offset to the first pixel we'll read/write */ 107af69d88dSmrg start = _mesa_image_offset(dimensions, pack, width, height, 108af69d88dSmrg format, type, 0, 0, 0); 1093464ebd5Sriastradh 1103464ebd5Sriastradh /* get the offset to just past the last pixel we'll read/write */ 111af69d88dSmrg end = _mesa_image_offset(dimensions, pack, width, height, 112af69d88dSmrg format, type, depth-1, height-1, width); 1133464ebd5Sriastradh 114af69d88dSmrg start += offset; 115af69d88dSmrg end += offset; 116af69d88dSmrg 117af69d88dSmrg if (start > size) { 1183464ebd5Sriastradh /* This will catch negative values / wrap-around */ 1193464ebd5Sriastradh return GL_FALSE; 1203464ebd5Sriastradh } 121af69d88dSmrg if (end > size) { 1223464ebd5Sriastradh /* Image read/write goes beyond end of buffer */ 1233464ebd5Sriastradh return GL_FALSE; 1243464ebd5Sriastradh } 1253464ebd5Sriastradh 1263464ebd5Sriastradh /* OK! */ 1273464ebd5Sriastradh return GL_TRUE; 1283464ebd5Sriastradh} 1293464ebd5Sriastradh 1303464ebd5Sriastradh 1313464ebd5Sriastradh/** 1323464ebd5Sriastradh * For commands that read from a PBO (glDrawPixels, glTexImage, 1333464ebd5Sriastradh * glPolygonStipple, etc), if we're reading from a PBO, map it read-only 1343464ebd5Sriastradh * and return the pointer into the PBO. If we're not reading from a 1353464ebd5Sriastradh * PBO, return \p src as-is. 1363464ebd5Sriastradh * If non-null return, must call _mesa_unmap_pbo_source() when done. 1373464ebd5Sriastradh * 1383464ebd5Sriastradh * \return NULL if error, else pointer to start of data 1393464ebd5Sriastradh */ 1403464ebd5Sriastradhconst GLvoid * 1413464ebd5Sriastradh_mesa_map_pbo_source(struct gl_context *ctx, 1423464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack, 1433464ebd5Sriastradh const GLvoid *src) 1443464ebd5Sriastradh{ 1453464ebd5Sriastradh const GLubyte *buf; 1463464ebd5Sriastradh 1473464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 1483464ebd5Sriastradh /* unpack from PBO */ 149af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 150af69d88dSmrg unpack->BufferObj->Size, 151af69d88dSmrg GL_MAP_READ_BIT, 152af69d88dSmrg unpack->BufferObj, 153af69d88dSmrg MAP_INTERNAL); 1543464ebd5Sriastradh if (!buf) 1553464ebd5Sriastradh return NULL; 1563464ebd5Sriastradh 1573464ebd5Sriastradh buf = ADD_POINTERS(buf, src); 1583464ebd5Sriastradh } 1593464ebd5Sriastradh else { 1603464ebd5Sriastradh /* unpack from normal memory */ 1613464ebd5Sriastradh buf = src; 1623464ebd5Sriastradh } 1633464ebd5Sriastradh 1643464ebd5Sriastradh return buf; 1653464ebd5Sriastradh} 1663464ebd5Sriastradh 1673464ebd5Sriastradh 1683464ebd5Sriastradh/** 1693464ebd5Sriastradh * Combine PBO-read validation and mapping. 1703464ebd5Sriastradh * If any GL errors are detected, they'll be recorded and NULL returned. 1713464ebd5Sriastradh * \sa _mesa_validate_pbo_access 1723464ebd5Sriastradh * \sa _mesa_map_pbo_source 1733464ebd5Sriastradh * A call to this function should have a matching call to 1743464ebd5Sriastradh * _mesa_unmap_pbo_source(). 1753464ebd5Sriastradh */ 1763464ebd5Sriastradhconst GLvoid * 1773464ebd5Sriastradh_mesa_map_validate_pbo_source(struct gl_context *ctx, 178af69d88dSmrg GLuint dimensions, 179af69d88dSmrg const struct gl_pixelstore_attrib *unpack, 180af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 181af69d88dSmrg GLenum format, GLenum type, 182af69d88dSmrg GLsizei clientMemSize, 183af69d88dSmrg const GLvoid *ptr, const char *where) 1843464ebd5Sriastradh{ 1853464ebd5Sriastradh ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); 1863464ebd5Sriastradh 1873464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 1883464ebd5Sriastradh format, type, clientMemSize, ptr)) { 1893464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 1903464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 1913464ebd5Sriastradh "%s(out of bounds PBO access)", where); 1923464ebd5Sriastradh } else { 1933464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 1943464ebd5Sriastradh "%s(out of bounds access: bufSize (%d) is too small)", 1953464ebd5Sriastradh where, clientMemSize); 1963464ebd5Sriastradh } 1973464ebd5Sriastradh return NULL; 1983464ebd5Sriastradh } 1993464ebd5Sriastradh 2003464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 2013464ebd5Sriastradh /* non-PBO access: no further validation to be done */ 2023464ebd5Sriastradh return ptr; 2033464ebd5Sriastradh } 2043464ebd5Sriastradh 205af69d88dSmrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 2063464ebd5Sriastradh /* buffer is already mapped - that's an error */ 2073464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); 2083464ebd5Sriastradh return NULL; 2093464ebd5Sriastradh } 2103464ebd5Sriastradh 2113464ebd5Sriastradh ptr = _mesa_map_pbo_source(ctx, unpack, ptr); 2123464ebd5Sriastradh return ptr; 2133464ebd5Sriastradh} 2143464ebd5Sriastradh 2153464ebd5Sriastradh 2163464ebd5Sriastradh/** 2173464ebd5Sriastradh * Counterpart to _mesa_map_pbo_source() 2183464ebd5Sriastradh */ 2193464ebd5Sriastradhvoid 2203464ebd5Sriastradh_mesa_unmap_pbo_source(struct gl_context *ctx, 2213464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack) 2223464ebd5Sriastradh{ 2233464ebd5Sriastradh ASSERT(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ 2243464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 225af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 2263464ebd5Sriastradh } 2273464ebd5Sriastradh} 2283464ebd5Sriastradh 2293464ebd5Sriastradh 2303464ebd5Sriastradh/** 2313464ebd5Sriastradh * For commands that write to a PBO (glReadPixels, glGetColorTable, etc), 2323464ebd5Sriastradh * if we're writing to a PBO, map it write-only and return the pointer 2333464ebd5Sriastradh * into the PBO. If we're not writing to a PBO, return \p dst as-is. 2343464ebd5Sriastradh * If non-null return, must call _mesa_unmap_pbo_dest() when done. 2353464ebd5Sriastradh * 2363464ebd5Sriastradh * \return NULL if error, else pointer to start of data 2373464ebd5Sriastradh */ 2383464ebd5Sriastradhvoid * 2393464ebd5Sriastradh_mesa_map_pbo_dest(struct gl_context *ctx, 2403464ebd5Sriastradh const struct gl_pixelstore_attrib *pack, 2413464ebd5Sriastradh GLvoid *dest) 2423464ebd5Sriastradh{ 2433464ebd5Sriastradh void *buf; 2443464ebd5Sriastradh 2453464ebd5Sriastradh if (_mesa_is_bufferobj(pack->BufferObj)) { 2463464ebd5Sriastradh /* pack into PBO */ 247af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 248af69d88dSmrg pack->BufferObj->Size, 249af69d88dSmrg GL_MAP_WRITE_BIT, 250af69d88dSmrg pack->BufferObj, 251af69d88dSmrg MAP_INTERNAL); 2523464ebd5Sriastradh if (!buf) 2533464ebd5Sriastradh return NULL; 2543464ebd5Sriastradh 2553464ebd5Sriastradh buf = ADD_POINTERS(buf, dest); 2563464ebd5Sriastradh } 2573464ebd5Sriastradh else { 2583464ebd5Sriastradh /* pack to normal memory */ 2593464ebd5Sriastradh buf = dest; 2603464ebd5Sriastradh } 2613464ebd5Sriastradh 2623464ebd5Sriastradh return buf; 2633464ebd5Sriastradh} 2643464ebd5Sriastradh 2653464ebd5Sriastradh 2663464ebd5Sriastradh/** 2673464ebd5Sriastradh * Combine PBO-write validation and mapping. 2683464ebd5Sriastradh * If any GL errors are detected, they'll be recorded and NULL returned. 2693464ebd5Sriastradh * \sa _mesa_validate_pbo_access 2703464ebd5Sriastradh * \sa _mesa_map_pbo_dest 2713464ebd5Sriastradh * A call to this function should have a matching call to 2723464ebd5Sriastradh * _mesa_unmap_pbo_dest(). 2733464ebd5Sriastradh */ 2743464ebd5SriastradhGLvoid * 2753464ebd5Sriastradh_mesa_map_validate_pbo_dest(struct gl_context *ctx, 276af69d88dSmrg GLuint dimensions, 277af69d88dSmrg const struct gl_pixelstore_attrib *unpack, 278af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 279af69d88dSmrg GLenum format, GLenum type, GLsizei clientMemSize, 280af69d88dSmrg GLvoid *ptr, const char *where) 2813464ebd5Sriastradh{ 2823464ebd5Sriastradh ASSERT(dimensions == 1 || dimensions == 2 || dimensions == 3); 2833464ebd5Sriastradh 2843464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 2853464ebd5Sriastradh format, type, clientMemSize, ptr)) { 2863464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 2873464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 2883464ebd5Sriastradh "%s(out of bounds PBO access)", where); 2893464ebd5Sriastradh } else { 2903464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, 2913464ebd5Sriastradh "%s(out of bounds access: bufSize (%d) is too small)", 2923464ebd5Sriastradh where, clientMemSize); 2933464ebd5Sriastradh } 2943464ebd5Sriastradh return NULL; 2953464ebd5Sriastradh } 2963464ebd5Sriastradh 2973464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 2983464ebd5Sriastradh /* non-PBO access: no further validation to be done */ 2993464ebd5Sriastradh return ptr; 3003464ebd5Sriastradh } 3013464ebd5Sriastradh 302af69d88dSmrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 3033464ebd5Sriastradh /* buffer is already mapped - that's an error */ 3043464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); 3053464ebd5Sriastradh return NULL; 3063464ebd5Sriastradh } 3073464ebd5Sriastradh 3083464ebd5Sriastradh ptr = _mesa_map_pbo_dest(ctx, unpack, ptr); 3093464ebd5Sriastradh return ptr; 3103464ebd5Sriastradh} 3113464ebd5Sriastradh 3123464ebd5Sriastradh 3133464ebd5Sriastradh/** 3143464ebd5Sriastradh * Counterpart to _mesa_map_pbo_dest() 3153464ebd5Sriastradh */ 3163464ebd5Sriastradhvoid 3173464ebd5Sriastradh_mesa_unmap_pbo_dest(struct gl_context *ctx, 3183464ebd5Sriastradh const struct gl_pixelstore_attrib *pack) 3193464ebd5Sriastradh{ 3203464ebd5Sriastradh ASSERT(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ 3213464ebd5Sriastradh if (_mesa_is_bufferobj(pack->BufferObj)) { 322af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); 3233464ebd5Sriastradh } 3243464ebd5Sriastradh} 3253464ebd5Sriastradh 3263464ebd5Sriastradh 3273464ebd5Sriastradh/** 3283464ebd5Sriastradh * Check if an unpack PBO is active prior to fetching a texture image. 3293464ebd5Sriastradh * If so, do bounds checking and map the buffer into main memory. 3303464ebd5Sriastradh * Any errors detected will be recorded. 3313464ebd5Sriastradh * The caller _must_ call _mesa_unmap_teximage_pbo() too! 3323464ebd5Sriastradh */ 3333464ebd5Sriastradhconst GLvoid * 3343464ebd5Sriastradh_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, 3353464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 3363464ebd5Sriastradh GLenum format, GLenum type, const GLvoid *pixels, 3373464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack, 3383464ebd5Sriastradh const char *funcName) 3393464ebd5Sriastradh{ 3403464ebd5Sriastradh GLubyte *buf; 3413464ebd5Sriastradh 3423464ebd5Sriastradh if (!_mesa_is_bufferobj(unpack->BufferObj)) { 3433464ebd5Sriastradh /* no PBO */ 3443464ebd5Sriastradh return pixels; 3453464ebd5Sriastradh } 3463464ebd5Sriastradh if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 347af69d88dSmrg format, type, INT_MAX, pixels)) { 348af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", 349af69d88dSmrg funcName, dimensions); 3503464ebd5Sriastradh return NULL; 3513464ebd5Sriastradh } 3523464ebd5Sriastradh 353af69d88dSmrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 354af69d88dSmrg unpack->BufferObj->Size, 355af69d88dSmrg GL_MAP_READ_BIT, 356af69d88dSmrg unpack->BufferObj, 357af69d88dSmrg MAP_INTERNAL); 3583464ebd5Sriastradh if (!buf) { 359af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, 360af69d88dSmrg dimensions); 3613464ebd5Sriastradh return NULL; 3623464ebd5Sriastradh } 3633464ebd5Sriastradh 3643464ebd5Sriastradh return ADD_POINTERS(buf, pixels); 3653464ebd5Sriastradh} 3663464ebd5Sriastradh 3673464ebd5Sriastradh 3683464ebd5Sriastradh/** 3693464ebd5Sriastradh * Check if an unpack PBO is active prior to fetching a compressed texture 3703464ebd5Sriastradh * image. 3713464ebd5Sriastradh * If so, do bounds checking and map the buffer into main memory. 3723464ebd5Sriastradh * Any errors detected will be recorded. 3733464ebd5Sriastradh * The caller _must_ call _mesa_unmap_teximage_pbo() too! 3743464ebd5Sriastradh */ 3753464ebd5Sriastradhconst GLvoid * 3763464ebd5Sriastradh_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, 377af69d88dSmrg GLuint dimensions, GLsizei imageSize, 378af69d88dSmrg const GLvoid *pixels, 3793464ebd5Sriastradh const struct gl_pixelstore_attrib *packing, 3803464ebd5Sriastradh const char *funcName) 3813464ebd5Sriastradh{ 3823464ebd5Sriastradh GLubyte *buf; 3833464ebd5Sriastradh 3843464ebd5Sriastradh if (!_mesa_is_bufferobj(packing->BufferObj)) { 3853464ebd5Sriastradh /* not using a PBO - return pointer unchanged */ 3863464ebd5Sriastradh return pixels; 3873464ebd5Sriastradh } 3883464ebd5Sriastradh if ((const GLubyte *) pixels + imageSize > 3893464ebd5Sriastradh ((const GLubyte *) 0) + packing->BufferObj->Size) { 3903464ebd5Sriastradh /* out of bounds read! */ 391af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", 392af69d88dSmrg funcName, dimensions); 3933464ebd5Sriastradh return NULL; 3943464ebd5Sriastradh } 3953464ebd5Sriastradh 396af69d88dSmrg buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, 397af69d88dSmrg packing->BufferObj->Size, 398af69d88dSmrg GL_MAP_READ_BIT, 399af69d88dSmrg packing->BufferObj, 400af69d88dSmrg MAP_INTERNAL); 4013464ebd5Sriastradh if (!buf) { 402af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, 403af69d88dSmrg dimensions); 4043464ebd5Sriastradh return NULL; 4053464ebd5Sriastradh } 4063464ebd5Sriastradh 4073464ebd5Sriastradh return ADD_POINTERS(buf, pixels); 4083464ebd5Sriastradh} 4093464ebd5Sriastradh 4103464ebd5Sriastradh 4113464ebd5Sriastradh/** 4123464ebd5Sriastradh * This function must be called after either of the validate_pbo_*_teximage() 4133464ebd5Sriastradh * functions. It unmaps the PBO buffer if it was mapped earlier. 4143464ebd5Sriastradh */ 4153464ebd5Sriastradhvoid 4163464ebd5Sriastradh_mesa_unmap_teximage_pbo(struct gl_context *ctx, 4173464ebd5Sriastradh const struct gl_pixelstore_attrib *unpack) 4183464ebd5Sriastradh{ 4193464ebd5Sriastradh if (_mesa_is_bufferobj(unpack->BufferObj)) { 420af69d88dSmrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 4213464ebd5Sriastradh } 4223464ebd5Sriastradh} 423