1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkOpenGLRenderWindow.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 "vtk_glew.h"
16 #include "vtkOpenGLRenderWindow.h"
17 
18 #include "vtkglVBOHelper.h"
19 
20 #include <cassert>
21 #include "vtkFloatArray.h"
22 #include "vtkNew.h"
23 #include "vtkObjectFactory.h"
24 #include "vtkOpenGLActor.h"
25 #include "vtkOpenGLCamera.h"
26 #include "vtkOpenGLLight.h"
27 #include "vtkOpenGLProperty.h"
28 #include "vtkOpenGLRenderer.h"
29 #include "vtkOpenGLError.h"
30 #include "vtkUnsignedCharArray.h"
31 #include "vtkOpenGLShaderCache.h"
32 #include "vtkStdString.h"
33 #include "vtkTextureObject.h"
34 #include "vtkTextureUnitManager.h"
35 #include "vtkRendererCollection.h"
36 
37 #include <sstream>
38 using std::ostringstream;
39 
40 vtkCxxSetObjectMacro(vtkOpenGLRenderWindow, TextureUnitManager, vtkTextureUnitManager);
41 
42 // Initialize static member that controls global maximum number of multisamples
43 // (off by default on Apple because it causes problems on some Mac models).
44 #if defined(__APPLE__)
45 static int vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = 0;
46 #else
47 static int vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = 8;
48 #endif
49 
50 // ----------------------------------------------------------------------------
SetGlobalMaximumNumberOfMultiSamples(int val)51 void vtkOpenGLRenderWindow::SetGlobalMaximumNumberOfMultiSamples(int val)
52 {
53   if (val == vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples)
54     {
55     return;
56     }
57   vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples = val;
58 }
59 
60 // ----------------------------------------------------------------------------
GetGlobalMaximumNumberOfMultiSamples()61 int vtkOpenGLRenderWindow::GetGlobalMaximumNumberOfMultiSamples()
62 {
63   return vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples;
64 }
65 
66 // used for OpenGL32 Support
67 static bool vtkOpenGLRenderWindowContextSupportsOpenGL32 = false;
68 
GetContextSupportsOpenGL32()69 bool vtkOpenGLRenderWindow::GetContextSupportsOpenGL32()
70 {
71   return vtkOpenGLRenderWindowContextSupportsOpenGL32;
72 }
73 
74 // ----------------------------------------------------------------------------
SetContextSupportsOpenGL32(bool val)75 void vtkOpenGLRenderWindow::SetContextSupportsOpenGL32(bool val)
76 {
77   if (val == vtkOpenGLRenderWindowContextSupportsOpenGL32)
78     {
79     return;
80     }
81   vtkOpenGLRenderWindowContextSupportsOpenGL32 = val;
82 }
83 
84 
85 // ----------------------------------------------------------------------------
vtkOpenGLRenderWindow()86 vtkOpenGLRenderWindow::vtkOpenGLRenderWindow()
87 {
88   this->Initialized = false;
89 
90   this->ShaderCache = vtkOpenGLShaderCache::New();
91 
92   this->TextureUnitManager=0;
93 
94   this->MultiSamples = vtkOpenGLRenderWindowGlobalMaximumNumberOfMultiSamples;
95   delete [] this->WindowName;
96   this->WindowName = new char[strlen("Visualization Toolkit - OpenGL")+1];
97   strcpy( this->WindowName, "Visualization Toolkit - OpenGL" );
98 
99   this->OffScreenUseFrameBuffer=0;
100 
101   this->BackLeftBuffer=static_cast<unsigned int>(GL_BACK_LEFT);
102   this->BackRightBuffer=static_cast<unsigned int>(GL_BACK_RIGHT);
103   this->FrontLeftBuffer=static_cast<unsigned int>(GL_FRONT_LEFT);
104   this->FrontRightBuffer=static_cast<unsigned int>(GL_FRONT_RIGHT);
105   this->BackBuffer=static_cast<unsigned int>(GL_BACK);
106   this->FrontBuffer=static_cast<unsigned int>(GL_FRONT);
107 
108   #ifndef VTK_LEGACY_REMOVE
109   this->LastGraphicError=static_cast<unsigned int>(GL_NO_ERROR);
110   #endif
111 
112   this->DrawPixelsTextureObject = NULL;
113 
114   this->OwnContext=1;
115 }
116 
117 // free up memory & close the window
118 // ----------------------------------------------------------------------------
~vtkOpenGLRenderWindow()119 vtkOpenGLRenderWindow::~vtkOpenGLRenderWindow()
120 {
121   if(this->DrawPixelsTextureObject != 0)
122     {
123     this->DrawPixelsTextureObject->UnRegister(this);
124     this->DrawPixelsTextureObject = NULL;
125     }
126   this->TextureResourceIds.clear();
127   if(this->TextureUnitManager!=0)
128     {
129     this->TextureUnitManager->SetContext(0);
130     }
131 
132   this->SetTextureUnitManager(0);
133   this->ShaderCache->UnRegister(this);
134 }
135 
ReleaseGraphicsResources()136 void vtkOpenGLRenderWindow::ReleaseGraphicsResources()
137 {
138   vtkCollectionSimpleIterator rsit;
139   this->Renderers->InitTraversal(rsit);
140   vtkRenderer *aren;
141   while ( (aren = this->Renderers->GetNextRenderer(rsit)) )
142     {
143     if (aren->GetRenderWindow() == this)
144       {
145       aren->ReleaseGraphicsResources(this);
146       }
147     }
148 
149   if(this->DrawPixelsTextureObject != 0)
150      {
151      this->DrawPixelsTextureObject->ReleaseGraphicsResources(this);
152      }
153 
154   this->ShaderCache->ReleaseGraphicsResources(this);
155 
156   if (this->TextureResourceIds.size())
157     {
158     vtkErrorMacro("There are still active textures when there should not be.");
159     typedef std::map<const vtkTextureObject *, int>::const_iterator TRIter;
160     TRIter found = this->TextureResourceIds.begin();
161     for ( ; found != this->TextureResourceIds.end(); found++)
162       {
163       vtkErrorMacro("Leaked for texture object: " << const_cast<vtkTextureObject *>(found->first));
164       }
165     }
166 }
167 
168 
169 // ----------------------------------------------------------------------------
GetContextCreationTime()170 unsigned long vtkOpenGLRenderWindow::GetContextCreationTime()
171 {
172   return this->ContextCreationTime.GetMTime();
173 }
174 
175 // ----------------------------------------------------------------------------
176 // Description:
177 // Return the OpenGL name of the back left buffer.
178 // It is GL_BACK_LEFT if GL is bound to the window-system-provided
179 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT if GL is bound to an
180 // application-created framebuffer object (GPU-based offscreen rendering)
181 // It is used by vtkOpenGLCamera.
GetBackLeftBuffer()182 unsigned int vtkOpenGLRenderWindow::GetBackLeftBuffer()
183 {
184   return this->BackLeftBuffer;
185 }
186 
187 // ----------------------------------------------------------------------------
188 // Description:
189 // Return the OpenGL name of the back right buffer.
190 // It is GL_BACK_RIGHT if GL is bound to the window-system-provided
191 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT+1 if GL is bound to an
192 // application-created framebuffer object (GPU-based offscreen rendering)
193 // It is used by vtkOpenGLCamera.
GetBackRightBuffer()194 unsigned int vtkOpenGLRenderWindow::GetBackRightBuffer()
195 {
196   return this->BackRightBuffer;
197 }
198 
199 // ----------------------------------------------------------------------------
200 // Description:
201 // Return the OpenGL name of the front left buffer.
202 // It is GL_FRONT_LEFT if GL is bound to the window-system-provided
203 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT if GL is bound to an
204 // application-created framebuffer object (GPU-based offscreen rendering)
205 // It is used by vtkOpenGLCamera.
GetFrontLeftBuffer()206 unsigned int vtkOpenGLRenderWindow::GetFrontLeftBuffer()
207 {
208   return this->FrontLeftBuffer;
209 }
210 
211 // ----------------------------------------------------------------------------
212 // Description:
213 // Return the OpenGL name of the front right buffer.
214 // It is GL_FRONT_RIGHT if GL is bound to the window-system-provided
215 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT+1 if GL is bound to an
216 // application-created framebuffer object (GPU-based offscreen rendering)
217 // It is used by vtkOpenGLCamera.
GetFrontRightBuffer()218 unsigned int vtkOpenGLRenderWindow::GetFrontRightBuffer()
219 {
220   return this->FrontRightBuffer;
221 }
222 
223 // ----------------------------------------------------------------------------
224 // Description:
225 // Return the OpenGL name of the back left buffer.
226 // It is GL_BACK if GL is bound to the window-system-provided
227 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT if GL is bound to an
228 // application-created framebuffer object (GPU-based offscreen rendering)
229 // It is used by vtkOpenGLCamera.
GetBackBuffer()230 unsigned int vtkOpenGLRenderWindow::GetBackBuffer()
231 {
232   return this->BackBuffer;
233 }
234 
235 // ----------------------------------------------------------------------------
236 // Description:
237 // Return the OpenGL name of the front left buffer.
238 // It is GL_FRONT if GL is bound to the window-system-provided
239 // framebuffer. It is GL_COLOR_ATTACHMENT0_EXT if GL is bound to an
240 // application-created framebuffer object (GPU-based offscreen rendering)
241 // It is used by vtkOpenGLCamera.
GetFrontBuffer()242 unsigned int vtkOpenGLRenderWindow::GetFrontBuffer()
243 {
244   return this->FrontBuffer;
245 }
246 
247 // Update system if needed due to stereo rendering.
StereoUpdate(void)248 void vtkOpenGLRenderWindow::StereoUpdate(void)
249 {
250   // if stereo is on and it wasn't before
251   if (this->StereoRender && (!this->StereoStatus))
252     {
253     switch (this->StereoType)
254       {
255       case VTK_STEREO_CRYSTAL_EYES:
256         // not clear this is supposed to be empty,
257         // but it has been that way forever.
258         break;
259       case VTK_STEREO_RED_BLUE:
260         this->StereoStatus = 1;
261         break;
262       case VTK_STEREO_ANAGLYPH:
263         this->StereoStatus = 1;
264         break;
265       case VTK_STEREO_DRESDEN:
266         this->StereoStatus = 1;
267         break;
268       case VTK_STEREO_INTERLACED:
269         this->StereoStatus = 1;
270         break;
271       case VTK_STEREO_CHECKERBOARD:
272         this->StereoStatus = 1;
273         break;
274       case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
275         this->StereoStatus = 1;
276         break;
277       }
278     }
279   else if ((!this->StereoRender) && this->StereoStatus)
280     {
281     switch (this->StereoType)
282       {
283       case VTK_STEREO_CRYSTAL_EYES:
284         this->StereoStatus = 0;
285         break;
286       case VTK_STEREO_RED_BLUE:
287         this->StereoStatus = 0;
288         break;
289       case VTK_STEREO_ANAGLYPH:
290         this->StereoStatus = 0;
291         break;
292       case VTK_STEREO_DRESDEN:
293         this->StereoStatus = 0;
294         break;
295       case VTK_STEREO_INTERLACED:
296         this->StereoStatus = 0;
297         break;
298       case VTK_STEREO_CHECKERBOARD:
299         this->StereoStatus = 0;
300         break;
301       case VTK_STEREO_SPLITVIEWPORT_HORIZONTAL:
302         this->StereoStatus = 0;
303         break;
304       }
305     }
306 }
307 
308 #ifndef VTK_LEGACY_REMOVE
309 //----------------------------------------------------------------------------
CheckGraphicError()310 void vtkOpenGLRenderWindow::CheckGraphicError()
311 {
312   VTK_LEGACY_BODY(vtkRenderWindow::CheckGraphicError, "VTK 6.1");
313   this->LastGraphicError=static_cast<unsigned int>(glGetError());
314 }
315 
316 //----------------------------------------------------------------------------
HasGraphicError()317 int vtkOpenGLRenderWindow::HasGraphicError()
318 {
319   VTK_LEGACY_BODY(vtkRenderWindow::HasGraphics, "VTK 6.1");
320   return static_cast<GLenum>(this->LastGraphicError)!=GL_NO_ERROR;
321 }
322 
323 //----------------------------------------------------------------------------
GetLastGraphicErrorString()324 const char *vtkOpenGLRenderWindow::GetLastGraphicErrorString()
325 {
326   VTK_LEGACY_BODY(vtkRenderWindow::GetLastGraphicErrorString, "VTK 6.1");
327   const char *result="Unknown error";
328   return result;
329 }
330 #endif
331 
332 
OpenGLInit()333 void vtkOpenGLRenderWindow::OpenGLInit()
334 {
335   OpenGLInitContext();
336   OpenGLInitState();
337 }
338 
OpenGLInitState()339 void vtkOpenGLRenderWindow::OpenGLInitState()
340 {
341   glDepthFunc( GL_LEQUAL );
342   glEnable( GL_DEPTH_TEST );
343 
344   // initialize blending for transparency
345   if(glBlendFuncSeparate != 0)
346     {
347     glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
348                              GL_ONE,GL_ONE_MINUS_SRC_ALPHA);
349     }
350   else
351     {
352     glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
353     }
354   glEnable(GL_BLEND);
355 
356   if (this->PointSmoothing)
357     {
358 #ifdef GL_POINT_SMOOTH
359     glEnable(GL_POINT_SMOOTH);
360 #endif
361     }
362   else
363     {
364 #ifdef GL_POINT_SMOOTH
365     glDisable(GL_POINT_SMOOTH);
366 #endif
367     }
368 
369   if (this->LineSmoothing)
370     {
371 #ifdef GL_LINE_SMOOTH
372     glEnable(GL_LINE_SMOOTH);
373 #endif
374     }
375   else
376     {
377 #ifdef GL_LINE_SMOOTH
378     glDisable(GL_LINE_SMOOTH);
379 #endif
380     }
381 
382   if (this->PolygonSmoothing)
383     {
384 #ifdef GL_POLYGON_SMOOTH
385     glEnable(GL_POLYGON_SMOOTH);
386 #endif
387     }
388   else
389     {
390 #ifdef GL_POLYGON_SMOOTH
391     glDisable(GL_POLYGON_SMOOTH);
392 #endif
393     }
394 
395   // Default OpenGL is 4 bytes but it is only safe with RGBA format.
396   // If format is RGB, row alignment is 4 bytes only if the width is divisible
397   // by 4. Let's do it the safe way: 1-byte alignment.
398   // If an algorithm really need 4 bytes alignment, it should set it itself,
399   // this is the recommended way in "Avoiding 16 Common OpenGL Pitfalls",
400   // section 7:
401   // http://www.opengl.org/resources/features/KilgardTechniques/oglpitfall/
402 #ifdef GL_UNPACK_ALIGNMENT
403   glPixelStorei(GL_UNPACK_ALIGNMENT,1);
404 #endif
405   glPixelStorei(GL_PACK_ALIGNMENT,1);
406   // Set the number of alpha bit planes used by the window
407   int rgba[4];
408   this->GetColorBufferSizes(rgba);
409   this->SetAlphaBitPlanes(rgba[3]);
410 }
411 
OpenGLInitContext()412 void vtkOpenGLRenderWindow::OpenGLInitContext()
413 {
414   this->ContextCreationTime.Modified();
415 
416   // When a new OpenGL context is created, force an update
417   if (!this->Initialized)
418     {
419 #ifdef GLEW_OK
420     GLenum result = glewInit();
421     bool m_valid = (result == GLEW_OK);
422     if (!m_valid)
423       {
424       vtkErrorMacro("GLEW could not be initialized.");
425       return;
426       }
427 
428     if (!GLEW_VERSION_2_1)
429       {
430       vtkErrorMacro("GL version 2.1 is not supported by your graphics driver.");
431       //m_valid = false;
432       return;
433       }
434 #endif
435     this->Initialized = true;
436     }
437 }
438 
PrintSelf(ostream & os,vtkIndent indent)439 void vtkOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
440 {
441   this->Superclass::PrintSelf(os,indent);
442 }
443 
GetDepthBufferSize()444 int vtkOpenGLRenderWindow::GetDepthBufferSize()
445 {
446   GLint size;
447 
448   if ( this->Mapped )
449     {
450     this->MakeCurrent();
451     size = 0;
452     glGetIntegerv( GL_DEPTH_BITS, &size );
453     return static_cast<int>(size);
454     }
455   else
456     {
457     vtkDebugMacro(<< "Window is not mapped yet!" );
458     return 24;
459     }
460 }
461 
GetColorBufferSizes(int * rgba)462 int vtkOpenGLRenderWindow::GetColorBufferSizes(int *rgba)
463 {
464   GLint size;
465 
466   if (rgba==NULL)
467     {
468     return 0;
469     }
470   rgba[0] = 0;
471   rgba[1] = 0;
472   rgba[2] = 0;
473   rgba[3] = 0;
474 
475   if ( this->Mapped)
476     {
477     this->MakeCurrent();
478     glGetIntegerv( GL_RED_BITS, &size );
479     rgba[0] = static_cast<int>(size);
480     glGetIntegerv( GL_GREEN_BITS, &size  );
481     rgba[1] = static_cast<int>(size);
482     glGetIntegerv( GL_BLUE_BITS, &size );
483     rgba[2] = static_cast<int>(size);
484     glGetIntegerv( GL_ALPHA_BITS, &size );
485     rgba[3] = static_cast<int>(size);
486     return rgba[0]+rgba[1]+rgba[2]+rgba[3];
487     }
488   else
489     {
490     vtkDebugMacro(<< "Window is not mapped yet!" );
491     rgba[0] = 8;
492     rgba[1] = 8;
493     rgba[2] = 8;
494     rgba[3] = 8;
495     return 32;
496     }
497 }
498 
GetPixelData(int x1,int y1,int x2,int y2,int front)499 unsigned char* vtkOpenGLRenderWindow::GetPixelData(int x1, int y1,
500                                                    int x2, int y2,
501                                                    int front)
502 {
503   int     y_low, y_hi;
504   int     x_low, x_hi;
505 
506   if (y1 < y2)
507     {
508     y_low = y1;
509     y_hi  = y2;
510     }
511   else
512     {
513     y_low = y2;
514     y_hi  = y1;
515     }
516 
517   if (x1 < x2)
518     {
519     x_low = x1;
520     x_hi  = x2;
521     }
522   else
523     {
524     x_low = x2;
525     x_hi  = x1;
526     }
527 
528   unsigned char *data =
529     new unsigned char[(x_hi - x_low + 1)*(y_hi - y_low + 1)*3];
530   this->GetPixelData(x1, y1, x2, y2, front, data);
531   return data;
532 }
533 
GetPixelData(int x1,int y1,int x2,int y2,int front,vtkUnsignedCharArray * data)534 int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1,
535                                         int x2, int y2,
536                                         int front,
537                                         vtkUnsignedCharArray* data)
538 {
539   int     y_low, y_hi;
540   int     x_low, x_hi;
541 
542   if (y1 < y2)
543     {
544     y_low = y1;
545     y_hi  = y2;
546     }
547   else
548     {
549     y_low = y2;
550     y_hi  = y1;
551     }
552 
553   if (x1 < x2)
554     {
555     x_low = x1;
556     x_hi  = x2;
557     }
558   else
559     {
560     x_low = x2;
561     x_hi  = x1;
562     }
563 
564   int width  = abs(x_hi - x_low) + 1;
565   int height = abs(y_hi - y_low) + 1;
566   int size = 3*width*height;
567 
568   if ( data->GetMaxId()+1 != size)
569     {
570     vtkDebugMacro("Resizing array.");
571     data->SetNumberOfComponents(3);
572     data->SetNumberOfValues(size);
573     }
574   return this->GetPixelData(x1, y1, x2, y2, front, data->GetPointer(0));
575 
576 }
577 
GetPixelData(int x1,int y1,int x2,int y2,int front,unsigned char * data)578 int vtkOpenGLRenderWindow::GetPixelData(int x1, int y1,
579                                         int x2, int y2,
580                                         int front, unsigned char* data)
581 {
582   int     y_low, y_hi;
583   int     x_low, x_hi;
584 
585   // set the current window
586   this->MakeCurrent();
587 
588   if (y1 < y2)
589     {
590     y_low = y1;
591     y_hi  = y2;
592     }
593   else
594     {
595     y_low = y2;
596     y_hi  = y1;
597     }
598 
599   if (x1 < x2)
600     {
601     x_low = x1;
602     x_hi  = x2;
603     }
604   else
605     {
606     x_low = x2;
607     x_hi  = x1;
608     }
609 
610   // Must clear previous errors first.
611   while(glGetError() != GL_NO_ERROR)
612     {
613     ;
614     }
615 
616   if (front)
617     {
618     glReadBuffer(static_cast<GLenum>(this->GetFrontLeftBuffer()));
619     }
620   else
621     {
622     glReadBuffer(static_cast<GLenum>(this->GetBackLeftBuffer()));
623     }
624 
625   glDisable( GL_SCISSOR_TEST );
626 
627   // Calling pack alignment ensures that we can grab the any size window
628   glPixelStorei( GL_PACK_ALIGNMENT, 1 );
629   glReadPixels(x_low, y_low, x_hi-x_low+1, y_hi-y_low+1, GL_RGB,
630                GL_UNSIGNED_BYTE, data);
631 
632   if (glGetError() != GL_NO_ERROR)
633     {
634     return VTK_ERROR;
635     }
636   else
637     {
638     return VTK_OK;
639     }
640 
641 }
642 
SetPixelData(int x1,int y1,int x2,int y2,vtkUnsignedCharArray * data,int front)643 int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2,
644                                         vtkUnsignedCharArray *data, int front)
645 {
646   int     y_low, y_hi;
647   int     x_low, x_hi;
648 
649   if (y1 < y2)
650     {
651 
652     y_low = y1;
653     y_hi  = y2;
654     }
655   else
656     {
657     y_low = y2;
658     y_hi  = y1;
659     }
660 
661   if (x1 < x2)
662     {
663     x_low = x1;
664     x_hi  = x2;
665     }
666   else
667     {
668     x_low = x2;
669     x_hi  = x1;
670     }
671 
672   int width  = abs(x_hi - x_low) + 1;
673   int height = abs(y_hi - y_low) + 1;
674   int size = 3*width*height;
675 
676   if ( data->GetMaxId()+1 != size)
677     {
678     vtkErrorMacro("Buffer is of wrong size.");
679     return VTK_ERROR;
680     }
681   return this->SetPixelData(x1, y1, x2, y2, data->GetPointer(0), front);
682 
683 }
684 
685 
686 // ---------------------------------------------------------------------------
687 // a program must be bound
688 // a VAO must be bound
RenderQuad(float * verts,float * tcoords,vtkShaderProgram * program,vtkgl::VertexArrayObject * vao)689 void vtkOpenGLRenderWindow::RenderQuad(
690   float *verts,
691   float *tcoords,
692   vtkShaderProgram *program, vtkgl::VertexArrayObject *vao)
693 {
694   if (!program || !vao || !verts)
695     {
696     vtkGenericWarningMacro(<< "Error must have verts, program and vao");
697     }
698 
699   vtkgl::BufferObject vbo;
700   vbo.Upload(verts, 12, vtkgl::BufferObject::ArrayBuffer);
701   vao->Bind();
702   if (!vao->AddAttributeArray(program, vbo, "vertexMC", 0, sizeof(float)*3, VTK_FLOAT, 3, false))
703     {
704     vtkGenericWarningMacro(<< "Error setting 'vertexMC' in shader VAO.");
705     }
706 
707   vtkgl::BufferObject tvbo;
708   if (tcoords)
709     {
710     tvbo.Upload(tcoords, 8, vtkgl::BufferObject::ArrayBuffer);
711     if (!vao->AddAttributeArray(program, tvbo, "tcoordMC", 0, sizeof(float)*2, VTK_FLOAT, 2, false))
712       {
713       vtkGenericWarningMacro(<< "Error setting 'tcoordMC' in shader VAO.");
714       }
715     }
716 
717   GLuint iboData[] = {0, 1, 2, 0, 2, 3};
718   vtkgl::BufferObject ibo;
719   vao->Bind();
720   ibo.Upload(iboData, 6, vtkgl::BufferObject::ElementArrayBuffer);
721   glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
722     reinterpret_cast<const GLvoid *>(NULL));
723   ibo.Release();
724   vao->Release();
725   vao->RemoveAttributeArray("vertexMC");
726   vao->RemoveAttributeArray("tcoordMC");
727   vbo.Release();
728   if (tcoords)
729     {
730     tvbo.Release();
731     }
732 }
733 
734 
735 // draw (and stretch as needed) the data to the current viewport
DrawPixels(int srcWidth,int srcHeight,int numComponents,int dataType,void * data)736 void vtkOpenGLRenderWindow::DrawPixels(
737   int srcWidth, int srcHeight, int numComponents, int dataType, void *data)
738 {
739   glDisable( GL_SCISSOR_TEST );
740   if (!this->DrawPixelsTextureObject)
741     {
742     this->DrawPixelsTextureObject = vtkTextureObject::New();
743     }
744   this->DrawPixelsTextureObject->SetContext(this);
745   this->DrawPixelsTextureObject->Create2DFromRaw(srcWidth, srcHeight,
746         numComponents, dataType, data);
747   this->DrawPixelsTextureObject->CopyToFrameBuffer(NULL, NULL);
748 
749   // This seems to be necessary for the image to show up
750   glFlush();
751 }
752 
753 // very generic call to draw pixel data to a region of the window
DrawPixels(int dstXmin,int dstYmin,int dstXmax,int dstYmax,int srcXmin,int srcYmin,int srcXmax,int srcYmax,int srcWidth,int srcHeight,int numComponents,int dataType,void * data)754 void vtkOpenGLRenderWindow::DrawPixels(
755   int dstXmin, int dstYmin, int dstXmax, int dstYmax,
756   int srcXmin, int srcYmin, int srcXmax, int srcYmax,
757   int srcWidth, int srcHeight, int numComponents, int dataType, void *data)
758 {
759   glDisable( GL_SCISSOR_TEST );
760   if (!this->DrawPixelsTextureObject)
761     {
762     this->DrawPixelsTextureObject = vtkTextureObject::New();
763     }
764   this->DrawPixelsTextureObject->SetContext(this);
765   this->DrawPixelsTextureObject->Create2DFromRaw(srcWidth, srcHeight,
766         numComponents, dataType, data);
767   this->DrawPixelsTextureObject->CopyToFrameBuffer(
768       srcXmin, srcYmin, srcXmax, srcYmax-1,
769       dstXmin, dstYmin, dstXmax, dstYmax,
770       this->GetSize()[0], this->GetSize()[1],
771       NULL, NULL);
772 
773   // This seems to be necessary for the image to show up
774   glFlush();
775 }
776 
777 // less generic verison, old API
DrawPixels(int x1,int y1,int x2,int y2,int numComponents,int dataType,void * data)778 void vtkOpenGLRenderWindow::DrawPixels(int x1, int y1, int x2, int y2, int numComponents, int dataType, void *data)
779 {
780   int     y_low, y_hi;
781   int     x_low, x_hi;
782 
783   if (y1 < y2)
784     {
785     y_low = y1;
786     y_hi  = y2;
787     }
788   else
789     {
790     y_low = y2;
791     y_hi  = y1;
792     }
793 
794   if (x1 < x2)
795     {
796     x_low = x1;
797     x_hi  = x2;
798     }
799   else
800     {
801     x_low = x2;
802     x_hi  = x1;
803     }
804 
805   int width = x_hi-x_low+1;
806   int height = y_hi-y_low+1;
807 
808   // call the more generic version
809   this->DrawPixels(x_low, y_low, x_hi, y_hi,
810     0, 0, width-1, height-1, width, height, numComponents, dataType, data);
811 }
812 
SetPixelData(int x1,int y1,int x2,int y2,unsigned char * data,int front)813 int vtkOpenGLRenderWindow::SetPixelData(int x1, int y1, int x2, int y2,
814                                         unsigned char *data, int front)
815 {
816   // set the current window
817   this->MakeCurrent();
818 
819   // Error checking
820   // Must clear previous errors first.
821   while(glGetError() != GL_NO_ERROR)
822     {
823     ;
824     }
825 
826   GLint buffer;
827 
828 #ifdef GL_DRAW_BUFFER
829   glGetIntegerv(GL_DRAW_BUFFER, &buffer);
830 #endif
831 
832   if (front)
833     {
834     glDrawBuffer(this->GetFrontBuffer());
835     }
836   else
837     {
838     glDrawBuffer(this->GetBackBuffer());
839     }
840 
841   this->DrawPixels(x1, y1, x2, y2, 3, VTK_UNSIGNED_CHAR, data);
842 
843   glDrawBuffer(buffer);
844 
845   if (glGetError() != GL_NO_ERROR)
846     {
847     return VTK_ERROR;
848     }
849   else
850     {
851     return VTK_OK;
852     }
853 }
854 
GetRGBAPixelData(int x1,int y1,int x2,int y2,int front)855 float* vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2,
856                                                int front)
857 {
858 
859   int     y_low, y_hi;
860   int     x_low, x_hi;
861   int     width, height;
862 
863   if (y1 < y2)
864     {
865     y_low = y1;
866     y_hi  = y2;
867     }
868   else
869     {
870     y_low = y2;
871     y_hi  = y1;
872     }
873 
874   if (x1 < x2)
875     {
876     x_low = x1;
877     x_hi  = x2;
878     }
879   else
880     {
881     x_low = x2;
882     x_hi  = x1;
883     }
884 
885   width  = abs(x_hi - x_low) + 1;
886   height = abs(y_hi - y_low) + 1;
887 
888   float *data = new float[ (width*height*4) ];
889   this->GetRGBAPixelData(x1, y1, x2, y2, front, data);
890 
891   return data;
892 
893 }
894 
GetRGBAPixelData(int x1,int y1,int x2,int y2,int front,vtkFloatArray * data)895 int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2,
896                                             int front, vtkFloatArray* data)
897 {
898   int     y_low, y_hi;
899   int     x_low, x_hi;
900   int     width, height;
901 
902   if (y1 < y2)
903     {
904     y_low = y1;
905     y_hi  = y2;
906     }
907   else
908     {
909     y_low = y2;
910     y_hi  = y1;
911     }
912 
913   if (x1 < x2)
914     {
915     x_low = x1;
916     x_hi  = x2;
917     }
918   else
919     {
920     x_low = x2;
921     x_hi  = x1;
922     }
923 
924   width  = abs(x_hi - x_low) + 1;
925   height = abs(y_hi - y_low) + 1;
926 
927   int size = 4*width*height;
928 
929   if ( data->GetMaxId()+1 != size)
930     {
931     vtkDebugMacro("Resizing array.");
932     data->SetNumberOfComponents(4);
933     data->SetNumberOfValues(size);
934     }
935   return this->GetRGBAPixelData(x1, y1, x2, y2, front, data->GetPointer(0));
936 
937 }
938 
GetRGBAPixelData(int x1,int y1,int x2,int y2,int front,float * data)939 int vtkOpenGLRenderWindow::GetRGBAPixelData(int x1, int y1, int x2, int y2,
940                                             int front, float* data)
941 {
942   int     y_low, y_hi;
943   int     x_low, x_hi;
944   int     width, height;
945 
946   // set the current window
947   this->MakeCurrent();
948 
949   if (y1 < y2)
950     {
951     y_low = y1;
952     y_hi  = y2;
953     }
954   else
955     {
956     y_low = y2;
957     y_hi  = y1;
958     }
959 
960   if (x1 < x2)
961     {
962     x_low = x1;
963     x_hi  = x2;
964     }
965   else
966     {
967     x_low = x2;
968     x_hi  = x1;
969     }
970 
971   // Error checking
972   // Must clear previous errors first.
973   while(glGetError() != GL_NO_ERROR)
974     {
975     ;
976     }
977 
978   if (front)
979     {
980     glReadBuffer(static_cast<GLenum>(this->GetFrontLeftBuffer()));
981     }
982   else
983     {
984     glReadBuffer(static_cast<GLenum>(this->GetBackLeftBuffer()));
985     }
986 
987   width  = abs(x_hi - x_low) + 1;
988   height = abs(y_hi - y_low) + 1;
989 
990 
991   // Turn of texturing in case it is on - some drivers have a problem
992   // getting / setting pixels with texturing enabled.
993   glDisable( GL_TEXTURE_2D );
994 
995   glPixelStorei( GL_PACK_ALIGNMENT, 1 );
996   glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_FLOAT, data);
997 
998   if (glGetError() != GL_NO_ERROR)
999     {
1000     return VTK_ERROR;
1001     }
1002   else
1003     {
1004     return VTK_OK;
1005     }
1006 }
1007 
ReleaseRGBAPixelData(float * data)1008 void vtkOpenGLRenderWindow::ReleaseRGBAPixelData(float *data)
1009 {
1010   delete[] data;
1011 }
1012 
SetRGBAPixelData(int x1,int y1,int x2,int y2,vtkFloatArray * data,int front,int blend)1013 int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2,
1014                                             vtkFloatArray *data, int front,
1015                                             int blend)
1016 {
1017   int     y_low, y_hi;
1018   int     x_low, x_hi;
1019   int     width, height;
1020 
1021   if (y1 < y2)
1022     {
1023     y_low = y1;
1024     y_hi  = y2;
1025     }
1026   else
1027     {
1028     y_low = y2;
1029     y_hi  = y1;
1030     }
1031 
1032   if (x1 < x2)
1033     {
1034     x_low = x1;
1035     x_hi  = x2;
1036     }
1037   else
1038     {
1039     x_low = x2;
1040     x_hi  = x1;
1041     }
1042 
1043   width  = abs(x_hi-x_low) + 1;
1044   height = abs(y_hi-y_low) + 1;
1045 
1046   int size = 4*width*height;
1047   if ( data->GetMaxId()+1 != size )
1048     {
1049     vtkErrorMacro("Buffer is of wrong size.");
1050     return VTK_ERROR;
1051     }
1052 
1053   return this->SetRGBAPixelData(x1, y1, x2, y2, data->GetPointer(0), front,
1054                                 blend);
1055 }
1056 
SetRGBAPixelData(int x1,int y1,int x2,int y2,float * data,int front,int blend)1057 int vtkOpenGLRenderWindow::SetRGBAPixelData(int x1, int y1, int x2, int y2,
1058                                             float *data, int front, int blend)
1059 {
1060   // set the current window
1061   this->MakeCurrent();
1062 
1063   // Error checking
1064   // Must clear previous errors first.
1065   while(glGetError() != GL_NO_ERROR)
1066     {
1067     ;
1068     }
1069 
1070   GLint buffer;
1071 #ifdef GL_DRAW_BUFFER
1072   glGetIntegerv(GL_DRAW_BUFFER, &buffer);
1073 #endif
1074 
1075   if (front)
1076     {
1077     glDrawBuffer(this->GetFrontBuffer());
1078     }
1079   else
1080     {
1081     glDrawBuffer(this->GetBackBuffer());
1082     }
1083 
1084   if (!blend)
1085     {
1086     glDisable(GL_BLEND);
1087     this->DrawPixels(x1, y1, x2, y2, 4, VTK_FLOAT, data); // TODO replace dprecated function
1088     glEnable(GL_BLEND);
1089     }
1090   else
1091     {
1092     this->DrawPixels(x1, y1, x2, y2, 4, VTK_FLOAT, data);
1093     }
1094 
1095   glDrawBuffer(buffer);
1096 
1097   if (glGetError() != GL_NO_ERROR)
1098     {
1099     return VTK_ERROR;
1100     }
1101   else
1102     {
1103     return VTK_OK;
1104     }
1105 }
1106 
GetRGBACharPixelData(int x1,int y1,int x2,int y2,int front)1107 unsigned char *vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1,
1108                                                            int x2, int y2,
1109                                                            int front)
1110 {
1111   int     y_low, y_hi;
1112   int     x_low, x_hi;
1113   int     width, height;
1114 
1115   if (y1 < y2)
1116     {
1117     y_low = y1;
1118     y_hi  = y2;
1119     }
1120   else
1121     {
1122     y_low = y2;
1123     y_hi  = y1;
1124     }
1125 
1126 
1127   if (x1 < x2)
1128     {
1129     x_low = x1;
1130     x_hi  = x2;
1131     }
1132   else
1133     {
1134     x_low = x2;
1135     x_hi  = x1;
1136     }
1137 
1138   width  = abs(x_hi - x_low) + 1;
1139   height = abs(y_hi - y_low) + 1;
1140 
1141   unsigned char *data = new unsigned char[ (width*height)*4 ];
1142   this->GetRGBACharPixelData(x1, y1, x2, y2, front, data);
1143 
1144   return data;
1145 }
1146 
GetRGBACharPixelData(int x1,int y1,int x2,int y2,int front,vtkUnsignedCharArray * data)1147 int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1,
1148                                                 int x2, int y2,
1149                                                 int front,
1150                                                 vtkUnsignedCharArray* data)
1151 {
1152   int     y_low, y_hi;
1153   int     x_low, x_hi;
1154 
1155   if (y1 < y2)
1156     {
1157     y_low = y1;
1158     y_hi  = y2;
1159     }
1160   else
1161     {
1162     y_low = y2;
1163     y_hi  = y1;
1164     }
1165 
1166   if (x1 < x2)
1167     {
1168     x_low = x1;
1169     x_hi  = x2;
1170     }
1171   else
1172     {
1173     x_low = x2;
1174     x_hi  = x1;
1175     }
1176 
1177   int width  = abs(x_hi - x_low) + 1;
1178   int height = abs(y_hi - y_low) + 1;
1179   int size = 4*width*height;
1180 
1181   if ( data->GetMaxId()+1 != size)
1182     {
1183     vtkDebugMacro("Resizing array.");
1184     data->SetNumberOfComponents(4);
1185     data->SetNumberOfValues(size);
1186     }
1187   return this->GetRGBACharPixelData(x1, y1, x2, y2, front,
1188                                     data->GetPointer(0));
1189 }
1190 
GetRGBACharPixelData(int x1,int y1,int x2,int y2,int front,unsigned char * data)1191 int vtkOpenGLRenderWindow::GetRGBACharPixelData(int x1, int y1,
1192                                                 int x2, int y2,
1193                                                 int front,
1194                                                 unsigned char* data)
1195 {
1196   int     y_low, y_hi;
1197   int     x_low, x_hi;
1198   int     width, height;
1199 
1200 
1201   // set the current window
1202   this->MakeCurrent();
1203 
1204 
1205   if (y1 < y2)
1206     {
1207     y_low = y1;
1208     y_hi  = y2;
1209     }
1210   else
1211     {
1212     y_low = y2;
1213     y_hi  = y1;
1214     }
1215 
1216 
1217   if (x1 < x2)
1218     {
1219     x_low = x1;
1220     x_hi  = x2;
1221     }
1222   else
1223     {
1224     x_low = x2;
1225     x_hi  = x1;
1226     }
1227 
1228 
1229   // Must clear previous errors first.
1230   while(glGetError() != GL_NO_ERROR)
1231     {
1232     ;
1233     }
1234 
1235   if (front)
1236     {
1237     glReadBuffer(static_cast<GLenum>(this->GetFrontLeftBuffer()));
1238     }
1239   else
1240     {
1241     glReadBuffer(static_cast<GLenum>(this->GetBackLeftBuffer()));
1242     }
1243 
1244   width  = abs(x_hi - x_low) + 1;
1245   height = abs(y_hi - y_low) + 1;
1246 
1247   glDisable( GL_SCISSOR_TEST );
1248 
1249   glReadPixels( x_low, y_low, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1250                 data);
1251 
1252   if (glGetError() != GL_NO_ERROR)
1253     {
1254     return VTK_ERROR;
1255     }
1256   else
1257     {
1258     return VTK_OK;
1259     }
1260 
1261 }
1262 
1263 
SetRGBACharPixelData(int x1,int y1,int x2,int y2,vtkUnsignedCharArray * data,int front,int blend)1264 int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1,int y1,int x2,int y2,
1265                                                 vtkUnsignedCharArray *data,
1266                                                 int front, int blend)
1267 {
1268   int     y_low, y_hi;
1269   int     x_low, x_hi;
1270   int     width, height;
1271 
1272   if (y1 < y2)
1273     {
1274     y_low = y1;
1275     y_hi  = y2;
1276     }
1277   else
1278     {
1279     y_low = y2;
1280     y_hi  = y1;
1281     }
1282 
1283   if (x1 < x2)
1284     {
1285     x_low = x1;
1286     x_hi  = x2;
1287     }
1288   else
1289     {
1290     x_low = x2;
1291     x_hi  = x1;
1292     }
1293 
1294   width  = abs(x_hi-x_low) + 1;
1295   height = abs(y_hi-y_low) + 1;
1296 
1297   int size = 4*width*height;
1298   if ( data->GetMaxId()+1 != size )
1299     {
1300     vtkErrorMacro("Buffer is of wrong size. It is " << data->GetMaxId()+1
1301                   << ", it should be: " << size);
1302     return VTK_ERROR;
1303     }
1304 
1305   return this->SetRGBACharPixelData(x1, y1, x2, y2, data->GetPointer(0),
1306                                     front, blend);
1307 
1308 }
1309 
SetRGBACharPixelData(int x1,int y1,int x2,int y2,unsigned char * data,int front,int blend)1310 int vtkOpenGLRenderWindow::SetRGBACharPixelData(int x1, int y1, int x2,
1311                                                 int y2, unsigned char *data,
1312                                                 int front, int blend)
1313 {
1314   // set the current window
1315   this->MakeCurrent();
1316 
1317 
1318   // Error checking
1319   // Must clear previous errors first.
1320   while(glGetError() != GL_NO_ERROR)
1321     {
1322     ;
1323     }
1324 
1325   GLint buffer;
1326 #ifdef GL_DRAW_BUFFER
1327   glGetIntegerv(GL_DRAW_BUFFER, &buffer);
1328 #endif
1329 
1330   if (front)
1331     {
1332     glDrawBuffer(this->GetFrontBuffer());
1333     }
1334   else
1335     {
1336     glDrawBuffer(this->GetBackBuffer());
1337     }
1338 
1339 
1340   // Disable writing on the z-buffer.
1341   glDepthMask(GL_FALSE);
1342   glDisable(GL_DEPTH_TEST);
1343 
1344   if (!blend)
1345     {
1346     glDisable(GL_BLEND);
1347     this->DrawPixels(x1,y1,x2,y2,4, VTK_UNSIGNED_CHAR, data);
1348     glEnable(GL_BLEND);
1349     }
1350   else
1351     {
1352     this->DrawPixels(x1,y1,x2,y2,4, VTK_UNSIGNED_CHAR, data);
1353     }
1354 
1355   // Renenable writing on the z-buffer.
1356   glDepthMask(GL_TRUE);
1357   glEnable(GL_DEPTH_TEST);
1358 
1359   // This seems to be necessary for the image to show up
1360   glFlush();
1361 
1362   glDrawBuffer(buffer);
1363 
1364   if (glGetError() != GL_NO_ERROR)
1365     {
1366     return VTK_ERROR;
1367     }
1368   else
1369     {
1370     return VTK_OK;
1371     }
1372 }
1373 
1374 
GetZbufferData(int x1,int y1,int x2,int y2,float * z_data)1375 int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2,
1376                                            float* z_data )
1377 {
1378   int             y_low;
1379   int             x_low;
1380   int             width, height;
1381 
1382   // set the current window
1383   this->MakeCurrent();
1384 
1385   if (y1 < y2)
1386     {
1387     y_low = y1;
1388     }
1389   else
1390     {
1391     y_low = y2;
1392     }
1393 
1394   if (x1 < x2)
1395     {
1396     x_low = x1;
1397     }
1398   else
1399     {
1400     x_low = x2;
1401     }
1402 
1403   width =  abs(x2 - x1)+1;
1404   height = abs(y2 - y1)+1;
1405 
1406   // Error checking
1407   // Must clear previous errors first.
1408   while(glGetError() != GL_NO_ERROR)
1409     {
1410     ;
1411     }
1412 
1413   // Turn of texturing in case it is on - some drivers have a problem
1414   // getting / setting pixels with texturing enabled.
1415   glDisable( GL_SCISSOR_TEST );
1416   glPixelStorei( GL_PACK_ALIGNMENT, 1 );
1417 
1418   glReadPixels( x_low, y_low,
1419                 width, height,
1420                 GL_DEPTH_COMPONENT, GL_FLOAT,
1421                 z_data );
1422 
1423   if (glGetError() != GL_NO_ERROR)
1424     {
1425     return VTK_ERROR;
1426     }
1427   else
1428     {
1429     return VTK_OK;
1430     }
1431 }
1432 
GetZbufferData(int x1,int y1,int x2,int y2)1433 float *vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2  )
1434 {
1435   float           *z_data;
1436 
1437   int             width, height;
1438   width =  abs(x2 - x1)+1;
1439   height = abs(y2 - y1)+1;
1440 
1441   z_data = new float[width*height];
1442   this->GetZbufferData(x1, y1, x2, y2, z_data);
1443 
1444   return z_data;
1445 }
1446 
GetZbufferData(int x1,int y1,int x2,int y2,vtkFloatArray * buffer)1447 int vtkOpenGLRenderWindow::GetZbufferData( int x1, int y1, int x2, int y2,
1448                                            vtkFloatArray *buffer )
1449 {
1450   int  width, height;
1451   width =  abs(x2 - x1)+1;
1452   height = abs(y2 - y1)+1;
1453   int size = width*height;
1454   if ( buffer->GetMaxId()+1 != size)
1455     {
1456     vtkDebugMacro("Resizing array.");
1457     buffer->SetNumberOfComponents(1);
1458     buffer->SetNumberOfValues(size);
1459     }
1460   return this->GetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0));
1461 }
1462 
SetZbufferData(int x1,int y1,int x2,int y2,vtkFloatArray * buffer)1463 int vtkOpenGLRenderWindow::SetZbufferData( int x1, int y1, int x2, int y2,
1464                                            vtkFloatArray *buffer )
1465 {
1466   int width, height;
1467   width =  abs(x2 - x1)+1;
1468   height = abs(y2 - y1)+1;
1469   int size = width*height;
1470   if ( buffer->GetMaxId()+1 != size )
1471     {
1472     vtkErrorMacro("Buffer is of wrong size.");
1473     return VTK_ERROR;
1474     }
1475   return this->SetZbufferData(x1, y1, x2, y2, buffer->GetPointer(0));
1476 }
1477 
SetZbufferData(int vtkNotUsed (x1),int vtkNotUsed (y1),int vtkNotUsed (x2),int vtkNotUsed (y2),float * vtkNotUsed (buffer))1478 int vtkOpenGLRenderWindow::SetZbufferData( int vtkNotUsed(x1), int vtkNotUsed(y1),
1479                                            int vtkNotUsed(x2), int vtkNotUsed(y2),
1480                                            float *vtkNotUsed(buffer) )
1481 {
1482   // Todo: not sure this can be done in the new opengl, either implement or remove
1483   return VTK_ERROR;
1484 }
1485 
1486 
ActivateTexture(vtkTextureObject * texture)1487 void vtkOpenGLRenderWindow::ActivateTexture(vtkTextureObject *texture)
1488 {
1489   // Only add if it isn't already there
1490   typedef std::map<const vtkTextureObject *, int>::const_iterator TRIter;
1491   TRIter found = this->TextureResourceIds.find(texture);
1492   if (found == this->TextureResourceIds.end())
1493     {
1494     int activeUnit =  this->GetTextureUnitManager()->Allocate();
1495     if (activeUnit < 0)
1496       {
1497       vtkErrorMacro("Hardware does not support the number of textures defined.");
1498       return;
1499       }
1500     this->TextureResourceIds.insert(std::make_pair(texture, activeUnit));
1501     glActiveTexture(GL_TEXTURE0 + activeUnit);
1502     }
1503   else
1504     {
1505     glActiveTexture(GL_TEXTURE0 + found->second);
1506     }
1507 }
1508 
DeactivateTexture(vtkTextureObject * texture)1509 void vtkOpenGLRenderWindow::DeactivateTexture(vtkTextureObject *texture)
1510 {
1511   // Only deactivate if it isn't already there
1512   typedef std::map<const vtkTextureObject *, int>::iterator TRIter;
1513   TRIter found = this->TextureResourceIds.find(texture);
1514   if (found != this->TextureResourceIds.end())
1515     {
1516     this->GetTextureUnitManager()->Free(found->second);
1517     this->TextureResourceIds.erase(found);
1518     }
1519 }
1520 
GetTextureUnitForTexture(vtkTextureObject * texture)1521 int vtkOpenGLRenderWindow::GetTextureUnitForTexture(vtkTextureObject *texture)
1522 {
1523   // Only deactivate if it isn't already there
1524   typedef std::map<const vtkTextureObject *, int>::const_iterator TRIter;
1525   TRIter found = this->TextureResourceIds.find(texture);
1526   if (found != this->TextureResourceIds.end())
1527     {
1528     return found->second;
1529     }
1530 
1531   return -1;
1532 }
1533 
1534 // ----------------------------------------------------------------------------
1535 // Description:
1536 // Create an offScreen window based on OpenGL framebuffer extension.
1537 // Return if the creation was successful or not.
1538 // \pre positive_width: width>0
1539 // \pre positive_height: height>0
1540 // \pre not_initialized: !OffScreenUseFrameBuffer
1541 // \post valid_result: (result==0 || result==1)
1542 //                     && (result implies OffScreenUseFrameBuffer)
CreateHardwareOffScreenWindow(int width,int height)1543 int vtkOpenGLRenderWindow::CreateHardwareOffScreenWindow(int width, int height)
1544 {
1545   assert("pre: positive_width" && width>0);
1546   assert("pre: positive_height" && height>0);
1547   assert("pre: not_initialized" && !this->OffScreenUseFrameBuffer);
1548 
1549   // 1. create a regular OpenGLcontext (ie create a window)
1550   this->CreateAWindow();
1551   this->MakeCurrent();
1552   int result = 0;
1553 
1554   // test for FBO support
1555 #if GL_ES_VERSION_2_0 != 1
1556   if(!glewIsSupported("GL_EXT_framebuffer_object"))
1557     {
1558     vtkDebugMacro( << " extension GL_EXT_framebuffer_object is not supported. "
1559       "Hardware accelerated offscreen rendering is not available" );
1560     this->DestroyWindow();
1561     }
1562   else
1563 #endif
1564     {
1565     // 2. regular framebuffer code
1566     this->NumberOfFrameBuffers=1;
1567 #ifdef GL_STEREO
1568     GLboolean flag;
1569     glGetBooleanv(GL_STEREO,&flag);
1570     if(flag)
1571       {
1572       this->NumberOfFrameBuffers<<=1;
1573       }
1574 #endif
1575 
1576     // Up to 2: stereo
1577     GLuint textureObjects[2];
1578 
1579     GLuint frameBufferObject;
1580     GLuint depthRenderBufferObject;
1581     glGenFramebuffers(1, &frameBufferObject); // color
1582     glGenRenderbuffers(1, &depthRenderBufferObject); // depth
1583     int i=0;
1584     while(i<this->NumberOfFrameBuffers)
1585       {
1586       textureObjects[i]=0;
1587       ++i;
1588       }
1589     glGenTextures(this->NumberOfFrameBuffers,textureObjects);
1590     // Color buffers
1591     glBindFramebuffer(GL_FRAMEBUFFER,frameBufferObject);
1592 
1593     GLenum target;
1594     target=GL_TEXTURE_2D;
1595 
1596     i=0;
1597     while(i<this->NumberOfFrameBuffers)
1598       {
1599       glBindTexture(target,textureObjects[i]);
1600       glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1601       glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1602       glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1603       glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1604 #ifdef GL_RGBA8
1605       glTexImage2D(target,0,GL_RGBA8,width,height,
1606                    0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
1607 #else
1608       glTexImage2D(target,0,GL_RGBA,width,height,
1609                    0, GL_RGBA, GL_UNSIGNED_BYTE, NULL );
1610 #endif
1611       glFramebufferTexture2D(GL_FRAMEBUFFER,
1612                              GL_COLOR_ATTACHMENT0+i,
1613                              target, textureObjects[i], 0);
1614       ++i;
1615       }
1616     GLenum status;
1617     status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1618     if(status != GL_FRAMEBUFFER_COMPLETE)
1619       {
1620       vtkDebugMacro(<<"Hardware does not support GPU Offscreen rendering.");
1621       glBindTexture(target,0);
1622       glBindFramebuffer(GL_FRAMEBUFFER,0);
1623       glDeleteFramebuffers(1,&frameBufferObject);
1624       glDeleteRenderbuffers(1,&depthRenderBufferObject);
1625       glDeleteTextures(this->NumberOfFrameBuffers,textureObjects);
1626       this->DestroyWindow();
1627       }
1628     else
1629       {
1630       // Set up the depth (and stencil), render buffer
1631       glBindRenderbuffer(GL_RENDERBUFFER,
1632                          depthRenderBufferObject);
1633 #ifdef GL_DEPTH_STENCIL
1634       if(this->StencilCapable)
1635         {
1636         glRenderbufferStorage(GL_RENDERBUFFER,
1637                               GL_DEPTH_STENCIL, width,height);
1638         }
1639       else
1640 #endif
1641         {
1642 #ifdef GL_DEPTH_COMPONENT24
1643         glRenderbufferStorage(GL_RENDERBUFFER,
1644                               GL_DEPTH_COMPONENT24,width,height);
1645 #else
1646         glRenderbufferStorage(GL_RENDERBUFFER,
1647                               GL_DEPTH_COMPONENT16,width,height);
1648 #endif
1649         }
1650       glFramebufferRenderbuffer(GL_FRAMEBUFFER,
1651                                 GL_DEPTH_ATTACHMENT,
1652                                 GL_RENDERBUFFER,
1653                                 depthRenderBufferObject);
1654       if(this->StencilCapable)
1655         {
1656         glFramebufferRenderbuffer(GL_FRAMEBUFFER,
1657                                   GL_STENCIL_ATTACHMENT,
1658                                   GL_RENDERBUFFER,
1659                                   depthRenderBufferObject);
1660         }
1661 
1662       // Last check to see if the FBO is supported or not.
1663       status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1664       if(status != GL_FRAMEBUFFER_COMPLETE)
1665         {
1666         vtkDebugMacro(<<"Hardware does not support GPU Offscreen rendering withthis depth/stencil configuration.");
1667         glBindTexture(target,0);
1668         glBindFramebuffer(GL_FRAMEBUFFER,0);
1669         glDeleteFramebuffers(1,&frameBufferObject);
1670         glDeleteRenderbuffers(1,&depthRenderBufferObject);
1671         glDeleteTextures(this->NumberOfFrameBuffers,textureObjects);
1672         this->DestroyWindow();
1673         }
1674       else
1675         {
1676         result=1;
1677         this->BackLeftBuffer=
1678           static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
1679         this->FrontLeftBuffer=
1680           static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
1681 
1682         this->BackBuffer=static_cast<unsigned int>(
1683           GL_COLOR_ATTACHMENT0);
1684         this->FrontBuffer=
1685           static_cast<unsigned int>(GL_COLOR_ATTACHMENT0);
1686 
1687         if(this->NumberOfFrameBuffers==2)
1688           {
1689           this->BackRightBuffer=
1690             static_cast<unsigned int>(GL_COLOR_ATTACHMENT0+1);
1691           this->FrontRightBuffer=
1692             static_cast<unsigned int>(GL_COLOR_ATTACHMENT0+1);
1693           }
1694 
1695         // Save GL objects by static casting to standard C types. GL* types
1696         // are not allowed in VTK header files.
1697         this->FrameBufferObject=static_cast<unsigned int>(frameBufferObject);
1698         this->DepthRenderBufferObject=
1699           static_cast<unsigned int>(depthRenderBufferObject);
1700         i=0;
1701         while(i<this->NumberOfFrameBuffers)
1702           {
1703           this->TextureObjects[i]=static_cast<unsigned int>(textureObjects[i]);
1704           ++i;
1705           }
1706         this->OffScreenUseFrameBuffer=1;
1707         }
1708       }
1709     }
1710   // A=>B = !A || B
1711   assert("post: valid_result" && (result==0 || result==1)
1712          && (!result || OffScreenUseFrameBuffer));
1713   return result;
1714 }
1715 
1716 // ----------------------------------------------------------------------------
1717 // Description:
1718 // Destroy an offscreen window based on OpenGL framebuffer extension.
1719 // \pre initialized: OffScreenUseFrameBuffer
1720 // \post destroyed: !OffScreenUseFrameBuffer
DestroyHardwareOffScreenWindow()1721 void vtkOpenGLRenderWindow::DestroyHardwareOffScreenWindow()
1722 {
1723   assert("pre: initialized" && this->OffScreenUseFrameBuffer);
1724 
1725   this->MakeCurrent();
1726   glBindFramebuffer(GL_FRAMEBUFFER, 0 );
1727 
1728   // Restore framebuffer names.
1729   this->BackLeftBuffer=static_cast<unsigned int>(GL_BACK_LEFT);
1730   this->BackRightBuffer=static_cast<unsigned int>(GL_BACK_RIGHT);
1731   this->FrontLeftBuffer=static_cast<unsigned int>(GL_FRONT_LEFT);
1732   this->FrontRightBuffer=static_cast<unsigned int>(GL_FRONT_RIGHT);
1733   this->BackBuffer=static_cast<unsigned int>(GL_BACK);
1734   this->FrontBuffer=static_cast<unsigned int>(GL_FRONT);
1735 
1736   GLuint frameBufferObject=static_cast<GLuint>(this->FrameBufferObject);
1737   glDeleteFramebuffers(1,&frameBufferObject);
1738 
1739   GLuint depthRenderBufferObject=static_cast<GLuint>(this->DepthRenderBufferObject);
1740   glDeleteRenderbuffers(1,&depthRenderBufferObject);
1741 
1742   GLuint textureObjects[4];
1743   int i=0;
1744   while(i<this->NumberOfFrameBuffers)
1745     {
1746     textureObjects[i]=static_cast<GLuint>(this->TextureObjects[i]);
1747     ++i;
1748     }
1749 
1750   glDeleteTextures(this->NumberOfFrameBuffers,textureObjects);
1751   this->DestroyWindow();
1752 
1753   this->OffScreenUseFrameBuffer=0;
1754 
1755   assert("post: destroyed" && !this->OffScreenUseFrameBuffer);
1756 }
1757 
1758 // ----------------------------------------------------------------------------
1759 // Description:
1760 // Returns its texture unit manager object. A new one will be created if one
1761 // hasn't already been set up.
GetTextureUnitManager()1762 vtkTextureUnitManager *vtkOpenGLRenderWindow::GetTextureUnitManager()
1763 {
1764   if(this->TextureUnitManager==0)
1765     {
1766     vtkTextureUnitManager *manager=vtkTextureUnitManager::New();
1767 
1768     // This does not form a reference loop since vtkOpenGLHardwareSupport does
1769     // not keep a reference to the render window.
1770     manager->SetContext(this);
1771     this->SetTextureUnitManager(manager);
1772     manager->Delete();
1773     }
1774   return this->TextureUnitManager;
1775 }
1776 
1777 // ----------------------------------------------------------------------------
1778 // Description:
1779 // Block the thread until the actual rendering is finished().
1780 // Useful for measurement only.
WaitForCompletion()1781 void vtkOpenGLRenderWindow::WaitForCompletion()
1782 {
1783   glFinish();
1784 }
1785