1 | /* $Id: cva.c,v 1.2 2000-05-23 20:40:27 jeroen Exp $ */
|
---|
2 |
|
---|
3 | /*
|
---|
4 | * Mesa 3-D graphics library
|
---|
5 | * Version: 3.3
|
---|
6 | *
|
---|
7 | * Copyright (C) 1999 Brian Paul All Rights Reserved.
|
---|
8 | *
|
---|
9 | * Permission is hereby granted, free of charge, to any person obtaining a
|
---|
10 | * copy of this software and associated documentation files (the "Software"),
|
---|
11 | * to deal in the Software without restriction, including without limitation
|
---|
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
---|
13 | * and/or sell copies of the Software, and to permit persons to whom the
|
---|
14 | * Software is furnished to do so, subject to the following conditions:
|
---|
15 | *
|
---|
16 | * The above copyright notice and this permission notice shall be included
|
---|
17 | * in all copies or substantial portions of the Software.
|
---|
18 | *
|
---|
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
---|
20 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
---|
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
---|
22 | * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
---|
23 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
---|
24 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
---|
25 | */
|
---|
26 |
|
---|
27 | /* Mesa CVA implementation.
|
---|
28 | * Copyright (C) 1999 Keith Whitwell
|
---|
29 | */
|
---|
30 |
|
---|
31 | #include "glheader.h"
|
---|
32 | #include "types.h"
|
---|
33 | #include "cva.h"
|
---|
34 | #include "mem.h"
|
---|
35 | #include "context.h"
|
---|
36 | #include "macros.h"
|
---|
37 | #include "pipeline.h"
|
---|
38 | #include "varray.h"
|
---|
39 | #include "vbcull.h"
|
---|
40 | #include "vbrender.h"
|
---|
41 | #include "vbxform.h"
|
---|
42 | #include "vector.h"
|
---|
43 |
|
---|
44 | /* Mesa CVA implementation.
|
---|
45 | * Copyright (C) 1999 Keith Whitwell
|
---|
46 | */
|
---|
47 |
|
---|
48 | static void copy_clipmask( GLubyte *dest, GLubyte *ormask, GLubyte *andmask,
|
---|
49 | const GLubyte *src,
|
---|
50 | const GLuint *elt, GLuint nr )
|
---|
51 | {
|
---|
52 | GLuint i;
|
---|
53 | GLubyte o = *ormask;
|
---|
54 | GLubyte a = *andmask;
|
---|
55 |
|
---|
56 | for (i = 0 ; i < nr ; i++) {
|
---|
57 | GLubyte t = src[elt[i]];
|
---|
58 | dest[i] = t;
|
---|
59 | o |= t;
|
---|
60 | a &= t;
|
---|
61 | }
|
---|
62 |
|
---|
63 | *ormask = o;
|
---|
64 | *andmask = a;
|
---|
65 | }
|
---|
66 |
|
---|
67 | static void translate_4f( GLvector4f *dest,
|
---|
68 | CONST GLvector4f *src,
|
---|
69 | CONST GLuint elt[],
|
---|
70 | GLuint nr )
|
---|
71 | {
|
---|
72 | GLuint i;
|
---|
73 | GLfloat (*from)[4] = (GLfloat (*)[4])src->start;
|
---|
74 | GLfloat (*to)[4] = (GLfloat (*)[4])dest->start;
|
---|
75 | GLuint stride = src->stride;
|
---|
76 |
|
---|
77 | if (stride == 4 * sizeof(GLfloat)) {
|
---|
78 | for (i = 0 ; i < nr ; i++)
|
---|
79 | COPY_4FV( to[i], from[elt[i]] );
|
---|
80 | } else {
|
---|
81 | for (i = 0 ; i < nr ; i++) {
|
---|
82 | CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
|
---|
83 | COPY_4FV( to[i], (GLfloat *)f );
|
---|
84 | }
|
---|
85 | }
|
---|
86 |
|
---|
87 | dest->size = src->size;
|
---|
88 | dest->flags |= (src->flags & VEC_SIZE_4);
|
---|
89 | dest->count = nr;
|
---|
90 | }
|
---|
91 |
|
---|
92 | static void translate_3f( GLvector3f *dest,
|
---|
93 | CONST GLvector3f *src,
|
---|
94 | CONST GLuint elt[],
|
---|
95 | GLuint nr )
|
---|
96 | {
|
---|
97 | GLuint i;
|
---|
98 | GLfloat (*from)[3] = (GLfloat (*)[3])src->start;
|
---|
99 | GLfloat (*to)[3] = (GLfloat (*)[3])dest->start;
|
---|
100 | GLuint stride = src->stride;
|
---|
101 |
|
---|
102 | if (stride == 3 * sizeof(GLfloat)) {
|
---|
103 | for (i = 0 ; i < nr ; i++)
|
---|
104 | COPY_3FV( to[i], from[elt[i]] );
|
---|
105 | } else {
|
---|
106 | for (i = 0 ; i < nr ; i++) {
|
---|
107 | CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
|
---|
108 | COPY_3FV( to[i], (GLfloat *)f );
|
---|
109 | }
|
---|
110 | }
|
---|
111 |
|
---|
112 | dest->count = nr;
|
---|
113 | }
|
---|
114 |
|
---|
115 | static void translate_4ub( GLvector4ub *dest,
|
---|
116 | CONST GLvector4ub *src,
|
---|
117 | GLuint elt[],
|
---|
118 | GLuint nr )
|
---|
119 | {
|
---|
120 | GLuint i;
|
---|
121 | GLubyte (*from)[4] = (GLubyte (*)[4])src->start;
|
---|
122 | GLubyte (*to)[4] = (GLubyte (*)[4])dest->start;
|
---|
123 | GLuint stride = src->stride;
|
---|
124 |
|
---|
125 | if (stride == 4 * sizeof(GLubyte)) {
|
---|
126 | for (i = 0 ; i < nr ; i++)
|
---|
127 | COPY_4UBV( to[i], from[elt[i]]);
|
---|
128 | } else {
|
---|
129 | for (i = 0 ; i < nr ; i++) {
|
---|
130 | CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
|
---|
131 | COPY_4UBV( to[i], f );
|
---|
132 | }
|
---|
133 | }
|
---|
134 |
|
---|
135 | dest->count = nr;
|
---|
136 | }
|
---|
137 |
|
---|
138 | static void translate_1ui( GLvector1ui *dest,
|
---|
139 | GLvector1ui *src,
|
---|
140 | GLuint elt[],
|
---|
141 | GLuint nr )
|
---|
142 | {
|
---|
143 | GLuint i;
|
---|
144 | GLuint *from = src->start;
|
---|
145 | GLuint *to = dest->start;
|
---|
146 | GLuint stride = src->stride;
|
---|
147 |
|
---|
148 | if (stride == sizeof(GLuint)) {
|
---|
149 | for (i = 0 ; i < nr ; i++)
|
---|
150 | to[i] = from[elt[i]];
|
---|
151 | } else {
|
---|
152 | for (i = 0 ; i < nr ; i++) {
|
---|
153 | CONST GLubyte *f = (GLubyte *)from + elt[i] * stride;
|
---|
154 | to[i] = *(GLuint *)f;
|
---|
155 | }
|
---|
156 | }
|
---|
157 |
|
---|
158 | dest->count = nr;
|
---|
159 | }
|
---|
160 |
|
---|
161 | static void translate_1ub( GLvector1ub *dest,
|
---|
162 | GLvector1ub *src,
|
---|
163 | GLuint elt[],
|
---|
164 | GLuint nr )
|
---|
165 | {
|
---|
166 | GLuint i;
|
---|
167 | GLubyte *from = src->start;
|
---|
168 | GLubyte *to = dest->start;
|
---|
169 | GLuint stride = src->stride;
|
---|
170 |
|
---|
171 | if (stride == sizeof(GLubyte)) {
|
---|
172 | for (i = 0 ; i < nr ; i++)
|
---|
173 | to[i] = from[elt[i]];
|
---|
174 | } else {
|
---|
175 | for (i = 0 ; i < nr ; i++) {
|
---|
176 | CONST GLubyte *f = from + elt[i] * stride;
|
---|
177 | to[i] = *f;
|
---|
178 | }
|
---|
179 | }
|
---|
180 |
|
---|
181 | dest->count = nr;
|
---|
182 | }
|
---|
183 |
|
---|
184 |
|
---|
185 | /* The fallback case for handling the merge of cva and immediate
|
---|
186 | * data. This code back-copies data from cva->immediate to build a
|
---|
187 | * normal looking immediate struct, which is then sent off to the
|
---|
188 | * old raster setup and render routines.
|
---|
189 | *
|
---|
190 | * The FX driver implements a replacement for this step which merges
|
---|
191 | * the new data into the already prepared GrVertex structs.
|
---|
192 | *
|
---|
193 | * When there is no data to merge, gl_render_vb_indirect is called
|
---|
194 | * instead.
|
---|
195 | */
|
---|
196 | void gl_merge_cva( struct vertex_buffer *VB,
|
---|
197 | struct vertex_buffer *cvaVB )
|
---|
198 | {
|
---|
199 | GLcontext *ctx = VB->ctx;
|
---|
200 | GLuint *elt = VB->EltPtr->start;
|
---|
201 | GLuint count = VB->Count - VB->Start;
|
---|
202 | GLuint available = ctx->CVA.pre.outputs | ctx->Array.Summary;
|
---|
203 | GLuint required = ctx->CVA.elt.inputs;
|
---|
204 | GLuint flags;
|
---|
205 |
|
---|
206 | /* Should attempt to build an or-flag of reduced (ie rasterization)
|
---|
207 | * prims in the VB, so a software points function doesn't screw us
|
---|
208 | * when we're doing hardware triangles.
|
---|
209 | */
|
---|
210 | if ((required & VERT_SETUP_FULL) &&
|
---|
211 | (ctx->IndirectTriangles & DD_SW_SETUP))
|
---|
212 | {
|
---|
213 | if (MESA_VERBOSE & VERBOSE_PIPELINE)
|
---|
214 | gl_print_vert_flags("extra flags for setup",
|
---|
215 | ctx->RenderFlags & available & ~required);
|
---|
216 | required |= ctx->RenderFlags;
|
---|
217 | }
|
---|
218 |
|
---|
219 | flags = required & available;
|
---|
220 |
|
---|
221 | if ((flags & VERT_DATA) == 0)
|
---|
222 | return;
|
---|
223 |
|
---|
224 | if (MESA_VERBOSE&VERBOSE_PIPELINE)
|
---|
225 | gl_print_vert_flags("cva merge", flags);
|
---|
226 |
|
---|
227 | if (flags & VERT_WIN) {
|
---|
228 | VB->ClipPtr = &VB->Clip;
|
---|
229 | VB->Projected = &VB->Win;
|
---|
230 | VB->CullMode = 0;
|
---|
231 |
|
---|
232 | if (cvaVB->ClipOrMask) {
|
---|
233 |
|
---|
234 | /* Copy clipmask back into VB, build a new clipOrMask */
|
---|
235 | copy_clipmask( VB->ClipMask + VB->Start,
|
---|
236 | &VB->ClipOrMask, &VB->ClipAndMask,
|
---|
237 | cvaVB->ClipMask,
|
---|
238 | elt,
|
---|
239 | VB->Count - VB->Start );
|
---|
240 |
|
---|
241 | /* overkill if !VB->ClipOrMask - should just copy 'copied' verts */
|
---|
242 | translate_4f( VB->ClipPtr, cvaVB->ClipPtr, elt, count);
|
---|
243 |
|
---|
244 | if (VB->ClipOrMask & CLIP_USER_BIT) {
|
---|
245 | GLubyte or = 0, and = ~0;
|
---|
246 |
|
---|
247 | copy_clipmask( VB->UserClipMask + VB->Start,
|
---|
248 | &or, &and,
|
---|
249 | cvaVB->UserClipMask,
|
---|
250 | elt,
|
---|
251 | VB->Count - VB->Start);
|
---|
252 |
|
---|
253 | if (and) VB->ClipAndMask |= CLIP_USER_BIT;
|
---|
254 | }
|
---|
255 |
|
---|
256 | if (VB->ClipOrMask)
|
---|
257 | VB->CullMode |= CLIP_MASK_ACTIVE;
|
---|
258 |
|
---|
259 | if (VB->ClipAndMask) {
|
---|
260 | VB->Culled = 1;
|
---|
261 | gl_dont_cull_vb( VB );
|
---|
262 | return;
|
---|
263 | }
|
---|
264 | }
|
---|
265 |
|
---|
266 | translate_4f( &VB->Win, &cvaVB->Win, elt, count );
|
---|
267 |
|
---|
268 | /* Can't be precomputed - but may be wasteful to do this now.
|
---|
269 | */
|
---|
270 | if (ctx->IndirectTriangles & DD_ANY_CULL)
|
---|
271 | {
|
---|
272 | GLuint cullcount = gl_cull_vb( VB );
|
---|
273 | if (cullcount) VB->CullMode |= CULL_MASK_ACTIVE;
|
---|
274 | if (cullcount == VB->Count) { VB->Culled = 2 ; return; }
|
---|
275 | }
|
---|
276 | else
|
---|
277 | gl_dont_cull_vb( VB );
|
---|
278 | } else {
|
---|
279 | VB->ClipPtr = &VB->Clip;
|
---|
280 | VB->Projected = &VB->Win;
|
---|
281 | }
|
---|
282 |
|
---|
283 | if (flags & VERT_EYE)
|
---|
284 | {
|
---|
285 | VB->Unprojected = VB->EyePtr = &VB->Eye;
|
---|
286 | translate_4f( VB->EyePtr, cvaVB->EyePtr, elt, count);
|
---|
287 | }
|
---|
288 |
|
---|
289 | if (flags & VERT_OBJ_ANY)
|
---|
290 | {
|
---|
291 | VB->ObjPtr = &VB->IM->v.Obj;
|
---|
292 | if (!ctx->NeedEyeCoords) VB->Unprojected = VB->ObjPtr;
|
---|
293 | translate_4f( VB->ObjPtr, cvaVB->ObjPtr, elt, count);
|
---|
294 | }
|
---|
295 |
|
---|
296 | if (flags & VERT_NORM)
|
---|
297 | {
|
---|
298 | VB->NormalPtr = &VB->IM->v.Normal;
|
---|
299 | translate_3f( VB->NormalPtr, cvaVB->NormalPtr, elt, count );
|
---|
300 | VB->CullMode &= ~COMPACTED_NORMALS;
|
---|
301 | }
|
---|
302 |
|
---|
303 | if (flags & VERT_RGBA)
|
---|
304 | {
|
---|
305 | VB->ColorPtr = VB->Color[0] = VB->LitColor[0];
|
---|
306 | translate_4ub( VB->Color[0], cvaVB->Color[0], elt, count );
|
---|
307 |
|
---|
308 | if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
|
---|
309 | VB->Color[1] = VB->LitColor[1];
|
---|
310 | translate_4ub( VB->Color[1], cvaVB->Color[1], elt, count );
|
---|
311 | }
|
---|
312 | }
|
---|
313 |
|
---|
314 | if (flags & VERT_INDEX)
|
---|
315 | {
|
---|
316 | VB->IndexPtr = VB->Index[0] = VB->LitIndex[0];
|
---|
317 | translate_1ui( VB->Index[0], cvaVB->Index[0], elt, count );
|
---|
318 |
|
---|
319 | if (ctx->TriangleCaps & DD_TRI_LIGHT_TWOSIDE) {
|
---|
320 | VB->Index[1] = VB->LitIndex[1];
|
---|
321 | translate_1ui( VB->Index[1], cvaVB->Index[1], elt, count );
|
---|
322 | }
|
---|
323 | }
|
---|
324 |
|
---|
325 | if (flags & VERT_EDGE)
|
---|
326 | {
|
---|
327 | VB->EdgeFlagPtr = &VB->IM->v.EdgeFlag;
|
---|
328 | translate_1ub( VB->EdgeFlagPtr, cvaVB->EdgeFlagPtr, elt, count );
|
---|
329 | }
|
---|
330 |
|
---|
331 | if (flags & VERT_TEX0_ANY)
|
---|
332 | {
|
---|
333 | VB->TexCoordPtr[0] = &VB->IM->v.TexCoord[0];
|
---|
334 | translate_4f( VB->TexCoordPtr[0], cvaVB->TexCoordPtr[0], elt, count);
|
---|
335 | }
|
---|
336 |
|
---|
337 | if (flags & VERT_TEX1_ANY)
|
---|
338 | {
|
---|
339 | VB->TexCoordPtr[1] = &VB->IM->v.TexCoord[1];
|
---|
340 | translate_4f( VB->TexCoordPtr[1], cvaVB->TexCoordPtr[1], elt, count);
|
---|
341 | }
|
---|
342 | }
|
---|
343 |
|
---|
344 |
|
---|
345 |
|
---|
346 |
|
---|
347 | /* We don't have a good mechanism for dealing with the situation where
|
---|
348 | * cva is 'abandoned' midway through a vertex buffer, or indeed any mixing
|
---|
349 | * of cva & standard data in a single immediate struct.
|
---|
350 | *
|
---|
351 | * Basically just abandon CVA even though the precalced data
|
---|
352 | * is already there.
|
---|
353 | */
|
---|
354 | void gl_rescue_cva( GLcontext *ctx, struct immediate *IM )
|
---|
355 | {
|
---|
356 | struct vertex_buffer *VB = ctx->VB;
|
---|
357 |
|
---|
358 | IM->Start = VB->CopyStart;
|
---|
359 |
|
---|
360 | ctx->CompileCVAFlag = 0;
|
---|
361 | gl_build_immediate_pipeline( ctx );
|
---|
362 | gl_exec_array_elements( ctx, IM, IM->Start, IM->Count );
|
---|
363 | }
|
---|
364 |
|
---|
365 |
|
---|
366 |
|
---|
367 |
|
---|
368 |
|
---|
369 | /* Transform the array components now, upto the setup call. When
|
---|
370 | * actual draw commands arrive, the data will be merged prior to
|
---|
371 | * calling render_vb.
|
---|
372 | */
|
---|
373 | void
|
---|
374 | _mesa_LockArraysEXT(GLint first, GLsizei count)
|
---|
375 | {
|
---|
376 | GET_CURRENT_CONTEXT(ctx);
|
---|
377 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "unlock arrays" );
|
---|
378 |
|
---|
379 | if (MESA_VERBOSE & VERBOSE_API)
|
---|
380 | fprintf(stderr, "glLockArrays %d %d\n", first, count);
|
---|
381 |
|
---|
382 | /* Can't mix locked & unlocked - if count is too large, just
|
---|
383 | * unlock.
|
---|
384 | */
|
---|
385 | if (first == 0 &&
|
---|
386 | count > 0 &&
|
---|
387 | count <= ctx->Const.MaxArrayLockSize)
|
---|
388 | {
|
---|
389 | struct gl_cva *cva = &ctx->CVA;
|
---|
390 |
|
---|
391 | if (!ctx->Array.LockCount) {
|
---|
392 | ctx->Array.NewArrayState = ~0;
|
---|
393 | ctx->CVA.lock_changed ^= 1;
|
---|
394 | ctx->NewState |= NEW_CLIENT_STATE;
|
---|
395 | }
|
---|
396 |
|
---|
397 | ctx->Array.LockFirst = first;
|
---|
398 | ctx->Array.LockCount = count;
|
---|
399 | ctx->CompileCVAFlag = !ctx->CompileFlag;
|
---|
400 |
|
---|
401 | if (!cva->VB) {
|
---|
402 | cva->VB = gl_vb_create_for_cva( ctx, ctx->Const.MaxArrayLockSize );
|
---|
403 | gl_alloc_cva_store( cva, cva->VB->Size );
|
---|
404 | gl_reset_cva_vb( cva->VB, ~0 );
|
---|
405 | }
|
---|
406 | }
|
---|
407 | else
|
---|
408 | {
|
---|
409 | if (ctx->Array.LockCount) {
|
---|
410 | ctx->CVA.lock_changed ^= 1;
|
---|
411 | ctx->NewState |= NEW_CLIENT_STATE;
|
---|
412 | }
|
---|
413 |
|
---|
414 |
|
---|
415 | ctx->Array.LockFirst = 0;
|
---|
416 | ctx->Array.LockCount = 0;
|
---|
417 | ctx->CompileCVAFlag = 0;
|
---|
418 | }
|
---|
419 | }
|
---|
420 |
|
---|
421 |
|
---|
422 |
|
---|
423 |
|
---|
424 | void
|
---|
425 | _mesa_UnlockArraysEXT( void )
|
---|
426 | {
|
---|
427 | GET_CURRENT_CONTEXT(ctx);
|
---|
428 | ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH( ctx, "unlock arrays" );
|
---|
429 |
|
---|
430 | if (MESA_VERBOSE & VERBOSE_API)
|
---|
431 | fprintf(stderr, "glUnlockArrays\n");
|
---|
432 |
|
---|
433 | if (ctx->Array.LockCount) {
|
---|
434 | ctx->CVA.lock_changed ^= 1;
|
---|
435 | ctx->NewState |= NEW_CLIENT_STATE;
|
---|
436 | }
|
---|
437 |
|
---|
438 | ctx->Array.LockFirst = 0;
|
---|
439 | ctx->Array.LockCount = 0;
|
---|
440 | ctx->CompileCVAFlag = 0;
|
---|
441 | }
|
---|
442 |
|
---|
443 |
|
---|
444 | /* This storage used to hold translated client data if type or stride
|
---|
445 | * need to be fixed.
|
---|
446 | */
|
---|
447 | void gl_alloc_cva_store( struct gl_cva *cva, GLuint size )
|
---|
448 | {
|
---|
449 | cva->store.Obj = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size );
|
---|
450 | cva->store.Normal = (GLfloat (*)[3])MALLOC( sizeof(GLfloat) * 3 * size );
|
---|
451 | cva->store.Color = (GLubyte (*)[4])MALLOC( sizeof(GLubyte) * 4 * size );
|
---|
452 | cva->store.EdgeFlag = (GLubyte *)MALLOC( sizeof(GLubyte) * size );
|
---|
453 | cva->store.Index = (GLuint *)MALLOC( sizeof(GLuint) * size );
|
---|
454 | cva->store.TexCoord[0] = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size);
|
---|
455 | cva->store.TexCoord[1] = (GLfloat (*)[4])MALLOC( sizeof(GLfloat) * 4 * size);
|
---|
456 | cva->store.Elt = (GLuint *)MALLOC( sizeof(GLuint) * size );
|
---|
457 | cva->elt_size = size;
|
---|
458 | }
|
---|
459 |
|
---|
460 | void gl_free_cva_store( struct gl_cva *cva )
|
---|
461 | {
|
---|
462 | FREE( cva->store.Obj );
|
---|
463 | FREE( cva->store.Normal );
|
---|
464 | FREE( cva->store.Color );
|
---|
465 | FREE( cva->store.EdgeFlag );
|
---|
466 | FREE( cva->store.Index );
|
---|
467 | FREE( cva->store.TexCoord[0] );
|
---|
468 | FREE( cva->store.TexCoord[1] );
|
---|
469 | FREE( cva->store.Elt );
|
---|
470 | }
|
---|
471 |
|
---|
472 |
|
---|
473 | void gl_prepare_arrays_cva( struct vertex_buffer *VB )
|
---|
474 | {
|
---|
475 | GLcontext *ctx = VB->ctx;
|
---|
476 | struct gl_cva *cva = &ctx->CVA;
|
---|
477 | GLuint start = ctx->Array.LockFirst;
|
---|
478 | GLuint n = ctx->Array.LockCount;
|
---|
479 | GLuint enable = ((ctx->Array.NewArrayState & ctx->Array.Summary) |
|
---|
480 | VB->pipeline->fallback);
|
---|
481 | GLuint disable = ctx->Array.NewArrayState & ~enable;
|
---|
482 | GLuint i;
|
---|
483 |
|
---|
484 | if (MESA_VERBOSE&VERBOSE_PIPELINE) {
|
---|
485 | gl_print_vert_flags("*** ENABLE", enable);
|
---|
486 | gl_print_vert_flags("*** DISABLE", disable);
|
---|
487 | }
|
---|
488 |
|
---|
489 | if (enable)
|
---|
490 | {
|
---|
491 | struct gl_client_array *client_data;
|
---|
492 | GLuint fallback = VB->pipeline->fallback;
|
---|
493 |
|
---|
494 | if (enable & VERT_ELT)
|
---|
495 | {
|
---|
496 | GLvector1ui *elt = VB->EltPtr = &cva->v.Elt;
|
---|
497 |
|
---|
498 | if (cva->Elt.Type == GL_UNSIGNED_INT)
|
---|
499 | {
|
---|
500 | elt->data = (GLuint *) cva->Elt.Ptr;
|
---|
501 | elt->stride = sizeof(GLuint);
|
---|
502 | elt->flags = 0;
|
---|
503 | } else {
|
---|
504 | elt->data = cva->store.Elt;
|
---|
505 | elt->stride = sizeof(GLuint);
|
---|
506 |
|
---|
507 | if (cva->elt_count > cva->elt_size)
|
---|
508 | {
|
---|
509 | while (cva->elt_count > (cva->elt_size *= 2)) {};
|
---|
510 | FREE(cva->store.Elt);
|
---|
511 | cva->store.Elt = (GLuint *) MALLOC(cva->elt_size *
|
---|
512 | sizeof(GLuint));
|
---|
513 | }
|
---|
514 | cva->EltFunc( elt->data, &cva->Elt, 0, cva->elt_count );
|
---|
515 | }
|
---|
516 | elt->start = VEC_ELT(elt, GLuint, 0);
|
---|
517 | elt->count = cva->elt_count;
|
---|
518 |
|
---|
519 | fallback |= (cva->pre.new_inputs & ~ctx->Array.Summary);
|
---|
520 | enable |= fallback;
|
---|
521 | disable &= ~fallback;
|
---|
522 | if (MESA_VERBOSE&VERBOSE_PIPELINE) {
|
---|
523 | gl_print_vert_flags("*** NEW INPUTS", cva->pre.new_inputs);
|
---|
524 | gl_print_vert_flags("*** FALLBACK", fallback);
|
---|
525 | }
|
---|
526 | }
|
---|
527 |
|
---|
528 | if (enable & VERT_RGBA)
|
---|
529 | {
|
---|
530 | GLvector4ub *col = &cva->v.Color;
|
---|
531 |
|
---|
532 | client_data = &ctx->Array.Color;
|
---|
533 | if (fallback & VERT_RGBA) client_data = &ctx->Fallback.Color;
|
---|
534 |
|
---|
535 | VB->Color[0] = VB->Color[1] = VB->ColorPtr = &cva->v.Color;
|
---|
536 |
|
---|
537 | if (client_data->Type != GL_UNSIGNED_BYTE ||
|
---|
538 | client_data->Size != 4)
|
---|
539 | {
|
---|
540 | col->data = cva->store.Color;
|
---|
541 | col->stride = 4 * sizeof(GLubyte);
|
---|
542 | ctx->Array.ColorFunc( col->data, client_data, start, n );
|
---|
543 | col->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
|
---|
544 | } else {
|
---|
545 | col->data = (GLubyte (*)[4]) client_data->Ptr;
|
---|
546 | col->stride = client_data->StrideB;
|
---|
547 | col->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
|
---|
548 | if (client_data->StrideB != 4 * sizeof(GLubyte))
|
---|
549 | col->flags ^= VEC_STRIDE_FLAGS;
|
---|
550 | }
|
---|
551 | col->start = VEC_ELT(col, GLubyte, start);
|
---|
552 | col->count = n;
|
---|
553 | }
|
---|
554 |
|
---|
555 | if (enable & VERT_INDEX)
|
---|
556 | {
|
---|
557 | GLvector1ui *index = VB->IndexPtr = &cva->v.Index;
|
---|
558 | VB->Index[0] = VB->Index[1] = VB->IndexPtr;
|
---|
559 |
|
---|
560 | client_data = &ctx->Array.Index;
|
---|
561 | if (fallback & VERT_INDEX) client_data = &ctx->Fallback.Index;
|
---|
562 |
|
---|
563 | if (client_data->Type != GL_UNSIGNED_INT)
|
---|
564 | {
|
---|
565 | index->data = cva->store.Index;
|
---|
566 | index->stride = sizeof(GLuint);
|
---|
567 | ctx->Array.IndexFunc( index->data, client_data, start, n );
|
---|
568 | index->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
|
---|
569 | } else {
|
---|
570 | index->data = (GLuint *) client_data->Ptr;
|
---|
571 | index->stride = client_data->StrideB;
|
---|
572 | index->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
|
---|
573 | if (index->stride != sizeof(GLuint))
|
---|
574 | index->flags ^= VEC_STRIDE_FLAGS;
|
---|
575 | }
|
---|
576 | index->count = n;
|
---|
577 | index->start = VEC_ELT(index, GLuint, start);
|
---|
578 | }
|
---|
579 |
|
---|
580 | for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
|
---|
581 | if (enable & PIPE_TEX(i)) {
|
---|
582 | GLvector4f *tc = VB->TexCoordPtr[i] = &cva->v.TexCoord[i];
|
---|
583 |
|
---|
584 | client_data = &ctx->Array.TexCoord[i];
|
---|
585 |
|
---|
586 | if (fallback & PIPE_TEX(i)) {
|
---|
587 | client_data = &ctx->Fallback.TexCoord[i];
|
---|
588 | client_data->Size = gl_texcoord_size( ctx->Current.Flag, i );
|
---|
589 | }
|
---|
590 |
|
---|
591 | /* Writeability and stride handled lazily by
|
---|
592 | * gl_import_client_data().
|
---|
593 | */
|
---|
594 | if (client_data->Type == GL_FLOAT)
|
---|
595 | {
|
---|
596 | tc->data = (GLfloat (*)[4]) client_data->Ptr;
|
---|
597 | tc->stride = client_data->StrideB;
|
---|
598 | tc->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
|
---|
599 | if (tc->stride != 4 * sizeof(GLfloat))
|
---|
600 | tc->flags ^= VEC_STRIDE_FLAGS;
|
---|
601 | } else {
|
---|
602 | tc->data = cva->store.TexCoord[i];
|
---|
603 | tc->stride = 4 * sizeof(GLfloat);
|
---|
604 | ctx->Array.TexCoordFunc[i]( tc->data, client_data, start, n );
|
---|
605 | tc->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
|
---|
606 | }
|
---|
607 | tc->count = n;
|
---|
608 | tc->start = VEC_ELT(tc, GLfloat, start);
|
---|
609 | tc->size = client_data->Size;
|
---|
610 | }
|
---|
611 |
|
---|
612 | if (enable & VERT_OBJ_ANY)
|
---|
613 | {
|
---|
614 | GLvector4f *obj = VB->ObjPtr = &cva->v.Obj;
|
---|
615 |
|
---|
616 | if (ctx->Array.Vertex.Type == GL_FLOAT)
|
---|
617 | {
|
---|
618 | obj->data = (GLfloat (*)[4]) ctx->Array.Vertex.Ptr;
|
---|
619 | obj->stride = ctx->Array.Vertex.StrideB;
|
---|
620 | obj->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
|
---|
621 | if (obj->stride != 4 * sizeof(GLfloat))
|
---|
622 | obj->flags ^= VEC_STRIDE_FLAGS;
|
---|
623 | } else {
|
---|
624 | obj->data = cva->store.Obj;
|
---|
625 | obj->stride = 4 * sizeof(GLfloat);
|
---|
626 | ctx->Array.VertexFunc( obj->data, &ctx->Array.Vertex, start, n );
|
---|
627 | obj->flags = VEC_WRITABLE|VEC_GOOD_STRIDE;
|
---|
628 | }
|
---|
629 | obj->count = n;
|
---|
630 | obj->start = VEC_ELT(obj, GLfloat, start);
|
---|
631 | obj->size = ctx->Array.Vertex.Size;
|
---|
632 | }
|
---|
633 |
|
---|
634 | if (enable & VERT_NORM)
|
---|
635 | {
|
---|
636 | GLvector3f *norm = VB->NormalPtr = &cva->v.Normal;
|
---|
637 |
|
---|
638 | client_data = &ctx->Array.Normal;
|
---|
639 |
|
---|
640 | if (fallback & VERT_NORM)
|
---|
641 | client_data = &ctx->Fallback.Normal;
|
---|
642 |
|
---|
643 | /* Never need to write to normals, and we can always cope with stride.
|
---|
644 | */
|
---|
645 | if (client_data->Type == GL_FLOAT) {
|
---|
646 | norm->data = (GLfloat (*)[3]) client_data->Ptr;
|
---|
647 | norm->stride = client_data->StrideB;
|
---|
648 | } else {
|
---|
649 | norm->data = cva->store.Normal;
|
---|
650 | norm->stride = 3 * sizeof(GLfloat);
|
---|
651 | ctx->Array.NormalFunc( norm->data, client_data, start, n );
|
---|
652 | }
|
---|
653 | norm->flags = 0;
|
---|
654 | norm->count = n;
|
---|
655 | norm->start = VEC_ELT(norm, GLfloat, start);
|
---|
656 | }
|
---|
657 |
|
---|
658 | if (enable & VERT_EDGE)
|
---|
659 | {
|
---|
660 | GLvector1ub *edge = VB->EdgeFlagPtr = &cva->v.EdgeFlag;
|
---|
661 |
|
---|
662 | client_data = &ctx->Array.EdgeFlag;
|
---|
663 |
|
---|
664 | if (fallback & VERT_EDGE)
|
---|
665 | client_data = &ctx->Fallback.EdgeFlag;
|
---|
666 |
|
---|
667 | edge->data = (GLboolean *) client_data->Ptr;
|
---|
668 | edge->stride = client_data->StrideB;
|
---|
669 | edge->flags = VEC_NOT_WRITABLE|VEC_GOOD_STRIDE;
|
---|
670 | if (edge->stride != sizeof(GLubyte))
|
---|
671 | edge->flags ^= VEC_STRIDE_FLAGS;
|
---|
672 |
|
---|
673 | edge->count = n;
|
---|
674 | edge->start = VEC_ELT(edge, GLubyte, start);
|
---|
675 | }
|
---|
676 | }
|
---|
677 |
|
---|
678 | if (disable) {
|
---|
679 | if (disable & VERT_RGBA) cva->v.Color = *VB->LitColor[0];
|
---|
680 | if (disable & VERT_INDEX) cva->v.Index = *VB->LitIndex[0];
|
---|
681 | if (disable & VERT_NORM) cva->v.Normal = *VB->store.Normal;
|
---|
682 | if (disable & VERT_OBJ_ANY) cva->v.Obj = *VB->store.Obj;
|
---|
683 | if (disable & VERT_TEX0_ANY) cva->v.TexCoord[0]= *(VB->store.TexCoord[0]);
|
---|
684 | if (disable & VERT_TEX0_ANY) cva->v.TexCoord[1]= *(VB->store.TexCoord[1]);
|
---|
685 | if (disable & VERT_EDGE) cva->v.EdgeFlag = *VB->store.EdgeFlag;
|
---|
686 | }
|
---|
687 |
|
---|
688 | VB->Flag[VB->Count] &= ~VERT_END_VB;
|
---|
689 | VB->Count = n;
|
---|
690 |
|
---|
691 | if (ctx->Enabled & ENABLE_LIGHT)
|
---|
692 | {
|
---|
693 | if (ctx->Array.Flags != VB->Flag[0])
|
---|
694 | VB->FlagMax = 0;
|
---|
695 |
|
---|
696 | if (VB->FlagMax < n) {
|
---|
697 | for (i = VB->FlagMax ; i < n ; i++)
|
---|
698 | VB->Flag[i] = ctx->Array.Flags;
|
---|
699 | VB->Flag[i] = 0;
|
---|
700 | VB->FlagMax = n;
|
---|
701 | }
|
---|
702 |
|
---|
703 | VB->Flag[n] |= VERT_END_VB;
|
---|
704 | }
|
---|
705 | }
|
---|
706 |
|
---|
707 | void gl_cva_force_precalc( GLcontext *ctx )
|
---|
708 | {
|
---|
709 | struct gl_cva *cva = &ctx->CVA;
|
---|
710 |
|
---|
711 | if (cva->pre.changed_ops)
|
---|
712 | gl_reset_cva_vb( cva->VB, cva->pre.changed_ops );
|
---|
713 |
|
---|
714 | gl_run_pipeline( cva->VB );
|
---|
715 |
|
---|
716 | ctx->Array.NewArrayState = 0;
|
---|
717 | }
|
---|
718 |
|
---|
719 |
|
---|
720 | /* Simplified: just make sure the pipelines are valid.
|
---|
721 | */
|
---|
722 | void gl_cva_compile_cassette( GLcontext *ctx, struct immediate *IM )
|
---|
723 | {
|
---|
724 | struct gl_cva *cva = &ctx->CVA;
|
---|
725 | cva->orflag |= IM->OrFlag;
|
---|
726 |
|
---|
727 | /* Allow pipeline recalculation based on inputs received from client.
|
---|
728 | */
|
---|
729 | if (IM->OrFlag & (cva->pre.forbidden_inputs|cva->elt.forbidden_inputs))
|
---|
730 | {
|
---|
731 | if (IM->OrFlag & cva->pre.forbidden_inputs)
|
---|
732 | {
|
---|
733 | cva->pre.pipeline_valid = 0;
|
---|
734 | cva->pre.data_valid = 0;
|
---|
735 | cva->pre.forbidden_inputs = 0;
|
---|
736 | }
|
---|
737 |
|
---|
738 | if ((IM->OrFlag & cva->elt.forbidden_inputs))
|
---|
739 | {
|
---|
740 | cva->elt.forbidden_inputs = 0;
|
---|
741 | }
|
---|
742 |
|
---|
743 | cva->elt.pipeline_valid = 0;
|
---|
744 | }
|
---|
745 |
|
---|
746 | /* Recalculate CVA data if necessary.
|
---|
747 | */
|
---|
748 | if (ctx->CompileCVAFlag && !cva->pre.data_valid)
|
---|
749 | {
|
---|
750 | if (!cva->pre.pipeline_valid)
|
---|
751 | gl_build_precalc_pipeline( ctx );
|
---|
752 |
|
---|
753 | gl_cva_force_precalc( ctx );
|
---|
754 | }
|
---|
755 |
|
---|
756 | /* Build immediate pipeline if necessary.
|
---|
757 | */
|
---|
758 | if (!cva->elt.pipeline_valid)
|
---|
759 | gl_build_immediate_pipeline( ctx );
|
---|
760 |
|
---|
761 | gl_fixup_input( ctx, IM );
|
---|
762 | gl_execute_cassette( ctx, IM );
|
---|
763 | }
|
---|
764 |
|
---|
765 |
|
---|
766 | void gl_cva_init( GLcontext *ctx )
|
---|
767 | {
|
---|
768 | (void) ctx;
|
---|
769 | }
|
---|