00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00032 #ifndef __vtkOpenGLContextDevice2DPrivate_h
00033 #define __vtkOpenGLContextDevice2DPrivate_h
00034
00035 #include "vtkOpenGLContextDevice2D.h"
00036
00037 #include "vtkFreeTypeTools.h"
00038 #include <algorithm>
00039 #include <list>
00040 #include <utility>
00041
00042
00043
00044
00045
00046
00047 template <class Key>
00048 class vtkTextureImageCache
00049 {
00050 public:
00051 struct CacheData
00052 {
00053 vtkSmartPointer<vtkImageData> ImageData;
00054 vtkSmartPointer<vtkTexture> Texture;
00055 };
00056
00058
00059 struct CacheElement: public std::pair<Key, CacheData>
00060 {
00061
00062 CacheElement()
00063 : std::pair<Key, CacheData>(Key(), CacheData()){}
00064
00065
00066
00067 CacheElement(const Key& key)
00068 : std::pair<Key, CacheData>(key, CacheData()){}
00069
00070 CacheElement(const Key& key, const CacheData& cacheData)
00071 : std::pair<Key, CacheData>(key, cacheData){}
00072
00073
00074 bool operator==(const CacheElement& other)const
00075 {
00076
00077
00078 return this->first == other.first;
00079 }
00080 };
00082
00084
00086 vtkTextureImageCache()
00087 {
00088 this->MaxSize = 50;
00089 }
00091
00093
00095 bool IsKeyInCache(const Key& key)const
00096 {
00097 return std::find(this->Cache.begin(), this->Cache.end(), key) != this->Cache.end();
00098 }
00100
00105 CacheData& GetCacheData(const Key& key);
00106
00108
00110 void ReleaseGraphicsResources(vtkWindow* window)
00111 {
00112 typename std::list<CacheElement >::iterator it;
00113 for (it = this->Cache.begin(); it != this->Cache.end(); ++it)
00114 {
00115 it->second.Texture->ReleaseGraphicsResources(window);
00116 }
00117 }
00119
00120 protected:
00122
00124 CacheData& AddCacheData(const Key& key, const CacheData& cacheData)
00125 {
00126 assert(!this->IsKeyInCache(key));
00127 if (this->Cache.size() >= this->MaxSize)
00128 {
00129 this->Cache.pop_back();
00130 }
00131 this->Cache.push_front(CacheElement(key, cacheData));
00132 return this->Cache.begin()->second;
00133 }
00135
00137
00138 std::list<CacheElement > Cache;
00139
00140
00141 size_t MaxSize;
00142 };
00144
00145 template<class Key>
00146 typename vtkTextureImageCache<Key>::CacheData& vtkTextureImageCache<Key>
00147 ::GetCacheData(const Key& key)
00148 {
00149 typename std::list<CacheElement>::iterator it =
00150 std::find(this->Cache.begin(), this->Cache.end(), CacheElement(key));
00151 if (it != this->Cache.end())
00152 {
00153 return it->second;
00154 }
00155 CacheData cacheData;
00156 cacheData.ImageData = vtkSmartPointer<vtkImageData>::New();
00157 cacheData.Texture = vtkSmartPointer<vtkTexture>::New();
00158 cacheData.Texture->SetInput(cacheData.ImageData);
00159 return this->AddCacheData(key, cacheData);
00160 }
00161
00162
00163
00164
00165 struct TextPropertyKey
00166 {
00168
00169 static unsigned long GetIdFromTextProperty(vtkTextProperty* textProperty)
00170 {
00171 unsigned long id;
00172 vtkFreeTypeTools::GetInstance()->MapTextPropertyToId(textProperty, &id);
00173 return id;
00174 }
00176
00178
00179 TextPropertyKey(vtkTextProperty* textProperty, const vtkStdString& text)
00180 {
00181 this->TextPropertyId = GetIdFromTextProperty(textProperty);
00182 this->Text = text;
00183 }
00185
00187
00189 bool operator==(const TextPropertyKey& other)const
00190 {
00191 return this->TextPropertyId == other.TextPropertyId &&
00192 this->Text == other.Text;
00193 }
00194 unsigned long TextPropertyId;
00195 vtkStdString Text;
00196 };
00198
00199 class vtkOpenGLContextDevice2D::Private
00200 {
00201 public:
00202 Private()
00203 {
00204 this->Texture = NULL;
00205 this->TextureProperties = vtkContextDevice2D::Linear |
00206 vtkContextDevice2D::Stretch;
00207 this->SpriteTexture = NULL;
00208 this->SavedLighting = GL_TRUE;
00209 this->SavedDepthTest = GL_TRUE;
00210 this->SavedAlphaTest = GL_TRUE;
00211 this->SavedStencilTest = GL_TRUE;
00212 this->SavedBlend = GL_TRUE;
00213 this->SavedDrawBuffer = 0;
00214 this->SavedClearColor[0] = this->SavedClearColor[1] =
00215 this->SavedClearColor[2] =
00216 this->SavedClearColor[3] = 0.0f;
00217 this->TextCounter = 0;
00218 this->GLExtensionsLoaded = false;
00219 this->OpenGL15 = false;
00220 this->OpenGL20 = false;
00221 this->GLSL = false;
00222 this->PowerOfTwoTextures = true;
00223 }
00224
00225 ~Private()
00226 {
00227 if (this->Texture)
00228 {
00229 this->Texture->Delete();
00230 this->Texture = NULL;
00231 }
00232 if (this->SpriteTexture)
00233 {
00234 this->SpriteTexture->Delete();
00235 this->SpriteTexture = NULL;
00236 }
00237 }
00238
00239 void SaveGLState(bool colorBuffer = false)
00240 {
00241 this->SavedLighting = glIsEnabled(GL_LIGHTING);
00242 this->SavedDepthTest = glIsEnabled(GL_DEPTH_TEST);
00243
00244 if (colorBuffer)
00245 {
00246 this->SavedAlphaTest = glIsEnabled(GL_ALPHA_TEST);
00247 this->SavedStencilTest = glIsEnabled(GL_STENCIL_TEST);
00248 this->SavedBlend = glIsEnabled(GL_BLEND);
00249 glGetFloatv(GL_COLOR_CLEAR_VALUE, this->SavedClearColor);
00250 glGetIntegerv(GL_DRAW_BUFFER, &this->SavedDrawBuffer);
00251 }
00252 }
00253
00254 void RestoreGLState(bool colorBuffer = false)
00255 {
00256 this->SetGLCapability(GL_LIGHTING, this->SavedLighting);
00257 this->SetGLCapability(GL_DEPTH_TEST, this->SavedDepthTest);
00258
00259 if (colorBuffer)
00260 {
00261 this->SetGLCapability(GL_ALPHA_TEST, this->SavedAlphaTest);
00262 this->SetGLCapability(GL_STENCIL_TEST, this->SavedStencilTest);
00263 this->SetGLCapability(GL_BLEND, this->SavedBlend);
00264
00265 if(this->SavedDrawBuffer != GL_BACK_LEFT)
00266 {
00267 glDrawBuffer(this->SavedDrawBuffer);
00268 }
00269
00270 int i = 0;
00271 bool colorDiffer = false;
00272 while(!colorDiffer && i < 4)
00273 {
00274 colorDiffer=this->SavedClearColor[i++] != 0.0;
00275 }
00276 if(colorDiffer)
00277 {
00278 glClearColor(this->SavedClearColor[0],
00279 this->SavedClearColor[1],
00280 this->SavedClearColor[2],
00281 this->SavedClearColor[3]);
00282 }
00283 }
00284 }
00285
00286 void SetGLCapability(GLenum capability, GLboolean state)
00287 {
00288 if (state)
00289 {
00290 glEnable(capability);
00291 }
00292 else
00293 {
00294 glDisable(capability);
00295 }
00296 }
00297
00298 float* TexCoords(float* f, int n)
00299 {
00300 float* texCoord = new float[2*n];
00301 float minX = f[0]; float minY = f[1];
00302 float maxX = f[0]; float maxY = f[1];
00303 float* fptr = f;
00304 for(int i = 0; i < n; ++i)
00305 {
00306 minX = fptr[0] < minX ? fptr[0] : minX;
00307 maxX = fptr[0] > maxX ? fptr[0] : maxX;
00308 minY = fptr[1] < minY ? fptr[1] : minY;
00309 maxY = fptr[1] > maxY ? fptr[1] : maxY;
00310 fptr+=2;
00311 }
00312 fptr = f;
00313 if (this->TextureProperties & vtkContextDevice2D::Repeat)
00314 {
00315 double* textureBounds = this->Texture->GetInput()->GetBounds();
00316 float rangeX = (textureBounds[1] - textureBounds[0]) ?
00317 textureBounds[1] - textureBounds[0] : 1.;
00318 float rangeY = (textureBounds[3] - textureBounds[2]) ?
00319 textureBounds[3] - textureBounds[2] : 1.;
00320 for (int i = 0; i < n; ++i)
00321 {
00322 texCoord[i*2] = (fptr[0]-minX) / rangeX;
00323 texCoord[i*2+1] = (fptr[1]-minY) / rangeY;
00324 fptr+=2;
00325 }
00326 }
00327 else
00328 {
00329 float rangeX = (maxX - minX)? maxX - minX : 1.f;
00330 float rangeY = (maxY - minY)? maxY - minY : 1.f;
00331 for (int i = 0; i < n; ++i)
00332 {
00333 texCoord[i*2] = (fptr[0]-minX)/rangeX;
00334 texCoord[i*2+1] = (fptr[1]-minY)/rangeY;
00335 fptr+=2;
00336 }
00337 }
00338 return texCoord;
00339 }
00340
00341 vtkVector2i FindPowerOfTwo(const vtkVector2i& size)
00342 {
00343 vtkVector2i pow2(1, 1);
00344 for (int i = 0; i < 2; ++i)
00345 {
00346 while (pow2[i] < size[i])
00347 {
00348 pow2[i] *= 2;
00349 }
00350 }
00351 return pow2;
00352 }
00353
00354 GLuint TextureFromImage(vtkImageData *image, vtkVector2f& texCoords)
00355 {
00356 if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
00357 {
00358 cout << "Error = not an unsigned char..." << endl;
00359 return 0;
00360 }
00361 int bytesPerPixel = image->GetNumberOfScalarComponents();
00362 int size[3];
00363 image->GetDimensions(size);
00364 vtkVector2i newImg = this->FindPowerOfTwo(vtkVector2i(size[0], size[1]));
00365
00366 for (int i = 0; i < 2; ++i)
00367 {
00368 texCoords[i] = size[i] / float(newImg[i]);
00369 }
00370
00371 unsigned char *dataPtr =
00372 new unsigned char[newImg[0] * newImg[1] * bytesPerPixel];
00373 unsigned char *origPtr =
00374 static_cast<unsigned char*>(image->GetScalarPointer());
00375
00376 for (int i = 0; i < newImg[0]; ++i)
00377 {
00378 for (int j = 0; j < newImg[1]; ++j)
00379 {
00380 for (int k = 0; k < bytesPerPixel; ++k)
00381 {
00382 if (i < size[0] && j < size[1])
00383 {
00384 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] =
00385 origPtr[i * size[0] * bytesPerPixel + j * bytesPerPixel + k];
00386 }
00387 else
00388 {
00389 dataPtr[i * newImg[0] * bytesPerPixel + j * bytesPerPixel + k] =
00390 k == 3 ? 0 : 255;
00391 }
00392 }
00393 }
00394 }
00395
00396 GLuint tmpIndex(0);
00397 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
00398 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
00399
00400 glGenTextures(1, &tmpIndex);
00401 glBindTexture(GL_TEXTURE_2D, tmpIndex);
00402
00403 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
00404 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
00405
00406 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00407 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00408 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
00409 vtkgl::CLAMP_TO_EDGE );
00410 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
00411 vtkgl::CLAMP_TO_EDGE );
00412
00413 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
00414 newImg[0], newImg[1], 0, glFormat,
00415 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
00416 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
00417 glEnable(GL_ALPHA_TEST);
00418 glMatrixMode(GL_TEXTURE);
00419 glLoadIdentity();
00420 glMatrixMode(GL_MODELVIEW);
00421 glEnable(GL_TEXTURE_2D);
00422 delete [] dataPtr;
00423 return tmpIndex;
00424 }
00425
00426 GLuint TextureFromImage(vtkImageData *image)
00427 {
00428 if (image->GetScalarType() != VTK_UNSIGNED_CHAR)
00429 {
00430 cout << "Error = not an unsigned char..." << endl;
00431 return 0;
00432 }
00433 int bytesPerPixel = image->GetNumberOfScalarComponents();
00434 int size[3];
00435 image->GetDimensions(size);
00436
00437 unsigned char *dataPtr =
00438 static_cast<unsigned char*>(image->GetScalarPointer());
00439 GLuint tmpIndex(0);
00440 GLint glFormat = bytesPerPixel == 3 ? GL_RGB : GL_RGBA;
00441 GLint glInternalFormat = bytesPerPixel == 3 ? GL_RGB8 : GL_RGBA8;
00442
00443 glGenTextures(1, &tmpIndex);
00444 glBindTexture(GL_TEXTURE_2D, tmpIndex);
00445
00446 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_RGB, GL_REPLACE);
00447 glTexEnvf(GL_TEXTURE_ENV, vtkgl::COMBINE_ALPHA, GL_REPLACE);
00448
00449 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
00450 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
00451 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,
00452 vtkgl::CLAMP_TO_EDGE );
00453 glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,
00454 vtkgl::CLAMP_TO_EDGE );
00455
00456 glTexImage2D(GL_TEXTURE_2D, 0 , glInternalFormat,
00457 size[0], size[1], 0, glFormat,
00458 GL_UNSIGNED_BYTE, static_cast<const GLvoid *>(dataPtr));
00459 glAlphaFunc(GL_GREATER, static_cast<GLclampf>(0));
00460 glEnable(GL_ALPHA_TEST);
00461 glMatrixMode(GL_TEXTURE);
00462 glLoadIdentity();
00463 glMatrixMode(GL_MODELVIEW);
00464 glEnable(GL_TEXTURE_2D);
00465 return tmpIndex;
00466 }
00467
00468 vtkTexture *Texture;
00469 unsigned int TextureProperties;
00470 vtkTexture *SpriteTexture;
00471
00472 GLboolean SavedLighting;
00473 GLboolean SavedDepthTest;
00474 GLboolean SavedAlphaTest;
00475 GLboolean SavedStencilTest;
00476 GLboolean SavedBlend;
00477 GLint SavedDrawBuffer;
00478 GLfloat SavedClearColor[4];
00479
00480 int TextCounter;
00481 vtkVector2i Dim;
00482 vtkVector2i Offset;
00483 bool GLExtensionsLoaded;
00484 bool OpenGL15;
00485 bool OpenGL20;
00486 bool GLSL;
00487 bool PowerOfTwoTextures;
00488
00490
00492 mutable vtkTextureImageCache<TextPropertyKey> TextTextureCache;
00493 };
00495
00496 #endif // VTKOPENGLCONTEXTDEVICE2DPRIVATE_H