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 // Dimensions of the text. Used for generating texture coords when the image 00058 // dimensions are scaled to a power of two. 00059 int TextWidth; 00060 int TextHeight; 00061 }; 00062 00064 00065 struct CacheElement: public std::pair<Key, CacheData> 00066 { 00067 // Default constructor 00068 CacheElement() 00069 : std::pair<Key, CacheData>(Key(), CacheData()){} 00070 // Construct a partial CacheElement with no CacheData 00071 // This can be used for temporary CacheElement used to search a given 00072 // key into the cache list. 00073 CacheElement(const Key& key) 00074 : std::pair<Key, CacheData>(key, CacheData()){} 00075 // Standard constructor of CacheElement 00076 CacheElement(const Key& key, const CacheData& cacheData) 00077 : std::pair<Key, CacheData>(key, cacheData){} 00078 // Operator tuned to be used when searching into the cache list using 00079 // std::find() 00080 bool operator==(const CacheElement& other)const 00081 { 00082 // Here we cheat and make the comparison only on the key, this allows 00083 // us to use std::find() to search for a given key. 00084 return this->first == other.first; 00085 } 00086 }; 00088 00090 00092 vtkTextureImageCache() 00093 { 00094 this->MaxSize = 50; 00095 } 00097 00099 00101 bool IsKeyInCache(const Key& key)const 00102 { 00103 return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end(); 00104 } 00106 00111 CacheData& GetCacheData(const Key& key); 00112 00114 00116 void ReleaseGraphicsResources(vtkWindow* window) 00117 { 00118 typename std::list<CacheElement >::iterator it; 00119 for (it = this->Cache.begin(); it != this->Cache.end(); ++it) 00120 { 00121 it->second.Texture->ReleaseGraphicsResources(window); 00122 } 00123 } 00125 00126 protected: 00128 00130 CacheData& AddCacheData(const Key& key, const CacheData& cacheData) 00131 { 00132 assert(!this->IsKeyInCache(key)); 00133 if (this->Cache.size() >= this->MaxSize) 00134 { 00135 this->Cache.pop_back(); 00136 } 00137 this->Cache.push_front(CacheElement(key, cacheData)); 00138 return this->Cache.begin()->second; 00139 } 00141 00143 std::list<CacheElement > Cache; 00145 00146 size_t MaxSize; 00147 }; 00149 00150 template<class Key> 00151 typename vtkTextureImageCache<Key>::CacheData& vtkTextureImageCache<Key> 00152 ::GetCacheData(const Key& key) 00153 { 00154 typename std::list<CacheElement>::iterator it = 00155 std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key)); 00156 if (it != this->Cache.end()) 00157 { 00158 return it->second; 00159 } 00160 CacheData cacheData; 00161 cacheData.ImageData = vtkSmartPointer<vtkImageData>::New(); 00162 cacheData.Texture = vtkSmartPointer<vtkTexture>::New(); 00163 cacheData.Texture->SetInputData(cacheData.ImageData); 00164 cacheData.TextWidth = 0; 00165 cacheData.TextHeight = 0; 00166 return this->AddCacheData(key, cacheData); 00167 } 00168 00169 // .NAME TextPropertyKey - unique key for a vtkTextProperty and text 00170 // .SECTION Description 00171 // Uniquely describe a pair of vtkTextProperty and text. 00172 struct TextPropertyKey 00173 { 00175 00176 static unsigned int GetIdFromTextProperty(vtkTextProperty* textProperty) 00177 { 00178 unsigned long id; 00179 vtkFreeTypeTools::GetInstance()->MapTextPropertyToId(textProperty, &id); 00180 return static_cast<unsigned int>(id); 00181 } 00183 00185 00186 TextPropertyKey(vtkTextProperty* textProperty, const vtkStdString& text) 00187 { 00188 this->TextPropertyId = GetIdFromTextProperty(textProperty); 00189 this->FontSize = textProperty->GetFontSize(); 00190 double color[3]; 00191 textProperty->GetColor(color); 00192 this->Color.Set(static_cast<unsigned char>(color[0] * 255), 00193 static_cast<unsigned char>(color[1] * 255), 00194 static_cast<unsigned char>(color[2] * 255), 00195 static_cast<unsigned char>(textProperty->GetOpacity() * 255)); 00196 this->Text = text; 00197 } 00199 00201 00203 bool operator==(const TextPropertyKey& other)const 00204 { 00205 return this->TextPropertyId == other.TextPropertyId && 00206 this->FontSize == other.FontSize && 00207 this->Text == other.Text && 00208 this->Color[0] == other.Color[0] && 00209 this->Color[1] == other.Color[1] && 00210 this->Color[2] == other.Color[2] && 00211 this->Color[3] == other.Color[3]; 00212 } 00214 00215 unsigned short FontSize; 00216 vtkColor4ub Color; 00217 // States in the function not to use more than 32 bits - int works fine here. 00218 unsigned int TextPropertyId; 00219 vtkStdString Text; 00220 }; 00221 00222 class vtkOpenGLContextDevice2D::Private 00223 { 00224 public: 00225 Private() 00226 { 00227 this->Texture = NULL; 00228 this->TextureProperties = vtkContextDevice2D::Linear | 00229 vtkContextDevice2D::Stretch; 00230 this->SpriteTexture = NULL; 00231 this->SavedLighting = GL_TRUE; 00232 this->SavedDepthTest = GL_TRUE; 00233 this->SavedAlphaTest = GL_TRUE; 00234 this->SavedStencilTest = GL_TRUE; 00235 this->SavedBlend = GL_TRUE; 00236 this->SavedDrawBuffer = 0; 00237 this->SavedClearColor[0] = this->SavedClearColor[1] = 00238 this->SavedClearColor[2] = 00239 this->SavedClearColor[3] = 0.0f; 00240 this->TextCounter = 0; 00241 this->GLExtensionsLoaded = false; 00242 this->OpenGL15 = false; 00243 this->OpenGL20 = false; 00244 this->GLSL = false; 00245 this->PowerOfTwoTextures = true; 00246 } 00247 00248 ~Private() 00249 { 00250 if (this->Texture) 00251 { 00252 this->Texture->Delete(); 00253 this->Texture = NULL; 00254 } 00255 if (this->SpriteTexture) 00256 { 00257 this->SpriteTexture->Delete(); 00258 this->SpriteTexture = NULL; 00259 } 00260 } 00261 00262 void SaveGLState(bool colorBuffer = false) 00263 { 00264 this->SavedLighting = glIsEnabled(GL_LIGHTING); 00265 this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST); 00266 00267 if (colorBuffer) 00268 { 00269 this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST); 00270 this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST); 00271 this->SavedBlend = glIsEnabled(GL_BLEND); 00272 glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor); 00273 glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer); 00274 } 00275 } 00276 00277 void RestoreGLState(bool colorBuffer = false) 00278 { 00279 this->SetGLCapability(GL_LIGHTING, this->SavedLighting); 00280 this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest); 00281 00282 if (colorBuffer) 00283 { 00284 this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest); 00285 this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest); 00286 this->SetGLCapability(GL_BLEND, this->SavedBlend); 00287 00288 if(this->SavedDrawBuffer != GL_BACK_LEFT) 00289 { 00290 glDrawBuffer(this->SavedDrawBuffer); 00291 } 00292 00293 int i = 0; 00294 bool colorDiffer = false; 00295 while(!colorDiffer && i < 4) 00296 { 00297 colorDiffer=this->SavedClearColor[i++] != 0.0; 00298 } 00299 if(colorDiffer) 00300 { 00301 glClearColor(this->SavedClearColor[0], 00302 this->SavedClearColor[1], 00303 this->SavedClearColor[2], 00304 this->SavedClearColor[3]); 00305 } 00306 } 00307 } 00308 00309 void SetGLCapability(GLenum capability, GLboolean state) 00310 { 00311 if (state) 00312 { 00313 glEnable(capability); 00314 } 00315 else 00316 { 00317 glDisable(capability); 00318 } 00319 } 00320 00321 float* TexCoords(float* f, int n) 00322 { 00323 float* texCoord = new float[2*n]; 00324 float minX = f[0]; float minY = f[1]; 00325 float maxX = f[0]; float maxY = f[1]; 00326 float* fptr = f; 00327 for(int i = 0; i < n; ++i) 00328 { 00329 minX = fptr[0] < minX ? fptr[0] : minX; 00330 maxX = fptr[0] > maxX ? fptr[0] : maxX; 00331 minY = fptr[1] < minY ? fptr[1] : minY; 00332 maxY = fptr[1] > maxY ? fptr[1] : maxY; 00333 fptr+=2; 00334 } 00335 fptr = f; 00336 if (this->TextureProperties & vtkContextDevice2D::Repeat) 00337 { 00338 double* textureBounds = this->Texture->GetInput()->GetBounds(); 00339 float rangeX = (textureBounds[1] - textureBounds[0]) ? 00340 textureBounds[1] - textureBounds[0] : 1.; 00341 float rangeY = (textureBounds[3] - textureBounds[2]) ? 00342 textureBounds[3] - textureBounds[2] : 1.; 00343 for (int i = 0; i < n; ++i) 00344 { 00345 texCoord[i*2] = (fptr[0]-minX) / rangeX; 00346 texCoord[i*2+1] = (fptr[1]-minY) / rangeY; 00347 fptr+=2; 00348 } 00349 } 00350 else // this->TextureProperties & vtkContextDevice2D::Stretch 00351 { 00352 float rangeX = (maxX - minX)? maxX - minX : 1.f; 00353 float rangeY = (maxY - minY)? maxY - minY : 1.f; 00354 for (int i = 0; i < n; ++i) 00355 { 00356 texCoord[i*2] = (fptr[0]-minX)/rangeX; 00357 texCoord[i*2+1] = (fptr[1]-minY)/rangeY; 00358 fptr+=2; 00359 } 00360 } 00361 return texCoord; 00362 } 00363 00364 vtkVector2i FindPowerOfTwo(const vtkVector2i& size) 00365 { 00366 vtkVector2i pow2(1, 1); 00367 for (int i = 0; i < 2; ++i) 00368 { 00369 while (pow2[i] < size[i]) 00370 { 00371 pow2[i] *= 2; 00372 } 00373 } 00374 return pow2; 00375 } 00376 00377 GLuint TextureFromImage(vtkImageData *image, vtkVector2f& texCoords) 00378 { 00379 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00380 { 00381 cout << "Error = not an unsigned char..." << endl; 00382 return 0; 00383 } 00384 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00385 int size[3]; 00386 image->GetDimensions(size); 00387 vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1])); 00388 00389 for (int i = 0; i < 2; ++i) 00390 { 00391 texCoords[i] = size[i] / float(newImg[i]); 00392 } 00393 00394 unsigned char *dataPtr = 00395 new unsigned char[newImg[0] * newImg[1] * bytesPerPixel]; 00396 unsigned char *origPtr = 00397 static_cast<unsigned char*>(image->GetScalarPointer()); 00398 00399 for (int i = 0; i < newImg[0]; ++i) 00400 { 00401 for (int j = 0; j < newImg[1]; ++j) 00402 { 00403 for (int k = 0; k < bytesPerPixel; ++k) 00404 { 00405 if (i < size[0] && j < size[1]) 00406 { 00407 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] = 00408 origPtr[i * size[0] * bytesPerPixel + j * bytesPerPixel + k]; 00409 } 00410 else 00411 { 00412 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] = 00413 k == 3 ? 0 : 255; 00414 } 00415 } 00416 } 00417 } 00418 00419 GLuint tmpIndex(0); 00420 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00421 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00422 00423 glGenTextures(1, &tmpIndex); 00424 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00425 00426 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00427 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00428 00429 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00430 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00431 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00432 vtkgl::CLAMP_TO_EDGE ); 00433 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00434 vtkgl::CLAMP_TO_EDGE ); 00435 00436 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00437 newImg[0], newImg[1], 0, glFormat, 00438 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00439 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00440 glEnable(GL_ALPHA_TEST); 00441 glMatrixMode(GL_TEXTURE); 00442 glLoadIdentity(); 00443 glMatrixMode(GL_MODELVIEW); 00444 glEnable(GL_TEXTURE_2D); 00445 delete [] dataPtr; 00446 return tmpIndex; 00447 } 00448 00449 GLuint TextureFromImage(vtkImageData *image) 00450 { 00451 if (image->GetScalarType() != VTK_UNSIGNED_CHAR) 00452 { 00453 cout << "Error = not an unsigned char..." << endl; 00454 return 0; 00455 } 00456 int bytesPerPixel = image->GetNumberOfScalarComponents(); 00457 int size[3]; 00458 image->GetDimensions(size); 00459 00460 unsigned char *dataPtr = 00461 static_cast<unsigned char*>(image->GetScalarPointer()); 00462 GLuint tmpIndex(0); 00463 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA; 00464 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8; 00465 00466 glGenTextures(1, &tmpIndex); 00467 glBindTexture(GL_TEXTURE_2D, tmpIndex); 00468 00469 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE); 00470 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE); 00471 00472 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 00473 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 00474 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 00475 vtkgl::CLAMP_TO_EDGE ); 00476 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, 00477 vtkgl::CLAMP_TO_EDGE ); 00478 00479 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat, 00480 size[0], size[1], 0, glFormat, 00481 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr)); 00482 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0)); 00483 glEnable(GL_ALPHA_TEST); 00484 glMatrixMode(GL_TEXTURE); 00485 glLoadIdentity(); 00486 glMatrixMode(GL_MODELVIEW); 00487 glEnable(GL_TEXTURE_2D); 00488 return tmpIndex; 00489 } 00490 00491 vtkTexture *Texture; 00492 unsigned int TextureProperties; 00493 vtkTexture *SpriteTexture; 00494 // Store the previous GL state so that we can restore it when complete 00495 GLboolean SavedLighting; 00496 GLboolean SavedDepthTest; 00497 GLboolean SavedAlphaTest; 00498 GLboolean SavedStencilTest; 00499 GLboolean SavedBlend; 00500 GLint SavedDrawBuffer; 00501 GLfloat SavedClearColor[4]; 00502 00503 int TextCounter; 00504 vtkVector2i Dim; 00505 vtkVector2i Offset; 00506 bool GLExtensionsLoaded; 00507 bool OpenGL15; 00508 bool OpenGL20; 00509 bool GLSL; 00510 bool PowerOfTwoTextures; 00511 00513 00515 mutable vtkTextureImageCache<TextPropertyKey> TextTextureCache; 00516 mutable vtkTextureImageCache<TextPropertyKey> MathTextTextureCache; 00517 }; 00519 00520 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H 00521 // VTK-HeaderTest-Exclude: vtkOpenGLContextDevice2DPrivate.h