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