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