VTK
vtkOpenGLStateCache.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkOpenGLStateCache.h
5 
6  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7  All rights reserved.
8  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10  This software is distributed WITHOUT ANY WARRANTY; without even
11  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12  PURPOSE. See the above copyright notice for more information.
13 
14 =========================================================================*/
23 #ifndef VTK_IMPLEMENT_MESA_CXX
24 # include "vtkOpenGL.h" // Needed for GL api types.
25 #endif
26 
27 #define vtkOpenGLCall_glEnable vtkOpenGLStateCache::CurrentGLCache->glEnable
28 #define vtkOpenGLCall_glDisable vtkOpenGLStateCache::CurrentGLCache->glDisable
29 #define vtkOpenGLCall_glAlphaFunc vtkOpenGLStateCache::CurrentGLCache->glAlphaFunc
30 #define vtkOpenGLCall_glBlendFunc vtkOpenGLStateCache::CurrentGLCache->glBlendFunc
31 #define vtkOpenGLCall_glDepthFunc vtkOpenGLStateCache::CurrentGLCache->glDepthFunc
32 #define vtkOpenGLCall_glTexEnvf vtkOpenGLStateCache::CurrentGLCache->glTexEnvf
33 #define vtkOpenGLCall_glLightModeli vtkOpenGLStateCache::CurrentGLCache->glLightModeli
34 #define vtkOpenGLCall_glLightModelfv vtkOpenGLStateCache::CurrentGLCache->glLightMOdelfv
35 #define vtkOpenGLCall_glLightfv vtkOpenGLStateCache::CurrentGLCache->glLightfv
36 #define vtkOpenGLCall_glLightf vtkOpenGLStateCache::CurrentGLCache->glLightf
37 #define vtkOpenGLCall_glLighti vtkOpenGLStateCache::CurrentGLCache->glLighti
38 #define vtkOpenGLCall_glMaterialfv vtkOpenGLStateCache::CurrentGLCache->glMaterialfv
39 #define vtkOpenGLCall_glShadeModel vtkOpenGLStateCache::CurrentGLCache->glShadeModel
40 #define vtkOpenGLCall_glClearColor vtkOpenGLStateCache::CurrentGLCache->glClearColor
41 #define vtkOpenGLCall_glClearDepth vtkOpenGLStateCache::CurrentGLCache->glClearDepth
42 #define vtkOpenGLCall_glDepthMask vtkOpenGLStateCache::CurrentGLCache->glDepthMask
43 #define vtkOpenGLCall_glCullFace vtkOpenGLStateCache::CurrentGLCache->glCullFace
44 #define vtkOpenGLCall_glClear vtkOpenGLStateCache::CurrentGLCache->glClear
45 #define vtkOpenGLCall_glDrawBuffer vtkOpenGLStateCache::CurrentGLCache->glDrawBuffer
46 #define vtkOpenGLCall_glMatrixMode vtkOpenGLStateCache::CurrentGLCache->glMatrixMode
47 #define vtkOpenGLCall_glViewport vtkOpenGLStateCache::CurrentGLCache->glViewport
48 #define vtkOpenGLCall_glScissor vtkOpenGLStateCache::CurrentGLCache->glScissor
49 #define vtkOpenGLCall_glClipPlane vtkOpenGLStateCache::CurrentGLCache->glClipPlane
50 #define vtkOpenGLCall_glColorMaterial vtkOpenGLStateCache::CurrentGLCache->glColorMaterial
51 #define vtkOpenGLCall_glPointSize vtkOpenGLStateCache::CurrentGLCache->glPointSize
52 #define vtkOpenGLCall_glLineWidth vtkOpenGLStateCache::CurrentGLCache->glLineWidth
53 #define vtkOpenGLCall_glLineStipple vtkOpenGLStateCache::CurrentGLCache->glLineStipple
54 #define vtkOpenGLCall_glDepthRange vtkOpenGLStateCache::CurrentGLCache->glDepthRange
55 #define vtkOpenGLCall_glPolygonOffset vtkOpenGLStateCache::CurrentGLCache->glPolygonOffset
56 
57 #define vtkOpenGLCall_glPushMatrix glPushMatrix
58 #define vtkOpenGLCall_glPopMatrix glPopMatrix
59 #define vtkOpenGLCall_glMultMatrixd glMultMatrixd
60 #define vtkOpenGLCall_glLoadMatrixd glLoadMatrixd
61 #define vtkOpenGLCall_glLoadIdentity glLoadIdentity
62 #define vtkOpenGLCall_glSelectBuffer glSelectBuffer
63 #define vtkOpenGLCall_glRenderMode glRenderMode
64 #define vtkOpenGLCall_glInitNames glInitNames
65 #define vtkOpenGLCall_glPushName glPushName
66 #define vtkOpenGLCall_glLoadName glLoadName
67 #define vtkOpenGLCall_glGetIntegerv glGetIntegerv
68 #define vtkOpenGLCall_glIsTexture glIsTexture
69 #define vtkOpenGLCall_glDeleteTextures glDeleteTexture
70 #define vtkOpenGLCall_glGenTextures glGenTextures
71 #define vtkOpenGLCall_glBindTexture glBindTexture
72 #define vtkOpenGLCall_glTexParameterf glTextParameterf
73 #define vtkOpenGLCall_glTexCoord2fv glTexCoord2fv
74 #define vtkOpenGLCall_glVertex3fv glVertex3fv
75 #define vtkOpenGLCall_glNormal3fv glNormal3fv
76 #define vtkOpenGLCall_glColor3f glColor3f
77 #define vtkOpenGLCall_glColor4ubv glColor4ubv
78 #define vtkOpenGLCall_glColor4fv glColor4fv
79 #define vtkOpenGLCall_glBegin glBegin
80 #define vtkOpenGLCall_glEnd glEnd
81 #define vtkOpenGLCall_glTexImage2D glTextImage2D
82 #define vtkOpenGLCall_glDeleteLists glDeleteLists
83 #define vtkOpenGLCall_glIsList glIsList
84 #define vtkOpenGLCall_glGenLists glGenLists
85 #define vtkOpenGLCall_glCallList glCallList
86 #define vtkOpenGLCall_glReadBuffer glReadBuffer
87 #define vtkOpenGLCall_glPixelStorei glPixelStorei
88 #define vtkOpenGLCall_glReadPixels glReadPixels
89 #define vtkOpenGLCall_glRasterPos3f glRasterPos3f
90 #define vtkOpenGLCall_glDrawPixels glDrawPixels
91 #define vtkOpenGLCall_glRasterPos2f glRasterPos2f
92 #define vtkOpenGLCall_glNewList glNewList
93 #define vtkOpenGLCall_glEndList glEndList
94 
96 {
97 public:
98  static vtkOpenGLStateCache *CurrentGLCache; // recursive definition
99 
100  vtkOpenGLStateCache(); // set all members to initial values
101  ~vtkOpenGLStateCache(); // delete any dynamic objects
102  void Initialize();
103 
104  // GL_BLEND = 0x0BE2
105  // GL_POINT_SMOOTH = 0x0B10
106  // GL_LINE_SMOOTH = 0x0B20
107  // GL_POLYGON_SMOOTH= 0x0B41
108  // GL_DEPTH_TEST = 0x0B71
109  // GL_ALPHA_TEST = 0x0BC0
110  // GL_TEXTURE_2D = 0x0DE1
111  // GL_CLIP_PLANE0+i = 0x3000
112  // GL_LIGHTING = 0x0B50
113  // GL_COLOR_MATERIAL= 0x0B57
114  // GL_NORMALIZE = 0x0BA1
115  // GL_CULL_FACE = 0x0B44
116  // GL_SCISSOR_TEST = 0x0C11
117  // GL_POLYGON_OFFSET_FILL = 0x8037
118  // GL_LINE_STIPPLE = 0x0B24
119  // GL_LIGHT+i = 0x4000
120  char Enable_buckets[0xDE1-0xB10+1]; // 0xB10-0xDE1
121  char Enable_GL_LIGHT_buckets[8]; // 0x4000 + i (0<i<8)
122  char Enable_GL_CLIP_PLANE_buckets[8]; // 0x8000 + i (0<i<8)
123  /* Need to have special handling for disabling and enabling the
124  GL_LIGHT's because they are disabling too many lights!
125  need to propagate in how many lights are actually *on*
126  and only apply the op to them.
127  */
128  inline void glEnable(GLenum e)
129  {
130  register int ex;
131  register char *val=0;
132  if(e&0x4000)
133  {
134  ex=e-0x4000;
135  if(ex<8) {val=Enable_GL_LIGHT_buckets+ex; }
136  }
137  else
138  {
139  if(e&0x8000)
140  {
141  ex=e-0x8000;
142  if(ex<8) { val=Enable_GL_CLIP_PLANE_buckets+ex; }
143  }
144  else
145  {
146  if(e>=0xB10 && e<=0xDE1)
147  {
148  ex=e-0xB10;
149  val=Enable_buckets+ex;
150  }
151  else
152  {
153  printf("Error: glEnable of 0x%X failed\n",e);
154  }
155  }
156  }
157  if(val && *val!=1)
158  {
159  *val=1;
160  ::glEnable(e);
161  }
162  }
163  inline void glDisable(GLenum e)
164  {
165  register int ex;
166  register char *val=0;
167  if(e&0x4000)
168  {
169  ex=e-0x4000;
170  if(ex<8) { val=Enable_GL_LIGHT_buckets+ex; }
171  }
172  else
173  {
174  if(e&0x8000)
175  {
176  ex=e-0x8000;
177  if(ex<8) { val=Enable_GL_CLIP_PLANE_buckets+ex; }
178  }
179  else
180  {
181  if(e>=0xB10 && e<=0xDE1)
182  {
183  ex=e-0xB10;
184  val=Enable_buckets+ex;
185  }
186  else
187  {
188  printf("Error: glEnable of 0x%X failed\n",e);
189  }
190  }
191  }
192  if(val && *val!=0)
193  {
194  *val=0;
195  ::glDisable(e);
196  }
197  }
198 
199  // GL_GREATER = 0x0204, (GLclampf) 0
201  inline void glAlphaFunc(GLenum e,GLclampf cf)
202  {
203  if(e==GL_GREATER && cf!=AlphaFunc_bucket)
204  {
205  AlphaFunc_bucket=cf;
206  ::glAlphaFunc(e,cf);
207  }
208  }
209 
210  // GL_SRC_ALPHA = 0x0302, GL_ONE_MINUS_SRC_ALPHA = 0x0303
211  GLenum BlendFunc_bucket; // multibucket if any other blendfunc is used
212  inline void glBlendFunc(GLenum e,GLenum e1)
213  {
214  if(e==GL_SRC_ALPHA && e1!=BlendFunc_bucket)
215  {
216  BlendFunc_bucket=e1;
217  ::glBlendFunc(e,e1);
218  }
219  }
220 
221  // GL_GREATER = 0x0204
222  // GL_LESS = 0x0201
223  // GL_LEQUAL = 0x0203
225  inline void glDepthFunc(GLenum e)
226  {
227  if(e!=DepthFunc_bucket)
228  {
230  ::glDepthFunc(e);
231  }
232  }
233 
234  // GL_TEXTURE_ENV = 0x2300, GL_TEXTURE_ENV_MODE = 0x2200, GL_MODULATE = 0x2100
235  GLfloat TexEnvf_MODE_bucket; // total kludge right now
236  inline void glTexEnvf(GLenum e,GLenum e1,GLfloat f)
237  {
238  if(e==GL_TEXTURE_ENV && e1==GL_TEXTURE_ENV_MODE)
239  {
240  if(f!=TexEnvf_MODE_bucket)
241  {
243  ::glTexEnvf(e,e1,f);
244  }
245  }
246  }
247 
248  // GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE/FALSE
249  // GL_LIGHT_MODEL_TWO_SIDE, 0
250  GLint LightModeli_LIGHT_MODEL_TWO_SIDE_bucket; // shoudld check other modes
251  inline void glLightModeli(GLenum e,GLint i)
252  {
253  if(e==GL_LIGHT_MODEL_TWO_SIDE && i!=LightModeli_LIGHT_MODEL_TWO_SIDE_bucket){
255  ::glLightModeli(e,i);
256  }
257  }
258 
259  // GL_LIGHT_MODEL_AMBIENT, fvect(amb color), A=1.0
260  // GL_LIGHT_MODEL_AMBIENT = 0x0B53
262  inline void glLightModelfv(GLenum e,GLfloat *fv)
263  {
264  if(e==GL_LIGHT_MODEL_AMBIENT &&
271  ::glLightModelfv(e,fv);
272  }
273  }
274 
275  // light=GL_LIGHT index
276  // pname= lighting type
277  // GL_DIFFUSE = 0x1201
278  // GL_SPECULAR = 0x1202
279  // GL_POSITION = 0x1203
280  // GL_SPOT_DIRECTION = 0x1204
281  GLfloat Lightfv_buckets[8*4*8];
282  inline void glLightfv( GLenum light, GLenum pname, const GLfloat *params)
283  {
284  register GLfloat *val = Lightfv_buckets + ((((int)(pname-0x1201))|((int)(light-GL_LIGHT0)<<3))<<2);
285  if(params[0]!=val[0] ||
286  params[1]!=val[1] ||
287  params[2]!=val[2] ||
288  params[3]!=val[3])
289  {
290  val[0]=params[0];
291  val[1]=params[1];
292  val[2]=params[2];
293  val[3]=params[3];
294  ::glLightfv(light,pname,params);
295  }
296  }
297 
298  // light=GL_LIGHT index
299  // pname= lighting parameter
300  // GL_SPOT_EXPONENT = 0x1205
301  // GL_SPOT_CUTOFF = 0x1206
302  // GL_CONSTANT_ATTENUATION = 0x1207
303  // GL_LINEAR_ATTENUATION = 0x1208
304  // GL_QUADRATIC_ATTENUATION= 0x1209
305  GLfloat Lightf_buckets[8*8];
307  inline void glLightf( GLenum light, GLenum pname, GLfloat f){
308  register GLfloat *val=Lightf_buckets+(((int)(light-GL_LIGHT0)<<3)|((int)(pname-0x1205)));
309  if(val[0]!=f)
310  {
311  val[0]=f;
312  ::glLightf(light,pname,f);
313  if(pname==GL_SPOT_CUTOFF) // invalidate integer spot cutoff
314  Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]=-1;
315  }
316  }
317 
318  // light=GL_LIGHT index
319  // pname=lighting parameter
320  // GL_SPOT_CUTOFF = 0x1206
321  // needs to invalidate the float light cutoff
322  inline void glLighti( GLenum light, GLenum pname, GLint f)
323  {
324  if(pname==GL_SPOT_CUTOFF && f!=Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]){
325  Lighti_SPOT_CUTOFF_buckets[light-GL_LIGHT0]=f;
326  ::glLighti(light,pname,f);
327  // need to invalidate the float cutoff
328  Lightf_buckets[((int)(light-GL_LIGHT0)<<3)|0x02] = -1.0f;
329  }
330  }
331 
332  // Face, GL_AMBIENT, float Info[4]
333  // GL_FRONT = 0x0404
334  // GL_BACK = 0x0405
335  // GL_FRONT_AND_BACK = 0x0408
336  // GL_AMBIENT = 0x1200
337  // GL_DIFFUSE = 0x1201
338  // GL_SPECULAR = 0x1202
339  // GL_EMISSION = 0x1600
340  // GL_SHININESS = 0x1601
341  // GL_AMBIENT_AND_DIFFUSE = 0x1602
342  // GL_COLOR_INDEXES = 0x1603
343  GLfloat Materialfv_buckets[8*8*4];
344  inline void glMaterialfv(GLenum face, GLenum pname, const GLfloat *params )
345  {
346  register int idx;
347  register GLfloat *val;
348  if(pname>=0x1600)
349  {
350  idx=pname-0x1600 + 4; // put it just past the 120x buckets
351  }
352  else
353  {
354  idx=pname-0x1200;
355  }
356  // FRONT/BACK and FRONT_AND_BACK should do both.
357  // or perhaps should be a separate state key?
358  // For now, we will treat FRONT_AND_BACK independently
359  // because from a practical standpoint, that's how
360  // it tends to get used.
361  val = Materialfv_buckets + ((((face-0x0404)<<3)|idx)<<2);
362  if(val[0]!=params[0] ||
363  val[1]!=params[1] ||
364  val[2]!=params[2] ||
365  val[3]!=params[3])
366  {
367  val[0]=params[0];
368  val[1]=params[1];
369  val[2]=params[2];
370  val[3]=params[3];
371  ::glMaterialfv(face,pname,params);
372  }
373  }
374 
375  /*
376  a=0;
377  a|=(val[0]^params[0])
378  a|=(val[1]^params[1])
379  a|=(val[2]^params[2])
380  a|=(val[3]^params[3])
381  */
382  // GL_FLAT = 0x1D00
383  // GL_SMOOTH = 0x1D01
385  inline void glShadeModel(GLenum e)
386  {
387  if(ShadeModel_bucket!=e)
388  {
390  ::glShadeModel(e);
391  }
392  }
393 
394  GLclampf ClearColor_buckets[4];
395  inline void glClearColor(GLclampf r,GLclampf g,GLclampf b,GLclampf a)
396  {
397  register GLclampf *c=ClearColor_buckets;
398  if(c[0]!=r ||
399  c[1]!=g ||
400  c[2]!=b ||
401  c[3]!=a)
402  {
403  c[0]=r;
404  c[1]=g;
405  c[2]=b;
406  c[3]=a;
407  ::glClearColor(r,g,b,a);
408  }
409  }
410 
412  inline void glClearDepth(GLclampd d)
413  {
414  if(d!=ClearDepth_bucket)
415  {
417  ::glClearDepth(d);
418  }
419  }
420 
422  inline void glDepthMask(GLenum e)
423  {
424  if(DepthMask_bucket!=e)
425  {
427  ::glDepthMask(e);
428  }
429  }
430 
431  // GL_FRONT = 0x0404
432  // GL_BACK = 0x0405
434  inline void glCullFace(GLenum e)
435  {
436  if(CullFace_bucket!=e)
437  {
438  CullFace_bucket=e;
439  ::glCullFace(e);
440  }
441  }
442 
443  // well, lets go ahead and let it clear when it wants to
444  inline void glClear(GLbitfield b) { ::glClear(b);}
445  // GL_BACK_LEFT = 0x0402
446  // GL_BACK_RIGHT = 0x0403
447  // GL_FRONT = 0x0404
448  // GL_BACK = 0x0405
450  inline void glDrawBuffer(GLenum e) {
451  if(e!=DrawBuffer_bucket){
453  ::glDrawBuffer(e);
454  }
455  }
456  //============Matrix Ops (behave different for deferred ops)===
457  // GL_MODELVIEW=0x1700
458  // GL_PROJECTION=0x1701
460  inline void glMatrixMode(GLenum e) {
461  if(e!=MatrixMode_bucket){
463  ::glMatrixMode(e);
464  }
465  }
466 
467  GLint Viewport_bucket[4];
468  inline void glViewport(GLint llx,GLint lly,GLint u,GLint v){
469  register GLint *val=Viewport_bucket;
470  if(val[0]!=llx ||
471  val[1]!=lly ||
472  val[2]!=u ||
473  val[3]!=v){
474  val[0]=llx;
475  val[1]=lly;
476  val[2]=u;
477  val[3]=v;
478  ::glViewport(llx,lly,u,v);
479  }
480  }
481  // only needs to be called if scissor changes (and it usually won't)
482  GLint Scissor_bucket[4];
483  inline void glScissor(GLint llx,GLint lly,GLint u,GLint v){
484  register GLint *val=Scissor_bucket;
485  if(val[0]!=llx ||
486  val[1]!=lly ||
487  val[2]!=u ||
488  val[3]!=v){
489  val[0]=llx;
490  val[1]=lly;
491  val[2]=u;
492  val[3]=v;
493  ::glScissor(llx,lly,u,v);
494  }
495  }
496 
497  // what is the order of the clip plane eqn???
498  // GL_CLIP_PLANE0 = 0x3000
499  GLdouble ClipPlane_bucket[4*GL_MAX_CLIP_PLANES];
500  inline void glClipPlane(GLenum e,const GLdouble *eqn){
501  register GLdouble *val=ClipPlane_bucket + ((e-0x3000)<<2);
502  if(val[0]!=eqn[0] ||
503  val[1]!=eqn[1] ||
504  val[2]!=eqn[2] ||
505  val[3]!=eqn[3]){
506  val[0]=eqn[0];
507  val[1]=eqn[1];
508  val[2]=eqn[2];
509  val[3]=eqn[3];
510  ::glClipPlane(e,eqn);
511  }
512  }
513 
514  // face=
515  // GL_FRONT = 0x0404
516  // GL_BACK = 0x0405
517  // GL_FRONT_AND_BACK = 0x0408
519  inline void glColorMaterial(GLenum face,GLenum mode ){
520  register GLenum *val= ColorMaterial_bucket + (face-0x0404);
521  if(*val!=mode){
522  *val=mode;
523  ::glColorMaterial(face,mode);
524  }
525  }
527  inline void glPointSize(GLfloat f) {
528  if(f!=PointSize_bucket){
530  ::glPointSize(f);
531  }
532  }
534  inline void glLineWidth(GLfloat f){
535  if(f!=LineWidth_bucket){
537  ::glPointSize(f);
538  }
539  }
542  inline void glLineStipple(GLint factor, GLushort pattern )
543  {
544  if(factor!=LineStipple_FACTOR_bucket ||
546  {
549  ::glLineStipple(factor,pattern);
550  }
551  }
552 
555  inline void glDepthRange(GLclampd nearval,GLclampd farval )
556  {
557  if(DepthRange_NEAR_bucket!=nearval ||
558  DepthRange_FAR_bucket!=farval)
559  {
560  DepthRange_NEAR_bucket=nearval;
561  DepthRange_FAR_bucket=farval;
562  ::glDepthRange(nearval,farval);
563  }
564  }
565 
566 #ifdef GL_VERSION_1_1
567  // enable GL_POLYGON_OFFSET_FILL = 0x8037
568  GLfloat PolygonOffset_bucket[2];
569  inline void glPolygonOffset( GLfloat f,GLfloat u) {
570  if(PolygonOffset_bucket[0]!=f ||
571  PolygonOffset_bucket[1]!=u){
572  PolygonOffset_bucket[0]=f;
573  PolygonOffset_bucket[1]=u;
574  ::glPolygonOffset(f,u);
575  }
576  }
577 #endif
578 };
579 
580 
581 //#ifdef vtkOpenGLStateCache_Cache
582 //#undef vtkOpenGLStateCache_Cache
583 //#endif