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