Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 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 |
||
33 | */ |
||
34 | |||
35 | #include "main/glheader.h" |
||
36 | #include "main/imports.h" |
||
37 | #include "main/mtypes.h" |
||
38 | #include "main/enums.h" |
||
39 | #include "main/colormac.h" |
||
40 | #include "main/light.h" |
||
41 | #include "main/state.h" |
||
42 | |||
43 | #include "vbo/vbo.h" |
||
44 | #include "tnl/tnl.h" |
||
45 | #include "tnl/t_pipeline.h" |
||
46 | |||
47 | #include "r200_context.h" |
||
48 | #include "r200_state.h" |
||
49 | #include "r200_ioctl.h" |
||
50 | #include "r200_tcl.h" |
||
51 | #include "r200_swtcl.h" |
||
52 | #include "r200_maos.h" |
||
53 | |||
54 | #include "radeon_common_context.h" |
||
55 | |||
56 | |||
57 | |||
58 | #define HAVE_POINTS 1 |
||
59 | #define HAVE_LINES 1 |
||
60 | #define HAVE_LINE_LOOP 0 |
||
61 | #define HAVE_LINE_STRIPS 1 |
||
62 | #define HAVE_TRIANGLES 1 |
||
63 | #define HAVE_TRI_STRIPS 1 |
||
64 | #define HAVE_TRI_STRIP_1 0 |
||
65 | #define HAVE_TRI_FANS 1 |
||
66 | #define HAVE_QUADS 1 |
||
67 | #define HAVE_QUAD_STRIPS 1 |
||
68 | #define HAVE_POLYGONS 1 |
||
69 | #define HAVE_ELTS 1 |
||
70 | |||
71 | |||
72 | #define HW_POINTS ((!ctx->Point.SmoothFlag) ? \ |
||
73 | R200_VF_PRIM_POINT_SPRITES : R200_VF_PRIM_POINTS) |
||
74 | #define HW_LINES R200_VF_PRIM_LINES |
||
75 | #define HW_LINE_LOOP 0 |
||
76 | #define HW_LINE_STRIP R200_VF_PRIM_LINE_STRIP |
||
77 | #define HW_TRIANGLES R200_VF_PRIM_TRIANGLES |
||
78 | #define HW_TRIANGLE_STRIP_0 R200_VF_PRIM_TRIANGLE_STRIP |
||
79 | #define HW_TRIANGLE_STRIP_1 0 |
||
80 | #define HW_TRIANGLE_FAN R200_VF_PRIM_TRIANGLE_FAN |
||
81 | #define HW_QUADS R200_VF_PRIM_QUADS |
||
82 | #define HW_QUAD_STRIP R200_VF_PRIM_QUAD_STRIP |
||
83 | #define HW_POLYGON R200_VF_PRIM_POLYGON |
||
84 | |||
85 | |||
86 | static GLboolean discrete_prim[0x10] = { |
||
87 | 0, /* 0 none */ |
||
88 | 1, /* 1 points */ |
||
89 | 1, /* 2 lines */ |
||
90 | 0, /* 3 line_strip */ |
||
91 | 1, /* 4 tri_list */ |
||
92 | 0, /* 5 tri_fan */ |
||
93 | 0, /* 6 tri_strip */ |
||
94 | 0, /* 7 tri_w_flags */ |
||
95 | 1, /* 8 rect list (unused) */ |
||
96 | 1, /* 9 3vert point */ |
||
97 | 1, /* a 3vert line */ |
||
98 | 0, /* b point sprite */ |
||
99 | 0, /* c line loop */ |
||
100 | 1, /* d quads */ |
||
101 | 0, /* e quad strip */ |
||
102 | 0, /* f polygon */ |
||
103 | }; |
||
104 | |||
105 | |||
106 | #define LOCAL_VARS r200ContextPtr rmesa = R200_CONTEXT(ctx) |
||
107 | #define ELT_TYPE GLushort |
||
108 | |||
109 | #define ELT_INIT(prim, hw_prim) \ |
||
110 | r200TclPrimitive( ctx, prim, hw_prim | R200_VF_PRIM_WALK_IND ) |
||
111 | |||
112 | #define GET_MESA_ELTS() TNL_CONTEXT(ctx)->vb.Elts |
||
113 | |||
114 | |||
115 | /* Don't really know how many elts will fit in what's left of cmdbuf, |
||
116 | * as there is state to emit, etc: |
||
117 | */ |
||
118 | |||
119 | /* Testing on isosurf shows a maximum around here. Don't know if it's |
||
120 | * the card or driver or kernel module that is causing the behaviour. |
||
121 | */ |
||
122 | #define GET_MAX_HW_ELTS() 300 |
||
123 | |||
124 | #define RESET_STIPPLE() do { \ |
||
125 | R200_STATECHANGE( rmesa, lin ); \ |
||
126 | radeonEmitState(&rmesa->radeon); \ |
||
127 | } while (0) |
||
128 | |||
129 | #define AUTO_STIPPLE( mode ) do { \ |
||
130 | R200_STATECHANGE( rmesa, lin ); \ |
||
131 | if (mode) \ |
||
132 | rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] |= \ |
||
133 | R200_LINE_PATTERN_AUTO_RESET; \ |
||
134 | else \ |
||
135 | rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] &= \ |
||
136 | ~R200_LINE_PATTERN_AUTO_RESET; \ |
||
137 | radeonEmitState(&rmesa->radeon); \ |
||
138 | } while (0) |
||
139 | |||
140 | |||
141 | #define ALLOC_ELTS(nr) r200AllocElts( rmesa, nr ) |
||
142 | |||
143 | static GLushort *r200AllocElts( r200ContextPtr rmesa, GLuint nr ) |
||
144 | { |
||
145 | if (rmesa->radeon.dma.flush == r200FlushElts && |
||
146 | rmesa->tcl.elt_used + nr*2 < R200_ELT_BUF_SZ) { |
||
147 | |||
148 | GLushort *dest = (GLushort *)(rmesa->radeon.tcl.elt_dma_bo->ptr + |
||
149 | rmesa->radeon.tcl.elt_dma_offset + rmesa->tcl.elt_used); |
||
150 | |||
151 | rmesa->tcl.elt_used += nr*2; |
||
152 | |||
153 | return dest; |
||
154 | } |
||
155 | else { |
||
156 | if (rmesa->radeon.dma.flush) |
||
157 | rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
||
158 | |||
159 | r200EmitAOS( rmesa, |
||
160 | rmesa->radeon.tcl.aos_count, 0 ); |
||
161 | |||
162 | r200EmitMaxVtxIndex(rmesa, rmesa->radeon.tcl.aos[0].count); |
||
163 | return r200AllocEltsOpenEnded( rmesa, rmesa->tcl.hw_primitive, nr ); |
||
164 | } |
||
165 | } |
||
166 | |||
167 | |||
168 | #define CLOSE_ELTS() \ |
||
169 | do { \ |
||
170 | if (0) R200_NEWPRIM( rmesa ); \ |
||
171 | } \ |
||
172 | while (0) |
||
173 | |||
174 | |||
175 | /* TODO: Try to extend existing primitive if both are identical, |
||
176 | * discrete and there are no intervening state changes. (Somewhat |
||
177 | * duplicates changes to DrawArrays code) |
||
178 | */ |
||
179 | static void r200EmitPrim( struct gl_context *ctx, |
||
180 | GLenum prim, |
||
181 | GLuint hwprim, |
||
182 | GLuint start, |
||
183 | GLuint count) |
||
184 | { |
||
185 | r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
||
186 | r200TclPrimitive( ctx, prim, hwprim ); |
||
187 | |||
188 | // fprintf(stderr,"Emit prim %d\n", rmesa->radeon.tcl.aos_count); |
||
189 | |||
190 | r200EmitAOS( rmesa, |
||
191 | rmesa->radeon.tcl.aos_count, |
||
192 | start ); |
||
193 | |||
194 | /* Why couldn't this packet have taken an offset param? |
||
195 | */ |
||
196 | r200EmitVbufPrim( rmesa, |
||
197 | rmesa->tcl.hw_primitive, |
||
198 | count - start ); |
||
199 | } |
||
200 | |||
201 | #define EMIT_PRIM(ctx, prim, hwprim, start, count) do { \ |
||
202 | r200EmitPrim( ctx, prim, hwprim, start, count ); \ |
||
203 | (void) rmesa; } while (0) |
||
204 | |||
205 | #define MAX_CONVERSION_SIZE 40 |
||
206 | /* Try & join small primitives |
||
207 | */ |
||
208 | #if 0 |
||
209 | #define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) 0 |
||
210 | #else |
||
211 | #define PREFER_DISCRETE_ELT_PRIM( NR, PRIM ) \ |
||
212 | ((NR) < 20 || \ |
||
213 | ((NR) < 40 && \ |
||
214 | rmesa->tcl.hw_primitive == (PRIM| \ |
||
215 | R200_VF_TCL_OUTPUT_VTX_ENABLE| \ |
||
216 | R200_VF_PRIM_WALK_IND))) |
||
217 | #endif |
||
218 | |||
219 | #ifdef MESA_BIG_ENDIAN |
||
220 | /* We could do without (most of) this ugliness if dest was always 32 bit word aligned... */ |
||
221 | #define EMIT_ELT(dest, offset, x) do { \ |
||
222 | int off = offset + ( ( (uintptr_t)dest & 0x2 ) >> 1 ); \ |
||
223 | GLushort *des = (GLushort *)( (uintptr_t)dest & ~0x2 ); \ |
||
224 | (des)[ off + 1 - 2 * ( off & 1 ) ] = (GLushort)(x); \ |
||
225 | (void)rmesa; } while (0) |
||
226 | #else |
||
227 | #define EMIT_ELT(dest, offset, x) do { \ |
||
228 | (dest)[offset] = (GLushort) (x); \ |
||
229 | (void)rmesa; } while (0) |
||
230 | #endif |
||
231 | |||
232 | #define EMIT_TWO_ELTS(dest, offset, x, y) *(GLuint *)((dest)+offset) = ((y)<<16)|(x); |
||
233 | |||
234 | |||
235 | |||
236 | #define TAG(x) tcl_##x |
||
237 | #include "tnl_dd/t_dd_dmatmp2.h" |
||
238 | |||
239 | /**********************************************************************/ |
||
240 | /* External entrypoints */ |
||
241 | /**********************************************************************/ |
||
242 | |||
243 | void r200EmitPrimitive( struct gl_context *ctx, |
||
244 | GLuint first, |
||
245 | GLuint last, |
||
246 | GLuint flags ) |
||
247 | { |
||
248 | tcl_render_tab_verts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
||
249 | } |
||
250 | |||
251 | void r200EmitEltPrimitive( struct gl_context *ctx, |
||
252 | GLuint first, |
||
253 | GLuint last, |
||
254 | GLuint flags ) |
||
255 | { |
||
256 | tcl_render_tab_elts[flags&PRIM_MODE_MASK]( ctx, first, last, flags ); |
||
257 | } |
||
258 | |||
259 | void r200TclPrimitive( struct gl_context *ctx, |
||
260 | GLenum prim, |
||
261 | int hw_prim ) |
||
262 | { |
||
263 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
264 | GLuint newprim = hw_prim | R200_VF_TCL_OUTPUT_VTX_ENABLE; |
||
265 | |||
266 | radeon_prepare_render(&rmesa->radeon); |
||
267 | if (rmesa->radeon.NewGLState) |
||
268 | r200ValidateState( ctx ); |
||
269 | |||
270 | if (newprim != rmesa->tcl.hw_primitive || |
||
271 | !discrete_prim[hw_prim&0xf]) { |
||
272 | /* need to disable perspective-correct texturing for point sprites */ |
||
273 | if ((prim & PRIM_MODE_MASK) == GL_POINTS && ctx->Point.PointSprite) { |
||
274 | if (rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE) { |
||
275 | R200_STATECHANGE( rmesa, set ); |
||
276 | rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PERSPECTIVE_ENABLE; |
||
277 | } |
||
278 | } |
||
279 | else if (!(rmesa->hw.set.cmd[SET_RE_CNTL] & R200_PERSPECTIVE_ENABLE)) { |
||
280 | R200_STATECHANGE( rmesa, set ); |
||
281 | rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PERSPECTIVE_ENABLE; |
||
282 | } |
||
283 | R200_NEWPRIM( rmesa ); |
||
284 | rmesa->tcl.hw_primitive = newprim; |
||
285 | } |
||
286 | } |
||
287 | |||
288 | /** |
||
289 | * Predict total emit size for next rendering operation so there is no flush in middle of rendering |
||
290 | * Prediction has to aim towards the best possible value that is worse than worst case scenario |
||
291 | */ |
||
292 | static GLuint r200EnsureEmitSize( struct gl_context * ctx , GLubyte* vimap_rev ) |
||
293 | { |
||
294 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
295 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
296 | struct vertex_buffer *VB = &tnl->vb; |
||
297 | GLuint space_required; |
||
298 | GLuint state_size; |
||
299 | GLuint nr_aos = 0; |
||
300 | int i; |
||
301 | /* predict number of aos to emit */ |
||
302 | for (i = 0; i < 15; ++i) |
||
303 | { |
||
304 | if (vimap_rev[i] != 255) |
||
305 | { |
||
306 | ++nr_aos; |
||
307 | } |
||
308 | } |
||
309 | |||
310 | { |
||
311 | /* count the prediction for state size */ |
||
312 | space_required = 0; |
||
313 | state_size = radeonCountStateEmitSize( &rmesa->radeon ); |
||
314 | /* vtx may be changed in r200EmitArrays so account for it if not dirty */ |
||
315 | if (!rmesa->hw.vtx.dirty) |
||
316 | state_size += rmesa->hw.vtx.check(&rmesa->radeon.glCtx, &rmesa->hw.vtx); |
||
317 | /* predict size for elements */ |
||
318 | for (i = 0; i < VB->PrimitiveCount; ++i) |
||
319 | { |
||
320 | if (!VB->Primitive[i].count) |
||
321 | continue; |
||
322 | /* If primitive.count is less than MAX_CONVERSION_SIZE |
||
323 | rendering code may decide convert to elts. |
||
324 | In that case we have to make pessimistic prediction. |
||
325 | and use larger of 2 paths. */ |
||
326 | const GLuint elt_count =(VB->Primitive[i].count/GET_MAX_HW_ELTS() + 1); |
||
327 | const GLuint elts = ELTS_BUFSZ(nr_aos) * elt_count; |
||
328 | const GLuint index = INDEX_BUFSZ * elt_count; |
||
329 | const GLuint vbuf = VBUF_BUFSZ; |
||
330 | if ( (!VB->Elts && VB->Primitive[i].count >= MAX_CONVERSION_SIZE) |
||
331 | || vbuf > index + elts) |
||
332 | space_required += vbuf; |
||
333 | else |
||
334 | space_required += index + elts; |
||
335 | space_required += AOS_BUFSZ(nr_aos); |
||
336 | } |
||
337 | } |
||
338 | |||
339 | radeon_print(RADEON_RENDER,RADEON_VERBOSE, |
||
340 | "%s space %u, aos %d\n", |
||
341 | __func__, space_required, AOS_BUFSZ(nr_aos) ); |
||
342 | /* flush the buffer in case we need more than is left. */ |
||
343 | if (rcommonEnsureCmdBufSpace(&rmesa->radeon, space_required + state_size, __FUNCTION__)) |
||
344 | return space_required + radeonCountStateEmitSize( &rmesa->radeon ); |
||
345 | else |
||
346 | return space_required + state_size; |
||
347 | } |
||
348 | |||
349 | |||
350 | /**********************************************************************/ |
||
351 | /* Render pipeline stage */ |
||
352 | /**********************************************************************/ |
||
353 | |||
354 | |||
355 | /* TCL render. |
||
356 | */ |
||
357 | static GLboolean r200_run_tcl_render( struct gl_context *ctx, |
||
358 | struct tnl_pipeline_stage *stage ) |
||
359 | { |
||
360 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
361 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
362 | struct vertex_buffer *VB = &tnl->vb; |
||
363 | GLuint i; |
||
364 | GLubyte *vimap_rev; |
||
365 | /* use hw fixed order for simplicity, pos 0, weight 1, normal 2, fog 3, |
||
366 | color0 - color3 4-7, texcoord0 - texcoord5 8-13, pos 1 14. Must not use |
||
367 | more than 12 of those at the same time. */ |
||
368 | GLubyte map_rev_fixed[15] = {255, 255, 255, 255, 255, 255, 255, 255, |
||
369 | 255, 255, 255, 255, 255, 255, 255}; |
||
370 | |||
371 | |||
372 | /* TODO: separate this from the swtnl pipeline |
||
373 | */ |
||
374 | if (rmesa->radeon.TclFallback) |
||
375 | return GL_TRUE; /* fallback to software t&l */ |
||
376 | |||
377 | radeon_print(RADEON_RENDER, RADEON_NORMAL, "%s\n", __FUNCTION__); |
||
378 | |||
379 | if (VB->Count == 0) |
||
380 | return GL_FALSE; |
||
381 | |||
382 | /* Validate state: |
||
383 | */ |
||
384 | if (rmesa->radeon.NewGLState) |
||
385 | if (!r200ValidateState( ctx )) |
||
386 | return GL_TRUE; /* fallback to sw t&l */ |
||
387 | |||
388 | if (!ctx->VertexProgram._Enabled) { |
||
389 | /* NOTE: inputs != tnl->render_inputs - these are the untransformed |
||
390 | * inputs. |
||
391 | */ |
||
392 | map_rev_fixed[0] = VERT_ATTRIB_POS; |
||
393 | /* technically there is no reason we always need VA_COLOR0. In theory |
||
394 | could disable it depending on lighting, color materials, texturing... */ |
||
395 | map_rev_fixed[4] = VERT_ATTRIB_COLOR0; |
||
396 | |||
397 | if (ctx->Light.Enabled) { |
||
398 | map_rev_fixed[2] = VERT_ATTRIB_NORMAL; |
||
399 | } |
||
400 | |||
401 | /* this also enables VA_COLOR1 when using separate specular |
||
402 | lighting model, which is unnecessary. |
||
403 | FIXME: OTOH, we're missing the case where a ATI_fragment_shader accesses |
||
404 | the secondary color (if lighting is disabled). The chip seems |
||
405 | misconfigured for that though elsewhere (tcl output, might lock up) */ |
||
406 | if (_mesa_need_secondary_color(ctx)) { |
||
407 | map_rev_fixed[5] = VERT_ATTRIB_COLOR1; |
||
408 | } |
||
409 | |||
410 | if ( (ctx->Fog.FogCoordinateSource == GL_FOG_COORD) && ctx->Fog.Enabled ) { |
||
411 | map_rev_fixed[3] = VERT_ATTRIB_FOG; |
||
412 | } |
||
413 | |||
414 | for (i = 0 ; i < ctx->Const.MaxTextureUnits; i++) { |
||
415 | if (ctx->Texture.Unit[i]._ReallyEnabled) { |
||
416 | if (rmesa->TexGenNeedNormals[i]) { |
||
417 | map_rev_fixed[2] = VERT_ATTRIB_NORMAL; |
||
418 | } |
||
419 | map_rev_fixed[8 + i] = VERT_ATTRIB_TEX0 + i; |
||
420 | } |
||
421 | } |
||
422 | vimap_rev = &map_rev_fixed[0]; |
||
423 | } |
||
424 | else { |
||
425 | /* vtx_tcl_output_vtxfmt_0/1 need to match configuration of "fragment |
||
426 | part", since using some vertex interpolator later which is not in |
||
427 | out_vtxfmt0/1 will lock up. It seems to be ok to write in vertex |
||
428 | prog to a not enabled output however, so just don't mess with it. |
||
429 | We only need to change compsel. */ |
||
430 | GLuint out_compsel = 0; |
||
431 | const GLbitfield64 vp_out = |
||
432 | rmesa->curr_vp_hw->mesa_program.Base.OutputsWritten; |
||
433 | |||
434 | vimap_rev = &rmesa->curr_vp_hw->inputmap_rev[0]; |
||
435 | assert(vp_out & BITFIELD64_BIT(VARYING_SLOT_POS)); |
||
436 | out_compsel = R200_OUTPUT_XYZW; |
||
437 | if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL0)) { |
||
438 | out_compsel |= R200_OUTPUT_COLOR_0; |
||
439 | } |
||
440 | if (vp_out & BITFIELD64_BIT(VARYING_SLOT_COL1)) { |
||
441 | out_compsel |= R200_OUTPUT_COLOR_1; |
||
442 | } |
||
443 | if (vp_out & BITFIELD64_BIT(VARYING_SLOT_FOGC)) { |
||
444 | out_compsel |= R200_OUTPUT_DISCRETE_FOG; |
||
445 | } |
||
446 | if (vp_out & BITFIELD64_BIT(VARYING_SLOT_PSIZ)) { |
||
447 | out_compsel |= R200_OUTPUT_PT_SIZE; |
||
448 | } |
||
449 | for (i = VARYING_SLOT_TEX0; i < VARYING_SLOT_TEX6; i++) { |
||
450 | if (vp_out & BITFIELD64_BIT(i)) { |
||
451 | out_compsel |= R200_OUTPUT_TEX_0 << (i - VARYING_SLOT_TEX0); |
||
452 | } |
||
453 | } |
||
454 | if (rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] != out_compsel) { |
||
455 | R200_STATECHANGE( rmesa, vtx ); |
||
456 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = out_compsel; |
||
457 | } |
||
458 | } |
||
459 | |||
460 | /* Do the actual work: |
||
461 | */ |
||
462 | radeonReleaseArrays( ctx, ~0 /* stage->changed_inputs */ ); |
||
463 | GLuint emit_end = r200EnsureEmitSize( ctx, vimap_rev ) |
||
464 | + rmesa->radeon.cmdbuf.cs->cdw; |
||
465 | r200EmitArrays( ctx, vimap_rev ); |
||
466 | |||
467 | for (i = 0 ; i < VB->PrimitiveCount ; i++) |
||
468 | { |
||
469 | GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); |
||
470 | GLuint start = VB->Primitive[i].start; |
||
471 | GLuint length = VB->Primitive[i].count; |
||
472 | |||
473 | if (!length) |
||
474 | continue; |
||
475 | |||
476 | if (VB->Elts) |
||
477 | r200EmitEltPrimitive( ctx, start, start+length, prim ); |
||
478 | else |
||
479 | r200EmitPrimitive( ctx, start, start+length, prim ); |
||
480 | } |
||
481 | if ( emit_end < rmesa->radeon.cmdbuf.cs->cdw ) |
||
482 | WARN_ONCE("Rendering was %d commands larger than predicted size." |
||
483 | " We might overflow command buffer.\n", rmesa->radeon.cmdbuf.cs->cdw - emit_end); |
||
484 | |||
485 | return GL_FALSE; /* finished the pipe */ |
||
486 | } |
||
487 | |||
488 | |||
489 | |||
490 | /* Initial state for tcl stage. |
||
491 | */ |
||
492 | const struct tnl_pipeline_stage _r200_tcl_stage = |
||
493 | { |
||
494 | "r200 render", |
||
495 | NULL, /* private */ |
||
496 | NULL, |
||
497 | NULL, |
||
498 | NULL, |
||
499 | r200_run_tcl_render /* run */ |
||
500 | }; |
||
501 | |||
502 | |||
503 | |||
504 | /**********************************************************************/ |
||
505 | /* Validate state at pipeline start */ |
||
506 | /**********************************************************************/ |
||
507 | |||
508 | |||
509 | /*----------------------------------------------------------------------- |
||
510 | * Manage TCL fallbacks |
||
511 | */ |
||
512 | |||
513 | |||
514 | static void transition_to_swtnl( struct gl_context *ctx ) |
||
515 | { |
||
516 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
517 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
518 | |||
519 | R200_NEWPRIM( rmesa ); |
||
520 | |||
521 | r200ChooseVertexState( ctx ); |
||
522 | r200ChooseRenderState( ctx ); |
||
523 | |||
524 | _tnl_validate_shine_tables( ctx ); |
||
525 | |||
526 | tnl->Driver.NotifyMaterialChange = |
||
527 | _tnl_validate_shine_tables; |
||
528 | |||
529 | radeonReleaseArrays( ctx, ~0 ); |
||
530 | |||
531 | /* Still using the D3D based hardware-rasterizer from the radeon; |
||
532 | * need to put the card into D3D mode to make it work: |
||
533 | */ |
||
534 | R200_STATECHANGE( rmesa, vap ); |
||
535 | rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~(R200_VAP_TCL_ENABLE|R200_VAP_PROG_VTX_SHADER_ENABLE); |
||
536 | } |
||
537 | |||
538 | static void transition_to_hwtnl( struct gl_context *ctx ) |
||
539 | { |
||
540 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
541 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
542 | |||
543 | _tnl_need_projected_coords( ctx, GL_FALSE ); |
||
544 | |||
545 | r200UpdateMaterial( ctx ); |
||
546 | |||
547 | tnl->Driver.NotifyMaterialChange = r200UpdateMaterial; |
||
548 | |||
549 | if ( rmesa->radeon.dma.flush ) |
||
550 | rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
||
551 | |||
552 | rmesa->radeon.dma.flush = NULL; |
||
553 | |||
554 | R200_STATECHANGE( rmesa, vap ); |
||
555 | rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_TCL_ENABLE; |
||
556 | rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_FORCE_W_TO_ONE; |
||
557 | |||
558 | if (ctx->VertexProgram._Enabled) { |
||
559 | rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] |= R200_VAP_PROG_VTX_SHADER_ENABLE; |
||
560 | } |
||
561 | |||
562 | if ( ((rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] & R200_FOG_USE_MASK) |
||
563 | == R200_FOG_USE_SPEC_ALPHA) && |
||
564 | (ctx->Fog.FogCoordinateSource == GL_FOG_COORD )) { |
||
565 | R200_STATECHANGE( rmesa, ctx ); |
||
566 | rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_USE_MASK; |
||
567 | rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= R200_FOG_USE_VTX_FOG; |
||
568 | } |
||
569 | |||
570 | R200_STATECHANGE( rmesa, vte ); |
||
571 | rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] &= ~(R200_VTX_XY_FMT|R200_VTX_Z_FMT); |
||
572 | rmesa->hw.vte.cmd[VTE_SE_VTE_CNTL] |= R200_VTX_W0_FMT; |
||
573 | |||
574 | if (R200_DEBUG & RADEON_FALLBACKS) |
||
575 | fprintf(stderr, "R200 end tcl fallback\n"); |
||
576 | } |
||
577 | |||
578 | |||
579 | static char *fallbackStrings[] = { |
||
580 | "Rasterization fallback", |
||
581 | "Unfilled triangles", |
||
582 | "Twosided lighting, differing materials", |
||
583 | "Materials in VB (maybe between begin/end)", |
||
584 | "Texgen unit 0", |
||
585 | "Texgen unit 1", |
||
586 | "Texgen unit 2", |
||
587 | "Texgen unit 3", |
||
588 | "Texgen unit 4", |
||
589 | "Texgen unit 5", |
||
590 | "User disable", |
||
591 | "Bitmap as points", |
||
592 | "Vertex program" |
||
593 | }; |
||
594 | |||
595 | |||
596 | static char *getFallbackString(GLuint bit) |
||
597 | { |
||
598 | int i = 0; |
||
599 | while (bit > 1) { |
||
600 | i++; |
||
601 | bit >>= 1; |
||
602 | } |
||
603 | return fallbackStrings[i]; |
||
604 | } |
||
605 | |||
606 | |||
607 | |||
608 | void r200TclFallback( struct gl_context *ctx, GLuint bit, GLboolean mode ) |
||
609 | { |
||
610 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
611 | GLuint oldfallback = rmesa->radeon.TclFallback; |
||
612 | |||
613 | if (mode) { |
||
614 | if (oldfallback == 0) { |
||
615 | /* We have to flush before transition */ |
||
616 | if ( rmesa->radeon.dma.flush ) |
||
617 | rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
||
618 | |||
619 | if (R200_DEBUG & RADEON_FALLBACKS) |
||
620 | fprintf(stderr, "R200 begin tcl fallback %s\n", |
||
621 | getFallbackString( bit )); |
||
622 | rmesa->radeon.TclFallback |= bit; |
||
623 | transition_to_swtnl( ctx ); |
||
624 | } else |
||
625 | rmesa->radeon.TclFallback |= bit; |
||
626 | } else { |
||
627 | if (oldfallback == bit) { |
||
628 | /* We have to flush before transition */ |
||
629 | if ( rmesa->radeon.dma.flush ) |
||
630 | rmesa->radeon.dma.flush( &rmesa->radeon.glCtx ); |
||
631 | |||
632 | if (R200_DEBUG & RADEON_FALLBACKS) |
||
633 | fprintf(stderr, "R200 end tcl fallback %s\n", |
||
634 | getFallbackString( bit )); |
||
635 | rmesa->radeon.TclFallback &= ~bit; |
||
636 | transition_to_hwtnl( ctx ); |
||
637 | } else |
||
638 | rmesa->radeon.TclFallback &= ~bit; |
||
639 | } |
||
640 | }>>><>>>>>16)|(x); |