revision 1160:219d05b638de
summary |
tree |
shortlog |
changelog |
graph |
changeset |
raw | bz2 | zip | gz changeset | 1160:219d05b638de |
parent | 1159:580436b01b6c |
child | 1161:d3511e94c29f |
author | nkeynes |
date | Thu Jan 20 06:51:15 2011 +1000 (11 years ago) |
Add gl_vbo.c
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +00001.2 +++ b/src/drivers/gl_vbo.c Thu Jan 20 06:51:15 2011 +10001.3 @@ -0,0 +1,265 @@1.4 +/**1.5 + * $Id$1.6 + *1.7 + * Generic GL vertex buffer/vertex array support1.8 + *1.9 + * Copyright (c) 2011 Nathan Keynes.1.10 + *1.11 + * This program is free software; you can redistribute it and/or modify1.12 + * it under the terms of the GNU General Public License as published by1.13 + * the Free Software Foundation; either version 2 of the License, or1.14 + * (at your option) any later version.1.15 + *1.16 + * This program is distributed in the hope that it will be useful,1.17 + * but WITHOUT ANY WARRANTY; without even the implied warranty of1.18 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the1.19 + * GNU General Public License for more details.1.20 + */1.21 +1.22 +#define GL_GLEXT_PROTOTYPES 11.23 +1.24 +#include <assert.h>1.25 +#include <stdlib.h>1.26 +#include <sys/mman.h>1.27 +#include "lxdream.h"1.28 +#include "display.h"1.29 +#include "drivers/video_gl.h"1.30 +#include "pvr2/glutil.h"1.31 +1.32 +#define MIN_VERTEX_ARRAY_SIZE (1024*1024)1.33 +1.34 +vertex_buffer_t vertex_buffer_new( vertex_buffer_t vtable )1.35 +{1.36 + vertex_buffer_t buf = g_malloc(sizeof(struct vertex_buffer));1.37 + memcpy( buf, vtable, sizeof(struct vertex_buffer));1.38 + buf->data = 0;1.39 + buf->id = 0;1.40 + buf->mapped_size = buf->capacity = 0;1.41 + buf->fence = 0;1.42 + return buf;1.43 +}1.44 +1.45 +/******************************* Default ***********************************/1.46 +1.47 +static void *def_map( vertex_buffer_t buf, uint32_t size )1.48 +{1.49 + buf->mapped_size = size;1.50 + if( size < MIN_VERTEX_ARRAY_SIZE )1.51 + size = MIN_VERTEX_ARRAY_SIZE;1.52 + if( size > buf->capacity ) {1.53 + g_free(buf->data);1.54 + buf->data = g_malloc(size);1.55 + buf->capacity = size;1.56 + }1.57 + return buf->data;1.58 +}1.59 +1.60 +static void *def_unmap( vertex_buffer_t buf )1.61 +{1.62 + return buf->data;1.63 +}1.64 +1.65 +static void def_finished( vertex_buffer_t buf )1.66 +{1.67 +}1.68 +1.69 +static void def_destroy( vertex_buffer_t buf )1.70 +{1.71 + g_free(buf->data);1.72 + buf->data = NULL;1.73 + g_free(buf);1.74 +}1.75 +1.76 +static struct vertex_buffer def_vtable = { def_map, def_unmap, def_finished, def_destroy };1.77 +1.78 +static vertex_buffer_t def_create_buffer( )1.79 +{1.80 + return vertex_buffer_new( &def_vtable );1.81 +}1.82 +1.83 +/************************** vertex_array_range *****************************/1.84 +1.85 +/**1.86 + * VAR extensions like the buffer to be allocated on page boundaries.1.87 + */1.88 +static void var_alloc_pages( vertex_buffer_t buf, uint32_t size )1.89 +{1.90 + if( size < MIN_VERTEX_ARRAY_SIZE )1.91 + size = MIN_VERTEX_ARRAY_SIZE;1.92 + if( size > buf->capacity ) {1.93 + size = (size + 4096-1) & (~(4096-1));1.94 + if( buf->data != NULL ) {1.95 + munmap( buf->data, buf->capacity );1.96 + }1.97 + buf->data = mmap( NULL, size, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0 );1.98 + assert( buf->data != MAP_FAILED );1.99 + buf->capacity = size;1.100 + }1.101 +}1.102 +1.103 +#ifdef APPLE_BUILD1.104 +1.105 +static void *apple_map( vertex_buffer_t buf, uint32_t size )1.106 +{1.107 + glFinishFenceAPPLE(buf->fence);1.108 + var_alloc_pages( buf, size );1.109 + glVertexArrayRangeAPPLE(size, buf->data);1.110 + buf->mapped_size = size;1.111 + return buf->data;1.112 +}1.113 +1.114 +static void *apple_unmap( vertex_buffer_t buf )1.115 +{1.116 + glFlushVertexArrayRangeAPPLE(buf->mapped_size, buf->data);1.117 + return buf->data;1.118 +}1.119 +1.120 +static void apple_finished( vertex_buffer_t buf )1.121 +{1.122 + glSetFenceAPPLE(buf->fence);1.123 +}1.124 +1.125 +static void apple_destroy( vertex_buffer_t buf )1.126 +{1.127 + glVertexArrayRangeAPPLE(0,0);1.128 + glDeleteFencesAPPLE(1, &buf->fence);1.129 + munmap( buf->data, buf->capacity );1.130 + g_free(buf);1.131 +}1.132 +static struct vertex_buffer apple_vtable = { apple_map, apple_unmap, apple_finished, apple_destroy };1.133 +1.134 +static vertex_buffer_t apple_create_buffer( uint32_t size )1.135 +{1.136 + vertex_buffer_t buf = vertex_buffer_new( &apple_vtable );1.137 + glGenFencesAPPLE(1, &buf->fence);1.138 + return buf;1.139 +}1.140 +1.141 +#endif1.142 +1.143 +#ifdef GL_VERTEX_ARRAY_RANGE_NV1.144 +1.145 +static void *nv_map( vertex_buffer_t buf, uint32_t size )1.146 +{1.147 + glFinishFenceNV(buf->fence);1.148 + var_alloc_pages( buf, size );1.149 + glVertexArrayRangeNV(size, buf->data);1.150 + buf->mapped_size = size;1.151 + return buf->data;1.152 +}1.153 +static void *nv_unmap( vertex_buffer_t buf )1.154 +{1.155 + glFlushVertexArrayRangeNV();1.156 + return buf->data;1.157 +}1.158 +1.159 +static void nv_finished( vertex_buffer_t buf )1.160 +{1.161 + glSetFenceNV(buf->fence, GL_ALL_COMPLETED_NV);1.162 +}1.163 +1.164 +static void nv_destroy( vertex_buffer_t buf )1.165 +{1.166 + glVertexArrayRangeNV(0,0);1.167 + glDeleteFencesNV(1, &buf->fence);1.168 + munmap( buf->data, buf->capacity );1.169 + g_free(buf);1.170 +}1.171 +1.172 +static struct vertex_buffer nv_vtable = { nv_map, nv_unmap, nv_finished, nv_destroy };1.173 +1.174 +static vertex_buffer_t nv_create_buffer( uint32_t size )1.175 +{1.176 + vertex_buffer_t buf = vertex_buffer_new( &nv_vtable );1.177 + glGenFencesNV(1, &buf->fence);1.178 + return buf;1.179 +}1.180 +1.181 +#endif /* !GL_VERTEX_ARRAY_RANGE_NV */1.182 +1.183 +/************************** vertex_buffer_object *****************************/1.184 +1.185 +#ifdef GL_ARRAY_BUFFER_ARB1.186 +1.187 +static void *vbo_map( vertex_buffer_t buf, uint32_t size )1.188 +{1.189 + glBindBufferARB( GL_ARRAY_BUFFER_ARB, buf->id );1.190 + if( size > buf->capacity ) {1.191 + glBufferDataARB( GL_ARRAY_BUFFER_ARB, size, NULL, GL_STREAM_DRAW_ARB );1.192 + assert( gl_check_error("Allocating vbo data") );1.193 + buf->capacity = size;1.194 + }1.195 + buf->data = glMapBufferARB( GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB );1.196 + buf->mapped_size = buf->capacity;1.197 + return buf->data;1.198 +}1.199 +1.200 +static void *vbo_unmap( vertex_buffer_t buf )1.201 +{1.202 + glUnmapBufferARB( GL_ARRAY_BUFFER_ARB );1.203 + return NULL;1.204 +}1.205 +1.206 +static void vbo_finished( vertex_buffer_t buf )1.207 +{1.208 + glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );1.209 +}1.210 +1.211 +static void vbo_destroy( vertex_buffer_t buf )1.212 +{1.213 + glBindBufferARB( GL_ARRAY_BUFFER_ARB, 0 );1.214 + glDeleteBuffersARB( 1, &buf->id );1.215 +}1.216 +1.217 +static struct vertex_buffer vbo_vtable = { vbo_map, vbo_unmap, vbo_finished, vbo_destroy };1.218 +1.219 +static vertex_buffer_t vbo_create_buffer( uint32_t size )1.220 +{1.221 + vertex_buffer_t buf = vertex_buffer_new( &vbo_vtable );1.222 + glGenBuffersARB( 1, &buf->id );1.223 + return buf;1.224 +}1.225 +1.226 +#endif1.227 +1.228 +/**1.229 + * Auto-detect the supported vertex buffer types, and select between them.1.230 + * Use vertex_buffer_object if available, otherwise vertex_array_range,1.231 + * otherwise just pure host buffers.1.232 + */1.233 +void gl_vbo_init( display_driver_t driver ) {1.234 +/* VBOs are disabled for now as they won't work with the triangle sorting,1.235 + * plus they seem to be slower than the other options anyway.1.236 + */1.237 +#ifdef ENABLE_VBO1.238 +#ifdef GL_ARRAY_BUFFER_ARB1.239 + if( isGLVertexBufferSupported() ) {1.240 + driver->create_vertex_buffer = vbo_create_buffer;1.241 + return;1.242 + }1.243 +#endif1.244 +#endif1.245 +1.246 +#ifdef APPLE_BUILD1.247 + if( isGLExtensionSupported("GL_APPLE_vertex_array_range") &&1.248 + isGLExtensionSupported("GL_APPLE_fence") ) {1.249 + glEnableClientState( GL_VERTEX_ARRAY_RANGE_APPLE );1.250 + driver->create_vertex_buffer = apple_create_buffer;1.251 + return;1.252 + }1.253 +#endif1.254 +1.255 +#ifdef GL_VERTEX_ARRAY_RANGE_NV1.256 + if( isGLExtensionSupported("GL_NV_vertex_array_range") &&1.257 + isGLExtensionSupported("GL_NV_fence") ) {1.258 + glEnableClientState( GL_VERTEX_ARRAY_RANGE_NV );1.259 + driver->create_vertex_buffer = nv_create_buffer;1.260 + return;1.261 + }1.262 +#endif1.263 + driver->create_vertex_buffer = def_create_buffer;1.264 +}1.265 +1.266 +void gl_vbo_fallback_init( display_driver_t driver ) {1.267 + driver->create_vertex_buffer = def_create_buffer;1.268 +}
.