Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenbufferobj.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.2 00004 * 00005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00033 #include "glheader.h" 00034 #include "hash.h" 00035 #include "imports.h" 00036 #include "image.h" 00037 #include "context.h" 00038 #include "bufferobj.h" 00039 00040 00050 static INLINE struct gl_buffer_object * 00051 get_buffer(GLcontext *ctx, GLenum target) 00052 { 00053 struct gl_buffer_object * bufObj = NULL; 00054 00055 switch (target) { 00056 case GL_ARRAY_BUFFER_ARB: 00057 bufObj = ctx->Array.ArrayBufferObj; 00058 break; 00059 case GL_ELEMENT_ARRAY_BUFFER_ARB: 00060 bufObj = ctx->Array.ElementArrayBufferObj; 00061 break; 00062 case GL_PIXEL_PACK_BUFFER_EXT: 00063 bufObj = ctx->Pack.BufferObj; 00064 break; 00065 case GL_PIXEL_UNPACK_BUFFER_EXT: 00066 bufObj = ctx->Unpack.BufferObj; 00067 break; 00068 default: 00069 /* error must be recorded by caller */ 00070 return NULL; 00071 } 00072 00073 /* bufObj should point to NullBufferObj or a user-created buffer object */ 00074 ASSERT(bufObj); 00075 00076 return bufObj; 00077 } 00078 00079 00096 static struct gl_buffer_object * 00097 buffer_object_subdata_range_good( GLcontext * ctx, GLenum target, 00098 GLintptrARB offset, GLsizeiptrARB size, 00099 const char *caller ) 00100 { 00101 struct gl_buffer_object *bufObj; 00102 00103 if (size < 0) { 00104 _mesa_error(ctx, GL_INVALID_VALUE, "%s(size < 0)", caller); 00105 return NULL; 00106 } 00107 00108 if (offset < 0) { 00109 _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset < 0)", caller); 00110 return NULL; 00111 } 00112 00113 bufObj = get_buffer(ctx, target); 00114 if (!bufObj) { 00115 _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", caller); 00116 return NULL; 00117 } 00118 if (bufObj->Name == 0) { 00119 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 00120 return NULL; 00121 } 00122 if (offset + size > bufObj->Size) { 00123 _mesa_error(ctx, GL_INVALID_VALUE, 00124 "%s(size + offset > buffer size)", caller); 00125 return NULL; 00126 } 00127 if (bufObj->Pointer) { 00128 /* Buffer is currently mapped */ 00129 _mesa_error(ctx, GL_INVALID_OPERATION, "%s", caller); 00130 return NULL; 00131 } 00132 00133 return bufObj; 00134 } 00135 00136 00143 struct gl_buffer_object * 00144 _mesa_new_buffer_object( GLcontext *ctx, GLuint name, GLenum target ) 00145 { 00146 struct gl_buffer_object *obj; 00147 00148 (void) ctx; 00149 00150 obj = MALLOC_STRUCT(gl_buffer_object); 00151 _mesa_initialize_buffer_object(obj, name, target); 00152 return obj; 00153 } 00154 00155 00162 void 00163 _mesa_delete_buffer_object( GLcontext *ctx, struct gl_buffer_object *bufObj ) 00164 { 00165 (void) ctx; 00166 00167 if (bufObj->Data) 00168 _mesa_free(bufObj->Data); 00169 00170 /* assign strange values here to help w/ debugging */ 00171 bufObj->RefCount = -1000; 00172 bufObj->Name = ~0; 00173 00174 _mesa_free(bufObj); 00175 } 00176 00177 00178 00182 void 00183 _mesa_reference_buffer_object(GLcontext *ctx, 00184 struct gl_buffer_object **ptr, 00185 struct gl_buffer_object *bufObj) 00186 { 00187 if (*ptr == bufObj) 00188 return; 00189 00190 if (*ptr) { 00191 /* Unreference the old texture */ 00192 GLboolean deleteFlag = GL_FALSE; 00193 struct gl_buffer_object *oldObj = *ptr; 00194 00195 /*_glthread_LOCK_MUTEX(oldObj->Mutex);*/ 00196 ASSERT(oldObj->RefCount > 0); 00197 oldObj->RefCount--; 00198 #if 0 00199 printf("BufferObj %p %d DECR to %d\n", 00200 (void *) oldObj, oldObj->Name, oldObj->RefCount); 00201 #endif 00202 deleteFlag = (oldObj->RefCount == 0); 00203 /*_glthread_UNLOCK_MUTEX(oldObj->Mutex);*/ 00204 00205 if (deleteFlag) { 00206 00207 /* some sanity checking: don't delete a buffer still in use */ 00208 #if 0 00209 /* unfortunately, these tests are invalid during context tear-down */ 00210 ASSERT(ctx->Array.ArrayBufferObj != bufObj); 00211 ASSERT(ctx->Array.ElementArrayBufferObj != bufObj); 00212 ASSERT(ctx->Array.ArrayObj->Vertex.BufferObj != bufObj); 00213 #endif 00214 00215 ASSERT(ctx->Driver.DeleteBuffer); 00216 ctx->Driver.DeleteBuffer(ctx, oldObj); 00217 } 00218 00219 *ptr = NULL; 00220 } 00221 ASSERT(!*ptr); 00222 00223 if (bufObj) { 00224 /* reference new texture */ 00225 /*_glthread_LOCK_MUTEX(tex->Mutex);*/ 00226 if (bufObj->RefCount == 0) { 00227 /* this buffer's being deleted (look just above) */ 00228 /* Not sure this can every really happen. Warn if it does. */ 00229 _mesa_problem(NULL, "referencing deleted buffer object"); 00230 *ptr = NULL; 00231 } 00232 else { 00233 bufObj->RefCount++; 00234 #if 0 00235 printf("BufferObj %p %d INCR to %d\n", 00236 (void *) bufObj, bufObj->Name, bufObj->RefCount); 00237 #endif 00238 *ptr = bufObj; 00239 } 00240 /*_glthread_UNLOCK_MUTEX(tex->Mutex);*/ 00241 } 00242 } 00243 00244 00248 void 00249 _mesa_initialize_buffer_object( struct gl_buffer_object *obj, 00250 GLuint name, GLenum target ) 00251 { 00252 (void) target; 00253 00254 _mesa_bzero(obj, sizeof(struct gl_buffer_object)); 00255 obj->RefCount = 1; 00256 obj->Name = name; 00257 obj->Usage = GL_STATIC_DRAW_ARB; 00258 obj->Access = GL_READ_WRITE_ARB; 00259 } 00260 00261 00281 void 00282 _mesa_buffer_data( GLcontext *ctx, GLenum target, GLsizeiptrARB size, 00283 const GLvoid * data, GLenum usage, 00284 struct gl_buffer_object * bufObj ) 00285 { 00286 void * new_data; 00287 00288 (void) ctx; (void) target; 00289 00290 new_data = _mesa_realloc( bufObj->Data, bufObj->Size, size ); 00291 if (new_data) { 00292 bufObj->Data = (GLubyte *) new_data; 00293 bufObj->Size = size; 00294 bufObj->Usage = usage; 00295 00296 if (data) { 00297 _mesa_memcpy( bufObj->Data, data, size ); 00298 } 00299 } 00300 } 00301 00302 00321 void 00322 _mesa_buffer_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, 00323 GLsizeiptrARB size, const GLvoid * data, 00324 struct gl_buffer_object * bufObj ) 00325 { 00326 (void) ctx; (void) target; 00327 00328 /* this should have been caught in _mesa_BufferSubData() */ 00329 ASSERT(size + offset <= bufObj->Size); 00330 00331 if (bufObj->Data) { 00332 _mesa_memcpy( (GLubyte *) bufObj->Data + offset, data, size ); 00333 } 00334 } 00335 00336 00355 void 00356 _mesa_buffer_get_subdata( GLcontext *ctx, GLenum target, GLintptrARB offset, 00357 GLsizeiptrARB size, GLvoid * data, 00358 struct gl_buffer_object * bufObj ) 00359 { 00360 (void) ctx; (void) target; 00361 00362 if (bufObj->Data && ((GLsizeiptrARB) (size + offset) <= bufObj->Size)) { 00363 _mesa_memcpy( data, (GLubyte *) bufObj->Data + offset, size ); 00364 } 00365 } 00366 00367 00384 void * 00385 _mesa_buffer_map( GLcontext *ctx, GLenum target, GLenum access, 00386 struct gl_buffer_object *bufObj ) 00387 { 00388 (void) ctx; 00389 (void) target; 00390 (void) access; 00391 ASSERT(!bufObj->OnCard); 00392 /* Just return a direct pointer to the data */ 00393 if (bufObj->Pointer) { 00394 /* already mapped! */ 00395 return NULL; 00396 } 00397 bufObj->Pointer = bufObj->Data; 00398 return bufObj->Pointer; 00399 } 00400 00401 00411 GLboolean 00412 _mesa_buffer_unmap( GLcontext *ctx, GLenum target, 00413 struct gl_buffer_object *bufObj ) 00414 { 00415 (void) ctx; 00416 (void) target; 00417 ASSERT(!bufObj->OnCard); 00418 /* XXX we might assert here that bufObj->Pointer is non-null */ 00419 bufObj->Pointer = NULL; 00420 return GL_TRUE; 00421 } 00422 00423 00427 void 00428 _mesa_init_buffer_objects( GLcontext *ctx ) 00429 { 00430 /* Allocate the default buffer object and set refcount so high that 00431 * it never gets deleted. 00432 * XXX with recent/improved refcounting this may not longer be needed. 00433 */ 00434 ctx->Array.NullBufferObj = _mesa_new_buffer_object(ctx, 0, 0); 00435 if (ctx->Array.NullBufferObj) 00436 ctx->Array.NullBufferObj->RefCount = 1000; 00437 00438 ctx->Array.ArrayBufferObj = ctx->Array.NullBufferObj; 00439 ctx->Array.ElementArrayBufferObj = ctx->Array.NullBufferObj; 00440 } 00441 00445 static void 00446 bind_buffer_object(GLcontext *ctx, GLenum target, GLuint buffer) 00447 { 00448 struct gl_buffer_object *oldBufObj; 00449 struct gl_buffer_object *newBufObj = NULL; 00450 struct gl_buffer_object **bindTarget = NULL; 00451 00452 switch (target) { 00453 case GL_ARRAY_BUFFER_ARB: 00454 bindTarget = &ctx->Array.ArrayBufferObj; 00455 break; 00456 case GL_ELEMENT_ARRAY_BUFFER_ARB: 00457 bindTarget = &ctx->Array.ElementArrayBufferObj; 00458 break; 00459 case GL_PIXEL_PACK_BUFFER_EXT: 00460 bindTarget = &ctx->Pack.BufferObj; 00461 break; 00462 case GL_PIXEL_UNPACK_BUFFER_EXT: 00463 bindTarget = &ctx->Unpack.BufferObj; 00464 break; 00465 default: 00466 _mesa_error(ctx, GL_INVALID_ENUM, "glBindBufferARB(target)"); 00467 return; 00468 } 00469 00470 /* Get pointer to old buffer object (to be unbound) */ 00471 oldBufObj = get_buffer(ctx, target); 00472 if (oldBufObj && oldBufObj->Name == buffer) 00473 return; /* rebinding the same buffer object- no change */ 00474 00475 /* 00476 * Get pointer to new buffer object (newBufObj) 00477 */ 00478 if (buffer == 0) { 00479 /* The spec says there's not a buffer object named 0, but we use 00480 * one internally because it simplifies things. 00481 */ 00482 newBufObj = ctx->Array.NullBufferObj; 00483 } 00484 else { 00485 /* non-default buffer object */ 00486 newBufObj = _mesa_lookup_bufferobj(ctx, buffer); 00487 if (!newBufObj) { 00488 /* if this is a new buffer object id, allocate a buffer object now */ 00489 ASSERT(ctx->Driver.NewBufferObject); 00490 newBufObj = ctx->Driver.NewBufferObject(ctx, buffer, target); 00491 if (!newBufObj) { 00492 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindBufferARB"); 00493 return; 00494 } 00495 _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, newBufObj); 00496 } 00497 } 00498 00499 /* bind new buffer */ 00500 _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); 00501 00502 /* Pass BindBuffer call to device driver */ 00503 if (ctx->Driver.BindBuffer && newBufObj) 00504 ctx->Driver.BindBuffer( ctx, target, newBufObj ); 00505 } 00506 00507 00513 void 00514 _mesa_update_default_objects_buffer_objects(GLcontext *ctx) 00515 { 00516 /* Bind the NullBufferObj to remove references to those 00517 * in the shared context hash table. 00518 */ 00519 bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); 00520 bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); 00521 bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); 00522 bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); 00523 } 00524 00525 00545 GLboolean 00546 _mesa_validate_pbo_access(GLuint dimensions, 00547 const struct gl_pixelstore_attrib *pack, 00548 GLsizei width, GLsizei height, GLsizei depth, 00549 GLenum format, GLenum type, const GLvoid *ptr) 00550 { 00551 GLvoid *start, *end; 00552 const GLubyte *sizeAddr; /* buffer size, cast to a pointer */ 00553 00554 ASSERT(pack->BufferObj->Name != 0); 00555 00556 if (pack->BufferObj->Size == 0) 00557 /* no buffer! */ 00558 return GL_FALSE; 00559 00560 /* get address of first pixel we'll read */ 00561 start = _mesa_image_address(dimensions, pack, ptr, width, height, 00562 format, type, 0, 0, 0); 00563 00564 /* get address just past the last pixel we'll read */ 00565 end = _mesa_image_address(dimensions, pack, ptr, width, height, 00566 format, type, depth-1, height-1, width); 00567 00568 00569 sizeAddr = ((const GLubyte *) 0) + pack->BufferObj->Size; 00570 00571 if ((const GLubyte *) start > sizeAddr) { 00572 /* This will catch negative values / wrap-around */ 00573 return GL_FALSE; 00574 } 00575 if ((const GLubyte *) end > sizeAddr) { 00576 /* Image read goes beyond end of buffer */ 00577 return GL_FALSE; 00578 } 00579 00580 /* OK! */ 00581 return GL_TRUE; 00582 } 00583 00584 00593 const GLubyte * 00594 _mesa_map_bitmap_pbo(GLcontext *ctx, 00595 const struct gl_pixelstore_attrib *unpack, 00596 const GLubyte *bitmap) 00597 { 00598 const GLubyte *buf; 00599 00600 if (unpack->BufferObj->Name) { 00601 /* unpack from PBO */ 00602 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00603 GL_READ_ONLY_ARB, 00604 unpack->BufferObj); 00605 if (!buf) 00606 return NULL; 00607 00608 buf = ADD_POINTERS(buf, bitmap); 00609 } 00610 else { 00611 /* unpack from normal memory */ 00612 buf = bitmap; 00613 } 00614 00615 return buf; 00616 } 00617 00618 00623 void 00624 _mesa_unmap_bitmap_pbo(GLcontext *ctx, 00625 const struct gl_pixelstore_attrib *unpack) 00626 { 00627 if (unpack->BufferObj->Name) { 00628 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00629 unpack->BufferObj); 00630 } 00631 } 00632 00633 00637 const GLvoid * 00638 _mesa_map_drawpix_pbo(GLcontext *ctx, 00639 const struct gl_pixelstore_attrib *unpack, 00640 const GLvoid *pixels) 00641 { 00642 const GLvoid *buf; 00643 00644 if (unpack->BufferObj->Name) { 00645 /* unpack from PBO */ 00646 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00647 GL_READ_ONLY_ARB, 00648 unpack->BufferObj); 00649 if (!buf) 00650 return NULL; 00651 00652 buf = ADD_POINTERS(buf, pixels); 00653 } 00654 else { 00655 /* unpack from normal memory */ 00656 buf = pixels; 00657 } 00658 00659 return buf; 00660 } 00661 00662 00666 void 00667 _mesa_unmap_drapix_pbo(GLcontext *ctx, 00668 const struct gl_pixelstore_attrib *unpack) 00669 { 00670 if (unpack->BufferObj->Name) { 00671 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 00672 unpack->BufferObj); 00673 } 00674 } 00675 00676 00682 void * 00683 _mesa_map_readpix_pbo(GLcontext *ctx, 00684 const struct gl_pixelstore_attrib *pack, 00685 GLvoid *dest) 00686 { 00687 void *buf; 00688 00689 if (pack->BufferObj->Name) { 00690 /* pack into PBO */ 00691 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, 00692 GL_WRITE_ONLY_ARB, 00693 pack->BufferObj); 00694 if (!buf) 00695 return NULL; 00696 00697 buf = ADD_POINTERS(buf, dest); 00698 } 00699 else { 00700 /* pack to normal memory */ 00701 buf = dest; 00702 } 00703 00704 return buf; 00705 } 00706 00707 00711 void 00712 _mesa_unmap_readpix_pbo(GLcontext *ctx, 00713 const struct gl_pixelstore_attrib *pack) 00714 { 00715 if (pack->BufferObj->Name) { 00716 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT, pack->BufferObj); 00717 } 00718 } 00719 00720 00721 00726 struct gl_buffer_object * 00727 _mesa_lookup_bufferobj(GLcontext *ctx, GLuint buffer) 00728 { 00729 if (buffer == 0) 00730 return NULL; 00731 else 00732 return (struct gl_buffer_object *) 00733 _mesa_HashLookup(ctx->Shared->BufferObjects, buffer); 00734 } 00735 00736 00743 static void 00744 unbind(GLcontext *ctx, 00745 struct gl_buffer_object **ptr, 00746 struct gl_buffer_object *obj) 00747 { 00748 if (*ptr == obj) { 00749 _mesa_reference_buffer_object(ctx, ptr, ctx->Array.NullBufferObj); 00750 } 00751 } 00752 00753 00754 00755 /**********************************************************************/ 00756 /* API Functions */ 00757 /**********************************************************************/ 00758 00759 void GLAPIENTRY 00760 _mesa_BindBufferARB(GLenum target, GLuint buffer) 00761 { 00762 GET_CURRENT_CONTEXT(ctx); 00763 ASSERT_OUTSIDE_BEGIN_END(ctx); 00764 00765 bind_buffer_object(ctx, target, buffer); 00766 } 00767 00768 00775 void GLAPIENTRY 00776 _mesa_DeleteBuffersARB(GLsizei n, const GLuint *ids) 00777 { 00778 GET_CURRENT_CONTEXT(ctx); 00779 GLsizei i; 00780 ASSERT_OUTSIDE_BEGIN_END(ctx); 00781 00782 if (n < 0) { 00783 _mesa_error(ctx, GL_INVALID_VALUE, "glDeleteBuffersARB(n)"); 00784 return; 00785 } 00786 00787 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 00788 00789 for (i = 0; i < n; i++) { 00790 struct gl_buffer_object *bufObj = _mesa_lookup_bufferobj(ctx, ids[i]); 00791 if (bufObj) { 00792 /* unbind any vertex pointers bound to this buffer */ 00793 GLuint j; 00794 00795 ASSERT(bufObj->Name == ids[i]); 00796 00797 if (bufObj->Pointer) { 00798 /* if mapped, unmap it now */ 00799 ctx->Driver.UnmapBuffer(ctx, 0, bufObj); 00800 bufObj->Access = GL_READ_WRITE_ARB; 00801 bufObj->Pointer = NULL; 00802 } 00803 00804 unbind(ctx, &ctx->Array.ArrayObj->Vertex.BufferObj, bufObj); 00805 unbind(ctx, &ctx->Array.ArrayObj->Normal.BufferObj, bufObj); 00806 unbind(ctx, &ctx->Array.ArrayObj->Color.BufferObj, bufObj); 00807 unbind(ctx, &ctx->Array.ArrayObj->SecondaryColor.BufferObj, bufObj); 00808 unbind(ctx, &ctx->Array.ArrayObj->FogCoord.BufferObj, bufObj); 00809 unbind(ctx, &ctx->Array.ArrayObj->Index.BufferObj, bufObj); 00810 unbind(ctx, &ctx->Array.ArrayObj->EdgeFlag.BufferObj, bufObj); 00811 for (j = 0; j < MAX_TEXTURE_COORD_UNITS; j++) { 00812 unbind(ctx, &ctx->Array.ArrayObj->TexCoord[j].BufferObj, bufObj); 00813 } 00814 for (j = 0; j < VERT_ATTRIB_MAX; j++) { 00815 unbind(ctx, &ctx->Array.ArrayObj->VertexAttrib[j].BufferObj, bufObj); 00816 } 00817 00818 if (ctx->Array.ArrayBufferObj == bufObj) { 00819 _mesa_BindBufferARB( GL_ARRAY_BUFFER_ARB, 0 ); 00820 } 00821 if (ctx->Array.ElementArrayBufferObj == bufObj) { 00822 _mesa_BindBufferARB( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); 00823 } 00824 00825 if (ctx->Pack.BufferObj == bufObj) { 00826 _mesa_BindBufferARB( GL_PIXEL_PACK_BUFFER_EXT, 0 ); 00827 } 00828 if (ctx->Unpack.BufferObj == bufObj) { 00829 _mesa_BindBufferARB( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); 00830 } 00831 00832 /* The ID is immediately freed for re-use */ 00833 _mesa_HashRemove(ctx->Shared->BufferObjects, bufObj->Name); 00834 _mesa_reference_buffer_object(ctx, &bufObj, NULL); 00835 } 00836 } 00837 00838 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 00839 } 00840 00841 00848 void GLAPIENTRY 00849 _mesa_GenBuffersARB(GLsizei n, GLuint *buffer) 00850 { 00851 GET_CURRENT_CONTEXT(ctx); 00852 GLuint first; 00853 GLint i; 00854 ASSERT_OUTSIDE_BEGIN_END(ctx); 00855 00856 if (n < 0) { 00857 _mesa_error(ctx, GL_INVALID_VALUE, "glGenBuffersARB"); 00858 return; 00859 } 00860 00861 if (!buffer) { 00862 return; 00863 } 00864 00865 /* 00866 * This must be atomic (generation and allocation of buffer object IDs) 00867 */ 00868 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 00869 00870 first = _mesa_HashFindFreeKeyBlock(ctx->Shared->BufferObjects, n); 00871 00872 /* Allocate new, empty buffer objects and return identifiers */ 00873 for (i = 0; i < n; i++) { 00874 struct gl_buffer_object *bufObj; 00875 GLuint name = first + i; 00876 GLenum target = 0; 00877 bufObj = ctx->Driver.NewBufferObject( ctx, name, target ); 00878 if (!bufObj) { 00879 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 00880 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glGenBuffersARB"); 00881 return; 00882 } 00883 _mesa_HashInsert(ctx->Shared->BufferObjects, first + i, bufObj); 00884 buffer[i] = first + i; 00885 } 00886 00887 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 00888 } 00889 00890 00898 GLboolean GLAPIENTRY 00899 _mesa_IsBufferARB(GLuint id) 00900 { 00901 struct gl_buffer_object *bufObj; 00902 GET_CURRENT_CONTEXT(ctx); 00903 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 00904 00905 _glthread_LOCK_MUTEX(ctx->Shared->Mutex); 00906 bufObj = _mesa_lookup_bufferobj(ctx, id); 00907 _glthread_UNLOCK_MUTEX(ctx->Shared->Mutex); 00908 00909 return bufObj ? GL_TRUE : GL_FALSE; 00910 } 00911 00912 00913 void GLAPIENTRY 00914 _mesa_BufferDataARB(GLenum target, GLsizeiptrARB size, 00915 const GLvoid * data, GLenum usage) 00916 { 00917 GET_CURRENT_CONTEXT(ctx); 00918 struct gl_buffer_object *bufObj; 00919 ASSERT_OUTSIDE_BEGIN_END(ctx); 00920 00921 if (size < 0) { 00922 _mesa_error(ctx, GL_INVALID_VALUE, "glBufferDataARB(size < 0)"); 00923 return; 00924 } 00925 00926 switch (usage) { 00927 case GL_STREAM_DRAW_ARB: 00928 case GL_STREAM_READ_ARB: 00929 case GL_STREAM_COPY_ARB: 00930 case GL_STATIC_DRAW_ARB: 00931 case GL_STATIC_READ_ARB: 00932 case GL_STATIC_COPY_ARB: 00933 case GL_DYNAMIC_DRAW_ARB: 00934 case GL_DYNAMIC_READ_ARB: 00935 case GL_DYNAMIC_COPY_ARB: 00936 /* OK */ 00937 break; 00938 default: 00939 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(usage)"); 00940 return; 00941 } 00942 00943 bufObj = get_buffer(ctx, target); 00944 if (!bufObj) { 00945 _mesa_error(ctx, GL_INVALID_ENUM, "glBufferDataARB(target)" ); 00946 return; 00947 } 00948 if (bufObj->Name == 0) { 00949 _mesa_error(ctx, GL_INVALID_OPERATION, "glBufferDataARB" ); 00950 return; 00951 } 00952 00953 if (bufObj->Pointer) { 00954 /* Unmap the existing buffer. We'll replace it now. Not an error. */ 00955 ctx->Driver.UnmapBuffer(ctx, target, bufObj); 00956 bufObj->Access = GL_READ_WRITE_ARB; 00957 bufObj->Pointer = NULL; 00958 } 00959 00960 ASSERT(ctx->Driver.BufferData); 00961 00962 /* Give the buffer object to the driver! <data> may be null! */ 00963 ctx->Driver.BufferData( ctx, target, size, data, usage, bufObj ); 00964 } 00965 00966 00967 void GLAPIENTRY 00968 _mesa_BufferSubDataARB(GLenum target, GLintptrARB offset, 00969 GLsizeiptrARB size, const GLvoid * data) 00970 { 00971 GET_CURRENT_CONTEXT(ctx); 00972 struct gl_buffer_object *bufObj; 00973 ASSERT_OUTSIDE_BEGIN_END(ctx); 00974 00975 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, 00976 "glBufferSubDataARB" ); 00977 if (!bufObj) { 00978 /* error already recorded */ 00979 return; 00980 } 00981 00982 ASSERT(ctx->Driver.BufferSubData); 00983 ctx->Driver.BufferSubData( ctx, target, offset, size, data, bufObj ); 00984 } 00985 00986 00987 void GLAPIENTRY 00988 _mesa_GetBufferSubDataARB(GLenum target, GLintptrARB offset, 00989 GLsizeiptrARB size, void * data) 00990 { 00991 GET_CURRENT_CONTEXT(ctx); 00992 struct gl_buffer_object *bufObj; 00993 ASSERT_OUTSIDE_BEGIN_END(ctx); 00994 00995 bufObj = buffer_object_subdata_range_good( ctx, target, offset, size, 00996 "glGetBufferSubDataARB" ); 00997 if (!bufObj) { 00998 /* error already recorded */ 00999 return; 01000 } 01001 01002 ASSERT(ctx->Driver.GetBufferSubData); 01003 ctx->Driver.GetBufferSubData( ctx, target, offset, size, data, bufObj ); 01004 } 01005 01006 01007 void * GLAPIENTRY 01008 _mesa_MapBufferARB(GLenum target, GLenum access) 01009 { 01010 GET_CURRENT_CONTEXT(ctx); 01011 struct gl_buffer_object * bufObj; 01012 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, NULL); 01013 01014 switch (access) { 01015 case GL_READ_ONLY_ARB: 01016 case GL_WRITE_ONLY_ARB: 01017 case GL_READ_WRITE_ARB: 01018 /* OK */ 01019 break; 01020 default: 01021 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(access)"); 01022 return NULL; 01023 } 01024 01025 bufObj = get_buffer(ctx, target); 01026 if (!bufObj) { 01027 _mesa_error(ctx, GL_INVALID_ENUM, "glMapBufferARB(target)" ); 01028 return NULL; 01029 } 01030 if (bufObj->Name == 0) { 01031 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB" ); 01032 return NULL; 01033 } 01034 if (bufObj->Pointer) { 01035 _mesa_error(ctx, GL_INVALID_OPERATION, "glMapBufferARB(already mapped)"); 01036 return NULL; 01037 } 01038 01039 ASSERT(ctx->Driver.MapBuffer); 01040 bufObj->Pointer = ctx->Driver.MapBuffer( ctx, target, access, bufObj ); 01041 if (!bufObj->Pointer) { 01042 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glMapBufferARB(access)"); 01043 } 01044 01045 bufObj->Access = access; 01046 01047 return bufObj->Pointer; 01048 } 01049 01050 01051 GLboolean GLAPIENTRY 01052 _mesa_UnmapBufferARB(GLenum target) 01053 { 01054 GET_CURRENT_CONTEXT(ctx); 01055 struct gl_buffer_object *bufObj; 01056 GLboolean status = GL_TRUE; 01057 ASSERT_OUTSIDE_BEGIN_END_WITH_RETVAL(ctx, GL_FALSE); 01058 01059 bufObj = get_buffer(ctx, target); 01060 if (!bufObj) { 01061 _mesa_error(ctx, GL_INVALID_ENUM, "glUnmapBufferARB(target)" ); 01062 return GL_FALSE; 01063 } 01064 if (bufObj->Name == 0) { 01065 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB" ); 01066 return GL_FALSE; 01067 } 01068 if (!bufObj->Pointer) { 01069 _mesa_error(ctx, GL_INVALID_OPERATION, "glUnmapBufferARB"); 01070 return GL_FALSE; 01071 } 01072 01073 status = ctx->Driver.UnmapBuffer( ctx, target, bufObj ); 01074 bufObj->Access = GL_READ_WRITE_ARB; 01075 bufObj->Pointer = NULL; 01076 01077 return status; 01078 } 01079 01080 01081 void GLAPIENTRY 01082 _mesa_GetBufferParameterivARB(GLenum target, GLenum pname, GLint *params) 01083 { 01084 GET_CURRENT_CONTEXT(ctx); 01085 struct gl_buffer_object *bufObj; 01086 ASSERT_OUTSIDE_BEGIN_END(ctx); 01087 01088 bufObj = get_buffer(ctx, target); 01089 if (!bufObj) { 01090 _mesa_error(ctx, GL_INVALID_ENUM, "GetBufferParameterivARB(target)" ); 01091 return; 01092 } 01093 if (bufObj->Name == 0) { 01094 _mesa_error(ctx, GL_INVALID_OPERATION, "GetBufferParameterivARB" ); 01095 return; 01096 } 01097 01098 switch (pname) { 01099 case GL_BUFFER_SIZE_ARB: 01100 *params = (GLint) bufObj->Size; 01101 break; 01102 case GL_BUFFER_USAGE_ARB: 01103 *params = bufObj->Usage; 01104 break; 01105 case GL_BUFFER_ACCESS_ARB: 01106 *params = bufObj->Access; 01107 break; 01108 case GL_BUFFER_MAPPED_ARB: 01109 *params = (bufObj->Pointer != NULL); 01110 break; 01111 default: 01112 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferParameterivARB(pname)"); 01113 return; 01114 } 01115 } 01116 01117 01118 void GLAPIENTRY 01119 _mesa_GetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params) 01120 { 01121 GET_CURRENT_CONTEXT(ctx); 01122 struct gl_buffer_object * bufObj; 01123 ASSERT_OUTSIDE_BEGIN_END(ctx); 01124 01125 if (pname != GL_BUFFER_MAP_POINTER_ARB) { 01126 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(pname)"); 01127 return; 01128 } 01129 01130 bufObj = get_buffer(ctx, target); 01131 if (!bufObj) { 01132 _mesa_error(ctx, GL_INVALID_ENUM, "glGetBufferPointervARB(target)" ); 01133 return; 01134 } 01135 if (bufObj->Name == 0) { 01136 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetBufferPointervARB" ); 01137 return; 01138 } 01139 01140 *params = bufObj->Pointer; 01141 } Generated on Tue May 22 2012 04:23:52 for ReactOS by
1.7.6.1
|