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 "vtk_glew.h"
18 
19 #include "vtkObjectFactory.h"
20 
21 #include "vtkNew.h"
22 #include "vtkOpenGLBufferObject.h"
23 #include "vtkOpenGLError.h"
24 #include "vtkOpenGLFramebufferObject.h"
25 #include "vtkOpenGLRenderUtilities.h"
26 #include "vtkOpenGLRenderWindow.h"
27 #include "vtkOpenGLResourceFreeCallback.h"
28 #include "vtkOpenGLShaderCache.h"
29 #include "vtkOpenGLState.h"
30 #include "vtkOpenGLTexture.h"
31 #include "vtkOpenGLVertexArrayObject.h"
32 #include "vtkPixelBufferObject.h"
33 #include "vtkRenderer.h"
34 #include "vtkShaderProgram.h"
35 
36 #include "vtkOpenGLHelper.h"
37 
38 #include <cassert>
39 
40 //#define VTK_TO_DEBUG
41 //#define VTK_TO_TIMING
42 
43 #ifdef VTK_TO_TIMING
44 #include "vtkTimerLog.h"
45 #endif
46 
47 #include "vtkTextureObjectFS.h"
48 #include "vtkTextureObjectVS.h" // a pass through shader
49 
50 #define BUFFER_OFFSET(i) (reinterpret_cast<char*>(i))
51 
52 // Mapping from DepthTextureCompareFunction values to OpenGL values.
53 //------------------------------------------------------------------------------
54 static GLint OpenGLDepthTextureCompareFunction[8] = { GL_LEQUAL, GL_GEQUAL, GL_LESS, GL_GREATER,
55   GL_EQUAL, GL_NOTEQUAL, GL_ALWAYS, GL_NEVER };
56 
57 //------------------------------------------------------------------------------
58 static const char* DepthTextureCompareFunctionAsString[8] = { "Lequal", "Gequal", "Less", "Greater",
59   "Equal", "NotEqual", "AlwaysTrue", "Never" };
60 
61 // Mapping from Wrap values to OpenGL values
62 #ifndef GL_ES_VERSION_3_0
63 //------------------------------------------------------------------------------
64 static GLint OpenGLWrap[4] = { GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT,
65   GL_CLAMP_TO_BORDER };
66 
67 //------------------------------------------------------------------------------
68 static const char* WrapAsString[4] = { "ClampToEdge", "Repeat", "MirroredRepeat", "ClampToBorder" };
69 
70 #else
71 //------------------------------------------------------------------------------
72 static GLint OpenGLWrap[3] = { GL_CLAMP_TO_EDGE, GL_REPEAT, GL_MIRRORED_REPEAT };
73 
74 //------------------------------------------------------------------------------
75 static const char* WrapAsString[3] = { "ClampToEdge", "Repeat", "MirroredRepeat" };
76 
77 #endif
78 
79 // Mapping MinificationFilter values to OpenGL values.
80 //------------------------------------------------------------------------------
81 static GLint OpenGLMinFilter[6] = { GL_NEAREST, GL_LINEAR, GL_NEAREST_MIPMAP_NEAREST,
82   GL_NEAREST_MIPMAP_LINEAR, GL_LINEAR_MIPMAP_NEAREST, GL_LINEAR_MIPMAP_LINEAR };
83 
84 // Mapping MagnificationFilter values to OpenGL values.
85 //------------------------------------------------------------------------------
86 static GLint OpenGLMagFilter[6] = { GL_NEAREST, GL_LINEAR };
87 
88 //------------------------------------------------------------------------------
89 static const char* MinMagFilterAsString[6] = { "Nearest", "Linear", "NearestMipmapNearest",
90   "NearestMipmapLinear", "LinearMipmapNearest", "LinearMipmapLinear" };
91 
92 //------------------------------------------------------------------------------
93 static GLenum OpenGLDepthInternalFormat[7] = {
94   GL_DEPTH_COMPONENT,   // native
95   GL_DEPTH_COMPONENT,   // fixed8
96   GL_DEPTH_COMPONENT16, // fixed16
97 #ifdef GL_DEPTH_COMPONENT24
98   GL_DEPTH_COMPONENT24, // fixed24
99 #else
100   GL_DEPTH_COMPONENT16,
101 #endif
102 #ifdef GL_DEPTH_COMPONENT32
103   GL_DEPTH_COMPONENT32, // fixed32
104 #else
105   GL_DEPTH_COMPONENT16,
106 #endif
107 #ifdef GL_DEPTH_COMPONENT32F
108   GL_DEPTH_COMPONENT32F, // float16
109   GL_DEPTH_COMPONENT32F  // float32
110 #else
111   GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT16
112 #endif
113 };
114 
115 //------------------------------------------------------------------------------
116 static GLenum OpenGLDepthInternalFormatType[7] = {
117   GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT, GL_UNSIGNED_INT,
118 #ifdef GL_DEPTH_COMPONENT32F
119   GL_FLOAT, GL_FLOAT
120 #else
121   GL_UNSIGNED_INT, GL_UNSIGNED_INT
122 #endif
123 };
124 
125 //------------------------------------------------------------------------------
126 vtkStandardNewMacro(vtkTextureObject);
127 
128 //------------------------------------------------------------------------------
vtkTextureObject()129 vtkTextureObject::vtkTextureObject()
130 {
131   this->Context = nullptr;
132   this->Handle = 0;
133   this->OwnHandle = false;
134   this->NumberOfDimensions = 0;
135   this->Target = 0;
136   this->Components = 0;
137   this->Width = 0;
138   this->Height = 0;
139   this->Depth = 0;
140   this->Samples = 0;
141   this->RequireTextureInteger = false;
142   this->SupportsTextureInteger = false;
143   this->RequireTextureFloat = false;
144   this->SupportsTextureFloat = false;
145   this->RequireDepthBufferFloat = false;
146   this->SupportsDepthBufferFloat = false;
147   this->AutoParameters = 1;
148   this->WrapS = Repeat;
149   this->WrapT = Repeat;
150   this->WrapR = Repeat;
151   this->MinificationFilter = Nearest;
152   this->MagnificationFilter = Nearest;
153   this->MinLOD = -1000.0f;
154   this->MaxLOD = 1000.0f;
155   this->BaseLevel = 0;
156   this->MaxLevel = 0;
157   this->DepthTextureCompare = false;
158   this->DepthTextureCompareFunction = Lequal;
159   this->GenerateMipmap = false;
160   this->ShaderProgram = nullptr;
161   this->BorderColor[0] = 0.0f;
162   this->BorderColor[1] = 0.0f;
163   this->BorderColor[2] = 0.0f;
164   this->BorderColor[3] = 0.0f;
165   this->MaximumAnisotropicFiltering = 1.0;
166   this->BufferObject = nullptr;
167   this->UseSRGBColorSpace = false;
168 
169   this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkTextureObject>(
170     this, &vtkTextureObject::ReleaseGraphicsResources);
171 
172   this->ResetFormatAndType();
173 }
174 
175 //------------------------------------------------------------------------------
~vtkTextureObject()176 vtkTextureObject::~vtkTextureObject()
177 {
178   if (this->ResourceCallback)
179   {
180     this->ResourceCallback->Release();
181     delete this->ResourceCallback;
182     this->ResourceCallback = nullptr;
183   }
184   if (this->ShaderProgram)
185   {
186     delete this->ShaderProgram;
187     this->ShaderProgram = nullptr;
188   }
189 }
190 
191 //------------------------------------------------------------------------------
SetContext(vtkOpenGLRenderWindow * renWin)192 void vtkTextureObject::SetContext(vtkOpenGLRenderWindow* renWin)
193 {
194   this->ResourceCallback->RegisterGraphicsResources(renWin);
195 
196   // avoid pointless reassignment
197   if (this->Context == renWin)
198   {
199     return;
200   }
201 
202   this->ResetFormatAndType();
203 
204   this->Context = nullptr;
205   this->Modified();
206   // all done if assigned null
207   if (!renWin)
208   {
209     return;
210   }
211 
212   // initialize
213   this->Context = renWin;
214   this->Context->MakeCurrent();
215 }
216 
217 //------------------------------------------------------------------------------
GetContext()218 vtkOpenGLRenderWindow* vtkTextureObject::GetContext()
219 {
220   return this->Context;
221 }
222 
223 //------------------------------------------------------------------------------
DestroyTexture()224 void vtkTextureObject::DestroyTexture()
225 {
226   // deactivate it first
227   this->Deactivate();
228 
229   // because we don't hold a reference to the render
230   // context we don't have any control on when it is
231   // destroyed. In fact it may be destroyed before
232   // we are(eg smart pointers), in which case we should
233   // do nothing.
234   if (this->Context && this->Handle)
235   {
236     GLuint tex = this->Handle;
237     glDeleteTextures(1, &tex);
238     vtkOpenGLCheckErrorMacro("failed at glDeleteTexture");
239   }
240   this->Handle = 0;
241   this->NumberOfDimensions = 0;
242   this->Target = 0;
243   this->Components = 0;
244   this->Width = this->Height = this->Depth = 0;
245   this->ResetFormatAndType();
246 }
247 
AssignToExistingTexture(unsigned int handle,unsigned int target)248 void vtkTextureObject::AssignToExistingTexture(unsigned int handle, unsigned int target)
249 {
250   if (this->Handle == handle && this->Target == target)
251   {
252     return;
253   }
254 
255   this->Handle = handle;
256   this->Target = target;
257   this->OwnHandle = false;
258   this->Modified();
259 }
260 
261 //------------------------------------------------------------------------------
CreateTexture()262 void vtkTextureObject::CreateTexture()
263 {
264   assert(this->Context);
265 
266   this->ResourceCallback->RegisterGraphicsResources(this->Context);
267 
268   // reuse the existing handle if we have one
269   if (!this->Handle)
270   {
271     GLuint tex = 0;
272     glGenTextures(1, &tex);
273     this->OwnHandle = true;
274     vtkOpenGLCheckErrorMacro("failed at glGenTextures");
275     this->Handle = tex;
276 
277 #if defined(GL_TEXTURE_BUFFER)
278     if (this->Target && this->Target != GL_TEXTURE_BUFFER)
279 #else
280     if (this->Target)
281 #endif
282     {
283       glBindTexture(this->Target, this->Handle);
284       vtkOpenGLCheckErrorMacro("failed at glBindTexture");
285 
286       // See: http://www.opengl.org/wiki/Common_Mistakes#Creating_a_complete_texture
287       // turn off mip map filter or set the base and max level correctly. here
288       // both are done.
289 #ifdef GL_TEXTURE_2D_MULTISAMPLE
290       if (this->Target != GL_TEXTURE_2D_MULTISAMPLE)
291 #endif
292       {
293         glTexParameteri(this->Target, GL_TEXTURE_MIN_FILTER,
294           this->GetMinificationFilterMode(this->MinificationFilter));
295         glTexParameteri(this->Target, GL_TEXTURE_MAG_FILTER,
296           this->GetMagnificationFilterMode(this->MagnificationFilter));
297 
298         glTexParameteri(this->Target, GL_TEXTURE_WRAP_S, this->GetWrapSMode(this->WrapS));
299         glTexParameteri(this->Target, GL_TEXTURE_WRAP_T, this->GetWrapTMode(this->WrapT));
300 
301 #if defined(GL_TEXTURE_3D)
302         if (this->Target == GL_TEXTURE_3D)
303         {
304           glTexParameteri(this->Target, GL_TEXTURE_WRAP_R, this->GetWrapRMode(this->WrapR));
305         }
306 #endif
307       }
308 
309       if (this->Target == GL_TEXTURE_2D) // maybe expand later on
310       {
311         glTexParameteri(this->Target, GL_TEXTURE_BASE_LEVEL, this->BaseLevel);
312         glTexParameteri(this->Target, GL_TEXTURE_MAX_LEVEL, this->MaxLevel);
313       }
314 
315       glBindTexture(this->Target, 0);
316     }
317   }
318 }
319 
320 //------------------------------------------------------------------------------
GetTextureUnit()321 int vtkTextureObject::GetTextureUnit()
322 {
323   if (this->Context)
324   {
325     return this->Context->GetTextureUnitForTexture(this);
326   }
327   return -1;
328 }
329 
330 //------------------------------------------------------------------------------
Activate()331 void vtkTextureObject::Activate()
332 {
333   // activate a free texture unit for this texture
334   this->Context->ActivateTexture(this);
335   this->Bind();
336 }
337 
338 //------------------------------------------------------------------------------
Deactivate()339 void vtkTextureObject::Deactivate()
340 {
341   if (this->Context)
342   {
343     this->Context->DeactivateTexture(this);
344   }
345 }
346 
347 //------------------------------------------------------------------------------
ReleaseGraphicsResources(vtkWindow * win)348 void vtkTextureObject::ReleaseGraphicsResources(vtkWindow* win)
349 {
350   if (!this->ResourceCallback->IsReleasing())
351   {
352     this->ResourceCallback->Release();
353     return;
354   }
355 
356   // Ensure that the context is current before releasing any graphics
357   // resources tied to it.
358   if (this->Handle)
359   {
360     vtkOpenGLRenderWindow* rwin = vtkOpenGLRenderWindow::SafeDownCast(win);
361     // you can commewnt out the next line to look for textures left active
362     rwin->DeactivateTexture(this);
363     if (this->OwnHandle)
364     {
365       GLuint tex = this->Handle;
366       glDeleteTextures(1, &tex);
367       this->OwnHandle = false;
368     }
369     this->Handle = 0;
370     this->NumberOfDimensions = 0;
371     this->Target = 0;
372     this->InternalFormat = 0;
373     this->Format = 0;
374     this->Type = 0;
375     this->Components = 0;
376     this->Width = this->Height = this->Depth = 0;
377   }
378   if (this->ShaderProgram)
379   {
380     this->ShaderProgram->ReleaseGraphicsResources(win);
381     delete this->ShaderProgram;
382     this->ShaderProgram = nullptr;
383   }
384 }
385 
386 //------------------------------------------------------------------------------
Bind()387 void vtkTextureObject::Bind()
388 {
389   assert(this->Context);
390   assert(this->Handle);
391 
392   glBindTexture(this->Target, this->Handle);
393   vtkOpenGLCheckErrorMacro("failed at glBindTexture");
394 
395   if (this->AutoParameters && (this->GetMTime() > this->SendParametersTime))
396   {
397     this->SendParameters();
398   }
399 }
400 
401 //------------------------------------------------------------------------------
IsBound()402 bool vtkTextureObject::IsBound()
403 {
404   bool result = false;
405   if (this->Context && this->Handle)
406   {
407     GLenum target = 0; // to avoid warnings.
408     switch (this->Target)
409     {
410 #if defined(GL_TEXTURE_1D) && defined(GL_TEXTURE_BINDING_1D)
411       case GL_TEXTURE_1D:
412         target = GL_TEXTURE_BINDING_1D;
413         break;
414 #endif
415       case GL_TEXTURE_2D:
416         target = GL_TEXTURE_BINDING_2D;
417         break;
418 #if defined(GL_TEXTURE_2D_MULTISAMPLE) && defined(GL_TEXTURE_BINDING_2D_MULTISAMPLE)
419       case GL_TEXTURE_2D_MULTISAMPLE:
420         target = GL_TEXTURE_BINDING_2D_MULTISAMPLE;
421         break;
422 #endif
423 #if defined(GL_TEXTURE_3D) && defined(GL_TEXTURE_BINDING_3D)
424       case GL_TEXTURE_3D:
425         target = GL_TEXTURE_BINDING_3D;
426         break;
427 #endif
428 #if defined(GL_TEXTURE_BUFFER) && defined(GL_TEXTURE_BINDING_BUFFER)
429       case GL_TEXTURE_BUFFER:
430         target = GL_TEXTURE_BINDING_BUFFER;
431         break;
432 #endif
433 #if defined(GL_TEXTURE_CUBE_MAP) && defined(GL_TEXTURE_BINDING_CUBE_MAP)
434       case GL_TEXTURE_CUBE_MAP:
435         target = GL_TEXTURE_BINDING_CUBE_MAP;
436         break;
437 #endif
438       default:
439         assert("check: impossible case" && 0);
440         break;
441     }
442     GLint objectId;
443     glGetIntegerv(target, &objectId);
444     result = static_cast<GLuint>(objectId) == this->Handle;
445   }
446   return result;
447 }
448 
449 //------------------------------------------------------------------------------
SendParameters()450 void vtkTextureObject::SendParameters()
451 {
452   assert("pre: is_bound" && this->IsBound());
453 
454 #if defined(GL_TEXTURE_BUFFER)
455   if (this->Target == GL_TEXTURE_BUFFER)
456   {
457     return;
458   }
459 #endif
460 
461 #ifdef GL_TEXTURE_2D_MULTISAMPLE
462   if (this->Target == GL_TEXTURE_2D_MULTISAMPLE)
463   {
464     return;
465   }
466 #endif
467 
468   glTexParameteri(this->Target, GL_TEXTURE_WRAP_S, OpenGLWrap[this->WrapS]);
469   glTexParameteri(this->Target, GL_TEXTURE_WRAP_T, OpenGLWrap[this->WrapT]);
470 
471 #ifdef GL_TEXTURE_WRAP_R
472   glTexParameteri(this->Target, GL_TEXTURE_WRAP_R, OpenGLWrap[this->WrapR]);
473 #endif
474 
475   glTexParameteri(this->Target, GL_TEXTURE_MIN_FILTER, OpenGLMinFilter[this->MinificationFilter]);
476 
477   glTexParameteri(this->Target, GL_TEXTURE_MAG_FILTER, OpenGLMagFilter[this->MagnificationFilter]);
478 
479 #ifndef GL_ES_VERSION_3_0
480   glTexParameterfv(this->Target, GL_TEXTURE_BORDER_COLOR, this->BorderColor);
481 
482   if (this->DepthTextureCompare)
483   {
484     glTexParameteri(this->Target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
485   }
486   else
487   {
488     glTexParameteri(this->Target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
489   }
490 #endif
491 
492   // if mipmaps are requested also turn on anisotropic if available
493 #ifdef GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT
494   if (GLEW_EXT_texture_filter_anisotropic)
495   {
496     float aniso = 0.0f;
497     glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &aniso);
498     if (aniso > this->MaximumAnisotropicFiltering)
499     {
500       aniso = this->MaximumAnisotropicFiltering;
501     }
502     glTexParameterf(this->Target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso);
503   }
504 #endif
505 
506   glTexParameterf(this->Target, GL_TEXTURE_MIN_LOD, this->MinLOD);
507   glTexParameterf(this->Target, GL_TEXTURE_MAX_LOD, this->MaxLOD);
508   glTexParameteri(this->Target, GL_TEXTURE_BASE_LEVEL, this->BaseLevel);
509   glTexParameteri(this->Target, GL_TEXTURE_MAX_LEVEL, this->MaxLevel);
510 
511   glTexParameteri(this->Target, GL_TEXTURE_COMPARE_FUNC,
512     OpenGLDepthTextureCompareFunction[this->DepthTextureCompareFunction]);
513 
514   vtkOpenGLCheckErrorMacro("failed after SendParameters");
515   this->SendParametersTime.Modified();
516 }
517 
518 //------------------------------------------------------------------------------
GetInternalFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)519 unsigned int vtkTextureObject::GetInternalFormat(
520   int vtktype, int numComps, bool shaderSupportsTextureInt)
521 {
522   if (this->InternalFormat)
523   {
524     return this->InternalFormat;
525   }
526 
527   // pre-condition
528   if (vtktype == VTK_VOID && numComps != 1)
529   {
530     vtkErrorMacro(
531       "Depth component texture must have 1 component only (" << numComps << " requested");
532     this->InternalFormat = 0;
533     return this->InternalFormat;
534   }
535 
536   this->InternalFormat =
537     this->GetDefaultInternalFormat(vtktype, numComps, shaderSupportsTextureInt);
538 
539   if (!this->InternalFormat)
540   {
541     vtkDebugMacro("Unable to find suitable internal format for T="
542       << vtktype << " NC=" << numComps << " SSTI=" << shaderSupportsTextureInt);
543   }
544 
545   return this->InternalFormat;
546 }
547 
548 //------------------------------------------------------------------------------
GetDefaultInternalFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)549 unsigned int vtkTextureObject::GetDefaultInternalFormat(
550   int vtktype, int numComps, bool shaderSupportsTextureInt)
551 {
552   GLenum result = 0;
553 
554   // if shader supports int textures try that first
555   if (shaderSupportsTextureInt)
556   {
557     result = this->Context->GetDefaultTextureInternalFormat(
558       vtktype, numComps, true, false, this->UseSRGBColorSpace);
559     if (!result)
560     {
561       vtkDebugMacro("Unsupported internal texture type!");
562     }
563     return result;
564   }
565 
566   // try default next
567   result = this->Context->GetDefaultTextureInternalFormat(
568     vtktype, numComps, false, false, this->UseSRGBColorSpace);
569   if (result)
570   {
571     return result;
572   }
573 
574   // try floating point
575   result = this->Context->GetDefaultTextureInternalFormat(
576     vtktype, numComps, false, true, this->UseSRGBColorSpace);
577 
578   if (!result)
579   {
580     vtkDebugMacro("Unsupported internal texture type!");
581     vtkDebugMacro("Unable to find suitable internal format for T="
582       << vtktype << " NC=" << numComps << " SSTI=" << shaderSupportsTextureInt);
583   }
584 
585   return result;
586 }
587 
588 //------------------------------------------------------------------------------
SetInternalFormat(unsigned int glInternalFormat)589 void vtkTextureObject::SetInternalFormat(unsigned int glInternalFormat)
590 {
591   if (this->InternalFormat != glInternalFormat)
592   {
593     this->InternalFormat = glInternalFormat;
594     this->Modified();
595   }
596 }
597 
598 //------------------------------------------------------------------------------
vtkGetVTKType(GLenum gltype)599 static int vtkGetVTKType(GLenum gltype)
600 {
601   // DON'T DEAL with VTK_CHAR as this is platform dependent.
602   switch (gltype)
603   {
604     case GL_BYTE:
605       return VTK_SIGNED_CHAR;
606 
607     case GL_UNSIGNED_BYTE:
608       return VTK_UNSIGNED_CHAR;
609 
610     case GL_SHORT:
611       return VTK_SHORT;
612 
613     case GL_UNSIGNED_SHORT:
614       return VTK_UNSIGNED_SHORT;
615 
616     case GL_INT:
617       return VTK_INT;
618 
619     case GL_UNSIGNED_INT:
620       return VTK_UNSIGNED_INT;
621 
622     case GL_FLOAT:
623       return VTK_FLOAT;
624   }
625 
626   return 0;
627 }
628 
GetShiftAndScale(float & shift,float & scale)629 void vtkTextureObject::GetShiftAndScale(float& shift, float& scale)
630 {
631   shift = 1.0;
632   scale = 1.0;
633 
634   // check to see if this is an int format
635   GLenum iresult = this->Context->GetDefaultTextureInternalFormat(
636     vtkGetVTKType(this->Type), this->Components, true, false, this->UseSRGBColorSpace);
637 
638   // using an int texture format, no shift scale
639   if (iresult == this->InternalFormat)
640   {
641     return;
642   }
643 
644   // for all float type internal formats
645   switch (this->Type)
646   {
647     case GL_BYTE:
648       scale = (VTK_SIGNED_CHAR_MAX - VTK_SIGNED_CHAR_MIN) / 2.0;
649       shift = scale + VTK_SIGNED_CHAR_MIN;
650       break;
651     case GL_UNSIGNED_BYTE:
652       scale = VTK_UNSIGNED_CHAR_MAX;
653       shift = 0.0;
654       break;
655     case GL_SHORT:
656       // this may be off a tad
657       scale = (VTK_SHORT_MAX - VTK_SHORT_MIN) / 2.0;
658       shift = scale + VTK_SHORT_MIN;
659       break;
660     case GL_UNSIGNED_SHORT:
661       scale = VTK_UNSIGNED_SHORT_MAX;
662       shift = 0.0;
663       break;
664     case GL_INT:
665       // this may be off a tad
666       scale = (1.0 * VTK_INT_MAX - VTK_INT_MIN) / 2.0;
667       shift = scale + VTK_INT_MIN;
668       break;
669     case GL_UNSIGNED_INT:
670       scale = static_cast<float>(VTK_UNSIGNED_INT_MAX);
671       shift = 0.0;
672       break;
673     case GL_FLOAT:
674     default:
675       break;
676   }
677 }
678 
679 //------------------------------------------------------------------------------
GetFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)680 unsigned int vtkTextureObject::GetFormat(int vtktype, int numComps, bool shaderSupportsTextureInt)
681 {
682   if (!this->Format)
683   {
684     this->Format = this->GetDefaultFormat(vtktype, numComps, shaderSupportsTextureInt);
685   }
686   return this->Format;
687 }
688 
689 //------------------------------------------------------------------------------
GetDefaultFormat(int vtktype,int numComps,bool shaderSupportsTextureInt)690 unsigned int vtkTextureObject::GetDefaultFormat(
691   int vtktype, int numComps, bool shaderSupportsTextureInt)
692 {
693   if (vtktype == VTK_VOID)
694   {
695     return GL_DEPTH_COMPONENT;
696   }
697 
698 #ifndef GL_ES_VERSION_3_0
699   if (this->SupportsTextureInteger && shaderSupportsTextureInt &&
700     (vtktype == VTK_SIGNED_CHAR || vtktype == VTK_UNSIGNED_CHAR || vtktype == VTK_SHORT ||
701       vtktype == VTK_UNSIGNED_SHORT || vtktype == VTK_INT || vtktype == VTK_UNSIGNED_INT))
702   {
703     switch (numComps)
704     {
705       case 1:
706         return GL_RED_INTEGER;
707       case 2:
708         return GL_RG_INTEGER;
709       case 3:
710         return GL_RGB_INTEGER_EXT;
711       case 4:
712         return GL_RGBA_INTEGER_EXT;
713     }
714   }
715   else
716   {
717     switch (numComps)
718     {
719       case 1:
720         return GL_RED;
721       case 2:
722         return GL_RG;
723       case 3:
724         return GL_RGB;
725       case 4:
726         return GL_RGBA;
727     }
728 #else
729   {
730     switch (numComps)
731     {
732 #ifdef GL_RED
733       case 1:
734         return GL_RED;
735       case 2:
736         return GL_RG;
737 #else
738       case 1:
739         return GL_LUMINANCE;
740       case 2:
741         return GL_LUMINANCE_ALPHA;
742 #endif
743       case 3:
744         return GL_RGB;
745       case 4:
746         return GL_RGBA;
747     }
748 #endif
749   }
750   return GL_RGB;
751 }
752 
753 //------------------------------------------------------------------------------
754 void vtkTextureObject::SetFormat(unsigned int glFormat)
755 {
756   if (this->Format != glFormat)
757   {
758     this->Format = glFormat;
759     this->Modified();
760   }
761 }
762 
763 //------------------------------------------------------------------------------
764 void vtkTextureObject::ResetFormatAndType()
765 {
766   this->Format = 0;
767   this->InternalFormat = 0;
768   this->Type = 0;
769 }
770 
771 //------------------------------------------------------------------------------
772 int vtkTextureObject::GetDefaultDataType(int vtk_scalar_type)
773 {
774   // DON'T DEAL with VTK_CHAR as this is platform dependent.
775   switch (vtk_scalar_type)
776   {
777     case VTK_SIGNED_CHAR:
778       return GL_BYTE;
779 
780     case VTK_UNSIGNED_CHAR:
781       return GL_UNSIGNED_BYTE;
782 
783     case VTK_SHORT:
784       return GL_SHORT;
785 
786     case VTK_UNSIGNED_SHORT:
787       return GL_UNSIGNED_SHORT;
788 
789     case VTK_INT:
790       return GL_INT;
791 
792     case VTK_UNSIGNED_INT:
793       return GL_UNSIGNED_INT;
794 
795     case VTK_FLOAT:
796     case VTK_VOID: // used for depth component textures.
797       return GL_FLOAT;
798   }
799   return 0;
800 }
801 
802 //------------------------------------------------------------------------------
803 int vtkTextureObject::GetVTKDataType()
804 {
805   return ::vtkGetVTKType(this->Type);
806 }
807 
808 //------------------------------------------------------------------------------
809 int vtkTextureObject::GetDataType(int vtk_scalar_type)
810 {
811   if (!this->Type)
812   {
813     this->Type = this->GetDefaultDataType(vtk_scalar_type);
814   }
815 
816   return this->Type;
817 }
818 
819 //------------------------------------------------------------------------------
820 void vtkTextureObject::SetDataType(unsigned int glType)
821 {
822   if (this->Type != glType)
823   {
824     this->Type = glType;
825     this->Modified();
826   }
827 }
828 
829 //------------------------------------------------------------------------------
830 unsigned int vtkTextureObject::GetMinificationFilterMode(int vtktype)
831 {
832   switch (vtktype)
833   {
834     case Nearest:
835       return GL_NEAREST;
836     case Linear:
837       return GL_LINEAR;
838     case NearestMipmapNearest:
839       return GL_NEAREST_MIPMAP_NEAREST;
840     case NearestMipmapLinear:
841       return GL_NEAREST_MIPMAP_LINEAR;
842     case LinearMipmapNearest:
843       return GL_LINEAR_MIPMAP_NEAREST;
844     case LinearMipmapLinear:
845       return GL_LINEAR_MIPMAP_LINEAR;
846     default:
847       return GL_NEAREST;
848   }
849 }
850 
851 //------------------------------------------------------------------------------
852 unsigned int vtkTextureObject::GetMagnificationFilterMode(int vtktype)
853 {
854   switch (vtktype)
855   {
856     case Nearest:
857       return GL_NEAREST;
858     case Linear:
859       return GL_LINEAR;
860     default:
861       return GL_NEAREST;
862   }
863 }
864 
865 //------------------------------------------------------------------------------
866 unsigned int vtkTextureObject::GetWrapSMode(int vtktype)
867 {
868   switch (vtktype)
869   {
870     case ClampToEdge:
871       return GL_CLAMP_TO_EDGE;
872     case Repeat:
873       return GL_REPEAT;
874 #ifdef GL_CLAMP_TO_BORDER
875     case ClampToBorder:
876       return GL_CLAMP_TO_BORDER;
877 #endif
878     case MirroredRepeat:
879       return GL_MIRRORED_REPEAT;
880     default:
881       return GL_CLAMP_TO_EDGE;
882   }
883 }
884 
885 //------------------------------------------------------------------------------
886 unsigned int vtkTextureObject::GetWrapTMode(int vtktype)
887 {
888   return this->GetWrapSMode(vtktype);
889 }
890 
891 //------------------------------------------------------------------------------
892 unsigned int vtkTextureObject::GetWrapRMode(int vtktype)
893 {
894   return this->GetWrapSMode(vtktype);
895 }
896 
897 // 1D  textures are not supported in ES 2.0 or 3.0
898 #ifndef GL_ES_VERSION_3_0
899 
900 //------------------------------------------------------------------------------
901 bool vtkTextureObject::Create1D(
902   int numComps, vtkPixelBufferObject* pbo, bool shaderSupportsTextureInt)
903 {
904   assert(this->Context);
905   assert(pbo->GetContext() == this->Context.GetPointer());
906 
907   GLenum target = GL_TEXTURE_1D;
908 
909   // Now, determine texture parameters using the information from the pbo.
910 
911   // * internalFormat depends on number of components and the data type.
912   GLenum internalFormat =
913     this->GetInternalFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
914 
915   // * format depends on the number of components.
916   GLenum format = this->GetFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
917 
918   // * type if the data type in the pbo
919   GLenum type = this->GetDefaultDataType(pbo->GetType());
920 
921   if (!internalFormat || !format || !type)
922   {
923     vtkErrorMacro("Failed to determine texture parameters.");
924     return false;
925   }
926 
927   this->Target = target;
928   this->Context->ActivateTexture(this);
929   this->CreateTexture();
930   this->Bind();
931 
932   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
933 
934   // Source texture data from the PBO.
935   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
936   glTexImage1D(target, 0, static_cast<GLint>(internalFormat),
937     static_cast<GLsizei>(pbo->GetSize() / static_cast<unsigned int>(numComps)), 0, format, type,
938     BUFFER_OFFSET(0));
939   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
940   pbo->UnBind();
941   this->Deactivate();
942 
943   this->Target = target;
944   this->Format = format;
945   this->Type = type;
946   this->Components = numComps;
947   this->Width = pbo->GetSize();
948   this->Height = 1;
949   this->Depth = 1;
950   this->NumberOfDimensions = 1;
951   return true;
952 }
953 
954 //------------------------------------------------------------------------------
955 bool vtkTextureObject::Create1DFromRaw(unsigned int width, int numComps, int dataType, void* data)
956 {
957   assert(this->Context);
958 
959   // Now determine the texture parameters using the arguments.
960   this->GetDataType(dataType);
961   this->GetInternalFormat(dataType, numComps, false);
962   this->GetFormat(dataType, numComps, false);
963 
964   if (!this->InternalFormat || !this->Format || !this->Type)
965   {
966     vtkErrorMacro("Failed to determine texture parameters.");
967     return false;
968   }
969 
970   GLenum target = GL_TEXTURE_1D;
971   this->Target = target;
972   this->Components = numComps;
973   this->Width = width;
974   this->Height = 1;
975   this->Depth = 1;
976   this->NumberOfDimensions = 1;
977   this->Context->ActivateTexture(this);
978   this->CreateTexture();
979   this->Bind();
980 
981   glTexImage1D(this->Target, 0, this->InternalFormat, static_cast<GLsizei>(this->Width), 0,
982     this->Format, this->Type, static_cast<const GLvoid*>(data));
983 
984   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
985 
986   this->Deactivate();
987   return true;
988 }
989 
990 // Description:
991 // Create a texture buffer basically a 1D texture that can be
992 // very large for passing data into the fragment shader
993 bool vtkTextureObject::CreateTextureBuffer(
994   unsigned int numValues, int numComps, int dataType, vtkOpenGLBufferObject* bo)
995 {
996   assert(this->Context);
997 
998   // Now, determine texture parameters using the arguments.
999   this->GetDataType(dataType);
1000   this->GetInternalFormat(dataType, numComps, false);
1001   this->GetFormat(dataType, numComps, false);
1002 
1003   if (!this->InternalFormat || !this->Format || !this->Type)
1004   {
1005     vtkErrorMacro("Failed to determine texture parameters.");
1006     return false;
1007   }
1008 
1009   this->Target = GL_TEXTURE_BUFFER;
1010   this->Components = numComps;
1011   this->Width = numValues;
1012   this->Height = 1;
1013   this->Depth = 1;
1014   this->NumberOfDimensions = 1;
1015   this->BufferObject = bo;
1016 
1017   this->Context->ActivateTexture(this);
1018   this->CreateTexture();
1019   this->Bind();
1020 
1021   int maxSize = -1;
1022   this->Context->GetState()->vtkglGetIntegerv(GL_MAX_TEXTURE_BUFFER_SIZE, &maxSize);
1023   if (maxSize > 0 && static_cast<unsigned int>(maxSize) < numValues)
1024   {
1025     vtkErrorMacro("Attempt to use a texture buffer exceeding your hardware's limits. "
1026                   "This can happen when trying to color by cell data with a large dataset. "
1027                   "Hardware limit is "
1028       << maxSize << " values while " << numValues << " was requested.");
1029   }
1030 
1031   // Source texture data from the PBO.
1032   glTexBuffer(this->Target, this->InternalFormat, this->BufferObject->GetHandle());
1033 
1034   vtkOpenGLCheckErrorMacro("failed at glTexBuffer");
1035 
1036   this->Deactivate();
1037 
1038   return true;
1039 }
1040 
1041 #else
1042 
1043 // Emulate 1D textures as 2D. Note that the any shader code will likely
1044 // have to be modified as well for this to work.
1045 
1046 //------------------------------------------------------------------------------
1047 bool vtkTextureObject::Create1D(
1048   int numComps, vtkPixelBufferObject* pbo, bool shaderSupportsTextureInt)
1049 {
1050   assert(this->Context);
1051   assert(pbo->GetContext() == this->Context.GetPointer());
1052 
1053   GLenum target = GL_TEXTURE_2D;
1054 
1055   // Now, determine texture parameters using the information from the pbo.
1056 
1057   // * internalFormat depends on number of components and the data type.
1058   GLenum internalFormat =
1059     this->GetInternalFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
1060 
1061   // * format depends on the number of components.
1062   GLenum format = this->GetFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
1063 
1064   // * type if the data type in the pbo
1065   GLenum type = this->GetDefaultDataType(pbo->GetType());
1066 
1067   if (!internalFormat || !format || !type)
1068   {
1069     vtkErrorMacro("Failed to determine texture parameters.");
1070     return false;
1071   }
1072 
1073   this->Target = target;
1074   this->Context->ActivateTexture(this);
1075   this->CreateTexture();
1076   this->Bind();
1077 
1078   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1079 
1080   // Source texture data from the PBO.
1081   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1082   glTexImage2D(target, 0, static_cast<GLint>(internalFormat),
1083     static_cast<GLsizei>(pbo->GetSize() / static_cast<unsigned int>(numComps)), 1, 0, format, type,
1084     BUFFER_OFFSET(0));
1085   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
1086   pbo->UnBind();
1087   this->Deactivate();
1088 
1089   this->Target = target;
1090   this->Format = format;
1091   this->Type = type;
1092   this->Components = numComps;
1093   this->Width = pbo->GetSize();
1094   this->Height = 1;
1095   this->Depth = 1;
1096   this->NumberOfDimensions = 1;
1097   return true;
1098 }
1099 
1100 //------------------------------------------------------------------------------
1101 bool vtkTextureObject::Create1DFromRaw(unsigned int width, int numComps, int dataType, void* data)
1102 {
1103   assert(this->Context);
1104 
1105   // Now determine the texture parameters using the arguments.
1106   this->GetDataType(dataType);
1107   this->GetInternalFormat(dataType, numComps, false);
1108   this->GetFormat(dataType, numComps, false);
1109 
1110   if (!this->InternalFormat || !this->Format || !this->Type)
1111   {
1112     vtkErrorMacro("Failed to determine texture parameters.");
1113     return false;
1114   }
1115 
1116   GLenum target = GL_TEXTURE_2D;
1117   this->Target = target;
1118   this->Components = numComps;
1119   this->Width = width;
1120   this->Height = 1;
1121   this->Depth = 1;
1122   this->NumberOfDimensions = 1;
1123   this->Context->ActivateTexture(this);
1124   this->CreateTexture();
1125   this->Bind();
1126 
1127   glTexImage2D(this->Target, 0, this->InternalFormat, static_cast<GLsizei>(this->Width), 1, 0,
1128     this->Format, this->Type, static_cast<const GLvoid*>(data));
1129 
1130   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
1131 
1132   this->Deactivate();
1133   return true;
1134 }
1135 
1136 // Description:
1137 // Create a texture buffer basically a 1D texture that can be
1138 // very large for passing data into the fragment shader
1139 bool vtkTextureObject::CreateTextureBuffer(
1140   unsigned int numValues, int numComps, int dataType, vtkOpenGLBufferObject* bo)
1141 {
1142   assert(this->Context);
1143   vtkErrorMacro("TextureBuffers not supported in OpenGL ES");
1144   // TODO: implement 1D and Texture buffers using 2D textures
1145   return false;
1146 }
1147 
1148 #endif // not ES 2.0 or 3.0
1149 
1150 //------------------------------------------------------------------------------
1151 bool vtkTextureObject::Create2D(unsigned int width, unsigned int height, int numComps,
1152   vtkPixelBufferObject* pbo, bool shaderSupportsTextureInt)
1153 {
1154   assert(this->Context);
1155   assert(pbo->GetContext() == this->Context.GetPointer());
1156 
1157   if (pbo->GetSize() < width * height * static_cast<unsigned int>(numComps))
1158   {
1159     vtkErrorMacro("PBO size must match texture size.");
1160     return false;
1161   }
1162 
1163   // Now, determine texture parameters using the information from the pbo.
1164   // * internalFormat depends on number of components and the data type.
1165   // * format depends on the number of components.
1166   // * type if the data type in the pbo
1167 
1168   int vtktype = pbo->GetType();
1169   GLenum type = this->GetDefaultDataType(vtktype);
1170 
1171   GLenum internalFormat = this->GetInternalFormat(vtktype, numComps, shaderSupportsTextureInt);
1172 
1173   GLenum format = this->GetFormat(vtktype, numComps, shaderSupportsTextureInt);
1174 
1175   if (!internalFormat || !format || !type)
1176   {
1177     vtkErrorMacro("Failed to determine texture parameters.");
1178     return false;
1179   }
1180 
1181   GLenum target = GL_TEXTURE_2D;
1182   this->Target = target;
1183   this->Context->ActivateTexture(this);
1184   this->CreateTexture();
1185   this->Bind();
1186 
1187   // Source texture data from the PBO.
1188   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1189   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1190 
1191   glTexImage2D(target, 0, internalFormat, static_cast<GLsizei>(width), static_cast<GLsizei>(height),
1192     0, format, type, BUFFER_OFFSET(0));
1193 
1194   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1195 
1196   pbo->UnBind();
1197   this->Deactivate();
1198 
1199   this->Target = target;
1200   this->Format = format;
1201   this->Type = type;
1202   this->Components = numComps;
1203   this->Width = width;
1204   this->Height = height;
1205   this->Depth = 1;
1206   this->NumberOfDimensions = 2;
1207 
1208   return true;
1209 }
1210 
1211 //------------------------------------------------------------------------------
1212 // Description:
1213 // Create a 2D depth texture using a PBO.
1214 bool vtkTextureObject::CreateDepth(
1215   unsigned int width, unsigned int height, int internalFormat, vtkPixelBufferObject* pbo)
1216 {
1217   assert("pre: context_exists" && this->GetContext() != nullptr);
1218   assert("pre: pbo_context_exists" && pbo->GetContext() != nullptr);
1219   assert("pre: context_match" && this->GetContext() == pbo->GetContext());
1220   assert("pre: sizes_match" && pbo->GetSize() == width * height);
1221   assert(
1222     "pre: valid_internalFormat" && internalFormat >= 0 && internalFormat < NumberOfDepthFormats);
1223 
1224   GLenum inFormat = OpenGLDepthInternalFormat[internalFormat];
1225   GLenum type = this->GetDefaultDataType(pbo->GetType());
1226 
1227   this->Target = GL_TEXTURE_2D;
1228   this->Format = GL_DEPTH_COMPONENT;
1229   this->Type = type;
1230   this->Width = width;
1231   this->Height = height;
1232   this->Depth = 1;
1233   this->NumberOfDimensions = 2;
1234   this->Components = 1;
1235 
1236   this->Context->ActivateTexture(this);
1237   this->CreateTexture();
1238   this->Bind();
1239 
1240   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1241 
1242   // Source texture data from the PBO.
1243   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1244   glTexImage2D(this->Target, 0, static_cast<GLint>(inFormat), static_cast<GLsizei>(width),
1245     static_cast<GLsizei>(height), 0, this->Format, this->Type, BUFFER_OFFSET(0));
1246   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1247   pbo->UnBind();
1248   this->Deactivate();
1249   return true;
1250 }
1251 
1252 //------------------------------------------------------------------------------
1253 bool vtkTextureObject::Create3D(unsigned int width, unsigned int height, unsigned int depth,
1254   int numComps, vtkPixelBufferObject* pbo, bool shaderSupportsTextureInt)
1255 {
1256 #ifdef GL_TEXTURE_3D
1257   assert(this->Context);
1258   assert(this->Context.GetPointer() == pbo->GetContext());
1259 
1260   if (pbo->GetSize() != width * height * depth * static_cast<unsigned int>(numComps))
1261   {
1262     vtkErrorMacro("PBO size must match texture size.");
1263     return false;
1264   }
1265 
1266   GLenum target = GL_TEXTURE_3D;
1267 
1268   // Now, determine texture parameters using the information from the pbo.
1269 
1270   // * internalFormat depends on number of components and the data type.
1271   GLenum internalFormat =
1272     this->GetInternalFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
1273 
1274   // * format depends on the number of components.
1275   GLenum format = this->GetFormat(pbo->GetType(), numComps, shaderSupportsTextureInt);
1276 
1277   // * type if the data type in the pbo
1278   GLenum type = this->GetDefaultDataType(pbo->GetType());
1279 
1280   if (!internalFormat || !format || !type)
1281   {
1282     vtkErrorMacro("Failed to determine texture parameters.");
1283     return false;
1284   }
1285 
1286   this->Target = target;
1287   this->Context->ActivateTexture(this);
1288   this->CreateTexture();
1289   this->Bind();
1290 
1291   pbo->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
1292 
1293   // Source texture data from the PBO.
1294   glTexImage3D(target, 0, static_cast<GLint>(internalFormat), static_cast<GLsizei>(width),
1295     static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, format, type, BUFFER_OFFSET(0));
1296 
1297   vtkOpenGLCheckErrorMacro("failed at glTexImage3D");
1298 
1299   pbo->UnBind();
1300   this->Deactivate();
1301 
1302   this->Target = target;
1303   this->Format = format;
1304   this->Type = type;
1305   this->Components = numComps;
1306   this->Width = width;
1307   this->Height = height;
1308   this->Depth = depth;
1309   this->NumberOfDimensions = 3;
1310   return true;
1311 
1312 #else
1313   return false;
1314 #endif
1315 }
1316 
1317 //------------------------------------------------------------------------------
1318 vtkPixelBufferObject* vtkTextureObject::Download(unsigned int target, unsigned int level)
1319 {
1320   assert(this->Context);
1321   assert(this->Handle);
1322 
1323   vtkPixelBufferObject* pbo = vtkPixelBufferObject::New();
1324   pbo->SetContext(this->Context);
1325 
1326   int vtktype = ::vtkGetVTKType(this->Type);
1327   if (vtktype == 0)
1328   {
1329     vtkErrorMacro("Failed to determine type.");
1330     return nullptr;
1331   }
1332 
1333   unsigned int size = this->Width * this->Height * this->Depth;
1334 
1335   // doesn't matter which Upload*D method we use since we are not really
1336   // uploading any data, simply allocating GPU space.
1337   if (!pbo->Upload1D(vtktype, nullptr, size, this->Components, 0))
1338   {
1339     vtkErrorMacro("Could not allocate memory for PBO.");
1340     pbo->Delete();
1341     return nullptr;
1342   }
1343 
1344   pbo->Bind(vtkPixelBufferObject::PACKED_BUFFER);
1345   this->Bind();
1346 
1347 #ifndef GL_ES_VERSION_3_0
1348   glGetTexImage(target, level, this->Format, this->Type, BUFFER_OFFSET(0));
1349 #else
1350   // you can do something with glReadPixels and binding a texture as a FBO
1351   // I believe for ES 2.0
1352 #endif
1353 
1354   vtkOpenGLCheckErrorMacro("failed at glGetTexImage");
1355   this->Deactivate();
1356   pbo->UnBind();
1357 
1358   pbo->SetComponents(this->Components);
1359 
1360   return pbo;
1361 }
1362 
1363 //------------------------------------------------------------------------------
1364 vtkPixelBufferObject* vtkTextureObject::Download()
1365 {
1366   return this->Download(this->Target, 0);
1367 }
1368 
1369 //------------------------------------------------------------------------------
1370 bool vtkTextureObject::Create3DFromRaw(unsigned int width, unsigned int height, unsigned int depth,
1371   int numComps, int dataType, void* data)
1372 {
1373   assert(this->Context);
1374   vtkOpenGLClearErrorMacro();
1375 
1376   // Now, determine texture parameters using the arguments.
1377   this->GetDataType(dataType);
1378   this->GetInternalFormat(dataType, numComps, false);
1379   this->GetFormat(dataType, numComps, false);
1380 
1381   if (!this->InternalFormat || !this->Format || !this->Type)
1382   {
1383     vtkErrorMacro("Failed to determine texture parameters.");
1384     return false;
1385   }
1386 
1387   this->Target = GL_TEXTURE_3D;
1388   this->Components = numComps;
1389   this->Width = width;
1390   this->Height = height;
1391   this->Depth = depth;
1392   this->NumberOfDimensions = 3;
1393 
1394   this->Context->ActivateTexture(this);
1395   this->CreateTexture();
1396   this->Bind();
1397 
1398   // Source texture data from the PBO.
1399   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1400 
1401   glTexImage3D(this->Target, 0, this->InternalFormat, static_cast<GLsizei>(this->Width),
1402     static_cast<GLsizei>(this->Height), static_cast<GLsizei>(this->Depth), 0, this->Format,
1403     this->Type, static_cast<const GLvoid*>(data));
1404 
1405   this->Deactivate();
1406 
1407   return vtkOpenGLCheckErrors("Failed to allocate 3D texture.");
1408 }
1409 
1410 //------------------------------------------------------------------------------
1411 bool vtkTextureObject::AllocateProxyTexture3D(unsigned int const width, unsigned int const height,
1412   unsigned int depth, int const numComps, int const dataType)
1413 {
1414 #ifndef GL_ES_VERSION_3_0
1415   assert(this->Context);
1416 
1417   this->GetDataType(dataType);
1418   this->GetInternalFormat(dataType, numComps, false);
1419   this->GetFormat(dataType, numComps, false);
1420 
1421   if (!this->InternalFormat || !this->Format || !this->Type)
1422   {
1423     vtkErrorMacro("Failed to determine texture parameters.");
1424     return false;
1425   }
1426 
1427   this->Target = GL_TEXTURE_3D;
1428   this->Context->ActivateTexture(this);
1429   this->CreateTexture();
1430   this->Bind();
1431 
1432   glTexImage3D(GL_PROXY_TEXTURE_3D, 0, this->InternalFormat, static_cast<GLsizei>(width),
1433     static_cast<GLsizei>(height), static_cast<GLsizei>(depth), 0, this->Format, this->Type,
1434     nullptr);
1435 
1436   GLsizei testWidth;
1437   glGetTexLevelParameteriv(GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &testWidth);
1438 
1439   vtkOpenGLCheckErrorMacro("Failed after glTexImage3D with PROXY target");
1440   this->Deactivate();
1441 
1442   if (testWidth == 0)
1443   {
1444     return false;
1445   }
1446 #endif
1447   return true;
1448 }
1449 
1450 //------------------------------------------------------------------------------
1451 bool vtkTextureObject::Create2DFromRaw(
1452   unsigned int width, unsigned int height, int numComps, int dataType, void* data)
1453 {
1454   assert(this->Context);
1455 
1456   // Now determine the texture parameters using the arguments.
1457   this->GetDataType(dataType);
1458   this->GetInternalFormat(dataType, numComps, false);
1459   this->GetFormat(dataType, numComps, false);
1460 
1461   if (!this->InternalFormat || !this->Format || !this->Type)
1462   {
1463     vtkErrorMacro("Failed to determine texture parameters. IF="
1464       << this->InternalFormat << " F=" << this->Format << " T=" << this->Type);
1465     return false;
1466   }
1467 
1468   GLenum target = GL_TEXTURE_2D;
1469   this->Target = target;
1470   this->Components = numComps;
1471   this->Width = width;
1472   this->Height = height;
1473   this->Depth = 1;
1474   this->NumberOfDimensions = 2;
1475   this->Context->ActivateTexture(this);
1476   this->CreateTexture();
1477   this->Bind();
1478 
1479   // Source texture data from the PBO.
1480   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1481 
1482   glTexImage2D(this->Target, 0, this->InternalFormat, static_cast<GLsizei>(this->Width),
1483     static_cast<GLsizei>(this->Height), 0, this->Format, this->Type,
1484     static_cast<const GLvoid*>(data));
1485 
1486   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1487 
1488   this->Deactivate();
1489   return true;
1490 }
1491 
1492 //------------------------------------------------------------------------------
1493 bool vtkTextureObject::CreateCubeFromRaw(
1494   unsigned int width, unsigned int height, int numComps, int dataType, void* data[6])
1495 {
1496   assert(this->Context);
1497 
1498   // Now determine the texture parameters using the arguments.
1499   this->GetDataType(dataType);
1500   this->GetInternalFormat(dataType, numComps, false);
1501   this->GetFormat(dataType, numComps, false);
1502 
1503   if (!this->InternalFormat || !this->Format || !this->Type)
1504   {
1505     vtkErrorMacro("Failed to determine texture parameters. IF="
1506       << this->InternalFormat << " F=" << this->Format << " T=" << this->Type);
1507     return false;
1508   }
1509 
1510   GLenum target = GL_TEXTURE_CUBE_MAP;
1511   this->Target = target;
1512   this->Components = numComps;
1513   this->Width = width;
1514   this->Height = height;
1515   this->Depth = 1;
1516   this->NumberOfDimensions = 2;
1517   this->Context->ActivateTexture(this);
1518   this->CreateTexture();
1519   this->Bind();
1520 
1521   // Source texture data from the PBO.
1522   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1523 
1524   for (int i = 0; i < 6; i++)
1525   {
1526     glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, this->InternalFormat,
1527       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
1528       this->Type, data ? static_cast<const GLvoid*>(data[i]) : nullptr);
1529     vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1530   }
1531 
1532   if (this->GenerateMipmap)
1533   {
1534     glGenerateMipmap(GL_TEXTURE_CUBE_MAP);
1535   }
1536 
1537   this->Deactivate();
1538   return true;
1539 }
1540 
1541 //------------------------------------------------------------------------------
1542 // Description:
1543 // Create a 2D depth texture using a raw pointer.
1544 // This is a blocking call. If you can, use PBO instead.
1545 bool vtkTextureObject::CreateDepthFromRaw(
1546   unsigned int width, unsigned int height, int internalFormat, int rawType, void* raw)
1547 {
1548   assert("pre: context_exists" && this->GetContext() != nullptr);
1549 
1550   assert(
1551     "pre: valid_internalFormat" && internalFormat >= 0 && internalFormat < NumberOfDepthFormats);
1552 
1553   // Now, determine texture parameters using the arguments.
1554   this->GetDataType(rawType);
1555 
1556   if (!this->InternalFormat)
1557   {
1558     this->InternalFormat = OpenGLDepthInternalFormat[internalFormat];
1559   }
1560 
1561   if (!this->InternalFormat || !this->Type)
1562   {
1563     vtkErrorMacro("Failed to determine texture parameters.");
1564     return false;
1565   }
1566 
1567   this->Target = GL_TEXTURE_2D;
1568   this->Format = GL_DEPTH_COMPONENT;
1569   this->Width = width;
1570   this->Height = height;
1571   this->Depth = 1;
1572   this->NumberOfDimensions = 2;
1573   this->Components = 1;
1574 
1575   this->Context->ActivateTexture(this);
1576   this->CreateTexture();
1577   this->Bind();
1578 
1579   this->Context->GetState()->vtkglPixelStorei(GL_UNPACK_ALIGNMENT, 1);
1580   glTexImage2D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
1581     static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
1582     this->Type, raw);
1583   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1584   this->Deactivate();
1585   return true;
1586 }
1587 
1588 //------------------------------------------------------------------------------
1589 bool vtkTextureObject::AllocateDepth(unsigned int width, unsigned int height, int internalFormat)
1590 {
1591   assert("pre: context_exists" && this->GetContext() != nullptr);
1592   assert(
1593     "pre: valid_internalFormat" && internalFormat >= 0 && internalFormat < NumberOfDepthFormats);
1594 
1595 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1596   this->Target = (this->Samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
1597 #else
1598   this->Target = GL_TEXTURE_2D;
1599 #endif
1600 
1601   this->Format = GL_DEPTH_COMPONENT;
1602 
1603   // Try to match vtk type to internal fmt
1604   if (!this->Type)
1605   {
1606     this->Type = OpenGLDepthInternalFormatType[internalFormat];
1607   }
1608 
1609   if (!this->InternalFormat)
1610   {
1611     this->InternalFormat = OpenGLDepthInternalFormat[internalFormat];
1612   }
1613 
1614   this->Width = width;
1615   this->Height = height;
1616   this->Depth = 1;
1617   this->NumberOfDimensions = 2;
1618   this->Components = 1;
1619 
1620   this->Context->ActivateTexture(this);
1621   this->CreateTexture();
1622   this->Bind();
1623 
1624 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1625   if (this->Samples)
1626   {
1627     glTexImage2DMultisample(this->Target, this->Samples, static_cast<GLint>(this->InternalFormat),
1628       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), GL_TRUE);
1629   }
1630   else
1631 #endif
1632   {
1633     glTexImage2D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
1634       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
1635       this->Type, nullptr);
1636   }
1637 
1638   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1639 
1640   this->Deactivate();
1641   return true;
1642 }
1643 
1644 bool vtkTextureObject::AllocateDepthStencil(unsigned int width, unsigned int height)
1645 {
1646   assert("pre: context_exists" && this->GetContext() != nullptr);
1647 
1648 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1649   this->Target = (this->Samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
1650 #else
1651   this->Target = GL_TEXTURE_2D;
1652 #endif
1653 
1654   this->Format = GL_DEPTH_STENCIL;
1655   this->Type = GL_UNSIGNED_INT_24_8;
1656   this->InternalFormat = GL_DEPTH24_STENCIL8;
1657 
1658   this->Width = width;
1659   this->Height = height;
1660   this->Depth = 1;
1661   this->NumberOfDimensions = 2;
1662   this->Components = 1;
1663 
1664   this->Context->ActivateTexture(this);
1665   this->CreateTexture();
1666   this->Bind();
1667 
1668 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1669   if (this->Samples)
1670   {
1671     glTexImage2DMultisample(this->Target, this->Samples, static_cast<GLint>(this->InternalFormat),
1672       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), GL_TRUE);
1673   }
1674   else
1675 #endif
1676   {
1677     glTexImage2D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
1678       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
1679       this->Type, nullptr);
1680   }
1681 
1682   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1683 
1684   this->Deactivate();
1685   return true;
1686 }
1687 
1688 //------------------------------------------------------------------------------
1689 bool vtkTextureObject::Allocate1D(unsigned int width, int numComps, int vtkType)
1690 {
1691 #ifdef GL_TEXTURE_1D
1692   assert(this->Context);
1693 
1694   this->Target = GL_TEXTURE_1D;
1695 
1696   this->GetDataType(vtkType);
1697   this->GetInternalFormat(vtkType, numComps, false);
1698   this->GetFormat(vtkType, numComps, false);
1699 
1700   this->Components = numComps;
1701   this->Width = width;
1702   this->Height = 1;
1703   this->Depth = 1;
1704   this->NumberOfDimensions = 1;
1705 
1706   this->Context->ActivateTexture(this);
1707   this->CreateTexture();
1708   this->Bind();
1709   glTexImage1D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
1710     static_cast<GLsizei>(this->Width), 0, this->Format, this->Type, nullptr);
1711   vtkOpenGLCheckErrorMacro("failed at glTexImage1D");
1712   this->Deactivate();
1713   return true;
1714 #else
1715   return false;
1716 #endif
1717 }
1718 
1719 //------------------------------------------------------------------------------
1720 // Description:
1721 // Create a 2D color texture but does not initialize its values.
1722 // Internal format is deduced from numComps and vtkType.
1723 bool vtkTextureObject::Allocate2D(
1724   unsigned int width, unsigned int height, int numComps, int vtkType, int level)
1725 {
1726   assert(this->Context);
1727 
1728 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1729   this->Target = (this->Samples ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D);
1730 #else
1731   this->Target = GL_TEXTURE_2D;
1732 #endif
1733 
1734   this->GetDataType(vtkType);
1735   this->GetInternalFormat(vtkType, numComps, false);
1736   this->GetFormat(vtkType, numComps, false);
1737 
1738   this->Components = numComps;
1739   this->Width = width;
1740   this->Height = height;
1741   this->Depth = 1;
1742   this->NumberOfDimensions = 2;
1743 
1744   this->Context->ActivateTexture(this);
1745   this->CreateTexture();
1746   this->Bind();
1747 
1748 #ifdef GL_TEXTURE_2D_MULTISAMPLE
1749   if (this->Samples)
1750   {
1751     glTexImage2DMultisample(this->Target, this->Samples, static_cast<GLint>(this->InternalFormat),
1752       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), GL_TRUE);
1753   }
1754   else
1755 #endif
1756   {
1757     glTexImage2D(this->Target, level, static_cast<GLint>(this->InternalFormat),
1758       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
1759       this->Type, nullptr);
1760   }
1761   vtkOpenGLCheckErrorMacro("failed at glTexImage2D");
1762   this->Deactivate();
1763   return true;
1764 }
1765 
1766 //------------------------------------------------------------------------------
1767 // Description:
1768 // Create a 3D color texture but does not initialize its values.
1769 // Internal format is deduced from numComps and vtkType.
1770 bool vtkTextureObject::Allocate3D(
1771   unsigned int width, unsigned int height, unsigned int depth, int numComps, int vtkType)
1772 {
1773 #ifdef GL_TEXTURE_3D
1774   this->Target = GL_TEXTURE_3D;
1775 
1776   if (this->Context == nullptr)
1777   {
1778     vtkErrorMacro("No context specified. Cannot create texture.");
1779     return false;
1780   }
1781 
1782   this->GetInternalFormat(vtkType, numComps, false);
1783   this->GetFormat(vtkType, numComps, false);
1784   this->GetDataType(vtkType);
1785 
1786   this->Components = numComps;
1787   this->Width = width;
1788   this->Height = height;
1789   this->Depth = depth;
1790   this->NumberOfDimensions = 3;
1791 
1792   this->Context->ActivateTexture(this);
1793   this->CreateTexture();
1794   this->Bind();
1795   glTexImage3D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
1796     static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height),
1797     static_cast<GLsizei>(this->Depth), 0, this->Format, this->Type, nullptr);
1798   vtkOpenGLCheckErrorMacro("failed at glTexImage3D");
1799   this->Deactivate();
1800   return true;
1801 #else
1802   return false;
1803 #endif
1804 }
1805 
1806 //------------------------------------------------------------------------------
1807 void vtkTextureObject::CopyToFrameBuffer(vtkShaderProgram* program, vtkOpenGLVertexArrayObject* vao)
1808 {
1809   // the following math really only works when texture
1810   // and viewport are of the same dimensions
1811   float minXTexCoord = static_cast<float>(static_cast<double>(0.5) / this->Width);
1812   float minYTexCoord = static_cast<float>(static_cast<double>(0.5) / this->Height);
1813 
1814   float maxXTexCoord = static_cast<float>(static_cast<double>(this->Width - 0.5) / this->Width);
1815   float maxYTexCoord = static_cast<float>(static_cast<double>(this->Height - 0.5) / this->Height);
1816 
1817   float tcoords[] = { minXTexCoord, minYTexCoord, maxXTexCoord, minYTexCoord, maxXTexCoord,
1818     maxYTexCoord, minXTexCoord, maxYTexCoord };
1819 
1820   float verts[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f, 0.0f };
1821 
1822   this->CopyToFrameBuffer(tcoords, verts, program, vao);
1823 }
1824 
1825 //------------------------------------------------------------------------------
1826 void vtkTextureObject::CopyToFrameBuffer(int srcXmin, int srcYmin, int srcXmax, int srcYmax,
1827   int dstXmin, int dstYmin, int dstSizeX, int dstSizeY, vtkShaderProgram* program,
1828   vtkOpenGLVertexArrayObject* vao)
1829 {
1830   float dstXmax = static_cast<float>(dstXmin + srcXmax - srcXmin);
1831   float dstYmax = static_cast<float>(dstYmin + srcYmax - srcYmin);
1832 
1833   this->CopyToFrameBuffer(srcXmin, srcYmin, srcXmax, srcYmax, dstXmin, dstYmin, dstXmax, dstYmax,
1834     dstSizeX, dstSizeY, program, vao);
1835 }
1836 
1837 //------------------------------------------------------------------------------
1838 void vtkTextureObject::CopyToFrameBuffer(int srcXmin, int srcYmin, int srcXmax, int srcYmax,
1839   int dstXmin, int dstYmin, int dstXmax, int dstYmax, int vtkNotUsed(dstSizeX),
1840   int vtkNotUsed(dstSizeY), vtkShaderProgram* program, vtkOpenGLVertexArrayObject* vao)
1841 {
1842   assert("pre: positive_srcXmin" && srcXmin >= 0);
1843   assert("pre: max_srcXmax" && static_cast<unsigned int>(srcXmax) < this->GetWidth());
1844   assert("pre: increasing_x" && srcXmin <= srcXmax);
1845   assert("pre: positive_srcYmin" && srcYmin >= 0);
1846   assert("pre: max_srcYmax" && static_cast<unsigned int>(srcYmax) < this->GetHeight());
1847   assert("pre: increasing_y" && srcYmin <= srcYmax);
1848   assert("pre: positive_dstXmin" && dstXmin >= 0);
1849   assert("pre: positive_dstYmin" && dstYmin >= 0);
1850 
1851   float minXTexCoord = static_cast<float>(static_cast<double>(srcXmin + 0.5) / this->Width);
1852   float minYTexCoord = static_cast<float>(static_cast<double>(srcYmin + 0.5) / this->Height);
1853 
1854   float maxXTexCoord = static_cast<float>(static_cast<double>(srcXmax + 0.5) / this->Width);
1855   float maxYTexCoord = static_cast<float>(static_cast<double>(srcYmax + 0.5) / this->Height);
1856 
1857   vtkOpenGLState::ScopedglViewport vsaver(this->Context->GetState());
1858   this->Context->GetState()->vtkglViewport(
1859     dstXmin, dstYmin, dstXmax - dstXmin + 1, dstYmax - dstYmin + 1);
1860 
1861   float tcoords[] = { minXTexCoord, minYTexCoord, maxXTexCoord, minYTexCoord, maxXTexCoord,
1862     maxYTexCoord, minXTexCoord, maxYTexCoord };
1863 
1864   float verts[] = { -1.f, -1.f, 0.0f, 1.0f, -1.f, 0.0f, 1.0f, 1.0f, 0.0f, -1.f, 1.0f, 0.0f };
1865 
1866   this->CopyToFrameBuffer(tcoords, verts, program, vao);
1867 
1868   vtkOpenGLCheckErrorMacro("failed after CopyToFrameBuffer");
1869 }
1870 
1871 void vtkTextureObject::CopyToFrameBuffer(
1872   float* tcoords, float* verts, vtkShaderProgram* program, vtkOpenGLVertexArrayObject* vao)
1873 {
1874   vtkOpenGLClearErrorMacro();
1875 
1876   // if no program or VAO was provided, then use
1877   // a simple pass through program and bind this
1878   // texture to it
1879   if (!program || !vao)
1880   {
1881     if (!this->ShaderProgram)
1882     {
1883       this->ShaderProgram = new vtkOpenGLHelper;
1884 
1885       // build the shader source code
1886       std::string VSSource = vtkTextureObjectVS;
1887       std::string FSSource = vtkTextureObjectFS;
1888       std::string GSSource;
1889 
1890       // compile and bind it if needed
1891       vtkShaderProgram* newShader = this->Context->GetShaderCache()->ReadyShaderProgram(
1892         VSSource.c_str(), FSSource.c_str(), GSSource.c_str());
1893 
1894       // if the shader changed reinitialize the VAO
1895       if (newShader != this->ShaderProgram->Program)
1896       {
1897         this->ShaderProgram->Program = newShader;
1898         this->ShaderProgram->VAO->ShaderProgramChanged(); // reset the VAO as the shader has changed
1899       }
1900 
1901       this->ShaderProgram->ShaderSourceTime.Modified();
1902     }
1903     else
1904     {
1905       this->Context->GetShaderCache()->ReadyShaderProgram(this->ShaderProgram->Program);
1906     }
1907 
1908     if (this->ShaderProgram->Program)
1909     {
1910       // bind and activate this texture
1911       this->Activate();
1912       int sourceId = this->GetTextureUnit();
1913       this->ShaderProgram->Program->SetUniformi("source", sourceId);
1914       vtkOpenGLRenderUtilities::RenderQuad(
1915         verts, tcoords, this->ShaderProgram->Program, this->ShaderProgram->VAO);
1916       this->Deactivate();
1917     }
1918   }
1919   else
1920   {
1921     vtkOpenGLRenderUtilities::RenderQuad(verts, tcoords, program, vao);
1922   }
1923 
1924   vtkOpenGLCheckErrorMacro("failed after CopyToFrameBuffer");
1925 }
1926 
1927 //------------------------------------------------------------------------------
1928 // Description:
1929 // Copy a sub-part of a logical buffer of the framebuffer (color or depth)
1930 // to the texture object. src is the framebuffer, dst is the texture.
1931 // (srcXmin,srcYmin) is the location of the lower left corner of the
1932 // rectangle in the framebuffer. (dstXmin,dstYmin) is the location of the
1933 // lower left corner of the rectangle in the texture. width and height
1934 // specifies the size of the rectangle in pixels.
1935 // If the logical buffer is a color buffer, it has to be selected first with
1936 // glReadBuffer().
1937 // \pre is2D: GetNumberOfDimensions()==2
1938 void vtkTextureObject::CopyFromFrameBuffer(
1939   int srcXmin, int srcYmin, int vtkNotUsed(dstXmin), int vtkNotUsed(dstYmin), int width, int height)
1940 {
1941   assert("pre: is2D" && this->GetNumberOfDimensions() == 2);
1942 
1943   // make assumption on the need to resolve
1944   // based on MultiSample setting
1945   if (this->Context->GetMultiSamples())
1946   {
1947     vtkNew<vtkOpenGLFramebufferObject> resolvedFBO;
1948     resolvedFBO->SetContext(this->Context);
1949     this->Context->GetState()->PushFramebufferBindings();
1950     resolvedFBO->PopulateFramebuffer(width, height,
1951       /* useTextures = */ true,
1952       /* numberOfColorAttachments = */ 1,
1953       /* colorDataType = */ VTK_UNSIGNED_CHAR,
1954       /* wantDepthAttachment = */ true,
1955       /* depthBitplanes = */ 24,
1956       /* multisamples = */ 0);
1957 
1958     // PopulateFramebuffer changes active read/write buffer bindings,
1959     // hence we restore the read buffer bindings to read from the original
1960     // frame buffer.
1961     this->Context->GetState()->PopReadFramebufferBinding();
1962 
1963     vtkOpenGLState::ScopedglViewport vsaver(this->Context->GetState());
1964     this->Context->GetState()->vtkglViewport(0, 0, width, height);
1965     vtkOpenGLState::ScopedglScissor ssaver(this->Context->GetState());
1966     this->Context->GetState()->vtkglScissor(0, 0, width, height);
1967 
1968     // Now blit to resolve the MSAA and get an anti-aliased rendering in
1969     // resolvedFBO.
1970     this->Context->GetState()->vtkglBlitFramebuffer(srcXmin, srcYmin, srcXmin + width,
1971       srcYmin + height, 0, 0, width, height, GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, GL_NEAREST);
1972 
1973     // Now make the resolvedFBO the read buffer and read from it.
1974     this->Context->GetState()->PushReadFramebufferBinding();
1975     resolvedFBO->Bind(GL_READ_FRAMEBUFFER);
1976     resolvedFBO->ActivateReadBuffer(0);
1977 
1978     this->Activate();
1979 
1980     glCopyTexImage2D(this->Target, 0, this->InternalFormat, 0, 0, width, height, 0);
1981 
1982     // restore bindings and release the resolvedFBO.
1983     this->Context->GetState()->PopFramebufferBindings();
1984   }
1985   else
1986   {
1987     this->Activate();
1988     glCopyTexImage2D(this->Target, 0, this->InternalFormat, srcXmin, srcYmin, width, height, 0);
1989   }
1990 
1991   vtkOpenGLCheckErrorMacro("failed at glCopyTexImage2D " << this->InternalFormat);
1992 }
1993 
1994 //------------------------------------------------------------------------------
1995 int vtkTextureObject::GetMaximumTextureSize(vtkOpenGLRenderWindow* context)
1996 {
1997   int maxSize = -1;
1998   if (context)
1999   {
2000     context->GetState()->vtkglGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
2001   }
2002 
2003   return maxSize;
2004 }
2005 
2006 //------------------------------------------------------------------------------
2007 int vtkTextureObject::GetMaximumTextureSize3D(vtkOpenGLRenderWindow* context)
2008 {
2009   GLint maxSize = -1;
2010   if (context && context->IsCurrent())
2011   {
2012     glGetIntegerv(GL_MAX_3D_TEXTURE_SIZE, &maxSize);
2013   }
2014 
2015   return static_cast<int>(maxSize);
2016 }
2017 
2018 //------------------------------------------------------------------------------
2019 int vtkTextureObject::GetMaximumTextureSize3D()
2020 {
2021   assert("Context == nullptr" && this->Context);
2022   return vtkTextureObject::GetMaximumTextureSize3D(this->Context);
2023 }
2024 
2025 //------------------------------------------------------------------------------
2026 void vtkTextureObject::Resize(unsigned int width, unsigned int height)
2027 {
2028   if (this->Width == width && this->Height == height)
2029   {
2030     return;
2031   }
2032 
2033   this->Width = width;
2034   this->Height = height;
2035 
2036   this->Context->ActivateTexture(this);
2037   this->Bind();
2038 
2039   if (this->NumberOfDimensions == 2)
2040   {
2041 #ifdef GL_TEXTURE_2D_MULTISAMPLE
2042     if (this->Samples)
2043     {
2044       glTexImage2DMultisample(this->Target, this->Samples, static_cast<GLint>(this->InternalFormat),
2045         static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), GL_TRUE);
2046     }
2047     else
2048 #endif
2049     {
2050       glTexImage2D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
2051         static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height), 0, this->Format,
2052         this->Type, nullptr);
2053     }
2054   }
2055   else if (this->NumberOfDimensions == 3)
2056   {
2057     glTexImage3D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
2058       static_cast<GLsizei>(this->Width), static_cast<GLsizei>(this->Height),
2059       static_cast<GLsizei>(this->Depth), 0, this->Format, this->Type, nullptr);
2060   }
2061 #ifdef GL_TEXTURE_1D
2062   else if (this->NumberOfDimensions == 1)
2063   {
2064     glTexImage1D(this->Target, 0, static_cast<GLint>(this->InternalFormat),
2065       static_cast<GLsizei>(this->Width), 0, this->Format, this->Type, nullptr);
2066   }
2067 #endif
2068 
2069   vtkOpenGLCheckErrorMacro("failed at texture resize");
2070   this->Deactivate();
2071 }
2072 
2073 //------------------------------------------------------------------------------
2074 void vtkTextureObject::PrintSelf(ostream& os, vtkIndent indent)
2075 {
2076   this->Superclass::PrintSelf(os, indent);
2077 
2078   os << indent << "Width: " << this->Width << endl;
2079   os << indent << "Height: " << this->Height << endl;
2080   os << indent << "Depth: " << this->Depth << endl;
2081   os << indent << "Components: " << this->Components << endl;
2082   os << indent << "Handle: " << this->Handle << endl;
2083   os << indent << "Target: ";
2084 
2085   switch (this->Target)
2086   {
2087 #ifdef GL_TEXTURE_1D
2088     case GL_TEXTURE_1D:
2089       os << "GL_TEXTURE_1D" << endl;
2090       break;
2091 #endif
2092     case GL_TEXTURE_2D:
2093       os << "GL_TEXTURE_2D" << endl;
2094       break;
2095 #ifdef GL_TEXTURE_3D
2096     case GL_TEXTURE_3D:
2097       os << "GL_TEXTURE_3D" << endl;
2098       break;
2099 #endif
2100     default:
2101       os << "unknown value: 0x" << hex << this->Target << dec << endl;
2102       break;
2103   }
2104 
2105   os << indent << "NumberOfDimensions: " << this->NumberOfDimensions << endl;
2106 
2107   os << indent << "Format: " << this->Format << endl;
2108   os << indent << "InternalFormat: " << this->InternalFormat << endl;
2109   os << indent << "Type: " << this->Type << endl;
2110 
2111   os << indent << "WrapS: " << WrapAsString[this->WrapS] << endl;
2112   os << indent << "WrapT: " << WrapAsString[this->WrapT] << endl;
2113   os << indent << "WrapR: " << WrapAsString[this->WrapR] << endl;
2114 
2115   os << indent << "MinificationFilter: " << MinMagFilterAsString[this->MinificationFilter] << endl;
2116 
2117   os << indent << "MagnificationFilter: " << MinMagFilterAsString[this->MagnificationFilter]
2118      << endl;
2119 
2120   os << indent << "MinLOD: " << this->MinLOD << endl;
2121   os << indent << "MaxLOD: " << this->MaxLOD << endl;
2122   os << indent << "BaseLevel: " << this->BaseLevel << endl;
2123   os << indent << "MaxLevel: " << this->MaxLevel << endl;
2124   os << indent << "DepthTextureCompare: " << this->DepthTextureCompare << endl;
2125   os << indent << "DepthTextureCompareFunction: "
2126      << DepthTextureCompareFunctionAsString[this->DepthTextureCompareFunction] << endl;
2127   os << indent << "GenerateMipmap: " << this->GenerateMipmap << endl;
2128 }
2129