• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/imports.h"
29 #include "main/mtypes.h"
30 #include "main/api_arrayelt.h"
31 #include "main/bufferobj.h"
32 #include "math/m_eval.h"
33 #include "vbo.h"
34 #include "vbo_context.h"
35 
36 
check_size(const GLfloat * attr)37 static GLuint check_size( const GLfloat *attr )
38 {
39    if (attr[3] != 1.0F) return 4;
40    if (attr[2] != 0.0F) return 3;
41    if (attr[1] != 0.0F) return 2;
42    return 1;
43 }
44 
45 
46 /**
47  * Helper for initializing a vertex array.
48  */
49 static void
init_array(struct gl_context * ctx,struct gl_vertex_array * cl,unsigned size,const void * pointer)50 init_array(struct gl_context *ctx, struct gl_vertex_array *cl,
51            unsigned size, const void *pointer)
52 {
53    memset(cl, 0, sizeof(*cl));
54 
55    cl->Size = size;
56    cl->Type = GL_FLOAT;
57    cl->Format = GL_RGBA;
58    cl->StrideB = 0;
59    cl->_ElementSize = cl->Size * sizeof(GLfloat);
60    cl->Ptr = pointer;
61 
62    _mesa_reference_buffer_object(ctx, &cl->BufferObj,
63                                  ctx->Shared->NullBufferObj);
64 }
65 
66 
67 /**
68  * Set up the vbo->currval arrays to point at the context's current
69  * vertex attributes (with strides = 0).
70  */
init_legacy_currval(struct gl_context * ctx)71 static void init_legacy_currval(struct gl_context *ctx)
72 {
73    struct vbo_context *vbo = vbo_context(ctx);
74    GLuint i;
75 
76    /* Set up a constant (StrideB == 0) array for each current
77     * attribute:
78     */
79    for (i = 0; i < VERT_ATTRIB_FF_MAX; i++) {
80       struct gl_vertex_array *cl = &vbo->currval[VERT_ATTRIB_FF(i)];
81 
82       init_array(ctx, cl,
83                  check_size(ctx->Current.Attrib[i]),
84                  ctx->Current.Attrib[i]);
85    }
86 }
87 
88 
init_generic_currval(struct gl_context * ctx)89 static void init_generic_currval(struct gl_context *ctx)
90 {
91    struct vbo_context *vbo = vbo_context(ctx);
92    GLuint i;
93 
94    for (i = 0; i < VERT_ATTRIB_GENERIC_MAX; i++) {
95       struct gl_vertex_array *cl = &vbo->currval[VBO_ATTRIB_GENERIC0 + i];
96 
97       init_array(ctx, cl, 1, ctx->Current.Attrib[VERT_ATTRIB_GENERIC0 + i]);
98    }
99 }
100 
101 
init_mat_currval(struct gl_context * ctx)102 static void init_mat_currval(struct gl_context *ctx)
103 {
104    struct vbo_context *vbo = vbo_context(ctx);
105    GLuint i;
106 
107    /* Set up a constant (StrideB == 0) array for each current
108     * attribute:
109     */
110    for (i = 0; i < MAT_ATTRIB_MAX; i++) {
111       struct gl_vertex_array *cl =
112          &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT + i];
113       unsigned size;
114 
115       /* Size is fixed for the material attributes, for others will
116        * be determined at runtime:
117        */
118       switch (i) {
119       case MAT_ATTRIB_FRONT_SHININESS:
120       case MAT_ATTRIB_BACK_SHININESS:
121          size = 1;
122          break;
123       case MAT_ATTRIB_FRONT_INDEXES:
124       case MAT_ATTRIB_BACK_INDEXES:
125          size = 3;
126          break;
127       default:
128          size = 4;
129          break;
130       }
131 
132       init_array(ctx, cl, size, ctx->Light.Material.Attrib[i]);
133    }
134 }
135 
136 static void
vbo_draw_indirect_prims(struct gl_context * ctx,GLuint mode,struct gl_buffer_object * indirect_data,GLsizeiptr indirect_offset,unsigned draw_count,unsigned stride,struct gl_buffer_object * indirect_params,GLsizeiptr indirect_params_offset,const struct _mesa_index_buffer * ib)137 vbo_draw_indirect_prims(struct gl_context *ctx,
138                         GLuint mode,
139                         struct gl_buffer_object *indirect_data,
140                         GLsizeiptr indirect_offset,
141                         unsigned draw_count,
142                         unsigned stride,
143                         struct gl_buffer_object *indirect_params,
144                         GLsizeiptr indirect_params_offset,
145                         const struct _mesa_index_buffer *ib)
146 {
147    struct vbo_context *vbo = vbo_context(ctx);
148    struct _mesa_prim *prim;
149    GLsizei i;
150 
151    prim = calloc(draw_count, sizeof(*prim));
152    if (prim == NULL) {
153       _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDraw%sIndirect%s",
154                   (draw_count > 1) ? "Multi" : "",
155                   ib ? "Elements" : "Arrays",
156                   indirect_params ? "CountARB" : "");
157       return;
158    }
159 
160    prim[0].begin = 1;
161    prim[draw_count - 1].end = 1;
162    for (i = 0; i < draw_count; ++i, indirect_offset += stride) {
163       prim[i].mode = mode;
164       prim[i].indexed = !!ib;
165       prim[i].indirect_offset = indirect_offset;
166       prim[i].is_indirect = 1;
167       prim[i].draw_id = i;
168    }
169 
170    vbo->draw_prims(ctx, prim, draw_count,
171                    ib, false, ~0, ~0,
172                    NULL, 0,
173                    ctx->DrawIndirectBuffer);
174 
175    free(prim);
176 }
177 
178 
_vbo_CreateContext(struct gl_context * ctx)179 GLboolean _vbo_CreateContext( struct gl_context *ctx )
180 {
181    struct vbo_context *vbo = CALLOC_STRUCT(vbo_context);
182 
183    ctx->vbo_context = vbo;
184 
185    /* Initialize the arrayelt helper
186     */
187    if (!ctx->aelt_context &&
188        !_ae_create_context( ctx )) {
189       return GL_FALSE;
190    }
191 
192    init_legacy_currval( ctx );
193    init_generic_currval( ctx );
194    init_mat_currval( ctx );
195    vbo_set_indirect_draw_func(ctx, vbo_draw_indirect_prims);
196 
197    /* Build mappings from VERT_ATTRIB -> VBO_ATTRIB depending on type
198     * of vertex program active.
199     */
200    {
201       GLuint i;
202 
203       /* identity mapping */
204       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_none); i++)
205 	 vbo->map_vp_none[i] = i;
206       /* map material attribs to generic slots */
207       for (i = 0; i < MAT_ATTRIB_MAX; i++)
208 	 vbo->map_vp_none[VERT_ATTRIB_GENERIC(i)]
209             = VBO_ATTRIB_MAT_FRONT_AMBIENT + i;
210 
211       for (i = 0; i < ARRAY_SIZE(vbo->map_vp_arb); i++)
212 	 vbo->map_vp_arb[i] = i;
213    }
214 
215 
216    /* Hook our functions into exec and compile dispatch tables.  These
217     * will pretty much be permanently installed, which means that the
218     * vtxfmt mechanism can be removed now.
219     */
220    vbo_exec_init( ctx );
221    if (ctx->API == API_OPENGL_COMPAT)
222       vbo_save_init( ctx );
223 
224    _math_init_eval();
225 
226    return GL_TRUE;
227 }
228 
229 
_vbo_InvalidateState(struct gl_context * ctx,GLbitfield new_state)230 void _vbo_InvalidateState( struct gl_context *ctx, GLbitfield new_state )
231 {
232    vbo_exec_invalidate_state(ctx, new_state);
233 }
234 
235 
_vbo_DestroyContext(struct gl_context * ctx)236 void _vbo_DestroyContext( struct gl_context *ctx )
237 {
238    struct vbo_context *vbo = vbo_context(ctx);
239 
240    if (ctx->aelt_context) {
241       _ae_destroy_context( ctx );
242       ctx->aelt_context = NULL;
243    }
244 
245    if (vbo) {
246       GLuint i;
247 
248       for (i = 0; i < VBO_ATTRIB_MAX; i++) {
249          _mesa_reference_buffer_object(ctx, &vbo->currval[i].BufferObj, NULL);
250       }
251 
252       vbo_exec_destroy(ctx);
253       if (ctx->API == API_OPENGL_COMPAT)
254          vbo_save_destroy(ctx);
255       free(vbo);
256       ctx->vbo_context = NULL;
257    }
258 }
259 
260 
vbo_set_draw_func(struct gl_context * ctx,vbo_draw_func func)261 void vbo_set_draw_func(struct gl_context *ctx, vbo_draw_func func)
262 {
263    struct vbo_context *vbo = vbo_context(ctx);
264    vbo->draw_prims = func;
265 }
266 
267 
vbo_set_indirect_draw_func(struct gl_context * ctx,vbo_indirect_draw_func func)268 void vbo_set_indirect_draw_func(struct gl_context *ctx,
269                                 vbo_indirect_draw_func func)
270 {
271    struct vbo_context *vbo = vbo_context(ctx);
272    vbo->draw_indirect_prims = func;
273 }
274