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