Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5564 | 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 | |||
25 | |||
26 | /** |
||
27 | * \file state.c |
||
28 | * State management. |
||
29 | * |
||
30 | * This file manages recalculation of derived values in struct gl_context. |
||
31 | */ |
||
32 | |||
33 | |||
34 | #include "glheader.h" |
||
35 | #include "mtypes.h" |
||
36 | #include "arrayobj.h" |
||
37 | #include "context.h" |
||
38 | #include "debug.h" |
||
39 | #include "macros.h" |
||
40 | #include "ffvertex_prog.h" |
||
41 | #include "framebuffer.h" |
||
42 | #include "light.h" |
||
43 | #include "matrix.h" |
||
44 | #include "pixel.h" |
||
45 | #include "program/program.h" |
||
46 | #include "program/prog_parameter.h" |
||
47 | #include "shaderobj.h" |
||
48 | #include "state.h" |
||
49 | #include "stencil.h" |
||
50 | #include "texenvprogram.h" |
||
51 | #include "texobj.h" |
||
52 | #include "texstate.h" |
||
53 | #include "varray.h" |
||
54 | #include "viewport.h" |
||
55 | #include "blend.h" |
||
56 | |||
57 | |||
58 | /** |
||
59 | * Update the following fields: |
||
60 | * ctx->VertexProgram._Enabled |
||
61 | * ctx->FragmentProgram._Enabled |
||
62 | * ctx->ATIFragmentShader._Enabled |
||
63 | * This needs to be done before texture state validation. |
||
64 | */ |
||
65 | static void |
||
66 | update_program_enables(struct gl_context *ctx) |
||
67 | { |
||
68 | /* These _Enabled flags indicate if the user-defined ARB/NV vertex/fragment |
||
69 | * program is enabled AND valid. Similarly for ATI fragment shaders. |
||
70 | * GLSL shaders not relevant here. |
||
71 | */ |
||
72 | ctx->VertexProgram._Enabled = ctx->VertexProgram.Enabled |
||
73 | && ctx->VertexProgram.Current->Base.Instructions; |
||
74 | ctx->FragmentProgram._Enabled = ctx->FragmentProgram.Enabled |
||
75 | && ctx->FragmentProgram.Current->Base.Instructions; |
||
76 | ctx->ATIFragmentShader._Enabled = ctx->ATIFragmentShader.Enabled |
||
77 | && ctx->ATIFragmentShader.Current->Instructions[0]; |
||
78 | } |
||
79 | |||
80 | |||
81 | /** |
||
82 | * Update the ctx->Vertex/Geometry/FragmentProgram._Current pointers to point |
||
83 | * to the current/active programs. Then call ctx->Driver.BindProgram() to |
||
84 | * tell the driver which programs to use. |
||
85 | * |
||
86 | * Programs may come from 3 sources: GLSL shaders, ARB/NV_vertex/fragment |
||
87 | * programs or programs derived from fixed-function state. |
||
88 | * |
||
89 | * This function needs to be called after texture state validation in case |
||
90 | * we're generating a fragment program from fixed-function texture state. |
||
91 | * |
||
92 | * \return bitfield which will indicate _NEW_PROGRAM state if a new vertex |
||
93 | * or fragment program is being used. |
||
94 | */ |
||
95 | static GLbitfield |
||
96 | update_program(struct gl_context *ctx) |
||
97 | { |
||
98 | const struct gl_shader_program *vsProg = |
||
99 | ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX]; |
||
100 | const struct gl_shader_program *gsProg = |
||
101 | ctx->_Shader->CurrentProgram[MESA_SHADER_GEOMETRY]; |
||
102 | struct gl_shader_program *fsProg = |
||
103 | ctx->_Shader->CurrentProgram[MESA_SHADER_FRAGMENT]; |
||
104 | const struct gl_shader_program *csProg = |
||
105 | ctx->_Shader->CurrentProgram[MESA_SHADER_COMPUTE]; |
||
106 | const struct gl_vertex_program *prevVP = ctx->VertexProgram._Current; |
||
107 | const struct gl_fragment_program *prevFP = ctx->FragmentProgram._Current; |
||
108 | const struct gl_geometry_program *prevGP = ctx->GeometryProgram._Current; |
||
109 | const struct gl_compute_program *prevCP = ctx->ComputeProgram._Current; |
||
110 | GLbitfield new_state = 0x0; |
||
111 | |||
112 | /* |
||
113 | * Set the ctx->VertexProgram._Current and ctx->FragmentProgram._Current |
||
114 | * pointers to the programs that should be used for rendering. If either |
||
115 | * is NULL, use fixed-function code paths. |
||
116 | * |
||
117 | * These programs may come from several sources. The priority is as |
||
118 | * follows: |
||
119 | * 1. OpenGL 2.0/ARB vertex/fragment shaders |
||
120 | * 2. ARB/NV vertex/fragment programs |
||
121 | * 3. Programs derived from fixed-function state. |
||
122 | * |
||
123 | * Note: it's possible for a vertex shader to get used with a fragment |
||
124 | * program (and vice versa) here, but in practice that shouldn't ever |
||
125 | * come up, or matter. |
||
126 | */ |
||
127 | |||
128 | if (fsProg && fsProg->LinkStatus |
||
129 | && fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]) { |
||
130 | /* Use GLSL fragment shader */ |
||
131 | _mesa_reference_shader_program(ctx, |
||
132 | &ctx->_Shader->_CurrentFragmentProgram, |
||
133 | fsProg); |
||
134 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, |
||
135 | gl_fragment_program(fsProg->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); |
||
136 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, |
||
137 | NULL); |
||
138 | } |
||
139 | else if (ctx->FragmentProgram._Enabled) { |
||
140 | /* Use user-defined fragment program */ |
||
141 | _mesa_reference_shader_program(ctx, |
||
142 | &ctx->_Shader->_CurrentFragmentProgram, |
||
143 | NULL); |
||
144 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, |
||
145 | ctx->FragmentProgram.Current); |
||
146 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, |
||
147 | NULL); |
||
148 | } |
||
149 | else if (ctx->FragmentProgram._MaintainTexEnvProgram) { |
||
150 | /* Use fragment program generated from fixed-function state */ |
||
151 | struct gl_shader_program *f = _mesa_get_fixed_func_fragment_program(ctx); |
||
152 | |||
153 | _mesa_reference_shader_program(ctx, |
||
154 | &ctx->_Shader->_CurrentFragmentProgram, |
||
155 | f); |
||
156 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, |
||
157 | gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); |
||
158 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, |
||
159 | gl_fragment_program(f->_LinkedShaders[MESA_SHADER_FRAGMENT]->Program)); |
||
160 | } |
||
161 | else { |
||
162 | /* No fragment program */ |
||
163 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._Current, NULL); |
||
164 | _mesa_reference_fragprog(ctx, &ctx->FragmentProgram._TexEnvProgram, |
||
165 | NULL); |
||
166 | } |
||
167 | |||
168 | if (gsProg && gsProg->LinkStatus |
||
169 | && gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]) { |
||
170 | /* Use GLSL geometry shader */ |
||
171 | _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, |
||
172 | gl_geometry_program(gsProg->_LinkedShaders[MESA_SHADER_GEOMETRY]->Program)); |
||
173 | } else { |
||
174 | /* No geometry program */ |
||
175 | _mesa_reference_geomprog(ctx, &ctx->GeometryProgram._Current, NULL); |
||
176 | } |
||
177 | |||
178 | /* Examine vertex program after fragment program as |
||
179 | * _mesa_get_fixed_func_vertex_program() needs to know active |
||
180 | * fragprog inputs. |
||
181 | */ |
||
182 | if (vsProg && vsProg->LinkStatus |
||
183 | && vsProg->_LinkedShaders[MESA_SHADER_VERTEX]) { |
||
184 | /* Use GLSL vertex shader */ |
||
185 | _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, |
||
186 | gl_vertex_program(vsProg->_LinkedShaders[MESA_SHADER_VERTEX]->Program)); |
||
187 | } |
||
188 | else if (ctx->VertexProgram._Enabled) { |
||
189 | /* Use user-defined vertex program */ |
||
190 | _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, |
||
191 | ctx->VertexProgram.Current); |
||
192 | } |
||
193 | else if (ctx->VertexProgram._MaintainTnlProgram) { |
||
194 | /* Use vertex program generated from fixed-function state */ |
||
195 | _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, |
||
196 | _mesa_get_fixed_func_vertex_program(ctx)); |
||
197 | _mesa_reference_vertprog(ctx, &ctx->VertexProgram._TnlProgram, |
||
198 | ctx->VertexProgram._Current); |
||
199 | } |
||
200 | else { |
||
201 | /* no vertex program */ |
||
202 | _mesa_reference_vertprog(ctx, &ctx->VertexProgram._Current, NULL); |
||
203 | } |
||
204 | |||
205 | if (csProg && csProg->LinkStatus |
||
206 | && csProg->_LinkedShaders[MESA_SHADER_COMPUTE]) { |
||
207 | /* Use GLSL compute shader */ |
||
208 | _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, |
||
209 | gl_compute_program(csProg->_LinkedShaders[MESA_SHADER_COMPUTE]->Program)); |
||
210 | } else { |
||
211 | /* no compute program */ |
||
212 | _mesa_reference_compprog(ctx, &ctx->ComputeProgram._Current, NULL); |
||
213 | } |
||
214 | |||
215 | /* Let the driver know what's happening: |
||
216 | */ |
||
217 | if (ctx->FragmentProgram._Current != prevFP) { |
||
218 | new_state |= _NEW_PROGRAM; |
||
219 | if (ctx->Driver.BindProgram) { |
||
220 | ctx->Driver.BindProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, |
||
221 | (struct gl_program *) ctx->FragmentProgram._Current); |
||
222 | } |
||
223 | } |
||
224 | |||
225 | if (ctx->GeometryProgram._Current != prevGP) { |
||
226 | new_state |= _NEW_PROGRAM; |
||
227 | if (ctx->Driver.BindProgram) { |
||
228 | ctx->Driver.BindProgram(ctx, MESA_GEOMETRY_PROGRAM, |
||
229 | (struct gl_program *) ctx->GeometryProgram._Current); |
||
230 | } |
||
231 | } |
||
232 | |||
233 | if (ctx->VertexProgram._Current != prevVP) { |
||
234 | new_state |= _NEW_PROGRAM; |
||
235 | if (ctx->Driver.BindProgram) { |
||
236 | ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, |
||
237 | (struct gl_program *) ctx->VertexProgram._Current); |
||
238 | } |
||
239 | } |
||
240 | |||
241 | if (ctx->ComputeProgram._Current != prevCP) { |
||
242 | new_state |= _NEW_PROGRAM; |
||
243 | if (ctx->Driver.BindProgram) { |
||
244 | ctx->Driver.BindProgram(ctx, GL_COMPUTE_PROGRAM_NV, |
||
245 | (struct gl_program *) ctx->ComputeProgram._Current); |
||
246 | } |
||
247 | } |
||
248 | |||
249 | return new_state; |
||
250 | } |
||
251 | |||
252 | |||
253 | /** |
||
254 | * Examine shader constants and return either _NEW_PROGRAM_CONSTANTS or 0. |
||
255 | */ |
||
256 | static GLbitfield |
||
257 | update_program_constants(struct gl_context *ctx) |
||
258 | { |
||
259 | GLbitfield new_state = 0x0; |
||
260 | |||
261 | if (ctx->FragmentProgram._Current) { |
||
262 | const struct gl_program_parameter_list *params = |
||
263 | ctx->FragmentProgram._Current->Base.Parameters; |
||
264 | if (params && params->StateFlags & ctx->NewState) { |
||
265 | new_state |= _NEW_PROGRAM_CONSTANTS; |
||
266 | } |
||
267 | } |
||
268 | |||
269 | if (ctx->GeometryProgram._Current) { |
||
270 | const struct gl_program_parameter_list *params = |
||
271 | ctx->GeometryProgram._Current->Base.Parameters; |
||
272 | /*FIXME: StateFlags is always 0 because we have unnamed constant |
||
273 | * not state changes */ |
||
274 | if (params /*&& params->StateFlags & ctx->NewState*/) { |
||
275 | new_state |= _NEW_PROGRAM_CONSTANTS; |
||
276 | } |
||
277 | } |
||
278 | |||
279 | if (ctx->VertexProgram._Current) { |
||
280 | const struct gl_program_parameter_list *params = |
||
281 | ctx->VertexProgram._Current->Base.Parameters; |
||
282 | if (params && params->StateFlags & ctx->NewState) { |
||
283 | new_state |= _NEW_PROGRAM_CONSTANTS; |
||
284 | } |
||
285 | } |
||
286 | |||
287 | return new_state; |
||
288 | } |
||
289 | |||
290 | |||
291 | |||
292 | |||
293 | /** |
||
294 | * Update the ctx->Polygon._FrontBit flag. |
||
295 | */ |
||
296 | static void |
||
297 | update_frontbit(struct gl_context *ctx) |
||
298 | { |
||
299 | if (ctx->Transform.ClipOrigin == GL_LOWER_LEFT) |
||
300 | ctx->Polygon._FrontBit = (ctx->Polygon.FrontFace == GL_CW); |
||
301 | else |
||
302 | ctx->Polygon._FrontBit = (ctx->Polygon.FrontFace == GL_CCW); |
||
303 | } |
||
304 | |||
305 | |||
306 | /** |
||
307 | * Update derived multisample state. |
||
308 | */ |
||
309 | static void |
||
310 | update_multisample(struct gl_context *ctx) |
||
311 | { |
||
312 | ctx->Multisample._Enabled = GL_FALSE; |
||
313 | if (ctx->Multisample.Enabled && |
||
314 | ctx->DrawBuffer && |
||
315 | ctx->DrawBuffer->Visual.sampleBuffers) |
||
316 | ctx->Multisample._Enabled = GL_TRUE; |
||
317 | } |
||
318 | |||
319 | |||
320 | /** |
||
321 | * Update the ctx->VertexProgram._TwoSideEnabled flag. |
||
322 | */ |
||
323 | static void |
||
324 | update_twoside(struct gl_context *ctx) |
||
325 | { |
||
326 | if (ctx->_Shader->CurrentProgram[MESA_SHADER_VERTEX] || |
||
327 | ctx->VertexProgram._Enabled) { |
||
328 | ctx->VertexProgram._TwoSideEnabled = ctx->VertexProgram.TwoSideEnabled; |
||
329 | } else { |
||
330 | ctx->VertexProgram._TwoSideEnabled = (ctx->Light.Enabled && |
||
331 | ctx->Light.Model.TwoSide); |
||
332 | } |
||
333 | } |
||
334 | |||
335 | |||
336 | /** |
||
337 | * Compute derived GL state. |
||
338 | * If __struct gl_contextRec::NewState is non-zero then this function \b must |
||
339 | * be called before rendering anything. |
||
340 | * |
||
341 | * Calls dd_function_table::UpdateState to perform any internal state |
||
342 | * management necessary. |
||
343 | * |
||
344 | * \sa _mesa_update_modelview_project(), _mesa_update_texture(), |
||
345 | * _mesa_update_buffer_bounds(), |
||
346 | * _mesa_update_lighting() and _mesa_update_tnl_spaces(). |
||
347 | */ |
||
348 | void |
||
349 | _mesa_update_state_locked( struct gl_context *ctx ) |
||
350 | { |
||
351 | GLbitfield new_state = ctx->NewState; |
||
352 | GLbitfield prog_flags = _NEW_PROGRAM; |
||
353 | GLbitfield new_prog_state = 0x0; |
||
354 | |||
355 | if (new_state == _NEW_CURRENT_ATTRIB) |
||
356 | goto out; |
||
357 | |||
358 | if (MESA_VERBOSE & VERBOSE_STATE) |
||
359 | _mesa_print_state("_mesa_update_state", new_state); |
||
360 | |||
361 | /* Determine which state flags effect vertex/fragment program state */ |
||
362 | if (ctx->FragmentProgram._MaintainTexEnvProgram) { |
||
363 | prog_flags |= (_NEW_BUFFERS | _NEW_TEXTURE | _NEW_FOG | |
||
364 | _NEW_VARYING_VP_INPUTS | _NEW_LIGHT | _NEW_POINT | |
||
365 | _NEW_RENDERMODE | _NEW_PROGRAM | _NEW_FRAG_CLAMP | |
||
366 | _NEW_COLOR); |
||
367 | } |
||
368 | if (ctx->VertexProgram._MaintainTnlProgram) { |
||
369 | prog_flags |= (_NEW_VARYING_VP_INPUTS | _NEW_TEXTURE | |
||
370 | _NEW_TEXTURE_MATRIX | _NEW_TRANSFORM | _NEW_POINT | |
||
371 | _NEW_FOG | _NEW_LIGHT | |
||
372 | _MESA_NEW_NEED_EYE_COORDS); |
||
373 | } |
||
374 | |||
375 | /* |
||
376 | * Now update derived state info |
||
377 | */ |
||
378 | |||
379 | if (new_state & prog_flags) |
||
380 | update_program_enables( ctx ); |
||
381 | |||
382 | if (new_state & (_NEW_MODELVIEW|_NEW_PROJECTION)) |
||
383 | _mesa_update_modelview_project( ctx, new_state ); |
||
384 | |||
385 | if (new_state & (_NEW_PROGRAM|_NEW_TEXTURE|_NEW_TEXTURE_MATRIX)) |
||
386 | _mesa_update_texture( ctx, new_state ); |
||
387 | |||
388 | if (new_state & _NEW_POLYGON) |
||
389 | update_frontbit( ctx ); |
||
390 | |||
391 | if (new_state & _NEW_BUFFERS) |
||
392 | _mesa_update_framebuffer(ctx, ctx->ReadBuffer, ctx->DrawBuffer); |
||
393 | |||
394 | if (new_state & (_NEW_SCISSOR | _NEW_BUFFERS | _NEW_VIEWPORT)) |
||
395 | _mesa_update_draw_buffer_bounds(ctx, ctx->DrawBuffer); |
||
396 | |||
397 | if (new_state & _NEW_LIGHT) |
||
398 | _mesa_update_lighting( ctx ); |
||
399 | |||
400 | if (new_state & (_NEW_LIGHT | _NEW_PROGRAM)) |
||
401 | update_twoside( ctx ); |
||
402 | |||
403 | if (new_state & (_NEW_STENCIL | _NEW_BUFFERS)) |
||
404 | _mesa_update_stencil( ctx ); |
||
405 | |||
406 | if (new_state & _NEW_PIXEL) |
||
407 | _mesa_update_pixel( ctx, new_state ); |
||
408 | |||
409 | if (new_state & (_NEW_MULTISAMPLE | _NEW_BUFFERS)) |
||
410 | update_multisample( ctx ); |
||
411 | |||
412 | /* ctx->_NeedEyeCoords is now up to date. |
||
413 | * |
||
414 | * If the truth value of this variable has changed, update for the |
||
415 | * new lighting space and recompute the positions of lights and the |
||
416 | * normal transform. |
||
417 | * |
||
418 | * If the lighting space hasn't changed, may still need to recompute |
||
419 | * light positions & normal transforms for other reasons. |
||
420 | */ |
||
421 | if (new_state & _MESA_NEW_NEED_EYE_COORDS) |
||
422 | _mesa_update_tnl_spaces( ctx, new_state ); |
||
423 | |||
424 | if (new_state & prog_flags) { |
||
425 | /* When we generate programs from fixed-function vertex/fragment state |
||
426 | * this call may generate/bind a new program. If so, we need to |
||
427 | * propogate the _NEW_PROGRAM flag to the driver. |
||
428 | */ |
||
429 | new_prog_state |= update_program( ctx ); |
||
430 | } |
||
431 | |||
432 | if (new_state & _NEW_ARRAY) |
||
433 | _mesa_update_vao_client_arrays(ctx, ctx->Array.VAO); |
||
434 | |||
435 | out: |
||
436 | new_prog_state |= update_program_constants(ctx); |
||
437 | |||
438 | /* |
||
439 | * Give the driver a chance to act upon the new_state flags. |
||
440 | * The driver might plug in different span functions, for example. |
||
441 | * Also, this is where the driver can invalidate the state of any |
||
442 | * active modules (such as swrast_setup, swrast, tnl, etc). |
||
443 | * |
||
444 | * Set ctx->NewState to zero to avoid recursion if |
||
445 | * Driver.UpdateState() has to call FLUSH_VERTICES(). (fixed?) |
||
446 | */ |
||
447 | new_state = ctx->NewState | new_prog_state; |
||
448 | ctx->NewState = 0; |
||
449 | ctx->Driver.UpdateState(ctx, new_state); |
||
450 | ctx->Array.VAO->NewArrays = 0x0; |
||
451 | } |
||
452 | |||
453 | |||
454 | /* This is the usual entrypoint for state updates: |
||
455 | */ |
||
456 | void |
||
457 | _mesa_update_state( struct gl_context *ctx ) |
||
458 | { |
||
459 | _mesa_lock_context_textures(ctx); |
||
460 | _mesa_update_state_locked(ctx); |
||
461 | _mesa_unlock_context_textures(ctx); |
||
462 | } |
||
463 | |||
464 | |||
465 | |||
466 | |||
467 | /** |
||
468 | * Want to figure out which fragment program inputs are actually |
||
469 | * constant/current values from ctx->Current. These should be |
||
470 | * referenced as a tracked state variable rather than a fragment |
||
471 | * program input, to save the overhead of putting a constant value in |
||
472 | * every submitted vertex, transferring it to hardware, interpolating |
||
473 | * it across the triangle, etc... |
||
474 | * |
||
475 | * When there is a VP bound, just use vp->outputs. But when we're |
||
476 | * generating vp from fixed function state, basically want to |
||
477 | * calculate: |
||
478 | * |
||
479 | * vp_out_2_fp_in( vp_in_2_vp_out( varying_inputs ) | |
||
480 | * potential_vp_outputs ) |
||
481 | * |
||
482 | * Where potential_vp_outputs is calculated by looking at enabled |
||
483 | * texgen, etc. |
||
484 | * |
||
485 | * The generated fragment program should then only declare inputs that |
||
486 | * may vary or otherwise differ from the ctx->Current values. |
||
487 | * Otherwise, the fp should track them as state values instead. |
||
488 | */ |
||
489 | void |
||
490 | _mesa_set_varying_vp_inputs( struct gl_context *ctx, |
||
491 | GLbitfield64 varying_inputs ) |
||
492 | { |
||
493 | if (ctx->varying_vp_inputs != varying_inputs) { |
||
494 | ctx->varying_vp_inputs = varying_inputs; |
||
495 | |||
496 | /* Only the fixed-func generated programs need to use the flag |
||
497 | * and the fixed-func fragment program uses it only if there is also |
||
498 | * a fixed-func vertex program, so this only depends on the latter. |
||
499 | * |
||
500 | * It's okay to check the VP pointer here, because this is called after |
||
501 | * _mesa_update_state in the vbo module. */ |
||
502 | if (ctx->VertexProgram._TnlProgram || |
||
503 | ctx->FragmentProgram._TexEnvProgram) { |
||
504 | ctx->NewState |= _NEW_VARYING_VP_INPUTS; |
||
505 | } |
||
506 | /*printf("%s %x\n", __func__, varying_inputs);*/ |
||
507 | } |
||
508 | } |
||
509 | |||
510 | |||
511 | /** |
||
512 | * Used by drivers to tell core Mesa that the driver is going to |
||
513 | * install/ use its own vertex program. In particular, this will |
||
514 | * prevent generated fragment programs from using state vars instead |
||
515 | * of ordinary varyings/inputs. |
||
516 | */ |
||
517 | void |
||
518 | _mesa_set_vp_override(struct gl_context *ctx, GLboolean flag) |
||
519 | { |
||
520 | if (ctx->VertexProgram._Overriden != flag) { |
||
521 | ctx->VertexProgram._Overriden = flag; |
||
522 | |||
523 | /* Set one of the bits which will trigger fragment program |
||
524 | * regeneration: |
||
525 | */ |
||
526 | ctx->NewState |= _NEW_PROGRAM; |
||
527 | } |
||
528 | } |