1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 * Authors: 25 * Keith Whitwell <keithw@vmware.com> 26 */ 27 28#include "main/errors.h" 29#include "main/bufferobj.h" 30#include "math/m_eval.h" 31#include "main/vtxfmt.h" 32#include "main/api_arrayelt.h" 33#include "main/arrayobj.h" 34#include "main/varray.h" 35#include "util/u_memory.h" 36#include "vbo.h" 37#include "vbo_private.h" 38 39 40static GLuint 41check_size(const GLfloat *attr) 42{ 43 if (attr[3] != 1.0F) 44 return 4; 45 if (attr[2] != 0.0F) 46 return 3; 47 if (attr[1] != 0.0F) 48 return 2; 49 return 1; 50} 51 52 53/** 54 * Helper for initializing a vertex array. 55 */ 56static void 57init_array(struct gl_context *ctx, struct gl_array_attributes *attrib, 58 unsigned size, const void *pointer) 59{ 60 memset(attrib, 0, sizeof(*attrib)); 61 62 vbo_set_vertex_format(&attrib->Format, size, GL_FLOAT); 63 attrib->Stride = 0; 64 attrib->Ptr = pointer; 65} 66 67 68/** 69 * Set up the vbo->currval arrays to point at the context's current 70 * vertex attributes (with strides = 0). 71 */ 72static void 73init_legacy_currval(struct gl_context *ctx) 74{ 75 struct vbo_context *vbo = vbo_context(ctx); 76 77 /* Set up a constant (Stride == 0) array for each current 78 * attribute: 79 */ 80 for (int attr = 0; attr < VERT_ATTRIB_MAX; attr++) { 81 if (VERT_BIT(attr) & VERT_BIT_GENERIC_ALL) 82 continue; 83 84 struct gl_array_attributes *attrib = &vbo->current[attr]; 85 86 init_array(ctx, attrib, check_size(ctx->Current.Attrib[attr]), 87 ctx->Current.Attrib[attr]); 88 } 89} 90 91 92static void 93init_generic_currval(struct gl_context *ctx) 94{ 95 struct vbo_context *vbo = vbo_context(ctx); 96 GLuint i; 97 98 for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) { 99 const unsigned attr = VBO_ATTRIB_GENERIC0 + i; 100 struct gl_array_attributes *attrib = &vbo->current[attr]; 101 102 init_array(ctx, attrib, 1, ctx->Current.Attrib[attr]); 103 } 104} 105 106 107static void 108init_mat_currval(struct gl_context *ctx) 109{ 110 struct vbo_context *vbo = vbo_context(ctx); 111 GLuint i; 112 113 /* Set up a constant (StrideB == 0) array for each current 114 * attribute: 115 */ 116 for (i = 0; i < MAT_ATTRIB_MAX; i++) { 117 const unsigned attr = VBO_ATTRIB_MAT_FRONT_AMBIENT + i; 118 struct gl_array_attributes *attrib = &vbo->current[attr]; 119 unsigned size; 120 121 /* Size is fixed for the material attributes, for others will 122 * be determined at runtime: 123 */ 124 switch (i) { 125 case MAT_ATTRIB_FRONT_SHININESS: 126 case MAT_ATTRIB_BACK_SHININESS: 127 size = 1; 128 break; 129 case MAT_ATTRIB_FRONT_INDEXES: 130 case MAT_ATTRIB_BACK_INDEXES: 131 size = 3; 132 break; 133 default: 134 size = 4; 135 break; 136 } 137 138 init_array(ctx, attrib, size, ctx->Light.Material.Attrib[i]); 139 } 140} 141 142 143void 144_vbo_install_exec_vtxfmt(struct gl_context *ctx) 145{ 146 struct vbo_context *vbo = vbo_context(ctx); 147 148 _mesa_install_exec_vtxfmt(ctx, &vbo->exec.vtxfmt); 149} 150 151 152void 153vbo_exec_update_eval_maps(struct gl_context *ctx) 154{ 155 struct vbo_context *vbo = vbo_context(ctx); 156 157 vbo->exec.eval.recalculate_maps = GL_TRUE; 158} 159 160 161GLboolean 162_vbo_CreateContext(struct gl_context *ctx, bool use_buffer_objects) 163{ 164 struct vbo_context *vbo = &ctx->vbo_context; 165 166 memset(vbo, 0, sizeof(*vbo)); 167 168 vbo->binding.Offset = 0; 169 vbo->binding.Stride = 0; 170 vbo->binding.InstanceDivisor = 0; 171 172 init_legacy_currval(ctx); 173 init_generic_currval(ctx); 174 init_mat_currval(ctx); 175 176 /* make sure all VBO_ATTRIB_ values can fit in an unsigned byte */ 177 STATIC_ASSERT(VBO_ATTRIB_MAX <= 255); 178 179 /* Hook our functions into exec and compile dispatch tables. These 180 * will pretty much be permanently installed, which means that the 181 * vtxfmt mechanism can be removed now. 182 */ 183 vbo_exec_init(ctx, use_buffer_objects); 184 if (ctx->API == API_OPENGL_COMPAT) 185 vbo_save_init(ctx); 186 187 vbo->VAO = _mesa_new_vao(ctx, ~((GLuint)0)); 188 /* The exec VAO assumes to have all arributes bound to binding 0 */ 189 for (unsigned i = 0; i < VERT_ATTRIB_MAX; ++i) 190 _mesa_vertex_attrib_binding(ctx, vbo->VAO, i, 0); 191 192 _math_init_eval(); 193 194 return GL_TRUE; 195} 196 197 198void 199_vbo_DestroyContext(struct gl_context *ctx) 200{ 201 struct vbo_context *vbo = vbo_context(ctx); 202 203 if (vbo) { 204 _mesa_reference_buffer_object(ctx, &vbo->binding.BufferObj, NULL); 205 206 vbo_exec_destroy(ctx); 207 if (ctx->API == API_OPENGL_COMPAT) 208 vbo_save_destroy(ctx); 209 _mesa_reference_vao(ctx, &vbo->VAO, NULL); 210 } 211} 212 213 214const struct gl_array_attributes * 215_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr) 216{ 217 const struct vbo_context *vbo = vbo_context_const(ctx); 218 const gl_vertex_processing_mode vmp = ctx->VertexProgram._VPMode; 219 return &vbo->current[_vbo_attribute_alias_map[vmp][attr]]; 220} 221 222 223const struct gl_vertex_buffer_binding * 224_vbo_current_binding(const struct gl_context *ctx) 225{ 226 const struct vbo_context *vbo = vbo_context_const(ctx); 227 return &vbo->binding; 228} 229