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