Subversion Repositories Kolibri OS

Rev

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
}