VTK
|
00001 /*========================================================================= 00002 00003 Program: Visualization Toolkit 00004 Module: vtkOpenGLContextDevice2DPrivate.h 00005 00006 Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen 00007 All rights reserved. 00008 See Copyright.txt or http://www.kitware.com/Copyright.htm for details. 00009 00010 This software is distributed WITHOUT ANY WARRANTY; without even 00011 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 00012 PURPOSE. See the above copyright notice for more information. 00013 00014 =========================================================================*/ 00015 00032 #ifndef __vtkOpenGLContextDevice2DPrivate_h 00033 #define __vtkOpenGLContextDevice2DPrivate_h 00034 00035 #include "vtkOpenGLContextDevice2D.h" 00036 00037 #include "vtkColor.h" 00038 #include "vtkTextProperty.h" 00039 #include "vtkFreeTypeTools.h" 00040 #include <algorithm> 00041 #include <list> 00042 #include <utility> 00043 00044 // .NAME vtkTextureImageCache - store vtkTexture and vtkImageData identified by 00045 // a unique key. 00046 // .SECTION Description 00047 // Creating and initializing a texture can be time consuming, 00048 // vtkTextureImageCache offers the ability to reuse them as much as possible. 00049 template <class Key> 00050 class vtkTextureImageCache 00051 { 00052 public: 00053 struct CacheData 00054 { 00055 vtkSmartPointer<vtkImageData> ImageData; 00056 vtkSmartPointer<vtkTexture> Texture; 00057 }; 00058 00060 00061 struct CacheElement: public std::pair<Key, CacheData> 00062 { 00063 // Default constructor 00064 CacheElement() 00065 : std::pair<Key, CacheData>(Key(), CacheData()){} 00066 // Construct a partial CacheElement with no CacheData 00067 // This can be used for temporary CacheElement used to search a given 00068 // key into the cache list. 00069 CacheElement(const Key& key) 00070 : std::pair<Key, CacheData>(key, CacheData()){} 00071 // Standard constructor of CacheElement 00072 CacheElement(const Key& key, const CacheData& cacheData) 00073 : std::pair<Key, CacheData>(key, cacheData){} 00074 // Operator tuned to be used when searching into the cache list using 00075 // std::find() 00076 bool operator==(const CacheElement& other)const 00077 { 00078 // Here we cheat and make the comparison only on the key, this allows 00079 // us to use std::find() to search for a given key. 00080 return this->first == other.first; 00081 } 00082 }; 00084 00086 00088 vtkTextureImageCache() 00089 { 00090 this->MaxSize = 50; 00091 } 00093 00095 00097 bool IsKeyInCache(const Key& key)const 00098 { 00099 return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end(); 00100 } 00102 00107 CacheData& GetCacheData(const Key& key); 00108 00110 00112 void ReleaseGraphicsResources(vtkWindow* window) 00113 { 00114 typename std::list<CacheElement >::iterator it; 00115 for (it = this->Cache.begin(); it != this->Cache.end(); ++it) 00116 { 00117 it->second.Texture->ReleaseGraphicsResources(window); 00118 } 00119 } 00121 00122 protected: 00124 00126 CacheData& AddCacheData(const Key& key, const CacheData& cacheData) 00127 { 00128 assert(!this->IsKeyInCache(key)); 00129 if (this->Cache.size() >= this->MaxSize) 00130 { 00131 this->Cache.pop_back(); 00132 } 00133 this->Cache.push_front(CacheElement(key, cacheData)); 00134 return this->Cache.begin()->second; 00135 } 00137 00139 std::list<CacheElement > Cache; 00141 00142 size_t MaxSize; 00143 }; 00145 00146 template<class Key> 00147 typename vtkTextureImageCache<Key>::CacheData& vtkTextureImageCache<Key> 00148 ::GetCacheData(const Key& key) 00149 { 00150 typename std::list<CacheElement>::iterator it = 00151 std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key)); 00152 if (it != this->Cache.end()) 00153 { 00154 return it->second; 00155 } 00156 CacheData cacheData; 00157 cacheData.ImageData = vtkSmartPointer<vtkImageData>::New(); 00158 cacheData.Texture = vtkSmartPointer<vtkTexture>::New(); 00159 cacheData.Texture->SetInput(cacheData.ImageData); 00160 return this->AddCacheData(key, cacheData); 00161 } 00162 00163 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text 00164 // .SECTION Description 00165 // Uniquely describe a pair of vtkTextProperty and text. 00166 struct TextPropertyKey 00167 { 00169 00170 static unsigned int GetIdFromTextProperty(vtkTextProperty* textProperty) 00171 { 00172 unsigned long id; 00173 vtkFreeTypeTools::GetInstance()->MapTextPropertyToId(textProperty, &id); 00174 return static_cast<unsigned int>(id); 00175 } 00177 00179 00180 TextPropertyKey(vtkTextProperty* textProperty, const vtkStdString& text) 00181 { 00182 this->TextPropertyId = GetIdFromTextProperty(textProperty); 00183 this->FontSize = textProperty->GetFontSize(); 00184 double color[3]; 00185 textProperty->GetColor(color); 00186 this->Color.Set(static_cast<unsigned char>(color[0] * 255), 00187 static_cast<unsigned char>(color[1] * 255), 00188 static_cast<unsigned char>(color[2] * 255), 00189 static_cast<unsigned char>(textProperty->GetOpacity() * 255)); 00190 this->Text = text; 00191 } 00193 00195 00197 bool operator==(const TextPropertyKey& other)const 00198 { 00199 return this->TextPropertyId == other.TextPropertyId && 00200 this->FontSize == other.FontSize && 00201 this->Text == other.Text && 00202 this->Color[0] == other.Color[0] && 00203 this->Color[1] == other.Color[1] && 00204 this->Color[2] == other.Color[2] && 00205 this->Color[3] == other.Color[3]; 00206 } 00208 00209 unsigned short FontSize; 00210 vtkColor4ub Color; 00211 // States in the function not to use more than 32 bits - int works fine here. 00212 unsigned int TextPropertyId; 00213 vtkStdString Text; 00214 }; 00215 00216 class vtkOpenGLContextDevice2D::Private 00217 { 00218 public: 00219 Private() 00220 { 00221 this->Texture = NULL; 00222 this->TextureProperties = vtkContextDevice2D::Linear | 00223 vtkContextDevice2D::Stretch; 00224 this->SpriteTexture = NULL; 00225 this->SavedLighting = GL_TRUE; 00226 this->SavedDepthTest = GL_TRUE; 00227 this->SavedAlphaTest = GL_TRUE; 00228 this->SavedStencilTest = GL_TRUE; 00229 this->SavedBlend = GL_TRUE; 00230 this->SavedDrawBuffer = 0; 00231 this->SavedClearColor[0] = this->SavedClearColor[1] = 00232 this->SavedClearColor[2] = 00233 this->SavedClearColor[3] = 0.0f; 00234 this->TextCounter = 0; 00235 this->GLExtensionsLoaded = false; 00236 this->OpenGL15 = false; 00237 this->OpenGL20 = false; 00238 this->GLSL = false; 00239 this->PowerOfTwoTextures = true; 00240 } 00241 00242 ~Private() 00243 { 00244 if (this->Texture) 00245 { 00246 this->Texture->Delete(); 00247 this->Texture = NULL; 00248 } 00249 if (this->SpriteTexture) 00250 { 00251 this->SpriteTexture->Delete(); 00252 this->SpriteTexture = NULL; 00253 } 00254 } 00255 00256 void SaveGLState(bool colorBuffer = false) 00257 { 00258 this->SavedLighting = glIsEnabled(GL_LIGHTING); 00259 this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST); 00260 00261 if (colorBuffer) 00262 { 00263 this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST); 00264 this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST); 00265 this->SavedBlend = glIsEnabled(GL_BLEND); 00266 glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor); 00267 glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer); 00268 } 00269 } 00270 00271 void RestoreGLState(bool colorBuffer = false) 00272 { 00273 this->SetGLCapability(GL_LIGHTING, this->SavedLighting); 00274 this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest); 00275 00276 if (colorBuffer) 00277 { 00278 this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest); 00279 this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest); 00280 this->SetGLCapability(GL_BLEND, this->SavedBlend); 00281 00282 if(this->SavedDrawBuffer != GL_BACK_LEFT) 00283 { 00284 glDrawBuffer(this->SavedDrawBuffer); 00285 } 00286 00287 int i = 0; 00288 bool colorDiffer = false; 00289 while(!colorDiffer && i < 4) 00290 { 00291 colorDiffer=this->SavedClearColor[i++] != 0.0; 00292 } 00293 if(colorDiffer) 00294 { 00295 glClearColor(this->SavedClearColor[0], 00296 this->SavedClearColor[1], 00297 this->SavedClearColor[2], 00298 this->SavedClearColor[3]); 00299 } 00300 } 00301 } 00302 00303 void SetGLCapability(GLenum capability, GLboolean state) 00304 { 00305 if (state) 00306 { 00307 glEnable(capability); 00308 } 00309 else 00310 { 00311 glDisable(capability); 00312 } 00313 } 00314 00315 float* TexCoords(float* f, int n) 00316 { 00317 float* texCoord = new float[2*n]; 00318 float minX = f[0]; float minY = f[1]; 00319 float maxX = f[0]; float maxY = f[1]; 00320 float* fptr = f; 00321 for(int i = 0; i < n; ++i) 00322 { 00323 minX = fptr[0] < minX ? fptr[0] : minX; 00324 maxX = fptr[0] > maxX ? fptr[0] : maxX; 00325 minY = fptr[1] < minY ? fptr[1] : minY; 00326 maxY = fptr[1] > maxY ? fptr[1] : maxY; 00327 fptr+=2; 00328 } 00329 fptr = f; 00330 if (this->TextureProperties & vtkContextDevice2D::Repeat) 00331 { 00332 double* textureBounds = this->Texture->GetInput()->GetBounds(); 00333 float rangeX = (textureBounds[1] - textureBounds[0]) ? 00334 textureBounds[1] - textureBounds[0] : 1.; 00335 float rangeY = (textureBounds[3] - textureBounds[2]) ? 00336 textureBounds[3] - textureBounds[2] : 1.; 00337 for (int i = 0; i < n; ++i) 00338 { 00339 texCoord[i*2] = (fptr[0]-minX) / rangeX; 00340 texCoord[i*2+1] = (fptr[1]-minY) / rangeY; 00341 fptr+=2; 00342 } 00343 } 00344 else // this->TextureProperties & vtkContextDevice2D::Stretch 00345 { 00346 float rangeX = (maxX - minX)? maxX - minX : 1.f; 00347 float rangeY = (maxY - minY)? maxY - minY : 1.f; 00348 for (int i = 0; i < n; ++i) 00349 { 00350 texCoord[i*2] = (fptr[0]-minX)/rangeX; 00351 texCoord[i*2+1] = (fptr[1]-minY)/rangeY; 00352 fptr+=2; 00353 } 00354 } 00355 return texCoord; 00356 } 00357 00358 vtkVector2i FindPowerOfTwo(const vtkVector2i& size) 00359 { 00360 vtkVector2i pow2(1, 1); 00361 for (int i = 0; i < 2; ++i) 00362 { 00363 while (pow2[i] < size[i]) 00364 { 00365 pow2[i] *= 2; 00366 } 00367 } 00368 return pow2; 00369 } 00370 00371 GLuint TextureFromImage(vtkImageData *image, vtkVector2f& texCoords) 00372 { 00373 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00374 { 00375 cout << "Error = not an unsigned char..." << endl; 00376 return 0; 00377 } 00378 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00379 int size[3]; 00380 image->GetDimensions(size); 00381 vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1])); 00382 00383 for (int i = 0; i < 2; ++i) 00384 { 00385 texCoords[i] = size[i] / float(newImg[i]); 00386 } 00387 00388 unsigned char *dataPtr = 00389 new unsigned char[newImg[0] * newImg[1] * bytesPerPixel]; 00390 unsigned char *origPtr = 00391 static_cast<unsigned char*>(image->GetScalarPointer()); 00392 00393 for (int i = 0; i < newImg[0]; ++i) 00394 { 00395 for (int j = 0; j < newImg[1]; ++j) 00396 { 00397 for (int k = 0; k < bytesPerPixel; ++k) 00398 { 00399 if (i < size[0] && j < size[1]) 00400 { 00401 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] = 00402 origPtr[i * size[0] * bytesPerPixel + j * bytesPerPixel + k]; 00403 } 00404 else 00405 { 00406 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] = 00407 k == 3 ? 0 : 255; 00408 } 00409 } 00410 } 00411 } 00412 00413 GLuint tmpIndex(0); 00414 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00415 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00416 00417 glGenTextures(1, &tmpIndex); 00418 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00419 00420 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00421 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00422 00423 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00424 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00425 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00426 vtkgl::CLAMP_TO_EDGE ); 00427 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00428 vtkgl::CLAMP_TO_EDGE ); 00429 00430 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00431 newImg[0], newImg[1], 0, glFormat, 00432 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00433 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00434 glEnable(GL_ALPHA_TEST); 00435 glMatrixMode(GL_TEXTURE); 00436 glLoadIdentity(); 00437 glMatrixMode(GL_MODELVIEW); 00438 glEnable(GL_TEXTURE_2D); 00439 delete [] dataPtr; 00440 return tmpIndex; 00441 } 00442 00443 GLuint TextureFromImage(vtkImageData *image) 00444 { 00445 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00446 { 00447 cout << "Error = not an unsigned char..." << endl; 00448 return 0; 00449 } 00450 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00451 int size[3]; 00452 image->GetDimensions(size); 00453 00454 unsigned char *dataPtr = 00455 static_cast<unsigned char*>(image->GetScalarPointer()); 00456 GLuint tmpIndex(0); 00457 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00458 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00459 00460 glGenTextures(1, &tmpIndex); 00461 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00462 00463 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00464 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00465 00466 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00467 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00468 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00469 vtkgl::CLAMP_TO_EDGE ); 00470 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00471 vtkgl::CLAMP_TO_EDGE ); 00472 00473 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00474 size[0], size[1], 0, glFormat, 00475 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00476 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00477 glEnable(GL_ALPHA_TEST); 00478 glMatrixMode(GL_TEXTURE); 00479 glLoadIdentity(); 00480 glMatrixMode(GL_MODELVIEW); 00481 glEnable(GL_TEXTURE_2D); 00482 return tmpIndex; 00483 } 00484 00485 vtkTexture *Texture; 00486 unsigned int TextureProperties; 00487 vtkTexture *SpriteTexture; 00488 // Store the previous GL state so that we can restore it when complete 00489 GLboolean SavedLighting; 00490 GLboolean SavedDepthTest; 00491 GLboolean SavedAlphaTest; 00492 GLboolean SavedStencilTest; 00493 GLboolean SavedBlend; 00494 GLint SavedDrawBuffer; 00495 GLfloat SavedClearColor[4]; 00496 00497 int TextCounter; 00498 vtkVector2i Dim; 00499 vtkVector2i Offset; 00500 bool GLExtensionsLoaded; 00501 bool OpenGL15; 00502 bool OpenGL20; 00503 bool GLSL; 00504 bool PowerOfTwoTextures; 00505 00507 00509 mutable vtkTextureImageCache<TextPropertyKey> TextTextureCache; 00510 }; 00512 00513 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H