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