ReactOS Fundraising Campaign 2012
 
€ 4,060 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

bufferobj.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.