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