1848b8605Smrg/* 2848b8605Smrg * Mesa 3-D graphics library 3848b8605Smrg * 4848b8605Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 5848b8605Smrg * Copyright (C) 2009-2011 VMware, Inc. All Rights Reserved. 6848b8605Smrg * 7848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 8848b8605Smrg * copy of this software and associated documentation files (the "Software"), 9848b8605Smrg * to deal in the Software without restriction, including without limitation 10848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 12848b8605Smrg * Software is furnished to do so, subject to the following conditions: 13848b8605Smrg * 14848b8605Smrg * The above copyright notice and this permission notice shall be included 15848b8605Smrg * in all copies or substantial portions of the Software. 16848b8605Smrg * 17848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE. 24848b8605Smrg */ 25848b8605Smrg 26848b8605Smrg 27848b8605Smrg/** 28848b8605Smrg * \file pbo.c 29848b8605Smrg * \brief Functions related to Pixel Buffer Objects. 30848b8605Smrg */ 31848b8605Smrg 32848b8605Smrg 33848b8605Smrg 34b8e80941Smrg#include "errors.h" 35848b8605Smrg#include "glheader.h" 36848b8605Smrg#include "bufferobj.h" 37848b8605Smrg#include "glformats.h" 38848b8605Smrg#include "image.h" 39848b8605Smrg#include "imports.h" 40848b8605Smrg#include "mtypes.h" 41848b8605Smrg#include "pbo.h" 42848b8605Smrg 43848b8605Smrg 44848b8605Smrg 45848b8605Smrg/** 46848b8605Smrg * When we're about to read pixel data out of a PBO (via glDrawPixels, 47848b8605Smrg * glTexImage, etc) or write data into a PBO (via glReadPixels, 48848b8605Smrg * glGetTexImage, etc) we call this function to check that we're not 49848b8605Smrg * going to read/write out of bounds. 50848b8605Smrg * 51848b8605Smrg * XXX This would also be a convenient time to check that the PBO isn't 52848b8605Smrg * currently mapped. Whoever calls this function should check for that. 53848b8605Smrg * Remember, we can't use a PBO when it's mapped! 54848b8605Smrg * 55848b8605Smrg * If we're not using a PBO, this is a no-op. 56848b8605Smrg * 57848b8605Smrg * \param width width of image to read/write 58848b8605Smrg * \param height height of image to read/write 59848b8605Smrg * \param depth depth of image to read/write 60848b8605Smrg * \param format format of image to read/write 61848b8605Smrg * \param type datatype of image to read/write 62848b8605Smrg * \param clientMemSize the maximum number of bytes to read/write 63848b8605Smrg * \param ptr the user-provided pointer/offset 64848b8605Smrg * \return GL_TRUE if the buffer access is OK, GL_FALSE if the access would 65848b8605Smrg * go out of bounds. 66848b8605Smrg */ 67848b8605SmrgGLboolean 68848b8605Smrg_mesa_validate_pbo_access(GLuint dimensions, 69848b8605Smrg const struct gl_pixelstore_attrib *pack, 70848b8605Smrg GLsizei width, GLsizei height, GLsizei depth, 71848b8605Smrg GLenum format, GLenum type, GLsizei clientMemSize, 72848b8605Smrg const GLvoid *ptr) 73848b8605Smrg{ 74848b8605Smrg /* unsigned, to detect overflow/wrap-around */ 75848b8605Smrg uintptr_t start, end, offset, size; 76848b8605Smrg 77848b8605Smrg /* If no PBO is bound, 'ptr' is a pointer to client memory containing 78848b8605Smrg 'clientMemSize' bytes. 79848b8605Smrg If a PBO is bound, 'ptr' is an offset into the bound PBO. 80848b8605Smrg In that case 'clientMemSize' is ignored: we just use the PBO's size. 81848b8605Smrg */ 82848b8605Smrg if (!_mesa_is_bufferobj(pack->BufferObj)) { 83848b8605Smrg offset = 0; 84b8e80941Smrg size = (clientMemSize == INT_MAX) ? UINTPTR_MAX : clientMemSize; 85848b8605Smrg } else { 86848b8605Smrg offset = (uintptr_t)ptr; 87848b8605Smrg size = pack->BufferObj->Size; 88848b8605Smrg /* The ARB_pixel_buffer_object spec says: 89848b8605Smrg * "INVALID_OPERATION is generated by ColorTable, ColorSubTable, 90848b8605Smrg * ConvolutionFilter2D, ConvolutionFilter1D, SeparableFilter2D, 91848b8605Smrg * TexImage1D, TexImage2D, TexImage3D, TexSubImage1D, 92848b8605Smrg * TexSubImage2D, TexSubImage3D, and DrawPixels if the current 93848b8605Smrg * PIXEL_UNPACK_BUFFER_BINDING_ARB value is non-zero and the data 94848b8605Smrg * parameter is not evenly divisible into the number of basic machine 95848b8605Smrg * units needed to store in memory a datum indicated by the type 96848b8605Smrg * parameter." 97848b8605Smrg */ 98848b8605Smrg if (type != GL_BITMAP && 99848b8605Smrg (offset % _mesa_sizeof_packed_type(type))) 100848b8605Smrg return GL_FALSE; 101848b8605Smrg } 102848b8605Smrg 103848b8605Smrg if (size == 0) 104848b8605Smrg /* no buffer! */ 105848b8605Smrg return GL_FALSE; 106848b8605Smrg 107b8e80941Smrg /* If the size of the image is zero then no pixels are accessed so we 108b8e80941Smrg * don't need to check anything else. 109b8e80941Smrg */ 110b8e80941Smrg if (width == 0 || height == 0 || depth == 0) 111b8e80941Smrg return GL_TRUE; 112b8e80941Smrg 113848b8605Smrg /* get the offset to the first pixel we'll read/write */ 114848b8605Smrg start = _mesa_image_offset(dimensions, pack, width, height, 115848b8605Smrg format, type, 0, 0, 0); 116848b8605Smrg 117848b8605Smrg /* get the offset to just past the last pixel we'll read/write */ 118848b8605Smrg end = _mesa_image_offset(dimensions, pack, width, height, 119848b8605Smrg format, type, depth-1, height-1, width); 120848b8605Smrg 121848b8605Smrg start += offset; 122848b8605Smrg end += offset; 123848b8605Smrg 124848b8605Smrg if (start > size) { 125848b8605Smrg /* This will catch negative values / wrap-around */ 126848b8605Smrg return GL_FALSE; 127848b8605Smrg } 128848b8605Smrg if (end > size) { 129848b8605Smrg /* Image read/write goes beyond end of buffer */ 130848b8605Smrg return GL_FALSE; 131848b8605Smrg } 132848b8605Smrg 133848b8605Smrg /* OK! */ 134848b8605Smrg return GL_TRUE; 135848b8605Smrg} 136848b8605Smrg 137848b8605Smrg 138848b8605Smrg/** 139848b8605Smrg * For commands that read from a PBO (glDrawPixels, glTexImage, 140848b8605Smrg * glPolygonStipple, etc), if we're reading from a PBO, map it read-only 141848b8605Smrg * and return the pointer into the PBO. If we're not reading from a 142848b8605Smrg * PBO, return \p src as-is. 143848b8605Smrg * If non-null return, must call _mesa_unmap_pbo_source() when done. 144848b8605Smrg * 145848b8605Smrg * \return NULL if error, else pointer to start of data 146848b8605Smrg */ 147848b8605Smrgconst GLvoid * 148848b8605Smrg_mesa_map_pbo_source(struct gl_context *ctx, 149848b8605Smrg const struct gl_pixelstore_attrib *unpack, 150848b8605Smrg const GLvoid *src) 151848b8605Smrg{ 152848b8605Smrg const GLubyte *buf; 153848b8605Smrg 154848b8605Smrg if (_mesa_is_bufferobj(unpack->BufferObj)) { 155848b8605Smrg /* unpack from PBO */ 156848b8605Smrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 157848b8605Smrg unpack->BufferObj->Size, 158848b8605Smrg GL_MAP_READ_BIT, 159848b8605Smrg unpack->BufferObj, 160848b8605Smrg MAP_INTERNAL); 161848b8605Smrg if (!buf) 162848b8605Smrg return NULL; 163848b8605Smrg 164848b8605Smrg buf = ADD_POINTERS(buf, src); 165848b8605Smrg } 166848b8605Smrg else { 167848b8605Smrg /* unpack from normal memory */ 168848b8605Smrg buf = src; 169848b8605Smrg } 170848b8605Smrg 171848b8605Smrg return buf; 172848b8605Smrg} 173848b8605Smrg 174848b8605Smrg/** 175b8e80941Smrg * Perform PBO validation for read operations with uncompressed textures. 176b8e80941Smrg * If any GL errors are detected, false is returned, otherwise returns true. 177848b8605Smrg * \sa _mesa_validate_pbo_access 178848b8605Smrg */ 179b8e80941Smrgbool 180b8e80941Smrg_mesa_validate_pbo_source(struct gl_context *ctx, GLuint dimensions, 181b8e80941Smrg const struct gl_pixelstore_attrib *unpack, 182b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 183b8e80941Smrg GLenum format, GLenum type, 184b8e80941Smrg GLsizei clientMemSize, 185b8e80941Smrg const GLvoid *ptr, const char *where) 186848b8605Smrg{ 187b8e80941Smrg assert(dimensions == 1 || dimensions == 2 || dimensions == 3); 188848b8605Smrg 189848b8605Smrg if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 190848b8605Smrg format, type, clientMemSize, ptr)) { 191848b8605Smrg if (_mesa_is_bufferobj(unpack->BufferObj)) { 192848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 193b8e80941Smrg "%s(out of bounds PBO access)", 194b8e80941Smrg where); 195848b8605Smrg } else { 196848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 197848b8605Smrg "%s(out of bounds access: bufSize (%d) is too small)", 198848b8605Smrg where, clientMemSize); 199848b8605Smrg } 200b8e80941Smrg return false; 201848b8605Smrg } 202848b8605Smrg 203848b8605Smrg if (!_mesa_is_bufferobj(unpack->BufferObj)) { 204848b8605Smrg /* non-PBO access: no further validation to be done */ 205b8e80941Smrg return true; 206848b8605Smrg } 207848b8605Smrg 208848b8605Smrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 209848b8605Smrg /* buffer is already mapped - that's an error */ 210b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", 211b8e80941Smrg where); 212b8e80941Smrg return false; 213b8e80941Smrg } 214b8e80941Smrg 215b8e80941Smrg return true; 216b8e80941Smrg} 217b8e80941Smrg 218b8e80941Smrg/** 219b8e80941Smrg * Perform PBO validation for read operations with compressed textures. 220b8e80941Smrg * If any GL errors are detected, false is returned, otherwise returns true. 221b8e80941Smrg */ 222b8e80941Smrgbool 223b8e80941Smrg_mesa_validate_pbo_source_compressed(struct gl_context *ctx, GLuint dimensions, 224b8e80941Smrg const struct gl_pixelstore_attrib *unpack, 225b8e80941Smrg GLsizei imageSize, const GLvoid *pixels, 226b8e80941Smrg const char *where) 227b8e80941Smrg{ 228b8e80941Smrg if (!_mesa_is_bufferobj(unpack->BufferObj)) { 229b8e80941Smrg /* not using a PBO */ 230b8e80941Smrg return true; 231b8e80941Smrg } 232b8e80941Smrg 233b8e80941Smrg if ((const GLubyte *) pixels + imageSize > 234b8e80941Smrg ((const GLubyte *) 0) + unpack->BufferObj->Size) { 235b8e80941Smrg /* out of bounds read! */ 236b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid PBO access)", 237b8e80941Smrg where); 238b8e80941Smrg return false; 239b8e80941Smrg } 240b8e80941Smrg 241b8e80941Smrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 242b8e80941Smrg /* buffer is already mapped - that's an error */ 243b8e80941Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", 244b8e80941Smrg where); 245b8e80941Smrg return false; 246b8e80941Smrg } 247b8e80941Smrg 248b8e80941Smrg return true; 249b8e80941Smrg} 250b8e80941Smrg 251b8e80941Smrg/** 252b8e80941Smrg * Perform PBO-read mapping. 253b8e80941Smrg * If any GL errors are detected, they'll be recorded and NULL returned. 254b8e80941Smrg * \sa _mesa_validate_pbo_source 255b8e80941Smrg * \sa _mesa_map_pbo_source 256b8e80941Smrg * A call to this function should have a matching call to 257b8e80941Smrg * _mesa_unmap_pbo_source(). 258b8e80941Smrg */ 259b8e80941Smrgconst GLvoid * 260b8e80941Smrg_mesa_map_validate_pbo_source(struct gl_context *ctx, 261b8e80941Smrg GLuint dimensions, 262b8e80941Smrg const struct gl_pixelstore_attrib *unpack, 263b8e80941Smrg GLsizei width, GLsizei height, GLsizei depth, 264b8e80941Smrg GLenum format, GLenum type, 265b8e80941Smrg GLsizei clientMemSize, 266b8e80941Smrg const GLvoid *ptr, const char *where) 267b8e80941Smrg{ 268b8e80941Smrg if (!_mesa_validate_pbo_source(ctx, dimensions, unpack, 269b8e80941Smrg width, height, depth, format, type, 270b8e80941Smrg clientMemSize, ptr, where)) { 271b8e80941Smrg return NULL; 272848b8605Smrg } 273848b8605Smrg 274848b8605Smrg ptr = _mesa_map_pbo_source(ctx, unpack, ptr); 275848b8605Smrg return ptr; 276848b8605Smrg} 277848b8605Smrg 278848b8605Smrg 279848b8605Smrg/** 280848b8605Smrg * Counterpart to _mesa_map_pbo_source() 281848b8605Smrg */ 282848b8605Smrgvoid 283848b8605Smrg_mesa_unmap_pbo_source(struct gl_context *ctx, 284848b8605Smrg const struct gl_pixelstore_attrib *unpack) 285848b8605Smrg{ 286b8e80941Smrg assert(unpack != &ctx->Pack); /* catch pack/unpack mismatch */ 287848b8605Smrg if (_mesa_is_bufferobj(unpack->BufferObj)) { 288848b8605Smrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 289848b8605Smrg } 290848b8605Smrg} 291848b8605Smrg 292848b8605Smrg 293848b8605Smrg/** 294848b8605Smrg * For commands that write to a PBO (glReadPixels, glGetColorTable, etc), 295848b8605Smrg * if we're writing to a PBO, map it write-only and return the pointer 296848b8605Smrg * into the PBO. If we're not writing to a PBO, return \p dst as-is. 297848b8605Smrg * If non-null return, must call _mesa_unmap_pbo_dest() when done. 298848b8605Smrg * 299848b8605Smrg * \return NULL if error, else pointer to start of data 300848b8605Smrg */ 301848b8605Smrgvoid * 302848b8605Smrg_mesa_map_pbo_dest(struct gl_context *ctx, 303848b8605Smrg const struct gl_pixelstore_attrib *pack, 304848b8605Smrg GLvoid *dest) 305848b8605Smrg{ 306848b8605Smrg void *buf; 307848b8605Smrg 308848b8605Smrg if (_mesa_is_bufferobj(pack->BufferObj)) { 309848b8605Smrg /* pack into PBO */ 310848b8605Smrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 311848b8605Smrg pack->BufferObj->Size, 312848b8605Smrg GL_MAP_WRITE_BIT, 313848b8605Smrg pack->BufferObj, 314848b8605Smrg MAP_INTERNAL); 315848b8605Smrg if (!buf) 316848b8605Smrg return NULL; 317848b8605Smrg 318848b8605Smrg buf = ADD_POINTERS(buf, dest); 319848b8605Smrg } 320848b8605Smrg else { 321848b8605Smrg /* pack to normal memory */ 322848b8605Smrg buf = dest; 323848b8605Smrg } 324848b8605Smrg 325848b8605Smrg return buf; 326848b8605Smrg} 327848b8605Smrg 328848b8605Smrg 329848b8605Smrg/** 330848b8605Smrg * Combine PBO-write validation and mapping. 331848b8605Smrg * If any GL errors are detected, they'll be recorded and NULL returned. 332848b8605Smrg * \sa _mesa_validate_pbo_access 333848b8605Smrg * \sa _mesa_map_pbo_dest 334848b8605Smrg * A call to this function should have a matching call to 335848b8605Smrg * _mesa_unmap_pbo_dest(). 336848b8605Smrg */ 337848b8605SmrgGLvoid * 338848b8605Smrg_mesa_map_validate_pbo_dest(struct gl_context *ctx, 339848b8605Smrg GLuint dimensions, 340848b8605Smrg const struct gl_pixelstore_attrib *unpack, 341848b8605Smrg GLsizei width, GLsizei height, GLsizei depth, 342848b8605Smrg GLenum format, GLenum type, GLsizei clientMemSize, 343848b8605Smrg GLvoid *ptr, const char *where) 344848b8605Smrg{ 345b8e80941Smrg assert(dimensions == 1 || dimensions == 2 || dimensions == 3); 346848b8605Smrg 347848b8605Smrg if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 348848b8605Smrg format, type, clientMemSize, ptr)) { 349848b8605Smrg if (_mesa_is_bufferobj(unpack->BufferObj)) { 350848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 351848b8605Smrg "%s(out of bounds PBO access)", where); 352848b8605Smrg } else { 353848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 354848b8605Smrg "%s(out of bounds access: bufSize (%d) is too small)", 355848b8605Smrg where, clientMemSize); 356848b8605Smrg } 357848b8605Smrg return NULL; 358848b8605Smrg } 359848b8605Smrg 360848b8605Smrg if (!_mesa_is_bufferobj(unpack->BufferObj)) { 361848b8605Smrg /* non-PBO access: no further validation to be done */ 362848b8605Smrg return ptr; 363848b8605Smrg } 364848b8605Smrg 365848b8605Smrg if (_mesa_check_disallowed_mapping(unpack->BufferObj)) { 366848b8605Smrg /* buffer is already mapped - that's an error */ 367848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(PBO is mapped)", where); 368848b8605Smrg return NULL; 369848b8605Smrg } 370848b8605Smrg 371848b8605Smrg ptr = _mesa_map_pbo_dest(ctx, unpack, ptr); 372848b8605Smrg return ptr; 373848b8605Smrg} 374848b8605Smrg 375848b8605Smrg 376848b8605Smrg/** 377848b8605Smrg * Counterpart to _mesa_map_pbo_dest() 378848b8605Smrg */ 379848b8605Smrgvoid 380848b8605Smrg_mesa_unmap_pbo_dest(struct gl_context *ctx, 381848b8605Smrg const struct gl_pixelstore_attrib *pack) 382848b8605Smrg{ 383b8e80941Smrg assert(pack != &ctx->Unpack); /* catch pack/unpack mismatch */ 384848b8605Smrg if (_mesa_is_bufferobj(pack->BufferObj)) { 385848b8605Smrg ctx->Driver.UnmapBuffer(ctx, pack->BufferObj, MAP_INTERNAL); 386848b8605Smrg } 387848b8605Smrg} 388848b8605Smrg 389848b8605Smrg 390848b8605Smrg/** 391848b8605Smrg * Check if an unpack PBO is active prior to fetching a texture image. 392848b8605Smrg * If so, do bounds checking and map the buffer into main memory. 393848b8605Smrg * Any errors detected will be recorded. 394848b8605Smrg * The caller _must_ call _mesa_unmap_teximage_pbo() too! 395848b8605Smrg */ 396848b8605Smrgconst GLvoid * 397848b8605Smrg_mesa_validate_pbo_teximage(struct gl_context *ctx, GLuint dimensions, 398848b8605Smrg GLsizei width, GLsizei height, GLsizei depth, 399848b8605Smrg GLenum format, GLenum type, const GLvoid *pixels, 400848b8605Smrg const struct gl_pixelstore_attrib *unpack, 401848b8605Smrg const char *funcName) 402848b8605Smrg{ 403848b8605Smrg GLubyte *buf; 404848b8605Smrg 405848b8605Smrg if (!_mesa_is_bufferobj(unpack->BufferObj)) { 406848b8605Smrg /* no PBO */ 407848b8605Smrg return pixels; 408848b8605Smrg } 409848b8605Smrg if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth, 410848b8605Smrg format, type, INT_MAX, pixels)) { 411848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(invalid PBO access)", 412848b8605Smrg funcName, dimensions); 413848b8605Smrg return NULL; 414848b8605Smrg } 415848b8605Smrg 416848b8605Smrg buf = (GLubyte *) ctx->Driver.MapBufferRange(ctx, 0, 417848b8605Smrg unpack->BufferObj->Size, 418848b8605Smrg GL_MAP_READ_BIT, 419848b8605Smrg unpack->BufferObj, 420848b8605Smrg MAP_INTERNAL); 421848b8605Smrg if (!buf) { 422848b8605Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s%uD(PBO is mapped)", funcName, 423848b8605Smrg dimensions); 424848b8605Smrg return NULL; 425848b8605Smrg } 426848b8605Smrg 427848b8605Smrg return ADD_POINTERS(buf, pixels); 428848b8605Smrg} 429848b8605Smrg 430848b8605Smrg 431848b8605Smrg/** 432848b8605Smrg * Check if an unpack PBO is active prior to fetching a compressed texture 433848b8605Smrg * image. 434848b8605Smrg * If so, do bounds checking and map the buffer into main memory. 435848b8605Smrg * Any errors detected will be recorded. 436848b8605Smrg * The caller _must_ call _mesa_unmap_teximage_pbo() too! 437848b8605Smrg */ 438848b8605Smrgconst GLvoid * 439848b8605Smrg_mesa_validate_pbo_compressed_teximage(struct gl_context *ctx, 440848b8605Smrg GLuint dimensions, GLsizei imageSize, 441848b8605Smrg const GLvoid *pixels, 442848b8605Smrg const struct gl_pixelstore_attrib *packing, 443848b8605Smrg const char *funcName) 444848b8605Smrg{ 445848b8605Smrg GLubyte *buf; 446848b8605Smrg 447b8e80941Smrg if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, packing, 448b8e80941Smrg imageSize, pixels, funcName)) { 449b8e80941Smrg /* error is already set during validation */ 450b8e80941Smrg return NULL; 451b8e80941Smrg } 452b8e80941Smrg 453848b8605Smrg if (!_mesa_is_bufferobj(packing->BufferObj)) { 454848b8605Smrg /* not using a PBO - return pointer unchanged */ 455848b8605Smrg return pixels; 456848b8605Smrg } 457848b8605Smrg 458848b8605Smrg buf = (GLubyte*) ctx->Driver.MapBufferRange(ctx, 0, 459848b8605Smrg packing->BufferObj->Size, 460848b8605Smrg GL_MAP_READ_BIT, 461848b8605Smrg packing->BufferObj, 462848b8605Smrg MAP_INTERNAL); 463b8e80941Smrg 464b8e80941Smrg /* Validation above already checked that PBO is not mapped, so buffer 465b8e80941Smrg * should not be null. 466b8e80941Smrg */ 467b8e80941Smrg assert(buf); 468848b8605Smrg 469848b8605Smrg return ADD_POINTERS(buf, pixels); 470848b8605Smrg} 471848b8605Smrg 472848b8605Smrg 473848b8605Smrg/** 474848b8605Smrg * This function must be called after either of the validate_pbo_*_teximage() 475848b8605Smrg * functions. It unmaps the PBO buffer if it was mapped earlier. 476848b8605Smrg */ 477848b8605Smrgvoid 478848b8605Smrg_mesa_unmap_teximage_pbo(struct gl_context *ctx, 479848b8605Smrg const struct gl_pixelstore_attrib *unpack) 480848b8605Smrg{ 481848b8605Smrg if (_mesa_is_bufferobj(unpack->BufferObj)) { 482848b8605Smrg ctx->Driver.UnmapBuffer(ctx, unpack->BufferObj, MAP_INTERNAL); 483848b8605Smrg } 484848b8605Smrg} 485