Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4358 | Serge | 1 | /* |
2 | * Mesa 3-D graphics library |
||
3 | * |
||
4 | * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. |
||
5 | * |
||
6 | * Permission is hereby granted, free of charge, to any person obtaining a |
||
7 | * copy of this software and associated documentation files (the "Software"), |
||
8 | * to deal in the Software without restriction, including without limitation |
||
9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
||
10 | * and/or sell copies of the Software, and to permit persons to whom the |
||
11 | * Software is furnished to do so, subject to the following conditions: |
||
12 | * |
||
13 | * The above copyright notice and this permission notice shall be included |
||
14 | * in all copies or substantial portions of the Software. |
||
15 | * |
||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
||
17 | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
||
20 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
||
21 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
||
22 | * OTHER DEALINGS IN THE SOFTWARE. |
||
23 | * |
||
24 | * Authors: |
||
25 | * Keith Whitwell |
||
26 | */ |
||
27 | |||
28 | #include "main/imports.h" |
||
29 | #include "main/bufferobj.h" |
||
30 | #include "main/colormac.h" |
||
31 | #include "main/mtypes.h" |
||
32 | #include "main/samplerobj.h" |
||
33 | #include "main/teximage.h" |
||
34 | #include "program/prog_parameter.h" |
||
35 | #include "program/prog_statevars.h" |
||
36 | #include "swrast.h" |
||
37 | #include "s_blend.h" |
||
38 | #include "s_context.h" |
||
39 | #include "s_lines.h" |
||
40 | #include "s_points.h" |
||
41 | #include "s_span.h" |
||
42 | #include "s_texfetch.h" |
||
43 | #include "s_triangle.h" |
||
44 | #include "s_texfilter.h" |
||
45 | |||
46 | |||
47 | /** |
||
48 | * Recompute the value of swrast->_RasterMask, etc. according to |
||
49 | * the current context. The _RasterMask field can be easily tested by |
||
50 | * drivers to determine certain basic GL state (does the primitive need |
||
51 | * stenciling, logic-op, fog, etc?). |
||
52 | */ |
||
53 | static void |
||
54 | _swrast_update_rasterflags( struct gl_context *ctx ) |
||
55 | { |
||
56 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
57 | GLbitfield rasterMask = 0; |
||
58 | GLuint i; |
||
59 | |||
60 | if (ctx->Color.AlphaEnabled) rasterMask |= ALPHATEST_BIT; |
||
61 | if (ctx->Color.BlendEnabled) rasterMask |= BLEND_BIT; |
||
62 | if (ctx->Depth.Test) rasterMask |= DEPTH_BIT; |
||
63 | if (swrast->_FogEnabled) rasterMask |= FOG_BIT; |
||
64 | if (ctx->Scissor.Enabled) rasterMask |= CLIP_BIT; |
||
65 | if (ctx->Stencil._Enabled) rasterMask |= STENCIL_BIT; |
||
66 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { |
||
67 | if (!ctx->Color.ColorMask[i][0] || |
||
68 | !ctx->Color.ColorMask[i][1] || |
||
69 | !ctx->Color.ColorMask[i][2] || |
||
70 | !ctx->Color.ColorMask[i][3]) { |
||
71 | rasterMask |= MASKING_BIT; |
||
72 | break; |
||
73 | } |
||
74 | } |
||
75 | if (ctx->Color.ColorLogicOpEnabled) rasterMask |= LOGIC_OP_BIT; |
||
76 | if (ctx->Texture._EnabledUnits) rasterMask |= TEXTURE_BIT; |
||
77 | if ( ctx->Viewport.X < 0 |
||
78 | || ctx->Viewport.X + ctx->Viewport.Width > (GLint) ctx->DrawBuffer->Width |
||
79 | || ctx->Viewport.Y < 0 |
||
80 | || ctx->Viewport.Y + ctx->Viewport.Height > (GLint) ctx->DrawBuffer->Height) { |
||
81 | rasterMask |= CLIP_BIT; |
||
82 | } |
||
83 | |||
84 | if (ctx->Query.CurrentOcclusionObject) |
||
85 | rasterMask |= OCCLUSION_BIT; |
||
86 | |||
87 | |||
88 | /* If we're not drawing to exactly one color buffer set the |
||
89 | * MULTI_DRAW_BIT flag. Also set it if we're drawing to no |
||
90 | * buffers or the RGBA or CI mask disables all writes. |
||
91 | */ |
||
92 | if (ctx->DrawBuffer->_NumColorDrawBuffers != 1) { |
||
93 | /* more than one color buffer designated for writing (or zero buffers) */ |
||
94 | rasterMask |= MULTI_DRAW_BIT; |
||
95 | } |
||
96 | |||
97 | for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { |
||
98 | if (ctx->Color.ColorMask[i][0] + |
||
99 | ctx->Color.ColorMask[i][1] + |
||
100 | ctx->Color.ColorMask[i][2] + |
||
101 | ctx->Color.ColorMask[i][3] == 0) { |
||
102 | rasterMask |= MULTI_DRAW_BIT; /* all RGBA channels disabled */ |
||
103 | break; |
||
104 | } |
||
105 | } |
||
106 | |||
107 | |||
108 | if (_swrast_use_fragment_program(ctx)) { |
||
109 | rasterMask |= FRAGPROG_BIT; |
||
110 | } |
||
111 | |||
112 | if (ctx->ATIFragmentShader._Enabled) { |
||
113 | rasterMask |= ATIFRAGSHADER_BIT; |
||
114 | } |
||
115 | |||
116 | #if CHAN_TYPE == GL_FLOAT |
||
117 | if (ctx->Color.ClampFragmentColor == GL_TRUE) { |
||
118 | rasterMask |= CLAMPING_BIT; |
||
119 | } |
||
120 | #endif |
||
121 | |||
122 | SWRAST_CONTEXT(ctx)->_RasterMask = rasterMask; |
||
123 | } |
||
124 | |||
125 | |||
126 | /** |
||
127 | * Examine polygon cull state to compute the _BackfaceCullSign field. |
||
128 | * _BackfaceCullSign will be 0 if no culling, -1 if culling back-faces, |
||
129 | * and 1 if culling front-faces. The Polygon FrontFace state also |
||
130 | * factors in. |
||
131 | */ |
||
132 | static void |
||
133 | _swrast_update_polygon( struct gl_context *ctx ) |
||
134 | { |
||
135 | GLfloat backface_sign; |
||
136 | |||
137 | if (ctx->Polygon.CullFlag) { |
||
138 | switch (ctx->Polygon.CullFaceMode) { |
||
139 | case GL_BACK: |
||
140 | backface_sign = -1.0F; |
||
141 | break; |
||
142 | case GL_FRONT: |
||
143 | backface_sign = 1.0F; |
||
144 | break; |
||
145 | case GL_FRONT_AND_BACK: |
||
146 | /* fallthrough */ |
||
147 | default: |
||
148 | backface_sign = 0.0F; |
||
149 | } |
||
150 | } |
||
151 | else { |
||
152 | backface_sign = 0.0F; |
||
153 | } |
||
154 | |||
155 | SWRAST_CONTEXT(ctx)->_BackfaceCullSign = backface_sign; |
||
156 | |||
157 | /* This is for front/back-face determination, but not for culling */ |
||
158 | SWRAST_CONTEXT(ctx)->_BackfaceSign |
||
159 | = (ctx->Polygon.FrontFace == GL_CW) ? -1.0F : 1.0F; |
||
160 | } |
||
161 | |||
162 | |||
163 | |||
164 | /** |
||
165 | * Update the _PreferPixelFog field to indicate if we need to compute |
||
166 | * fog blend factors (from the fog coords) per-fragment. |
||
167 | */ |
||
168 | static void |
||
169 | _swrast_update_fog_hint( struct gl_context *ctx ) |
||
170 | { |
||
171 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
172 | swrast->_PreferPixelFog = (!swrast->AllowVertexFog || |
||
173 | _swrast_use_fragment_program(ctx) || |
||
174 | (ctx->Hint.Fog == GL_NICEST && |
||
175 | swrast->AllowPixelFog)); |
||
176 | } |
||
177 | |||
178 | |||
179 | |||
180 | /** |
||
181 | * Update the swrast->_TextureCombinePrimary flag. |
||
182 | */ |
||
183 | static void |
||
184 | _swrast_update_texture_env( struct gl_context *ctx ) |
||
185 | { |
||
186 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
187 | GLuint i; |
||
188 | |||
189 | swrast->_TextureCombinePrimary = GL_FALSE; |
||
190 | |||
191 | for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
||
192 | const struct gl_tex_env_combine_state *combine = |
||
193 | ctx->Texture.Unit[i]._CurrentCombine; |
||
194 | GLuint term; |
||
195 | for (term = 0; term < combine->_NumArgsRGB; term++) { |
||
196 | if (combine->SourceRGB[term] == GL_PRIMARY_COLOR) { |
||
197 | swrast->_TextureCombinePrimary = GL_TRUE; |
||
198 | return; |
||
199 | } |
||
200 | if (combine->SourceA[term] == GL_PRIMARY_COLOR) { |
||
201 | swrast->_TextureCombinePrimary = GL_TRUE; |
||
202 | return; |
||
203 | } |
||
204 | } |
||
205 | } |
||
206 | } |
||
207 | |||
208 | |||
209 | /** |
||
210 | * Determine if we can defer texturing/shading until after Z/stencil |
||
211 | * testing. This potentially allows us to skip texturing/shading for |
||
212 | * lots of fragments. |
||
213 | */ |
||
214 | static void |
||
215 | _swrast_update_deferred_texture(struct gl_context *ctx) |
||
216 | { |
||
217 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
218 | if (ctx->Color.AlphaEnabled) { |
||
219 | /* alpha test depends on post-texture/shader colors */ |
||
220 | swrast->_DeferredTexture = GL_FALSE; |
||
221 | } |
||
222 | else { |
||
223 | GLboolean use_fprog = _swrast_use_fragment_program(ctx); |
||
224 | const struct gl_fragment_program *fprog |
||
225 | = ctx->FragmentProgram._Current; |
||
226 | if (use_fprog && (fprog->Base.OutputsWritten & (1 << FRAG_RESULT_DEPTH))) { |
||
227 | /* Z comes from fragment program/shader */ |
||
228 | swrast->_DeferredTexture = GL_FALSE; |
||
229 | } |
||
230 | else if (use_fprog && fprog->UsesKill) { |
||
231 | swrast->_DeferredTexture = GL_FALSE; |
||
232 | } |
||
233 | else if (ctx->Query.CurrentOcclusionObject) { |
||
234 | /* occlusion query depends on shader discard/kill results */ |
||
235 | swrast->_DeferredTexture = GL_FALSE; |
||
236 | } |
||
237 | else { |
||
238 | swrast->_DeferredTexture = GL_TRUE; |
||
239 | } |
||
240 | } |
||
241 | } |
||
242 | |||
243 | |||
244 | /** |
||
245 | * Update swrast->_FogColor and swrast->_FogEnable values. |
||
246 | */ |
||
247 | static void |
||
248 | _swrast_update_fog_state( struct gl_context *ctx ) |
||
249 | { |
||
250 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
251 | const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; |
||
252 | |||
253 | assert(fp == NULL || fp->Base.Target == GL_FRAGMENT_PROGRAM_ARB); |
||
254 | |||
255 | /* determine if fog is needed, and if so, which fog mode */ |
||
256 | swrast->_FogEnabled = (!_swrast_use_fragment_program(ctx) && |
||
257 | ctx->Fog.Enabled); |
||
258 | } |
||
259 | |||
260 | |||
261 | /** |
||
262 | * Update state for running fragment programs. Basically, load the |
||
263 | * program parameters with current state values. |
||
264 | */ |
||
265 | static void |
||
266 | _swrast_update_fragment_program(struct gl_context *ctx, GLbitfield newState) |
||
267 | { |
||
268 | if (!_swrast_use_fragment_program(ctx)) |
||
269 | return; |
||
270 | |||
271 | _mesa_load_state_parameters(ctx, |
||
272 | ctx->FragmentProgram._Current->Base.Parameters); |
||
273 | } |
||
274 | |||
275 | |||
276 | /** |
||
277 | * See if we can do early diffuse+specular (primary+secondary) color |
||
278 | * add per vertex instead of per-fragment. |
||
279 | */ |
||
280 | static void |
||
281 | _swrast_update_specular_vertex_add(struct gl_context *ctx) |
||
282 | { |
||
283 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
284 | GLboolean separateSpecular = ctx->Fog.ColorSumEnabled || |
||
285 | (ctx->Light.Enabled && |
||
286 | ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR); |
||
287 | |||
288 | swrast->SpecularVertexAdd = (separateSpecular |
||
289 | && ctx->Texture._EnabledUnits == 0x0 |
||
290 | && !_swrast_use_fragment_program(ctx) |
||
291 | && !ctx->ATIFragmentShader._Enabled); |
||
292 | } |
||
293 | |||
294 | |||
295 | #define _SWRAST_NEW_DERIVED (_SWRAST_NEW_RASTERMASK | \ |
||
296 | _NEW_PROGRAM_CONSTANTS | \ |
||
297 | _NEW_TEXTURE | \ |
||
298 | _NEW_HINT | \ |
||
299 | _NEW_POLYGON ) |
||
300 | |||
301 | /* State referenced by _swrast_choose_triangle, _swrast_choose_line. |
||
302 | */ |
||
303 | #define _SWRAST_NEW_TRIANGLE (_SWRAST_NEW_DERIVED | \ |
||
304 | _NEW_RENDERMODE| \ |
||
305 | _NEW_POLYGON| \ |
||
306 | _NEW_DEPTH| \ |
||
307 | _NEW_STENCIL| \ |
||
308 | _NEW_COLOR| \ |
||
309 | _NEW_TEXTURE| \ |
||
310 | _SWRAST_NEW_RASTERMASK| \ |
||
311 | _NEW_LIGHT| \ |
||
312 | _NEW_FOG | \ |
||
313 | _MESA_NEW_SEPARATE_SPECULAR) |
||
314 | |||
315 | #define _SWRAST_NEW_LINE (_SWRAST_NEW_DERIVED | \ |
||
316 | _NEW_RENDERMODE| \ |
||
317 | _NEW_LINE| \ |
||
318 | _NEW_TEXTURE| \ |
||
319 | _NEW_LIGHT| \ |
||
320 | _NEW_FOG| \ |
||
321 | _NEW_DEPTH | \ |
||
322 | _MESA_NEW_SEPARATE_SPECULAR) |
||
323 | |||
324 | #define _SWRAST_NEW_POINT (_SWRAST_NEW_DERIVED | \ |
||
325 | _NEW_RENDERMODE | \ |
||
326 | _NEW_POINT | \ |
||
327 | _NEW_TEXTURE | \ |
||
328 | _NEW_LIGHT | \ |
||
329 | _NEW_FOG | \ |
||
330 | _MESA_NEW_SEPARATE_SPECULAR) |
||
331 | |||
332 | #define _SWRAST_NEW_TEXTURE_SAMPLE_FUNC _NEW_TEXTURE |
||
333 | |||
334 | #define _SWRAST_NEW_TEXTURE_ENV_MODE _NEW_TEXTURE |
||
335 | |||
336 | #define _SWRAST_NEW_BLEND_FUNC _NEW_COLOR |
||
337 | |||
338 | |||
339 | |||
340 | /** |
||
341 | * Stub for swrast->Triangle to select a true triangle function |
||
342 | * after a state change. |
||
343 | */ |
||
344 | static void |
||
345 | _swrast_validate_triangle( struct gl_context *ctx, |
||
346 | const SWvertex *v0, |
||
347 | const SWvertex *v1, |
||
348 | const SWvertex *v2 ) |
||
349 | { |
||
350 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
351 | |||
352 | _swrast_validate_derived( ctx ); |
||
353 | swrast->choose_triangle( ctx ); |
||
354 | ASSERT(swrast->Triangle); |
||
355 | |||
356 | if (swrast->SpecularVertexAdd) { |
||
357 | /* separate specular color, but no texture */ |
||
358 | swrast->SpecTriangle = swrast->Triangle; |
||
359 | swrast->Triangle = _swrast_add_spec_terms_triangle; |
||
360 | } |
||
361 | |||
362 | swrast->Triangle( ctx, v0, v1, v2 ); |
||
363 | } |
||
364 | |||
365 | /** |
||
366 | * Called via swrast->Line. Examine current GL state and choose a software |
||
367 | * line routine. Then call it. |
||
368 | */ |
||
369 | static void |
||
370 | _swrast_validate_line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 ) |
||
371 | { |
||
372 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
373 | |||
374 | _swrast_validate_derived( ctx ); |
||
375 | swrast->choose_line( ctx ); |
||
376 | ASSERT(swrast->Line); |
||
377 | |||
378 | if (swrast->SpecularVertexAdd) { |
||
379 | swrast->SpecLine = swrast->Line; |
||
380 | swrast->Line = _swrast_add_spec_terms_line; |
||
381 | } |
||
382 | |||
383 | swrast->Line( ctx, v0, v1 ); |
||
384 | } |
||
385 | |||
386 | /** |
||
387 | * Called via swrast->Point. Examine current GL state and choose a software |
||
388 | * point routine. Then call it. |
||
389 | */ |
||
390 | static void |
||
391 | _swrast_validate_point( struct gl_context *ctx, const SWvertex *v0 ) |
||
392 | { |
||
393 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
394 | |||
395 | _swrast_validate_derived( ctx ); |
||
396 | swrast->choose_point( ctx ); |
||
397 | |||
398 | if (swrast->SpecularVertexAdd) { |
||
399 | swrast->SpecPoint = swrast->Point; |
||
400 | swrast->Point = _swrast_add_spec_terms_point; |
||
401 | } |
||
402 | |||
403 | swrast->Point( ctx, v0 ); |
||
404 | } |
||
405 | |||
406 | |||
407 | /** |
||
408 | * Called via swrast->BlendFunc. Examine GL state to choose a blending |
||
409 | * function, then call it. |
||
410 | */ |
||
411 | static void _ASMAPI |
||
412 | _swrast_validate_blend_func(struct gl_context *ctx, GLuint n, const GLubyte mask[], |
||
413 | GLvoid *src, const GLvoid *dst, |
||
414 | GLenum chanType ) |
||
415 | { |
||
416 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
417 | |||
418 | _swrast_validate_derived( ctx ); /* why is this needed? */ |
||
419 | _swrast_choose_blend_func( ctx, chanType ); |
||
420 | |||
421 | swrast->BlendFunc( ctx, n, mask, src, dst, chanType ); |
||
422 | } |
||
423 | |||
424 | static void |
||
425 | _swrast_sleep( struct gl_context *ctx, GLbitfield new_state ) |
||
426 | { |
||
427 | (void) ctx; (void) new_state; |
||
428 | } |
||
429 | |||
430 | |||
431 | static void |
||
432 | _swrast_invalidate_state( struct gl_context *ctx, GLbitfield new_state ) |
||
433 | { |
||
434 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
435 | GLuint i; |
||
436 | |||
437 | swrast->NewState |= new_state; |
||
438 | |||
439 | /* After 10 statechanges without any swrast functions being called, |
||
440 | * put the module to sleep. |
||
441 | */ |
||
442 | if (++swrast->StateChanges > 10) { |
||
443 | swrast->InvalidateState = _swrast_sleep; |
||
444 | swrast->NewState = ~0; |
||
445 | new_state = ~0; |
||
446 | } |
||
447 | |||
448 | if (new_state & swrast->InvalidateTriangleMask) |
||
449 | swrast->Triangle = _swrast_validate_triangle; |
||
450 | |||
451 | if (new_state & swrast->InvalidateLineMask) |
||
452 | swrast->Line = _swrast_validate_line; |
||
453 | |||
454 | if (new_state & swrast->InvalidatePointMask) |
||
455 | swrast->Point = _swrast_validate_point; |
||
456 | |||
457 | if (new_state & _SWRAST_NEW_BLEND_FUNC) |
||
458 | swrast->BlendFunc = _swrast_validate_blend_func; |
||
459 | |||
460 | if (new_state & _SWRAST_NEW_TEXTURE_SAMPLE_FUNC) |
||
461 | for (i = 0 ; i < ARRAY_SIZE(swrast->TextureSample); i++) |
||
462 | swrast->TextureSample[i] = NULL; |
||
463 | } |
||
464 | |||
465 | |||
466 | void |
||
467 | _swrast_update_texture_samplers(struct gl_context *ctx) |
||
468 | { |
||
469 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
470 | GLuint u; |
||
471 | |||
472 | if (!swrast) |
||
473 | return; /* pipe hack */ |
||
474 | |||
475 | for (u = 0; u < ARRAY_SIZE(swrast->TextureSample); u++) { |
||
476 | struct gl_texture_object *tObj = ctx->Texture.Unit[u]._Current; |
||
477 | /* Note: If tObj is NULL, the sample function will be a simple |
||
478 | * function that just returns opaque black (0,0,0,1). |
||
479 | */ |
||
480 | _mesa_update_fetch_functions(ctx, u); |
||
481 | swrast->TextureSample[u] = |
||
482 | _swrast_choose_texture_sample_func(ctx, tObj, |
||
483 | _mesa_get_samplerobj(ctx, u)); |
||
484 | } |
||
485 | } |
||
486 | |||
487 | |||
488 | /** |
||
489 | * Update swrast->_ActiveAttribs, swrast->_NumActiveAttribs, |
||
490 | * swrast->_ActiveAtttribMask. |
||
491 | */ |
||
492 | static void |
||
493 | _swrast_update_active_attribs(struct gl_context *ctx) |
||
494 | { |
||
495 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
496 | GLbitfield64 attribsMask; |
||
497 | |||
498 | /* |
||
499 | * Compute _ActiveAttribsMask = which fragment attributes are needed. |
||
500 | */ |
||
501 | if (_swrast_use_fragment_program(ctx)) { |
||
502 | /* fragment program/shader */ |
||
503 | attribsMask = ctx->FragmentProgram._Current->Base.InputsRead; |
||
504 | attribsMask &= ~VARYING_BIT_POS; /* WPOS is always handled specially */ |
||
505 | } |
||
506 | else if (ctx->ATIFragmentShader._Enabled) { |
||
507 | attribsMask = ~0; /* XXX fix me */ |
||
508 | } |
||
509 | else { |
||
510 | /* fixed function */ |
||
511 | attribsMask = 0x0; |
||
512 | |||
513 | #if CHAN_TYPE == GL_FLOAT |
||
514 | attribsMask |= VARYING_BIT_COL0; |
||
515 | #endif |
||
516 | |||
517 | if (ctx->Fog.ColorSumEnabled || |
||
518 | (ctx->Light.Enabled && |
||
519 | ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)) { |
||
520 | attribsMask |= VARYING_BIT_COL1; |
||
521 | } |
||
522 | |||
523 | if (swrast->_FogEnabled) |
||
524 | attribsMask |= VARYING_BIT_FOGC; |
||
525 | |||
526 | attribsMask |= (ctx->Texture._EnabledUnits << VARYING_SLOT_TEX0); |
||
527 | } |
||
528 | |||
529 | swrast->_ActiveAttribMask = attribsMask; |
||
530 | |||
531 | /* Update _ActiveAttribs[] list */ |
||
532 | { |
||
533 | GLuint i, num = 0; |
||
534 | for (i = 0; i < VARYING_SLOT_MAX; i++) { |
||
535 | if (attribsMask & BITFIELD64_BIT(i)) { |
||
536 | swrast->_ActiveAttribs[num++] = i; |
||
537 | /* how should this attribute be interpolated? */ |
||
538 | if (i == VARYING_SLOT_COL0 || i == VARYING_SLOT_COL1) |
||
539 | swrast->_InterpMode[i] = ctx->Light.ShadeModel; |
||
540 | else |
||
541 | swrast->_InterpMode[i] = GL_SMOOTH; |
||
542 | } |
||
543 | } |
||
544 | swrast->_NumActiveAttribs = num; |
||
545 | } |
||
546 | } |
||
547 | |||
548 | |||
549 | void |
||
550 | _swrast_validate_derived( struct gl_context *ctx ) |
||
551 | { |
||
552 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
553 | |||
554 | if (swrast->NewState) { |
||
555 | if (swrast->NewState & _NEW_POLYGON) |
||
556 | _swrast_update_polygon( ctx ); |
||
557 | |||
558 | if (swrast->NewState & (_NEW_HINT | _NEW_PROGRAM)) |
||
559 | _swrast_update_fog_hint( ctx ); |
||
560 | |||
561 | if (swrast->NewState & _SWRAST_NEW_TEXTURE_ENV_MODE) |
||
562 | _swrast_update_texture_env( ctx ); |
||
563 | |||
564 | if (swrast->NewState & (_NEW_FOG | _NEW_PROGRAM)) |
||
565 | _swrast_update_fog_state( ctx ); |
||
566 | |||
567 | if (swrast->NewState & (_NEW_PROGRAM_CONSTANTS | _NEW_PROGRAM)) |
||
568 | _swrast_update_fragment_program( ctx, swrast->NewState ); |
||
569 | |||
570 | if (swrast->NewState & (_NEW_TEXTURE | _NEW_PROGRAM)) { |
||
571 | _swrast_update_texture_samplers( ctx ); |
||
572 | } |
||
573 | |||
574 | if (swrast->NewState & (_NEW_COLOR | _NEW_PROGRAM)) |
||
575 | _swrast_update_deferred_texture(ctx); |
||
576 | |||
577 | if (swrast->NewState & _SWRAST_NEW_RASTERMASK) |
||
578 | _swrast_update_rasterflags( ctx ); |
||
579 | |||
580 | if (swrast->NewState & (_NEW_DEPTH | |
||
581 | _NEW_FOG | |
||
582 | _NEW_LIGHT | |
||
583 | _NEW_PROGRAM | |
||
584 | _NEW_TEXTURE)) |
||
585 | _swrast_update_active_attribs(ctx); |
||
586 | |||
587 | if (swrast->NewState & (_NEW_FOG | |
||
588 | _NEW_PROGRAM | |
||
589 | _NEW_LIGHT | |
||
590 | _NEW_TEXTURE)) |
||
591 | _swrast_update_specular_vertex_add(ctx); |
||
592 | |||
593 | swrast->NewState = 0; |
||
594 | swrast->StateChanges = 0; |
||
595 | swrast->InvalidateState = _swrast_invalidate_state; |
||
596 | } |
||
597 | } |
||
598 | |||
599 | #define SWRAST_DEBUG 0 |
||
600 | |||
601 | /* Public entrypoints: See also s_bitmap.c, etc. |
||
602 | */ |
||
603 | void |
||
604 | _swrast_Quad( struct gl_context *ctx, |
||
605 | const SWvertex *v0, const SWvertex *v1, |
||
606 | const SWvertex *v2, const SWvertex *v3 ) |
||
607 | { |
||
608 | if (SWRAST_DEBUG) { |
||
609 | _mesa_debug(ctx, "_swrast_Quad\n"); |
||
610 | _swrast_print_vertex( ctx, v0 ); |
||
611 | _swrast_print_vertex( ctx, v1 ); |
||
612 | _swrast_print_vertex( ctx, v2 ); |
||
613 | _swrast_print_vertex( ctx, v3 ); |
||
614 | } |
||
615 | SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v3 ); |
||
616 | SWRAST_CONTEXT(ctx)->Triangle( ctx, v1, v2, v3 ); |
||
617 | } |
||
618 | |||
619 | void |
||
620 | _swrast_Triangle( struct gl_context *ctx, const SWvertex *v0, |
||
621 | const SWvertex *v1, const SWvertex *v2 ) |
||
622 | { |
||
623 | if (SWRAST_DEBUG) { |
||
624 | _mesa_debug(ctx, "_swrast_Triangle\n"); |
||
625 | _swrast_print_vertex( ctx, v0 ); |
||
626 | _swrast_print_vertex( ctx, v1 ); |
||
627 | _swrast_print_vertex( ctx, v2 ); |
||
628 | } |
||
629 | SWRAST_CONTEXT(ctx)->Triangle( ctx, v0, v1, v2 ); |
||
630 | } |
||
631 | |||
632 | void |
||
633 | _swrast_Line( struct gl_context *ctx, const SWvertex *v0, const SWvertex *v1 ) |
||
634 | { |
||
635 | if (SWRAST_DEBUG) { |
||
636 | _mesa_debug(ctx, "_swrast_Line\n"); |
||
637 | _swrast_print_vertex( ctx, v0 ); |
||
638 | _swrast_print_vertex( ctx, v1 ); |
||
639 | } |
||
640 | SWRAST_CONTEXT(ctx)->Line( ctx, v0, v1 ); |
||
641 | } |
||
642 | |||
643 | void |
||
644 | _swrast_Point( struct gl_context *ctx, const SWvertex *v0 ) |
||
645 | { |
||
646 | if (SWRAST_DEBUG) { |
||
647 | _mesa_debug(ctx, "_swrast_Point\n"); |
||
648 | _swrast_print_vertex( ctx, v0 ); |
||
649 | } |
||
650 | SWRAST_CONTEXT(ctx)->Point( ctx, v0 ); |
||
651 | } |
||
652 | |||
653 | void |
||
654 | _swrast_InvalidateState( struct gl_context *ctx, GLbitfield new_state ) |
||
655 | { |
||
656 | if (SWRAST_DEBUG) { |
||
657 | _mesa_debug(ctx, "_swrast_InvalidateState\n"); |
||
658 | } |
||
659 | SWRAST_CONTEXT(ctx)->InvalidateState( ctx, new_state ); |
||
660 | } |
||
661 | |||
662 | void |
||
663 | _swrast_ResetLineStipple( struct gl_context *ctx ) |
||
664 | { |
||
665 | if (SWRAST_DEBUG) { |
||
666 | _mesa_debug(ctx, "_swrast_ResetLineStipple\n"); |
||
667 | } |
||
668 | SWRAST_CONTEXT(ctx)->StippleCounter = 0; |
||
669 | } |
||
670 | |||
671 | void |
||
672 | _swrast_SetFacing(struct gl_context *ctx, GLuint facing) |
||
673 | { |
||
674 | SWRAST_CONTEXT(ctx)->PointLineFacing = facing; |
||
675 | } |
||
676 | |||
677 | void |
||
678 | _swrast_allow_vertex_fog( struct gl_context *ctx, GLboolean value ) |
||
679 | { |
||
680 | if (SWRAST_DEBUG) { |
||
681 | _mesa_debug(ctx, "_swrast_allow_vertex_fog %d\n", value); |
||
682 | } |
||
683 | SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); |
||
684 | SWRAST_CONTEXT(ctx)->AllowVertexFog = value; |
||
685 | } |
||
686 | |||
687 | void |
||
688 | _swrast_allow_pixel_fog( struct gl_context *ctx, GLboolean value ) |
||
689 | { |
||
690 | if (SWRAST_DEBUG) { |
||
691 | _mesa_debug(ctx, "_swrast_allow_pixel_fog %d\n", value); |
||
692 | } |
||
693 | SWRAST_CONTEXT(ctx)->InvalidateState( ctx, _NEW_HINT ); |
||
694 | SWRAST_CONTEXT(ctx)->AllowPixelFog = value; |
||
695 | } |
||
696 | |||
697 | |||
698 | /** |
||
699 | * Initialize native program limits by copying the logical limits. |
||
700 | * See comments in init_program_limits() in context.c |
||
701 | */ |
||
702 | static void |
||
703 | init_program_native_limits(struct gl_program_constants *prog) |
||
704 | { |
||
705 | prog->MaxNativeInstructions = prog->MaxInstructions; |
||
706 | prog->MaxNativeAluInstructions = prog->MaxAluInstructions; |
||
707 | prog->MaxNativeTexInstructions = prog->MaxTexInstructions; |
||
708 | prog->MaxNativeTexIndirections = prog->MaxTexIndirections; |
||
709 | prog->MaxNativeAttribs = prog->MaxAttribs; |
||
710 | prog->MaxNativeTemps = prog->MaxTemps; |
||
711 | prog->MaxNativeAddressRegs = prog->MaxAddressRegs; |
||
712 | prog->MaxNativeParameters = prog->MaxParameters; |
||
713 | } |
||
714 | |||
715 | |||
716 | GLboolean |
||
717 | _swrast_CreateContext( struct gl_context *ctx ) |
||
718 | { |
||
719 | GLuint i; |
||
720 | SWcontext *swrast = calloc(1, sizeof(SWcontext)); |
||
721 | #ifdef _OPENMP |
||
722 | const GLuint maxThreads = omp_get_max_threads(); |
||
723 | #else |
||
724 | const GLuint maxThreads = 1; |
||
725 | #endif |
||
726 | |||
727 | assert(ctx->Const.MaxViewportWidth <= SWRAST_MAX_WIDTH); |
||
728 | assert(ctx->Const.MaxViewportHeight <= SWRAST_MAX_WIDTH); |
||
729 | |||
730 | assert(ctx->Const.MaxRenderbufferSize <= SWRAST_MAX_WIDTH); |
||
731 | |||
732 | /* make sure largest texture image is <= SWRAST_MAX_WIDTH in size */ |
||
733 | assert((1 << (ctx->Const.MaxTextureLevels - 1)) <= SWRAST_MAX_WIDTH); |
||
734 | assert((1 << (ctx->Const.MaxCubeTextureLevels - 1)) <= SWRAST_MAX_WIDTH); |
||
735 | assert((1 << (ctx->Const.Max3DTextureLevels - 1)) <= SWRAST_MAX_WIDTH); |
||
736 | |||
737 | assert(PROG_MAX_WIDTH == SWRAST_MAX_WIDTH); |
||
738 | |||
739 | if (SWRAST_DEBUG) { |
||
740 | _mesa_debug(ctx, "_swrast_CreateContext\n"); |
||
741 | } |
||
742 | |||
743 | if (!swrast) |
||
744 | return GL_FALSE; |
||
745 | |||
746 | swrast->NewState = ~0; |
||
747 | |||
748 | swrast->choose_point = _swrast_choose_point; |
||
749 | swrast->choose_line = _swrast_choose_line; |
||
750 | swrast->choose_triangle = _swrast_choose_triangle; |
||
751 | |||
752 | swrast->InvalidatePointMask = _SWRAST_NEW_POINT; |
||
753 | swrast->InvalidateLineMask = _SWRAST_NEW_LINE; |
||
754 | swrast->InvalidateTriangleMask = _SWRAST_NEW_TRIANGLE; |
||
755 | |||
756 | swrast->Point = _swrast_validate_point; |
||
757 | swrast->Line = _swrast_validate_line; |
||
758 | swrast->Triangle = _swrast_validate_triangle; |
||
759 | swrast->InvalidateState = _swrast_sleep; |
||
760 | swrast->BlendFunc = _swrast_validate_blend_func; |
||
761 | |||
762 | swrast->AllowVertexFog = GL_TRUE; |
||
763 | swrast->AllowPixelFog = GL_TRUE; |
||
764 | |||
765 | swrast->Driver.SpanRenderStart = _swrast_span_render_start; |
||
766 | swrast->Driver.SpanRenderFinish = _swrast_span_render_finish; |
||
767 | |||
768 | for (i = 0; i < ARRAY_SIZE(swrast->TextureSample); i++) |
||
769 | swrast->TextureSample[i] = NULL; |
||
770 | |||
771 | /* SpanArrays is global and shared by all SWspan instances. However, when |
||
772 | * using multiple threads, it is necessary to have one SpanArrays instance |
||
773 | * per thread. |
||
774 | */ |
||
775 | swrast->SpanArrays = malloc(maxThreads * sizeof(SWspanarrays)); |
||
776 | if (!swrast->SpanArrays) { |
||
777 | free(swrast); |
||
778 | return GL_FALSE; |
||
779 | } |
||
780 | for(i = 0; i < maxThreads; i++) { |
||
781 | swrast->SpanArrays[i].ChanType = CHAN_TYPE; |
||
782 | #if CHAN_TYPE == GL_UNSIGNED_BYTE |
||
783 | swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba8; |
||
784 | #elif CHAN_TYPE == GL_UNSIGNED_SHORT |
||
785 | swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].rgba16; |
||
786 | #else |
||
787 | swrast->SpanArrays[i].rgba = swrast->SpanArrays[i].attribs[VARYING_SLOT_COL0]; |
||
788 | #endif |
||
789 | } |
||
790 | |||
791 | /* init point span buffer */ |
||
792 | swrast->PointSpan.primitive = GL_POINT; |
||
793 | swrast->PointSpan.end = 0; |
||
794 | swrast->PointSpan.facing = 0; |
||
795 | swrast->PointSpan.array = swrast->SpanArrays; |
||
796 | |||
797 | init_program_native_limits(&ctx->Const.VertexProgram); |
||
798 | init_program_native_limits(&ctx->Const.GeometryProgram); |
||
799 | init_program_native_limits(&ctx->Const.FragmentProgram); |
||
800 | |||
801 | ctx->swrast_context = swrast; |
||
802 | |||
803 | swrast->stencil_temp.buf1 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte)); |
||
804 | swrast->stencil_temp.buf2 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte)); |
||
805 | swrast->stencil_temp.buf3 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte)); |
||
806 | swrast->stencil_temp.buf4 = malloc(SWRAST_MAX_WIDTH * sizeof(GLubyte)); |
||
807 | |||
808 | if (!swrast->stencil_temp.buf1 || |
||
809 | !swrast->stencil_temp.buf2 || |
||
810 | !swrast->stencil_temp.buf3 || |
||
811 | !swrast->stencil_temp.buf4) { |
||
812 | _swrast_DestroyContext(ctx); |
||
813 | return GL_FALSE; |
||
814 | } |
||
815 | |||
816 | return GL_TRUE; |
||
817 | } |
||
818 | |||
819 | void |
||
820 | _swrast_DestroyContext( struct gl_context *ctx ) |
||
821 | { |
||
822 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
823 | |||
824 | if (SWRAST_DEBUG) { |
||
825 | _mesa_debug(ctx, "_swrast_DestroyContext\n"); |
||
826 | } |
||
827 | |||
828 | free( swrast->SpanArrays ); |
||
829 | free( swrast->ZoomedArrays ); |
||
830 | free( swrast->TexelBuffer ); |
||
831 | |||
832 | free(swrast->stencil_temp.buf1); |
||
833 | free(swrast->stencil_temp.buf2); |
||
834 | free(swrast->stencil_temp.buf3); |
||
835 | free(swrast->stencil_temp.buf4); |
||
836 | |||
837 | free( swrast ); |
||
838 | |||
839 | ctx->swrast_context = 0; |
||
840 | } |
||
841 | |||
842 | |||
843 | struct swrast_device_driver * |
||
844 | _swrast_GetDeviceDriverReference( struct gl_context *ctx ) |
||
845 | { |
||
846 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
847 | return &swrast->Driver; |
||
848 | } |
||
849 | |||
850 | void |
||
851 | _swrast_flush( struct gl_context *ctx ) |
||
852 | { |
||
853 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
854 | /* flush any pending fragments from rendering points */ |
||
855 | if (swrast->PointSpan.end > 0) { |
||
856 | _swrast_write_rgba_span(ctx, &(swrast->PointSpan)); |
||
857 | swrast->PointSpan.end = 0; |
||
858 | } |
||
859 | } |
||
860 | |||
861 | void |
||
862 | _swrast_render_primitive( struct gl_context *ctx, GLenum prim ) |
||
863 | { |
||
864 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
865 | if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) { |
||
866 | _swrast_flush(ctx); |
||
867 | } |
||
868 | swrast->Primitive = prim; |
||
869 | } |
||
870 | |||
871 | |||
872 | /** called via swrast->Driver.SpanRenderStart() */ |
||
873 | void |
||
874 | _swrast_span_render_start(struct gl_context *ctx) |
||
875 | { |
||
876 | _swrast_map_textures(ctx); |
||
877 | _swrast_map_renderbuffers(ctx); |
||
878 | } |
||
879 | |||
880 | |||
881 | /** called via swrast->Driver.SpanRenderFinish() */ |
||
882 | void |
||
883 | _swrast_span_render_finish(struct gl_context *ctx) |
||
884 | { |
||
885 | _swrast_unmap_textures(ctx); |
||
886 | _swrast_unmap_renderbuffers(ctx); |
||
887 | } |
||
888 | |||
889 | |||
890 | void |
||
891 | _swrast_render_start( struct gl_context *ctx ) |
||
892 | { |
||
893 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
894 | if (swrast->Driver.SpanRenderStart) |
||
895 | swrast->Driver.SpanRenderStart( ctx ); |
||
896 | swrast->PointSpan.end = 0; |
||
897 | } |
||
898 | |||
899 | void |
||
900 | _swrast_render_finish( struct gl_context *ctx ) |
||
901 | { |
||
902 | SWcontext *swrast = SWRAST_CONTEXT(ctx); |
||
903 | |||
904 | _swrast_flush(ctx); |
||
905 | |||
906 | if (swrast->Driver.SpanRenderFinish) |
||
907 | swrast->Driver.SpanRenderFinish( ctx ); |
||
908 | } |
||
909 | |||
910 | |||
911 | #define SWRAST_DEBUG_VERTICES 0 |
||
912 | |||
913 | void |
||
914 | _swrast_print_vertex( struct gl_context *ctx, const SWvertex *v ) |
||
915 | { |
||
916 | GLuint i; |
||
917 | |||
918 | if (SWRAST_DEBUG_VERTICES) { |
||
919 | _mesa_debug(ctx, "win %f %f %f %f\n", |
||
920 | v->attrib[VARYING_SLOT_POS][0], |
||
921 | v->attrib[VARYING_SLOT_POS][1], |
||
922 | v->attrib[VARYING_SLOT_POS][2], |
||
923 | v->attrib[VARYING_SLOT_POS][3]); |
||
924 | |||
925 | for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) |
||
926 | if (ctx->Texture.Unit[i]._ReallyEnabled) |
||
927 | _mesa_debug(ctx, "texcoord[%d] %f %f %f %f\n", i, |
||
928 | v->attrib[VARYING_SLOT_TEX0 + i][0], |
||
929 | v->attrib[VARYING_SLOT_TEX0 + i][1], |
||
930 | v->attrib[VARYING_SLOT_TEX0 + i][2], |
||
931 | v->attrib[VARYING_SLOT_TEX0 + i][3]); |
||
932 | |||
933 | #if CHAN_TYPE == GL_FLOAT |
||
934 | _mesa_debug(ctx, "color %f %f %f %f\n", |
||
935 | v->color[0], v->color[1], v->color[2], v->color[3]); |
||
936 | #else |
||
937 | _mesa_debug(ctx, "color %d %d %d %d\n", |
||
938 | v->color[0], v->color[1], v->color[2], v->color[3]); |
||
939 | #endif |
||
940 | _mesa_debug(ctx, "spec %g %g %g %g\n", |
||
941 | v->attrib[VARYING_SLOT_COL1][0], |
||
942 | v->attrib[VARYING_SLOT_COL1][1], |
||
943 | v->attrib[VARYING_SLOT_COL1][2], |
||
944 | v->attrib[VARYING_SLOT_COL1][3]); |
||
945 | _mesa_debug(ctx, "fog %f\n", v->attrib[VARYING_SLOT_FOGC][0]); |
||
946 | _mesa_debug(ctx, "index %f\n", v->attrib[VARYING_SLOT_CI][0]); |
||
947 | _mesa_debug(ctx, "pointsize %f\n", v->pointSize); |
||
948 | _mesa_debug(ctx, "\n"); |
||
949 | } |
||
950 | }>>>=>><>=>><>=>><>=>=>=>=>>><>>>><>>>>>>> |