Search
lxdream.org :: lxdream/src/drivers/gl_vbo.c
lxdream 0.9.1
released Jun 29
Download Now
filename src/drivers/gl_vbo.c
changeset 1164:01b45ca393c6
prev1160:219d05b638de
next1289:ef8b0ddb8185
author Nathan Keynes <nkeynes@lxdream.org>
date Thu Apr 07 21:42:55 2011 +1000 (13 years ago)
permissions -rw-r--r--
last change Add german translation update from Riemann80, thanks!
view annotate diff log raw
     1 /**
     2  * $Id$
     3  *
     4  * Generic GL vertex buffer/vertex array support
     5  *
     6  * Copyright (c) 2011 Nathan Keynes.
     7  *
     8  * This program is free software; you can redistribute it and/or modify
     9  * it under the terms of the GNU General Public License as published by
    10  * the Free Software Foundation; either version 2 of the License, or
    11  * (at your option) any later version.
    12  *
    13  * This program is distributed in the hope that it will be useful,
    14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    16  * GNU General Public License for more details.
    17  */
    19 #define GL_GLEXT_PROTOTYPES 1
    21 #include <assert.h>
    22 #include <stdlib.h>
    23 #include <sys/mman.h>
    24 #include "lxdream.h"
    25 #include "display.h"
    26 #include "drivers/video_gl.h"
    27 #include "pvr2/glutil.h"
    29 #define MIN_VERTEX_ARRAY_SIZE (1024*1024)
    31 vertex_buffer_t vertex_buffer_new( vertex_buffer_t vtable )
    32 {
    33     vertex_buffer_t buf = g_malloc(sizeof(struct vertex_buffer));
    34     memcpy( buf, vtable, sizeof(struct vertex_buffer));
    35     buf->data = 0;
    36     buf->id = 0;
    37     buf->mapped_size = buf->capacity = 0;
    38     buf->fence = 0;
    39     return buf;
    40 }
    42 /******************************* Default ***********************************/
    44 static void *def_map( vertex_buffer_t buf, uint32_t size )
    45 {
    46     buf->mapped_size = size;
    47     if( size < MIN_VERTEX_ARRAY_SIZE )
    48         size = MIN_VERTEX_ARRAY_SIZE;
    49     if( size > buf->capacity ) {
    50         g_free(buf->data);
    51         buf->data = g_malloc(size);
    52         buf->capacity = size;
    53     }
    54     return buf->data;
    55 }
    57 static void *def_unmap( vertex_buffer_t buf )
    58 {
    59     return buf->data;
    60 }
    62 static void def_finished( vertex_buffer_t buf )
    63 {
    64 }
    66 static void def_destroy( vertex_buffer_t buf )
    67 {
    68     g_free(buf->data);
    69     buf->data = NULL;
    70     g_free(buf);
    71 }
    73 static struct vertex_buffer def_vtable = { def_map, def_unmap, def_finished, def_destroy };
    75 static vertex_buffer_t def_create_buffer( )
    76 {
    77     return vertex_buffer_new( &def_vtable );
    78 }
    80 /************************** vertex_array_range *****************************/
    82 /**
    83  * VAR extensions like the buffer to be allocated on page boundaries.
    84  */
    85 static void var_alloc_pages( vertex_buffer_t buf, uint32_t size )
    86 {
    87     if( size < MIN_VERTEX_ARRAY_SIZE )
    88         size = MIN_VERTEX_ARRAY_SIZE;
    89     if( size > buf->capacity ) {
    90         size = (size + 4096-1) & (~(4096-1));
    91         if( buf->data != NULL ) {
    92             munmap( buf->data, buf->capacity );
    93         }
    94         buf->data = mmap( NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0 );
    95         assert( buf->data != MAP_FAILED );
    96         buf->capacity = size;
    97     }
    98 }
   100 #ifdef APPLE_BUILD
   102 static void *apple_map( vertex_buffer_t buf, uint32_t size )
   103 {
   104     glFinishFenceAPPLE(buf->fence);
   105     var_alloc_pages( buf, size );
   106     glVertexArrayRangeAPPLE(size, buf->data);
   107     buf->mapped_size = size;
   108     return buf->data;
   109 }
   111 static void *apple_unmap( vertex_buffer_t buf )
   112 {
   113     glFlushVertexArrayRangeAPPLE(buf->mapped_size, buf->data);
   114     return buf->data;
   115 }
   117 static void apple_finished( vertex_buffer_t buf )
   118 {
   119     glSetFenceAPPLE(buf->fence);
   120 }
   122 static void apple_destroy( vertex_buffer_t buf )
   123 {
   124     glVertexArrayRangeAPPLE(0,0);
   125     glDeleteFencesAPPLE(1, &buf->fence);
   126     munmap( buf->data, buf->capacity );
   127     g_free(buf);
   128 }
   129 static struct vertex_buffer apple_vtable = { apple_map, apple_unmap, apple_finished, apple_destroy };
   131 static vertex_buffer_t apple_create_buffer( uint32_t size )
   132 {
   133     vertex_buffer_t buf = vertex_buffer_new( &apple_vtable );
   134     glGenFencesAPPLE(1, &buf->fence);
   135     glSetFenceAPPLE(buf->fence);    
   136     return buf;
   137 }
   139 #endif
   141 #ifdef GL_VERTEX_ARRAY_RANGE_NV
   143 #pragma weak glVertexArrayRangeNV
   144 #pragma weak glFlushVertexArrayRangeNV
   145 #pragma weak glFinishFenceNV
   146 #pragma weak glSetFenceNV
   147 #pragma weak glGenFencesNV
   148 #pragma weak glDeleteFencesNV
   150 static void *nv_map( vertex_buffer_t buf, uint32_t size )
   151 {
   152     glFinishFenceNV(buf->fence);
   153     var_alloc_pages( buf, size );
   154     glVertexArrayRangeNV(size, buf->data);
   155     buf->mapped_size = size;
   156     return buf->data;
   157 }
   158 static void *nv_unmap( vertex_buffer_t buf )
   159 {
   160     glFlushVertexArrayRangeNV();
   161     return buf->data;
   162 }
   164 static void nv_finished( vertex_buffer_t buf )
   165 {
   166     glSetFenceNV(buf->fence, GL_ALL_COMPLETED_NV);
   167 }
   169 static void nv_destroy( vertex_buffer_t buf )
   170 {
   171     glVertexArrayRangeNV(0,0);
   172     glDeleteFencesNV(1, &buf->fence);
   173     munmap( buf->data, buf->capacity );
   174     g_free(buf);
   175 }
   177 static struct vertex_buffer nv_vtable = { nv_map, nv_unmap, nv_finished, nv_destroy };
   179 static vertex_buffer_t nv_create_buffer( uint32_t size )
   180 {
   181     vertex_buffer_t buf = vertex_buffer_new( &nv_vtable );
   182     glGenFencesNV(1, &buf->fence);
   183     glSetFenceNV(buf->fence, GL_ALL_COMPLETED_NV);
   184     return buf;
   185 }
   187 #endif /* !GL_VERTEX_ARRAY_RANGE_NV */
   189 /************************** vertex_buffer_object *****************************/
   191 #ifdef GL_ARRAY_BUFFER_ARB
   193 static void *vbo_map( vertex_buffer_t buf, uint32_t size )
   194 {
   195     glBindBufferARB( GL_ARRAY_BUFFER_ARB, buf->id );
   196      if( size > buf->capacity ) {
   197          glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB );
   198          assert( gl_check_error("Allocating vbo data") );
   199          buf->capacity = size;
   200     }
   201     buf->data = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );
   202     buf->mapped_size = buf->capacity;
   203     return buf->data;
   204 }
   206 static void *vbo_unmap( vertex_buffer_t buf )
   207 {
   208     glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );
   209     return NULL;
   210 }
   212 static void vbo_finished( vertex_buffer_t buf )
   213 {
   214     glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
   215 }
   217 static void vbo_destroy( vertex_buffer_t buf )
   218 {
   219     glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );
   220     glDeleteBuffersARB( 1, &buf->id );
   221 }
   223 static struct vertex_buffer vbo_vtable = { vbo_map, vbo_unmap, vbo_finished, vbo_destroy };
   225 static vertex_buffer_t vbo_create_buffer( uint32_t size )
   226 {
   227     vertex_buffer_t buf = vertex_buffer_new( &vbo_vtable );
   228     glGenBuffersARB( 1, &buf->id );
   229     return buf;
   230 }
   232 #endif
   234 /**
   235  * Auto-detect the supported vertex buffer types, and select between them.
   236  * Use vertex_buffer_object if available, otherwise vertex_array_range,
   237  * otherwise just pure host buffers.
   238  */
   239 void gl_vbo_init( display_driver_t driver ) {
   240 /* VBOs are disabled for now as they won't work with the triangle sorting,
   241  * plus they seem to be slower than the other options anyway.
   242  */
   243 #ifdef ENABLE_VBO
   244 #ifdef GL_ARRAY_BUFFER_ARB
   245     if( isGLVertexBufferSupported() ) {
   246         driver->create_vertex_buffer = vbo_create_buffer;
   247         return;
   248     }
   249 #endif
   250 #endif
   252 #ifdef APPLE_BUILD
   253     if( isGLExtensionSupported("GL_APPLE_vertex_array_range") &&
   254             isGLExtensionSupported("GL_APPLE_fence") ) {
   255         glEnableClientState( GL_VERTEX_ARRAY_RANGE_APPLE );
   256         driver->create_vertex_buffer = apple_create_buffer;
   257         return;
   258     }
   259 #endif
   261 #ifdef GL_VERTEX_ARRAY_RANGE_NV
   262     if( isGLExtensionSupported("GL_NV_vertex_array_range") &&
   263             isGLExtensionSupported("GL_NV_fence") ) {
   264         glEnableClientState( GL_VERTEX_ARRAY_RANGE_NV );
   265         driver->create_vertex_buffer = nv_create_buffer;
   266         return;
   267     }
   268 #endif
   269     driver->create_vertex_buffer = def_create_buffer;
   270 }
   272 void gl_vbo_fallback_init( display_driver_t driver ) {
   273     driver->create_vertex_buffer = def_create_buffer;
   274 }
.