vbo_exec_array.c revision 99efde461d3b8615863bdb7308e05289e0db0422
1aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com/************************************************************************** 2aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * 3aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 4aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * All Rights Reserved. 5aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * 6aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * Permission is hereby granted, free of charge, to any person obtaining a 7aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * copy of this software and associated documentation files (the 8aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * "Software"), to deal in the Software without restriction, including 9aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * without limitation the rights to use, copy, modify, merge, publish, 10aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * distribute, sub license, and/or sell copies of the Software, and to 11aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * permit persons to whom the Software is furnished to do so, subject to 12aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * the following conditions: 13ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips * 14a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips * The above copyright notice and this permission notice (including the 15aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * next paragraph) shall be included in all copies or substantial portions 166bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon * of the Software. 178dc7c3a839b38b73af34cc2674a06f49eb1ce527egdaniel * 18aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips * 2628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org **************************************************************************/ 2728361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org 2828361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org#include "glheader.h" 29c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips#include "context.h" 30c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips#include "state.h" 31c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips#include "api_validate.h" 32c9a3706f1ee38c331610ec1e872d9a658566c397robertphillips#include "api_noop.h" 332e1e51f04985f7c258b96f0decc190456f5dd74drobertphillips#include "dispatch.h" 34ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillips 3528361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org#include "vbo_context.h" 3628361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org 37ea4615034498aca2f9ca1753fb9a1ef10508d8ccrobertphillipsstatic GLuint get_max_index( GLuint count, GLuint type, 382e1e51f04985f7c258b96f0decc190456f5dd74drobertphillips const GLvoid *indices ) 3928361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org{ 4028361fad1054d59ed4e6a320c7a8b8782a1487c7commit-bot@chromium.org GLint i; 41fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org 42aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com /* Compute max element. This is only needed for upload of non-VBO, 4349f085dddff10473b6ebf832a974288300224e60bsalomon * non-constant data elements. 44aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * 45aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * XXX: Postpone this calculation until it is known that it is 46aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * needed. Otherwise could scan this pointlessly in the all-vbo 47aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com * case. 48aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com */ 49aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com switch(type) { 50aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com case GL_UNSIGNED_INT: { 51aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com const GLuint *ui_indices = (const GLuint *)indices; 52aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com GLuint max_ui = 0; 53aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com for (i = 0; i < count; i++) 54fd03d4a829efe2d77a712fd991927c55f59a2ffecommit-bot@chromium.org if (ui_indices[i] > max_ui) 55aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com max_ui = ui_indices[i]; 56aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com return max_ui; 57aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com } 58aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com case GL_UNSIGNED_SHORT: { 59aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com const GLushort *us_indices = (const GLushort *)indices; 60aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com GLuint max_us = 0; 61aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com for (i = 0; i < count; i++) 62aa5b6730f2658618015ed56ffb5882f15b6f053fbsalomon@google.com if (us_indices[i] > max_us) 6381c3f8de1cbb93a8b99d730a75ab16d864612e95bsalomon@google.com max_us = us_indices[i]; 6481c3f8de1cbb93a8b99d730a75ab16d864612e95bsalomon@google.com return max_us; 65d6bbbf8a831cc982cda9b91e84c5600c631af5b2robertphillips@google.com } 66ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel case GL_UNSIGNED_BYTE: { 67d364554bcfd391c3b6111af8bff963a35ab87ba7robertphillips@google.com const GLubyte *ub_indices = (const GLubyte *)indices; 68d364554bcfd391c3b6111af8bff963a35ab87ba7robertphillips@google.com GLuint max_ub = 0; 69d6bbbf8a831cc982cda9b91e84c5600c631af5b2robertphillips@google.com for (i = 0; i < count; i++) 70d6bbbf8a831cc982cda9b91e84c5600c631af5b2robertphillips@google.com if (ub_indices[i] > max_ub) 71d6bbbf8a831cc982cda9b91e84c5600c631af5b2robertphillips@google.com max_ub = ub_indices[i]; 72ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel return max_ub; 73498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips } 74498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips default: 75498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips return 0; 76498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips } 77d364554bcfd391c3b6111af8bff963a35ab87ba7robertphillips@google.com} 78d364554bcfd391c3b6111af8bff963a35ab87ba7robertphillips@google.com 79d6bbbf8a831cc982cda9b91e84c5600c631af5b2robertphillips@google.com 806bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon/* Just translate the arrayobj into a sane layout. 81a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips */ 82a106c627532ad669cf7d879955ae8ea6a53233c1robertphillipsstatic void bind_array_obj( GLcontext *ctx ) 83498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips{ 84498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips struct vbo_exec_context *exec = &vbo_context(ctx)->exec; 85a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips GLuint i; 86498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips 87498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips /* TODO: Fix the ArrayObj struct to keep legacy arrays in an array 88a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips * rather than as individual named arrays. Then this function can 89a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips * go away. 90498d7ac86bfb45bdfc8f9aa7424f7236235987b5robertphillips */ 91a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips exec->array.legacy_array[VERT_ATTRIB_POS] = &ctx->Array.ArrayObj->Vertex; 92a106c627532ad669cf7d879955ae8ea6a53233c1robertphillips exec->array.legacy_array[VERT_ATTRIB_NORMAL] = &ctx->Array.ArrayObj->Normal; 936bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon exec->array.legacy_array[VERT_ATTRIB_COLOR0] = &ctx->Array.ArrayObj->Color; 946bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon exec->array.legacy_array[VERT_ATTRIB_COLOR1] = &ctx->Array.ArrayObj->SecondaryColor; 95ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel exec->array.legacy_array[VERT_ATTRIB_FOG] = &ctx->Array.ArrayObj->FogCoord; 9679bd2aee8ca328b688c8d421973f96bcd13fd12degdaniel exec->array.legacy_array[VERT_ATTRIB_COLOR_INDEX] = &ctx->Array.ArrayObj->Index; 9779bd2aee8ca328b688c8d421973f96bcd13fd12degdaniel exec->array.legacy_array[VBO_ATTRIB_EDGEFLAG] = &ctx->Array.ArrayObj->EdgeFlag; 9879bd2aee8ca328b688c8d421973f96bcd13fd12degdaniel 9979bd2aee8ca328b688c8d421973f96bcd13fd12degdaniel for (i = 0; i < 8; i++) 10079bd2aee8ca328b688c8d421973f96bcd13fd12degdaniel exec->array.legacy_array[VBO_ATTRIB_TEX0 + i] = &ctx->Array.ArrayObj->TexCoord[i]; 101ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel 102ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel for (i = 0; i < VERT_ATTRIB_MAX; i++) 103ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel exec->array.generic_array[i] = &ctx->Array.ArrayObj->VertexAttrib[i]; 104ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel 105ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel exec->array.array_obj = ctx->Array.ArrayObj->Name; 106ec00d94199fad7723b5987b86c1abef8ddafe2d8egdaniel} 1076bc1b5fab8554a9cb643277b4867965dd4535cd6bsalomon 108static void recalculate_input_bindings( GLcontext *ctx ) 109{ 110 struct vbo_context *vbo = vbo_context(ctx); 111 struct vbo_exec_context *exec = &vbo->exec; 112 const struct gl_client_array **inputs = &exec->array.inputs[0]; 113 GLuint i; 114 115 exec->array.program_mode = get_program_mode(ctx); 116 exec->array.enabled_flags = ctx->Array.ArrayObj->_Enabled; 117 118 /* TODO: Get rid of NV_program (please!). 119 */ 120 switch (exec->array.program_mode) { 121 case VP_NONE: 122 /* When no vertex program is active, we put the material values 123 * into the generic slots. This is the only situation where 124 * material values are available as per-vertex attributes. 125 */ 126 for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { 127 if (exec->array.legacy_array[i]->Enabled) 128 inputs[i] = exec->array.legacy_array[i]; 129 else 130 inputs[i] = &vbo->legacy_currval[i]; 131 } 132 133 for (i = 0; i < MAT_ATTRIB_MAX; i++) { 134 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->mat_currval[i]; 135 } 136 break; 137 case VP_NV: 138 /* NV_vertex_program - attribute arrays alias and override 139 * conventional, legacy arrays. No materials, and the generic 140 * slots are vacant. 141 */ 142 for (i = 0; i <= VERT_ATTRIB_TEX7; i++) { 143 if (exec->array.generic_array[i]->Enabled) 144 inputs[i] = exec->array.generic_array[i]; 145 else if (exec->array.legacy_array[i]->Enabled) 146 inputs[i] = exec->array.legacy_array[i]; 147 else 148 inputs[i] = &vbo->legacy_currval[i]; 149 } 150 break; 151 case VP_ARB: 152 /* ARB_vertex_program - Only the attribute zero (position) array 153 * aliases and overrides the legacy position array. 154 * 155 * Otherwise, legacy attributes available in the legacy slots, 156 * generic attributes in the generic slots and materials are not 157 * available as per-vertex attributes. 158 */ 159 if (exec->array.generic_array[0]->Enabled) 160 inputs[0] = exec->array.generic_array[0]; 161 else if (exec->array.legacy_array[0]->Enabled) 162 inputs[0] = exec->array.legacy_array[0]; 163 else 164 inputs[0] = &vbo->legacy_currval[0]; 165 166 167 for (i = 1; i <= VERT_ATTRIB_TEX7; i++) { 168 if (exec->array.legacy_array[i]->Enabled) 169 inputs[i] = exec->array.legacy_array[i]; 170 else 171 inputs[i] = &vbo->legacy_currval[i]; 172 } 173 174 for (i = 0; i < 16; i++) { 175 if (exec->array.generic_array[0]->Enabled) 176 inputs[VERT_ATTRIB_GENERIC0 + i] = exec->array.generic_array[i]; 177 else 178 inputs[VERT_ATTRIB_GENERIC0 + i] = &vbo->generic_currval[i]; 179 } 180 break; 181 } 182} 183 184static void bind_arrays( GLcontext *ctx ) 185{ 186#if 0 187 if (ctx->Array.ArrayObj.Name != exec->array.array_obj) { 188 bind_array_obj(ctx); 189 recalculate_input_bindings(ctx); 190 } 191 else if (exec->array.program_mode != get_program_mode(ctx) || 192 exec->array.enabled_flags != ctx->Array.ArrayObj->_Enabled) { 193 194 recalculate_input_bindings(ctx); 195 } 196#else 197 bind_array_obj(ctx); 198 recalculate_input_bindings(ctx); 199#endif 200} 201 202 203 204/*********************************************************************** 205 * API functions. 206 */ 207 208static void GLAPIENTRY 209vbo_exec_DrawArrays(GLenum mode, GLint start, GLsizei count) 210{ 211 GET_CURRENT_CONTEXT(ctx); 212 struct vbo_context *vbo = vbo_context(ctx); 213 struct vbo_exec_context *exec = &vbo->exec; 214 struct _mesa_prim prim[1]; 215 216 if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) 217 return; 218 219 FLUSH_CURRENT( ctx, 0 ); 220 221 if (ctx->NewState) 222 _mesa_update_state( ctx ); 223 224 bind_arrays( ctx ); 225 226 prim[0].begin = 1; 227 prim[0].end = 1; 228 prim[0].weak = 0; 229 prim[0].pad = 0; 230 231 if (exec->array.inputs[0]->BufferObj->Name) { 232 /* Use vertex attribute as a hint to tell us if we expect all 233 * arrays to be in VBO's and if so, don't worry about avoiding 234 * the upload of elements < start. 235 */ 236 prim[0].mode = mode; 237 prim[0].start = start; 238 prim[0].count = count; 239 prim[0].indexed = 0; 240 241 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, 0, start + count ); 242 } 243 else { 244 /* If not using VBO's, we don't want to upload any more elements 245 * than necessary from the arrays as they will not be valid next 246 * time the application tries to draw with them. 247 */ 248 prim[0].mode = mode; 249 prim[0].start = 0; 250 prim[0].count = count; 251 prim[0].indexed = 0; 252 253 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, NULL, start, start + count ); 254 } 255} 256 257 258 259static void GLAPIENTRY 260vbo_exec_DrawRangeElements(GLenum mode, 261 GLuint start, GLuint end, 262 GLsizei count, GLenum type, const GLvoid *indices) 263{ 264 GET_CURRENT_CONTEXT(ctx); 265 struct vbo_context *vbo = vbo_context(ctx); 266 struct vbo_exec_context *exec = &vbo->exec; 267 struct _mesa_index_buffer ib; 268 struct _mesa_prim prim[1]; 269 270 if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, type, indices )) 271 return; 272 273 FLUSH_CURRENT( ctx, 0 ); 274 275 if (ctx->NewState) 276 _mesa_update_state( ctx ); 277 278 ib.count = count; 279 ib.type = type; 280 ib.obj = ctx->Array.ElementArrayBufferObj; 281 ib.ptr = indices; 282 283 if (ctx->Array.ElementArrayBufferObj->Name) { 284 /* Use the fact that indices are in a VBO as a hint that the 285 * program has put all the arrays in VBO's and we don't have to 286 * worry about performance implications of start > 0. 287 * 288 * XXX: consider passing start as min_index to draw_prims instead. 289 */ 290 ib.rebase = 0; 291 } 292 else { 293 ib.rebase = start; 294 } 295 296 prim[0].begin = 1; 297 prim[0].end = 1; 298 prim[0].weak = 0; 299 prim[0].pad = 0; 300 prim[0].mode = mode; 301 prim[0].start = 0; 302 prim[0].count = count; 303 prim[0].indexed = 1; 304 305 vbo->draw_prims( ctx, exec->array.inputs, prim, 1, &ib, ib.rebase, end+1 ); 306} 307 308 309static void GLAPIENTRY 310vbo_exec_DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices) 311{ 312 GET_CURRENT_CONTEXT(ctx); 313 GLuint max_index; 314 315 if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) 316 return; 317 318 if (ctx->Array.ElementArrayBufferObj->Name) { 319 const GLvoid *map = ctx->Driver.MapBuffer(ctx, 320 GL_ELEMENT_ARRAY_BUFFER_ARB, 321 GL_DYNAMIC_READ_ARB, 322 ctx->Array.ElementArrayBufferObj); 323 324 max_index = get_max_index(count, type, ADD_POINTERS(map, indices)); 325 326 ctx->Driver.UnmapBuffer(ctx, 327 GL_ELEMENT_ARRAY_BUFFER_ARB, 328 ctx->Array.ElementArrayBufferObj); 329 } 330 else { 331 max_index = get_max_index(count, type, indices); 332 } 333 334 vbo_exec_DrawRangeElements(mode, 0, max_index, count, type, indices); 335} 336 337 338/*********************************************************************** 339 * Initialization 340 */ 341 342 343 344 345void vbo_exec_array_init( struct vbo_exec_context *exec ) 346{ 347 GLcontext *ctx = exec->ctx; 348 349#if 1 350 exec->vtxfmt.DrawArrays = vbo_exec_DrawArrays; 351 exec->vtxfmt.DrawElements = vbo_exec_DrawElements; 352 exec->vtxfmt.DrawRangeElements = vbo_exec_DrawRangeElements; 353#else 354 exec->vtxfmt.DrawArrays = _mesa_noop_DrawArrays; 355 exec->vtxfmt.DrawElements = _mesa_noop_DrawElements; 356 exec->vtxfmt.DrawRangeElements = _mesa_noop_DrawRangeElements; 357#endif 358 359 exec->array.index_obj = ctx->Driver.NewBufferObject(ctx, 1, GL_ARRAY_BUFFER_ARB); 360} 361 362 363void vbo_exec_array_destroy( struct vbo_exec_context *exec ) 364{ 365 GLcontext *ctx = exec->ctx; 366 367 ctx->Driver.DeleteBuffer(ctx, exec->array.index_obj); 368} 369