VTK
vtkOpenGLContextDevice2DPrivate.h
Go to the documentation of this file.
1 /*=========================================================================
2 
3  Program: Visualization Toolkit
4  Module: vtkOpenGLContextDevice2DPrivate.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 =========================================================================*/
15 
32 #ifndef __vtkOpenGLContextDevice2DPrivate_h
33 #define __vtkOpenGLContextDevice2DPrivate_h
34 
36 
37 #include "vtkColor.h"
38 #include "vtkTextProperty.h"
39 #include "vtkFreeTypeTools.h"
40 #include <algorithm>
41 #include <list>
42 #include <utility>
43 
44 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by
45 // a unique key.
46 // .SECTION Description
47 // Creating and initializing a texture can be time consuming,
48 // vtkTextureImageCache offers the ability to reuse them as much as possible.
49 template <class Key>
51 {
52 public:
53  struct CacheData
54  {
57  };
58 
60 
61  struct CacheElement: public std::pair<Key, CacheData>
62  {
63  // Default constructor
65  : std::pair<Key, CacheData>(Key(), CacheData()){}
66  // Construct a partial CacheElement with no CacheData
67  // This can be used for temporary CacheElement used to search a given
68  // key into the cache list.
69  CacheElement(const Key& key)
70  : std::pair<Key, CacheData>(key, CacheData()){}
71  // Standard constructor of CacheElement
72  CacheElement(const Key& key, const CacheData& cacheData)
73  : std::pair<Key, CacheData>(key, cacheData){}
74  // Operator tuned to be used when searching into the cache list using
75  // std::find()
76  bool operator==(const CacheElement& other)const
77  {
78  // Here we cheat and make the comparison only on the key, this allows
79  // us to use std::find() to search for a given key.
80  return this->first == other.first;
81  }
82  };
84 
86 
89  {
90  this->MaxSize = 50;
91  }
93 
95 
97  bool IsKeyInCache(const Key& key)const
98  {
99  return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
100  }
102 
107  CacheData& GetCacheData(const Key& key);
108 
110 
113  {
114  typename std::list<CacheElement >::iterator it;
115  for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
116  {
117  it->second.Texture->ReleaseGraphicsResources(window);
118  }
119  }
121 
122 protected:
124 
126  CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
127  {
128  assert(!this->IsKeyInCache(key));
129  if (this->Cache.size() >= this->MaxSize)
130  {
131  this->Cache.pop_back();
132  }
133  this->Cache.push_front(CacheElement(key, cacheData));
134  return this->Cache.begin()->second;
135  }
137 
139  std::list<CacheElement > Cache;
141 
142  size_t MaxSize;
143 };
145 
146 template<class Key>
148 ::GetCacheData(const Key& key)
149 {
150  typename std::list<CacheElement>::iterator it =
151  std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
152  if (it != this->Cache.end())
153  {
154  return it->second;
155  }
156  CacheData cacheData;
159  cacheData.Texture->SetInputData(cacheData.ImageData);
160  return this->AddCacheData(key, cacheData);
161 }
162 
163 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text
164 // .SECTION Description
165 // Uniquely describe a pair of vtkTextProperty and text.
167 {
169 
170  static unsigned int GetIdFromTextProperty(vtkTextProperty* textProperty)
171  {
172  unsigned long id;
174  return static_cast<unsigned int>(id);
175  }
177 
179 
180  TextPropertyKey(vtkTextProperty* textProperty, const vtkStdString& text)
181  {
182  this->TextPropertyId = GetIdFromTextProperty(textProperty);
183  this->FontSize = textProperty->GetFontSize();
184  double color[3];
185  textProperty->GetColor(color);
186  this->Color.Set(static_cast<unsigned char>(color[0] * 255),
187  static_cast<unsigned char>(color[1] * 255),
188  static_cast<unsigned char>(color[2] * 255),
189  static_cast<unsigned char>(textProperty->GetOpacity() * 255));
190  this->Text = text;
191  }
193 
195 
197  bool operator==(const TextPropertyKey& other)const
198  {
199  return this->TextPropertyId == other.TextPropertyId &&
200  this->FontSize == other.FontSize &&
201  this->Text == other.Text &&
202  this->Color[0] == other.Color[0] &&
203  this->Color[1] == other.Color[1] &&
204  this->Color[2] == other.Color[2] &&
205  this->Color[3] == other.Color[3];
206  }
208 
209  unsigned short FontSize;
211  // States in the function not to use more than 32 bits - int works fine here.
212  unsigned int TextPropertyId;
214 };
215 
217 {
218 public:
220  {
221  this->Texture = NULL;
224  this->SpriteTexture = NULL;
225  this->SavedLighting = GL_TRUE;
226  this->SavedDepthTest = GL_TRUE;
227  this->SavedAlphaTest = GL_TRUE;
228  this->SavedStencilTest = GL_TRUE;
229  this->SavedBlend = GL_TRUE;
230  this->SavedDrawBuffer = 0;
231  this->SavedClearColor[0] = this->SavedClearColor[1] =
232  this->SavedClearColor[2] =
233  this->SavedClearColor[3] = 0.0f;
234  this->TextCounter = 0;
235  this->GLExtensionsLoaded = false;
236  this->OpenGL15 = false;
237  this->OpenGL20 = false;
238  this->GLSL = false;
239  this->PowerOfTwoTextures = true;
240  }
241 
243  {
244  if (this->Texture)
245  {
246  this->Texture->Delete();
247  this->Texture = NULL;
248  }
249  if (this->SpriteTexture)
250  {
251  this->SpriteTexture->Delete();
252  this->SpriteTexture = NULL;
253  }
254  }
255 
256  void SaveGLState(bool colorBuffer = false)
257  {
258  this->SavedLighting = glIsEnabled(GL_LIGHTING);
259  this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST);
260 
261  if (colorBuffer)
262  {
263  this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST);
264  this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST);
265  this->SavedBlend = glIsEnabled(GL_BLEND);
266  glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
267  glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
268  }
269  }
270 
271  void RestoreGLState(bool colorBuffer = false)
272  {
273  this->SetGLCapability(GL_LIGHTING, this->SavedLighting);
274  this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest);
275 
276  if (colorBuffer)
277  {
278  this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest);
279  this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest);
280  this->SetGLCapability(GL_BLEND, this->SavedBlend);
281 
282  if(this->SavedDrawBuffer != GL_BACK_LEFT)
283  {
284  glDrawBuffer(this->SavedDrawBuffer);
285  }
286 
287  int i = 0;
288  bool colorDiffer = false;
289  while(!colorDiffer && i < 4)
290  {
291  colorDiffer=this->SavedClearColor[i++] != 0.0;
292  }
293  if(colorDiffer)
294  {
295  glClearColor(this->SavedClearColor[0],
296  this->SavedClearColor[1],
297  this->SavedClearColor[2],
298  this->SavedClearColor[3]);
299  }
300  }
301  }
302 
303  void SetGLCapability(GLenum capability, GLboolean state)
304  {
305  if (state)
306  {
307  glEnable(capability);
308  }
309  else
310  {
311  glDisable(capability);
312  }
313  }
314 
315  float* TexCoords(float* f, int n)
316  {
317  float* texCoord = new float[2*n];
318  float minX = f[0]; float minY = f[1];
319  float maxX = f[0]; float maxY = f[1];
320  float* fptr = f;
321  for(int i = 0; i < n; ++i)
322  {
323  minX = fptr[0] < minX ? fptr[0] : minX;
324  maxX = fptr[0] > maxX ? fptr[0] : maxX;
325  minY = fptr[1] < minY ? fptr[1] : minY;
326  maxY = fptr[1] > maxY ? fptr[1] : maxY;
327  fptr+=2;
328  }
329  fptr = f;
331  {
332  double* textureBounds = this->Texture->GetInput()->GetBounds();
333  float rangeX = (textureBounds[1] - textureBounds[0]) ?
334  textureBounds[1] - textureBounds[0] : 1.;
335  float rangeY = (textureBounds[3] - textureBounds[2]) ?
336  textureBounds[3] - textureBounds[2] : 1.;
337  for (int i = 0; i < n; ++i)
338  {
339  texCoord[i*2] = (fptr[0]-minX) / rangeX;
340  texCoord[i*2+1] = (fptr[1]-minY) / rangeY;
341  fptr+=2;
342  }
343  }
344  else // this->TextureProperties & vtkContextDevice2D::Stretch
345  {
346  float rangeX = (maxX - minX)? maxX - minX : 1.f;
347  float rangeY = (maxY - minY)? maxY - minY : 1.f;
348  for (int i = 0; i < n; ++i)
349  {
350  texCoord[i*2] = (fptr[0]-minX)/rangeX;
351  texCoord[i*2+1] = (fptr[1]-minY)/rangeY;
352  fptr+=2;
353  }
354  }
355  return texCoord;
356  }
357 
359  {
360  vtkVector2i pow2(1, 1);
361  for (int i = 0; i < 2; ++i)
362  {
363  while (pow2[i] < size[i])
364  {
365  pow2[i] *= 2;
366  }
367  }
368  return pow2;
369  }
370 
372  {
373  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
374  {
375  cout << "Error = not an unsigned char..." << endl;
376  return 0;
377  }
378  int bytesPerPixel = image->GetNumberOfScalarComponents();
379  int size[3];
380  image->GetDimensions(size);
381  vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
382 
383  for (int i = 0; i < 2; ++i)
384  {
385  texCoords[i] = size[i] / float(newImg[i]);
386  }
387 
388  unsigned char *dataPtr =
389  new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
390  unsigned char *origPtr =
391  static_cast<unsigned char*>(image->GetScalarPointer());
392 
393  for (int i = 0; i < newImg[0]; ++i)
394  {
395  for (int j = 0; j < newImg[1]; ++j)
396  {
397  for (int k = 0; k < bytesPerPixel; ++k)
398  {
399  if (i < size[0] && j < size[1])
400  {
401  dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] =
402  origPtr[i * size[0] * bytesPerPixel + j * bytesPerPixel + k];
403  }
404  else
405  {
406  dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] =
407  k == 3 ? 0 : 255;
408  }
409  }
410  }
411  }
412 
413  GLuint tmpIndex(0);
414  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
415  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
416 
417  glGenTextures(1, &tmpIndex);
418  glBindTexture(GL_TEXTURE_2D, tmpIndex);
419 
420  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
421  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
422 
423  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
424  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
425  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
426  vtkgl::CLAMP_TO_EDGE );
427  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
428  vtkgl::CLAMP_TO_EDGE );
429 
430  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
431  newImg[0], newImg[1], 0, glFormat,
432  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
433  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
434  glEnable(GL_ALPHA_TEST);
435  glMatrixMode(GL_TEXTURE);
436  glLoadIdentity();
437  glMatrixMode(GL_MODELVIEW);
438  glEnable(GL_TEXTURE_2D);
439  delete [] dataPtr;
440  return tmpIndex;
441  }
442 
444  {
445  if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
446  {
447  cout << "Error = not an unsigned char..." << endl;
448  return 0;
449  }
450  int bytesPerPixel = image->GetNumberOfScalarComponents();
451  int size[3];
452  image->GetDimensions(size);
453 
454  unsigned char *dataPtr =
455  static_cast<unsigned char*>(image->GetScalarPointer());
456  GLuint tmpIndex(0);
457  GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
458  GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
459 
460  glGenTextures(1, &tmpIndex);
461  glBindTexture(GL_TEXTURE_2D, tmpIndex);
462 
463  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
464  glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
465 
466  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
467  glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
468  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
469  vtkgl::CLAMP_TO_EDGE );
470  glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
471  vtkgl::CLAMP_TO_EDGE );
472 
473  glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
474  size[0], size[1], 0, glFormat,
475  GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
476  glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
477  glEnable(GL_ALPHA_TEST);
478  glMatrixMode(GL_TEXTURE);
479  glLoadIdentity();
480  glMatrixMode(GL_MODELVIEW);
481  glEnable(GL_TEXTURE_2D);
482  return tmpIndex;
483  }
484 
486  unsigned int TextureProperties;
488  // Store the previous GL state so that we can restore it when complete
489  GLboolean SavedLighting;
490  GLboolean SavedDepthTest;
491  GLboolean SavedAlphaTest;
492  GLboolean SavedStencilTest;
493  GLboolean SavedBlend;
495  GLfloat SavedClearColor[4];
496 
501  bool OpenGL15;
502  bool OpenGL20;
503  bool GLSL;
505 
507 
510 };
512 
513 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H
514 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h