1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkTextureObject.cxx
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 #include "vtkTextureObject.h"
16 
17 #include "vtkObjectFactory.h"
18 #include "vtkPixelBufferObject.h"
19 #include "vtkOpenGLExtensionManager.h"
20 #include "vtkOpenGLRenderWindow.h"
21 #include "vtkOpenGLError.h"
22 
23 #include "vtkgl.h"
24 #include <cassert>
25 
26 //#define VTK_TO_DEBUG
27 //#define VTK_TO_TIMING
28 
29 #ifdef VTK_TO_TIMING
30 #include "vtkTimerLog.h"
31 #endif
32 
33 #define BUFFER_OFFSET(i) (static_cast<char *>(NULL) + (i))
34 
35 // Mapping from DepthTextureCompareFunction values to OpenGL values.
36 
37 static GLint OpenGLDepthTextureCompareFunction[8]=
38 {
39   GL_LEQUAL,
40   GL_GEQUAL,
41   GL_LESS,
42   GL_GREATER,
43   GL_EQUAL,
44   GL_NOTEQUAL,
45   GL_ALWAYS,
46   GL_NEVER
47 };
48 
49 static const char *DepthTextureCompareFunctionAsString[8]=
50 {
51   "Lequal",
52   "Gequal",
53   "Less",
54   "Greater",
55   "Equal",
56   "NotEqual",
57   "AlwaysTrue",
58   "Never"
59 };
60 
61 // Mapping from DepthTextureMode values to OpenGL values.
62 
63 static GLint OpenGLDepthTextureMode[3]=
64 {
65   GL_LUMINANCE,
66   GL_INTENSITY,
67   GL_ALPHA
68 };
69 
70 static const char *DepthTextureModeAsString[3]=
71 {
72   "Luminance",
73   "Intensity",
74   "Alpha"
75 };
76 
77 // Mapping from Wrap values to OpenGL values.
78 static GLint OpenGLWrap[5]=
79 {
80   GL_CLAMP,
81   vtkgl::CLAMP_TO_EDGE,
82   GL_REPEAT,
83   vtkgl::CLAMP_TO_BORDER,
84   vtkgl::MIRRORED_REPEAT
85 };
86 
87 static const char *WrapAsString[5]=
88 {
89   "Clamp",
90   "ClampToEdge",
91   "Repeat",
92   "ClampToBorder",
93   "MirroredRepeat"
94 };
95 
96 // Mapping MinificationFilter values to OpenGL values.
97 static GLint OpenGLMinFilter[6]=
98 {
99   GL_NEAREST,
100   GL_LINEAR,
101   GL_NEAREST_MIPMAP_NEAREST,
102   GL_NEAREST_MIPMAP_LINEAR,
103   GL_LINEAR_MIPMAP_NEAREST,
104   GL_LINEAR_MIPMAP_LINEAR
105 };
106 
107 // Mapping MagnificationFilter values to OpenGL values.
108 static GLint OpenGLMagFilter[6]=
109 {
110   GL_NEAREST,
111   GL_LINEAR
112 };
113 
114 static const char *MinMagFilterAsString[6]=
115 {
116   "Nearest",
117   "Linear",
118   "NearestMipmapNearest",
119   "NearestMipmapLinear",
120   "LinearMipmapNearest",
121   "LinearMipmapLinear"
122 };
123 
124 static GLenum OpenGLDepthInternalFormat[5]=
125 {
126   GL_DEPTH_COMPONENT,
127   vtkgl::DEPTH_COMPONENT16,
128   vtkgl::DEPTH_COMPONENT24,
129   vtkgl::DEPTH_COMPONENT32,
130   vtkgl::DEPTH_COMPONENT32F
131 };
132 
133 static GLenum OpenGLDepthInternalFormatType[5]=
134 {
135   GL_UNSIGNED_INT,
136   GL_UNSIGNED_INT,
137   GL_UNSIGNED_INT,
138   GL_UNSIGNED_INT,
139   GL_FLOAT
140 };
141 
142 /*
143 static const char *DepthInternalFormatFilterAsString[6]=
144 {
145   "Native",
146   "Fixed16",
147   "Fixed24",
148   "Fixed32",
149   "Float32"
150 };
151 */
152 
153 //----------------------------------------------------------------------------
154 vtkStandardNewMacro(vtkTextureObject);
155 
156 //----------------------------------------------------------------------------
vtkTextureObject()157 vtkTextureObject::vtkTextureObject()
158 {
159   this->Context = NULL;
160   this->Handle = 0;
161   this->NumberOfDimensions = 0;
162   this->Target = 0;
163   this->Format = 0;
164   this->Type = 0;
165   this->Components = 0;
166   this->Width = 0;
167   this->Height = 0;
168   this->Depth = 0;
169   this->RequireTextureInteger = false;
170   this->SupportsTextureInteger = false;
171   this->RequireTextureFloat = false;
172   this->SupportsTextureFloat = false;
173   this->RequireDepthBufferFloat = false;
174   this->SupportsDepthBufferFloat = false;
175   this->AutoParameters = 1;
176   this->WrapS = Repeat;
177   this->WrapT = Repeat;
178   this->WrapR = Repeat;
179   this->MinificationFilter = Nearest;
180   this->MagnificationFilter = Nearest;
181   this->LinearMagnification = false;
182   this->BorderColor[0] = 0.0f;
183   this->BorderColor[1] = 0.0f;
184   this->BorderColor[2] = 0.0f;
185   this->BorderColor[3] = 0.0f;
186   this->Priority = 1.0f;
187   this->MinLOD = -1000.0f;
188   this->MaxLOD = 1000.0f;
189   this->BaseLevel = 0;
190   this->MaxLevel = 0;
191   this->DepthTextureCompare = false;
192   this->DepthTextureCompareFunction = Lequal;
193   this->DepthTextureMode = Luminance;
194   this->GenerateMipmap = false;
195 }
196 
197 //----------------------------------------------------------------------------
~vtkTextureObject()198 vtkTextureObject::~vtkTextureObject()
199 {
200   this->DestroyTexture();
201 }
202 
203 //----------------------------------------------------------------------------
IsSupported(vtkRenderWindow * win,bool requireTexFloat,bool requireDepthFloat,bool requireTexInt)204 bool vtkTextureObject::IsSupported(vtkRenderWindow* win,
205       bool requireTexFloat,
206       bool requireDepthFloat,
207       bool requireTexInt)
208 {
209   vtkOpenGLRenderWindow* renWin = vtkOpenGLRenderWindow::SafeDownCast(win);
210   if (renWin)
211     {
212     vtkOpenGLExtensionManager* mgr = renWin->GetExtensionManager();
213 
214     bool gl12 = mgr->ExtensionSupported("GL_VERSION_1_2")==1;
215     bool gl13 = mgr->ExtensionSupported("GL_VERSION_1_3")==1;
216     bool gl20 = mgr->ExtensionSupported("GL_VERSION_2_0")==1;
217 
218     bool npot=gl20 ||
219       mgr->ExtensionSupported("GL_ARB_texture_non_power_of_two");
220 
221     bool tex3D=gl12 || mgr->ExtensionSupported("GL_EXT_texture3D");
222     bool multi=gl13 || mgr->ExtensionSupported("GL_ARB_multitexture");
223 
224     bool texFloat = true;
225     if (requireTexFloat)
226       {
227       texFloat = mgr->ExtensionSupported("GL_ARB_texture_float")==1;
228       }
229 
230     bool depthFloat = true;
231     if (requireDepthFloat)
232       {
233       depthFloat = mgr->ExtensionSupported("GL_ARB_depth_buffer_float")==1;
234       }
235 
236     bool texInt = true;
237     if (requireTexInt)
238       {
239       texInt = mgr->ExtensionSupported("GL_EXT_texture_integer")==1;
240       }
241 
242     return npot && tex3D && multi && texFloat && depthFloat && texInt;
243     }
244   return false;
245 }
246 
247 //----------------------------------------------------------------------------
LoadRequiredExtensions(vtkRenderWindow * renWin)248 bool vtkTextureObject::LoadRequiredExtensions(vtkRenderWindow *renWin)
249 {
250   vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(renWin);
251   if (!context)
252     {
253     return false;
254     }
255 
256   vtkOpenGLExtensionManager* mgr = context->GetExtensionManager();
257 
258   bool gl12 = mgr->ExtensionSupported("GL_VERSION_1_2")==1;
259   bool gl13 = mgr->ExtensionSupported("GL_VERSION_1_3")==1;
260   bool gl20 = mgr->ExtensionSupported("GL_VERSION_2_0")==1;
261 
262   bool npot = (gl20 ||
263     mgr->ExtensionSupported("GL_ARB_texture_non_power_of_two"));
264 
265   bool tex3D = (gl12 || mgr->ExtensionSupported("GL_EXT_texture3D"));
266   bool multi = (gl13 || mgr->ExtensionSupported("GL_ARB_multitexture"));
267 
268   this->SupportsTextureInteger
269     = mgr->LoadSupportedExtension("GL_EXT_texture_integer")==1;
270 
271   bool texInt
272     = (!this->RequireTextureInteger || this->SupportsTextureInteger);
273 
274   this->SupportsTextureFloat
275     = mgr->ExtensionSupported("GL_ARB_texture_float")==1;
276 
277   bool texFloat
278     = (!this->RequireTextureFloat || this->SupportsTextureFloat);
279 
280   this->SupportsDepthBufferFloat
281     = mgr->ExtensionSupported("GL_ARB_depth_buffer_float")==1;
282 
283   bool depthFloat
284     = (!this->RequireDepthBufferFloat || this->SupportsDepthBufferFloat);
285 
286   bool supported
287     = npot && tex3D && multi && texInt && texFloat && depthFloat;
288 
289   if (supported)
290     {
291     // tex3D
292     if(gl12)
293       {
294       mgr->LoadSupportedExtension("GL_VERSION_1_2");
295       }
296     else
297       {
298       mgr->LoadCorePromotedExtension("GL_EXT_texture3D");
299       }
300     // multi
301     if(gl13)
302       {
303       mgr->LoadSupportedExtension("GL_VERSION_1_3");
304       }
305     else
306       {
307       mgr->LoadCorePromotedExtension("GL_ARB_multitexture");
308       }
309     // nothing to load for:
310     // GL_ARB_texture_non_power_of_two, GL_ARB_texture_float,
311     // GL_ARB_depth_buffer_float only defineconstants
312     // only using constants from GL_EXT_texture_integer
313     }
314 
315   return supported;
316 }
317 
318 //----------------------------------------------------------------------------
SetContext(vtkRenderWindow * renWin)319 void vtkTextureObject::SetContext(vtkRenderWindow* renWin)
320 {
321   // avoid pointless reassignment
322   if (this->Context == renWin)
323     {
324     return;
325     }
326   // free previous resources
327   this->DestroyTexture();
328   this->Context = NULL;
329   this->Modified();
330   // all done if assigned null
331   if (!renWin)
332     {
333     return;
334     }
335   // check for support
336   vtkOpenGLRenderWindow *context
337      = dynamic_cast<vtkOpenGLRenderWindow*>(renWin);
338 
339   if ( !context
340     || !this->LoadRequiredExtensions(renWin) )
341     {
342     vtkErrorMacro("Required OpenGL extensions not supported by the context.");
343     return;
344     }
345   // initialize
346   this->Context = renWin;
347   this->Context->MakeCurrent();
348 }
349 
350 //----------------------------------------------------------------------------
GetContext()351 vtkRenderWindow* vtkTextureObject::GetContext()
352 {
353   return static_cast<vtkRenderWindow*>(this->Context);
354 }
355 
356 //----------------------------------------------------------------------------
DestroyTexture()357 void vtkTextureObject::DestroyTexture()
358 {
359   // because we don't hold a reference to the render
360   // context we don't have any control on when it is
361   // destroyed. In fact it may be destroyed before
362   // we are(eg smart pointers), in which case we should
363   // do nothing.
364   if (this->Context && this->Handle)
365     {
366     GLuint tex = this->Handle;
367     glDeleteTextures(1, &tex);
368     vtkOpenGLCheckErrorMacro("failed at glDeleteTexture");
369     }
370   this->Handle = 0;
371   this->NumberOfDimensions = 0;
372   this->Target =0;
373   this->Format = 0;
374   this->Type = 0;
375   this->Components = 0;
376   this->Width = this->Height = this->Depth = 0;
377 }
378 
379 //----------------------------------------------------------------------------
CreateTexture()380 void vtkTextureObject::CreateTexture()
381 {
382   assert(this->Context);
383 
384   // reuse the existing handle if we have one
385   if (!this->Handle)
386     {
387     GLuint tex=0;
388     glGenTextures(1, &tex);
389     vtkOpenGLCheckErrorMacro("failed at glGenTextures");
390     this->Handle=tex;
391 
392     if (this->Target)
393       {
394       glBindTexture(this->Target, this->Handle);
395       vtkOpenGLCheckErrorMacro("failed at glBindTexture");
396 
397       // See: http://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture
398       // turn off mip map filter or set the base and max level correctly. here
399       // both are done.
400       glTexParameteri(this->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
401       glTexParameteri(this->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
402 
403       glTexParameteri(this->Target, GL_TEXTURE_WRAP_S, GL_CLAMP);
404       glTexParameteri(this->Target, GL_TEXTURE_WRAP_T, GL_CLAMP);
405 
406       glTexParameteri(GL_TEXTURE_2D, vtkgl::TEXTURE_BASE_LEVEL, 0);
407       glTexParameteri(GL_TEXTURE_2D, vtkgl::TEXTURE_MAX_LEVEL, 0);
408 
409       glBindTexture(this->Target, 0);
410       }
411     }
412 }
413 
414 //---------------------------------------------------------------------------
Activate(unsigned int texUnit)415 void vtkTextureObject::Activate(unsigned int texUnit)
416 {
417   vtkgl::ActiveTexture(static_cast<GLenum>(texUnit));
418   this->Bind();
419 }
420 
421 //---------------------------------------------------------------------------
Deactivate(unsigned int texUnit)422 void vtkTextureObject::Deactivate(unsigned int texUnit)
423 {
424   vtkgl::ActiveTexture(static_cast<GLenum>(texUnit));
425   this->UnBind();
426 }
427 
428 //----------------------------------------------------------------------------
Bind()429 void vtkTextureObject::Bind()
430 {
431   assert(this->Context);
432   assert(this->Handle);
433 
434   glBindTexture(this->Target, this->Handle);
435   vtkOpenGLCheckErrorMacro("failed at glBindTexture");
436 
437   if (this->AutoParameters && (this->GetMTime()>this->SendParametersTime))
438     {
439     this->SendParameters();
440     }
441 }
442 
443 //----------------------------------------------------------------------------
UnBind()444 void vtkTextureObject::UnBind()
445 {
446   glBindTexture(this->Target, 0);
447   vtkOpenGLCheckErrorMacro("failed at glBindTexture(0)");
448 }
449 
450 //----------------------------------------------------------------------------
IsBound()451 bool vtkTextureObject::IsBound()
452 {
453   bool result=false;
454   if(this->Context && this->Handle)
455     {
456     GLenum target=0; // to avoid warnings.
457     switch(this->Target)
458       {
459       case GL_TEXTURE_1D:
460         target=GL_TEXTURE_BINDING_1D;
461         break;
462       case GL_TEXTURE_2D:
463         target=GL_TEXTURE_BINDING_2D;
464         break;
465       case vtkgl::TEXTURE_3D:
466         target=vtkgl::TEXTURE_BINDING_3D;
467         break;
468       default:
469         assert("check: impossible case" && 0);
470         break;
471       }
472     GLint objectId;
473     glGetIntegerv(target,&objectId);
474     result=static_cast<GLuint>(objectId)==this->Handle;
475     }
476   return result;
477 }
478 
479 //----------------------------------------------------------------------------
SendParameters()480 void vtkTextureObject::SendParameters()
481 {
482   assert("pre: is_bound" && this->IsBound());
483 
484   glTexParameteri(this->Target,GL_TEXTURE_WRAP_S, OpenGLWrap[this->WrapS]);
485   glTexParameteri(this->Target,GL_TEXTURE_WRAP_T,OpenGLWrap[this->WrapT]);
486 
487   glTexParameteri(
488         this->Target,
489         vtkgl::TEXTURE_WRAP_R,
490         OpenGLWrap[this->WrapR]);
491 
492   glTexParameteri(
493         this->Target,
494         GL_TEXTURE_MIN_FILTER,
495         OpenGLMinFilter[this->MinificationFilter]);
496 
497   glTexParameteri(
498         this->Target,
499         GL_TEXTURE_MAG_FILTER,
500         OpenGLMagFilter[this->MagnificationFilter]);
501 
502   glTexParameterfv(this->Target,GL_TEXTURE_BORDER_COLOR,this->BorderColor);
503 
504   glTexParameterf(this->Target,GL_TEXTURE_PRIORITY,this->Priority);
505   glTexParameterf(this->Target,vtkgl::TEXTURE_MIN_LOD,this->MinLOD);
506   glTexParameterf(this->Target,vtkgl::TEXTURE_MAX_LOD,this->MaxLOD);
507   glTexParameteri(this->Target,vtkgl::TEXTURE_BASE_LEVEL,this->BaseLevel);
508   glTexParameteri(this->Target,vtkgl::TEXTURE_MAX_LEVEL,this->MaxLevel);
509 
510   glTexParameteri(
511         this->Target,
512         vtkgl::DEPTH_TEXTURE_MODE,
513         OpenGLDepthTextureMode[this->DepthTextureMode]);
514 
515   if(DepthTextureCompare)
516     {
517     glTexParameteri(
518           this->Target,
519           vtkgl::TEXTURE_COMPARE_MODE,
520           vtkgl::COMPARE_R_TO_TEXTURE);
521     }
522   else
523     {
524     glTexParameteri(
525           this->Target,
526           vtkgl::TEXTURE_COMPARE_MODE,
527           GL_NONE);
528     }
529 
530   glTexParameteri(
531         this->Target,
532         vtkgl::TEXTURE_COMPARE_FUNC,
533         OpenGLDepthTextureCompareFunction[this->DepthTextureCompareFunction]);
534 
535   vtkOpenGLCheckErrorMacro("failed after SendParameters");
536   this->SendParametersTime.Modified();
537 }
538 
539 //----------------------------------------------------------------------------
GetInternalFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)540 unsigned int vtkTextureObject::GetInternalFormat(int vtktype, int numComps,
541                                                  bool shaderSupportsTextureInt)
542 {
543   // 1 or 2 components not supported as render target in FBO on GeForce<8
544   // force internal format component to be 3 or 4, even if client format is 1
545   // or 2 components.
546   // see spec 2.1 page 137 (pdf page 151) in section 3.6.4 Rasterization of
547   // Pixel Rectangles: "Conversion to RGB": this step is applied only if
548   // the format is LUMINANCE or LUMINANCE_ALPHA:
549   // L: R=L, G=L, B=L
550   // LA: R=L, G=L, B=L, A=A
551 
552   // pre-condition
553   if(vtktype==VTK_VOID && numComps != 1)
554     {
555       vtkErrorMacro("Depth component texture must have 1 component only (" <<
556                     numComps << " requested");
557       return 0;
558     }
559   const bool oldGeForce=!this->SupportsTextureInteger;
560 
561   if(oldGeForce && numComps<3)
562     {
563     numComps+=2;
564     }
565   // DON'T DEAL WITH VTK_CHAR as this is platform dependent.
566   switch (vtktype)
567     {
568   case VTK_VOID:
569     // numComps can be 3 on GeForce<8.
570     return GL_DEPTH_COMPONENT;
571 
572     case VTK_SIGNED_CHAR:
573       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
574         {
575         switch (numComps)
576           {
577           case 1:
578             return vtkgl::LUMINANCE8I_EXT;
579           case 2:
580             return vtkgl::LUMINANCE_ALPHA8I_EXT;
581           case 3:
582             return vtkgl::RGB8I_EXT;
583           case 4:
584             return vtkgl::RGBA8I_EXT;
585           }
586         }
587       else
588         {
589         switch (numComps)
590           {
591           case 1:
592             return GL_LUMINANCE8;
593           case 2:
594             return GL_LUMINANCE8_ALPHA8;
595           case 3:
596             return GL_RGB8;
597           case 4:
598             return GL_RGBA8;
599           }
600         }
601 
602     case VTK_UNSIGNED_CHAR:
603       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
604         {
605         switch (numComps)
606           {
607           case 1:
608             return vtkgl::LUMINANCE8UI_EXT;
609           case 2:
610             return vtkgl::LUMINANCE_ALPHA8UI_EXT;
611           case 3:
612             return vtkgl::RGB8UI_EXT;
613           case 4:
614             return vtkgl::RGBA8UI_EXT;
615           }
616         }
617       else
618         {
619         switch (numComps)
620           {
621           case 1:
622             return GL_LUMINANCE8;
623           case 2:
624             return GL_LUMINANCE8_ALPHA8;
625           case 3:
626             return GL_RGB8;
627           case 4:
628             return GL_RGBA8;
629           }
630         }
631 
632     case VTK_SHORT:
633       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
634         {
635         switch (numComps)
636           {
637           case 1:
638             return vtkgl::LUMINANCE16I_EXT;
639           case 2:
640             return vtkgl::LUMINANCE_ALPHA16I_EXT;
641           case 3:
642             return vtkgl::RGB16I_EXT;
643           case 4:
644             return vtkgl::RGBA16I_EXT;
645           }
646         }
647       else
648         {
649         switch (numComps)
650           {
651           case 1:
652             if(this->SupportsTextureFloat)
653               {
654               return vtkgl::LUMINANCE32F_ARB;
655 //            return GL_LUMINANCE16; // not supported as a render target
656               }
657             else
658               {
659               vtkGenericWarningMacro("Unsupported type!");
660               return 0;
661               }
662           case 2:
663             if(this->SupportsTextureFloat)
664               {
665               return vtkgl::LUMINANCE_ALPHA32F_ARB;
666               //            return GL_LUMINANCE16_ALPHA16; // not supported as a render target
667               }
668             else
669               {
670               vtkGenericWarningMacro("Unsupported type!");
671               return 0;
672               }
673           case 3:
674             return GL_RGB16;
675           case 4:
676             return GL_RGBA16;
677           }
678         }
679 
680     case VTK_UNSIGNED_SHORT:
681       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
682         {
683         switch (numComps)
684           {
685           case 1:
686             return vtkgl::LUMINANCE16UI_EXT;
687           case 2:
688             return vtkgl::LUMINANCE_ALPHA16UI_EXT;
689           case 3:
690             return vtkgl::RGB16UI_EXT;
691           case 4:
692             return vtkgl::RGBA16UI_EXT;
693           }
694         }
695       else
696         {
697         switch (numComps)
698           {
699           case 1:
700             if(this->SupportsTextureFloat)
701               {
702               return vtkgl::LUMINANCE32F_ARB;
703 //      return GL_LUMINANCE16; // not supported as a render target
704               }
705             else
706               {
707               vtkGenericWarningMacro("Unsupported type!");
708               return 0;
709               }
710           case 2:
711             if(this->SupportsTextureFloat)
712               {
713               return vtkgl::LUMINANCE_ALPHA32F_ARB;
714 //      return GL_LUMINANCE16_ALPHA16; // not supported as a render target
715               }
716             else
717               {
718                vtkGenericWarningMacro("Unsupported type!");
719                return 0;
720               }
721           case 3:
722             return GL_RGB16;
723           case 4:
724             return GL_RGBA16;
725           }
726         }
727 
728     case VTK_INT:
729       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
730         {
731         switch (numComps)
732           {
733           case 1:
734             return vtkgl::LUMINANCE32I_EXT;
735 
736           case 2:
737             return vtkgl::LUMINANCE_ALPHA32I_EXT;
738 
739           case 3:
740             return vtkgl::RGB32I_EXT;
741 
742           case 4:
743             return vtkgl::RGBA32I_EXT;
744           }
745         }
746       else
747         {
748         if(this->SupportsTextureFloat)
749           {
750           switch (numComps)
751             {
752             case 1:
753               return vtkgl::LUMINANCE32F_ARB;
754 
755             case 2:
756               return vtkgl::LUMINANCE_ALPHA32F_ARB;
757 
758             case 3:
759               return vtkgl::RGB32F_ARB;
760 
761             case 4:
762               return vtkgl::RGBA32F_ARB;
763             }
764           }
765         else
766           {
767           vtkGenericWarningMacro("Unsupported type!");
768           return 0;
769           }
770         }
771 
772     case VTK_UNSIGNED_INT:
773       if(this->SupportsTextureInteger && shaderSupportsTextureInt)
774         {
775         switch (numComps)
776           {
777           case 1:
778             return vtkgl::LUMINANCE32UI_EXT;
779 
780           case 2:
781             return vtkgl::LUMINANCE_ALPHA32UI_EXT;
782 
783           case 3:
784             return vtkgl::RGB32UI_EXT;
785 
786           case 4:
787             return vtkgl::RGBA32UI_EXT;
788           }
789         }
790       else
791         {
792         if(this->SupportsTextureFloat)
793           {
794           switch (numComps)
795             {
796             case 1:
797               return vtkgl::LUMINANCE32F_ARB;
798 
799             case 2:
800               return vtkgl::LUMINANCE_ALPHA32F_ARB;
801 
802             case 3:
803               return vtkgl::RGB32F_ARB;
804 
805             case 4:
806               return vtkgl::RGBA32F_ARB;
807             }
808           }
809         else
810           {
811           vtkGenericWarningMacro("Unsupported type!");
812           return 0;
813           }
814         }
815 
816     case VTK_FLOAT:
817       if(this->SupportsTextureFloat)
818         {
819         switch (numComps)
820           {
821           case 1:
822             return vtkgl::LUMINANCE32F_ARB;
823 
824           case 2:
825             return vtkgl::LUMINANCE_ALPHA32F_ARB;
826 
827           case 3:
828             return vtkgl::RGB32F_ARB;
829 
830           case 4:
831             return vtkgl::RGBA32F_ARB;
832           }
833         }
834       else
835         {
836         vtkGenericWarningMacro("Unsupported type!");
837         return 0;
838         }
839     case VTK_DOUBLE:
840       vtkGenericWarningMacro("Unsupported type double!");
841     }
842   return 0;
843 }
844 
GetFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)845 unsigned int vtkTextureObject::GetFormat(int vtktype, int numComps,
846                                          bool shaderSupportsTextureInt)
847 {
848   if (vtktype == VTK_VOID)
849     {
850     return GL_DEPTH_COMPONENT;
851     }
852 
853   if(this->SupportsTextureInteger && shaderSupportsTextureInt
854      && (vtktype==VTK_SIGNED_CHAR||vtktype==VTK_UNSIGNED_CHAR||
855          vtktype==VTK_SHORT||vtktype==VTK_UNSIGNED_SHORT||vtktype==VTK_INT||
856        vtktype==VTK_UNSIGNED_INT))
857     {
858     switch (numComps)
859       {
860       case 1:
861         return vtkgl::LUMINANCE_INTEGER_EXT;
862       case 2:
863         return vtkgl::LUMINANCE_ALPHA_INTEGER_EXT;
864       case 3:
865         return vtkgl::RGB_INTEGER_EXT;
866       case 4:
867         return vtkgl::RGBA_INTEGER_EXT;
868       }
869     }
870   else
871     {
872     switch (numComps)
873       {
874       case 1:
875         return GL_LUMINANCE;
876       case 2:
877         return GL_LUMINANCE_ALPHA;
878       case 3:
879         return GL_RGB;
880       case 4:
881         return GL_RGBA;
882       }
883     }
884   return 0;
885 }
886 
vtkGetType(int vtk_scalar_type)887 static GLenum vtkGetType(int vtk_scalar_type)
888 {
889   // DON'T DEAL with VTK_CHAR as this is platform dependent.
890 
891   switch (vtk_scalar_type)
892     {
893   case VTK_SIGNED_CHAR:
894     return GL_BYTE;
895 
896   case VTK_UNSIGNED_CHAR:
897     return GL_UNSIGNED_BYTE;
898 
899   case VTK_SHORT:
900     return GL_SHORT;
901 
902   case VTK_UNSIGNED_SHORT:
903     return GL_UNSIGNED_SHORT;
904 
905   case VTK_INT:
906     return GL_INT;
907 
908   case VTK_UNSIGNED_INT:
909     return GL_UNSIGNED_INT;
910 
911   case VTK_FLOAT:
912   case VTK_VOID: // used for depth component textures.
913     return GL_FLOAT;
914     }
915   return 0;
916 }
917 
vtkGetVTKType(GLenum gltype)918 static int vtkGetVTKType(GLenum gltype)
919 {
920    // DON'T DEAL with VTK_CHAR as this is platform dependent.
921   switch (gltype)
922     {
923   case GL_BYTE:
924     return VTK_SIGNED_CHAR;
925 
926   case GL_UNSIGNED_BYTE:
927     return VTK_UNSIGNED_CHAR;
928 
929   case GL_SHORT:
930     return VTK_SHORT;
931 
932   case GL_UNSIGNED_SHORT:
933     return VTK_UNSIGNED_SHORT;
934 
935   case GL_INT:
936     return VTK_INT;
937 
938   case GL_UNSIGNED_INT:
939     return VTK_UNSIGNED_INT;
940 
941   case GL_FLOAT:
942     return VTK_FLOAT;
943     }
944 
945   return 0;
946 }
947 
948 //----------------------------------------------------------------------------
GetDataType()949 int vtkTextureObject::GetDataType()
950 {
951   return ::vtkGetVTKType(this->Type);
952 }
953 
954 //----------------------------------------------------------------------------
Create1D(int numComps,vtkPixelBufferObject * pbo,bool shaderSupportsTextureInt)955 bool vtkTextureObject::Create1D(int numComps,
956                                 vtkPixelBufferObject* pbo,
957                                 bool shaderSupportsTextureInt)
958 {
959 #ifdef VTK_TO_TIMING
960   vtkTimerLog *timer=vtkTimerLog::New();
961   timer->StartTimer();
962 #endif
963   assert(this->Context);
964   assert(pbo->GetContext() == this->Context);
965 
966   GLenum target = GL_TEXTURE_1D;
967 
968   // Now, detemine texture parameters using the information from the pbo.
969 
970   // * internalFormat depends on number of components and the data type.
971   GLenum internalFormat = this->GetInternalFormat(pbo->GetType(), numComps,
972                                                  shaderSupportsTextureInt);
973 
974   // * format depends on the number of components.
975   GLenum format = this->GetFormat(pbo->GetType(), numComps,
976                                  shaderSupportsTextureInt);
977 
978   // * type if the data type in the pbo
979   GLenum type = ::vtkGetType(pbo->GetType());
980 
981   if (!internalFormat || !format || !type)
982     {
983     vtkErrorMacro("Failed to detemine texture parameters.");
984     return false;
985     }
986 
987   this->Target = target;
988   this->CreateTexture();
989   this->Bind();
990 
991   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
992 
993   // Source texture data from the PBO.
994   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
995   glTexImage1D(target, 0, static_cast<GLint>(internalFormat),
996                static_cast<GLsizei>(pbo->GetSize()/
997                                     static_cast<unsigned int>(numComps)),
998                0, format,
999                type, BUFFER_OFFSET(0));
1000   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
1001   pbo->UnBind();
1002   this->UnBind();
1003 
1004   this->Target = target;
1005   this->Format = format;
1006   this->Type = type;
1007   this->Components = numComps;
1008   this->Width = pbo->GetSize();
1009   this->Height = 1;
1010   this->Depth =1;
1011   this->NumberOfDimensions=1;
1012 #ifdef VTK_TO_TIMING
1013   timer->StopTimer();
1014   double time=timer->GetElapsedTime();
1015   timer->Delete();
1016   cerr<<"upload PBO to 1D texture time="<<time<<" seconds."<<endl;
1017 #endif
1018   return true;
1019 }
1020 
1021 //----------------------------------------------------------------------------
Create2D(unsigned int width,unsigned int height,int numComps,vtkPixelBufferObject * pbo,bool shaderSupportsTextureInt)1022 bool vtkTextureObject::Create2D(unsigned int width, unsigned int height,
1023                                 int numComps, vtkPixelBufferObject* pbo,
1024                                 bool shaderSupportsTextureInt)
1025 {
1026 #ifdef VTK_TO_TIMING
1027   vtkTimerLog *timer=vtkTimerLog::New();
1028   timer->StartTimer();
1029 #endif
1030   assert(this->Context);
1031   assert(pbo->GetContext() == this->Context);
1032 
1033   if (pbo->GetSize() < width*height*static_cast<unsigned int>(numComps))
1034     {
1035     vtkErrorMacro("PBO size must match texture size.");
1036     return false;
1037     }
1038 
1039   // Now, detemine texture parameters using the information from the pbo.
1040   // * internalFormat depends on number of components and the data type.
1041   // * format depends on the number of components.
1042   // * type if the data type in the pbo
1043 
1044   int vtktype = pbo->GetType();
1045   GLenum type = ::vtkGetType(vtktype);
1046 
1047   GLenum internalFormat
1048     = this->GetInternalFormat(vtktype, numComps, shaderSupportsTextureInt);
1049 
1050   GLenum format
1051     = this->GetFormat(vtktype, numComps, shaderSupportsTextureInt);
1052 
1053   if (!internalFormat || !format || !type)
1054     {
1055     vtkErrorMacro("Failed to detemine texture parameters.");
1056     return false;
1057     }
1058 
1059   GLenum target = GL_TEXTURE_2D;
1060   this->Target = target;
1061   this->CreateTexture();
1062   this->Bind();
1063 
1064   // Source texture data from the PBO.
1065   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1066   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1067 
1068   glTexImage2D(
1069         target,
1070         0,
1071         internalFormat,
1072         static_cast<GLsizei>(width),
1073         static_cast<GLsizei>(height),
1074         0,
1075         format,
1076         type,
1077         BUFFER_OFFSET(0));
1078 
1079   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1080 
1081   pbo->UnBind();
1082   this->UnBind();
1083 
1084   this->Target = target;
1085   this->Format = format;
1086   this->Type = type;
1087   this->Components = numComps;
1088   this->Width = width;
1089   this->Height = height;
1090   this->Depth = 1;
1091   this->NumberOfDimensions = 2;
1092 
1093 #ifdef VTK_TO_TIMING
1094   timer->StopTimer();
1095   double time=timer->GetElapsedTime();
1096   timer->Delete();
1097   cerr<<"upload PBO to 2D texture time="<<time<<" seconds."<<endl;
1098 #endif
1099   return true;
1100 }
1101 
1102 // ----------------------------------------------------------------------------
1103 // Description:
1104 // Create a 2D depth texture using a PBO.
CreateDepth(unsigned int width,unsigned int height,int internalFormat,vtkPixelBufferObject * pbo)1105 bool vtkTextureObject::CreateDepth(unsigned int width,
1106                                    unsigned int height,
1107                                    int internalFormat,
1108                                    vtkPixelBufferObject *pbo)
1109 {
1110   assert("pre: context_exists" && this->GetContext()!=0);
1111   assert("pre: pbo_context_exists" && pbo->GetContext()!=0);
1112   assert("pre: context_match" && this->GetContext()==pbo->GetContext());
1113   assert("pre: sizes_match" && pbo->GetSize()==width*height);
1114   assert("pre: valid_internalFormat" && internalFormat>=0
1115          && internalFormat<NumberOfDepthFormats);
1116 
1117 #ifdef VTK_TO_DEBUG
1118   cerr << "pbo size=" << pbo->GetSize() << endl;
1119   cerr << "width=" << width << endl;
1120   cerr << "height=" << height << endl;
1121   cerr << "width*height=" << width*height << endl;
1122 #endif
1123 
1124   GLenum inFormat=OpenGLDepthInternalFormat[internalFormat];
1125   GLenum type=::vtkGetType(pbo->GetType());
1126 
1127   this->Target=GL_TEXTURE_2D;
1128   this->Format=GL_DEPTH_COMPONENT;
1129   this->Type=type;
1130   this->Width=width;
1131   this->Height=height;
1132   this->Depth=1;
1133   this->NumberOfDimensions=2;
1134   this->Components=1;
1135 
1136   this->CreateTexture();
1137   this->Bind();
1138 
1139   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1140 
1141   // Source texture data from the PBO.
1142   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1143   glTexImage2D(this->Target, 0, static_cast<GLint>(inFormat),
1144                static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0,
1145                this->Format, this->Type, BUFFER_OFFSET(0));
1146   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1147   pbo->UnBind();
1148   this->UnBind();
1149   return true;
1150 }
1151 
1152 // ----------------------------------------------------------------------------
1153 // Description:
1154 // Create a 2D depth texture using a raw pointer.
1155 // This is a blocking call. If you can, use PBO instead.
CreateDepthFromRaw(unsigned int width,unsigned int height,int internalFormat,int rawType,void * raw)1156 bool vtkTextureObject::CreateDepthFromRaw(unsigned int width,
1157                                           unsigned int height,
1158                                           int internalFormat,
1159                                           int rawType,
1160                                           void *raw)
1161 {
1162   assert("pre: context_exists" && this->GetContext()!=0);
1163   assert("pre: raw_exists" && raw!=0);
1164 
1165 #ifdef VTK_TO_DEBUG
1166   cerr << "width=" << width << endl;
1167   cerr << "height=" << height << endl;
1168   cerr << "width*height=" << width*height << endl;
1169 #endif
1170 
1171   assert("pre: valid_internalFormat" && internalFormat>=0
1172          && internalFormat<NumberOfDepthFormats);
1173 
1174   GLenum inFormat=OpenGLDepthInternalFormat[internalFormat];
1175   GLenum type=::vtkGetType(rawType);
1176 
1177   this->Target=GL_TEXTURE_2D;
1178   this->Format=GL_DEPTH_COMPONENT;
1179   this->Type=type;
1180   this->Width=width;
1181   this->Height=height;
1182   this->Depth=1;
1183   this->NumberOfDimensions=2;
1184   this->Components=1;
1185 
1186   this->CreateTexture();
1187   this->Bind();
1188 
1189   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1190   glTexImage2D(this->Target, 0, static_cast<GLint>(inFormat),
1191                static_cast<GLsizei>(width), static_cast<GLsizei>(height), 0,
1192                this->Format, this->Type,raw);
1193   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1194   this->UnBind();
1195   return true;
1196 }
1197 
1198 // ----------------------------------------------------------------------------
AllocateDepth(unsigned int width,unsigned int height,int internalFormat)1199 bool vtkTextureObject::AllocateDepth(unsigned int width,unsigned int height,
1200                                      int internalFormat)
1201 {
1202   assert("pre: context_exists" && this->GetContext()!=0);
1203   assert("pre: valid_internalFormat" && internalFormat>=0
1204          && internalFormat<NumberOfDepthFormats);
1205 
1206   this->Target=GL_TEXTURE_2D;
1207   this->Format=GL_DEPTH_COMPONENT;
1208   // try to match vtk type to internal fmt
1209   this->Type=OpenGLDepthInternalFormatType[internalFormat];
1210   this->Width=width;
1211   this->Height=height;
1212   this->Depth=1;
1213   this->NumberOfDimensions=2;
1214   this->Components=1;
1215 
1216   this->CreateTexture();
1217   this->Bind();
1218 
1219   GLenum inFormat=OpenGLDepthInternalFormat[internalFormat];
1220   glTexImage2D(
1221           this->Target,
1222           0,
1223           static_cast<GLint>(inFormat),
1224           static_cast<GLsizei>(width),
1225           static_cast<GLsizei>(height),
1226           0,
1227           this->Format,
1228           this->Type,
1229           0);
1230 
1231   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1232 
1233   this->UnBind();
1234   return true;
1235 }
1236 
1237 // ----------------------------------------------------------------------------
Allocate1D(unsigned int width,int numComps,int vtkType)1238 bool vtkTextureObject::Allocate1D(unsigned int width, int numComps,
1239                                   int vtkType)
1240 {
1241   assert(this->Context);
1242 
1243   this->Target=GL_TEXTURE_1D;
1244   GLenum internalFormat = this->GetInternalFormat(vtkType, numComps,
1245                                                   false);
1246 
1247   // don't care, allocation only, no data transfer
1248   GLenum format = this->GetFormat(vtkType, numComps,false);
1249 
1250   GLenum type = ::vtkGetType(vtkType);
1251 
1252   this->Format = format;
1253   this->Type = type;
1254   this->Components = numComps;
1255   this->Width = width;
1256   this->Height = 1;
1257   this->Depth =1;
1258   this->NumberOfDimensions=1;
1259 
1260   this->CreateTexture();
1261   this->Bind();
1262   glTexImage1D(this->Target, 0, static_cast<GLint>(internalFormat),
1263                static_cast<GLsizei>(width),0, format, type,0);
1264   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
1265   this->UnBind();
1266   return true;
1267 }
1268 
1269 // ----------------------------------------------------------------------------
1270 // Description:
1271 // Create a 2D color texture but does not initialize its values.
1272 // Internal format is deduced from numComps and vtkType.
Allocate2D(unsigned int width,unsigned int height,int numComps,int vtkType)1273 bool vtkTextureObject::Allocate2D(unsigned int width,unsigned int height,
1274                                   int numComps,int vtkType)
1275 {
1276   assert(this->Context);
1277 
1278   this->Target=GL_TEXTURE_2D;
1279 
1280   GLenum internalFormat = this->GetInternalFormat(vtkType, numComps,
1281                                                   false);
1282 
1283   // don't care, allocation only, no data transfer
1284   GLenum format = this->GetFormat(vtkType, numComps,false);
1285 
1286   GLenum type = ::vtkGetType(vtkType);
1287 
1288   this->Format = format;
1289   this->Type = type;
1290   this->Components = numComps;
1291   this->Width = width;
1292   this->Height = height;
1293   this->Depth =1;
1294   this->NumberOfDimensions=2;
1295 
1296   this->CreateTexture();
1297   this->Bind();
1298   glTexImage2D(this->Target, 0, static_cast<GLint>(internalFormat),
1299                static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1300                0, format, type,0);
1301   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1302   this->UnBind();
1303   return true;
1304 }
1305 
1306 // ----------------------------------------------------------------------------
1307 // Description:
1308 // Create a 3D color texture but does not initialize its values.
1309 // Internal format is deduced from numComps and vtkType.
Allocate3D(unsigned int width,unsigned int height,unsigned int depth,int numComps,int vtkType)1310 bool vtkTextureObject::Allocate3D(unsigned int width,unsigned int height,
1311                                   unsigned int depth, int numComps,
1312                                   int vtkType)
1313 {
1314   this->Target=vtkgl::TEXTURE_3D;
1315 
1316   if(this->Context==0)
1317     {
1318     vtkErrorMacro("No context specified. Cannot create texture.");
1319     return false;
1320     }
1321   GLenum internalFormat = this->GetInternalFormat(vtkType, numComps,
1322                                                   false);
1323 
1324   // don't care, allocation only, no data transfer
1325   GLenum format = this->GetFormat(vtkType, numComps,false);
1326 
1327   GLenum type = ::vtkGetType(vtkType);
1328 
1329   this->Format = format;
1330   this->Type = type;
1331   this->Components = numComps;
1332   this->Width = width;
1333   this->Height = height;
1334   this->Depth =depth;
1335   this->NumberOfDimensions=3;
1336 
1337   this->CreateTexture();
1338   this->Bind();
1339   vtkgl::TexImage3D(this->Target, 0, static_cast<GLint>(internalFormat),
1340                     static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1341                     static_cast<GLsizei>(depth), 0, format, type,0);
1342   vtkOpenGLCheckErrorMacro("failed at glTexImage3D");
1343   this->UnBind();
1344   return true;
1345 }
1346 
1347 //----------------------------------------------------------------------------
Create3D(unsigned int width,unsigned int height,unsigned int depth,int numComps,vtkPixelBufferObject * pbo,bool shaderSupportsTextureInt)1348 bool vtkTextureObject::Create3D(unsigned int width, unsigned int height,
1349                                 unsigned int depth, int numComps,
1350                                 vtkPixelBufferObject* pbo,
1351                                 bool shaderSupportsTextureInt)
1352 {
1353 #ifdef VTK_TO_TIMING
1354   vtkTimerLog *timer=vtkTimerLog::New();
1355   timer->StartTimer();
1356 #endif
1357   assert(this->Context);
1358   assert(this->Context == pbo->GetContext());
1359 
1360   if (pbo->GetSize() != width*height*depth*static_cast<unsigned int>(numComps))
1361     {
1362     vtkErrorMacro("PBO size must match texture size.");
1363     return false;
1364     }
1365 
1366   GLenum target = vtkgl::TEXTURE_3D;
1367 
1368   // Now, detemine texture parameters using the information from the pbo.
1369 
1370   // * internalFormat depends on number of components and the data type.
1371   GLenum internalFormat = this->GetInternalFormat(pbo->GetType(), numComps,
1372                                                  shaderSupportsTextureInt);
1373 
1374   // * format depends on the number of components.
1375   GLenum format = this->GetFormat(pbo->GetType(), numComps,
1376                                   shaderSupportsTextureInt);
1377 
1378   // * type if the data type in the pbo
1379   GLenum type = ::vtkGetType(pbo->GetType());
1380 
1381   if (!internalFormat || !format || !type)
1382     {
1383     vtkErrorMacro("Failed to detemine texture parameters.");
1384     return false;
1385     }
1386 
1387   this->Target = target;
1388   this->CreateTexture();
1389   this->Bind();
1390 
1391   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1392 
1393   // Source texture data from the PBO.
1394   vtkgl::TexImage3D(target, 0, static_cast<GLint>(internalFormat),
1395                     static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1396                     static_cast<GLsizei>(depth), 0, format, type,
1397                     BUFFER_OFFSET(0));
1398 
1399   vtkOpenGLCheckErrorMacro("failed at glTexImage3D");
1400 
1401   pbo->UnBind();
1402   this->UnBind();
1403 
1404   this->Target = target;
1405   this->Format = format;
1406   this->Type = type;
1407   this->Components = numComps;
1408   this->Width = width;
1409   this->Height = height;
1410   this->Depth = depth;
1411   this->NumberOfDimensions = 3;
1412 
1413 #ifdef VTK_TO_TIMING
1414   timer->StopTimer();
1415   double time=timer->GetElapsedTime();
1416   timer->Delete();
1417   cerr<<"upload PBO to 3D texture time="<<time<<" seconds."<<endl;
1418 #endif
1419   return true;
1420 }
1421 
1422 //----------------------------------------------------------------------------
Download()1423 vtkPixelBufferObject* vtkTextureObject::Download()
1424 {
1425 #ifdef VTK_TO_TIMING
1426   vtkTimerLog *timer=vtkTimerLog::New();
1427   timer->StartTimer();
1428 #endif
1429   assert(this->Context);
1430   assert(this->Handle);
1431 
1432   vtkPixelBufferObject* pbo = vtkPixelBufferObject::New();
1433   pbo->SetContext(this->Context);
1434 
1435   int vtktype = ::vtkGetVTKType(this->Type);
1436   if (vtktype == 0)
1437     {
1438     vtkErrorMacro("Failed to determine type.");
1439     return 0;
1440     }
1441 
1442   unsigned int size = this->Width* this->Height* this->Depth;
1443 
1444   // doesn't matter which Upload*D method we use since we are not really
1445   // uploading any data, simply allocating GPU space.
1446   if (!pbo->Upload1D(vtktype, NULL, size, this->Components, 0))
1447     {
1448     vtkErrorMacro("Could not allocate memory for PBO.");
1449     pbo->Delete();
1450     return 0;
1451     }
1452 
1453   pbo->Bind(vtkPixelBufferObject::PACKED_BUFFER);
1454   this->Bind();
1455   glGetTexImage(this->Target, 0, this->Format, this->Type, BUFFER_OFFSET(0));
1456   vtkOpenGLCheckErrorMacro("failed at glGetTexImage");
1457   this->UnBind();
1458   pbo->UnBind();
1459 
1460   pbo->SetComponents(this->Components);
1461 
1462 #ifdef VTK_TO_TIMING
1463   timer->StopTimer();
1464   double time=timer->GetElapsedTime();
1465   timer->Delete();
1466   cerr<<"download texture to PBO, time="<<time<<" seconds."<<endl;
1467 #endif
1468 
1469   return pbo;
1470 }
1471 
1472 //----------------------------------------------------------------------------
Create2D(unsigned int width,unsigned int height,int numComps,int vtktype,bool shaderSupportsTextureInt)1473 bool vtkTextureObject::Create2D(unsigned int width, unsigned int height,
1474                                 int numComps, int vtktype,
1475                                 bool shaderSupportsTextureInt)
1476 {
1477   assert(this->Context);
1478 
1479   GLenum target = GL_TEXTURE_2D;
1480 
1481   // Now, detemine texture parameters using the information provided.
1482   // * internalFormat depends on number of components and the data type.
1483   GLenum internalFormat = this->GetInternalFormat(vtktype, numComps,
1484                                                  shaderSupportsTextureInt);
1485 
1486   // * format depends on the number of components.
1487   GLenum format = this->GetFormat(vtktype, numComps,
1488                                  shaderSupportsTextureInt);
1489 
1490   // * type if the data type in the pbo
1491   GLenum type = ::vtkGetType(vtktype);
1492 
1493   if (!internalFormat || !format || !type)
1494     {
1495     vtkErrorMacro("Failed to detemine texture parameters.");
1496     return false;
1497     }
1498 
1499   this->Target = target;
1500   this->CreateTexture();
1501   this->Bind();
1502 
1503   // Allocate space for texture, don't upload any data.
1504   glTexImage2D(target, 0, static_cast<GLint>(internalFormat),
1505                static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1506                0, format, type, NULL);
1507   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1508   this->UnBind();
1509 
1510   this->Target = target;
1511   this->Format = format;
1512   this->Type = type;
1513   this->Components = numComps;
1514   this->Width = width;
1515   this->Height = height;
1516   this->Depth = 1;
1517   this->NumberOfDimensions = 2;
1518   return true;
1519 }
1520 
1521 //----------------------------------------------------------------------------
Create3D(unsigned int width,unsigned int height,unsigned int depth,int numComps,int vtktype,bool shaderSupportsTextureInt)1522 bool vtkTextureObject::Create3D(unsigned int width, unsigned int height,
1523                                 unsigned int depth,
1524                                 int numComps, int vtktype,
1525                                 bool shaderSupportsTextureInt)
1526 {
1527   assert(this->Context);
1528 
1529   GLenum target = vtkgl::TEXTURE_3D;
1530 
1531   // Now, detemine texture parameters using the information provided.
1532   // * internalFormat depends on number of components and the data type.
1533   GLenum internalFormat = this->GetInternalFormat(vtktype, numComps,
1534                                                  shaderSupportsTextureInt);
1535 
1536   // * format depends on the number of components.
1537   GLenum format = this->GetFormat(vtktype, numComps,
1538                                  shaderSupportsTextureInt);
1539 
1540   // * type if the data type in the pbo
1541   GLenum type = ::vtkGetType(vtktype);
1542 
1543   if (!internalFormat || !format || !type)
1544     {
1545     vtkErrorMacro("Failed to detemine texture parameters.");
1546     return false;
1547     }
1548 
1549   this->Target = target;
1550   this->CreateTexture();
1551   this->Bind();
1552 
1553   // Allocate space for texture, don't upload any data.
1554   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1555   vtkgl::TexImage3D(target, 0, static_cast<GLint>(internalFormat),
1556                     static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1557                     static_cast<GLsizei>(depth), 0, format, type, NULL);
1558   vtkOpenGLCheckErrorMacro("falied at glTexImage3D");
1559   this->UnBind();
1560 
1561   this->Target = target;
1562   this->Format = format;
1563   this->Type = type;
1564   this->Components = numComps;
1565   this->Width = width;
1566   this->Height = height;
1567   this->Depth = depth;
1568   this->NumberOfDimensions = 3;
1569   return true;
1570 }
1571 
1572 // ----------------------------------------------------------------------------
CopyToFrameBuffer(int srcXmin,int srcYmin,int srcXmax,int srcYmax,int dstXmin,int dstYmin,int width,int height)1573 void vtkTextureObject::CopyToFrameBuffer(int srcXmin,
1574                                          int srcYmin,
1575                                          int srcXmax,
1576                                          int srcYmax,
1577                                          int dstXmin,
1578                                          int dstYmin,
1579                                          int width,
1580                                          int height)
1581 {
1582   assert("pre: positive_srcXmin" && srcXmin>=0);
1583   assert("pre: max_srcXmax" &&
1584          static_cast<unsigned int>(srcXmax)<this->GetWidth());
1585   assert("pre: increasing_x" && srcXmin<=srcXmax);
1586   assert("pre: positive_srcYmin" && srcYmin>=0);
1587   assert("pre: max_srcYmax" &&
1588          static_cast<unsigned int>(srcYmax)<this->GetHeight());
1589   assert("pre: increasing_y" && srcYmin<=srcYmax);
1590   assert("pre: positive_dstXmin" && dstXmin>=0);
1591   assert("pre: positive_dstYmin" && dstYmin>=0);
1592   assert("pre: positive_width" && width>0);
1593   assert("pre: positive_height" && height>0);
1594   assert("pre: x_fit" && dstXmin+(srcXmax-srcXmin)<width);
1595   assert("pre: y_fit" && dstYmin+(srcYmax-srcYmin)<height);
1596 
1597   vtkOpenGLClearErrorMacro();
1598 
1599   glMatrixMode(GL_PROJECTION);
1600   glPushMatrix();
1601   glLoadIdentity();
1602   glOrtho(0.0,width,0.0,height,-1,1);
1603   glMatrixMode(GL_MODELVIEW);
1604   glPushMatrix();
1605   glLoadIdentity();
1606 
1607   glPushAttrib(GL_VIEWPORT_BIT|GL_POLYGON_BIT|GL_TEXTURE_BIT);
1608   vtkgl::ActiveTexture(vtkgl::TEXTURE0);
1609   glMatrixMode(GL_TEXTURE);
1610   glPushMatrix();
1611   glLoadIdentity();
1612 
1613   glViewport(0,0,width,height);
1614   glDepthRange(0.0,1.0);
1615   glDisable(GL_POLYGON_OFFSET_FILL);
1616 
1617   GLfloat minXTexCoord=static_cast<GLfloat>(
1618     static_cast<double>(srcXmin)/this->Width);
1619   GLfloat minYTexCoord=static_cast<GLfloat>(
1620     static_cast<double>(srcYmin)/this->Height);
1621 
1622   GLfloat maxXTexCoord=static_cast<GLfloat>(
1623     static_cast<double>(srcXmax+1)/this->Width);
1624   GLfloat maxYTexCoord=static_cast<GLfloat>(
1625     static_cast<double>(srcYmax+1)/this->Height);
1626 
1627   GLfloat dstXmax=static_cast<GLfloat>(dstXmin+srcXmax-srcXmin);
1628   GLfloat dstYmax=static_cast<GLfloat>(dstYmin+srcYmax-srcYmin);
1629 
1630   // rasterization rules are different from points, lines and polygons.
1631   // the following vertex coordinates are only valid for 1:1 mapping in the
1632   // case of polygons.
1633 
1634   // Draw a quad.
1635   glBegin(GL_TRIANGLE_FAN);
1636   glTexCoord2f(minXTexCoord,minYTexCoord);
1637   glVertex2f(static_cast<GLfloat>(dstXmin), static_cast<GLfloat>(dstYmin));
1638   glTexCoord2f(maxXTexCoord, minYTexCoord);
1639   glVertex2f(dstXmax+1, static_cast<GLfloat>(dstYmin));
1640   glTexCoord2f(maxXTexCoord, maxYTexCoord);
1641   glVertex2f(dstXmax+1, dstYmax+1);
1642   glTexCoord2f(minXTexCoord, maxYTexCoord);
1643   glVertex2f(static_cast<GLfloat>(dstXmin), dstYmax+1);
1644   glEnd();
1645 
1646   glMatrixMode(GL_TEXTURE);
1647   glPopMatrix();
1648 
1649   glPopAttrib();
1650   glMatrixMode(GL_PROJECTION);
1651   glPopMatrix();
1652   glMatrixMode(GL_MODELVIEW);
1653   glPopMatrix();
1654 
1655   vtkOpenGLCheckErrorMacro("failed after CopyToFrameBuffer")
1656 }
1657 
1658 //----------------------------------------------------------------------------
1659 // Description:
1660 // Copy a sub-part of a logical buffer of the framebuffer (color or depth)
1661 // to the texture object. src is the framebuffer, dst is the texture.
1662 // (srcXmin,srcYmin) is the location of the lower left corner of the
1663 // rectangle in the framebuffer. (dstXmin,dstYmin) is the location of the
1664 // lower left corner of the rectangle in the texture. width and height
1665 // specifies the size of the rectangle in pixels.
1666 // If the logical buffer is a color buffer, it has to be selected first with
1667 // glReadBuffer().
1668 // \pre is2D: GetNumberOfDimensions()==2
CopyFromFrameBuffer(int srcXmin,int srcYmin,int dstXmin,int dstYmin,int width,int height)1669 void vtkTextureObject::CopyFromFrameBuffer(int srcXmin,
1670                                            int srcYmin,
1671                                            int dstXmin,
1672                                            int dstYmin,
1673                                            int width,
1674                                            int height)
1675 {
1676   assert("pre: is2D" && this->GetNumberOfDimensions()==2);
1677   this->Bind();
1678   glCopyTexSubImage2D(this->Target,0,dstXmin,dstYmin,srcXmin,srcYmin,width,
1679                       height);
1680   vtkOpenGLCheckErrorMacro("failed at glCopyTexSubImage2D");
1681   this->UnBind();
1682 }
1683 
1684 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)1685 void vtkTextureObject::PrintSelf(ostream& os, vtkIndent indent)
1686 {
1687   this->Superclass::PrintSelf(os, indent);
1688 
1689   os << indent << "Width: " << this->Width << endl;
1690   os << indent << "Height: " << this->Height << endl;
1691   os << indent << "Depth: " << this->Depth << endl;
1692   os << indent << "Components: " << this->Components << endl;
1693   os << indent << "Handle: " << this->Handle << endl;
1694   os << indent << "Target: ";
1695 
1696   switch(this->Target)
1697     {
1698     case GL_TEXTURE_1D:
1699       os << "GL_TEXTURE_1D" << endl;
1700       break;
1701     case  GL_TEXTURE_2D:
1702       os << "GL_TEXTURE_2D" << endl;
1703       break;
1704     case  vtkgl::TEXTURE_3D:
1705       os << "vtkgl::TEXTURE_3D" << endl;
1706       break;
1707     default:
1708       os << "unknown value: 0x" << hex << this->Target << dec <<endl;
1709       break;
1710     }
1711 
1712   os << indent << "NumberOfDimensions: " << this->NumberOfDimensions << endl;
1713 
1714   os << indent << "WrapS: " << WrapAsString[this->WrapS] << endl;
1715   os << indent << "WrapT: " << WrapAsString[this->WrapT] << endl;
1716   os << indent << "WrapR: " << WrapAsString[this->WrapR] << endl;
1717 
1718   os << indent << "MinificationFilter: "
1719      << MinMagFilterAsString[this->MinificationFilter] << endl;
1720 
1721   os << indent << "MagnificationFilter: "
1722      << MinMagFilterAsString[this->MagnificationFilter] << endl;
1723 
1724   os << indent << "LinearMagnification: " << this->LinearMagnification << endl;
1725 
1726   os << indent << "BorderColor: (" << this->BorderColor[0] << ","
1727      << this->BorderColor[1] << "," << this->BorderColor[2] << ","
1728      << this->BorderColor[3] << endl;
1729 
1730   os << indent << "Priority: " << this->Priority <<  endl;
1731   os << indent << "MinLOD: " << this->MinLOD << endl;
1732   os << indent << "MaxLOD: " << this->MaxLOD << endl;
1733   os << indent << "BaseLevel: " << this->BaseLevel << endl;
1734   os << indent << "MaxLevel: " << this->MaxLevel << endl;
1735   os << indent << "DepthTextureCompare: " << this->DepthTextureCompare
1736      << endl;
1737   os << indent << "DepthTextureCompareFunction: "
1738      << DepthTextureCompareFunctionAsString[this->DepthTextureCompareFunction]
1739      << endl;
1740   os << indent << "DepthTextureMode: "
1741      << DepthTextureModeAsString[this->DepthTextureMode] << endl;
1742   os << indent << "GenerateMipmap: " << this->GenerateMipmap << endl;
1743 }
1744