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