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