1848b8605Smrg/*
2848b8605Smrg * Mesa 3-D graphics library
3848b8605Smrg *
4848b8605Smrg * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
5848b8605Smrg *
6848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a
7848b8605Smrg * copy of this software and associated documentation files (the "Software"),
8848b8605Smrg * to deal in the Software without restriction, including without limitation
9848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the
11848b8605Smrg * Software is furnished to do so, subject to the following conditions:
12848b8605Smrg *
13848b8605Smrg * The above copyright notice and this permission notice shall be included
14848b8605Smrg * in all copies or substantial portions of the Software.
15848b8605Smrg *
16848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17848b8605Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20848b8605Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21848b8605Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22848b8605Smrg * OTHER DEALINGS IN THE SOFTWARE.
23848b8605Smrg *
24848b8605Smrg * Authors:
25848b8605Smrg *    Keith Whitwell <keithw@vmware.com>
26848b8605Smrg */
27848b8605Smrg
28b8e80941Smrg#include "main/errors.h"
29848b8605Smrg#include "main/bufferobj.h"
30848b8605Smrg#include "math/m_eval.h"
31b8e80941Smrg#include "main/vtxfmt.h"
32b8e80941Smrg#include "main/api_arrayelt.h"
33b8e80941Smrg#include "main/arrayobj.h"
34b8e80941Smrg#include "main/varray.h"
35848b8605Smrg#include "vbo.h"
36b8e80941Smrg#include "vbo_private.h"
37b8e80941Smrg
38b8e80941Smrg
39b8e80941Smrgstatic GLuint
40b8e80941Smrgcheck_size(const GLfloat *attr)
41b8e80941Smrg{
42b8e80941Smrg   if (attr[3] != 1.0F)
43b8e80941Smrg      return 4;
44b8e80941Smrg   if (attr[2] != 0.0F)
45b8e80941Smrg      return 3;
46b8e80941Smrg   if (attr[1] != 0.0F)
47b8e80941Smrg      return 2;
48b8e80941Smrg   return 1;
49b8e80941Smrg}
50848b8605Smrg
51848b8605Smrg
52b8e80941Smrg/**
53b8e80941Smrg * Helper for initializing a vertex array.
54b8e80941Smrg */
55b8e80941Smrgstatic void
56b8e80941Smrginit_array(struct gl_context *ctx, struct gl_array_attributes *attrib,
57b8e80941Smrg           unsigned size, const void *pointer)
58848b8605Smrg{
59b8e80941Smrg   memset(attrib, 0, sizeof(*attrib));
60b8e80941Smrg
61b8e80941Smrg   vbo_set_vertex_format(&attrib->Format, size, GL_FLOAT);
62b8e80941Smrg   attrib->Stride = 0;
63b8e80941Smrg   attrib->Ptr = pointer;
64848b8605Smrg}
65848b8605Smrg
66848b8605Smrg
67b8e80941Smrg/**
68b8e80941Smrg * Set up the vbo->currval arrays to point at the context's current
69b8e80941Smrg * vertex attributes (with strides = 0).
70b8e80941Smrg */
71b8e80941Smrgstatic void
72b8e80941Smrginit_legacy_currval(struct gl_context *ctx)
73848b8605Smrg{
74848b8605Smrg   struct vbo_context *vbo = vbo_context(ctx);
75848b8605Smrg   GLuint i;
76848b8605Smrg
77b8e80941Smrg   /* Set up a constant (Stride == 0) array for each current
78848b8605Smrg    * attribute:
79848b8605Smrg    */
80848b8605Smrg   for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
81b8e80941Smrg      const unsigned attr = VERT_ATTRIB_FF(i);
82b8e80941Smrg      struct gl_array_attributes *attrib = &vbo->current[attr];
83848b8605Smrg
84b8e80941Smrg      init_array(ctx, attrib, check_size(ctx->Current.Attrib[attr]),
85b8e80941Smrg                 ctx->Current.Attrib[attr]);
86848b8605Smrg   }
87848b8605Smrg}
88848b8605Smrg
89848b8605Smrg
90b8e80941Smrgstatic void
91b8e80941Smrginit_generic_currval(struct gl_context *ctx)
92848b8605Smrg{
93848b8605Smrg   struct vbo_context *vbo = vbo_context(ctx);
94848b8605Smrg   GLuint i;
95848b8605Smrg
96848b8605Smrg   for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
97b8e80941Smrg      const unsigned attr = VBO_ATTRIB_GENERIC0 + i;
98b8e80941Smrg      struct gl_array_attributes *attrib = &vbo->current[attr];
99848b8605Smrg
100b8e80941Smrg      init_array(ctx, attrib, 1, ctx->Current.Attrib[attr]);
101848b8605Smrg   }
102848b8605Smrg}
103848b8605Smrg
104848b8605Smrg
105b8e80941Smrgstatic void
106b8e80941Smrginit_mat_currval(struct gl_context *ctx)
107848b8605Smrg{
108848b8605Smrg   struct vbo_context *vbo = vbo_context(ctx);
109848b8605Smrg   GLuint i;
110848b8605Smrg
111848b8605Smrg   /* Set up a constant (StrideB == 0) array for each current
112848b8605Smrg    * attribute:
113848b8605Smrg    */
114b8e80941Smrg   for (i = 0; i < MAT_ATTRIB_MAX; i++) {
115b8e80941Smrg      const unsigned attr = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
116b8e80941Smrg      struct gl_array_attributes *attrib = &vbo->current[attr];
117b8e80941Smrg      unsigned size;
118848b8605Smrg
119848b8605Smrg      /* Size is fixed for the material attributes, for others will
120848b8605Smrg       * be determined at runtime:
121848b8605Smrg       */
122b8e80941Smrg      switch (i) {
123848b8605Smrg      case MAT_ATTRIB_FRONT_SHININESS:
124848b8605Smrg      case MAT_ATTRIB_BACK_SHININESS:
125b8e80941Smrg         size = 1;
126b8e80941Smrg         break;
127848b8605Smrg      case MAT_ATTRIB_FRONT_INDEXES:
128848b8605Smrg      case MAT_ATTRIB_BACK_INDEXES:
129b8e80941Smrg         size = 3;
130b8e80941Smrg         break;
131848b8605Smrg      default:
132b8e80941Smrg         size = 4;
133b8e80941Smrg         break;
134848b8605Smrg      }
135848b8605Smrg
136b8e80941Smrg      init_array(ctx, attrib, size, ctx->Light.Material.Attrib[i]);
137848b8605Smrg   }
138848b8605Smrg}
139848b8605Smrg
140848b8605Smrg
141b8e80941Smrgvoid
142b8e80941Smrg_vbo_install_exec_vtxfmt(struct gl_context *ctx)
143848b8605Smrg{
144b8e80941Smrg   struct vbo_context *vbo = vbo_context(ctx);
145848b8605Smrg
146b8e80941Smrg   _mesa_install_exec_vtxfmt(ctx, &vbo->exec.vtxfmt);
147b8e80941Smrg}
148848b8605Smrg
149848b8605Smrg
150b8e80941Smrgvoid
151b8e80941Smrgvbo_exec_invalidate_state(struct gl_context *ctx)
152b8e80941Smrg{
153b8e80941Smrg   struct vbo_context *vbo = vbo_context(ctx);
154b8e80941Smrg   struct vbo_exec_context *exec = &vbo->exec;
155b8e80941Smrg
156b8e80941Smrg   if (ctx->NewState & _NEW_EVAL)
157b8e80941Smrg      exec->eval.recalculate_maps = GL_TRUE;
158b8e80941Smrg}
159b8e80941Smrg
160848b8605Smrg
161b8e80941SmrgGLboolean
162b8e80941Smrg_vbo_CreateContext(struct gl_context *ctx)
163b8e80941Smrg{
164b8e80941Smrg   struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
165b8e80941Smrg
166b8e80941Smrg   ctx->vbo_context = vbo;
167b8e80941Smrg
168b8e80941Smrg   vbo->binding.Offset = 0;
169b8e80941Smrg   vbo->binding.Stride = 0;
170b8e80941Smrg   vbo->binding.InstanceDivisor = 0;
171b8e80941Smrg   _mesa_reference_buffer_object(ctx, &vbo->binding.BufferObj,
172b8e80941Smrg                                 ctx->Shared->NullBufferObj);
173b8e80941Smrg   init_legacy_currval(ctx);
174b8e80941Smrg   init_generic_currval(ctx);
175b8e80941Smrg   init_mat_currval(ctx);
176848b8605Smrg
177b8e80941Smrg   /* make sure all VBO_ATTRIB_ values can fit in an unsigned byte */
178b8e80941Smrg   STATIC_ASSERT(VBO_ATTRIB_MAX <= 255);
179848b8605Smrg
180848b8605Smrg   /* Hook our functions into exec and compile dispatch tables.  These
181848b8605Smrg    * will pretty much be permanently installed, which means that the
182848b8605Smrg    * vtxfmt mechanism can be removed now.
183848b8605Smrg    */
184b8e80941Smrg   vbo_exec_init(ctx);
185848b8605Smrg   if (ctx->API == API_OPENGL_COMPAT)
186b8e80941Smrg      vbo_save_init(ctx);
187b8e80941Smrg
188b8e80941Smrg   vbo->VAO = _mesa_new_vao(ctx, ~((GLuint)0));
189b8e80941Smrg   /* The exec VAO assumes to have all arributes bound to binding 0 */
190b8e80941Smrg   for (unsigned i = 0; i < VERT_ATTRIB_MAX; ++i)
191b8e80941Smrg      _mesa_vertex_attrib_binding(ctx, vbo->VAO, i, 0);
192848b8605Smrg
193848b8605Smrg   _math_init_eval();
194848b8605Smrg
195848b8605Smrg   return GL_TRUE;
196848b8605Smrg}
197848b8605Smrg
198848b8605Smrg
199b8e80941Smrgvoid
200b8e80941Smrg_vbo_DestroyContext(struct gl_context *ctx)
201848b8605Smrg{
202848b8605Smrg   struct vbo_context *vbo = vbo_context(ctx);
203848b8605Smrg
204848b8605Smrg   if (vbo) {
205848b8605Smrg
206b8e80941Smrg      _mesa_reference_buffer_object(ctx, &vbo->binding.BufferObj, NULL);
207848b8605Smrg
208848b8605Smrg      vbo_exec_destroy(ctx);
209848b8605Smrg      if (ctx->API == API_OPENGL_COMPAT)
210848b8605Smrg         vbo_save_destroy(ctx);
211b8e80941Smrg      _mesa_reference_vao(ctx, &vbo->VAO, NULL);
212848b8605Smrg      free(vbo);
213848b8605Smrg      ctx->vbo_context = NULL;
214848b8605Smrg   }
215848b8605Smrg}
216848b8605Smrg
217848b8605Smrg
218b8e80941Smrgconst struct gl_array_attributes *
219b8e80941Smrg_vbo_current_attrib(const struct gl_context *ctx, gl_vert_attrib attr)
220848b8605Smrg{
221b8e80941Smrg   const struct vbo_context *vbo = vbo_context_const(ctx);
222b8e80941Smrg   const gl_vertex_processing_mode vmp = ctx->VertexProgram._VPMode;
223b8e80941Smrg   return &vbo->current[_vbo_attribute_alias_map[vmp][attr]];
224848b8605Smrg}
225848b8605Smrg
226b8e80941Smrg
227b8e80941Smrgconst struct gl_vertex_buffer_binding *
228b8e80941Smrg_vbo_current_binding(const struct gl_context *ctx)
229b8e80941Smrg{
230b8e80941Smrg   const struct vbo_context *vbo = vbo_context_const(ctx);
231b8e80941Smrg   return &vbo->binding;
232b8e80941Smrg}
233