1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkPixelBufferObject.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 "vtkPixelBufferObject.h"
16 
17 #include "vtk_glew.h"
18 
19 #include "vtkObjectFactory.h"
20 #include "vtkOpenGLRenderWindow.h"
21 
22 #include "vtkOpenGLError.h"
23 
24 //#define VTK_PBO_DEBUG
25 //#define VTK_PBO_TIMING
26 
27 #ifdef VTK_PBO_TIMING
28 #include "vtkTimerLog.h"
29 #endif
30 
31 #include <cassert>
32 
33 // Mapping from Usage values to OpenGL values.
34 
35 static const GLenum OpenGLBufferObjectUsage[9]=
36 {
37   GL_STREAM_DRAW,
38   GL_STREAM_READ,
39   GL_STREAM_COPY,
40   GL_STATIC_DRAW,
41   GL_STATIC_READ,
42   GL_STATIC_COPY,
43   GL_DYNAMIC_DRAW,
44   GL_DYNAMIC_READ,
45   GL_DYNAMIC_COPY
46 };
47 
48 static const char *BufferObjectUsageAsString[9]=
49 {
50   "StreamDraw",
51   "StreamRead",
52   "StreamCopy",
53   "StaticDraw",
54   "StaticRead",
55   "StaticCopy",
56   "DynamicDraw",
57   "DynamicRead",
58   "DynamicCopy"
59 };
60 
61 // access modes
62 const GLenum OpenGLBufferObjectAccess[2]=
63 {
64 #if GL_ES_VERSION_3_0 == 1
65   GL_MAP_WRITE_BIT,
66   GL_MAP_READ_BIT
67 #else
68   GL_WRITE_ONLY,
69   GL_READ_ONLY
70 #endif
71 };
72 
73 // targets
74 const GLenum OpenGLBufferObjectTarget[2]=
75 {
76   GL_PIXEL_UNPACK_BUFFER,
77   GL_PIXEL_PACK_BUFFER
78 };
79 
80 
81 #ifdef  VTK_PBO_DEBUG
82 #include <pthread.h> // for debugging with MPI, pthread_self()
83 #endif
84 
85 // converting double to float behind the
86 // scene so we need sizeof(double)==4
87 template< class T >
88 class vtksizeof
89 {
90 public:
GetSize()91   static int GetSize() { return sizeof(T); }
92 };
93 
94 template<>
95 class vtksizeof< double >
96 {
97 public:
GetSize()98   static int GetSize() { return sizeof(float); }
99 };
100 
vtkGetSize(int type)101 static int vtkGetSize(int type)
102 {
103   switch (type)
104   {
105     vtkTemplateMacro(
106       return ::vtksizeof<VTK_TT>::GetSize();
107       );
108   }
109   return 0;
110 }
111 
112 //----------------------------------------------------------------------------
113 vtkStandardNewMacro(vtkPixelBufferObject);
114 
115 //----------------------------------------------------------------------------
vtkPixelBufferObject()116 vtkPixelBufferObject::vtkPixelBufferObject()
117 {
118   this->Handle = 0;
119   this->Context = nullptr;
120   this->BufferTarget = 0;
121   this->Components = 0;
122   this->Size = 0;
123   this->Type = VTK_UNSIGNED_CHAR;
124   this->Usage = StaticDraw;
125 }
126 
127 //----------------------------------------------------------------------------
~vtkPixelBufferObject()128 vtkPixelBufferObject::~vtkPixelBufferObject()
129 {
130   this->DestroyBuffer();
131 }
132 
133 //----------------------------------------------------------------------------
IsSupported(vtkRenderWindow *)134 bool vtkPixelBufferObject::IsSupported(vtkRenderWindow*)
135 {
136   return true;
137 }
138 
139 //----------------------------------------------------------------------------
LoadRequiredExtensions(vtkRenderWindow * vtkNotUsed (renWin))140 bool vtkPixelBufferObject::LoadRequiredExtensions(vtkRenderWindow *vtkNotUsed(renWin))
141 {
142   return true;
143 }
144 
145 //----------------------------------------------------------------------------
SetContext(vtkRenderWindow * renWin)146 void vtkPixelBufferObject::SetContext(vtkRenderWindow* renWin)
147 {
148   // avoid pointless re-assignment
149   if (this->Context==renWin)
150   {
151     return;
152   }
153   // free resource allocations
154   this->DestroyBuffer();
155   this->Context = nullptr;
156   this->Modified();
157   // all done if assigned null
158   if (!renWin)
159   {
160     return;
161   }
162 
163   // update context
164   this->Context = renWin;
165   this->Context->MakeCurrent();
166 }
167 
168 //----------------------------------------------------------------------------
GetContext()169 vtkRenderWindow* vtkPixelBufferObject::GetContext()
170 {
171   return this->Context;
172 }
173 
174 //----------------------------------------------------------------------------
SetSize(unsigned int nTups,int nComps)175 void vtkPixelBufferObject::SetSize(unsigned int nTups, int nComps)
176 {
177   this->Size = nTups*nComps;
178 }
179 
180 //----------------------------------------------------------------------------
Bind(BufferType type)181 void vtkPixelBufferObject::Bind(BufferType type)
182 {
183   assert(this->Context);
184 
185   this->CreateBuffer();
186 
187   GLenum target;
188   switch (type)
189   {
190     case vtkPixelBufferObject::PACKED_BUFFER:
191       target = GL_PIXEL_PACK_BUFFER;
192       break;
193 
194     case vtkPixelBufferObject::UNPACKED_BUFFER:
195       target = GL_PIXEL_UNPACK_BUFFER;
196       break;
197 
198     default:
199       vtkErrorMacro("Impossible BufferType.");
200       target = static_cast<GLenum>(this->BufferTarget);
201       break;
202   }
203 
204   if (this->BufferTarget && this->BufferTarget != target)
205   {
206     this->UnBind();
207   }
208   this->BufferTarget = target;
209   glBindBuffer(static_cast<GLenum>(this->BufferTarget), this->Handle);
210   vtkOpenGLCheckErrorMacro("failed at glBindBuffer");
211 }
212 
213 //----------------------------------------------------------------------------
UnBind()214 void vtkPixelBufferObject::UnBind()
215 {
216   assert(this->Context);
217   if (this->Handle && this->BufferTarget)
218   {
219     glBindBuffer(this->BufferTarget, 0);
220     vtkOpenGLCheckErrorMacro("failed at glBindBuffer(0)");
221     this->BufferTarget = 0;
222   }
223 }
224 
225 //----------------------------------------------------------------------------
CreateBuffer()226 void vtkPixelBufferObject::CreateBuffer()
227 {
228   if (!this->Handle)
229   {
230     GLuint ioBuf;
231     glGenBuffers(1, &ioBuf);
232     vtkOpenGLCheckErrorMacro("failed at glGenBuffers");
233     this->Handle = ioBuf;
234   }
235 }
236 
237 //----------------------------------------------------------------------------
DestroyBuffer()238 void vtkPixelBufferObject::DestroyBuffer()
239 {
240   // because we don't hold a reference to the render
241   // context we don't have any control on when it is
242   // destroyed. In fact it may be destroyed before
243   // we are(eg smart pointers), in which case we should
244   // do nothing.
245   if (this->Context && this->Handle)
246   {
247     GLuint ioBuf = static_cast<GLuint>(this->Handle);
248     glDeleteBuffers(1, &ioBuf);
249     vtkOpenGLCheckErrorMacro("failed at glDeleteBuffers");
250   }
251   this->Handle = 0;
252 }
253 
254 //----------------------------------------------------------------------------
255 template <class T>
256 class vtkUpload3D
257 {
258 public:
Upload(void * pboPtr,T * inData,unsigned int dims[3],int numComponents,vtkIdType continuousIncrements[3],int components,int * componentList)259   static void Upload(void *pboPtr,
260                      T *inData,
261                      unsigned int dims[3],
262                      int numComponents,
263                      vtkIdType continuousIncrements[3],
264                      int components,
265                      int *componentList)
266   {
267       //  cout<<"incs[3]="<<continuousIncrements[0]<<" "<<continuousIncrements[1]
268       //      <<" "<<continuousIncrements[2]<<endl;
269 
270       T* fIoMem = static_cast<T*>(pboPtr);
271 
272       int numComp;
273       int *permutation=nullptr;
274       if(components==0)
275       {
276         numComp=numComponents;
277         permutation=new int[numComponents];
278         int i=0;
279         while(i<numComp)
280         {
281           permutation[i]=i;
282           ++i;
283         }
284       }
285       else
286       {
287         numComp=components;
288         permutation=componentList;
289       }
290 
291       vtkIdType tupleSize =
292         static_cast<vtkIdType>(numComponents + continuousIncrements[0]);
293       for (unsigned int zz=0; zz < dims[2]; zz++)
294       {
295         for (unsigned int yy = 0; yy < dims[1]; yy++)
296         {
297           for (unsigned int xx=0; xx < dims[0]; xx++)
298           {
299             for (int compNo=0; compNo < numComp; compNo++)
300             {
301               *fIoMem = inData[permutation[compNo]];
302 //              cout<<"upload[zz="<<zz<<"][yy="<<yy<<"][xx="<<xx<<"][compNo="<<
303 //              compNo<<"] from inData to pbo="<<(double)(*fIoMem)<<endl;
304 
305               fIoMem++;
306             }
307             inData += tupleSize+continuousIncrements[0];
308           }
309           // Reached end of row, go to start of next row.
310           inData += continuousIncrements[1] * tupleSize;
311         }
312         // Reached end of 2D plane.
313         inData += continuousIncrements[2] * tupleSize;
314       }
315 
316       if(components==0)
317       {
318         delete[] permutation;
319       }
320   }
321 };
322 
323 template<>
324 class vtkUpload3D< double >
325 {
326 public:
Upload(void * pboPtr,double * inData,unsigned int dims[3],int numComponents,vtkIdType continuousIncrements[3],int components,int * componentList)327   static void Upload(void *pboPtr,
328                      double *inData,
329                      unsigned int dims[3],
330                      int numComponents,
331                      vtkIdType continuousIncrements[3],
332                      int components,
333                      int *componentList)
334   {
335       float* fIoMem = static_cast<float*>(pboPtr);
336 
337       int numComp;
338       int *permutation=nullptr;
339       if(components==0)
340       {
341         numComp=numComponents;
342         permutation=new int[numComponents];
343         int i=0;
344         while(i<numComp)
345         {
346           permutation[i]=i;
347           ++i;
348         }
349       }
350       else
351       {
352         numComp=components;
353         permutation=componentList;
354       }
355 
356       vtkIdType tupleSize =
357         static_cast<vtkIdType>(numComponents + continuousIncrements[0]);
358       for (unsigned int zz=0; zz < dims[2]; zz++)
359       {
360         for (unsigned int yy = 0; yy < dims[1]; yy++)
361         {
362           for (unsigned int xx=0; xx < dims[0]; xx++)
363           {
364             for (int compNo=0; compNo < numComponents; compNo++)
365             {
366               *fIoMem = static_cast<float>(inData[permutation[compNo]]);
367 
368               //        cout<<"upload specialized double[zz="<<zz<<"][yy="<<yy<<"][xx="<<xx<<"][compNo="<<compNo<<"] from inData="<<(*inData)<<" to pbo="<<(*fIoMem)<<endl;
369 
370               fIoMem++;
371             }
372 
373             inData += tupleSize+continuousIncrements[0];
374           }
375           // Reached end of row, go to start of next row.
376           inData += continuousIncrements[1] * tupleSize;
377         }
378         // Reached end of 2D plane.
379         inData += continuousIncrements[2] * tupleSize;
380       }
381       if(components==0)
382       {
383         delete[] permutation;
384       }
385   }
386 };
387 
388 //----------------------------------------------------------------------------
MapBuffer(unsigned int nbytes,BufferType mode)389 void *vtkPixelBufferObject::MapBuffer(
390         unsigned int nbytes,
391         BufferType mode)
392 {
393   // from vtk to opengl enums
394   GLenum target = OpenGLBufferObjectTarget[mode];
395   GLenum access = OpenGLBufferObjectAccess[mode];
396   GLenum usage = OpenGLBufferObjectUsage[mode];
397   GLuint size = static_cast<GLuint>(nbytes);
398   GLuint ioBuf = static_cast<GLuint>(this->Handle);
399 
400   if (!ioBuf)
401   {
402     glGenBuffers(1, &ioBuf);
403     vtkOpenGLCheckErrorMacro("failed at glGenBuffers");
404     this->Handle = static_cast<unsigned int>(ioBuf);
405   }
406   this->BufferTarget = 0;
407 
408   // pointer to the mapped memory
409   glBindBuffer(target, ioBuf);
410   vtkOpenGLCheckErrorMacro("failed at glBindBuffer");
411 
412   glBufferData(target, size, nullptr, usage);
413   vtkOpenGLCheckErrorMacro("failed at glBufferData");
414 
415 #if GL_ES_VERSION_3_0 == 1
416   void *pPBO = glMapBufferRange(target, 0, size, access);
417 #else
418   void *pPBO = glMapBuffer(target, access);
419 #endif
420   vtkOpenGLCheckErrorMacro("failed at glMapBuffer");
421 
422   glBindBuffer(target, 0);
423 
424   return pPBO;
425 }
426 
427 //----------------------------------------------------------------------------
MapBuffer(int type,unsigned int numtuples,int comps,BufferType mode)428 void *vtkPixelBufferObject::MapBuffer(
429         int type,
430         unsigned int numtuples,
431         int comps,
432         BufferType mode)
433 {
434   // from vtk to opengl enums
435   this->Size = numtuples*comps;
436   this->Type = type;
437   this->Components = comps;
438   unsigned int size = ::vtkGetSize(type)*this->Size;
439 
440   return this->MapBuffer(size, mode);
441 }
442 
443 //----------------------------------------------------------------------------
MapBuffer(BufferType mode)444 void *vtkPixelBufferObject::MapBuffer(BufferType mode)
445 {
446   // from vtk to opengl enum
447   GLuint ioBuf = static_cast<GLuint>(this->Handle);
448   if (!ioBuf)
449   {
450     vtkErrorMacro("Uninitialized object");
451     return nullptr;
452   }
453   GLenum target = OpenGLBufferObjectTarget[mode];
454   GLenum access = OpenGLBufferObjectAccess[mode];
455 
456   // pointer to the mnapped memory
457   glBindBuffer(target, ioBuf);
458   vtkOpenGLCheckErrorMacro("failed at glBindBuffer");
459 
460 #if GL_ES_VERSION_3_0 == 1
461   void *pPBO = glMapBufferRange(this->BufferTarget, 0, this->Size, access);
462 #else
463   void *pPBO = glMapBuffer(target, access);
464 #endif
465   vtkOpenGLCheckErrorMacro("failed at glMapBuffer");
466 
467   glBindBuffer(target, 0);
468   vtkOpenGLCheckErrorMacro("failed at glBindBuffer(0)");
469 
470   this->BufferTarget = 0;
471 
472   return pPBO;
473 }
474 
475 //----------------------------------------------------------------------------
UnmapBuffer(BufferType mode)476 void vtkPixelBufferObject::UnmapBuffer(BufferType mode)
477 {
478   GLuint ioBuf = static_cast<GLuint>(this->Handle);
479   if (!ioBuf)
480   {
481     vtkErrorMacro("Uninitialized object");
482     return;
483   }
484   GLenum target = OpenGLBufferObjectTarget[mode];
485 
486   glBindBuffer(target, ioBuf);
487   vtkOpenGLCheckErrorMacro("failed at glBindBuffer");
488 
489   glUnmapBuffer(target);
490   vtkOpenGLCheckErrorMacro("failed at glUnmapBuffer");
491 
492   glBindBuffer(target, 0);
493   vtkOpenGLCheckErrorMacro("failed at glBindBuffer(0)");
494 }
495 
496 //----------------------------------------------------------------------------
Upload3D(int type,void * data,unsigned int dims[3],int numComponents,vtkIdType continuousIncrements[3],int components,int * componentList)497 bool vtkPixelBufferObject::Upload3D(
498   int type, void* data,
499   unsigned int dims[3],
500   int numComponents,
501   vtkIdType continuousIncrements[3],
502   int components,
503   int *componentList)
504 {
505 #ifdef VTK_PBO_TIMING
506   vtkTimerLog *timer=vtkTimerLog::New();
507   timer->StartTimer();
508 #endif
509   assert(this->Context);
510 
511   this->CreateBuffer();
512   this->Bind(vtkPixelBufferObject::UNPACKED_BUFFER);
513 
514   unsigned int size;
515 
516   if(components==0)
517   {
518     size = dims[0]*dims[1]*dims[2]*static_cast<unsigned int>(numComponents);
519   }
520   else
521   {
522     size = dims[0]*dims[1]*dims[2]*static_cast<unsigned int>(components);
523   }
524 
525   this->Components = numComponents;
526 
527   if(data!=nullptr)
528   {
529     this->Usage=StreamDraw;
530   }
531   else
532   {
533     this->Usage=StreamRead;
534   }
535 
536   glBufferData(this->BufferTarget,
537                     size*static_cast<unsigned int>(::vtkGetSize(type)),
538                     nullptr,OpenGLBufferObjectUsage[this->Usage]);
539   vtkOpenGLCheckErrorMacro("failed at glBufferData");
540   this->Type = type;
541   if (this->Type == VTK_DOUBLE)
542   {
543     this->Type = VTK_FLOAT;
544   }
545   this->Size = size;
546 
547   if (data)
548   {
549 #if GL_ES_VERSION_3_0 == 1
550     void* ioMem = glMapBufferRange(this->BufferTarget, 0, size, GL_MAP_WRITE_BIT);
551 #else
552     void* ioMem = glMapBuffer(this->BufferTarget, GL_WRITE_ONLY);
553 #endif
554     vtkOpenGLCheckErrorMacro("");
555     switch (type)
556     {
557       vtkTemplateMacro(
558         ::vtkUpload3D< VTK_TT >::Upload(ioMem, static_cast<VTK_TT*>(data),
559                                         dims, numComponents,
560                                         continuousIncrements,
561                                         components,componentList);
562         );
563       default:
564         vtkErrorMacro("unsupported vtk type");
565         return false;
566     }
567     glUnmapBuffer(this->BufferTarget);
568     vtkOpenGLCheckErrorMacro("failed at glUnmapBuffer");
569   }
570 
571   this->UnBind();
572 #ifdef VTK_PBO_TIMING
573   timer->StopTimer();
574   double time=timer->GetElapsedTime();
575   timer->Delete();
576   cout<<"Upload data to PBO"<<time<<" seconds."<<endl;
577 #endif
578   return true;
579 }
580 
581 //----------------------------------------------------------------------------
Allocate(int type,unsigned int numtuples,int comps,BufferType mode)582 void vtkPixelBufferObject::Allocate(
583         int type,
584         unsigned int numtuples,
585         int comps,
586         BufferType mode)
587 {
588   assert(this->Context);
589 
590   // from vtk to opengl enums
591   this->Size = numtuples*comps;
592   this->Type = type;
593   this->Components = comps;
594   unsigned int size = ::vtkGetSize(type)*this->Size;
595 
596   this->Allocate(size, mode);
597 }
598 
599 //----------------------------------------------------------------------------
Allocate(unsigned int nbytes,BufferType mode)600 void vtkPixelBufferObject::Allocate(
601         unsigned int nbytes,
602         BufferType mode)
603 {
604   assert(this->Context);
605 
606   // from vtk to opengl enums
607   GLenum target = OpenGLBufferObjectTarget[mode];
608   GLenum usage = OpenGLBufferObjectUsage[mode];
609   GLuint size = static_cast<GLuint>(nbytes);
610   GLuint ioBuf = static_cast<GLuint>(this->Handle);
611 
612   if (!ioBuf)
613   {
614     glGenBuffers(1, &ioBuf);
615     vtkOpenGLCheckErrorMacro("failed at glGenBuffers");
616     this->Handle = static_cast<unsigned int>(ioBuf);
617   }
618   this->BufferTarget = 0;
619 
620   glBindBuffer(target, ioBuf);
621   vtkOpenGLCheckErrorMacro("failed at glBindBuffer");
622 
623   glBufferData(target, size, nullptr, usage);
624   vtkOpenGLCheckErrorMacro("failed at glBufferData");
625 
626   glBindBuffer(target, 0);
627 }
628 
629 
630 //----------------------------------------------------------------------------
ReleaseMemory()631 void vtkPixelBufferObject::ReleaseMemory()
632 {
633   assert(this->Context);
634   assert(this->Handle);
635 
636   this->Bind(vtkPixelBufferObject::PACKED_BUFFER);
637   glBufferData(this->BufferTarget, 0, nullptr, GL_STREAM_DRAW);
638   vtkOpenGLCheckErrorMacro("failed at glBufferData");
639   this->Size = 0;
640 }
641 
642 // ----------------------------------------------------------------------------
643 template <class TPBO, class TCPU>
vtkDownload3D(TPBO * pboPtr,TCPU * cpuPtr,unsigned int dims[3],int numcomps,vtkIdType increments[3])644 void vtkDownload3D(TPBO *pboPtr,
645                    TCPU *cpuPtr,
646                    unsigned int dims[3],
647                    int numcomps,
648                    vtkIdType increments[3])
649 {
650 #ifdef  VTK_PBO_DEBUG
651   cout << "template vtkDownload3D" << endl;
652 #endif
653   vtkIdType tupleSize = static_cast<vtkIdType>(numcomps + increments[0]);
654   for (unsigned int zz=0; zz < dims[2]; zz++)
655   {
656     for (unsigned int yy = 0; yy < dims[1]; yy++)
657     {
658       for (unsigned int xx=0; xx < dims[0]; xx++)
659       {
660         for (int comp=0; comp < numcomps; comp++)
661         {
662           *cpuPtr = static_cast<TCPU>(*pboPtr);
663 //          cout<<"download[zz="<<zz<<"][yy="<<yy<<"][xx="<<xx<<"][comp="<<comp<<"] from pbo="<<(*pboPtr)<<" to cpu="<<(*cpuPtr)<<endl;
664           pboPtr++;
665           cpuPtr++;
666         }
667         cpuPtr += increments[0];
668       }
669       // Reached end of row, go to start of next row.
670       cpuPtr += increments[1]*tupleSize;
671     }
672     cpuPtr += increments[2]*tupleSize;
673   }
674 }
675 
676 // ----------------------------------------------------------------------------
677 template <class OType>
vtkDownload3DSpe(int iType,void * iData,OType odata,unsigned int dims[3],int numcomps,vtkIdType increments[3])678 void vtkDownload3DSpe(int iType,
679                       void *iData,
680                       OType odata,
681                       unsigned int dims[3],
682                       int numcomps,
683                       vtkIdType increments[3])
684 {
685 #ifdef  VTK_PBO_DEBUG
686   cout << "vtkDownload3DSpe" << endl;
687 #endif
688   switch(iType)
689   {
690     vtkTemplateMacro(
691       ::vtkDownload3D(static_cast<VTK_TT*>(iData), odata,
692                       dims, numcomps, increments);
693       );
694     default:
695 #ifdef  VTK_PBO_DEBUG
696       cout << "d nested default." << endl;
697 #endif
698       break;
699   }
700 }
701 
702 //----------------------------------------------------------------------------
Download3D(int type,void * data,unsigned int dims[3],int numcomps,vtkIdType increments[3])703 bool vtkPixelBufferObject::Download3D(
704   int type, void* data,
705   unsigned int dims[3],
706   int numcomps,
707   vtkIdType increments[3])
708 {
709 #ifdef VTK_PBO_TIMING
710   vtkTimerLog *timer=vtkTimerLog::New();
711   timer->StartTimer();
712 #endif
713   assert(this->Context);
714 
715   if (!this->Handle)
716   {
717     vtkErrorMacro("No GPU data available.");
718     return false;
719   }
720 
721   if (this->Size < dims[0]*dims[1]*dims[2]*static_cast<unsigned int>(numcomps))
722   {
723     vtkErrorMacro("Size too small.");
724     return false;
725   }
726 
727   this->Bind(vtkPixelBufferObject::PACKED_BUFFER);
728 
729 
730 #if GL_ES_VERSION_3_0 == 1
731   void* ioMem = glMapBufferRange(this->BufferTarget, 0, this->Size, GL_MAP_READ_BIT);
732 #else
733   void* ioMem = glMapBuffer(this->BufferTarget, GL_READ_ONLY);
734 #endif
735   vtkOpenGLCheckErrorMacro("failed at glMapBuffer");
736 
737   switch (type)
738   {
739     vtkTemplateMacro(
740       VTK_TT* odata = static_cast<VTK_TT*>(data);
741       ::vtkDownload3DSpe(this->Type,ioMem,odata,dims,numcomps,increments);
742       );
743     default:
744       vtkErrorMacro("unsupported vtk type");
745       return false;
746   }
747   glUnmapBuffer(this->BufferTarget);
748   vtkOpenGLCheckErrorMacro("failed at glUnmapBuffer");
749   this->UnBind();
750 
751 #ifdef VTK_PBO_TIMING
752   timer->StopTimer();
753   double time=timer->GetElapsedTime();
754   timer->Delete();
755   cout<<"dowmload data from PBO"<<time<<" seconds."<<endl;
756 #endif
757 
758   return true;
759 }
760 
761 //----------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)762 void vtkPixelBufferObject::PrintSelf(ostream& os, vtkIndent indent)
763 {
764   this->Superclass::PrintSelf(os, indent);
765   os << indent << "Context: " << this->Context << endl;
766   os << indent << "Handle: " << this->Handle << endl;
767   os << indent << "Size: " << this->Size << endl;
768   os << indent << "VTK Type: " << vtkImageScalarTypeNameMacro(this->Type)
769      << endl;
770   os << indent << "Usage:" << BufferObjectUsageAsString[this->Usage] << endl;
771 }
772