1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkOSOpenGLRenderWindow.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 "vtkOSOpenGLRenderWindow.h"
16 #include "vtkOpenGLRenderer.h"
17 #include "vtkOpenGLProperty.h"
18 #include "vtkOpenGLTexture.h"
19 #include "vtkOpenGLCamera.h"
20 #include "vtkOpenGLLight.h"
21 #include "vtkOpenGLActor.h"
22 #include <GL/gl.h>
23 #include "vtkgl.h"
24
25 #ifdef VTK_OPENGL_HAS_OSMESA
26 # include <GL/osmesa.h>
27 #endif
28
29 #include "vtkCommand.h"
30 #include "vtkIdList.h"
31 #include "vtkObjectFactory.h"
32 #include "vtkRendererCollection.h"
33 #include "vtkOpenGLExtensionManager.h"
34
35 #include "vtksys/SystemTools.hxx"
36 #include "vtksys/ios/sstream"
37
38 class vtkOSOpenGLRenderWindow;
39 class vtkRenderWindow;
40
41 class vtkOSOpenGLRenderWindowInternal
42 {
43 friend class vtkOSOpenGLRenderWindow;
44 private:
45 vtkOSOpenGLRenderWindowInternal(vtkRenderWindow*);
46
47 // store previous settings of on screen window
48 int ScreenDoubleBuffer;
49 int ScreenMapped;
50
51 // OffScreen stuff
52 OSMesaContext OffScreenContextId;
53 void *OffScreenWindow;
54 };
55
vtkOSOpenGLRenderWindowInternal(vtkRenderWindow * rw)56 vtkOSOpenGLRenderWindowInternal::vtkOSOpenGLRenderWindowInternal(
57 vtkRenderWindow *rw)
58 {
59
60 this->ScreenMapped = rw->GetMapped();
61 this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
62
63 // OpenGL specific
64 this->OffScreenContextId = NULL;
65 this->OffScreenWindow = NULL;
66 }
67
68
69 vtkStandardNewMacro(vtkOSOpenGLRenderWindow);
70
71 // a couple of routines for offscreen rendering
vtkOSMesaDestroyWindow(void * Window)72 void vtkOSMesaDestroyWindow(void *Window)
73 {
74 free(Window);
75 }
76
vtkOSMesaCreateWindow(int width,int height)77 void *vtkOSMesaCreateWindow(int width, int height)
78 {
79 return malloc(width*height*4);
80 }
81
vtkOSOpenGLRenderWindow()82 vtkOSOpenGLRenderWindow::vtkOSOpenGLRenderWindow()
83 {
84 // this->ParentId = (Window)NULL;
85 this->ScreenSize[0] = 1280;
86 this->ScreenSize[1] = 1024;
87 this->OwnDisplay = 0;
88 this->CursorHidden = 0;
89 this->ForceMakeCurrent = 0;
90 this->OwnWindow = 0;
91
92 this->Internal = new vtkOSOpenGLRenderWindowInternal(this);
93
94 this->Capabilities = 0;
95
96 }
97
98 // free up memory & close the window
~vtkOSOpenGLRenderWindow()99 vtkOSOpenGLRenderWindow::~vtkOSOpenGLRenderWindow()
100 {
101 // close-down all system-specific drawing resources
102 this->Finalize();
103
104 vtkRenderer *ren;
105 vtkCollectionSimpleIterator rit;
106 this->Renderers->InitTraversal(rit);
107 while ( (ren = this->Renderers->GetNextRenderer(rit)) )
108 {
109 ren->SetRenderWindow(NULL);
110 }
111
112 delete this->Internal;
113 }
114
115 // End the rendering process and display the image.
Frame()116 void vtkOSOpenGLRenderWindow::Frame()
117 {
118 this->MakeCurrent();
119 glFlush();
120 }
121
122 //
123 // Set the variable that indicates that we want a stereo capable window
124 // be created. This method can only be called before a window is realized.
125 //
SetStereoCapableWindow(int capable)126 void vtkOSOpenGLRenderWindow::SetStereoCapableWindow(int capable)
127 {
128 if (!this->Internal->OffScreenContextId)
129 {
130 vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
131 }
132 else
133 {
134 vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
135 << "before the window is realized, i.e. before a render.");
136 }
137 }
138
CreateAWindow()139 void vtkOSOpenGLRenderWindow::CreateAWindow()
140 {
141 this->CreateOffScreenWindow(this->ScreenSize[0], this->ScreenSize[1]);
142 }
143
DestroyWindow()144 void vtkOSOpenGLRenderWindow::DestroyWindow()
145 {
146 this->MakeCurrent();
147
148 // tell each of the renderers that this render window/graphics context
149 // is being removed (the RendererCollection is removed by vtkRenderWindow's
150 // destructor)
151 vtkRenderer* ren;
152 this->Renderers->InitTraversal();
153 for ( ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject());
154 ren != NULL;
155 ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject()) )
156 {
157 ren->SetRenderWindow(NULL);
158 ren->SetRenderWindow(this);
159 }
160
161
162 if (this->Capabilities)
163 {
164 delete[] this->Capabilities;
165 this->Capabilities = 0;
166 }
167
168 this->DestroyOffScreenWindow();
169
170 // make sure all other code knows we're not mapped anymore
171 this->Mapped = 0;
172
173 }
174
CreateOffScreenWindow(int width,int height)175 void vtkOSOpenGLRenderWindow::CreateOffScreenWindow(int width, int height)
176 {
177
178 this->DoubleBuffer = 0;
179
180 if (!this->Internal->OffScreenWindow)
181 {
182 this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
183 this->OwnWindow = 1;
184 }
185 if (!this->Internal->OffScreenContextId)
186 {
187 this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
188 }
189 this->MakeCurrent();
190
191 this->Mapped = 0;
192 this->Size[0] = width;
193 this->Size[1] = height;
194
195 this->MakeCurrent();
196
197 // tell our renderers about us
198 vtkRenderer* ren;
199 for (this->Renderers->InitTraversal();
200 (ren = this->Renderers->GetNextItem());)
201 {
202 ren->SetRenderWindow(0);
203 ren->SetRenderWindow(this);
204 }
205
206 this->OpenGLInit();
207 }
208
DestroyOffScreenWindow()209 void vtkOSOpenGLRenderWindow::DestroyOffScreenWindow()
210 {
211
212 // release graphic resources.
213 vtkRenderer *ren;
214 vtkCollectionSimpleIterator rit;
215 this->Renderers->InitTraversal(rit);
216 while ( (ren = this->Renderers->GetNextRenderer(rit)) )
217 {
218 ren->SetRenderWindow(NULL);
219 ren->SetRenderWindow(this);
220 }
221
222
223 if (this->Internal->OffScreenContextId)
224 {
225 OSMesaDestroyContext(this->Internal->OffScreenContextId);
226 this->Internal->OffScreenContextId = NULL;
227 vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
228 this->Internal->OffScreenWindow = NULL;
229 }
230 }
231
ResizeOffScreenWindow(int width,int height)232 void vtkOSOpenGLRenderWindow::ResizeOffScreenWindow(int width, int height)
233 {
234 if(this->Internal->OffScreenContextId)
235 {
236 this->DestroyOffScreenWindow();
237 this->CreateOffScreenWindow(width, height);
238 }
239 }
240
241
242 // Initialize the window for rendering.
WindowInitialize(void)243 void vtkOSOpenGLRenderWindow::WindowInitialize (void)
244 {
245 this->CreateAWindow();
246
247 this->MakeCurrent();
248
249 // tell our renderers about us
250 vtkRenderer* ren;
251 for (this->Renderers->InitTraversal();
252 (ren = this->Renderers->GetNextItem());)
253 {
254 ren->SetRenderWindow(0);
255 ren->SetRenderWindow(this);
256 }
257
258 this->OpenGLInit();
259 }
260
261 // Initialize the rendering window.
Initialize(void)262 void vtkOSOpenGLRenderWindow::Initialize (void)
263 {
264 if(! (this->Internal->OffScreenContextId))
265 {
266 // initialize offscreen window
267 int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
268 int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
269 this->CreateOffScreenWindow(width, height);
270 }
271 }
272
Finalize(void)273 void vtkOSOpenGLRenderWindow::Finalize (void)
274 {
275
276 // clean up offscreen stuff
277 this->SetOffScreenRendering(0);
278
279 // clean and destroy window
280 this->DestroyWindow();
281
282 }
283
284 // Change the window to fill the entire screen.
SetFullScreen(int arg)285 void vtkOSOpenGLRenderWindow::SetFullScreen(int arg)
286 {
287 (void)arg;
288 this->Modified();
289 }
290
291 // Resize the window.
WindowRemap()292 void vtkOSOpenGLRenderWindow::WindowRemap()
293 {
294 // shut everything down
295 this->Finalize();
296
297 // set the default windowid
298 // this->WindowId = this->NextWindowId;
299 // this->NextWindowId = (Window)NULL;
300
301 // set everything up again
302 this->Initialize();
303 }
304
305 // Begin the rendering process.
Start(void)306 void vtkOSOpenGLRenderWindow::Start(void)
307 {
308 this->Initialize();
309
310 // set the current window
311 this->MakeCurrent();
312 }
313
314
315 // Specify the size of the rendering window.
SetSize(int width,int height)316 void vtkOSOpenGLRenderWindow::SetSize(int width,int height)
317 {
318 if ((this->Size[0] != width)||(this->Size[1] != height))
319 {
320 this->Size[0] = width;
321 this->Size[1] = height;
322 this->ResizeOffScreenWindow(width,height);
323 this->Modified();
324 }
325 }
326
PrintSelf(ostream & os,vtkIndent indent)327 void vtkOSOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
328 {
329 this->Superclass::PrintSelf(os,indent);
330
331 os << indent << "OffScreenContextId: " << this->Internal->OffScreenContextId << "\n";
332 // os << indent << "Color Map: " << this->ColorMap << "\n";
333 // os << indent << "Next Window Id: " << this->NextWindowId << "\n";
334 // os << indent << "Window Id: " << this->GetWindowId() << "\n";
335 }
336
MakeCurrent()337 void vtkOSOpenGLRenderWindow::MakeCurrent()
338 {
339 // set the current window
340 if (this->Internal->OffScreenContextId)
341 {
342 if (OSMesaMakeCurrent(this->Internal->OffScreenContextId,
343 this->Internal->OffScreenWindow, GL_UNSIGNED_BYTE,
344 this->Size[0], this->Size[1]) != GL_TRUE)
345 {
346 vtkWarningMacro("failed call to OSMesaMakeCurrent");
347 }
348 }
349 }
350
351 // ----------------------------------------------------------------------------
352 // Description:
353 // Tells if this window is the current OpenGL context for the calling thread.
IsCurrent()354 bool vtkOSOpenGLRenderWindow::IsCurrent()
355 {
356 bool result=false;
357 if(this->Internal->OffScreenContextId)
358 {
359 result=this->Internal->OffScreenContextId==OSMesaGetCurrentContext();
360 }
361 return result;
362 }
363
364
SetForceMakeCurrent()365 void vtkOSOpenGLRenderWindow::SetForceMakeCurrent()
366 {
367 this->ForceMakeCurrent = 1;
368 }
369
GetGenericContext()370 void *vtkOSOpenGLRenderWindow::GetGenericContext()
371 {
372 return (void *)this->Internal->OffScreenContextId;
373 }
374
GetEventPending()375 int vtkOSOpenGLRenderWindow::GetEventPending()
376 {
377 return 0;
378 }
379
380 // Get the size of the screen in pixels
GetScreenSize()381 int *vtkOSOpenGLRenderWindow::GetScreenSize()
382 {
383
384 this->ScreenSize[0] = 1280;
385 this->ScreenSize[1] = 1024;
386 return this->ScreenSize;
387 }
388
389 // Get the position in screen coordinates (pixels) of the window.
GetPosition(void)390 int *vtkOSOpenGLRenderWindow::GetPosition(void)
391 {
392 return this->Position;
393 }
394
395 // Move the window to a new position on the display.
SetPosition(int x,int y)396 void vtkOSOpenGLRenderWindow::SetPosition(int x, int y)
397 {
398 if ((this->Position[0] != x)||(this->Position[1] != y))
399 {
400 this->Modified();
401 }
402 this->Position[0] = x;
403 this->Position[1] = y;
404 }
405
406 // Set this RenderWindow's X window id to a pre-existing window.
SetWindowInfo(char * info)407 void vtkOSOpenGLRenderWindow::SetWindowInfo(char *info)
408 {
409 int tmp;
410
411 this->OwnDisplay = 1;
412
413 sscanf(info,"%i",&tmp);
414
415 }
416
417 // Set this RenderWindow's X window id to a pre-existing window.
SetNextWindowInfo(char * info)418 void vtkOSOpenGLRenderWindow::SetNextWindowInfo(char *info)
419 {
420 int tmp;
421 sscanf(info,"%i",&tmp);
422
423 // this->SetNextWindowId((Window)tmp);
424 }
425
426 // Sets the X window id of the window that WILL BE created.
SetParentInfo(char * info)427 void vtkOSOpenGLRenderWindow::SetParentInfo(char *info)
428 {
429 int tmp;
430
431 // get the default display connection
432 this->OwnDisplay = 1;
433
434 sscanf(info,"%i",&tmp);
435
436 // this->SetParentId(tmp);
437 }
438
SetWindowId(void * arg)439 void vtkOSOpenGLRenderWindow::SetWindowId(void *arg)
440 {
441 (void)arg;
442 // this->SetWindowId((Window)arg);
443 }
SetParentId(void * arg)444 void vtkOSOpenGLRenderWindow::SetParentId(void *arg)
445 {
446 (void)arg;
447 // this->SetParentId((Window)arg);
448 }
449
ReportCapabilities()450 const char* vtkOSOpenGLRenderWindow::ReportCapabilities()
451 {
452 MakeCurrent();
453
454 // int scrnum = DefaultScreen(this->DisplayId);
455
456 const char *glVendor = (const char *) glGetString(GL_VENDOR);
457 const char *glRenderer = (const char *) glGetString(GL_RENDERER);
458 const char *glVersion = (const char *) glGetString(GL_VERSION);
459 const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
460
461 vtksys_ios::ostringstream strm;
462 strm << "OpenGL vendor string: " << glVendor << endl;
463 strm << "OpenGL renderer string: " << glRenderer << endl;
464 strm << "OpenGL version string: " << glVersion << endl;
465 strm << "OpenGL extensions: " << glExtensions << endl;
466 delete[] this->Capabilities;
467 size_t len = strm.str().length();
468 this->Capabilities = new char[len + 1];
469 strncpy(this->Capabilities, strm.str().c_str(), len);
470 this->Capabilities[len] = 0;
471 return this->Capabilities;
472 }
473
SupportsOpenGL()474 int vtkOSOpenGLRenderWindow::SupportsOpenGL()
475 {
476 MakeCurrent();
477 return 1;
478 }
479
480
IsDirect()481 int vtkOSOpenGLRenderWindow::IsDirect()
482 {
483 MakeCurrent();
484 return 0;
485 }
486
487
SetWindowName(const char * cname)488 void vtkOSOpenGLRenderWindow::SetWindowName(const char * cname)
489 {
490 char *name = new char[ strlen(cname)+1 ];
491 strcpy(name, cname);
492 vtkOpenGLRenderWindow::SetWindowName( name );
493 delete [] name;
494 }
495
496 // Specify the X window id to use if a WindowRemap is done.
497 /*void vtkOSOpenGLRenderWindow::SetNextWindowId(Window arg)
498 {
499 vtkDebugMacro(<< "Setting NextWindowId to " << (void *)arg << "\n");
500
501 this->NextWindowId = arg;
502 }*/
503
SetNextWindowId(void * arg)504 void vtkOSOpenGLRenderWindow::SetNextWindowId(void *arg)
505 {
506 (void)arg;
507 // this->SetNextWindowId((Window)arg);
508 }
509
510
511 // Set the X display id for this RenderWindow to use to a pre-existing
512 // X display id.
513 /*void vtkOSOpenGLRenderWindow::SetDisplayId(Display *arg)
514 {
515 vtkDebugMacro(<< "Setting DisplayId to " << (void *)arg << "\n");
516
517 this->DisplayId = arg;
518 this->OwnDisplay = 0;
519
520 }*/
521
522 /*void vtkOSOpenGLRenderWindow::SetDisplayId(void *arg)
523 {
524 this->SetDisplayId((Display *)arg);
525 this->OwnDisplay = 0;
526 }*/
527
528 //============================================================================
529 // Stuff above this is almost a mirror of vtkOSOpenGLRenderWindow.
530 // The code specific to OpenGL Off-Screen stuff may eventually be
531 // put in a supper class so this whole file could just be included
532 // (mangled) from vtkOSOpenGLRenderWindow like the other OpenGL classes.
533 //============================================================================
534
SetOffScreenRendering(int i)535 void vtkOSOpenGLRenderWindow::SetOffScreenRendering(int i)
536 {
537 if (this->OffScreenRendering == i)
538 {
539 return;
540 }
541
542 // invoke super
543 this->vtkRenderWindow::SetOffScreenRendering(i);
544
545 this->Internal->ScreenDoubleBuffer = this->DoubleBuffer;
546 this->DoubleBuffer = 0;
547 if(this->Mapped)
548 {
549 this->DestroyWindow();
550 }
551
552 // delay initialization until Render
553 }
554
555 // This probably has been moved to superclass.
GetGenericWindowId()556 void *vtkOSOpenGLRenderWindow::GetGenericWindowId()
557 {
558 return (void *)this->Internal->OffScreenWindow;
559 }
560
SetCurrentCursor(int shape)561 void vtkOSOpenGLRenderWindow::SetCurrentCursor(int shape)
562 {
563 if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) )
564 {
565 return;
566 }
567 this->Superclass::SetCurrentCursor(shape);
568 }
569