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