merge current trunk into vbo branch
[mesa.git] / src / mesa / drivers / dri / i915tex / intel_tris.c
1 /**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * 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
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 #include "glheader.h"
29 #include "context.h"
30 #include "macros.h"
31 #include "enums.h"
32 #include "texobj.h"
33 #include "state.h"
34 #include "dd.h"
35
36 #include "swrast/swrast.h"
37 #include "swrast_setup/swrast_setup.h"
38 #include "tnl/t_context.h"
39 #include "tnl/t_pipeline.h"
40 #include "tnl/t_vertex.h"
41
42 #include "intel_screen.h"
43 #include "intel_context.h"
44 #include "intel_tris.h"
45 #include "intel_batchbuffer.h"
46 #include "intel_reg.h"
47 #include "intel_span.h"
48 #include "intel_tex.h"
49
50 static void intelRenderPrimitive(GLcontext * ctx, GLenum prim);
51 static void intelRasterPrimitive(GLcontext * ctx, GLenum rprim,
52 GLuint hwprim);
53
54 /*
55 */
56 static void
57 intel_flush_inline_primitive(struct intel_context *intel)
58 {
59 GLuint used = intel->batch->ptr - intel->prim.start_ptr;
60
61 assert(intel->prim.primitive != ~0);
62
63 /* _mesa_printf("/\n"); */
64
65 if (used < 8)
66 goto do_discard;
67
68 *(int *) intel->prim.start_ptr = (_3DPRIMITIVE |
69 intel->prim.primitive | (used / 4 - 2));
70
71 goto finished;
72
73 do_discard:
74 intel->batch->ptr -= used;
75
76 finished:
77 intel->prim.primitive = ~0;
78 intel->prim.start_ptr = 0;
79 intel->prim.flush = 0;
80 }
81
82
83 /* Emit a primitive referencing vertices in a vertex buffer.
84 */
85 void
86 intelStartInlinePrimitive(struct intel_context *intel,
87 GLuint prim, GLuint batch_flags)
88 {
89 BATCH_LOCALS;
90
91 intel->vtbl.emit_state(intel);
92
93 /* Need to make sure at the very least that we don't wrap
94 * batchbuffers in BEGIN_BATCH below, otherwise the primitive will
95 * be emitted to a batchbuffer missing the required full-state
96 * preamble.
97 */
98 if (intel_batchbuffer_space(intel->batch) < 100) {
99 intel_batchbuffer_flush(intel->batch);
100 intel->vtbl.emit_state(intel);
101 }
102
103 /* _mesa_printf("%s *", __progname); */
104
105 /* Emit a slot which will be filled with the inline primitive
106 * command later.
107 */
108 BEGIN_BATCH(2, batch_flags);
109 OUT_BATCH(0);
110
111 intel->prim.start_ptr = intel->batch->ptr;
112 intel->prim.primitive = prim;
113 intel->prim.flush = intel_flush_inline_primitive;
114
115 OUT_BATCH(0);
116 ADVANCE_BATCH();
117
118 /* _mesa_printf(">"); */
119 }
120
121
122 void
123 intelWrapInlinePrimitive(struct intel_context *intel)
124 {
125 GLuint prim = intel->prim.primitive;
126 GLuint batchflags = intel->batch->flags;
127
128 intel_flush_inline_primitive(intel);
129 intel_batchbuffer_flush(intel->batch);
130 intelStartInlinePrimitive(intel, prim, batchflags); /* ??? */
131 }
132
133 GLuint *
134 intelExtendInlinePrimitive(struct intel_context *intel, GLuint dwords)
135 {
136 GLuint sz = dwords * sizeof(GLuint);
137 GLuint *ptr;
138
139 assert(intel->prim.flush == intel_flush_inline_primitive);
140
141 if (intel_batchbuffer_space(intel->batch) < sz)
142 intelWrapInlinePrimitive(intel);
143
144 /* _mesa_printf("."); */
145
146 intel->vtbl.assert_not_dirty(intel);
147
148 ptr = (GLuint *) intel->batch->ptr;
149 intel->batch->ptr += sz;
150
151 return ptr;
152 }
153
154
155
156 /***********************************************************************
157 * Emit primitives as inline vertices *
158 ***********************************************************************/
159
160 #ifdef __i386__
161 #define COPY_DWORDS( j, vb, vertsize, v ) \
162 do { \
163 int __tmp; \
164 __asm__ __volatile__( "rep ; movsl" \
165 : "=%c" (j), "=D" (vb), "=S" (__tmp) \
166 : "0" (vertsize), \
167 "D" ((long)vb), \
168 "S" ((long)v) ); \
169 } while (0)
170 #else
171 #define COPY_DWORDS( j, vb, vertsize, v ) \
172 do { \
173 for ( j = 0 ; j < vertsize ; j++ ) { \
174 vb[j] = ((GLuint *)v)[j]; \
175 } \
176 vb += vertsize; \
177 } while (0)
178 #endif
179
180 static void
181 intel_draw_quad(struct intel_context *intel,
182 intelVertexPtr v0,
183 intelVertexPtr v1, intelVertexPtr v2, intelVertexPtr v3)
184 {
185 GLuint vertsize = intel->vertex_size;
186 GLuint *vb = intelExtendInlinePrimitive(intel, 6 * vertsize);
187 int j;
188
189 COPY_DWORDS(j, vb, vertsize, v0);
190 COPY_DWORDS(j, vb, vertsize, v1);
191
192 /* If smooth shading, draw like a trifan which gives better
193 * rasterization. Otherwise draw as two triangles with provoking
194 * vertex in third position as required for flat shading.
195 */
196 if (intel->ctx.Light.ShadeModel == GL_FLAT) {
197 COPY_DWORDS(j, vb, vertsize, v3);
198 COPY_DWORDS(j, vb, vertsize, v1);
199 }
200 else {
201 COPY_DWORDS(j, vb, vertsize, v2);
202 COPY_DWORDS(j, vb, vertsize, v0);
203 }
204
205 COPY_DWORDS(j, vb, vertsize, v2);
206 COPY_DWORDS(j, vb, vertsize, v3);
207 }
208
209 static void
210 intel_draw_triangle(struct intel_context *intel,
211 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
212 {
213 GLuint vertsize = intel->vertex_size;
214 GLuint *vb = intelExtendInlinePrimitive(intel, 3 * vertsize);
215 int j;
216
217 COPY_DWORDS(j, vb, vertsize, v0);
218 COPY_DWORDS(j, vb, vertsize, v1);
219 COPY_DWORDS(j, vb, vertsize, v2);
220 }
221
222
223 static void
224 intel_draw_line(struct intel_context *intel,
225 intelVertexPtr v0, intelVertexPtr v1)
226 {
227 GLuint vertsize = intel->vertex_size;
228 GLuint *vb = intelExtendInlinePrimitive(intel, 2 * vertsize);
229 int j;
230
231 COPY_DWORDS(j, vb, vertsize, v0);
232 COPY_DWORDS(j, vb, vertsize, v1);
233 }
234
235
236 static void
237 intel_draw_point(struct intel_context *intel, intelVertexPtr v0)
238 {
239 GLuint vertsize = intel->vertex_size;
240 GLuint *vb = intelExtendInlinePrimitive(intel, vertsize);
241 int j;
242
243 /* Adjust for sub pixel position -- still required for conform. */
244 *(float *) &vb[0] = v0->v.x - 0.125;
245 *(float *) &vb[1] = v0->v.y - 0.125;
246 for (j = 2; j < vertsize; j++)
247 vb[j] = v0->ui[j];
248 }
249
250
251
252 /***********************************************************************
253 * Fixup for ARB_point_parameters *
254 ***********************************************************************/
255
256 /* Currently not working - VERT_ATTRIB_POINTSIZE isn't correctly
257 * represented in the fragment program InputsRead field.
258 */
259 static void
260 intel_atten_point(struct intel_context *intel, intelVertexPtr v0)
261 {
262 GLcontext *ctx = &intel->ctx;
263 GLfloat psz[4], col[4], restore_psz, restore_alpha;
264
265 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
266 _tnl_get_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
267
268 restore_psz = psz[0];
269 restore_alpha = col[3];
270
271 if (psz[0] >= ctx->Point.Threshold) {
272 psz[0] = MIN2(psz[0], ctx->Point.MaxSize);
273 }
274 else {
275 GLfloat dsize = psz[0] / ctx->Point.Threshold;
276 psz[0] = MAX2(ctx->Point.Threshold, ctx->Point.MinSize);
277 col[3] *= dsize * dsize;
278 }
279
280 if (psz[0] < 1.0)
281 psz[0] = 1.0;
282
283 if (restore_psz != psz[0] || restore_alpha != col[3]) {
284 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
285 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
286
287 intel_draw_point(intel, v0);
288
289 psz[0] = restore_psz;
290 col[3] = restore_alpha;
291
292 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_POINTSIZE, psz);
293 _tnl_set_attr(ctx, v0, _TNL_ATTRIB_COLOR0, col);
294 }
295 else
296 intel_draw_point(intel, v0);
297 }
298
299
300
301
302
303 /***********************************************************************
304 * Fixup for I915 WPOS texture coordinate *
305 ***********************************************************************/
306
307
308
309 static void
310 intel_wpos_triangle(struct intel_context *intel,
311 intelVertexPtr v0, intelVertexPtr v1, intelVertexPtr v2)
312 {
313 GLuint offset = intel->wpos_offset;
314 GLuint size = intel->wpos_size;
315
316 __memcpy(((char *) v0) + offset, v0, size);
317 __memcpy(((char *) v1) + offset, v1, size);
318 __memcpy(((char *) v2) + offset, v2, size);
319
320 intel_draw_triangle(intel, v0, v1, v2);
321 }
322
323
324 static void
325 intel_wpos_line(struct intel_context *intel,
326 intelVertexPtr v0, intelVertexPtr v1)
327 {
328 GLuint offset = intel->wpos_offset;
329 GLuint size = intel->wpos_size;
330
331 __memcpy(((char *) v0) + offset, v0, size);
332 __memcpy(((char *) v1) + offset, v1, size);
333
334 intel_draw_line(intel, v0, v1);
335 }
336
337
338 static void
339 intel_wpos_point(struct intel_context *intel, intelVertexPtr v0)
340 {
341 GLuint offset = intel->wpos_offset;
342 GLuint size = intel->wpos_size;
343
344 __memcpy(((char *) v0) + offset, v0, size);
345
346 intel_draw_point(intel, v0);
347 }
348
349
350
351
352
353
354 /***********************************************************************
355 * Macros for t_dd_tritmp.h to draw basic primitives *
356 ***********************************************************************/
357
358 #define TRI( a, b, c ) \
359 do { \
360 if (DO_FALLBACK) \
361 intel->draw_tri( intel, a, b, c ); \
362 else \
363 intel_draw_triangle( intel, a, b, c ); \
364 } while (0)
365
366 #define QUAD( a, b, c, d ) \
367 do { \
368 if (DO_FALLBACK) { \
369 intel->draw_tri( intel, a, b, d ); \
370 intel->draw_tri( intel, b, c, d ); \
371 } else \
372 intel_draw_quad( intel, a, b, c, d ); \
373 } while (0)
374
375 #define LINE( v0, v1 ) \
376 do { \
377 if (DO_FALLBACK) \
378 intel->draw_line( intel, v0, v1 ); \
379 else \
380 intel_draw_line( intel, v0, v1 ); \
381 } while (0)
382
383 #define POINT( v0 ) \
384 do { \
385 if (DO_FALLBACK) \
386 intel->draw_point( intel, v0 ); \
387 else \
388 intel_draw_point( intel, v0 ); \
389 } while (0)
390
391
392 /***********************************************************************
393 * Build render functions from dd templates *
394 ***********************************************************************/
395
396 #define INTEL_OFFSET_BIT 0x01
397 #define INTEL_TWOSIDE_BIT 0x02
398 #define INTEL_UNFILLED_BIT 0x04
399 #define INTEL_FALLBACK_BIT 0x08
400 #define INTEL_MAX_TRIFUNC 0x10
401
402
403 static struct
404 {
405 tnl_points_func points;
406 tnl_line_func line;
407 tnl_triangle_func triangle;
408 tnl_quad_func quad;
409 } rast_tab[INTEL_MAX_TRIFUNC];
410
411
412 #define DO_FALLBACK (IND & INTEL_FALLBACK_BIT)
413 #define DO_OFFSET (IND & INTEL_OFFSET_BIT)
414 #define DO_UNFILLED (IND & INTEL_UNFILLED_BIT)
415 #define DO_TWOSIDE (IND & INTEL_TWOSIDE_BIT)
416 #define DO_FLAT 0
417 #define DO_TRI 1
418 #define DO_QUAD 1
419 #define DO_LINE 1
420 #define DO_POINTS 1
421 #define DO_FULL_QUAD 1
422
423 #define HAVE_RGBA 1
424 #define HAVE_SPEC 1
425 #define HAVE_BACK_COLORS 0
426 #define HAVE_HW_FLATSHADE 1
427 #define VERTEX intelVertex
428 #define TAB rast_tab
429
430 /* Only used to pull back colors into vertices (ie, we know color is
431 * floating point).
432 */
433 #define INTEL_COLOR( dst, src ) \
434 do { \
435 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
436 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
437 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
438 UNCLAMPED_FLOAT_TO_UBYTE((dst)[3], (src)[3]); \
439 } while (0)
440
441 #define INTEL_SPEC( dst, src ) \
442 do { \
443 UNCLAMPED_FLOAT_TO_UBYTE((dst)[0], (src)[2]); \
444 UNCLAMPED_FLOAT_TO_UBYTE((dst)[1], (src)[1]); \
445 UNCLAMPED_FLOAT_TO_UBYTE((dst)[2], (src)[0]); \
446 } while (0)
447
448
449 #define DEPTH_SCALE intel->polygon_offset_scale
450 #define UNFILLED_TRI unfilled_tri
451 #define UNFILLED_QUAD unfilled_quad
452 #define VERT_X(_v) _v->v.x
453 #define VERT_Y(_v) _v->v.y
454 #define VERT_Z(_v) _v->v.z
455 #define AREA_IS_CCW( a ) (a > 0)
456 #define GET_VERTEX(e) (intel->verts + (e * intel->vertex_size * sizeof(GLuint)))
457
458 #define VERT_SET_RGBA( v, c ) if (coloroffset) INTEL_COLOR( v->ub4[coloroffset], c )
459 #define VERT_COPY_RGBA( v0, v1 ) if (coloroffset) v0->ui[coloroffset] = v1->ui[coloroffset]
460 #define VERT_SAVE_RGBA( idx ) if (coloroffset) color[idx] = v[idx]->ui[coloroffset]
461 #define VERT_RESTORE_RGBA( idx ) if (coloroffset) v[idx]->ui[coloroffset] = color[idx]
462
463 #define VERT_SET_SPEC( v, c ) if (specoffset) INTEL_SPEC( v->ub4[specoffset], c )
464 #define VERT_COPY_SPEC( v0, v1 ) if (specoffset) COPY_3V(v0->ub4[specoffset], v1->ub4[specoffset])
465 #define VERT_SAVE_SPEC( idx ) if (specoffset) spec[idx] = v[idx]->ui[specoffset]
466 #define VERT_RESTORE_SPEC( idx ) if (specoffset) v[idx]->ui[specoffset] = spec[idx]
467
468 #define LOCAL_VARS(n) \
469 struct intel_context *intel = intel_context(ctx); \
470 GLuint color[n], spec[n]; \
471 GLuint coloroffset = intel->coloroffset; \
472 GLboolean specoffset = intel->specoffset; \
473 (void) color; (void) spec; (void) coloroffset; (void) specoffset;
474
475
476 /***********************************************************************
477 * Helpers for rendering unfilled primitives *
478 ***********************************************************************/
479
480 static const GLuint hw_prim[GL_POLYGON + 1] = {
481 PRIM3D_POINTLIST,
482 PRIM3D_LINELIST,
483 PRIM3D_LINELIST,
484 PRIM3D_LINELIST,
485 PRIM3D_TRILIST,
486 PRIM3D_TRILIST,
487 PRIM3D_TRILIST,
488 PRIM3D_TRILIST,
489 PRIM3D_TRILIST,
490 PRIM3D_TRILIST
491 };
492
493 #define RASTERIZE(x) intelRasterPrimitive( ctx, x, hw_prim[x] )
494 #define RENDER_PRIMITIVE intel->render_primitive
495 #define TAG(x) x
496 #define IND INTEL_FALLBACK_BIT
497 #include "tnl_dd/t_dd_unfilled.h"
498 #undef IND
499
500 /***********************************************************************
501 * Generate GL render functions *
502 ***********************************************************************/
503
504 #define IND (0)
505 #define TAG(x) x
506 #include "tnl_dd/t_dd_tritmp.h"
507
508 #define IND (INTEL_OFFSET_BIT)
509 #define TAG(x) x##_offset
510 #include "tnl_dd/t_dd_tritmp.h"
511
512 #define IND (INTEL_TWOSIDE_BIT)
513 #define TAG(x) x##_twoside
514 #include "tnl_dd/t_dd_tritmp.h"
515
516 #define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT)
517 #define TAG(x) x##_twoside_offset
518 #include "tnl_dd/t_dd_tritmp.h"
519
520 #define IND (INTEL_UNFILLED_BIT)
521 #define TAG(x) x##_unfilled
522 #include "tnl_dd/t_dd_tritmp.h"
523
524 #define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
525 #define TAG(x) x##_offset_unfilled
526 #include "tnl_dd/t_dd_tritmp.h"
527
528 #define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT)
529 #define TAG(x) x##_twoside_unfilled
530 #include "tnl_dd/t_dd_tritmp.h"
531
532 #define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT)
533 #define TAG(x) x##_twoside_offset_unfilled
534 #include "tnl_dd/t_dd_tritmp.h"
535
536 #define IND (INTEL_FALLBACK_BIT)
537 #define TAG(x) x##_fallback
538 #include "tnl_dd/t_dd_tritmp.h"
539
540 #define IND (INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
541 #define TAG(x) x##_offset_fallback
542 #include "tnl_dd/t_dd_tritmp.h"
543
544 #define IND (INTEL_TWOSIDE_BIT|INTEL_FALLBACK_BIT)
545 #define TAG(x) x##_twoside_fallback
546 #include "tnl_dd/t_dd_tritmp.h"
547
548 #define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_FALLBACK_BIT)
549 #define TAG(x) x##_twoside_offset_fallback
550 #include "tnl_dd/t_dd_tritmp.h"
551
552 #define IND (INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
553 #define TAG(x) x##_unfilled_fallback
554 #include "tnl_dd/t_dd_tritmp.h"
555
556 #define IND (INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
557 #define TAG(x) x##_offset_unfilled_fallback
558 #include "tnl_dd/t_dd_tritmp.h"
559
560 #define IND (INTEL_TWOSIDE_BIT|INTEL_UNFILLED_BIT|INTEL_FALLBACK_BIT)
561 #define TAG(x) x##_twoside_unfilled_fallback
562 #include "tnl_dd/t_dd_tritmp.h"
563
564 #define IND (INTEL_TWOSIDE_BIT|INTEL_OFFSET_BIT|INTEL_UNFILLED_BIT| \
565 INTEL_FALLBACK_BIT)
566 #define TAG(x) x##_twoside_offset_unfilled_fallback
567 #include "tnl_dd/t_dd_tritmp.h"
568
569
570 static void
571 init_rast_tab(void)
572 {
573 init();
574 init_offset();
575 init_twoside();
576 init_twoside_offset();
577 init_unfilled();
578 init_offset_unfilled();
579 init_twoside_unfilled();
580 init_twoside_offset_unfilled();
581 init_fallback();
582 init_offset_fallback();
583 init_twoside_fallback();
584 init_twoside_offset_fallback();
585 init_unfilled_fallback();
586 init_offset_unfilled_fallback();
587 init_twoside_unfilled_fallback();
588 init_twoside_offset_unfilled_fallback();
589 }
590
591
592 /***********************************************************************
593 * Rasterization fallback helpers *
594 ***********************************************************************/
595
596
597 /* This code is hit only when a mix of accelerated and unaccelerated
598 * primitives are being drawn, and only for the unaccelerated
599 * primitives.
600 */
601 static void
602 intel_fallback_tri(struct intel_context *intel,
603 intelVertex * v0, intelVertex * v1, intelVertex * v2)
604 {
605 GLcontext *ctx = &intel->ctx;
606 SWvertex v[3];
607
608 if (0)
609 fprintf(stderr, "\n%s\n", __FUNCTION__);
610
611 INTEL_FIREVERTICES(intel);
612
613 _swsetup_Translate(ctx, v0, &v[0]);
614 _swsetup_Translate(ctx, v1, &v[1]);
615 _swsetup_Translate(ctx, v2, &v[2]);
616 intelSpanRenderStart(ctx);
617 _swrast_Triangle(ctx, &v[0], &v[1], &v[2]);
618 intelSpanRenderFinish(ctx);
619 }
620
621
622 static void
623 intel_fallback_line(struct intel_context *intel,
624 intelVertex * v0, intelVertex * v1)
625 {
626 GLcontext *ctx = &intel->ctx;
627 SWvertex v[2];
628
629 if (0)
630 fprintf(stderr, "\n%s\n", __FUNCTION__);
631
632 INTEL_FIREVERTICES(intel);
633
634 _swsetup_Translate(ctx, v0, &v[0]);
635 _swsetup_Translate(ctx, v1, &v[1]);
636 intelSpanRenderStart(ctx);
637 _swrast_Line(ctx, &v[0], &v[1]);
638 intelSpanRenderFinish(ctx);
639 }
640
641 static void
642 intel_fallback_point(struct intel_context *intel,
643 intelVertex * v0)
644 {
645 GLcontext *ctx = &intel->ctx;
646 SWvertex v[1];
647
648 if (0)
649 fprintf(stderr, "\n%s\n", __FUNCTION__);
650
651 INTEL_FIREVERTICES(intel);
652
653 _swsetup_Translate(ctx, v0, &v[0]);
654 intelSpanRenderStart(ctx);
655 _swrast_Point(ctx, &v[0]);
656 intelSpanRenderFinish(ctx);
657 }
658
659
660 /**********************************************************************/
661 /* Render unclipped begin/end objects */
662 /**********************************************************************/
663
664 #define IND 0
665 #define V(x) (intelVertex *)(vertptr + ((x)*vertsize*sizeof(GLuint)))
666 #define RENDER_POINTS( start, count ) \
667 for ( ; start < count ; start++) POINT( V(ELT(start)) );
668 #define RENDER_LINE( v0, v1 ) LINE( V(v0), V(v1) )
669 #define RENDER_TRI( v0, v1, v2 ) TRI( V(v0), V(v1), V(v2) )
670 #define RENDER_QUAD( v0, v1, v2, v3 ) QUAD( V(v0), V(v1), V(v2), V(v3) )
671 #define INIT(x) intelRenderPrimitive( ctx, x )
672 #undef LOCAL_VARS
673 #define LOCAL_VARS \
674 struct intel_context *intel = intel_context(ctx); \
675 GLubyte *vertptr = (GLubyte *)intel->verts; \
676 const GLuint vertsize = intel->vertex_size; \
677 const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
678 (void) elt;
679 #define RESET_STIPPLE
680 #define RESET_OCCLUSION
681 #define PRESERVE_VB_DEFS
682 #define ELT(x) x
683 #define TAG(x) intel_##x##_verts
684 #include "tnl/t_vb_rendertmp.h"
685 #undef ELT
686 #undef TAG
687 #define TAG(x) intel_##x##_elts
688 #define ELT(x) elt[x]
689 #include "tnl/t_vb_rendertmp.h"
690
691 /**********************************************************************/
692 /* Render clipped primitives */
693 /**********************************************************************/
694
695
696
697 static void
698 intelRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
699 {
700 struct intel_context *intel = intel_context(ctx);
701 TNLcontext *tnl = TNL_CONTEXT(ctx);
702 struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
703 GLuint prim = intel->render_primitive;
704
705 /* Render the new vertices as an unclipped polygon.
706 */
707 {
708 GLuint *tmp = VB->Elts;
709 VB->Elts = (GLuint *) elts;
710 tnl->Driver.Render.PrimTabElts[GL_POLYGON] (ctx, 0, n,
711 PRIM_BEGIN | PRIM_END);
712 VB->Elts = tmp;
713 }
714
715 /* Restore the render primitive
716 */
717 if (prim != GL_POLYGON)
718 tnl->Driver.Render.PrimitiveNotify(ctx, prim);
719 }
720
721 static void
722 intelRenderClippedLine(GLcontext * ctx, GLuint ii, GLuint jj)
723 {
724 TNLcontext *tnl = TNL_CONTEXT(ctx);
725
726 tnl->Driver.Render.Line(ctx, ii, jj);
727 }
728
729 static void
730 intelFastRenderClippedPoly(GLcontext * ctx, const GLuint * elts, GLuint n)
731 {
732 struct intel_context *intel = intel_context(ctx);
733 const GLuint vertsize = intel->vertex_size;
734 GLuint *vb = intelExtendInlinePrimitive(intel, (n - 2) * 3 * vertsize);
735 GLubyte *vertptr = (GLubyte *) intel->verts;
736 const GLuint *start = (const GLuint *) V(elts[0]);
737 int i, j;
738
739 for (i = 2; i < n; i++) {
740 COPY_DWORDS(j, vb, vertsize, V(elts[i - 1]));
741 COPY_DWORDS(j, vb, vertsize, V(elts[i]));
742 COPY_DWORDS(j, vb, vertsize, start);
743 }
744 }
745
746 /**********************************************************************/
747 /* Choose render functions */
748 /**********************************************************************/
749
750
751
752
753 #define ANY_FALLBACK_FLAGS (DD_LINE_STIPPLE | DD_TRI_STIPPLE | DD_POINT_ATTEN | DD_POINT_SMOOTH | DD_TRI_SMOOTH)
754 #define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE | DD_TRI_OFFSET | DD_TRI_UNFILLED)
755
756 void
757 intelChooseRenderState(GLcontext * ctx)
758 {
759 TNLcontext *tnl = TNL_CONTEXT(ctx);
760 struct intel_context *intel = intel_context(ctx);
761 GLuint flags = ctx->_TriangleCaps;
762 const struct gl_fragment_program *fprog = ctx->FragmentProgram._Current;
763 GLboolean have_wpos = (fprog && (fprog->Base.InputsRead & FRAG_BIT_WPOS));
764 GLuint index = 0;
765
766 if (INTEL_DEBUG & DEBUG_STATE)
767 fprintf(stderr, "\n%s\n", __FUNCTION__);
768
769 if ((flags & (ANY_FALLBACK_FLAGS | ANY_RASTER_FLAGS)) || have_wpos) {
770
771 if (flags & ANY_RASTER_FLAGS) {
772 if (flags & DD_TRI_LIGHT_TWOSIDE)
773 index |= INTEL_TWOSIDE_BIT;
774 if (flags & DD_TRI_OFFSET)
775 index |= INTEL_OFFSET_BIT;
776 if (flags & DD_TRI_UNFILLED)
777 index |= INTEL_UNFILLED_BIT;
778 }
779
780 if (have_wpos) {
781 intel->draw_point = intel_wpos_point;
782 intel->draw_line = intel_wpos_line;
783 intel->draw_tri = intel_wpos_triangle;
784
785 /* Make sure these get called:
786 */
787 index |= INTEL_FALLBACK_BIT;
788 }
789 else {
790 intel->draw_point = intel_draw_point;
791 intel->draw_line = intel_draw_line;
792 intel->draw_tri = intel_draw_triangle;
793 }
794
795 /* Hook in fallbacks for specific primitives.
796 */
797 if (flags & ANY_FALLBACK_FLAGS) {
798 if (flags & DD_LINE_STIPPLE)
799 intel->draw_line = intel_fallback_line;
800
801 if ((flags & DD_TRI_STIPPLE) && !intel->hw_stipple)
802 intel->draw_tri = intel_fallback_tri;
803
804 if (flags & DD_TRI_SMOOTH) {
805 if (intel->strict_conformance)
806 intel->draw_tri = intel_fallback_tri;
807 }
808
809 if (flags & DD_POINT_ATTEN) {
810 if (0)
811 intel->draw_point = intel_atten_point;
812 else
813 intel->draw_point = intel_fallback_point;
814 }
815
816 if (flags & DD_POINT_SMOOTH) {
817 if (intel->strict_conformance)
818 intel->draw_point = intel_fallback_point;
819 }
820
821 index |= INTEL_FALLBACK_BIT;
822 }
823 }
824
825 if (intel->RenderIndex != index) {
826 intel->RenderIndex = index;
827
828 tnl->Driver.Render.Points = rast_tab[index].points;
829 tnl->Driver.Render.Line = rast_tab[index].line;
830 tnl->Driver.Render.Triangle = rast_tab[index].triangle;
831 tnl->Driver.Render.Quad = rast_tab[index].quad;
832
833 if (index == 0) {
834 tnl->Driver.Render.PrimTabVerts = intel_render_tab_verts;
835 tnl->Driver.Render.PrimTabElts = intel_render_tab_elts;
836 tnl->Driver.Render.ClippedLine = line; /* from tritmp.h */
837 tnl->Driver.Render.ClippedPolygon = intelFastRenderClippedPoly;
838 }
839 else {
840 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
841 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
842 tnl->Driver.Render.ClippedLine = intelRenderClippedLine;
843 tnl->Driver.Render.ClippedPolygon = intelRenderClippedPoly;
844 }
845 }
846 }
847
848 static const GLenum reduced_prim[GL_POLYGON + 1] = {
849 GL_POINTS,
850 GL_LINES,
851 GL_LINES,
852 GL_LINES,
853 GL_TRIANGLES,
854 GL_TRIANGLES,
855 GL_TRIANGLES,
856 GL_TRIANGLES,
857 GL_TRIANGLES,
858 GL_TRIANGLES
859 };
860
861
862 /**********************************************************************/
863 /* High level hooks for t_vb_render.c */
864 /**********************************************************************/
865
866
867
868
869 static void
870 intelRunPipeline(GLcontext * ctx)
871 {
872 struct intel_context *intel = intel_context(ctx);
873
874 _mesa_lock_context_textures(ctx);
875
876 if (ctx->NewState)
877 _mesa_update_state_locked(ctx);
878
879 if (intel->NewGLState) {
880 if (intel->NewGLState & _NEW_TEXTURE) {
881 intel->vtbl.update_texture_state(intel);
882 }
883
884 if (!intel->Fallback) {
885 if (intel->NewGLState & _INTEL_NEW_RENDERSTATE)
886 intelChooseRenderState(ctx);
887 }
888
889 intel->NewGLState = 0;
890 }
891
892 _tnl_run_pipeline(ctx);
893
894 _mesa_unlock_context_textures(ctx);
895 }
896
897 static void
898 intelRenderStart(GLcontext * ctx)
899 {
900 struct intel_context *intel = intel_context(ctx);
901
902 intel->vtbl.render_start(intel_context(ctx));
903 intel->vtbl.emit_state(intel);
904 }
905
906 static void
907 intelRenderFinish(GLcontext * ctx)
908 {
909 struct intel_context *intel = intel_context(ctx);
910
911 if (intel->RenderIndex & INTEL_FALLBACK_BIT)
912 _swrast_flush(ctx);
913
914 INTEL_FIREVERTICES(intel);
915 }
916
917
918
919
920 /* System to flush dma and emit state changes based on the rasterized
921 * primitive.
922 */
923 static void
924 intelRasterPrimitive(GLcontext * ctx, GLenum rprim, GLuint hwprim)
925 {
926 struct intel_context *intel = intel_context(ctx);
927
928 if (0)
929 fprintf(stderr, "%s %s %x\n", __FUNCTION__,
930 _mesa_lookup_enum_by_nr(rprim), hwprim);
931
932 intel->vtbl.reduced_primitive_state(intel, rprim);
933
934 /* Start a new primitive. Arrange to have it flushed later on.
935 */
936 if (hwprim != intel->prim.primitive) {
937 INTEL_FIREVERTICES(intel);
938
939 intelStartInlinePrimitive(intel, hwprim, INTEL_BATCH_CLIPRECTS);
940 }
941 }
942
943
944 /*
945 */
946 static void
947 intelRenderPrimitive(GLcontext * ctx, GLenum prim)
948 {
949 struct intel_context *intel = intel_context(ctx);
950
951 if (0)
952 fprintf(stderr, "%s %s\n", __FUNCTION__, _mesa_lookup_enum_by_nr(prim));
953
954 /* Let some clipping routines know which primitive they're dealing
955 * with.
956 */
957 intel->render_primitive = prim;
958
959 /* Shortcircuit this when called from t_dd_rendertmp.h for unfilled
960 * triangles. The rasterized primitive will always be reset by
961 * lower level functions in that case, potentially pingponging the
962 * state:
963 */
964 if (reduced_prim[prim] == GL_TRIANGLES &&
965 (ctx->_TriangleCaps & DD_TRI_UNFILLED))
966 return;
967
968 /* Set some primitive-dependent state and Start? a new primitive.
969 */
970 intelRasterPrimitive(ctx, reduced_prim[prim], hw_prim[prim]);
971 }
972
973
974 /**********************************************************************/
975 /* Transition to/from hardware rasterization. */
976 /**********************************************************************/
977
978 static char *fallbackStrings[] = {
979 [0] = "Draw buffer",
980 [1] = "Read buffer",
981 [2] = "Depth buffer",
982 [3] = "Stencil buffer",
983 [4] = "User disable",
984 [5] = "Render mode",
985
986 [12] = "Texture",
987 [13] = "Color mask",
988 [14] = "Stencil",
989 [15] = "Stipple",
990 [16] = "Program",
991 [17] = "Logic op",
992 [18] = "Smooth polygon",
993 [19] = "Smooth point",
994 };
995
996
997 static char *
998 getFallbackString(GLuint bit)
999 {
1000 int i = 0;
1001 while (bit > 1) {
1002 i++;
1003 bit >>= 1;
1004 }
1005 return fallbackStrings[i];
1006 }
1007
1008
1009
1010 void
1011 intelFallback(struct intel_context *intel, GLuint bit, GLboolean mode)
1012 {
1013 GLcontext *ctx = &intel->ctx;
1014 TNLcontext *tnl = TNL_CONTEXT(ctx);
1015 GLuint oldfallback = intel->Fallback;
1016
1017 if (mode) {
1018 intel->Fallback |= bit;
1019 if (oldfallback == 0) {
1020 intelFlush(ctx);
1021 if (INTEL_DEBUG & DEBUG_FALLBACKS)
1022 fprintf(stderr, "ENTER FALLBACK %x: %s\n",
1023 bit, getFallbackString(bit));
1024 _swsetup_Wakeup(ctx);
1025 intel->RenderIndex = ~0;
1026 }
1027 }
1028 else {
1029 intel->Fallback &= ~bit;
1030 if (oldfallback == bit) {
1031 _swrast_flush(ctx);
1032 if (INTEL_DEBUG & DEBUG_FALLBACKS)
1033 fprintf(stderr, "LEAVE FALLBACK %s\n", getFallbackString(bit));
1034 tnl->Driver.Render.Start = intelRenderStart;
1035 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
1036 tnl->Driver.Render.Finish = intelRenderFinish;
1037 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1038 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1039 tnl->Driver.Render.Interp = _tnl_interp;
1040
1041 _tnl_invalidate_vertex_state(ctx, ~0);
1042 _tnl_invalidate_vertices(ctx, ~0);
1043 _tnl_install_attrs(ctx,
1044 intel->vertex_attrs,
1045 intel->vertex_attr_count,
1046 intel->ViewportMatrix.m, 0);
1047
1048 intel->NewGLState |= _INTEL_NEW_RENDERSTATE;
1049 }
1050 }
1051 }
1052
1053 union fi
1054 {
1055 GLfloat f;
1056 GLint i;
1057 };
1058
1059
1060 /**********************************************************************/
1061 /* Used only with the metaops callbacks. */
1062 /**********************************************************************/
1063 void
1064 intel_meta_draw_poly(struct intel_context *intel,
1065 GLuint n,
1066 GLfloat xy[][2],
1067 GLfloat z, GLuint color, GLfloat tex[][2])
1068 {
1069 union fi *vb;
1070 GLint i;
1071
1072 /* All 3d primitives should be emitted with INTEL_BATCH_CLIPRECTS,
1073 * otherwise the drawing origin (DR4) might not be set correctly.
1074 */
1075 intelStartInlinePrimitive(intel, PRIM3D_TRIFAN, INTEL_BATCH_CLIPRECTS);
1076 vb = (union fi *) intelExtendInlinePrimitive(intel, n * 6);
1077
1078 for (i = 0; i < n; i++) {
1079 vb[0].f = xy[i][0];
1080 vb[1].f = xy[i][1];
1081 vb[2].f = z;
1082 vb[3].i = color;
1083 vb[4].f = tex[i][0];
1084 vb[5].f = tex[i][1];
1085 vb += 6;
1086 }
1087
1088 INTEL_FIREVERTICES(intel);
1089 }
1090
1091 void
1092 intel_meta_draw_quad(struct intel_context *intel,
1093 GLfloat x0, GLfloat x1,
1094 GLfloat y0, GLfloat y1,
1095 GLfloat z,
1096 GLuint color,
1097 GLfloat s0, GLfloat s1, GLfloat t0, GLfloat t1)
1098 {
1099 GLfloat xy[4][2];
1100 GLfloat tex[4][2];
1101
1102 xy[0][0] = x0;
1103 xy[0][1] = y0;
1104 xy[1][0] = x1;
1105 xy[1][1] = y0;
1106 xy[2][0] = x1;
1107 xy[2][1] = y1;
1108 xy[3][0] = x0;
1109 xy[3][1] = y1;
1110
1111 tex[0][0] = s0;
1112 tex[0][1] = t0;
1113 tex[1][0] = s1;
1114 tex[1][1] = t0;
1115 tex[2][0] = s1;
1116 tex[2][1] = t1;
1117 tex[3][0] = s0;
1118 tex[3][1] = t1;
1119
1120 intel_meta_draw_poly(intel, 4, xy, z, color, tex);
1121 }
1122
1123
1124
1125 /**********************************************************************/
1126 /* Initialization. */
1127 /**********************************************************************/
1128
1129
1130 void
1131 intelInitTriFuncs(GLcontext * ctx)
1132 {
1133 TNLcontext *tnl = TNL_CONTEXT(ctx);
1134 static int firsttime = 1;
1135
1136 if (firsttime) {
1137 init_rast_tab();
1138 firsttime = 0;
1139 }
1140
1141 tnl->Driver.RunPipeline = intelRunPipeline;
1142 tnl->Driver.Render.Start = intelRenderStart;
1143 tnl->Driver.Render.Finish = intelRenderFinish;
1144 tnl->Driver.Render.PrimitiveNotify = intelRenderPrimitive;
1145 tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
1146 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
1147 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
1148 tnl->Driver.Render.Interp = _tnl_interp;
1149 }