Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5563 | serge | 1 | /************************************************************************** |
2 | |||
3 | Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. |
||
4 | |||
5 | The Weather Channel (TM) funded Tungsten Graphics to develop the |
||
6 | initial release of the Radeon 8500 driver under the XFree86 license. |
||
7 | This notice must be preserved. |
||
8 | |||
9 | Permission is hereby granted, free of charge, to any person obtaining |
||
10 | a copy of this software and associated documentation files (the |
||
11 | "Software"), to deal in the Software without restriction, including |
||
12 | without limitation the rights to use, copy, modify, merge, publish, |
||
13 | distribute, sublicense, and/or sell copies of the Software, and to |
||
14 | permit persons to whom the Software is furnished to do so, subject to |
||
15 | the following conditions: |
||
16 | |||
17 | The above copyright notice and this permission notice (including the |
||
18 | next paragraph) shall be included in all copies or substantial |
||
19 | portions of the Software. |
||
20 | |||
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
||
22 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
||
23 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
||
24 | IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE |
||
25 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
||
26 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
||
27 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
||
28 | |||
29 | **************************************************************************/ |
||
30 | |||
31 | /* |
||
32 | * Authors: |
||
33 | * Keith Whitwell |
||
34 | */ |
||
35 | |||
36 | #include "main/glheader.h" |
||
37 | #include "main/imports.h" |
||
38 | #include "main/api_arrayelt.h" |
||
39 | #include "main/enums.h" |
||
40 | #include "main/colormac.h" |
||
41 | #include "main/light.h" |
||
42 | #include "main/framebuffer.h" |
||
43 | #include "main/fbobject.h" |
||
44 | #include "main/stencil.h" |
||
45 | |||
46 | #include "swrast/swrast.h" |
||
47 | #include "vbo/vbo.h" |
||
48 | #include "tnl/tnl.h" |
||
49 | #include "tnl/t_pipeline.h" |
||
50 | #include "swrast_setup/swrast_setup.h" |
||
51 | #include "drivers/common/meta.h" |
||
52 | |||
53 | #include "radeon_common.h" |
||
54 | #include "radeon_mipmap_tree.h" |
||
55 | #include "r200_context.h" |
||
56 | #include "r200_ioctl.h" |
||
57 | #include "r200_state.h" |
||
58 | #include "r200_tcl.h" |
||
59 | #include "r200_tex.h" |
||
60 | #include "r200_swtcl.h" |
||
61 | #include "r200_vertprog.h" |
||
62 | |||
63 | |||
64 | /* ============================================================= |
||
65 | * Alpha blending |
||
66 | */ |
||
67 | |||
68 | static void r200AlphaFunc( struct gl_context *ctx, GLenum func, GLfloat ref ) |
||
69 | { |
||
70 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
71 | int pp_misc = rmesa->hw.ctx.cmd[CTX_PP_MISC]; |
||
72 | GLubyte refByte; |
||
73 | |||
74 | CLAMPED_FLOAT_TO_UBYTE(refByte, ref); |
||
75 | |||
76 | R200_STATECHANGE( rmesa, ctx ); |
||
77 | |||
78 | pp_misc &= ~(R200_ALPHA_TEST_OP_MASK | R200_REF_ALPHA_MASK); |
||
79 | pp_misc |= (refByte & R200_REF_ALPHA_MASK); |
||
80 | |||
81 | switch ( func ) { |
||
82 | case GL_NEVER: |
||
83 | pp_misc |= R200_ALPHA_TEST_FAIL; |
||
84 | break; |
||
85 | case GL_LESS: |
||
86 | pp_misc |= R200_ALPHA_TEST_LESS; |
||
87 | break; |
||
88 | case GL_EQUAL: |
||
89 | pp_misc |= R200_ALPHA_TEST_EQUAL; |
||
90 | break; |
||
91 | case GL_LEQUAL: |
||
92 | pp_misc |= R200_ALPHA_TEST_LEQUAL; |
||
93 | break; |
||
94 | case GL_GREATER: |
||
95 | pp_misc |= R200_ALPHA_TEST_GREATER; |
||
96 | break; |
||
97 | case GL_NOTEQUAL: |
||
98 | pp_misc |= R200_ALPHA_TEST_NEQUAL; |
||
99 | break; |
||
100 | case GL_GEQUAL: |
||
101 | pp_misc |= R200_ALPHA_TEST_GEQUAL; |
||
102 | break; |
||
103 | case GL_ALWAYS: |
||
104 | pp_misc |= R200_ALPHA_TEST_PASS; |
||
105 | break; |
||
106 | } |
||
107 | |||
108 | rmesa->hw.ctx.cmd[CTX_PP_MISC] = pp_misc; |
||
109 | } |
||
110 | |||
111 | static void r200BlendColor( struct gl_context *ctx, const GLfloat cf[4] ) |
||
112 | { |
||
113 | GLubyte color[4]; |
||
114 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
115 | R200_STATECHANGE( rmesa, ctx ); |
||
116 | CLAMPED_FLOAT_TO_UBYTE(color[0], cf[0]); |
||
117 | CLAMPED_FLOAT_TO_UBYTE(color[1], cf[1]); |
||
118 | CLAMPED_FLOAT_TO_UBYTE(color[2], cf[2]); |
||
119 | CLAMPED_FLOAT_TO_UBYTE(color[3], cf[3]); |
||
120 | rmesa->hw.ctx.cmd[CTX_RB3D_BLENDCOLOR] = radeonPackColor( 4, color[0], color[1], color[2], color[3] ); |
||
121 | } |
||
122 | |||
123 | /** |
||
124 | * Calculate the hardware blend factor setting. This same function is used |
||
125 | * for source and destination of both alpha and RGB. |
||
126 | * |
||
127 | * \returns |
||
128 | * The hardware register value for the specified blend factor. This value |
||
129 | * will need to be shifted into the correct position for either source or |
||
130 | * destination factor. |
||
131 | * |
||
132 | * \todo |
||
133 | * Since the two cases where source and destination are handled differently |
||
134 | * are essentially error cases, they should never happen. Determine if these |
||
135 | * cases can be removed. |
||
136 | */ |
||
137 | static int blend_factor( GLenum factor, GLboolean is_src ) |
||
138 | { |
||
139 | int func; |
||
140 | |||
141 | switch ( factor ) { |
||
142 | case GL_ZERO: |
||
143 | func = R200_BLEND_GL_ZERO; |
||
144 | break; |
||
145 | case GL_ONE: |
||
146 | func = R200_BLEND_GL_ONE; |
||
147 | break; |
||
148 | case GL_DST_COLOR: |
||
149 | func = R200_BLEND_GL_DST_COLOR; |
||
150 | break; |
||
151 | case GL_ONE_MINUS_DST_COLOR: |
||
152 | func = R200_BLEND_GL_ONE_MINUS_DST_COLOR; |
||
153 | break; |
||
154 | case GL_SRC_COLOR: |
||
155 | func = R200_BLEND_GL_SRC_COLOR; |
||
156 | break; |
||
157 | case GL_ONE_MINUS_SRC_COLOR: |
||
158 | func = R200_BLEND_GL_ONE_MINUS_SRC_COLOR; |
||
159 | break; |
||
160 | case GL_SRC_ALPHA: |
||
161 | func = R200_BLEND_GL_SRC_ALPHA; |
||
162 | break; |
||
163 | case GL_ONE_MINUS_SRC_ALPHA: |
||
164 | func = R200_BLEND_GL_ONE_MINUS_SRC_ALPHA; |
||
165 | break; |
||
166 | case GL_DST_ALPHA: |
||
167 | func = R200_BLEND_GL_DST_ALPHA; |
||
168 | break; |
||
169 | case GL_ONE_MINUS_DST_ALPHA: |
||
170 | func = R200_BLEND_GL_ONE_MINUS_DST_ALPHA; |
||
171 | break; |
||
172 | case GL_SRC_ALPHA_SATURATE: |
||
173 | func = (is_src) ? R200_BLEND_GL_SRC_ALPHA_SATURATE : R200_BLEND_GL_ZERO; |
||
174 | break; |
||
175 | case GL_CONSTANT_COLOR: |
||
176 | func = R200_BLEND_GL_CONST_COLOR; |
||
177 | break; |
||
178 | case GL_ONE_MINUS_CONSTANT_COLOR: |
||
179 | func = R200_BLEND_GL_ONE_MINUS_CONST_COLOR; |
||
180 | break; |
||
181 | case GL_CONSTANT_ALPHA: |
||
182 | func = R200_BLEND_GL_CONST_ALPHA; |
||
183 | break; |
||
184 | case GL_ONE_MINUS_CONSTANT_ALPHA: |
||
185 | func = R200_BLEND_GL_ONE_MINUS_CONST_ALPHA; |
||
186 | break; |
||
187 | default: |
||
188 | func = (is_src) ? R200_BLEND_GL_ONE : R200_BLEND_GL_ZERO; |
||
189 | } |
||
190 | return func; |
||
191 | } |
||
192 | |||
193 | /** |
||
194 | * Sets both the blend equation and the blend function. |
||
195 | * This is done in a single |
||
196 | * function because some blend equations (i.e., \c GL_MIN and \c GL_MAX) |
||
197 | * change the interpretation of the blend function. |
||
198 | * Also, make sure that blend function and blend equation are set to their default |
||
199 | * value if color blending is not enabled, since at least blend equations GL_MIN |
||
200 | * and GL_FUNC_REVERSE_SUBTRACT will cause wrong results otherwise for |
||
201 | * unknown reasons. |
||
202 | */ |
||
203 | static void r200_set_blend_state( struct gl_context * ctx ) |
||
204 | { |
||
205 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
206 | GLuint cntl = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & |
||
207 | ~(R200_ROP_ENABLE | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE); |
||
208 | |||
209 | int func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
210 | (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); |
||
211 | int eqn = R200_COMB_FCN_ADD_CLAMP; |
||
212 | int funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
213 | (R200_BLEND_GL_ZERO << R200_DST_BLEND_SHIFT); |
||
214 | int eqnA = R200_COMB_FCN_ADD_CLAMP; |
||
215 | |||
216 | R200_STATECHANGE( rmesa, ctx ); |
||
217 | |||
218 | if (ctx->Color.ColorLogicOpEnabled) { |
||
219 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ROP_ENABLE; |
||
220 | rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; |
||
221 | rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
||
222 | return; |
||
223 | } else if (ctx->Color.BlendEnabled) { |
||
224 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl | R200_ALPHA_BLEND_ENABLE | R200_SEPARATE_ALPHA_ENABLE; |
||
225 | } |
||
226 | else { |
||
227 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = cntl; |
||
228 | rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqn | func; |
||
229 | rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
||
230 | return; |
||
231 | } |
||
232 | |||
233 | func = (blend_factor( ctx->Color.Blend[0].SrcRGB, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | |
||
234 | (blend_factor( ctx->Color.Blend[0].DstRGB, GL_FALSE ) << R200_DST_BLEND_SHIFT); |
||
235 | |||
236 | switch(ctx->Color.Blend[0].EquationRGB) { |
||
237 | case GL_FUNC_ADD: |
||
238 | eqn = R200_COMB_FCN_ADD_CLAMP; |
||
239 | break; |
||
240 | |||
241 | case GL_FUNC_SUBTRACT: |
||
242 | eqn = R200_COMB_FCN_SUB_CLAMP; |
||
243 | break; |
||
244 | |||
245 | case GL_FUNC_REVERSE_SUBTRACT: |
||
246 | eqn = R200_COMB_FCN_RSUB_CLAMP; |
||
247 | break; |
||
248 | |||
249 | case GL_MIN: |
||
250 | eqn = R200_COMB_FCN_MIN; |
||
251 | func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
252 | (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
||
253 | break; |
||
254 | |||
255 | case GL_MAX: |
||
256 | eqn = R200_COMB_FCN_MAX; |
||
257 | func = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
258 | (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
||
259 | break; |
||
260 | |||
261 | default: |
||
262 | fprintf( stderr, "[%s:%u] Invalid RGB blend equation (0x%04x).\n", |
||
263 | __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationRGB ); |
||
264 | return; |
||
265 | } |
||
266 | |||
267 | funcA = (blend_factor( ctx->Color.Blend[0].SrcA, GL_TRUE ) << R200_SRC_BLEND_SHIFT) | |
||
268 | (blend_factor( ctx->Color.Blend[0].DstA, GL_FALSE ) << R200_DST_BLEND_SHIFT); |
||
269 | |||
270 | switch(ctx->Color.Blend[0].EquationA) { |
||
271 | case GL_FUNC_ADD: |
||
272 | eqnA = R200_COMB_FCN_ADD_CLAMP; |
||
273 | break; |
||
274 | |||
275 | case GL_FUNC_SUBTRACT: |
||
276 | eqnA = R200_COMB_FCN_SUB_CLAMP; |
||
277 | break; |
||
278 | |||
279 | case GL_FUNC_REVERSE_SUBTRACT: |
||
280 | eqnA = R200_COMB_FCN_RSUB_CLAMP; |
||
281 | break; |
||
282 | |||
283 | case GL_MIN: |
||
284 | eqnA = R200_COMB_FCN_MIN; |
||
285 | funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
286 | (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
||
287 | break; |
||
288 | |||
289 | case GL_MAX: |
||
290 | eqnA = R200_COMB_FCN_MAX; |
||
291 | funcA = (R200_BLEND_GL_ONE << R200_SRC_BLEND_SHIFT) | |
||
292 | (R200_BLEND_GL_ONE << R200_DST_BLEND_SHIFT); |
||
293 | break; |
||
294 | |||
295 | default: |
||
296 | fprintf( stderr, "[%s:%u] Invalid A blend equation (0x%04x).\n", |
||
297 | __FUNCTION__, __LINE__, ctx->Color.Blend[0].EquationA ); |
||
298 | return; |
||
299 | } |
||
300 | |||
301 | rmesa->hw.ctx.cmd[CTX_RB3D_ABLENDCNTL] = eqnA | funcA; |
||
302 | rmesa->hw.ctx.cmd[CTX_RB3D_CBLENDCNTL] = eqn | func; |
||
303 | |||
304 | } |
||
305 | |||
306 | static void r200BlendEquationSeparate( struct gl_context *ctx, |
||
307 | GLenum modeRGB, GLenum modeA ) |
||
308 | { |
||
309 | r200_set_blend_state( ctx ); |
||
310 | } |
||
311 | |||
312 | static void r200BlendFuncSeparate( struct gl_context *ctx, |
||
313 | GLenum sfactorRGB, GLenum dfactorRGB, |
||
314 | GLenum sfactorA, GLenum dfactorA ) |
||
315 | { |
||
316 | r200_set_blend_state( ctx ); |
||
317 | } |
||
318 | |||
319 | |||
320 | /* ============================================================= |
||
321 | * Depth testing |
||
322 | */ |
||
323 | |||
324 | static void r200DepthFunc( struct gl_context *ctx, GLenum func ) |
||
325 | { |
||
326 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
327 | |||
328 | R200_STATECHANGE( rmesa, ctx ); |
||
329 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_TEST_MASK; |
||
330 | |||
331 | switch ( ctx->Depth.Func ) { |
||
332 | case GL_NEVER: |
||
333 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEVER; |
||
334 | break; |
||
335 | case GL_LESS: |
||
336 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LESS; |
||
337 | break; |
||
338 | case GL_EQUAL: |
||
339 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_EQUAL; |
||
340 | break; |
||
341 | case GL_LEQUAL: |
||
342 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_LEQUAL; |
||
343 | break; |
||
344 | case GL_GREATER: |
||
345 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GREATER; |
||
346 | break; |
||
347 | case GL_NOTEQUAL: |
||
348 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_NEQUAL; |
||
349 | break; |
||
350 | case GL_GEQUAL: |
||
351 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_GEQUAL; |
||
352 | break; |
||
353 | case GL_ALWAYS: |
||
354 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_TEST_ALWAYS; |
||
355 | break; |
||
356 | } |
||
357 | } |
||
358 | |||
359 | static void r200DepthMask( struct gl_context *ctx, GLboolean flag ) |
||
360 | { |
||
361 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
362 | R200_STATECHANGE( rmesa, ctx ); |
||
363 | |||
364 | if ( ctx->Depth.Mask ) { |
||
365 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_Z_WRITE_ENABLE; |
||
366 | } else { |
||
367 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_Z_WRITE_ENABLE; |
||
368 | } |
||
369 | } |
||
370 | |||
371 | |||
372 | /* ============================================================= |
||
373 | * Fog |
||
374 | */ |
||
375 | |||
376 | |||
377 | static void r200Fogfv( struct gl_context *ctx, GLenum pname, const GLfloat *param ) |
||
378 | { |
||
379 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
380 | union { int i; float f; } c, d; |
||
381 | GLubyte col[4]; |
||
382 | GLuint i; |
||
383 | |||
384 | c.i = rmesa->hw.fog.cmd[FOG_C]; |
||
385 | d.i = rmesa->hw.fog.cmd[FOG_D]; |
||
386 | |||
387 | switch (pname) { |
||
388 | case GL_FOG_MODE: |
||
389 | if (!ctx->Fog.Enabled) |
||
390 | return; |
||
391 | R200_STATECHANGE(rmesa, tcl); |
||
392 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; |
||
393 | switch (ctx->Fog.Mode) { |
||
394 | case GL_LINEAR: |
||
395 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_LINEAR; |
||
396 | if (ctx->Fog.Start == ctx->Fog.End) { |
||
397 | c.f = 1.0F; |
||
398 | d.f = 1.0F; |
||
399 | } |
||
400 | else { |
||
401 | c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); |
||
402 | d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); |
||
403 | } |
||
404 | break; |
||
405 | case GL_EXP: |
||
406 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP; |
||
407 | c.f = 0.0; |
||
408 | d.f = -ctx->Fog.Density; |
||
409 | break; |
||
410 | case GL_EXP2: |
||
411 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_TCL_FOG_EXP2; |
||
412 | c.f = 0.0; |
||
413 | d.f = -(ctx->Fog.Density * ctx->Fog.Density); |
||
414 | break; |
||
415 | default: |
||
416 | return; |
||
417 | } |
||
418 | break; |
||
419 | case GL_FOG_DENSITY: |
||
420 | switch (ctx->Fog.Mode) { |
||
421 | case GL_EXP: |
||
422 | c.f = 0.0; |
||
423 | d.f = -ctx->Fog.Density; |
||
424 | break; |
||
425 | case GL_EXP2: |
||
426 | c.f = 0.0; |
||
427 | d.f = -(ctx->Fog.Density * ctx->Fog.Density); |
||
428 | break; |
||
429 | default: |
||
430 | break; |
||
431 | } |
||
432 | break; |
||
433 | case GL_FOG_START: |
||
434 | case GL_FOG_END: |
||
435 | if (ctx->Fog.Mode == GL_LINEAR) { |
||
436 | if (ctx->Fog.Start == ctx->Fog.End) { |
||
437 | c.f = 1.0F; |
||
438 | d.f = 1.0F; |
||
439 | } else { |
||
440 | c.f = ctx->Fog.End/(ctx->Fog.End-ctx->Fog.Start); |
||
441 | d.f = -1.0/(ctx->Fog.End-ctx->Fog.Start); |
||
442 | } |
||
443 | } |
||
444 | break; |
||
445 | case GL_FOG_COLOR: |
||
446 | R200_STATECHANGE( rmesa, ctx ); |
||
447 | _mesa_unclamped_float_rgba_to_ubyte(col, ctx->Fog.Color ); |
||
448 | i = radeonPackColor( 4, col[0], col[1], col[2], 0 ); |
||
449 | rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] &= ~R200_FOG_COLOR_MASK; |
||
450 | rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] |= i; |
||
451 | break; |
||
452 | case GL_FOG_COORD_SRC: { |
||
453 | GLuint out_0 = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]; |
||
454 | GLuint fog = rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR]; |
||
455 | |||
456 | fog &= ~R200_FOG_USE_MASK; |
||
457 | if ( ctx->Fog.FogCoordinateSource == GL_FOG_COORD || ctx->VertexProgram.Enabled) { |
||
458 | fog |= R200_FOG_USE_VTX_FOG; |
||
459 | out_0 |= R200_VTX_DISCRETE_FOG; |
||
460 | } |
||
461 | else { |
||
462 | fog |= R200_FOG_USE_SPEC_ALPHA; |
||
463 | out_0 &= ~R200_VTX_DISCRETE_FOG; |
||
464 | } |
||
465 | |||
466 | if ( fog != rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] ) { |
||
467 | R200_STATECHANGE( rmesa, ctx ); |
||
468 | rmesa->hw.ctx.cmd[CTX_PP_FOG_COLOR] = fog; |
||
469 | } |
||
470 | |||
471 | if (out_0 != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0]) { |
||
472 | R200_STATECHANGE( rmesa, vtx ); |
||
473 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] = out_0; |
||
474 | } |
||
475 | |||
476 | break; |
||
477 | } |
||
478 | default: |
||
479 | return; |
||
480 | } |
||
481 | |||
482 | if (c.i != rmesa->hw.fog.cmd[FOG_C] || d.i != rmesa->hw.fog.cmd[FOG_D]) { |
||
483 | R200_STATECHANGE( rmesa, fog ); |
||
484 | rmesa->hw.fog.cmd[FOG_C] = c.i; |
||
485 | rmesa->hw.fog.cmd[FOG_D] = d.i; |
||
486 | } |
||
487 | } |
||
488 | |||
489 | /* ============================================================= |
||
490 | * Culling |
||
491 | */ |
||
492 | |||
493 | static void r200CullFace( struct gl_context *ctx, GLenum unused ) |
||
494 | { |
||
495 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
496 | GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
||
497 | GLuint t = rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL]; |
||
498 | |||
499 | s |= R200_FFACE_SOLID | R200_BFACE_SOLID; |
||
500 | t &= ~(R200_CULL_FRONT | R200_CULL_BACK); |
||
501 | |||
502 | if ( ctx->Polygon.CullFlag ) { |
||
503 | switch ( ctx->Polygon.CullFaceMode ) { |
||
504 | case GL_FRONT: |
||
505 | s &= ~R200_FFACE_SOLID; |
||
506 | t |= R200_CULL_FRONT; |
||
507 | break; |
||
508 | case GL_BACK: |
||
509 | s &= ~R200_BFACE_SOLID; |
||
510 | t |= R200_CULL_BACK; |
||
511 | break; |
||
512 | case GL_FRONT_AND_BACK: |
||
513 | s &= ~(R200_FFACE_SOLID | R200_BFACE_SOLID); |
||
514 | t |= (R200_CULL_FRONT | R200_CULL_BACK); |
||
515 | break; |
||
516 | } |
||
517 | } |
||
518 | |||
519 | if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
||
520 | R200_STATECHANGE(rmesa, set ); |
||
521 | rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
||
522 | } |
||
523 | |||
524 | if ( rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] != t ) { |
||
525 | R200_STATECHANGE(rmesa, tcl ); |
||
526 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] = t; |
||
527 | } |
||
528 | } |
||
529 | |||
530 | static void r200FrontFace( struct gl_context *ctx, GLenum mode ) |
||
531 | { |
||
532 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
533 | int cull_face = (mode == GL_CW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW; |
||
534 | |||
535 | R200_STATECHANGE( rmesa, set ); |
||
536 | rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_FFACE_CULL_DIR_MASK; |
||
537 | |||
538 | R200_STATECHANGE( rmesa, tcl ); |
||
539 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_CULL_FRONT_IS_CCW; |
||
540 | |||
541 | /* Winding is inverted when rendering to FBO */ |
||
542 | if (ctx->DrawBuffer && _mesa_is_user_fbo(ctx->DrawBuffer)) |
||
543 | cull_face = (mode == GL_CCW) ? R200_FFACE_CULL_CW : R200_FFACE_CULL_CCW; |
||
544 | rmesa->hw.set.cmd[SET_SE_CNTL] |= cull_face; |
||
545 | |||
546 | if ( mode == GL_CCW ) |
||
547 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= R200_CULL_FRONT_IS_CCW; |
||
548 | } |
||
549 | |||
550 | /* ============================================================= |
||
551 | * Point state |
||
552 | */ |
||
553 | static void r200PointSize( struct gl_context *ctx, GLfloat size ) |
||
554 | { |
||
555 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
556 | GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
||
557 | |||
558 | radeon_print(RADEON_STATE, RADEON_TRACE, |
||
559 | "%s(%p) size: %f, fixed point result: %d.%d (%d/16)\n", |
||
560 | __func__, ctx, size, |
||
561 | ((GLuint)(ctx->Point.Size * 16.0))/16, |
||
562 | (((GLuint)(ctx->Point.Size * 16.0))&15)*100/16, |
||
563 | ((GLuint)(ctx->Point.Size * 16.0))&15); |
||
564 | |||
565 | R200_STATECHANGE( rmesa, cst ); |
||
566 | R200_STATECHANGE( rmesa, ptp ); |
||
567 | rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= ~0xffff; |
||
568 | rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= ((GLuint)(ctx->Point.Size * 16.0)); |
||
569 | /* this is the size param of the point size calculation (point size reg value |
||
570 | is not used when calculation is active). */ |
||
571 | fcmd[PTP_VPORT_SCALE_PTSIZE] = ctx->Point.Size; |
||
572 | } |
||
573 | |||
574 | static void r200PointParameter( struct gl_context *ctx, GLenum pname, const GLfloat *params) |
||
575 | { |
||
576 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
577 | GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
||
578 | |||
579 | switch (pname) { |
||
580 | case GL_POINT_SIZE_MIN: |
||
581 | /* Can clamp both in tcl and setup - just set both (as does fglrx) */ |
||
582 | R200_STATECHANGE( rmesa, lin ); |
||
583 | R200_STATECHANGE( rmesa, ptp ); |
||
584 | rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= 0xffff; |
||
585 | rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint)(ctx->Point.MinSize * 16.0) << 16; |
||
586 | fcmd[PTP_CLAMP_MIN] = ctx->Point.MinSize; |
||
587 | break; |
||
588 | case GL_POINT_SIZE_MAX: |
||
589 | R200_STATECHANGE( rmesa, cst ); |
||
590 | R200_STATECHANGE( rmesa, ptp ); |
||
591 | rmesa->hw.cst.cmd[CST_RE_POINTSIZE] &= 0xffff; |
||
592 | rmesa->hw.cst.cmd[CST_RE_POINTSIZE] |= (GLuint)(ctx->Point.MaxSize * 16.0) << 16; |
||
593 | fcmd[PTP_CLAMP_MAX] = ctx->Point.MaxSize; |
||
594 | break; |
||
595 | case GL_POINT_DISTANCE_ATTENUATION: |
||
596 | R200_STATECHANGE( rmesa, vtx ); |
||
597 | R200_STATECHANGE( rmesa, spr ); |
||
598 | R200_STATECHANGE( rmesa, ptp ); |
||
599 | GLfloat *fcmd = (GLfloat *)rmesa->hw.ptp.cmd; |
||
600 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= |
||
601 | ~(R200_PS_MULT_MASK | R200_PS_LIN_ATT_ZERO | R200_PS_SE_SEL_STATE); |
||
602 | /* can't rely on ctx->Point._Attenuated here and test for NEW_POINT in |
||
603 | r200ValidateState looks like overkill */ |
||
604 | if (ctx->Point.Params[0] != 1.0 || |
||
605 | ctx->Point.Params[1] != 0.0 || |
||
606 | ctx->Point.Params[2] != 0.0 || |
||
607 | (ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled)) { |
||
608 | /* all we care for vp would be the ps_se_sel_state setting */ |
||
609 | fcmd[PTP_ATT_CONST_QUAD] = ctx->Point.Params[2]; |
||
610 | fcmd[PTP_ATT_CONST_LIN] = ctx->Point.Params[1]; |
||
611 | fcmd[PTP_ATT_CONST_CON] = ctx->Point.Params[0]; |
||
612 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_MULT_ATTENCONST; |
||
613 | if (ctx->Point.Params[1] == 0.0) |
||
614 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= R200_PS_LIN_ATT_ZERO; |
||
615 | /* FIXME: setting this here doesn't look quite ok - we only want to do |
||
616 | that if we're actually drawing points probably */ |
||
617 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_PT_SIZE; |
||
618 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= R200_VTX_POINT_SIZE; |
||
619 | } |
||
620 | else { |
||
621 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= |
||
622 | R200_PS_SE_SEL_STATE | R200_PS_MULT_CONST; |
||
623 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_PT_SIZE; |
||
624 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~R200_VTX_POINT_SIZE; |
||
625 | } |
||
626 | break; |
||
627 | case GL_POINT_FADE_THRESHOLD_SIZE: |
||
628 | /* don't support multisampling, so doesn't matter. */ |
||
629 | break; |
||
630 | /* can't do these but don't need them. |
||
631 | case GL_POINT_SPRITE_R_MODE_NV: |
||
632 | case GL_POINT_SPRITE_COORD_ORIGIN: */ |
||
633 | default: |
||
634 | fprintf(stderr, "bad pname parameter in r200PointParameter\n"); |
||
635 | return; |
||
636 | } |
||
637 | } |
||
638 | |||
639 | /* ============================================================= |
||
640 | * Line state |
||
641 | */ |
||
642 | static void r200LineWidth( struct gl_context *ctx, GLfloat widthf ) |
||
643 | { |
||
644 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
645 | |||
646 | R200_STATECHANGE( rmesa, lin ); |
||
647 | R200_STATECHANGE( rmesa, set ); |
||
648 | |||
649 | /* Line width is stored in U6.4 format. |
||
650 | * Same min/max limits for AA, non-AA lines. |
||
651 | */ |
||
652 | rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] &= ~0xffff; |
||
653 | rmesa->hw.lin.cmd[LIN_SE_LINE_WIDTH] |= (GLuint) |
||
654 | (CLAMP(widthf, ctx->Const.MinLineWidth, ctx->Const.MaxLineWidth) * 16.0); |
||
655 | |||
656 | if ( widthf > 1.0 ) { |
||
657 | rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_WIDELINE_ENABLE; |
||
658 | } else { |
||
659 | rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_WIDELINE_ENABLE; |
||
660 | } |
||
661 | } |
||
662 | |||
663 | static void r200LineStipple( struct gl_context *ctx, GLint factor, GLushort pattern ) |
||
664 | { |
||
665 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
666 | |||
667 | R200_STATECHANGE( rmesa, lin ); |
||
668 | rmesa->hw.lin.cmd[LIN_RE_LINE_PATTERN] = |
||
669 | ((((GLuint)factor & 0xff) << 16) | ((GLuint)pattern)); |
||
670 | } |
||
671 | |||
672 | |||
673 | /* ============================================================= |
||
674 | * Masks |
||
675 | */ |
||
676 | static void r200ColorMask( struct gl_context *ctx, |
||
677 | GLboolean r, GLboolean g, |
||
678 | GLboolean b, GLboolean a ) |
||
679 | { |
||
680 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
681 | GLuint mask; |
||
682 | struct radeon_renderbuffer *rrb; |
||
683 | GLuint flag = rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] & ~R200_PLANE_MASK_ENABLE; |
||
684 | |||
685 | rrb = radeon_get_colorbuffer(&rmesa->radeon); |
||
686 | if (!rrb) |
||
687 | return; |
||
688 | mask = radeonPackColor( rrb->cpp, |
||
689 | ctx->Color.ColorMask[0][RCOMP], |
||
690 | ctx->Color.ColorMask[0][GCOMP], |
||
691 | ctx->Color.ColorMask[0][BCOMP], |
||
692 | ctx->Color.ColorMask[0][ACOMP] ); |
||
693 | |||
694 | |||
695 | if (!(r && g && b && a)) |
||
696 | flag |= R200_PLANE_MASK_ENABLE; |
||
697 | |||
698 | if ( rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] != flag ) { |
||
699 | R200_STATECHANGE( rmesa, ctx ); |
||
700 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] = flag; |
||
701 | } |
||
702 | |||
703 | if ( rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] != mask ) { |
||
704 | R200_STATECHANGE( rmesa, msk ); |
||
705 | rmesa->hw.msk.cmd[MSK_RB3D_PLANEMASK] = mask; |
||
706 | } |
||
707 | } |
||
708 | |||
709 | |||
710 | /* ============================================================= |
||
711 | * Polygon state |
||
712 | */ |
||
713 | |||
714 | static void r200PolygonOffset( struct gl_context *ctx, |
||
715 | GLfloat factor, GLfloat units ) |
||
716 | { |
||
717 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
718 | const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
||
719 | float_ui32_type constant = { units * depthScale }; |
||
720 | float_ui32_type factoru = { factor }; |
||
721 | |||
722 | /* factor *= 2; */ |
||
723 | /* constant *= 2; */ |
||
724 | |||
725 | /* fprintf(stderr, "%s f:%f u:%f\n", __FUNCTION__, factor, constant); */ |
||
726 | |||
727 | R200_STATECHANGE( rmesa, zbs ); |
||
728 | rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_FACTOR] = factoru.ui32; |
||
729 | rmesa->hw.zbs.cmd[ZBS_SE_ZBIAS_CONSTANT] = constant.ui32; |
||
730 | } |
||
731 | |||
732 | static void r200PolygonMode( struct gl_context *ctx, GLenum face, GLenum mode ) |
||
733 | { |
||
734 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
735 | GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL || |
||
736 | ctx->Polygon.BackMode != GL_FILL); |
||
737 | |||
738 | /* Can't generally do unfilled via tcl, but some good special |
||
739 | * cases work. |
||
740 | */ |
||
741 | TCL_FALLBACK( ctx, R200_TCL_FALLBACK_UNFILLED, unfilled); |
||
742 | if (rmesa->radeon.TclFallback) { |
||
743 | r200ChooseRenderState( ctx ); |
||
744 | r200ChooseVertexState( ctx ); |
||
745 | } |
||
746 | } |
||
747 | |||
748 | |||
749 | /* ============================================================= |
||
750 | * Rendering attributes |
||
751 | * |
||
752 | * We really don't want to recalculate all this every time we bind a |
||
753 | * texture. These things shouldn't change all that often, so it makes |
||
754 | * sense to break them out of the core texture state update routines. |
||
755 | */ |
||
756 | |||
757 | /* Examine lighting and texture state to determine if separate specular |
||
758 | * should be enabled. |
||
759 | */ |
||
760 | static void r200UpdateSpecular( struct gl_context *ctx ) |
||
761 | { |
||
762 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
763 | uint32_t p = rmesa->hw.ctx.cmd[CTX_PP_CNTL]; |
||
764 | |||
765 | R200_STATECHANGE( rmesa, tcl ); |
||
766 | R200_STATECHANGE( rmesa, vtx ); |
||
767 | |||
768 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3< |
||
769 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] &= ~(3< |
||
770 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_0; |
||
771 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] &= ~R200_OUTPUT_COLOR_1; |
||
772 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LIGHTING_ENABLE; |
||
773 | |||
774 | p &= ~R200_SPECULAR_ENABLE; |
||
775 | |||
776 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_DIFFUSE_SPECULAR_COMBINE; |
||
777 | |||
778 | |||
779 | if (ctx->Light.Enabled && |
||
780 | ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) { |
||
781 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
||
782 | ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | |
||
783 | (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
||
784 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; |
||
785 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; |
||
786 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; |
||
787 | p |= R200_SPECULAR_ENABLE; |
||
788 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= |
||
789 | ~R200_DIFFUSE_SPECULAR_COMBINE; |
||
790 | } |
||
791 | else if (ctx->Light.Enabled) { |
||
792 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
||
793 | ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); |
||
794 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_0; |
||
795 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHTING_ENABLE; |
||
796 | } else if (ctx->Fog.ColorSumEnabled ) { |
||
797 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
||
798 | ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT) | |
||
799 | (R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
||
800 | p |= R200_SPECULAR_ENABLE; |
||
801 | } else { |
||
802 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
||
803 | ((R200_VTX_FP_RGBA << R200_VTX_COLOR_0_SHIFT)); |
||
804 | } |
||
805 | |||
806 | if (ctx->Fog.Enabled) { |
||
807 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_VTXFMT_0] |= |
||
808 | ((R200_VTX_FP_RGBA << R200_VTX_COLOR_1_SHIFT)); |
||
809 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] |= R200_OUTPUT_COLOR_1; |
||
810 | } |
||
811 | |||
812 | if ( rmesa->hw.ctx.cmd[CTX_PP_CNTL] != p ) { |
||
813 | R200_STATECHANGE( rmesa, ctx ); |
||
814 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] = p; |
||
815 | } |
||
816 | |||
817 | /* Update vertex/render formats |
||
818 | */ |
||
819 | if (rmesa->radeon.TclFallback) { |
||
820 | r200ChooseRenderState( ctx ); |
||
821 | r200ChooseVertexState( ctx ); |
||
822 | } |
||
823 | } |
||
824 | |||
825 | |||
826 | /* ============================================================= |
||
827 | * Materials |
||
828 | */ |
||
829 | |||
830 | |||
831 | /* Update on colormaterial, material emmissive/ambient, |
||
832 | * lightmodel.globalambient |
||
833 | */ |
||
834 | static void update_global_ambient( struct gl_context *ctx ) |
||
835 | { |
||
836 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
837 | float *fcmd = (float *)R200_DB_STATE( glt ); |
||
838 | |||
839 | /* Need to do more if both emmissive & ambient are PREMULT: |
||
840 | * I believe this is not nessary when using source_material. This condition thus |
||
841 | * will never happen currently, and the function has no dependencies on materials now |
||
842 | */ |
||
843 | if ((rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] & |
||
844 | ((3 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
||
845 | (3 << R200_FRONT_AMBIENT_SOURCE_SHIFT))) == 0) |
||
846 | { |
||
847 | COPY_3V( &fcmd[GLT_RED], |
||
848 | ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_EMISSION]); |
||
849 | ACC_SCALE_3V( &fcmd[GLT_RED], |
||
850 | ctx->Light.Model.Ambient, |
||
851 | ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_AMBIENT]); |
||
852 | } |
||
853 | else |
||
854 | { |
||
855 | COPY_3V( &fcmd[GLT_RED], ctx->Light.Model.Ambient ); |
||
856 | } |
||
857 | |||
858 | R200_DB_STATECHANGE(rmesa, &rmesa->hw.glt); |
||
859 | } |
||
860 | |||
861 | /* Update on change to |
||
862 | * - light[p].colors |
||
863 | * - light[p].enabled |
||
864 | */ |
||
865 | static void update_light_colors( struct gl_context *ctx, GLuint p ) |
||
866 | { |
||
867 | struct gl_light *l = &ctx->Light.Light[p]; |
||
868 | |||
869 | /* fprintf(stderr, "%s\n", __FUNCTION__); */ |
||
870 | |||
871 | if (l->Enabled) { |
||
872 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
873 | float *fcmd = (float *)R200_DB_STATE( lit[p] ); |
||
874 | |||
875 | COPY_4V( &fcmd[LIT_AMBIENT_RED], l->Ambient ); |
||
876 | COPY_4V( &fcmd[LIT_DIFFUSE_RED], l->Diffuse ); |
||
877 | COPY_4V( &fcmd[LIT_SPECULAR_RED], l->Specular ); |
||
878 | |||
879 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
||
880 | } |
||
881 | } |
||
882 | |||
883 | static void r200ColorMaterial( struct gl_context *ctx, GLenum face, GLenum mode ) |
||
884 | { |
||
885 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
886 | GLuint light_model_ctl1 = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]; |
||
887 | light_model_ctl1 &= ~((0xf << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
||
888 | (0xf << R200_FRONT_AMBIENT_SOURCE_SHIFT) | |
||
889 | (0xf << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | |
||
890 | (0xf << R200_FRONT_SPECULAR_SOURCE_SHIFT) | |
||
891 | (0xf << R200_BACK_EMISSIVE_SOURCE_SHIFT) | |
||
892 | (0xf << R200_BACK_AMBIENT_SOURCE_SHIFT) | |
||
893 | (0xf << R200_BACK_DIFFUSE_SOURCE_SHIFT) | |
||
894 | (0xf << R200_BACK_SPECULAR_SOURCE_SHIFT)); |
||
895 | |||
896 | if (ctx->Light.ColorMaterialEnabled) { |
||
897 | GLuint mask = ctx->Light._ColorMaterialBitmask; |
||
898 | |||
899 | if (mask & MAT_BIT_FRONT_EMISSION) { |
||
900 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
901 | R200_FRONT_EMISSIVE_SOURCE_SHIFT); |
||
902 | } |
||
903 | else |
||
904 | light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
||
905 | R200_FRONT_EMISSIVE_SOURCE_SHIFT); |
||
906 | |||
907 | if (mask & MAT_BIT_FRONT_AMBIENT) { |
||
908 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
909 | R200_FRONT_AMBIENT_SOURCE_SHIFT); |
||
910 | } |
||
911 | else |
||
912 | light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
||
913 | R200_FRONT_AMBIENT_SOURCE_SHIFT); |
||
914 | |||
915 | if (mask & MAT_BIT_FRONT_DIFFUSE) { |
||
916 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
917 | R200_FRONT_DIFFUSE_SOURCE_SHIFT); |
||
918 | } |
||
919 | else |
||
920 | light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
||
921 | R200_FRONT_DIFFUSE_SOURCE_SHIFT); |
||
922 | |||
923 | if (mask & MAT_BIT_FRONT_SPECULAR) { |
||
924 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
925 | R200_FRONT_SPECULAR_SOURCE_SHIFT); |
||
926 | } |
||
927 | else { |
||
928 | light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_0 << |
||
929 | R200_FRONT_SPECULAR_SOURCE_SHIFT); |
||
930 | } |
||
931 | |||
932 | if (mask & MAT_BIT_BACK_EMISSION) { |
||
933 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
934 | R200_BACK_EMISSIVE_SOURCE_SHIFT); |
||
935 | } |
||
936 | |||
937 | else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
||
938 | R200_BACK_EMISSIVE_SOURCE_SHIFT); |
||
939 | |||
940 | if (mask & MAT_BIT_BACK_AMBIENT) { |
||
941 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
942 | R200_BACK_AMBIENT_SOURCE_SHIFT); |
||
943 | } |
||
944 | else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
||
945 | R200_BACK_AMBIENT_SOURCE_SHIFT); |
||
946 | |||
947 | if (mask & MAT_BIT_BACK_DIFFUSE) { |
||
948 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
949 | R200_BACK_DIFFUSE_SOURCE_SHIFT); |
||
950 | } |
||
951 | else light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
||
952 | R200_BACK_DIFFUSE_SOURCE_SHIFT); |
||
953 | |||
954 | if (mask & MAT_BIT_BACK_SPECULAR) { |
||
955 | light_model_ctl1 |= (R200_LM1_SOURCE_VERTEX_COLOR_0 << |
||
956 | R200_BACK_SPECULAR_SOURCE_SHIFT); |
||
957 | } |
||
958 | else { |
||
959 | light_model_ctl1 |= (R200_LM1_SOURCE_MATERIAL_1 << |
||
960 | R200_BACK_SPECULAR_SOURCE_SHIFT); |
||
961 | } |
||
962 | } |
||
963 | else { |
||
964 | /* Default to SOURCE_MATERIAL: |
||
965 | */ |
||
966 | light_model_ctl1 |= |
||
967 | (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_EMISSIVE_SOURCE_SHIFT) | |
||
968 | (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_AMBIENT_SOURCE_SHIFT) | |
||
969 | (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_DIFFUSE_SOURCE_SHIFT) | |
||
970 | (R200_LM1_SOURCE_MATERIAL_0 << R200_FRONT_SPECULAR_SOURCE_SHIFT) | |
||
971 | (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_EMISSIVE_SOURCE_SHIFT) | |
||
972 | (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_AMBIENT_SOURCE_SHIFT) | |
||
973 | (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_DIFFUSE_SOURCE_SHIFT) | |
||
974 | (R200_LM1_SOURCE_MATERIAL_1 << R200_BACK_SPECULAR_SOURCE_SHIFT); |
||
975 | } |
||
976 | |||
977 | if (light_model_ctl1 != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1]) { |
||
978 | R200_STATECHANGE( rmesa, tcl ); |
||
979 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_1] = light_model_ctl1; |
||
980 | } |
||
981 | |||
982 | |||
983 | } |
||
984 | |||
985 | void r200UpdateMaterial( struct gl_context *ctx ) |
||
986 | { |
||
987 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
988 | GLfloat (*mat)[4] = ctx->Light.Material.Attrib; |
||
989 | GLfloat *fcmd = (GLfloat *)R200_DB_STATE( mtl[0] ); |
||
990 | GLfloat *fcmd2 = (GLfloat *)R200_DB_STATE( mtl[1] ); |
||
991 | GLuint mask = ~0; |
||
992 | |||
993 | /* Might be possible and faster to update everything unconditionally? */ |
||
994 | if (ctx->Light.ColorMaterialEnabled) |
||
995 | mask &= ~ctx->Light._ColorMaterialBitmask; |
||
996 | |||
997 | if (R200_DEBUG & RADEON_STATE) |
||
998 | fprintf(stderr, "%s\n", __FUNCTION__); |
||
999 | |||
1000 | if (mask & MAT_BIT_FRONT_EMISSION) { |
||
1001 | fcmd[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_FRONT_EMISSION][0]; |
||
1002 | fcmd[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_FRONT_EMISSION][1]; |
||
1003 | fcmd[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_FRONT_EMISSION][2]; |
||
1004 | fcmd[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_FRONT_EMISSION][3]; |
||
1005 | } |
||
1006 | if (mask & MAT_BIT_FRONT_AMBIENT) { |
||
1007 | fcmd[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_FRONT_AMBIENT][0]; |
||
1008 | fcmd[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_FRONT_AMBIENT][1]; |
||
1009 | fcmd[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_FRONT_AMBIENT][2]; |
||
1010 | fcmd[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_FRONT_AMBIENT][3]; |
||
1011 | } |
||
1012 | if (mask & MAT_BIT_FRONT_DIFFUSE) { |
||
1013 | fcmd[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_FRONT_DIFFUSE][0]; |
||
1014 | fcmd[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_FRONT_DIFFUSE][1]; |
||
1015 | fcmd[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_FRONT_DIFFUSE][2]; |
||
1016 | fcmd[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_FRONT_DIFFUSE][3]; |
||
1017 | } |
||
1018 | if (mask & MAT_BIT_FRONT_SPECULAR) { |
||
1019 | fcmd[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_FRONT_SPECULAR][0]; |
||
1020 | fcmd[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_FRONT_SPECULAR][1]; |
||
1021 | fcmd[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_FRONT_SPECULAR][2]; |
||
1022 | fcmd[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_FRONT_SPECULAR][3]; |
||
1023 | } |
||
1024 | if (mask & MAT_BIT_FRONT_SHININESS) { |
||
1025 | fcmd[MTL_SHININESS] = mat[MAT_ATTRIB_FRONT_SHININESS][0]; |
||
1026 | } |
||
1027 | |||
1028 | if (mask & MAT_BIT_BACK_EMISSION) { |
||
1029 | fcmd2[MTL_EMMISSIVE_RED] = mat[MAT_ATTRIB_BACK_EMISSION][0]; |
||
1030 | fcmd2[MTL_EMMISSIVE_GREEN] = mat[MAT_ATTRIB_BACK_EMISSION][1]; |
||
1031 | fcmd2[MTL_EMMISSIVE_BLUE] = mat[MAT_ATTRIB_BACK_EMISSION][2]; |
||
1032 | fcmd2[MTL_EMMISSIVE_ALPHA] = mat[MAT_ATTRIB_BACK_EMISSION][3]; |
||
1033 | } |
||
1034 | if (mask & MAT_BIT_BACK_AMBIENT) { |
||
1035 | fcmd2[MTL_AMBIENT_RED] = mat[MAT_ATTRIB_BACK_AMBIENT][0]; |
||
1036 | fcmd2[MTL_AMBIENT_GREEN] = mat[MAT_ATTRIB_BACK_AMBIENT][1]; |
||
1037 | fcmd2[MTL_AMBIENT_BLUE] = mat[MAT_ATTRIB_BACK_AMBIENT][2]; |
||
1038 | fcmd2[MTL_AMBIENT_ALPHA] = mat[MAT_ATTRIB_BACK_AMBIENT][3]; |
||
1039 | } |
||
1040 | if (mask & MAT_BIT_BACK_DIFFUSE) { |
||
1041 | fcmd2[MTL_DIFFUSE_RED] = mat[MAT_ATTRIB_BACK_DIFFUSE][0]; |
||
1042 | fcmd2[MTL_DIFFUSE_GREEN] = mat[MAT_ATTRIB_BACK_DIFFUSE][1]; |
||
1043 | fcmd2[MTL_DIFFUSE_BLUE] = mat[MAT_ATTRIB_BACK_DIFFUSE][2]; |
||
1044 | fcmd2[MTL_DIFFUSE_ALPHA] = mat[MAT_ATTRIB_BACK_DIFFUSE][3]; |
||
1045 | } |
||
1046 | if (mask & MAT_BIT_BACK_SPECULAR) { |
||
1047 | fcmd2[MTL_SPECULAR_RED] = mat[MAT_ATTRIB_BACK_SPECULAR][0]; |
||
1048 | fcmd2[MTL_SPECULAR_GREEN] = mat[MAT_ATTRIB_BACK_SPECULAR][1]; |
||
1049 | fcmd2[MTL_SPECULAR_BLUE] = mat[MAT_ATTRIB_BACK_SPECULAR][2]; |
||
1050 | fcmd2[MTL_SPECULAR_ALPHA] = mat[MAT_ATTRIB_BACK_SPECULAR][3]; |
||
1051 | } |
||
1052 | if (mask & MAT_BIT_BACK_SHININESS) { |
||
1053 | fcmd2[MTL_SHININESS] = mat[MAT_ATTRIB_BACK_SHININESS][0]; |
||
1054 | } |
||
1055 | |||
1056 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[0] ); |
||
1057 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.mtl[1] ); |
||
1058 | |||
1059 | /* currently material changes cannot trigger a global ambient change, I believe this is correct |
||
1060 | update_global_ambient( ctx ); */ |
||
1061 | } |
||
1062 | |||
1063 | /* _NEW_LIGHT |
||
1064 | * _NEW_MODELVIEW |
||
1065 | * _MESA_NEW_NEED_EYE_COORDS |
||
1066 | * |
||
1067 | * Uses derived state from mesa: |
||
1068 | * _VP_inf_norm |
||
1069 | * _h_inf_norm |
||
1070 | * _Position |
||
1071 | * _NormSpotDirection |
||
1072 | * _ModelViewInvScale |
||
1073 | * _NeedEyeCoords |
||
1074 | * _EyeZDir |
||
1075 | * |
||
1076 | * which are calculated in light.c and are correct for the current |
||
1077 | * lighting space (model or eye), hence dependencies on _NEW_MODELVIEW |
||
1078 | * and _MESA_NEW_NEED_EYE_COORDS. |
||
1079 | */ |
||
1080 | static void update_light( struct gl_context *ctx ) |
||
1081 | { |
||
1082 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1083 | |||
1084 | /* Have to check these, or have an automatic shortcircuit mechanism |
||
1085 | * to remove noop statechanges. (Or just do a better job on the |
||
1086 | * front end). |
||
1087 | */ |
||
1088 | { |
||
1089 | GLuint tmp = rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]; |
||
1090 | |||
1091 | if (ctx->_NeedEyeCoords) |
||
1092 | tmp &= ~R200_LIGHT_IN_MODELSPACE; |
||
1093 | else |
||
1094 | tmp |= R200_LIGHT_IN_MODELSPACE; |
||
1095 | |||
1096 | if (tmp != rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]) |
||
1097 | { |
||
1098 | R200_STATECHANGE( rmesa, tcl ); |
||
1099 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] = tmp; |
||
1100 | } |
||
1101 | } |
||
1102 | |||
1103 | { |
||
1104 | GLfloat *fcmd = (GLfloat *)R200_DB_STATE( eye ); |
||
1105 | fcmd[EYE_X] = ctx->_EyeZDir[0]; |
||
1106 | fcmd[EYE_Y] = ctx->_EyeZDir[1]; |
||
1107 | fcmd[EYE_Z] = - ctx->_EyeZDir[2]; |
||
1108 | fcmd[EYE_RESCALE_FACTOR] = ctx->_ModelViewInvScale; |
||
1109 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.eye ); |
||
1110 | } |
||
1111 | |||
1112 | |||
1113 | |||
1114 | if (ctx->Light.Enabled) { |
||
1115 | GLint p; |
||
1116 | for (p = 0 ; p < MAX_LIGHTS; p++) { |
||
1117 | if (ctx->Light.Light[p].Enabled) { |
||
1118 | struct gl_light *l = &ctx->Light.Light[p]; |
||
1119 | GLfloat *fcmd = (GLfloat *)R200_DB_STATE( lit[p] ); |
||
1120 | |||
1121 | if (l->EyePosition[3] == 0.0) { |
||
1122 | COPY_3FV( &fcmd[LIT_POSITION_X], l->_VP_inf_norm ); |
||
1123 | COPY_3FV( &fcmd[LIT_DIRECTION_X], l->_h_inf_norm ); |
||
1124 | fcmd[LIT_POSITION_W] = 0; |
||
1125 | fcmd[LIT_DIRECTION_W] = 0; |
||
1126 | } else { |
||
1127 | COPY_4V( &fcmd[LIT_POSITION_X], l->_Position ); |
||
1128 | fcmd[LIT_DIRECTION_X] = -l->_NormSpotDirection[0]; |
||
1129 | fcmd[LIT_DIRECTION_Y] = -l->_NormSpotDirection[1]; |
||
1130 | fcmd[LIT_DIRECTION_Z] = -l->_NormSpotDirection[2]; |
||
1131 | fcmd[LIT_DIRECTION_W] = 0; |
||
1132 | } |
||
1133 | |||
1134 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.lit[p] ); |
||
1135 | } |
||
1136 | } |
||
1137 | } |
||
1138 | } |
||
1139 | |||
1140 | static void r200Lightfv( struct gl_context *ctx, GLenum light, |
||
1141 | GLenum pname, const GLfloat *params ) |
||
1142 | { |
||
1143 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1144 | GLint p = light - GL_LIGHT0; |
||
1145 | struct gl_light *l = &ctx->Light.Light[p]; |
||
1146 | GLfloat *fcmd = (GLfloat *)rmesa->hw.lit[p].cmd; |
||
1147 | |||
1148 | |||
1149 | switch (pname) { |
||
1150 | case GL_AMBIENT: |
||
1151 | case GL_DIFFUSE: |
||
1152 | case GL_SPECULAR: |
||
1153 | update_light_colors( ctx, p ); |
||
1154 | break; |
||
1155 | |||
1156 | case GL_SPOT_DIRECTION: |
||
1157 | /* picked up in update_light */ |
||
1158 | break; |
||
1159 | |||
1160 | case GL_POSITION: { |
||
1161 | /* positions picked up in update_light, but can do flag here */ |
||
1162 | GLuint flag = (p&1)? R200_LIGHT_1_IS_LOCAL : R200_LIGHT_0_IS_LOCAL; |
||
1163 | GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
||
1164 | |||
1165 | R200_STATECHANGE(rmesa, tcl); |
||
1166 | if (l->EyePosition[3] != 0.0F) |
||
1167 | rmesa->hw.tcl.cmd[idx] |= flag; |
||
1168 | else |
||
1169 | rmesa->hw.tcl.cmd[idx] &= ~flag; |
||
1170 | break; |
||
1171 | } |
||
1172 | |||
1173 | case GL_SPOT_EXPONENT: |
||
1174 | R200_STATECHANGE(rmesa, lit[p]); |
||
1175 | fcmd[LIT_SPOT_EXPONENT] = params[0]; |
||
1176 | break; |
||
1177 | |||
1178 | case GL_SPOT_CUTOFF: { |
||
1179 | GLuint flag = (p&1) ? R200_LIGHT_1_IS_SPOT : R200_LIGHT_0_IS_SPOT; |
||
1180 | GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
||
1181 | |||
1182 | R200_STATECHANGE(rmesa, lit[p]); |
||
1183 | fcmd[LIT_SPOT_CUTOFF] = l->_CosCutoff; |
||
1184 | |||
1185 | R200_STATECHANGE(rmesa, tcl); |
||
1186 | if (l->SpotCutoff != 180.0F) |
||
1187 | rmesa->hw.tcl.cmd[idx] |= flag; |
||
1188 | else |
||
1189 | rmesa->hw.tcl.cmd[idx] &= ~flag; |
||
1190 | |||
1191 | break; |
||
1192 | } |
||
1193 | |||
1194 | case GL_CONSTANT_ATTENUATION: |
||
1195 | R200_STATECHANGE(rmesa, lit[p]); |
||
1196 | fcmd[LIT_ATTEN_CONST] = params[0]; |
||
1197 | if ( params[0] == 0.0 ) |
||
1198 | fcmd[LIT_ATTEN_CONST_INV] = FLT_MAX; |
||
1199 | else |
||
1200 | fcmd[LIT_ATTEN_CONST_INV] = 1.0 / params[0]; |
||
1201 | break; |
||
1202 | case GL_LINEAR_ATTENUATION: |
||
1203 | R200_STATECHANGE(rmesa, lit[p]); |
||
1204 | fcmd[LIT_ATTEN_LINEAR] = params[0]; |
||
1205 | break; |
||
1206 | case GL_QUADRATIC_ATTENUATION: |
||
1207 | R200_STATECHANGE(rmesa, lit[p]); |
||
1208 | fcmd[LIT_ATTEN_QUADRATIC] = params[0]; |
||
1209 | break; |
||
1210 | default: |
||
1211 | return; |
||
1212 | } |
||
1213 | |||
1214 | /* Set RANGE_ATTEN only when needed */ |
||
1215 | switch (pname) { |
||
1216 | case GL_POSITION: |
||
1217 | case GL_CONSTANT_ATTENUATION: |
||
1218 | case GL_LINEAR_ATTENUATION: |
||
1219 | case GL_QUADRATIC_ATTENUATION: { |
||
1220 | GLuint *icmd = (GLuint *)R200_DB_STATE( tcl ); |
||
1221 | GLuint idx = TCL_PER_LIGHT_CTL_0 + p/2; |
||
1222 | GLuint atten_flag = ( p&1 ) ? R200_LIGHT_1_ENABLE_RANGE_ATTEN |
||
1223 | : R200_LIGHT_0_ENABLE_RANGE_ATTEN; |
||
1224 | GLuint atten_const_flag = ( p&1 ) ? R200_LIGHT_1_CONSTANT_RANGE_ATTEN |
||
1225 | : R200_LIGHT_0_CONSTANT_RANGE_ATTEN; |
||
1226 | |||
1227 | if ( l->EyePosition[3] == 0.0F || |
||
1228 | ( ( fcmd[LIT_ATTEN_CONST] == 0.0 || fcmd[LIT_ATTEN_CONST] == 1.0 ) && |
||
1229 | fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) ) { |
||
1230 | /* Disable attenuation */ |
||
1231 | icmd[idx] &= ~atten_flag; |
||
1232 | } else { |
||
1233 | if ( fcmd[LIT_ATTEN_QUADRATIC] == 0.0 && fcmd[LIT_ATTEN_LINEAR] == 0.0 ) { |
||
1234 | /* Enable only constant portion of attenuation calculation */ |
||
1235 | icmd[idx] |= ( atten_flag | atten_const_flag ); |
||
1236 | } else { |
||
1237 | /* Enable full attenuation calculation */ |
||
1238 | icmd[idx] &= ~atten_const_flag; |
||
1239 | icmd[idx] |= atten_flag; |
||
1240 | } |
||
1241 | } |
||
1242 | |||
1243 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.tcl ); |
||
1244 | break; |
||
1245 | } |
||
1246 | default: |
||
1247 | break; |
||
1248 | } |
||
1249 | } |
||
1250 | |||
1251 | static void r200UpdateLocalViewer ( struct gl_context *ctx ) |
||
1252 | { |
||
1253 | /* It looks like for the texgen modes GL_SPHERE_MAP, GL_NORMAL_MAP and |
||
1254 | GL_REFLECTION_MAP we need R200_LOCAL_VIEWER set (fglrx does exactly that |
||
1255 | for these and only these modes). This means specular highlights may turn out |
||
1256 | wrong in some cases when lighting is enabled but GL_LIGHT_MODEL_LOCAL_VIEWER |
||
1257 | is not set, though it seems to happen rarely and the effect seems quite |
||
1258 | subtle. May need TCL fallback to fix it completely, though I'm not sure |
||
1259 | how you'd identify the cases where the specular highlights indeed will |
||
1260 | be wrong. Don't know if fglrx does something special in that case. |
||
1261 | */ |
||
1262 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1263 | R200_STATECHANGE( rmesa, tcl ); |
||
1264 | if (ctx->Light.Model.LocalViewer || |
||
1265 | ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) |
||
1266 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LOCAL_VIEWER; |
||
1267 | else |
||
1268 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_LOCAL_VIEWER; |
||
1269 | } |
||
1270 | |||
1271 | static void r200LightModelfv( struct gl_context *ctx, GLenum pname, |
||
1272 | const GLfloat *param ) |
||
1273 | { |
||
1274 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1275 | |||
1276 | switch (pname) { |
||
1277 | case GL_LIGHT_MODEL_AMBIENT: |
||
1278 | update_global_ambient( ctx ); |
||
1279 | break; |
||
1280 | |||
1281 | case GL_LIGHT_MODEL_LOCAL_VIEWER: |
||
1282 | r200UpdateLocalViewer( ctx ); |
||
1283 | break; |
||
1284 | |||
1285 | case GL_LIGHT_MODEL_TWO_SIDE: |
||
1286 | R200_STATECHANGE( rmesa, tcl ); |
||
1287 | if (ctx->Light.Model.TwoSide) |
||
1288 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_LIGHT_TWOSIDE; |
||
1289 | else |
||
1290 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~(R200_LIGHT_TWOSIDE); |
||
1291 | if (rmesa->radeon.TclFallback) { |
||
1292 | r200ChooseRenderState( ctx ); |
||
1293 | r200ChooseVertexState( ctx ); |
||
1294 | } |
||
1295 | break; |
||
1296 | |||
1297 | case GL_LIGHT_MODEL_COLOR_CONTROL: |
||
1298 | r200UpdateSpecular(ctx); |
||
1299 | break; |
||
1300 | |||
1301 | default: |
||
1302 | break; |
||
1303 | } |
||
1304 | } |
||
1305 | |||
1306 | static void r200ShadeModel( struct gl_context *ctx, GLenum mode ) |
||
1307 | { |
||
1308 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1309 | GLuint s = rmesa->hw.set.cmd[SET_SE_CNTL]; |
||
1310 | |||
1311 | s &= ~(R200_DIFFUSE_SHADE_MASK | |
||
1312 | R200_ALPHA_SHADE_MASK | |
||
1313 | R200_SPECULAR_SHADE_MASK | |
||
1314 | R200_FOG_SHADE_MASK | |
||
1315 | R200_DISC_FOG_SHADE_MASK); |
||
1316 | |||
1317 | switch ( mode ) { |
||
1318 | case GL_FLAT: |
||
1319 | s |= (R200_DIFFUSE_SHADE_FLAT | |
||
1320 | R200_ALPHA_SHADE_FLAT | |
||
1321 | R200_SPECULAR_SHADE_FLAT | |
||
1322 | R200_FOG_SHADE_FLAT | |
||
1323 | R200_DISC_FOG_SHADE_FLAT); |
||
1324 | break; |
||
1325 | case GL_SMOOTH: |
||
1326 | s |= (R200_DIFFUSE_SHADE_GOURAUD | |
||
1327 | R200_ALPHA_SHADE_GOURAUD | |
||
1328 | R200_SPECULAR_SHADE_GOURAUD | |
||
1329 | R200_FOG_SHADE_GOURAUD | |
||
1330 | R200_DISC_FOG_SHADE_GOURAUD); |
||
1331 | break; |
||
1332 | default: |
||
1333 | return; |
||
1334 | } |
||
1335 | |||
1336 | if ( rmesa->hw.set.cmd[SET_SE_CNTL] != s ) { |
||
1337 | R200_STATECHANGE( rmesa, set ); |
||
1338 | rmesa->hw.set.cmd[SET_SE_CNTL] = s; |
||
1339 | } |
||
1340 | } |
||
1341 | |||
1342 | |||
1343 | /* ============================================================= |
||
1344 | * User clip planes |
||
1345 | */ |
||
1346 | |||
1347 | static void r200ClipPlane( struct gl_context *ctx, GLenum plane, const GLfloat *eq ) |
||
1348 | { |
||
1349 | GLint p = (GLint) plane - (GLint) GL_CLIP_PLANE0; |
||
1350 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1351 | GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
||
1352 | |||
1353 | R200_STATECHANGE( rmesa, ucp[p] ); |
||
1354 | rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
||
1355 | rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
||
1356 | rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
||
1357 | rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
||
1358 | } |
||
1359 | |||
1360 | static void r200UpdateClipPlanes( struct gl_context *ctx ) |
||
1361 | { |
||
1362 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1363 | GLuint p; |
||
1364 | |||
1365 | for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { |
||
1366 | if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { |
||
1367 | GLint *ip = (GLint *)ctx->Transform._ClipUserPlane[p]; |
||
1368 | |||
1369 | R200_STATECHANGE( rmesa, ucp[p] ); |
||
1370 | rmesa->hw.ucp[p].cmd[UCP_X] = ip[0]; |
||
1371 | rmesa->hw.ucp[p].cmd[UCP_Y] = ip[1]; |
||
1372 | rmesa->hw.ucp[p].cmd[UCP_Z] = ip[2]; |
||
1373 | rmesa->hw.ucp[p].cmd[UCP_W] = ip[3]; |
||
1374 | } |
||
1375 | } |
||
1376 | } |
||
1377 | |||
1378 | |||
1379 | /* ============================================================= |
||
1380 | * Stencil |
||
1381 | */ |
||
1382 | |||
1383 | static void |
||
1384 | r200StencilFuncSeparate( struct gl_context *ctx, GLenum face, GLenum func, |
||
1385 | GLint ref, GLuint mask ) |
||
1386 | { |
||
1387 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1388 | GLuint refmask = ((_mesa_get_stencil_ref(ctx, 0) << R200_STENCIL_REF_SHIFT) | |
||
1389 | ((ctx->Stencil.ValueMask[0] & 0xff) << R200_STENCIL_MASK_SHIFT)); |
||
1390 | |||
1391 | R200_STATECHANGE( rmesa, ctx ); |
||
1392 | R200_STATECHANGE( rmesa, msk ); |
||
1393 | |||
1394 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~R200_STENCIL_TEST_MASK; |
||
1395 | rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~(R200_STENCIL_REF_MASK| |
||
1396 | R200_STENCIL_VALUE_MASK); |
||
1397 | |||
1398 | switch ( ctx->Stencil.Function[0] ) { |
||
1399 | case GL_NEVER: |
||
1400 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEVER; |
||
1401 | break; |
||
1402 | case GL_LESS: |
||
1403 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LESS; |
||
1404 | break; |
||
1405 | case GL_EQUAL: |
||
1406 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_EQUAL; |
||
1407 | break; |
||
1408 | case GL_LEQUAL: |
||
1409 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_LEQUAL; |
||
1410 | break; |
||
1411 | case GL_GREATER: |
||
1412 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GREATER; |
||
1413 | break; |
||
1414 | case GL_NOTEQUAL: |
||
1415 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_NEQUAL; |
||
1416 | break; |
||
1417 | case GL_GEQUAL: |
||
1418 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_GEQUAL; |
||
1419 | break; |
||
1420 | case GL_ALWAYS: |
||
1421 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_TEST_ALWAYS; |
||
1422 | break; |
||
1423 | } |
||
1424 | |||
1425 | rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= refmask; |
||
1426 | } |
||
1427 | |||
1428 | static void |
||
1429 | r200StencilMaskSeparate( struct gl_context *ctx, GLenum face, GLuint mask ) |
||
1430 | { |
||
1431 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1432 | |||
1433 | R200_STATECHANGE( rmesa, msk ); |
||
1434 | rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] &= ~R200_STENCIL_WRITE_MASK; |
||
1435 | rmesa->hw.msk.cmd[MSK_RB3D_STENCILREFMASK] |= |
||
1436 | ((ctx->Stencil.WriteMask[0] & 0xff) << R200_STENCIL_WRITEMASK_SHIFT); |
||
1437 | } |
||
1438 | |||
1439 | static void |
||
1440 | r200StencilOpSeparate( struct gl_context *ctx, GLenum face, GLenum fail, |
||
1441 | GLenum zfail, GLenum zpass ) |
||
1442 | { |
||
1443 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1444 | |||
1445 | R200_STATECHANGE( rmesa, ctx ); |
||
1446 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] &= ~(R200_STENCIL_FAIL_MASK | |
||
1447 | R200_STENCIL_ZFAIL_MASK | |
||
1448 | R200_STENCIL_ZPASS_MASK); |
||
1449 | |||
1450 | switch ( ctx->Stencil.FailFunc[0] ) { |
||
1451 | case GL_KEEP: |
||
1452 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_KEEP; |
||
1453 | break; |
||
1454 | case GL_ZERO: |
||
1455 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_ZERO; |
||
1456 | break; |
||
1457 | case GL_REPLACE: |
||
1458 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_REPLACE; |
||
1459 | break; |
||
1460 | case GL_INCR: |
||
1461 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC; |
||
1462 | break; |
||
1463 | case GL_DECR: |
||
1464 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC; |
||
1465 | break; |
||
1466 | case GL_INCR_WRAP_EXT: |
||
1467 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INC_WRAP; |
||
1468 | break; |
||
1469 | case GL_DECR_WRAP_EXT: |
||
1470 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_DEC_WRAP; |
||
1471 | break; |
||
1472 | case GL_INVERT: |
||
1473 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_FAIL_INVERT; |
||
1474 | break; |
||
1475 | } |
||
1476 | |||
1477 | switch ( ctx->Stencil.ZFailFunc[0] ) { |
||
1478 | case GL_KEEP: |
||
1479 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_KEEP; |
||
1480 | break; |
||
1481 | case GL_ZERO: |
||
1482 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_ZERO; |
||
1483 | break; |
||
1484 | case GL_REPLACE: |
||
1485 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_REPLACE; |
||
1486 | break; |
||
1487 | case GL_INCR: |
||
1488 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC; |
||
1489 | break; |
||
1490 | case GL_DECR: |
||
1491 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC; |
||
1492 | break; |
||
1493 | case GL_INCR_WRAP_EXT: |
||
1494 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INC_WRAP; |
||
1495 | break; |
||
1496 | case GL_DECR_WRAP_EXT: |
||
1497 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_DEC_WRAP; |
||
1498 | break; |
||
1499 | case GL_INVERT: |
||
1500 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZFAIL_INVERT; |
||
1501 | break; |
||
1502 | } |
||
1503 | |||
1504 | switch ( ctx->Stencil.ZPassFunc[0] ) { |
||
1505 | case GL_KEEP: |
||
1506 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_KEEP; |
||
1507 | break; |
||
1508 | case GL_ZERO: |
||
1509 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_ZERO; |
||
1510 | break; |
||
1511 | case GL_REPLACE: |
||
1512 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_REPLACE; |
||
1513 | break; |
||
1514 | case GL_INCR: |
||
1515 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC; |
||
1516 | break; |
||
1517 | case GL_DECR: |
||
1518 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC; |
||
1519 | break; |
||
1520 | case GL_INCR_WRAP_EXT: |
||
1521 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INC_WRAP; |
||
1522 | break; |
||
1523 | case GL_DECR_WRAP_EXT: |
||
1524 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_DEC_WRAP; |
||
1525 | break; |
||
1526 | case GL_INVERT: |
||
1527 | rmesa->hw.ctx.cmd[CTX_RB3D_ZSTENCILCNTL] |= R200_STENCIL_ZPASS_INVERT; |
||
1528 | break; |
||
1529 | } |
||
1530 | } |
||
1531 | |||
1532 | |||
1533 | /* ============================================================= |
||
1534 | * Window position and viewport transformation |
||
1535 | */ |
||
1536 | |||
1537 | /** |
||
1538 | * Called when window size or position changes or viewport or depth range |
||
1539 | * state is changed. We update the hardware viewport state here. |
||
1540 | */ |
||
1541 | void r200UpdateWindow( struct gl_context *ctx ) |
||
1542 | { |
||
1543 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1544 | __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
||
1545 | GLfloat xoffset = 0; |
||
1546 | GLfloat yoffset = dPriv ? (GLfloat) dPriv->h : 0; |
||
1547 | const GLfloat *v = ctx->Viewport._WindowMap.m; |
||
1548 | const GLboolean render_to_fbo = (ctx->DrawBuffer ? _mesa_is_user_fbo(ctx->DrawBuffer) : 0); |
||
1549 | const GLfloat depthScale = 1.0F / ctx->DrawBuffer->_DepthMaxF; |
||
1550 | GLfloat y_scale, y_bias; |
||
1551 | |||
1552 | if (render_to_fbo) { |
||
1553 | y_scale = 1.0; |
||
1554 | y_bias = 0; |
||
1555 | } else { |
||
1556 | y_scale = -1.0; |
||
1557 | y_bias = yoffset; |
||
1558 | } |
||
1559 | |||
1560 | float_ui32_type sx = { v[MAT_SX] }; |
||
1561 | float_ui32_type tx = { v[MAT_TX] + xoffset }; |
||
1562 | float_ui32_type sy = { v[MAT_SY] * y_scale }; |
||
1563 | float_ui32_type ty = { (v[MAT_TY] * y_scale) + y_bias }; |
||
1564 | float_ui32_type sz = { v[MAT_SZ] * depthScale }; |
||
1565 | float_ui32_type tz = { v[MAT_TZ] * depthScale }; |
||
1566 | |||
1567 | R200_STATECHANGE( rmesa, vpt ); |
||
1568 | |||
1569 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_XSCALE] = sx.ui32; |
||
1570 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
||
1571 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_YSCALE] = sy.ui32; |
||
1572 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
||
1573 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZSCALE] = sz.ui32; |
||
1574 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_ZOFFSET] = tz.ui32; |
||
1575 | } |
||
1576 | |||
1577 | void r200_vtbl_update_scissor( struct gl_context *ctx ) |
||
1578 | { |
||
1579 | r200ContextPtr r200 = R200_CONTEXT(ctx); |
||
1580 | unsigned x1, y1, x2, y2; |
||
1581 | struct radeon_renderbuffer *rrb; |
||
1582 | |||
1583 | R200_SET_STATE(r200, set, SET_RE_CNTL, R200_SCISSOR_ENABLE | r200->hw.set.cmd[SET_RE_CNTL]); |
||
1584 | |||
1585 | if (r200->radeon.state.scissor.enabled) { |
||
1586 | x1 = r200->radeon.state.scissor.rect.x1; |
||
1587 | y1 = r200->radeon.state.scissor.rect.y1; |
||
1588 | x2 = r200->radeon.state.scissor.rect.x2; |
||
1589 | y2 = r200->radeon.state.scissor.rect.y2; |
||
1590 | } else { |
||
1591 | rrb = radeon_get_colorbuffer(&r200->radeon); |
||
1592 | x1 = 0; |
||
1593 | y1 = 0; |
||
1594 | x2 = rrb->base.Base.Width - 1; |
||
1595 | y2 = rrb->base.Base.Height - 1; |
||
1596 | } |
||
1597 | |||
1598 | R200_SET_STATE(r200, sci, SCI_XY_1, x1 | (y1 << 16)); |
||
1599 | R200_SET_STATE(r200, sci, SCI_XY_2, x2 | (y2 << 16)); |
||
1600 | } |
||
1601 | |||
1602 | |||
1603 | static void r200Viewport( struct gl_context *ctx, GLint x, GLint y, |
||
1604 | GLsizei width, GLsizei height ) |
||
1605 | { |
||
1606 | /* Don't pipeline viewport changes, conflict with window offset |
||
1607 | * setting below. Could apply deltas to rescue pipelined viewport |
||
1608 | * values, or keep the originals hanging around. |
||
1609 | */ |
||
1610 | r200UpdateWindow( ctx ); |
||
1611 | |||
1612 | radeon_viewport(ctx, x, y, width, height); |
||
1613 | } |
||
1614 | |||
1615 | static void r200DepthRange( struct gl_context *ctx, GLclampd nearval, |
||
1616 | GLclampd farval ) |
||
1617 | { |
||
1618 | r200UpdateWindow( ctx ); |
||
1619 | } |
||
1620 | |||
1621 | void r200UpdateViewportOffset( struct gl_context *ctx ) |
||
1622 | { |
||
1623 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1624 | __DRIdrawable *dPriv = radeon_get_drawable(&rmesa->radeon); |
||
1625 | GLfloat xoffset = (GLfloat)0; |
||
1626 | GLfloat yoffset = (GLfloat)dPriv->h; |
||
1627 | const GLfloat *v = ctx->Viewport._WindowMap.m; |
||
1628 | |||
1629 | float_ui32_type tx; |
||
1630 | float_ui32_type ty; |
||
1631 | |||
1632 | tx.f = v[MAT_TX] + xoffset; |
||
1633 | ty.f = (- v[MAT_TY]) + yoffset; |
||
1634 | |||
1635 | if ( rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] != tx.ui32 || |
||
1636 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] != ty.ui32 ) |
||
1637 | { |
||
1638 | /* Note: this should also modify whatever data the context reset |
||
1639 | * code uses... |
||
1640 | */ |
||
1641 | R200_STATECHANGE( rmesa, vpt ); |
||
1642 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_XOFFSET] = tx.ui32; |
||
1643 | rmesa->hw.vpt.cmd[VPT_SE_VPORT_YOFFSET] = ty.ui32; |
||
1644 | |||
1645 | /* update polygon stipple x/y screen offset */ |
||
1646 | { |
||
1647 | GLuint stx, sty; |
||
1648 | GLuint m = rmesa->hw.msc.cmd[MSC_RE_MISC]; |
||
1649 | |||
1650 | m &= ~(R200_STIPPLE_X_OFFSET_MASK | |
||
1651 | R200_STIPPLE_Y_OFFSET_MASK); |
||
1652 | |||
1653 | /* add magic offsets, then invert */ |
||
1654 | stx = 31 - ((-1) & R200_STIPPLE_COORD_MASK); |
||
1655 | sty = 31 - ((dPriv->h - 1) |
||
1656 | & R200_STIPPLE_COORD_MASK); |
||
1657 | |||
1658 | m |= ((stx << R200_STIPPLE_X_OFFSET_SHIFT) | |
||
1659 | (sty << R200_STIPPLE_Y_OFFSET_SHIFT)); |
||
1660 | |||
1661 | if ( rmesa->hw.msc.cmd[MSC_RE_MISC] != m ) { |
||
1662 | R200_STATECHANGE( rmesa, msc ); |
||
1663 | rmesa->hw.msc.cmd[MSC_RE_MISC] = m; |
||
1664 | } |
||
1665 | } |
||
1666 | } |
||
1667 | |||
1668 | radeonUpdateScissor( ctx ); |
||
1669 | } |
||
1670 | |||
1671 | |||
1672 | |||
1673 | /* ============================================================= |
||
1674 | * Miscellaneous |
||
1675 | */ |
||
1676 | |||
1677 | static void r200RenderMode( struct gl_context *ctx, GLenum mode ) |
||
1678 | { |
||
1679 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1680 | FALLBACK( rmesa, R200_FALLBACK_RENDER_MODE, (mode != GL_RENDER) ); |
||
1681 | } |
||
1682 | |||
1683 | |||
1684 | static GLuint r200_rop_tab[] = { |
||
1685 | R200_ROP_CLEAR, |
||
1686 | R200_ROP_AND, |
||
1687 | R200_ROP_AND_REVERSE, |
||
1688 | R200_ROP_COPY, |
||
1689 | R200_ROP_AND_INVERTED, |
||
1690 | R200_ROP_NOOP, |
||
1691 | R200_ROP_XOR, |
||
1692 | R200_ROP_OR, |
||
1693 | R200_ROP_NOR, |
||
1694 | R200_ROP_EQUIV, |
||
1695 | R200_ROP_INVERT, |
||
1696 | R200_ROP_OR_REVERSE, |
||
1697 | R200_ROP_COPY_INVERTED, |
||
1698 | R200_ROP_OR_INVERTED, |
||
1699 | R200_ROP_NAND, |
||
1700 | R200_ROP_SET, |
||
1701 | }; |
||
1702 | |||
1703 | static void r200LogicOpCode( struct gl_context *ctx, GLenum opcode ) |
||
1704 | { |
||
1705 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1706 | GLuint rop = (GLuint)opcode - GL_CLEAR; |
||
1707 | |||
1708 | ASSERT( rop < 16 ); |
||
1709 | |||
1710 | R200_STATECHANGE( rmesa, msk ); |
||
1711 | rmesa->hw.msk.cmd[MSK_RB3D_ROPCNTL] = r200_rop_tab[rop]; |
||
1712 | } |
||
1713 | |||
1714 | /* ============================================================= |
||
1715 | * State enable/disable |
||
1716 | */ |
||
1717 | |||
1718 | static void r200Enable( struct gl_context *ctx, GLenum cap, GLboolean state ) |
||
1719 | { |
||
1720 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
1721 | GLuint p, flag; |
||
1722 | |||
1723 | if ( R200_DEBUG & RADEON_STATE ) |
||
1724 | fprintf( stderr, "%s( %s = %s )\n", __FUNCTION__, |
||
1725 | _mesa_lookup_enum_by_nr( cap ), |
||
1726 | state ? "GL_TRUE" : "GL_FALSE" ); |
||
1727 | |||
1728 | switch ( cap ) { |
||
1729 | /* Fast track this one... |
||
1730 | */ |
||
1731 | case GL_TEXTURE_1D: |
||
1732 | case GL_TEXTURE_2D: |
||
1733 | case GL_TEXTURE_3D: |
||
1734 | break; |
||
1735 | |||
1736 | case GL_ALPHA_TEST: |
||
1737 | R200_STATECHANGE( rmesa, ctx ); |
||
1738 | if (state) { |
||
1739 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ALPHA_TEST_ENABLE; |
||
1740 | } else { |
||
1741 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ALPHA_TEST_ENABLE; |
||
1742 | } |
||
1743 | break; |
||
1744 | |||
1745 | case GL_BLEND: |
||
1746 | case GL_COLOR_LOGIC_OP: |
||
1747 | r200_set_blend_state( ctx ); |
||
1748 | break; |
||
1749 | |||
1750 | case GL_CLIP_PLANE0: |
||
1751 | case GL_CLIP_PLANE1: |
||
1752 | case GL_CLIP_PLANE2: |
||
1753 | case GL_CLIP_PLANE3: |
||
1754 | case GL_CLIP_PLANE4: |
||
1755 | case GL_CLIP_PLANE5: |
||
1756 | p = cap-GL_CLIP_PLANE0; |
||
1757 | R200_STATECHANGE( rmesa, tcl ); |
||
1758 | if (state) { |
||
1759 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0< |
||
1760 | r200ClipPlane( ctx, cap, NULL ); |
||
1761 | } |
||
1762 | else { |
||
1763 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0< |
||
1764 | } |
||
1765 | break; |
||
1766 | |||
1767 | case GL_COLOR_MATERIAL: |
||
1768 | r200ColorMaterial( ctx, 0, 0 ); |
||
1769 | r200UpdateMaterial( ctx ); |
||
1770 | break; |
||
1771 | |||
1772 | case GL_CULL_FACE: |
||
1773 | r200CullFace( ctx, 0 ); |
||
1774 | break; |
||
1775 | |||
1776 | case GL_DEPTH_TEST: |
||
1777 | R200_STATECHANGE(rmesa, ctx ); |
||
1778 | if ( state ) { |
||
1779 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_Z_ENABLE; |
||
1780 | } else { |
||
1781 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_Z_ENABLE; |
||
1782 | } |
||
1783 | break; |
||
1784 | |||
1785 | case GL_DITHER: |
||
1786 | R200_STATECHANGE(rmesa, ctx ); |
||
1787 | if ( state ) { |
||
1788 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_DITHER_ENABLE; |
||
1789 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~rmesa->radeon.state.color.roundEnable; |
||
1790 | } else { |
||
1791 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_DITHER_ENABLE; |
||
1792 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= rmesa->radeon.state.color.roundEnable; |
||
1793 | } |
||
1794 | break; |
||
1795 | |||
1796 | case GL_FOG: |
||
1797 | R200_STATECHANGE(rmesa, ctx ); |
||
1798 | if ( state ) { |
||
1799 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_FOG_ENABLE; |
||
1800 | r200Fogfv( ctx, GL_FOG_MODE, NULL ); |
||
1801 | } else { |
||
1802 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_FOG_ENABLE; |
||
1803 | R200_STATECHANGE(rmesa, tcl); |
||
1804 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~R200_TCL_FOG_MASK; |
||
1805 | } |
||
1806 | r200UpdateSpecular( ctx ); /* for PK_SPEC */ |
||
1807 | if (rmesa->radeon.TclFallback) |
||
1808 | r200ChooseVertexState( ctx ); |
||
1809 | _mesa_allow_light_in_model( ctx, !state ); |
||
1810 | break; |
||
1811 | |||
1812 | case GL_LIGHT0: |
||
1813 | case GL_LIGHT1: |
||
1814 | case GL_LIGHT2: |
||
1815 | case GL_LIGHT3: |
||
1816 | case GL_LIGHT4: |
||
1817 | case GL_LIGHT5: |
||
1818 | case GL_LIGHT6: |
||
1819 | case GL_LIGHT7: |
||
1820 | R200_STATECHANGE(rmesa, tcl); |
||
1821 | p = cap - GL_LIGHT0; |
||
1822 | if (p&1) |
||
1823 | flag = (R200_LIGHT_1_ENABLE | |
||
1824 | R200_LIGHT_1_ENABLE_AMBIENT | |
||
1825 | R200_LIGHT_1_ENABLE_SPECULAR); |
||
1826 | else |
||
1827 | flag = (R200_LIGHT_0_ENABLE | |
||
1828 | R200_LIGHT_0_ENABLE_AMBIENT | |
||
1829 | R200_LIGHT_0_ENABLE_SPECULAR); |
||
1830 | |||
1831 | if (state) |
||
1832 | rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] |= flag; |
||
1833 | else |
||
1834 | rmesa->hw.tcl.cmd[p/2 + TCL_PER_LIGHT_CTL_0] &= ~flag; |
||
1835 | |||
1836 | /* |
||
1837 | */ |
||
1838 | update_light_colors( ctx, p ); |
||
1839 | break; |
||
1840 | |||
1841 | case GL_LIGHTING: |
||
1842 | r200UpdateSpecular(ctx); |
||
1843 | /* for reflection map fixup - might set recheck_texgen for all units too */ |
||
1844 | rmesa->radeon.NewGLState |= _NEW_TEXTURE; |
||
1845 | break; |
||
1846 | |||
1847 | case GL_LINE_SMOOTH: |
||
1848 | R200_STATECHANGE( rmesa, ctx ); |
||
1849 | if ( state ) { |
||
1850 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_LINE; |
||
1851 | } else { |
||
1852 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_LINE; |
||
1853 | } |
||
1854 | break; |
||
1855 | |||
1856 | case GL_LINE_STIPPLE: |
||
1857 | R200_STATECHANGE( rmesa, set ); |
||
1858 | if ( state ) { |
||
1859 | rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_PATTERN_ENABLE; |
||
1860 | } else { |
||
1861 | rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_PATTERN_ENABLE; |
||
1862 | } |
||
1863 | break; |
||
1864 | |||
1865 | case GL_NORMALIZE: |
||
1866 | R200_STATECHANGE( rmesa, tcl ); |
||
1867 | if ( state ) { |
||
1868 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_NORMALIZE_NORMALS; |
||
1869 | } else { |
||
1870 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_NORMALIZE_NORMALS; |
||
1871 | } |
||
1872 | break; |
||
1873 | |||
1874 | /* Pointsize registers on r200 only work for point sprites, and point smooth |
||
1875 | * doesn't work for point sprites (and isn't needed for 1.0 sized aa points). |
||
1876 | * In any case, setting pointmin == pointsizemax == 1.0 for aa points |
||
1877 | * is enough to satisfy conform. |
||
1878 | */ |
||
1879 | case GL_POINT_SMOOTH: |
||
1880 | break; |
||
1881 | |||
1882 | /* These don't really do anything, as we don't use the 3vtx |
||
1883 | * primitives yet. |
||
1884 | */ |
||
1885 | #if 0 |
||
1886 | case GL_POLYGON_OFFSET_POINT: |
||
1887 | R200_STATECHANGE( rmesa, set ); |
||
1888 | if ( state ) { |
||
1889 | rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_POINT; |
||
1890 | } else { |
||
1891 | rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_POINT; |
||
1892 | } |
||
1893 | break; |
||
1894 | |||
1895 | case GL_POLYGON_OFFSET_LINE: |
||
1896 | R200_STATECHANGE( rmesa, set ); |
||
1897 | if ( state ) { |
||
1898 | rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_LINE; |
||
1899 | } else { |
||
1900 | rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_LINE; |
||
1901 | } |
||
1902 | break; |
||
1903 | #endif |
||
1904 | |||
1905 | case GL_POINT_SPRITE_ARB: |
||
1906 | R200_STATECHANGE( rmesa, spr ); |
||
1907 | if ( state ) { |
||
1908 | int i; |
||
1909 | for (i = 0; i < 6; i++) { |
||
1910 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] |= |
||
1911 | ctx->Point.CoordReplace[i] << (R200_PS_GEN_TEX_0_SHIFT + i); |
||
1912 | } |
||
1913 | } else { |
||
1914 | rmesa->hw.spr.cmd[SPR_POINT_SPRITE_CNTL] &= ~R200_PS_GEN_TEX_MASK; |
||
1915 | } |
||
1916 | break; |
||
1917 | |||
1918 | case GL_POLYGON_OFFSET_FILL: |
||
1919 | R200_STATECHANGE( rmesa, set ); |
||
1920 | if ( state ) { |
||
1921 | rmesa->hw.set.cmd[SET_SE_CNTL] |= R200_ZBIAS_ENABLE_TRI; |
||
1922 | } else { |
||
1923 | rmesa->hw.set.cmd[SET_SE_CNTL] &= ~R200_ZBIAS_ENABLE_TRI; |
||
1924 | } |
||
1925 | break; |
||
1926 | |||
1927 | case GL_POLYGON_SMOOTH: |
||
1928 | R200_STATECHANGE( rmesa, ctx ); |
||
1929 | if ( state ) { |
||
1930 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] |= R200_ANTI_ALIAS_POLY; |
||
1931 | } else { |
||
1932 | rmesa->hw.ctx.cmd[CTX_PP_CNTL] &= ~R200_ANTI_ALIAS_POLY; |
||
1933 | } |
||
1934 | break; |
||
1935 | |||
1936 | case GL_POLYGON_STIPPLE: |
||
1937 | R200_STATECHANGE(rmesa, set ); |
||
1938 | if ( state ) { |
||
1939 | rmesa->hw.set.cmd[SET_RE_CNTL] |= R200_STIPPLE_ENABLE; |
||
1940 | } else { |
||
1941 | rmesa->hw.set.cmd[SET_RE_CNTL] &= ~R200_STIPPLE_ENABLE; |
||
1942 | } |
||
1943 | break; |
||
1944 | |||
1945 | case GL_RESCALE_NORMAL_EXT: { |
||
1946 | GLboolean tmp = ctx->_NeedEyeCoords ? state : !state; |
||
1947 | R200_STATECHANGE( rmesa, tcl ); |
||
1948 | if ( tmp ) { |
||
1949 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; |
||
1950 | } else { |
||
1951 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; |
||
1952 | } |
||
1953 | break; |
||
1954 | } |
||
1955 | |||
1956 | case GL_SCISSOR_TEST: |
||
1957 | radeon_firevertices(&rmesa->radeon); |
||
1958 | rmesa->radeon.state.scissor.enabled = state; |
||
1959 | radeonUpdateScissor( ctx ); |
||
1960 | break; |
||
1961 | |||
1962 | case GL_STENCIL_TEST: |
||
1963 | { |
||
1964 | GLboolean hw_stencil = GL_FALSE; |
||
1965 | if (ctx->DrawBuffer) { |
||
1966 | struct radeon_renderbuffer *rrbStencil |
||
1967 | = radeon_get_renderbuffer(ctx->DrawBuffer, BUFFER_STENCIL); |
||
1968 | hw_stencil = (rrbStencil && rrbStencil->bo); |
||
1969 | } |
||
1970 | |||
1971 | if (hw_stencil) { |
||
1972 | R200_STATECHANGE( rmesa, ctx ); |
||
1973 | if ( state ) { |
||
1974 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] |= R200_STENCIL_ENABLE; |
||
1975 | } else { |
||
1976 | rmesa->hw.ctx.cmd[CTX_RB3D_CNTL] &= ~R200_STENCIL_ENABLE; |
||
1977 | } |
||
1978 | } else { |
||
1979 | FALLBACK( rmesa, R200_FALLBACK_STENCIL, state ); |
||
1980 | } |
||
1981 | } |
||
1982 | break; |
||
1983 | |||
1984 | case GL_TEXTURE_GEN_Q: |
||
1985 | case GL_TEXTURE_GEN_R: |
||
1986 | case GL_TEXTURE_GEN_S: |
||
1987 | case GL_TEXTURE_GEN_T: |
||
1988 | /* Picked up in r200UpdateTextureState. |
||
1989 | */ |
||
1990 | rmesa->recheck_texgen[ctx->Texture.CurrentUnit] = GL_TRUE; |
||
1991 | break; |
||
1992 | |||
1993 | case GL_COLOR_SUM_EXT: |
||
1994 | r200UpdateSpecular ( ctx ); |
||
1995 | break; |
||
1996 | |||
1997 | case GL_VERTEX_PROGRAM_ARB: |
||
1998 | if (!state) { |
||
1999 | GLuint i; |
||
2000 | rmesa->curr_vp_hw = NULL; |
||
2001 | R200_STATECHANGE( rmesa, vap ); |
||
2002 | rmesa->hw.vap.cmd[VAP_SE_VAP_CNTL] &= ~R200_VAP_PROG_VTX_SHADER_ENABLE; |
||
2003 | /* mark all tcl atoms (tcl vector state got overwritten) dirty |
||
2004 | not sure about tcl scalar state - we need at least grd |
||
2005 | with vert progs too. |
||
2006 | ucp looks like it doesn't get overwritten (may even work |
||
2007 | with vp for pos-invariant progs if we're lucky) */ |
||
2008 | R200_STATECHANGE( rmesa, mtl[0] ); |
||
2009 | R200_STATECHANGE( rmesa, mtl[1] ); |
||
2010 | R200_STATECHANGE( rmesa, fog ); |
||
2011 | R200_STATECHANGE( rmesa, glt ); |
||
2012 | R200_STATECHANGE( rmesa, eye ); |
||
2013 | for (i = R200_MTX_MV; i <= R200_MTX_TEX5; i++) { |
||
2014 | R200_STATECHANGE( rmesa, mat[i] ); |
||
2015 | } |
||
2016 | for (i = 0 ; i < 8; i++) { |
||
2017 | R200_STATECHANGE( rmesa, lit[i] ); |
||
2018 | } |
||
2019 | R200_STATECHANGE( rmesa, tcl ); |
||
2020 | for (i = 0; i <= ctx->Const.MaxClipPlanes; i++) { |
||
2021 | if (ctx->Transform.ClipPlanesEnabled & (1 << i)) { |
||
2022 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] |= (R200_UCP_ENABLE_0 << i); |
||
2023 | } |
||
2024 | /* else { |
||
2025 | rmesa->hw.tcl.cmd[TCL_UCP_VERT_BLEND_CTL] &= ~(R200_UCP_ENABLE_0 << i); |
||
2026 | }*/ |
||
2027 | } |
||
2028 | /* ugly. Need to call everything which might change compsel. */ |
||
2029 | r200UpdateSpecular( ctx ); |
||
2030 | #if 0 |
||
2031 | /* shouldn't be necessary, as it's picked up anyway in r200ValidateState (_NEW_PROGRAM), |
||
2032 | but without it doom3 locks up at always the same places. Why? */ |
||
2033 | /* FIXME: This can (and should) be replaced by a call to the TCL_STATE_FLUSH reg before |
||
2034 | accessing VAP_SE_VAP_CNTL. Requires drm changes (done). Remove after some time... */ |
||
2035 | r200UpdateTextureState( ctx ); |
||
2036 | /* if we call r200UpdateTextureState we need the code below because we are calling it with |
||
2037 | non-current derived enabled values which may revert the state atoms for frag progs even when |
||
2038 | they already got disabled... ugh |
||
2039 | Should really figure out why we need to call r200UpdateTextureState in the first place */ |
||
2040 | GLuint unit; |
||
2041 | for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { |
||
2042 | R200_STATECHANGE( rmesa, pix[unit] ); |
||
2043 | R200_STATECHANGE( rmesa, tex[unit] ); |
||
2044 | rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= |
||
2045 | ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
||
2046 | rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; |
||
2047 | /* need to guard this with drmSupportsFragmentShader? Should never get here if |
||
2048 | we don't announce ATI_fs, right? */ |
||
2049 | rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; |
||
2050 | } |
||
2051 | R200_STATECHANGE( rmesa, cst ); |
||
2052 | R200_STATECHANGE( rmesa, tf ); |
||
2053 | rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; |
||
2054 | #endif |
||
2055 | } |
||
2056 | else { |
||
2057 | /* picked up later */ |
||
2058 | } |
||
2059 | /* call functions which change hw state based on ARB_vp enabled or not. */ |
||
2060 | r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); |
||
2061 | r200Fogfv( ctx, GL_FOG_COORD_SRC, NULL ); |
||
2062 | break; |
||
2063 | |||
2064 | case GL_VERTEX_PROGRAM_POINT_SIZE_ARB: |
||
2065 | r200PointParameter( ctx, GL_POINT_DISTANCE_ATTENUATION, NULL ); |
||
2066 | break; |
||
2067 | |||
2068 | case GL_FRAGMENT_SHADER_ATI: |
||
2069 | if ( !state ) { |
||
2070 | /* restore normal tex env colors and make sure tex env combine will get updated |
||
2071 | mark env atoms dirty (as their data was overwritten by afs even |
||
2072 | if they didn't change) and restore tex coord routing */ |
||
2073 | GLuint unit; |
||
2074 | for (unit = 0; unit < R200_MAX_TEXTURE_UNITS; unit++) { |
||
2075 | R200_STATECHANGE( rmesa, pix[unit] ); |
||
2076 | R200_STATECHANGE( rmesa, tex[unit] ); |
||
2077 | rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] &= |
||
2078 | ~(R200_TXFORMAT_ST_ROUTE_MASK | R200_TXFORMAT_LOOKUP_DISABLE); |
||
2079 | rmesa->hw.tex[unit].cmd[TEX_PP_TXFORMAT] |= unit << R200_TXFORMAT_ST_ROUTE_SHIFT; |
||
2080 | rmesa->hw.tex[unit].cmd[TEX_PP_TXMULTI_CTL] = 0; |
||
2081 | } |
||
2082 | R200_STATECHANGE( rmesa, cst ); |
||
2083 | R200_STATECHANGE( rmesa, tf ); |
||
2084 | rmesa->hw.cst.cmd[CST_PP_CNTL_X] = 0; |
||
2085 | } |
||
2086 | else { |
||
2087 | /* need to mark this dirty as pix/tf atoms have overwritten the data |
||
2088 | even if the data in the atoms didn't change */ |
||
2089 | R200_STATECHANGE( rmesa, atf ); |
||
2090 | R200_STATECHANGE( rmesa, afs[1] ); |
||
2091 | /* everything else picked up in r200UpdateTextureState hopefully */ |
||
2092 | } |
||
2093 | break; |
||
2094 | default: |
||
2095 | return; |
||
2096 | } |
||
2097 | } |
||
2098 | |||
2099 | |||
2100 | void r200LightingSpaceChange( struct gl_context *ctx ) |
||
2101 | { |
||
2102 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
2103 | GLboolean tmp; |
||
2104 | |||
2105 | if (R200_DEBUG & RADEON_STATE) |
||
2106 | fprintf(stderr, "%s %d BEFORE %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
||
2107 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); |
||
2108 | |||
2109 | if (ctx->_NeedEyeCoords) |
||
2110 | tmp = ctx->Transform.RescaleNormals; |
||
2111 | else |
||
2112 | tmp = !ctx->Transform.RescaleNormals; |
||
2113 | |||
2114 | R200_STATECHANGE( rmesa, tcl ); |
||
2115 | if ( tmp ) { |
||
2116 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] |= R200_RESCALE_NORMALS; |
||
2117 | } else { |
||
2118 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0] &= ~R200_RESCALE_NORMALS; |
||
2119 | } |
||
2120 | |||
2121 | if (R200_DEBUG & RADEON_STATE) |
||
2122 | fprintf(stderr, "%s %d AFTER %x\n", __FUNCTION__, ctx->_NeedEyeCoords, |
||
2123 | rmesa->hw.tcl.cmd[TCL_LIGHT_MODEL_CTL_0]); |
||
2124 | } |
||
2125 | |||
2126 | /* ============================================================= |
||
2127 | * Deferred state management - matrices, textures, other? |
||
2128 | */ |
||
2129 | |||
2130 | |||
2131 | |||
2132 | |||
2133 | static void upload_matrix( r200ContextPtr rmesa, GLfloat *src, int idx ) |
||
2134 | { |
||
2135 | float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; |
||
2136 | int i; |
||
2137 | |||
2138 | |||
2139 | for (i = 0 ; i < 4 ; i++) { |
||
2140 | *dest++ = src[i]; |
||
2141 | *dest++ = src[i+4]; |
||
2142 | *dest++ = src[i+8]; |
||
2143 | *dest++ = src[i+12]; |
||
2144 | } |
||
2145 | |||
2146 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
||
2147 | } |
||
2148 | |||
2149 | static void upload_matrix_t( r200ContextPtr rmesa, const GLfloat *src, int idx ) |
||
2150 | { |
||
2151 | float *dest = ((float *)R200_DB_STATE( mat[idx] ))+MAT_ELT_0; |
||
2152 | memcpy(dest, src, 16*sizeof(float)); |
||
2153 | R200_DB_STATECHANGE( rmesa, &rmesa->hw.mat[idx] ); |
||
2154 | } |
||
2155 | |||
2156 | |||
2157 | static void update_texturematrix( struct gl_context *ctx ) |
||
2158 | { |
||
2159 | r200ContextPtr rmesa = R200_CONTEXT( ctx ); |
||
2160 | GLuint tpc = rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]; |
||
2161 | GLuint compsel = rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]; |
||
2162 | int unit; |
||
2163 | |||
2164 | if (R200_DEBUG & RADEON_STATE) |
||
2165 | fprintf(stderr, "%s before COMPSEL: %x\n", __FUNCTION__, |
||
2166 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]); |
||
2167 | |||
2168 | rmesa->TexMatEnabled = 0; |
||
2169 | rmesa->TexMatCompSel = 0; |
||
2170 | |||
2171 | for (unit = 0 ; unit < ctx->Const.MaxTextureUnits; unit++) { |
||
2172 | if (!ctx->Texture.Unit[unit]._ReallyEnabled) |
||
2173 | continue; |
||
2174 | |||
2175 | if (ctx->TextureMatrixStack[unit].Top->type != MATRIX_IDENTITY) { |
||
2176 | rmesa->TexMatEnabled |= (R200_TEXGEN_TEXMAT_0_ENABLE| |
||
2177 | R200_TEXMAT_0_ENABLE) << unit; |
||
2178 | |||
2179 | rmesa->TexMatCompSel |= R200_OUTPUT_TEX_0 << unit; |
||
2180 | |||
2181 | if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { |
||
2182 | /* Need to preconcatenate any active texgen |
||
2183 | * obj/eyeplane matrices: |
||
2184 | */ |
||
2185 | _math_matrix_mul_matrix( &rmesa->tmpmat, |
||
2186 | ctx->TextureMatrixStack[unit].Top, |
||
2187 | &rmesa->TexGenMatrix[unit] ); |
||
2188 | upload_matrix( rmesa, rmesa->tmpmat.m, R200_MTX_TEX0+unit ); |
||
2189 | } |
||
2190 | else { |
||
2191 | upload_matrix( rmesa, ctx->TextureMatrixStack[unit].Top->m, |
||
2192 | R200_MTX_TEX0+unit ); |
||
2193 | } |
||
2194 | } |
||
2195 | else if (rmesa->TexGenEnabled & (R200_TEXMAT_0_ENABLE << unit)) { |
||
2196 | upload_matrix( rmesa, rmesa->TexGenMatrix[unit].m, |
||
2197 | R200_MTX_TEX0+unit ); |
||
2198 | } |
||
2199 | } |
||
2200 | |||
2201 | tpc = (rmesa->TexMatEnabled | rmesa->TexGenEnabled); |
||
2202 | if (tpc != rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0]) { |
||
2203 | R200_STATECHANGE(rmesa, tcg); |
||
2204 | rmesa->hw.tcg.cmd[TCG_TEX_PROC_CTL_0] = tpc; |
||
2205 | } |
||
2206 | |||
2207 | compsel &= ~R200_OUTPUT_TEX_MASK; |
||
2208 | compsel |= rmesa->TexMatCompSel | rmesa->TexGenCompSel; |
||
2209 | if (compsel != rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL]) { |
||
2210 | R200_STATECHANGE(rmesa, vtx); |
||
2211 | rmesa->hw.vtx.cmd[VTX_TCL_OUTPUT_COMPSEL] = compsel; |
||
2212 | } |
||
2213 | } |
||
2214 | |||
2215 | static GLboolean r200ValidateBuffers(struct gl_context *ctx) |
||
2216 | { |
||
2217 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
2218 | struct radeon_renderbuffer *rrb; |
||
2219 | struct radeon_dma_bo *dma_bo; |
||
2220 | int i, ret; |
||
2221 | |||
2222 | if (RADEON_DEBUG & RADEON_IOCTL) |
||
2223 | fprintf(stderr, "%s\n", __FUNCTION__); |
||
2224 | radeon_cs_space_reset_bos(rmesa->radeon.cmdbuf.cs); |
||
2225 | |||
2226 | rrb = radeon_get_colorbuffer(&rmesa->radeon); |
||
2227 | /* color buffer */ |
||
2228 | if (rrb && rrb->bo) { |
||
2229 | radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
||
2230 | 0, RADEON_GEM_DOMAIN_VRAM); |
||
2231 | } |
||
2232 | |||
2233 | /* depth buffer */ |
||
2234 | rrb = radeon_get_depthbuffer(&rmesa->radeon); |
||
2235 | /* color buffer */ |
||
2236 | if (rrb && rrb->bo) { |
||
2237 | radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, rrb->bo, |
||
2238 | 0, RADEON_GEM_DOMAIN_VRAM); |
||
2239 | } |
||
2240 | |||
2241 | for (i = 0; i < ctx->Const.FragmentProgram.MaxTextureImageUnits; ++i) { |
||
2242 | radeonTexObj *t; |
||
2243 | |||
2244 | if (!ctx->Texture.Unit[i]._ReallyEnabled) |
||
2245 | continue; |
||
2246 | |||
2247 | t = radeon_tex_obj(ctx->Texture.Unit[i]._Current); |
||
2248 | if (t->image_override && t->bo) |
||
2249 | radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->bo, |
||
2250 | RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
||
2251 | else if (t->mt->bo) |
||
2252 | radeon_cs_space_add_persistent_bo(rmesa->radeon.cmdbuf.cs, t->mt->bo, |
||
2253 | RADEON_GEM_DOMAIN_GTT | RADEON_GEM_DOMAIN_VRAM, 0); |
||
2254 | } |
||
2255 | |||
2256 | dma_bo = first_elem(&rmesa->radeon.dma.reserved); |
||
2257 | { |
||
2258 | ret = radeon_cs_space_check_with_bo(rmesa->radeon.cmdbuf.cs, dma_bo->bo, RADEON_GEM_DOMAIN_GTT, 0); |
||
2259 | if (ret) |
||
2260 | return GL_FALSE; |
||
2261 | } |
||
2262 | return GL_TRUE; |
||
2263 | } |
||
2264 | |||
2265 | GLboolean r200ValidateState( struct gl_context *ctx ) |
||
2266 | { |
||
2267 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
2268 | GLuint new_state = rmesa->radeon.NewGLState; |
||
2269 | |||
2270 | if (new_state & _NEW_BUFFERS) { |
||
2271 | _mesa_update_framebuffer(ctx); |
||
2272 | /* this updates the DrawBuffer's Width/Height if it's a FBO */ |
||
2273 | _mesa_update_draw_buffer_bounds(ctx); |
||
2274 | |||
2275 | R200_STATECHANGE(rmesa, ctx); |
||
2276 | } |
||
2277 | |||
2278 | if (new_state & (_NEW_TEXTURE | _NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS)) { |
||
2279 | r200UpdateTextureState( ctx ); |
||
2280 | new_state |= rmesa->radeon.NewGLState; /* may add TEXTURE_MATRIX */ |
||
2281 | r200UpdateLocalViewer( ctx ); |
||
2282 | } |
||
2283 | |||
2284 | /* we need to do a space check here */ |
||
2285 | if (!r200ValidateBuffers(ctx)) |
||
2286 | return GL_FALSE; |
||
2287 | |||
2288 | /* FIXME: don't really need most of these when vertex progs are enabled */ |
||
2289 | |||
2290 | /* Need an event driven matrix update? |
||
2291 | */ |
||
2292 | if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) |
||
2293 | upload_matrix( rmesa, ctx->_ModelProjectMatrix.m, R200_MTX_MVP ); |
||
2294 | |||
2295 | /* Need these for lighting (shouldn't upload otherwise) |
||
2296 | */ |
||
2297 | if (new_state & (_NEW_MODELVIEW)) { |
||
2298 | upload_matrix( rmesa, ctx->ModelviewMatrixStack.Top->m, R200_MTX_MV ); |
||
2299 | upload_matrix_t( rmesa, ctx->ModelviewMatrixStack.Top->inv, R200_MTX_IMV ); |
||
2300 | } |
||
2301 | |||
2302 | /* Does this need to be triggered on eg. modelview for |
||
2303 | * texgen-derived objplane/eyeplane matrices? |
||
2304 | */ |
||
2305 | if (new_state & (_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) { |
||
2306 | update_texturematrix( ctx ); |
||
2307 | } |
||
2308 | |||
2309 | if (new_state & (_NEW_LIGHT|_NEW_MODELVIEW|_MESA_NEW_NEED_EYE_COORDS)) { |
||
2310 | update_light( ctx ); |
||
2311 | } |
||
2312 | |||
2313 | /* emit all active clip planes if projection matrix changes. |
||
2314 | */ |
||
2315 | if (new_state & (_NEW_PROJECTION)) { |
||
2316 | if (ctx->Transform.ClipPlanesEnabled) |
||
2317 | r200UpdateClipPlanes( ctx ); |
||
2318 | } |
||
2319 | |||
2320 | if (new_state & (_NEW_PROGRAM| |
||
2321 | _NEW_PROGRAM_CONSTANTS | |
||
2322 | /* need to test for pretty much anything due to possible parameter bindings */ |
||
2323 | _NEW_MODELVIEW|_NEW_PROJECTION|_NEW_TRANSFORM| |
||
2324 | _NEW_LIGHT|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX| |
||
2325 | _NEW_FOG|_NEW_POINT|_NEW_TRACK_MATRIX)) { |
||
2326 | if (ctx->VertexProgram._Enabled) { |
||
2327 | r200SetupVertexProg( ctx ); |
||
2328 | } |
||
2329 | else TCL_FALLBACK(ctx, R200_TCL_FALLBACK_VERTEX_PROGRAM, 0); |
||
2330 | } |
||
2331 | |||
2332 | rmesa->radeon.NewGLState = 0; |
||
2333 | return GL_TRUE; |
||
2334 | } |
||
2335 | |||
2336 | |||
2337 | static void r200InvalidateState( struct gl_context *ctx, GLuint new_state ) |
||
2338 | { |
||
2339 | _swrast_InvalidateState( ctx, new_state ); |
||
2340 | _swsetup_InvalidateState( ctx, new_state ); |
||
2341 | _vbo_InvalidateState( ctx, new_state ); |
||
2342 | _tnl_InvalidateState( ctx, new_state ); |
||
2343 | _ae_invalidate_state( ctx, new_state ); |
||
2344 | R200_CONTEXT(ctx)->radeon.NewGLState |= new_state; |
||
2345 | } |
||
2346 | |||
2347 | /* A hack. The r200 can actually cope just fine with materials |
||
2348 | * between begin/ends, so fix this. |
||
2349 | * Should map to inputs just like the generic vertex arrays for vertex progs. |
||
2350 | * In theory there could still be too many and we'd still need a fallback. |
||
2351 | */ |
||
2352 | static GLboolean check_material( struct gl_context *ctx ) |
||
2353 | { |
||
2354 | TNLcontext *tnl = TNL_CONTEXT(ctx); |
||
2355 | GLint i; |
||
2356 | |||
2357 | for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; |
||
2358 | i < _TNL_ATTRIB_MAT_BACK_INDEXES; |
||
2359 | i++) |
||
2360 | if (tnl->vb.AttribPtr[i] && |
||
2361 | tnl->vb.AttribPtr[i]->stride) |
||
2362 | return GL_TRUE; |
||
2363 | |||
2364 | return GL_FALSE; |
||
2365 | } |
||
2366 | |||
2367 | static void r200WrapRunPipeline( struct gl_context *ctx ) |
||
2368 | { |
||
2369 | r200ContextPtr rmesa = R200_CONTEXT(ctx); |
||
2370 | GLboolean has_material; |
||
2371 | |||
2372 | if (0) |
||
2373 | fprintf(stderr, "%s, newstate: %x\n", __FUNCTION__, rmesa->radeon.NewGLState); |
||
2374 | |||
2375 | /* Validate state: |
||
2376 | */ |
||
2377 | if (rmesa->radeon.NewGLState) |
||
2378 | if (!r200ValidateState( ctx )) |
||
2379 | FALLBACK(rmesa, RADEON_FALLBACK_TEXTURE, GL_TRUE); |
||
2380 | |||
2381 | has_material = !ctx->VertexProgram._Enabled && ctx->Light.Enabled && check_material( ctx ); |
||
2382 | |||
2383 | if (has_material) { |
||
2384 | TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_TRUE ); |
||
2385 | } |
||
2386 | |||
2387 | /* Run the pipeline. |
||
2388 | */ |
||
2389 | _tnl_run_pipeline( ctx ); |
||
2390 | |||
2391 | if (has_material) { |
||
2392 | TCL_FALLBACK( ctx, R200_TCL_FALLBACK_MATERIAL, GL_FALSE ); |
||
2393 | } |
||
2394 | } |
||
2395 | |||
2396 | |||
2397 | static void r200PolygonStipple( struct gl_context *ctx, const GLubyte *mask ) |
||
2398 | { |
||
2399 | r200ContextPtr r200 = R200_CONTEXT(ctx); |
||
2400 | GLint i; |
||
2401 | |||
2402 | radeon_firevertices(&r200->radeon); |
||
2403 | |||
2404 | radeon_print(RADEON_STATE, RADEON_TRACE, |
||
2405 | "%s(%p) first 32 bits are %x.\n", |
||
2406 | __func__, |
||
2407 | ctx, |
||
2408 | *(uint32_t*)mask); |
||
2409 | |||
2410 | R200_STATECHANGE(r200, stp); |
||
2411 | |||
2412 | /* Must flip pattern upside down. |
||
2413 | */ |
||
2414 | for ( i = 31 ; i >= 0; i--) { |
||
2415 | r200->hw.stp.cmd[3 + i] = ((GLuint *) mask)[i]; |
||
2416 | } |
||
2417 | } |
||
2418 | /* Initialize the driver's state functions. |
||
2419 | */ |
||
2420 | void r200InitStateFuncs( radeonContextPtr radeon, struct dd_function_table *functions ) |
||
2421 | { |
||
2422 | functions->UpdateState = r200InvalidateState; |
||
2423 | functions->LightingSpaceChange = r200LightingSpaceChange; |
||
2424 | |||
2425 | functions->DrawBuffer = radeonDrawBuffer; |
||
2426 | functions->ReadBuffer = radeonReadBuffer; |
||
2427 | |||
2428 | functions->CopyPixels = _mesa_meta_CopyPixels; |
||
2429 | functions->DrawPixels = _mesa_meta_DrawPixels; |
||
2430 | functions->ReadPixels = radeonReadPixels; |
||
2431 | |||
2432 | functions->AlphaFunc = r200AlphaFunc; |
||
2433 | functions->BlendColor = r200BlendColor; |
||
2434 | functions->BlendEquationSeparate = r200BlendEquationSeparate; |
||
2435 | functions->BlendFuncSeparate = r200BlendFuncSeparate; |
||
2436 | functions->ClipPlane = r200ClipPlane; |
||
2437 | functions->ColorMask = r200ColorMask; |
||
2438 | functions->CullFace = r200CullFace; |
||
2439 | functions->DepthFunc = r200DepthFunc; |
||
2440 | functions->DepthMask = r200DepthMask; |
||
2441 | functions->DepthRange = r200DepthRange; |
||
2442 | functions->Enable = r200Enable; |
||
2443 | functions->Fogfv = r200Fogfv; |
||
2444 | functions->FrontFace = r200FrontFace; |
||
2445 | functions->Hint = NULL; |
||
2446 | functions->LightModelfv = r200LightModelfv; |
||
2447 | functions->Lightfv = r200Lightfv; |
||
2448 | functions->LineStipple = r200LineStipple; |
||
2449 | functions->LineWidth = r200LineWidth; |
||
2450 | functions->LogicOpcode = r200LogicOpCode; |
||
2451 | functions->PolygonMode = r200PolygonMode; |
||
2452 | functions->PolygonOffset = r200PolygonOffset; |
||
2453 | functions->PolygonStipple = r200PolygonStipple; |
||
2454 | functions->PointParameterfv = r200PointParameter; |
||
2455 | functions->PointSize = r200PointSize; |
||
2456 | functions->RenderMode = r200RenderMode; |
||
2457 | functions->Scissor = radeonScissor; |
||
2458 | functions->ShadeModel = r200ShadeModel; |
||
2459 | functions->StencilFuncSeparate = r200StencilFuncSeparate; |
||
2460 | functions->StencilMaskSeparate = r200StencilMaskSeparate; |
||
2461 | functions->StencilOpSeparate = r200StencilOpSeparate; |
||
2462 | functions->Viewport = r200Viewport; |
||
2463 | } |
||
2464 | |||
2465 | |||
2466 | void r200InitTnlFuncs( struct gl_context *ctx ) |
||
2467 | { |
||
2468 | TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange = r200UpdateMaterial; |
||
2469 | TNL_CONTEXT(ctx)->Driver.RunPipeline = r200WrapRunPipeline; |
||
2470 | }>>><>><>><>><>>>><>>><>>><>><>><>=>>=>><>> |