• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 Copyright (C) The Weather Channel, Inc.  2002.  All Rights Reserved.
3 
4 The Weather Channel (TM) funded Tungsten Graphics to develop the
5 initial release of the Radeon 8500 driver under the XFree86 license.
6 This notice must be preserved.
7 
8 Permission is hereby granted, free of charge, to any person obtaining
9 a copy of this software and associated documentation files (the
10 "Software"), to deal in the Software without restriction, including
11 without limitation the rights to use, copy, modify, merge, publish,
12 distribute, sublicense, and/or sell copies of the Software, and to
13 permit persons to whom the Software is furnished to do so, subject to
14 the following conditions:
15 
16 The above copyright notice and this permission notice (including the
17 next paragraph) shall be included in all copies or substantial
18 portions of the Software.
19 
20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
24 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 
28 **************************************************************************/
29 
30 /*
31  * Authors:
32  *   Keith Whitwell <keithw@vmware.com>
33  */
34 
35 #include "main/glheader.h"
36 #include "main/mtypes.h"
37 #include "main/enums.h"
38 #include "main/image.h"
39 #include "main/imports.h"
40 #include "main/macros.h"
41 
42 #include "swrast/s_context.h"
43 #include "swrast/s_fog.h"
44 #include "swrast_setup/swrast_setup.h"
45 #include "tnl/tnl.h"
46 #include "tnl/t_context.h"
47 #include "tnl/t_pipeline.h"
48 
49 #include "r200_context.h"
50 #include "r200_ioctl.h"
51 #include "r200_state.h"
52 #include "r200_swtcl.h"
53 #include "r200_tcl.h"
54 
55 
56 /***********************************************************************
57  *                         Initialization
58  ***********************************************************************/
59 
60 #define EMIT_ATTR( ATTR, STYLE, F0 )					\
61 do {									\
62    rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = (ATTR);	\
63    rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = (STYLE);	\
64    rmesa->radeon.swtcl.vertex_attr_count++;					\
65    fmt_0 |= F0;								\
66 } while (0)
67 
68 #define EMIT_PAD( N )							\
69 do {									\
70    rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].attrib = 0;		\
71    rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].format = EMIT_PAD;	\
72    rmesa->radeon.swtcl.vertex_attrs[rmesa->radeon.swtcl.vertex_attr_count].offset = (N);		\
73    rmesa->radeon.swtcl.vertex_attr_count++;					\
74 } while (0)
75 
r200SetVertexFormat(struct gl_context * ctx)76 static void r200SetVertexFormat( struct gl_context *ctx )
77 {
78    r200ContextPtr rmesa = R200_CONTEXT( ctx );
79    TNLcontext *tnl = TNL_CONTEXT(ctx);
80    struct vertex_buffer *VB = &tnl->vb;
81    GLbitfield64 index_bitset = tnl->render_inputs_bitset;
82    int fmt_0 = 0;
83    int fmt_1 = 0;
84    int offset = 0;
85 
86    /* Important:
87     */
88    if ( VB->NdcPtr != NULL ) {
89       VB->AttribPtr[VERT_ATTRIB_POS] = VB->NdcPtr;
90    }
91    else {
92       VB->AttribPtr[VERT_ATTRIB_POS] = VB->ClipPtr;
93    }
94 
95    assert( VB->AttribPtr[VERT_ATTRIB_POS] != NULL );
96    rmesa->radeon.swtcl.vertex_attr_count = 0;
97 
98    /* EMIT_ATTR's must be in order as they tell t_vertex.c how to
99     * build up a hardware vertex.
100     */
101    if ( !rmesa->swtcl.needproj ||
102         (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) ) {
103       /* need w coord for projected textures */
104       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_4F, R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0 );
105       offset = 4;
106    }
107    else {
108       EMIT_ATTR( _TNL_ATTRIB_POS, EMIT_3F, R200_VTX_XY | R200_VTX_Z0 );
109       offset = 3;
110    }
111 
112    if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_POINTSIZE)) {
113       EMIT_ATTR( _TNL_ATTRIB_POINTSIZE, EMIT_1F, R200_VTX_POINT_SIZE );
114       offset += 1;
115    }
116 
117    rmesa->swtcl.coloroffset = offset;
118 #if MESA_LITTLE_ENDIAN
119    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_RGBA, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
120 #else
121    EMIT_ATTR( _TNL_ATTRIB_COLOR0, EMIT_4UB_4F_ABGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT) );
122 #endif
123    offset += 1;
124 
125    rmesa->swtcl.specoffset = 0;
126    if (index_bitset &
127        (BITFIELD64_BIT(_TNL_ATTRIB_COLOR1) | BITFIELD64_BIT(_TNL_ATTRIB_FOG))) {
128 
129 #if MESA_LITTLE_ENDIAN
130       if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
131 	 rmesa->swtcl.specoffset = offset;
132 	 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_RGB, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
133       }
134       else {
135 	 EMIT_PAD( 3 );
136       }
137 
138       if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
139 	 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
140       }
141       else {
142 	 EMIT_PAD( 1 );
143       }
144 #else
145       if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_FOG)) {
146 	 EMIT_ATTR( _TNL_ATTRIB_FOG, EMIT_1UB_1F, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
147       }
148       else {
149 	 EMIT_PAD( 1 );
150       }
151 
152       if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_COLOR1)) {
153 	 rmesa->swtcl.specoffset = offset;
154 	 EMIT_ATTR( _TNL_ATTRIB_COLOR1, EMIT_3UB_3F_BGR, (R200_VTX_PK_RGBA << R200_VTX_COLOR_1_SHIFT) );
155       }
156       else {
157 	 EMIT_PAD( 3 );
158       }
159 #endif
160    }
161 
162    if (index_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) {
163       int i;
164 
165       for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
166 	 if (index_bitset & BITFIELD64_BIT(_TNL_ATTRIB_TEX(i))) {
167 	    GLuint sz = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]->size;
168 
169 	    fmt_1 |= sz << (3 * i);
170 	    EMIT_ATTR( _TNL_ATTRIB_TEX0+i, EMIT_1F + sz - 1, 0 );
171 	 }
172       }
173    }
174 
175    if ( (rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK)
176       != R200_FOG_USE_SPEC_ALPHA ) {
177       R200_STATECHANGE( rmesa, ctx );
178       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK;
179       rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_SPEC_ALPHA;
180    }
181 
182    if (rmesa->radeon.tnl_index_bitset != index_bitset ||
183 	(rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0) ||
184 	(rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
185       R200_NEWPRIM(rmesa);
186       R200_STATECHANGE( rmesa, vtx );
187       rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
188       rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
189 
190       rmesa->radeon.swtcl.vertex_size =
191 	  _tnl_install_attrs( ctx,
192 			      rmesa->radeon.swtcl.vertex_attrs,
193 			      rmesa->radeon.swtcl.vertex_attr_count,
194 			      NULL, 0 );
195       rmesa->radeon.swtcl.vertex_size /= 4;
196       rmesa->radeon.tnl_index_bitset = index_bitset;
197    }
198 }
199 
r200_predict_emit_size(r200ContextPtr rmesa)200 static void r200_predict_emit_size( r200ContextPtr rmesa )
201 {
202    if (RADEON_DEBUG & RADEON_VERTS)
203       fprintf(stderr, "%s\n", __func__);
204    const int vertex_array_size = 7;
205    const int prim_size = 3;
206    if (!rmesa->radeon.swtcl.emit_prediction) {
207       const int state_size = radeonCountStateEmitSize(&rmesa->radeon);
208       if (rcommonEnsureCmdBufSpace(&rmesa->radeon,
209 	       state_size +
210 	       vertex_array_size + prim_size,
211 	       __func__))
212 	 rmesa->radeon.swtcl.emit_prediction = radeonCountStateEmitSize(&rmesa->radeon);
213       else
214 	 rmesa->radeon.swtcl.emit_prediction = state_size;
215       rmesa->radeon.swtcl.emit_prediction += vertex_array_size + prim_size
216 	 + rmesa->radeon.cmdbuf.cs->cdw;
217    }
218 }
219 
220 
r200RenderStart(struct gl_context * ctx)221 static void r200RenderStart( struct gl_context *ctx )
222 {
223    r200SetVertexFormat( ctx );
224    if (RADEON_DEBUG & RADEON_VERTS)
225       fprintf(stderr, "%s\n", __func__);
226 }
227 
228 
229 /**
230  * Set vertex state for SW TCL.  The primary purpose of this function is to
231  * determine in advance whether or not the hardware can / should do the
232  * projection divide or Mesa should do it.
233  */
r200ChooseVertexState(struct gl_context * ctx)234 void r200ChooseVertexState( struct gl_context *ctx )
235 {
236    r200ContextPtr rmesa = R200_CONTEXT( ctx );
237    TNLcontext *tnl = TNL_CONTEXT(ctx);
238    GLuint vte;
239    GLuint vap;
240    GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
241                          ctx->Polygon.BackMode != GL_FILL);
242    GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
243 
244    /* We must ensure that we don't do _tnl_need_projected_coords while in a
245     * rasterization fallback.  As this function will be called again when we
246     * leave a rasterization fallback, we can just skip it for now.
247     */
248    if (rmesa->radeon.Fallback != 0)
249       return;
250 
251    vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
252    vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
253 
254    /* HW perspective divide is a win, but tiny vertex formats are a
255     * bigger one.
256     */
257    if ((0 == (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)))
258        || twosided
259        || unfilled) {
260       rmesa->swtcl.needproj = GL_TRUE;
261       vte |= R200_VTX_XY_FMT | R200_VTX_Z_FMT;
262       vte &= ~R200_VTX_W0_FMT;
263       if (tnl->render_inputs_bitset & BITFIELD64_RANGE(_TNL_ATTRIB_TEX0, _TNL_NUM_TEX)) {
264 	 vap &= ~R200_VAP_FORCE_W_TO_ONE;
265       }
266       else {
267 	 vap |= R200_VAP_FORCE_W_TO_ONE;
268       }
269    }
270    else {
271       rmesa->swtcl.needproj = GL_FALSE;
272       vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
273       vte |= R200_VTX_W0_FMT;
274       vap &= ~R200_VAP_FORCE_W_TO_ONE;
275    }
276 
277    _tnl_need_projected_coords( ctx, rmesa->swtcl.needproj );
278 
279    if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
280       R200_STATECHANGE( rmesa, vte );
281       rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
282    }
283 
284    if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
285       R200_STATECHANGE( rmesa, vap );
286       rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
287    }
288 }
289 
r200_swtcl_flush(struct gl_context * ctx,uint32_t current_offset)290 void r200_swtcl_flush(struct gl_context *ctx, uint32_t current_offset)
291 {
292    r200ContextPtr rmesa = R200_CONTEXT(ctx);
293    if (RADEON_DEBUG & RADEON_VERTS)
294       fprintf(stderr, "%s\n", __func__);
295 
296 
297    radeonEmitState(&rmesa->radeon);
298    r200EmitVertexAOS( rmesa,
299 		      rmesa->radeon.swtcl.vertex_size,
300 		      rmesa->radeon.swtcl.bo,
301 		      current_offset);
302 
303 
304    r200EmitVbufPrim( rmesa,
305 		     rmesa->radeon.swtcl.hw_primitive,
306 		     rmesa->radeon.swtcl.numverts);
307    if ( rmesa->radeon.swtcl.emit_prediction < rmesa->radeon.cmdbuf.cs->cdw )
308       WARN_ONCE("Rendering was %d commands larger than predicted size."
309 	    " We might overflow  command buffer.\n",
310 	    rmesa->radeon.cmdbuf.cs->cdw - rmesa->radeon.swtcl.emit_prediction );
311 
312    rmesa->radeon.swtcl.emit_prediction = 0;
313 
314 }
315 
316 /**************************************************************************/
317 
318 
reduced_hw_prim(struct gl_context * ctx,GLuint prim)319 static inline GLuint reduced_hw_prim( struct gl_context *ctx, GLuint prim)
320 {
321    switch (prim) {
322    case GL_POINTS:
323       return ((!ctx->Point.SmoothFlag) ?
324 	 R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS);
325    case GL_LINES:
326    /* fallthrough */
327    case GL_LINE_LOOP:
328    /* fallthrough */
329    case GL_LINE_STRIP:
330       return R200_VF_PRIM_LINES;
331    default:
332    /* all others reduced to triangles */
333       return R200_VF_PRIM_TRIANGLES;
334    }
335 }
336 
337 
338 static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim );
339 static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim );
340 static void r200ResetLineStipple( struct gl_context *ctx );
341 
342 /***********************************************************************
343  *                    Emit primitives as inline vertices               *
344  ***********************************************************************/
345 
346 #define HAVE_POINTS      1
347 #define HAVE_LINES       1
348 #define HAVE_LINE_STRIPS 1
349 #define HAVE_TRIANGLES   1
350 #define HAVE_TRI_STRIPS  1
351 #define HAVE_TRI_FANS    1
352 #define HAVE_QUADS       0
353 #define HAVE_QUAD_STRIPS 0
354 #define HAVE_POLYGONS    1
355 #define HAVE_ELTS        0
356 
r200_alloc_verts(r200ContextPtr rmesa,GLuint n,GLuint size)357 static void* r200_alloc_verts( r200ContextPtr rmesa, GLuint n, GLuint size)
358 {
359    void *rv;
360    do {
361       r200_predict_emit_size( rmesa );
362       rv = rcommonAllocDmaLowVerts( &rmesa->radeon, n, size * 4 );
363    } while(!rv);
364    return rv;
365 }
366 
367 #undef LOCAL_VARS
368 #undef ALLOC_VERTS
369 #define CTX_ARG r200ContextPtr rmesa
370 #define GET_VERTEX_DWORDS() rmesa->radeon.swtcl.vertex_size
371 #define ALLOC_VERTS( n, size ) r200_alloc_verts(rmesa, n, size)
372 #define LOCAL_VARS						\
373    r200ContextPtr rmesa = R200_CONTEXT(ctx);		\
374    const char *r200verts = (char *)rmesa->radeon.swtcl.verts;
375 #define VERT(x) (radeonVertex *)(r200verts + ((x) * vertsize * sizeof(int)))
376 #define VERTEX radeonVertex
377 #define DO_DEBUG_VERTS (1 && (R200_DEBUG & RADEON_VERTS))
378 
379 #undef TAG
380 #define TAG(x) r200_##x
381 #include "tnl_dd/t_dd_triemit.h"
382 
383 
384 /***********************************************************************
385  *          Macros for t_dd_tritmp.h to draw basic primitives          *
386  ***********************************************************************/
387 
388 #define QUAD( a, b, c, d ) r200_quad( rmesa, a, b, c, d )
389 #define TRI( a, b, c )     r200_triangle( rmesa, a, b, c )
390 #define LINE( a, b )       r200_line( rmesa, a, b )
391 #define POINT( a )         r200_point( rmesa, a )
392 
393 /***********************************************************************
394  *              Build render functions from dd templates               *
395  ***********************************************************************/
396 
397 #define R200_TWOSIDE_BIT	0x01
398 #define R200_UNFILLED_BIT	0x02
399 #define R200_MAX_TRIFUNC	0x04
400 
401 
402 static struct {
403    tnl_points_func	        points;
404    tnl_line_func		line;
405    tnl_triangle_func	triangle;
406    tnl_quad_func		quad;
407 } rast_tab[R200_MAX_TRIFUNC];
408 
409 
410 #define DO_FALLBACK  0
411 #define DO_UNFILLED ((IND & R200_UNFILLED_BIT) != 0)
412 #define DO_TWOSIDE  ((IND & R200_TWOSIDE_BIT) != 0)
413 #define DO_FLAT      0
414 #define DO_OFFSET     0
415 #define DO_TRI       1
416 #define DO_QUAD      1
417 #define DO_LINE      1
418 #define DO_POINTS    1
419 #define DO_FULL_QUAD 1
420 
421 #define HAVE_SPEC   1
422 #define HAVE_BACK_COLORS  0
423 #define HAVE_HW_FLATSHADE 1
424 #define TAB rast_tab
425 
426 #define DEPTH_SCALE 1.0
427 #define UNFILLED_TRI unfilled_tri
428 #define UNFILLED_QUAD unfilled_quad
429 #define VERT_X(_v) _v->v.x
430 #define VERT_Y(_v) _v->v.y
431 #define VERT_Z(_v) _v->v.z
432 #define AREA_IS_CCW( a ) (a < 0)
433 #define GET_VERTEX(e) (rmesa->radeon.swtcl.verts + (e*rmesa->radeon.swtcl.vertex_size*sizeof(int)))
434 
435 #define VERT_SET_RGBA( v, c )  					\
436 do {								\
437    radeon_color_t *color = (radeon_color_t *)&((v)->ui[coloroffset]);	\
438    UNCLAMPED_FLOAT_TO_UBYTE(color->red, (c)[0]);		\
439    UNCLAMPED_FLOAT_TO_UBYTE(color->green, (c)[1]);		\
440    UNCLAMPED_FLOAT_TO_UBYTE(color->blue, (c)[2]);		\
441    UNCLAMPED_FLOAT_TO_UBYTE(color->alpha, (c)[3]);		\
442 } while (0)
443 
444 #define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
445 
446 #define VERT_SET_SPEC( v, c )					\
447 do {								\
448    if (specoffset) {						\
449       radeon_color_t *spec = (radeon_color_t *)&((v)->ui[specoffset]);	\
450       UNCLAMPED_FLOAT_TO_UBYTE(spec->red, (c)[0]);	\
451       UNCLAMPED_FLOAT_TO_UBYTE(spec->green, (c)[1]);	\
452       UNCLAMPED_FLOAT_TO_UBYTE(spec->blue, (c)[2]);	\
453    }								\
454 } while (0)
455 #define VERT_COPY_SPEC( v0, v1 )			\
456 do {							\
457    if (specoffset) {					\
458       radeon_color_t *spec0 = (radeon_color_t *)&((v0)->ui[specoffset]);	\
459       radeon_color_t *spec1 = (radeon_color_t *)&((v1)->ui[specoffset]);	\
460       spec0->red   = spec1->red;	\
461       spec0->green = spec1->green;	\
462       spec0->blue  = spec1->blue; 	\
463    }							\
464 } while (0)
465 
466 /* These don't need LE32_TO_CPU() as they used to save and restore
467  * colors which are already in the correct format.
468  */
469 #define VERT_SAVE_RGBA( idx )    color[idx] = v[idx]->ui[coloroffset]
470 #define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
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 #undef LOCAL_VARS
475 #undef TAG
476 #undef INIT
477 
478 #define LOCAL_VARS(n)							\
479    r200ContextPtr rmesa = R200_CONTEXT(ctx);			\
480    GLuint color[n] = {0}, spec[n] = {0};						\
481    GLuint coloroffset = rmesa->swtcl.coloroffset;	\
482    GLuint specoffset = rmesa->swtcl.specoffset;			\
483    (void) color; (void) spec; (void) coloroffset; (void) specoffset;
484 
485 /***********************************************************************
486  *                Helpers for rendering unfilled primitives            *
487  ***********************************************************************/
488 
489 #define RASTERIZE(x) r200RasterPrimitive( ctx, reduced_hw_prim(ctx, x) )
490 #define RENDER_PRIMITIVE rmesa->radeon.swtcl.render_primitive
491 #undef TAG
492 #define TAG(x) x
493 #include "tnl_dd/t_dd_unfilled.h"
494 #undef IND
495 
496 
497 /***********************************************************************
498  *                      Generate GL render functions                   *
499  ***********************************************************************/
500 
501 
502 #define IND (0)
503 #define TAG(x) x
504 #include "tnl_dd/t_dd_tritmp.h"
505 
506 #define IND (R200_TWOSIDE_BIT)
507 #define TAG(x) x##_twoside
508 #include "tnl_dd/t_dd_tritmp.h"
509 
510 #define IND (R200_UNFILLED_BIT)
511 #define TAG(x) x##_unfilled
512 #include "tnl_dd/t_dd_tritmp.h"
513 
514 #define IND (R200_TWOSIDE_BIT|R200_UNFILLED_BIT)
515 #define TAG(x) x##_twoside_unfilled
516 #include "tnl_dd/t_dd_tritmp.h"
517 
518 
init_rast_tab(void)519 static void init_rast_tab( void )
520 {
521    init();
522    init_twoside();
523    init_unfilled();
524    init_twoside_unfilled();
525 }
526 
527 /**********************************************************************/
528 /*               Render unclipped begin/end objects                   */
529 /**********************************************************************/
530 
531 #define RENDER_POINTS( start, count )		\
532    for ( ; start < count ; start++)		\
533       r200_point( rmesa, VERT(start) )
534 #define RENDER_LINE( v0, v1 ) \
535    r200_line( rmesa, VERT(v0), VERT(v1) )
536 #define RENDER_TRI( v0, v1, v2 )  \
537    r200_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
538 #define RENDER_QUAD( v0, v1, v2, v3 ) \
539    r200_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
540 #define INIT(x) do {					\
541    r200RenderPrimitive( ctx, x );			\
542 } while (0)
543 #undef LOCAL_VARS
544 #define LOCAL_VARS						\
545    r200ContextPtr rmesa = R200_CONTEXT(ctx);		\
546    const GLuint vertsize = rmesa->radeon.swtcl.vertex_size;		\
547    const char *r200verts = (char *)rmesa->radeon.swtcl.verts;		\
548    const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts;	\
549    const GLboolean stipple = ctx->Line.StippleFlag;		\
550    (void) elt; (void) stipple;
551 #define RESET_STIPPLE	if ( stipple ) r200ResetLineStipple( ctx );
552 #define RESET_OCCLUSION
553 #define PRESERVE_VB_DEFS
554 #define ELT(x) (x)
555 #define TAG(x) r200_##x##_verts
556 #include "tnl/t_vb_rendertmp.h"
557 #undef ELT
558 #undef TAG
559 #define TAG(x) r200_##x##_elts
560 #define ELT(x) elt[x]
561 #include "tnl/t_vb_rendertmp.h"
562 
563 
564 
565 /**********************************************************************/
566 /*                    Choose render functions                         */
567 /**********************************************************************/
568 
r200ChooseRenderState(struct gl_context * ctx)569 void r200ChooseRenderState( struct gl_context *ctx )
570 {
571    TNLcontext *tnl = TNL_CONTEXT(ctx);
572    r200ContextPtr rmesa = R200_CONTEXT(ctx);
573    GLuint index = 0;
574    GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
575                          ctx->Polygon.BackMode != GL_FILL);
576    GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
577 
578    if (!rmesa->radeon.TclFallback || rmesa->radeon.Fallback)
579       return;
580 
581    if (twosided)
582       index |= R200_TWOSIDE_BIT;
583    if (unfilled)
584       index |= R200_UNFILLED_BIT;
585 
586    if (index != rmesa->radeon.swtcl.RenderIndex) {
587       tnl->Driver.Render.Points = rast_tab[index].points;
588       tnl->Driver.Render.Line = rast_tab[index].line;
589       tnl->Driver.Render.ClippedLine = rast_tab[index].line;
590       tnl->Driver.Render.Triangle = rast_tab[index].triangle;
591       tnl->Driver.Render.Quad = rast_tab[index].quad;
592 
593       if (index == 0) {
594 	 tnl->Driver.Render.PrimTabVerts = r200_render_tab_verts;
595 	 tnl->Driver.Render.PrimTabElts = r200_render_tab_elts;
596 	 tnl->Driver.Render.ClippedPolygon = r200_fast_clipped_poly;
597       } else {
598 	 tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
599 	 tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
600 	 tnl->Driver.Render.ClippedPolygon = _tnl_RenderClippedPolygon;
601       }
602 
603       rmesa->radeon.swtcl.RenderIndex = index;
604    }
605 }
606 
607 
608 /**********************************************************************/
609 /*                 High level hooks for t_vb_render.c                 */
610 /**********************************************************************/
611 
612 
r200RasterPrimitive(struct gl_context * ctx,GLuint hwprim)613 static void r200RasterPrimitive( struct gl_context *ctx, GLuint hwprim )
614 {
615    r200ContextPtr rmesa = R200_CONTEXT(ctx);
616 
617    radeon_prepare_render(&rmesa->radeon);
618    if (rmesa->radeon.NewGLState)
619       r200ValidateState( ctx );
620 
621 
622    if (rmesa->radeon.swtcl.hw_primitive != hwprim) {
623       /* need to disable perspective-correct texturing for point sprites */
624       if ((hwprim & 0xf) == R200_VF_PRIM_POINT_SPRITES && ctx->Point.PointSprite) {
625 	 if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) {
626 	    R200_STATECHANGE( rmesa, set );
627 	    rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE;
628 	 }
629       }
630       else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) {
631 	 R200_STATECHANGE( rmesa, set );
632 	 rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE;
633       }
634       R200_NEWPRIM( rmesa );
635       rmesa->radeon.swtcl.hw_primitive = hwprim;
636    }
637 }
638 
r200RenderPrimitive(struct gl_context * ctx,GLenum prim)639 static void r200RenderPrimitive( struct gl_context *ctx, GLenum prim )
640 {
641    r200ContextPtr rmesa = R200_CONTEXT(ctx);
642    GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
643                          ctx->Polygon.BackMode != GL_FILL);
644 
645    rmesa->radeon.swtcl.render_primitive = prim;
646    if (prim < GL_TRIANGLES || !unfilled)
647       r200RasterPrimitive( ctx, reduced_hw_prim(ctx, prim) );
648 }
649 
r200RenderFinish(struct gl_context * ctx)650 static void r200RenderFinish( struct gl_context *ctx )
651 {
652 }
653 
r200ResetLineStipple(struct gl_context * ctx)654 static void r200ResetLineStipple( struct gl_context *ctx )
655 {
656    r200ContextPtr rmesa = R200_CONTEXT(ctx);
657    R200_STATECHANGE( rmesa, lin );
658 }
659 
660 
661 /**********************************************************************/
662 /*           Transition to/from hardware rasterization.               */
663 /**********************************************************************/
664 
665 static const char * const fallbackStrings[] = {
666    "Texture mode",
667    "glDrawBuffer(GL_FRONT_AND_BACK)",
668    "glEnable(GL_STENCIL) without hw stencil buffer",
669    "glRenderMode(selection or feedback)",
670    "R200_NO_RAST",
671    "Mixing GL_CLAMP_TO_BORDER and GL_CLAMP (or GL_MIRROR_CLAMP_ATI)"
672 };
673 
674 
getFallbackString(GLuint bit)675 static const char *getFallbackString(GLuint bit)
676 {
677    int i = 0;
678    while (bit > 1) {
679       i++;
680       bit >>= 1;
681    }
682    return fallbackStrings[i];
683 }
684 
685 
r200Fallback(struct gl_context * ctx,GLuint bit,GLboolean mode)686 void r200Fallback( struct gl_context *ctx, GLuint bit, GLboolean mode )
687 {
688    r200ContextPtr rmesa = R200_CONTEXT(ctx);
689    TNLcontext *tnl = TNL_CONTEXT(ctx);
690    GLuint oldfallback = rmesa->radeon.Fallback;
691 
692    if (mode) {
693       rmesa->radeon.Fallback |= bit;
694       if (oldfallback == 0) {
695 	 radeon_firevertices(&rmesa->radeon);
696 	 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_TRUE );
697 	 _swsetup_Wakeup( ctx );
698 	 rmesa->radeon.swtcl.RenderIndex = ~0;
699          if (R200_DEBUG & RADEON_FALLBACKS) {
700             fprintf(stderr, "R200 begin rasterization fallback: 0x%x %s\n",
701                     bit, getFallbackString(bit));
702          }
703       }
704    }
705    else {
706       rmesa->radeon.Fallback &= ~bit;
707       if (oldfallback == bit) {
708 
709 	 _swrast_flush( ctx );
710 	 tnl->Driver.Render.Start = r200RenderStart;
711 	 tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
712 	 tnl->Driver.Render.Finish = r200RenderFinish;
713 
714 	 tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
715 	 tnl->Driver.Render.CopyPV = _tnl_copy_pv;
716 	 tnl->Driver.Render.Interp = _tnl_interp;
717 
718 	 tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
719 	 TCL_FALLBACK( ctx, R200_TCL_FALLBACK_RASTER, GL_FALSE );
720 	 if (rmesa->radeon.TclFallback) {
721 	    /* These are already done if rmesa->radeon.TclFallback goes to
722 	     * zero above. But not if it doesn't (R200_NO_TCL for
723 	     * example?)
724 	     */
725 	    _tnl_invalidate_vertex_state( ctx, ~0 );
726 	    _tnl_invalidate_vertices( ctx, ~0 );
727 	    rmesa->radeon.tnl_index_bitset = 0;
728 	    r200ChooseVertexState( ctx );
729 	    r200ChooseRenderState( ctx );
730 	 }
731          if (R200_DEBUG & RADEON_FALLBACKS) {
732             fprintf(stderr, "R200 end rasterization fallback: 0x%x %s\n",
733                     bit, getFallbackString(bit));
734          }
735       }
736    }
737 }
738 
739 
740 
741 
742 /**
743  * Cope with depth operations by drawing individual pixels as points.
744  *
745  * \todo
746  * The way the vertex state is set in this routine is hokey.  It seems to
747  * work, but it's very hackish.  This whole routine is pretty hackish.  If
748  * the bitmap is small enough, it seems like it would be faster to copy it
749  * to AGP memory and use it as a non-power-of-two texture (i.e.,
750  * NV_texture_rectangle).
751  */
752 void
r200PointsBitmap(struct gl_context * ctx,GLint px,GLint py,GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLubyte * bitmap)753 r200PointsBitmap( struct gl_context *ctx, GLint px, GLint py,
754 		  GLsizei width, GLsizei height,
755 		  const struct gl_pixelstore_attrib *unpack,
756 		  const GLubyte *bitmap )
757 {
758    r200ContextPtr rmesa = R200_CONTEXT(ctx);
759    const GLfloat *rc = ctx->Current.RasterColor;
760    GLint row, col;
761    radeonVertex vert;
762    GLuint orig_vte;
763    GLuint h;
764 
765 
766    /* Turn off tcl.
767     */
768    TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 1 );
769 
770    /* Choose tiny vertex format
771     */
772    {
773       const GLuint fmt_0 = R200_VTX_XY | R200_VTX_Z0 | R200_VTX_W0
774 	  | (R200_VTX_PK_RGBA << R200_VTX_COLOR_0_SHIFT);
775       const GLuint fmt_1 = 0;
776       GLuint vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
777       GLuint vap = rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL];
778 
779       vte &= ~(R200_VTX_XY_FMT | R200_VTX_Z_FMT);
780       vte |= R200_VTX_W0_FMT;
781       vap &= ~R200_VAP_FORCE_W_TO_ONE;
782 
783       rmesa->radeon.swtcl.vertex_size = 5;
784 
785       if ( (rmesa->hw.vtx.cmd[VTX_VTXFMT_0] != fmt_0)
786 	   || (rmesa->hw.vtx.cmd[VTX_VTXFMT_1] != fmt_1) ) {
787 	 R200_NEWPRIM(rmesa);
788 	 R200_STATECHANGE( rmesa, vtx );
789 	 rmesa->hw.vtx.cmd[VTX_VTXFMT_0] = fmt_0;
790 	 rmesa->hw.vtx.cmd[VTX_VTXFMT_1] = fmt_1;
791       }
792 
793       if (vte != rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL]) {
794 	 R200_STATECHANGE( rmesa, vte );
795 	 rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = vte;
796       }
797 
798       if (vap != rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL]) {
799 	 R200_STATECHANGE( rmesa, vap );
800 	 rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] = vap;
801       }
802    }
803 
804    /* Ready for point primitives:
805     */
806    r200RenderPrimitive( ctx, GL_POINTS );
807 
808    /* Turn off the hw viewport transformation:
809     */
810    R200_STATECHANGE( rmesa, vte );
811    orig_vte = rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL];
812    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VPORT_X_SCALE_ENA |
813 					   R200_VPORT_Y_SCALE_ENA |
814 					   R200_VPORT_Z_SCALE_ENA |
815 					   R200_VPORT_X_OFFSET_ENA |
816 					   R200_VPORT_Y_OFFSET_ENA |
817 					   R200_VPORT_Z_OFFSET_ENA);
818 
819    /* Turn off other stuff:  Stipple?, texture?, blending?, etc.
820     */
821 
822 
823    /* Populate the vertex
824     *
825     * Incorporate FOG into RGBA
826     */
827    if (ctx->Fog.Enabled) {
828       const GLfloat *fc = ctx->Fog.Color;
829       GLfloat color[4];
830       GLfloat f;
831 
832       if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
833          f = _swrast_z_to_fogfactor(ctx, ctx->Current.Attrib[VERT_ATTRIB_FOG][0]);
834       else
835          f = _swrast_z_to_fogfactor(ctx, ctx->Current.RasterDistance);
836 
837       color[0] = f * rc[0] + (1.F - f) * fc[0];
838       color[1] = f * rc[1] + (1.F - f) * fc[1];
839       color[2] = f * rc[2] + (1.F - f) * fc[2];
840       color[3] = rc[3];
841 
842       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   color[0]);
843       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, color[1]);
844       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  color[2]);
845       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, color[3]);
846    }
847    else {
848       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.red,   rc[0]);
849       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.green, rc[1]);
850       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.blue,  rc[2]);
851       UNCLAMPED_FLOAT_TO_CHAN(vert.tv.color.alpha, rc[3]);
852    }
853 
854 
855    vert.tv.z = ctx->Current.RasterPos[2];
856 
857 
858    /* Update window height
859     */
860    h = radeon_get_drawable(&rmesa->radeon)->h;
861 
862    /* Clipping handled by existing mechansims in r200_ioctl.c?
863     */
864    for (row=0; row<height; row++) {
865       const GLubyte *src = (const GLubyte *)
866 	 _mesa_image_address2d(unpack, bitmap, width, height,
867                                GL_COLOR_INDEX, GL_BITMAP, row, 0 );
868 
869       if (unpack->LsbFirst) {
870          /* Lsb first */
871          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
872          for (col=0; col<width; col++) {
873             if (*src & mask) {
874 	       vert.tv.x = px+col;
875 	       vert.tv.y = h - (py+row) - 1;
876 	       r200_point( rmesa, &vert );
877             }
878 	    src += (mask >> 7);
879 	    mask = ((mask << 1) & 0xff) | (mask >> 7);
880          }
881 
882          /* get ready for next row */
883          if (mask != 1)
884             src++;
885       }
886       else {
887          /* Msb first */
888          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
889          for (col=0; col<width; col++) {
890             if (*src & mask) {
891 	       vert.tv.x = px+col;
892 	       vert.tv.y = h - (py+row) - 1;
893 	       r200_point( rmesa, &vert );
894             }
895 	    src += mask & 1;
896 	    mask = ((mask << 7) & 0xff) | (mask >> 1);
897          }
898          /* get ready for next row */
899          if (mask != 128)
900             src++;
901       }
902    }
903 
904    /* Fire outstanding vertices, restore state
905     */
906    R200_STATECHANGE( rmesa, vte );
907    rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] = orig_vte;
908 
909    /* Unfallback
910     */
911    TCL_FALLBACK( ctx, R200_TCL_FALLBACK_BITMAP, 0 );
912 
913    /* Need to restore vertexformat?
914     */
915    if (rmesa->radeon.TclFallback)
916       r200ChooseVertexState( ctx );
917 }
918 
919 
920 
921 /**********************************************************************/
922 /*                            Initialization.                         */
923 /**********************************************************************/
924 
r200InitSwtcl(struct gl_context * ctx)925 void r200InitSwtcl( struct gl_context *ctx )
926 {
927    TNLcontext *tnl = TNL_CONTEXT(ctx);
928    r200ContextPtr rmesa = R200_CONTEXT(ctx);
929    static int firsttime = 1;
930 
931    if (firsttime) {
932       init_rast_tab();
933       firsttime = 0;
934    }
935    rmesa->radeon.swtcl.emit_prediction = 0;
936 
937    tnl->Driver.Render.Start = r200RenderStart;
938    tnl->Driver.Render.Finish = r200RenderFinish;
939    tnl->Driver.Render.PrimitiveNotify = r200RenderPrimitive;
940    tnl->Driver.Render.ResetLineStipple = r200ResetLineStipple;
941    tnl->Driver.Render.BuildVertices = _tnl_build_vertices;
942    tnl->Driver.Render.CopyPV = _tnl_copy_pv;
943    tnl->Driver.Render.Interp = _tnl_interp;
944 
945    /* FIXME: what are these numbers? */
946    _tnl_init_vertices( ctx, ctx->Const.MaxArrayLockSize + 12,
947 		       36 * sizeof(GLfloat) );
948 
949    rmesa->radeon.swtcl.verts = (GLubyte *)tnl->clipspace.vertex_buf;
950    rmesa->radeon.swtcl.RenderIndex = ~0;
951    rmesa->radeon.swtcl.render_primitive = GL_TRIANGLES;
952    rmesa->radeon.swtcl.hw_primitive = 0;
953 }
954 
955