Big-endian fixes for R200 sw TCL path.
[mesa.git] / src / mesa / tnl / t_vertex.c
1 /*
2 * Copyright 2003 Tungsten Graphics, inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
14 * Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
23 *
24 * Authors:
25 * Keith Whitwell <keithw@tungstengraphics.com>
26 */
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "colormac.h"
31
32 #include "t_context.h"
33 #include "t_vertex.h"
34
35
36 /* Build and manage clipspace/ndc/window vertices.
37 *
38 * Another new mechanism designed and crying out for codegen. Before
39 * that, it would be very interesting to investigate the merger of
40 * these vertices and those built in t_vtx_*.
41 */
42
43
44
45
46
47
48 /*
49 * These functions take the NDC coordinates pointed to by 'in', apply the
50 * NDC->Viewport mapping and store the results at 'v'.
51 */
52
53 static void
54 insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
55 const GLfloat *in )
56 {
57 GLfloat *out = (GLfloat *)v;
58 const GLfloat * const vp = a->vp;
59
60 out[0] = vp[0] * in[0] + vp[12];
61 out[1] = vp[5] * in[1] + vp[13];
62 out[2] = vp[10] * in[2] + vp[14];
63 out[3] = in[3];
64 }
65
66 static void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
67 const GLfloat *in )
68 {
69 GLfloat *out = (GLfloat *)v;
70 const GLfloat * const vp = a->vp;
71
72 out[0] = vp[0] * in[0] + vp[12];
73 out[1] = vp[5] * in[1] + vp[13];
74 out[2] = vp[10] * in[2] + vp[14];
75 out[3] = 1;
76 }
77
78 static void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
79 const GLfloat *in )
80 {
81 GLfloat *out = (GLfloat *)v;
82 const GLfloat * const vp = a->vp;
83
84 out[0] = vp[0] * in[0] + vp[12];
85 out[1] = vp[5] * in[1] + vp[13];
86 out[2] = vp[14];
87 out[3] = 1;
88 }
89
90 static void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
91 const GLfloat *in )
92 {
93 GLfloat *out = (GLfloat *)v;
94 const GLfloat * const vp = a->vp;
95
96 out[0] = vp[0] * in[0] + vp[12];
97 out[1] = vp[13];
98 out[2] = vp[14];
99 out[3] = 1;
100 }
101
102 static void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
103 const GLfloat *in )
104 {
105 GLfloat *out = (GLfloat *)v;
106 const GLfloat * const vp = a->vp;
107
108 out[0] = vp[0] * in[0] + vp[12];
109 out[1] = vp[5] * in[1] + vp[13];
110 out[2] = vp[10] * in[2] + vp[14];
111 }
112
113 static void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
114 const GLfloat *in )
115 {
116 GLfloat *out = (GLfloat *)v;
117 const GLfloat * const vp = a->vp;
118
119 out[0] = vp[0] * in[0] + vp[12];
120 out[1] = vp[5] * in[1] + vp[13];
121 out[2] = vp[10] * in[2] + vp[14];
122 }
123
124 static void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
125 const GLfloat *in )
126 {
127 GLfloat *out = (GLfloat *)v;
128 const GLfloat * const vp = a->vp;
129
130 out[0] = vp[0] * in[0] + vp[12];
131 out[1] = vp[13];
132 out[2] = vp[14];
133 }
134
135 static void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
136 const GLfloat *in )
137 {
138 GLfloat *out = (GLfloat *)v;
139 const GLfloat * const vp = a->vp;
140
141 out[0] = vp[0] * in[0] + vp[12];
142 out[1] = vp[5] * in[1] + vp[13];
143 }
144
145 static void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
146 const GLfloat *in )
147 {
148 GLfloat *out = (GLfloat *)v;
149 const GLfloat * const vp = a->vp;
150
151 out[0] = vp[0] * in[0] + vp[12];
152 out[1] = vp[13];
153 }
154
155
156 /*
157 * These functions do the same as above, except for the viewport mapping.
158 */
159
160 static void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
161 {
162 GLfloat *out = (GLfloat *)(v);
163 (void) a;
164
165 out[0] = in[0];
166 out[1] = in[1];
167 out[2] = in[2];
168 out[3] = in[3];
169 }
170
171 static void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
172 {
173 GLfloat *out = (GLfloat *)(v);
174 (void) a;
175
176 out[0] = in[0];
177 out[1] = in[1];
178 out[2] = in[2];
179 out[3] = 1;
180 }
181
182 static void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
183 {
184 GLfloat *out = (GLfloat *)(v);
185 (void) a;
186
187 out[0] = in[0];
188 out[1] = in[1];
189 out[2] = 0;
190 out[3] = 1;
191 }
192
193 static void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
194 {
195 GLfloat *out = (GLfloat *)(v);
196 (void) a;
197
198 out[0] = in[0];
199 out[1] = 0;
200 out[2] = 0;
201 out[3] = 1;
202 }
203
204 static void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
205 {
206 GLfloat *out = (GLfloat *)(v);
207 (void) a;
208
209 out[0] = in[0];
210 out[1] = in[1];
211 out[2] = in[3];
212 }
213
214 static void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
215 {
216 (void) a; (void) v; (void) in;
217 abort();
218 }
219
220 static void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
221 {
222 GLfloat *out = (GLfloat *)(v);
223 (void) a;
224
225 out[0] = in[0];
226 out[1] = in[1];
227 out[2] = in[2];
228 }
229
230 static void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
231 {
232 GLfloat *out = (GLfloat *)(v);
233 (void) a;
234
235 out[0] = in[0];
236 out[1] = in[1];
237 out[2] = 0;
238 }
239
240 static void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
241 {
242 GLfloat *out = (GLfloat *)(v);
243 (void) a;
244
245 out[0] = in[0];
246 out[1] = 0;
247 out[2] = 0;
248 }
249
250
251 static void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
252 {
253 GLfloat *out = (GLfloat *)(v);
254 (void) a;
255
256 out[0] = in[0];
257 out[1] = in[1];
258 }
259
260 static void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
261 {
262 GLfloat *out = (GLfloat *)(v);
263 (void) a;
264
265 out[0] = in[0];
266 out[1] = 0;
267 }
268
269 static void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
270 {
271 GLfloat *out = (GLfloat *)(v);
272 (void) a;
273
274 out[0] = in[0];
275 }
276
277 static void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
278 const GLfloat *in )
279 {
280 GLchan *c = (GLchan *)v;
281 (void) a;
282 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
283 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
284 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
285 UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
286 }
287
288 static void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
289 const GLfloat *in )
290 {
291 GLchan *c = (GLchan *)v;
292 (void) a;
293 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
294 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
295 UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
296 c[3] = CHAN_MAX;
297 }
298
299 static void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
300 const GLfloat *in )
301 {
302 GLchan *c = (GLchan *)v;
303 (void) a;
304 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
305 UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
306 c[2] = 0;
307 c[3] = CHAN_MAX;
308 }
309
310 static void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
311 const GLfloat *in )
312 {
313 GLchan *c = (GLchan *)v;
314 (void) a;
315 UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
316 c[1] = 0;
317 c[2] = 0;
318 c[3] = CHAN_MAX;
319 }
320
321 static void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
322 const GLfloat *in )
323 {
324 (void) a;
325 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
326 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
327 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
328 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
329 }
330
331 static void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
332 const GLfloat *in )
333 {
334 (void) a;
335 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
336 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
337 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
338 v[3] = 0xff;
339 }
340
341 static void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
342 const GLfloat *in )
343 {
344 (void) a;
345 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
346 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
347 v[2] = 0;
348 v[3] = 0xff;
349 }
350
351 static void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
352 const GLfloat *in )
353 {
354 (void) a;
355 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
356 v[1] = 0;
357 v[2] = 0;
358 v[3] = 0xff;
359 }
360
361 static void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
362 const GLfloat *in )
363 {
364 (void) a;
365 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
366 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
367 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
368 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
369 }
370
371 static void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
372 const GLfloat *in )
373 {
374 (void) a;
375 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
376 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
377 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
378 v[3] = 0xff;
379 }
380
381 static void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
382 const GLfloat *in )
383 {
384 (void) a;
385 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
386 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
387 v[0] = 0;
388 v[3] = 0xff;
389 }
390
391 static void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
392 const GLfloat *in )
393 {
394 (void) a;
395 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
396 v[1] = 0;
397 v[0] = 0;
398 v[3] = 0xff;
399 }
400
401 static void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v,
402 const GLfloat *in )
403 {
404 (void) a;
405 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
406 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
407 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
408 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
409 }
410
411 static void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
412 const GLfloat *in )
413 {
414 (void) a;
415 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
416 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
417 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
418 v[0] = 0xff;
419 }
420
421 static void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
422 const GLfloat *in )
423 {
424 (void) a;
425 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
426 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
427 v[3] = 0x00;
428 v[0] = 0xff;
429 }
430
431 static void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
432 const GLfloat *in )
433 {
434 (void) a;
435 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
436 v[2] = 0x00;
437 v[3] = 0x00;
438 v[0] = 0xff;
439 }
440
441 static void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v,
442 const GLfloat *in )
443 {
444 (void) a;
445 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
446 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
447 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
448 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
449 }
450
451 static void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
452 const GLfloat *in )
453 {
454 (void) a;
455 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
456 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
457 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
458 v[0] = 0xff;
459 }
460
461 static void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
462 const GLfloat *in )
463 {
464 (void) a;
465 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
466 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
467 v[1] = 0x00;
468 v[0] = 0xff;
469 }
470
471 static void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
472 const GLfloat *in )
473 {
474 (void) a;
475 UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
476 v[2] = 0x00;
477 v[1] = 0x00;
478 v[0] = 0xff;
479 }
480
481 static void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
482 const GLfloat *in )
483 {
484 (void) a;
485 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
486 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
487 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
488 }
489
490 static void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
491 const GLfloat *in )
492 {
493 (void) a;
494 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
495 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
496 v[2] = 0;
497 }
498
499 static void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
500 const GLfloat *in )
501 {
502 (void) a;
503 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
504 v[1] = 0;
505 v[2] = 0;
506 }
507
508 static void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
509 const GLfloat *in )
510 {
511 (void) a;
512 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
513 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
514 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
515 }
516
517 static void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
518 const GLfloat *in )
519 {
520 (void) a;
521 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
522 UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
523 v[0] = 0;
524 }
525
526 static void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
527 const GLfloat *in )
528 {
529 (void) a;
530 UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
531 v[1] = 0;
532 v[0] = 0;
533 }
534
535
536 static void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
537 const GLfloat *in )
538 {
539 (void) a;
540 UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
541 }
542
543
544 /***********************************************************************
545 * Functions to perform the reverse operations to the above, for
546 * swrast translation and clip-interpolation.
547 *
548 * Currently always extracts a full 4 floats.
549 */
550
551 static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
552 const GLubyte *v )
553 {
554 const GLfloat *in = (const GLfloat *)v;
555 const GLfloat * const vp = a->vp;
556
557 /* Although included for completeness, the position coordinate is
558 * usually handled differently during clipping.
559 */
560 out[0] = (in[0] - vp[12]) / vp[0];
561 out[1] = (in[1] - vp[13]) / vp[5];
562 out[2] = (in[2] - vp[14]) / vp[10];
563 out[3] = in[3];
564 }
565
566 static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
567 const GLubyte *v )
568 {
569 const GLfloat *in = (const GLfloat *)v;
570 const GLfloat * const vp = a->vp;
571
572 out[0] = (in[0] - vp[12]) / vp[0];
573 out[1] = (in[1] - vp[13]) / vp[5];
574 out[2] = (in[2] - vp[14]) / vp[10];
575 out[3] = 1;
576 }
577
578
579 static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
580 const GLubyte *v )
581 {
582 const GLfloat *in = (const GLfloat *)v;
583 const GLfloat * const vp = a->vp;
584
585 out[0] = (in[0] - vp[12]) / vp[0];
586 out[1] = (in[1] - vp[13]) / vp[5];
587 out[2] = 0;
588 out[3] = 1;
589 }
590
591
592 static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
593 {
594 const GLfloat *in = (const GLfloat *)v;
595 (void) a;
596
597 out[0] = in[0];
598 out[1] = in[1];
599 out[2] = in[2];
600 out[3] = in[3];
601 }
602
603 static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
604 {
605 const GLfloat *in = (const GLfloat *)v;
606 (void) a;
607
608 out[0] = in[0];
609 out[1] = in[1];
610 out[2] = 0;
611 out[3] = in[2];
612 }
613
614
615 static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
616 {
617 const GLfloat *in = (const GLfloat *)v;
618 (void) a;
619
620 out[0] = in[0];
621 out[1] = in[1];
622 out[2] = in[2];
623 out[3] = 1;
624 }
625
626
627 static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
628 {
629 const GLfloat *in = (const GLfloat *)v;
630 (void) a;
631
632 out[0] = in[0];
633 out[1] = in[1];
634 out[2] = 0;
635 out[3] = 1;
636 }
637
638 static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
639 {
640 const GLfloat *in = (const GLfloat *)v;
641 (void) a;
642
643 out[0] = in[0];
644 out[1] = 0;
645 out[2] = 0;
646 out[3] = 1;
647 }
648
649 static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
650 const GLubyte *v )
651 {
652 GLchan *c = (GLchan *)v;
653 (void) a;
654
655 out[0] = CHAN_TO_FLOAT(c[0]);
656 out[1] = CHAN_TO_FLOAT(c[1]);
657 out[2] = CHAN_TO_FLOAT(c[2]);
658 out[3] = CHAN_TO_FLOAT(c[3]);
659 }
660
661 static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
662 const GLubyte *v )
663 {
664 (void) a;
665 out[0] = UBYTE_TO_FLOAT(v[0]);
666 out[1] = UBYTE_TO_FLOAT(v[1]);
667 out[2] = UBYTE_TO_FLOAT(v[2]);
668 out[3] = UBYTE_TO_FLOAT(v[3]);
669 }
670
671 static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
672 const GLubyte *v )
673 {
674 (void) a;
675 out[2] = UBYTE_TO_FLOAT(v[0]);
676 out[1] = UBYTE_TO_FLOAT(v[1]);
677 out[0] = UBYTE_TO_FLOAT(v[2]);
678 out[3] = UBYTE_TO_FLOAT(v[3]);
679 }
680
681 static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out,
682 const GLubyte *v )
683 {
684 (void) a;
685 out[3] = UBYTE_TO_FLOAT(v[0]);
686 out[0] = UBYTE_TO_FLOAT(v[1]);
687 out[1] = UBYTE_TO_FLOAT(v[2]);
688 out[2] = UBYTE_TO_FLOAT(v[3]);
689 }
690
691 static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out,
692 const GLubyte *v )
693 {
694 (void) a;
695 out[3] = UBYTE_TO_FLOAT(v[0]);
696 out[2] = UBYTE_TO_FLOAT(v[1]);
697 out[1] = UBYTE_TO_FLOAT(v[2]);
698 out[0] = UBYTE_TO_FLOAT(v[3]);
699 }
700
701 static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
702 const GLubyte *v )
703 {
704 (void) a;
705 out[0] = UBYTE_TO_FLOAT(v[0]);
706 out[1] = UBYTE_TO_FLOAT(v[1]);
707 out[2] = UBYTE_TO_FLOAT(v[2]);
708 out[3] = 1;
709 }
710
711 static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
712 const GLubyte *v )
713 {
714 (void) a;
715 out[2] = UBYTE_TO_FLOAT(v[0]);
716 out[1] = UBYTE_TO_FLOAT(v[1]);
717 out[0] = UBYTE_TO_FLOAT(v[2]);
718 out[3] = 1;
719 }
720
721 static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
722 {
723 (void) a;
724 out[0] = UBYTE_TO_FLOAT(v[0]);
725 out[1] = 0;
726 out[2] = 0;
727 out[3] = 1;
728 }
729
730
731 static struct {
732 const char *name;
733 tnl_extract_func extract;
734 tnl_insert_func insert[4];
735 const GLuint attrsize;
736 } format_info[EMIT_MAX] = {
737
738 { "1f",
739 extract_1f,
740 { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
741 sizeof(GLfloat) },
742
743 { "2f",
744 extract_2f,
745 { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
746 2 * sizeof(GLfloat) },
747
748 { "3f",
749 extract_3f,
750 { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
751 3 * sizeof(GLfloat) },
752
753 { "4f",
754 extract_4f,
755 { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
756 4 * sizeof(GLfloat) },
757
758 { "2f_viewport",
759 extract_2f_viewport,
760 { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
761 insert_2f_viewport_2 },
762 2 * sizeof(GLfloat) },
763
764 { "3f_viewport",
765 extract_3f_viewport,
766 { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
767 insert_3f_viewport_3 },
768 3 * sizeof(GLfloat) },
769
770 { "4f_viewport",
771 extract_4f_viewport,
772 { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
773 insert_4f_viewport_4 },
774 4 * sizeof(GLfloat) },
775
776 { "3f_xyw",
777 extract_3f_xyw,
778 { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
779 insert_3f_xyw_4 },
780 3 * sizeof(GLfloat) },
781
782 { "1ub_1f",
783 extract_1ub_1f,
784 { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
785 sizeof(GLubyte) },
786
787 { "3ub_3f_rgb",
788 extract_3ub_3f_rgb,
789 { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
790 insert_3ub_3f_rgb_3 },
791 3 * sizeof(GLubyte) },
792
793 { "3ub_3f_bgr",
794 extract_3ub_3f_bgr,
795 { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
796 insert_3ub_3f_bgr_3 },
797 3 * sizeof(GLubyte) },
798
799 { "4ub_4f_rgba",
800 extract_4ub_4f_rgba,
801 { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
802 insert_4ub_4f_rgba_4 },
803 4 * sizeof(GLubyte) },
804
805 { "4ub_4f_bgra",
806 extract_4ub_4f_bgra,
807 { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
808 insert_4ub_4f_bgra_4 },
809 4 * sizeof(GLubyte) },
810
811 { "4ub_4f_argb",
812 extract_4ub_4f_argb,
813 { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
814 insert_4ub_4f_argb_4 },
815 4 * sizeof(GLubyte) },
816
817 { "4ub_4f_abgr",
818 extract_4ub_4f_abgr,
819 { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
820 insert_4ub_4f_abgr_4 },
821 4 * sizeof(GLubyte) },
822
823 { "4chan_4f_rgba",
824 extract_4chan_4f_rgba,
825 { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
826 insert_4chan_4f_rgba_4 },
827 4 * sizeof(GLchan) },
828
829 { "pad",
830 0,
831 { 0, 0, 0, 0 },
832 0 }
833
834 };
835
836
837 /***********************************************************************
838 * Generic (non-codegen) functions for whole vertices or groups of
839 * vertices
840 */
841
842 static void generic_emit( GLcontext *ctx,
843 GLuint start, GLuint end,
844 void *dest )
845 {
846 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
847 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
848 struct tnl_clipspace_attr *a = vtx->attr;
849 GLubyte *v = (GLubyte *)dest;
850 GLuint i, j;
851 const GLuint count = vtx->attr_count;
852 GLuint stride;
853
854 for (j = 0; j < count; j++) {
855 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
856 a[j].inputstride = vptr->stride;
857 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
858 a[j].emit = a[j].insert[vptr->size - 1];
859 }
860
861 end -= start;
862 stride = vtx->vertex_size;
863
864 for (i = 0 ; i < end ; i++, v += stride) {
865 for (j = 0; j < count; j++) {
866 GLfloat *in = (GLfloat *)a[j].inputptr;
867 a[j].inputptr += a[j].inputstride;
868 a[j].emit( &a[j], v + a[j].vertoffset, in );
869 }
870 }
871 }
872
873
874 static void generic_interp( GLcontext *ctx,
875 GLfloat t,
876 GLuint edst, GLuint eout, GLuint ein,
877 GLboolean force_boundary )
878 {
879 TNLcontext *tnl = TNL_CONTEXT(ctx);
880 struct vertex_buffer *VB = &tnl->vb;
881 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
882 const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size;
883 const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
884 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
885 const struct tnl_clipspace_attr *a = vtx->attr;
886 const GLuint attr_count = vtx->attr_count;
887 GLuint j;
888 (void) force_boundary;
889
890 if (tnl->NeedNdcCoords) {
891 const GLfloat *dstclip = VB->ClipPtr->data[edst];
892 if (dstclip[3] != 0.0) {
893 const GLfloat w = 1.0f / dstclip[3];
894 GLfloat pos[4];
895
896 pos[0] = dstclip[0] * w;
897 pos[1] = dstclip[1] * w;
898 pos[2] = dstclip[2] * w;
899 pos[3] = w;
900
901 a[0].insert[4-1]( &a[0], vdst, pos );
902 }
903 }
904 else {
905 a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
906 }
907
908
909 for (j = 1; j < attr_count; j++) {
910 GLfloat fin[4], fout[4], fdst[4];
911
912 a[j].extract( &a[j], fin, vin + a[j].vertoffset );
913 a[j].extract( &a[j], fout, vout + a[j].vertoffset );
914
915 INTERP_F( t, fdst[3], fout[3], fin[3] );
916 INTERP_F( t, fdst[2], fout[2], fin[2] );
917 INTERP_F( t, fdst[1], fout[1], fin[1] );
918 INTERP_F( t, fdst[0], fout[0], fin[0] );
919
920 a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
921 }
922 }
923
924
925 /* Extract color attributes from one vertex and insert them into
926 * another. (Shortcircuit extract/insert with memcpy).
927 */
928 static void generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
929 {
930 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
931 GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
932 GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
933 const struct tnl_clipspace_attr *a = vtx->attr;
934 const GLuint attr_count = vtx->attr_count;
935 GLuint j;
936
937 for (j = 0; j < attr_count; j++) {
938 if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
939 a[j].attrib == VERT_ATTRIB_COLOR1) {
940
941 _mesa_memcpy( vdst + a[j].vertoffset,
942 vsrc + a[j].vertoffset,
943 a[j].vertattrsize );
944 }
945 }
946 }
947
948
949 /* Helper functions for hardware which doesn't put back colors and/or
950 * edgeflags into vertices.
951 */
952 static void generic_interp_extras( GLcontext *ctx,
953 GLfloat t,
954 GLuint dst, GLuint out, GLuint in,
955 GLboolean force_boundary )
956 {
957 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
958
959 if (VB->ColorPtr[1]) {
960 assert(VB->ColorPtr[1]->stride == 4 * sizeof(GLfloat));
961
962 INTERP_4F( t,
963 VB->ColorPtr[1]->data[dst],
964 VB->ColorPtr[1]->data[out],
965 VB->ColorPtr[1]->data[in] );
966
967 if (VB->SecondaryColorPtr[1]) {
968 INTERP_3F( t,
969 VB->SecondaryColorPtr[1]->data[dst],
970 VB->SecondaryColorPtr[1]->data[out],
971 VB->SecondaryColorPtr[1]->data[in] );
972 }
973 }
974 else if (VB->IndexPtr[1]) {
975 VB->IndexPtr[1]->data[dst][0] = LINTERP( t,
976 VB->IndexPtr[1]->data[out][0],
977 VB->IndexPtr[1]->data[in][0] );
978 }
979
980 if (VB->EdgeFlag) {
981 VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
982 }
983
984 generic_interp(ctx, t, dst, out, in, force_boundary);
985 }
986
987 static void generic_copy_pv_extras( GLcontext *ctx,
988 GLuint dst, GLuint src )
989 {
990 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
991
992 if (VB->ColorPtr[1]) {
993 COPY_4FV( VB->ColorPtr[1]->data[dst],
994 VB->ColorPtr[1]->data[src] );
995
996 if (VB->SecondaryColorPtr[1]) {
997 COPY_4FV( VB->SecondaryColorPtr[1]->data[dst],
998 VB->SecondaryColorPtr[1]->data[src] );
999 }
1000 }
1001 else if (VB->IndexPtr[1]) {
1002 VB->IndexPtr[1]->data[dst][0] = VB->IndexPtr[1]->data[src][0];
1003 }
1004
1005 generic_copy_pv(ctx, dst, src);
1006 }
1007
1008
1009
1010
1011 /***********************************************************************
1012 * Build codegen functions or return generic ones:
1013 */
1014
1015
1016 static void do_emit( GLcontext *ctx, GLuint start, GLuint end,
1017 void *dest)
1018 {
1019 TNLcontext *tnl = TNL_CONTEXT(ctx);
1020 struct vertex_buffer *VB = &tnl->vb;
1021 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1022 struct tnl_clipspace_attr *a = vtx->attr;
1023 const GLuint count = vtx->attr_count;
1024 GLuint j;
1025
1026 for (j = 0; j < count; j++) {
1027 GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
1028 a[j].inputstride = vptr->stride;
1029 a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
1030 a[j].emit = a[j].insert[vptr->size - 1];
1031 }
1032
1033 vtx->emit = 0;
1034
1035 if (0)
1036 vtx->emit = _tnl_codegen_emit(ctx);
1037
1038 if (!vtx->emit)
1039 vtx->emit = generic_emit;
1040
1041 vtx->emit( ctx, start, end, dest );
1042 }
1043
1044
1045
1046 static void choose_interp_func( GLcontext *ctx,
1047 GLfloat t,
1048 GLuint edst, GLuint eout, GLuint ein,
1049 GLboolean force_boundary )
1050 {
1051 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1052
1053 if (vtx->need_extras &&
1054 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
1055 vtx->interp = generic_interp_extras;
1056 } else {
1057 vtx->interp = generic_interp;
1058 }
1059
1060 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
1061 }
1062
1063
1064 static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc )
1065 {
1066 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1067
1068 if (vtx->need_extras &&
1069 (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
1070 vtx->copy_pv = generic_copy_pv_extras;
1071 } else {
1072 vtx->copy_pv = generic_copy_pv;
1073 }
1074
1075 vtx->copy_pv( ctx, edst, esrc );
1076 }
1077
1078
1079 /***********************************************************************
1080 * Public entrypoints, mostly dispatch to the above:
1081 */
1082
1083
1084 /* Interpolate between two vertices to produce a third:
1085 */
1086 void _tnl_interp( GLcontext *ctx,
1087 GLfloat t,
1088 GLuint edst, GLuint eout, GLuint ein,
1089 GLboolean force_boundary )
1090 {
1091 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1092 vtx->interp( ctx, t, edst, eout, ein, force_boundary );
1093 }
1094
1095 /* Copy colors from one vertex to another:
1096 */
1097 void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc )
1098 {
1099 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1100 vtx->copy_pv( ctx, edst, esrc );
1101 }
1102
1103
1104 /* Extract a named attribute from a hardware vertex. Will have to
1105 * reverse any viewport transformation, swizzling or other conversions
1106 * which may have been applied:
1107 */
1108 void _tnl_get_attr( GLcontext *ctx, const void *vin,
1109 GLenum attr, GLfloat *dest )
1110 {
1111 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1112 const struct tnl_clipspace_attr *a = vtx->attr;
1113 const GLuint attr_count = vtx->attr_count;
1114 GLuint j;
1115
1116 for (j = 0; j < attr_count; j++) {
1117 if (a[j].attrib == attr) {
1118 a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
1119 return;
1120 }
1121 }
1122
1123 /* Else return the value from ctx->Current -- dangerous???
1124 */
1125 _mesa_memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
1126 }
1127
1128
1129 /* Complementary operation to the above.
1130 */
1131 void _tnl_set_attr( GLcontext *ctx, void *vout,
1132 GLenum attr, const GLfloat *src )
1133 {
1134 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1135 const struct tnl_clipspace_attr *a = vtx->attr;
1136 const GLuint attr_count = vtx->attr_count;
1137 GLuint j;
1138
1139 for (j = 0; j < attr_count; j++) {
1140 if (a[j].attrib == attr) {
1141 a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
1142 return;
1143 }
1144 }
1145 }
1146
1147
1148 void *_tnl_get_vertex( GLcontext *ctx, GLuint nr )
1149 {
1150 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1151
1152 return vtx->vertex_buf + nr * vtx->vertex_size;
1153 }
1154
1155 void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state )
1156 {
1157 if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
1158 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1159 vtx->new_inputs = ~0;
1160 vtx->interp = choose_interp_func;
1161 vtx->copy_pv = choose_copy_pv_func;
1162 }
1163 }
1164
1165
1166 GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map,
1167 GLuint nr, const GLfloat *vp,
1168 GLuint unpacked_size )
1169 {
1170 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1171 GLuint offset = 0;
1172 GLuint i, j;
1173
1174 assert(nr < _TNL_ATTRIB_MAX);
1175 assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
1176
1177 vtx->emit = 0;
1178 vtx->interp = choose_interp_func;
1179 vtx->copy_pv = choose_copy_pv_func;
1180 vtx->new_inputs = ~0;
1181
1182 for (j = 0, i = 0; i < nr; i++) {
1183 const GLuint format = map[i].format;
1184 if (format == EMIT_PAD) {
1185 /*
1186 fprintf(stderr, "%d: pad %d, offset %d\n", i,
1187 map[i].offset, offset);
1188 */
1189 offset += map[i].offset;
1190
1191 }
1192 else {
1193 vtx->attr[j].attrib = map[i].attrib;
1194 vtx->attr[j].format = format;
1195 vtx->attr[j].vp = vp;
1196 vtx->attr[j].insert = format_info[format].insert;
1197 vtx->attr[j].extract = format_info[format].extract;
1198 vtx->attr[j].vertattrsize = format_info[format].attrsize;
1199
1200 if (unpacked_size)
1201 vtx->attr[j].vertoffset = map[i].offset;
1202 else
1203 vtx->attr[j].vertoffset = offset;
1204
1205 /*
1206 fprintf(stderr, "%d: %s, vp %p, offset %d\n", i,
1207 format_info[format].name, (void *)vp,
1208 vtx->attr[j].vertoffset);
1209 */
1210 offset += format_info[format].attrsize;
1211 j++;
1212 }
1213 }
1214
1215 vtx->attr_count = j;
1216
1217 if (unpacked_size)
1218 vtx->vertex_size = unpacked_size;
1219 else
1220 vtx->vertex_size = offset;
1221
1222 assert(vtx->vertex_size <= vtx->max_vertex_size);
1223
1224 return vtx->vertex_size;
1225 }
1226
1227
1228
1229 void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs )
1230 {
1231 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1232 vtx->new_inputs |= newinputs;
1233 }
1234
1235
1236 void _tnl_build_vertices( GLcontext *ctx,
1237 GLuint start,
1238 GLuint end,
1239 GLuint newinputs )
1240 {
1241 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1242 const GLuint stride = vtx->vertex_size;
1243 GLubyte *vDest = ((GLubyte *)vtx->vertex_buf + (start*stride));
1244
1245 newinputs |= vtx->new_inputs;
1246 vtx->new_inputs = 0;
1247
1248 if (newinputs)
1249 do_emit( ctx, start, end, vDest );
1250 }
1251
1252
1253 void *_tnl_emit_vertices_to_buffer( GLcontext *ctx,
1254 GLuint start,
1255 GLuint end,
1256 void *dest )
1257 {
1258 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1259 do_emit( ctx, start, end, dest );
1260 return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
1261 }
1262
1263
1264 void _tnl_init_vertices( GLcontext *ctx,
1265 GLuint vb_size,
1266 GLuint max_vertex_size )
1267 {
1268 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1269
1270 _tnl_install_attrs( ctx, 0, 0, 0, 0 );
1271
1272 vtx->need_extras = GL_TRUE;
1273 if (max_vertex_size > vtx->max_vertex_size) {
1274 _tnl_free_vertices( ctx );
1275 vtx->max_vertex_size = max_vertex_size;
1276 vtx->vertex_buf = (GLubyte *)ALIGN_CALLOC(vb_size * max_vertex_size, 32 );
1277 }
1278
1279 _tnl_init_c_codegen( &vtx->codegen );
1280 }
1281
1282
1283 void _tnl_free_vertices( GLcontext *ctx )
1284 {
1285 struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
1286 if (vtx->vertex_buf) {
1287 ALIGN_FREE(vtx->vertex_buf);
1288 vtx->vertex_buf = 0;
1289 }
1290 }