1 /*=========================================================================
2
3 Program: Visualization Toolkit
4 Module: vtkXOpenGLRenderWindow.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
16 #include "vtkXOpenGLRenderWindow.h"
17 #include "vtkOpenGLRenderer.h"
18
19 #include "vtk_glew.h"
20
21 // define GLX_GLXEXT_LEGACY to prevent glx.h to include glxext.h provided by
22 // the system
23 //#define GLX_GLXEXT_LEGACY
24 #include "GL/glx.h"
25
26 #include "vtkToolkits.h"
27
28 #ifdef VTK_OPENGL_HAS_OSMESA
29 #include <GL/osmesa.h>
30 #endif
31
32 #include "vtkCommand.h"
33 #include "vtkIdList.h"
34 #include "vtkObjectFactory.h"
35 #include "vtkRendererCollection.h"
36 #include "vtkRenderWindowInteractor.h"
37
38 #include "vtksys/SystemTools.hxx"
39
40 #include <vtksys/ios/sstream>
41
42 #include <X11/Xlib.h>
43 #include <X11/Xutil.h>
44 #include <X11/cursorfont.h>
45
46 class vtkXOpenGLRenderWindow;
47 class vtkRenderWindow;
48 class vtkXOpenGLRenderWindowInternal
49 {
50 friend class vtkXOpenGLRenderWindow;
51 private:
52 vtkXOpenGLRenderWindowInternal(vtkRenderWindow*);
53
54 GLXContext ContextId;
55
56 // so we basically have 4 methods here for handling drawables
57 // how about abstracting this a bit?
58
59 // support for Pixmap based offscreen rendering
60 Pixmap pixmap;
61 GLXContext PixmapContextId;
62 Window PixmapWindowId;
63
64
65 // support for Pbuffer based offscreen rendering
66 GLXContext PbufferContextId;
67 GLXPbuffer Pbuffer;
68
69 // store previous settings of on screen window
70 int ScreenDoubleBuffer;
71 int ScreenMapped;
72
73 #if defined( VTK_OPENGL_HAS_OSMESA )
74 // OffScreen stuff
75 OSMesaContext OffScreenContextId;
76 void *OffScreenWindow;
77 #endif
78 };
79
vtkXOpenGLRenderWindowInternal(vtkRenderWindow * rw)80 vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal(
81 vtkRenderWindow *rw)
82 {
83 this->ContextId = NULL;
84
85 this->PixmapContextId = NULL;
86 this->PixmapWindowId = 0;
87
88 this->PbufferContextId = NULL;
89 this->Pbuffer = 0;
90
91 this->ScreenMapped = rw->GetMapped();
92 this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
93
94 // OpenGL specific
95 #ifdef VTK_OPENGL_HAS_OSMESA
96 this->OffScreenContextId = NULL;
97 this->OffScreenWindow = NULL;
98 #endif
99 }
100
101 vtkStandardNewMacro(vtkXOpenGLRenderWindow);
102
103 #define MAX_LIGHTS 8
104
105 #ifdef VTK_OPENGL_HAS_OSMESA
106 // a couple of routines for offscreen rendering
vtkOSMesaDestroyWindow(void * Window)107 void vtkOSMesaDestroyWindow(void *Window)
108 {
109 free(Window);
110 }
111
vtkOSMesaCreateWindow(int width,int height)112 void *vtkOSMesaCreateWindow(int width, int height)
113 {
114 return malloc(width*height*4);
115 }
116 #endif
117
vtkXOpenGLRenderWindowTryForFBConfig(Display * DisplayId,int drawable_type,int doublebuff,int stereo,int multisamples,int alphaBitPlanes,int stencil)118 GLXFBConfig* vtkXOpenGLRenderWindowTryForFBConfig(Display *DisplayId,
119 int drawable_type,
120 int doublebuff,
121 int stereo,
122 int multisamples,
123 int alphaBitPlanes,
124 int stencil)
125 {
126 int index;
127 static int attributes[50];
128
129 // setup the default stuff we ask for
130 index = 0;
131 attributes[index++] = GLX_DRAWABLE_TYPE;
132 attributes[index++] = drawable_type;
133 attributes[index++] = GLX_RENDER_TYPE;
134 attributes[index++] = GLX_RGBA_BIT;
135 attributes[index++] = GLX_RED_SIZE;
136 attributes[index++] = 1;
137 attributes[index++] = GLX_GREEN_SIZE;
138 attributes[index++] = 1;
139 attributes[index++] = GLX_BLUE_SIZE;
140 attributes[index++] = 1;
141 attributes[index++] = GLX_DEPTH_SIZE;
142 attributes[index++] = 1;
143 if (alphaBitPlanes)
144 {
145 attributes[index++] = GLX_ALPHA_SIZE;
146 attributes[index++] = 1;
147 }
148 if (doublebuff)
149 {
150 attributes[index++] = GLX_DOUBLEBUFFER;
151 }
152 if (stencil)
153 {
154 attributes[index++] = GLX_STENCIL_SIZE;
155 attributes[index++] = 8;
156 }
157 if (stereo)
158 {
159 // also try for STEREO
160 attributes[index++] = GLX_STEREO;
161 }
162 if (multisamples)
163 {
164 #ifdef GLX_SAMPLE_BUFFERS_SGIS
165 attributes[index++] = GLX_SAMPLE_BUFFERS_SGIS;
166 attributes[index++] = 1;
167 attributes[index++] = GLX_SAMPLES_SGIS;
168 attributes[index++] = multisamples;
169 #endif
170 }
171
172 attributes[index++] = None;
173 int tmp;
174 GLXFBConfig* fb = glXChooseFBConfig(DisplayId, XDefaultScreen(DisplayId),
175 attributes, &tmp);
176 return fb;
177 }
178
vtkXOpenGLRenderWindowTryForVisual(Display * DisplayId,int doublebuff,int stereo,int multisamples,int alphaBitPlanes,int stencil)179 XVisualInfo *vtkXOpenGLRenderWindowTryForVisual(Display *DisplayId,
180 int doublebuff, int stereo,
181 int multisamples,
182 int alphaBitPlanes,
183 int stencil)
184 {
185 int index;
186 static int attributes[50];
187
188 // setup the default stuff we ask for
189 index = 0;
190 attributes[index++] = GLX_RGBA;
191 attributes[index++] = GLX_RED_SIZE;
192 attributes[index++] = 1;
193 attributes[index++] = GLX_GREEN_SIZE;
194 attributes[index++] = 1;
195 attributes[index++] = GLX_BLUE_SIZE;
196 attributes[index++] = 1;
197 attributes[index++] = GLX_DEPTH_SIZE;
198 attributes[index++] = 1;
199 if (alphaBitPlanes)
200 {
201 attributes[index++] = GLX_ALPHA_SIZE;
202 attributes[index++] = 1;
203 }
204 if (doublebuff)
205 {
206 attributes[index++] = GLX_DOUBLEBUFFER;
207 }
208 if (stencil)
209 {
210 attributes[index++] = GLX_STENCIL_SIZE;
211 attributes[index++] = 8;
212 }
213 if (stereo)
214 {
215 // also try for STEREO
216 attributes[index++] = GLX_STEREO;
217 }
218 if (multisamples)
219 {
220 #ifdef GLX_SAMPLE_BUFFERS_SGIS
221 attributes[index++] = GLX_SAMPLE_BUFFERS_SGIS;
222 attributes[index++] = 1;
223 attributes[index++] = GLX_SAMPLES_SGIS;
224 attributes[index++] = multisamples;
225 #endif
226 }
227
228 attributes[index++] = None;
229
230 return glXChooseVisual(DisplayId, XDefaultScreen(DisplayId), attributes );
231 }
232
vtkXOpenGLRenderWindowGetDesiredFBConfig(Display * DisplayId,int & win_stereo,int & win_multisamples,int & win_doublebuffer,int & win_alphaplanes,int drawable_type,int & stencil)233 GLXFBConfig *vtkXOpenGLRenderWindowGetDesiredFBConfig(
234 Display *DisplayId,
235 int &win_stereo,
236 int &win_multisamples,
237 int &win_doublebuffer,
238 int &win_alphaplanes,
239 int drawable_type,
240 int &stencil)
241 {
242 GLXFBConfig *fbc = NULL;
243 int multi;
244 int stereo = 0;
245
246 // try every possibility stoping when we find one that works
247 for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
248 {
249 for (multi = win_multisamples; !fbc && multi >= 0; multi--)
250 {
251 if (fbc)
252 {
253 XFree(fbc);
254 }
255 fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
256 drawable_type,
257 win_doublebuffer,
258 stereo, multi,
259 win_alphaplanes,
260 stencil);
261 if (fbc && win_stereo && !stereo)
262 {
263 // requested a stereo capable window but we could not get one
264 win_stereo = 0;
265 }
266 }
267 }
268 for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
269 {
270 for (multi = win_multisamples; !fbc && multi >= 0; multi--)
271 {
272 if (fbc)
273 {
274 XFree(fbc);
275 }
276 fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
277 drawable_type,
278 !win_doublebuffer,
279 stereo, multi,
280 win_alphaplanes,
281 stencil);
282 if (fbc)
283 {
284 win_doublebuffer = !win_doublebuffer;
285 }
286 if (fbc && win_stereo && !stereo)
287 {
288 // requested a stereo capable window but we could not get one
289 win_stereo = 0;
290 }
291 }
292 }
293 return ( fbc );
294 }
295
GetDesiredVisualInfo()296 XVisualInfo *vtkXOpenGLRenderWindow::GetDesiredVisualInfo()
297 {
298 XVisualInfo *v = NULL;
299 int alpha;
300 int multi;
301 int stereo = 0;
302 int stencil;
303
304 // get the default display connection
305 if (!this->DisplayId)
306 {
307 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
308
309 if (this->DisplayId == NULL)
310 {
311 vtkErrorMacro(<< "bad X server connection. DISPLAY="
312 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
313 abort();
314 }
315
316 this->OwnDisplay = 1;
317 }
318
319 // try every possibility stoping when we find one that works
320 for (stencil = this->StencilCapable; !v && stencil >= 0; stencil--)
321 {
322 for (alpha = this->AlphaBitPlanes; !v && alpha >= 0; alpha--)
323 {
324 for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
325 {
326 for (multi = this->MultiSamples; !v && multi >= 0; multi--)
327 {
328 if (v)
329 {
330 XFree(v);
331 }
332 v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
333 this->DoubleBuffer,
334 stereo, multi, alpha,
335 stencil);
336 if (v)
337 {
338 this->StereoCapableWindow = stereo;
339 this->MultiSamples = multi;
340 this->AlphaBitPlanes = alpha;
341 this->StencilCapable = stencil;
342 }
343 }
344 }
345 }
346 }
347 for (stencil = this->StencilCapable; !v && stencil >= 0; stencil--)
348 {
349 for (alpha = this->AlphaBitPlanes; !v && alpha >= 0; alpha--)
350 {
351 for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
352 {
353 for (multi = this->MultiSamples; !v && multi >= 0; multi--)
354 {
355 v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
356 !this->DoubleBuffer,
357 stereo, multi, alpha,
358 stencil);
359 if (v)
360 {
361 this->DoubleBuffer = !this->DoubleBuffer;
362 this->StereoCapableWindow = stereo;
363 this->MultiSamples = multi;
364 this->AlphaBitPlanes = alpha;
365 this->StencilCapable = stencil;
366 }
367 }
368 }
369 }
370 }
371 if (!v)
372 {
373 vtkErrorMacro(<< "Could not find a decent visual\n");
374 }
375 return ( v );
376 }
377
vtkXOpenGLRenderWindow()378 vtkXOpenGLRenderWindow::vtkXOpenGLRenderWindow()
379 {
380 this->ParentId = static_cast<Window>(NULL);
381 this->ScreenSize[0] = 0;
382 this->ScreenSize[1] = 0;
383 this->OwnDisplay = 0;
384 this->CursorHidden = 0;
385 this->ForceMakeCurrent = 0;
386 this->UsingHardware = 0;
387 this->DisplayId = static_cast<Display *>(NULL);
388 this->WindowId = static_cast<Window>(NULL);
389 this->NextWindowId = static_cast<Window>(NULL);
390 this->ColorMap = static_cast<Colormap>(0);
391 this->OwnWindow = 0;
392
393 this->Internal = new vtkXOpenGLRenderWindowInternal(this);
394
395 this->XCCrosshair = 0;
396 this->XCArrow = 0;
397 this->XCSizeAll = 0;
398 this->XCSizeNS = 0;
399 this->XCSizeWE = 0;
400 this->XCSizeNE = 0;
401 this->XCSizeNW = 0;
402 this->XCSizeSE = 0;
403 this->XCSizeSW = 0;
404 this->XCHand = 0;
405
406 this->Capabilities = 0;
407
408 }
409
410 // free up memory & close the window
~vtkXOpenGLRenderWindow()411 vtkXOpenGLRenderWindow::~vtkXOpenGLRenderWindow()
412 {
413 // close-down all system-specific drawing resources
414 this->Finalize();
415
416 vtkRenderer *ren;
417 vtkCollectionSimpleIterator rit;
418 this->Renderers->InitTraversal(rit);
419 while ( (ren = this->Renderers->GetNextRenderer(rit)) )
420 {
421 ren->SetRenderWindow(NULL);
422 }
423
424 delete this->Internal;
425 }
426
427 // End the rendering process and display the image.
Frame()428 void vtkXOpenGLRenderWindow::Frame()
429 {
430 this->MakeCurrent();
431 if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers
432 && this->WindowId!=0)
433 {
434 glXSwapBuffers(this->DisplayId, this->WindowId);
435 vtkDebugMacro(<< " glXSwapBuffers\n");
436 }
437 else
438 {
439 glFlush();
440 }
441 }
442
InitializeFromCurrentContext()443 bool vtkXOpenGLRenderWindow::InitializeFromCurrentContext()
444 {
445 GLXContext currentContext = glXGetCurrentContext();
446 if (currentContext != NULL)
447 {
448 this->SetDisplayId((void*)glXGetCurrentDisplay());
449 this->SetWindowId((void*)glXGetCurrentDrawable());
450 this->Internal->ContextId = currentContext;
451 this->OpenGLInit();
452 this->OwnContext = 0;
453 return true;
454 }
455 return false;
456 }
457
458 //
459 // Set the variable that indicates that we want a stereo capable window
460 // be created. This method can only be called before a window is realized.
461 //
SetStereoCapableWindow(int capable)462 void vtkXOpenGLRenderWindow::SetStereoCapableWindow(int capable)
463 {
464 if (!this->Internal->ContextId && !this->Internal->PixmapContextId
465 && !this->Internal->PbufferContextId
466 #if defined( VTK_OPENGL_HAS_OSMESA )
467 && !this->Internal->OffScreenContextId
468 #endif
469 )
470 {
471 vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
472 }
473 else
474 {
475 vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
476 << "before the window is realized, i.e. before a render.");
477 }
478 }
479
480 static int PbufferAllocFail = 0;
481 extern "C"
482 {
vtkXOGLPbufferErrorHandler(Display *,XErrorEvent *)483 int vtkXOGLPbufferErrorHandler(Display*, XErrorEvent*)
484 {
485 PbufferAllocFail = 1;
486 return 1;
487 }
488 }
489
CreateAWindow()490 void vtkXOpenGLRenderWindow::CreateAWindow()
491 {
492 XVisualInfo *v, matcher;
493 XSetWindowAttributes attr;
494 int x, y, width, height, nItems;
495 XWindowAttributes winattr;
496 XSizeHints xsh;
497
498 xsh.flags = USSize;
499 if ((this->Position[0] >= 0)&&(this->Position[1] >= 0))
500 {
501 xsh.flags |= USPosition;
502 xsh.x = static_cast<int>(this->Position[0]);
503 xsh.y = static_cast<int>(this->Position[1]);
504 }
505
506 x = ((this->Position[0] >= 0) ? this->Position[0] : 5);
507 y = ((this->Position[1] >= 0) ? this->Position[1] : 5);
508 width = ((this->Size[0] > 0) ? this->Size[0] : 300);
509 height = ((this->Size[1] > 0) ? this->Size[1] : 300);
510
511 xsh.width = width;
512 xsh.height = height;
513
514 // get the default display connection
515 if (!this->DisplayId)
516 {
517 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
518 if (this->DisplayId == NULL)
519 {
520 vtkErrorMacro(<< "bad X server connection. DISPLAY="
521 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
522 abort();
523 }
524 this->OwnDisplay = 1;
525 }
526
527 attr.override_redirect = False;
528 if (this->Borders == 0.0)
529 {
530 attr.override_redirect = True;
531 }
532
533 // create our own window ?
534 this->OwnWindow = 0;
535 if (!this->WindowId)
536 {
537 v = this->GetDesiredVisualInfo();
538 this->ColorMap = XCreateColormap(this->DisplayId,
539 XRootWindow(this->DisplayId,v->screen),
540 v->visual, AllocNone);
541
542 attr.background_pixel = 0;
543 attr.border_pixel = 0;
544 attr.colormap = this->ColorMap;
545 attr.event_mask = StructureNotifyMask | ExposureMask;
546
547 // get a default parent if one has not been set.
548 if (! this->ParentId)
549 {
550 this->ParentId = XRootWindow(this->DisplayId, v->screen);
551 }
552 this->WindowId =
553 XCreateWindow(this->DisplayId,
554 this->ParentId,
555 x, y, static_cast<unsigned int>(width),
556 static_cast<unsigned int>(height), 0, v->depth,
557 InputOutput, v->visual,
558 CWBackPixel | CWBorderPixel | CWColormap |
559 CWOverrideRedirect | CWEventMask,
560 &attr);
561 XStoreName(this->DisplayId, this->WindowId, this->WindowName);
562 XSetNormalHints(this->DisplayId,this->WindowId,&xsh);
563 this->OwnWindow = 1;
564 }
565 else
566 {
567 XChangeWindowAttributes(this->DisplayId,this->WindowId,
568 CWOverrideRedirect, &attr);
569 XGetWindowAttributes(this->DisplayId,
570 this->WindowId,&winattr);
571 matcher.visualid = XVisualIDFromVisual(winattr.visual);
572 matcher.screen = XDefaultScreen(DisplayId);
573 v = XGetVisualInfo(this->DisplayId, VisualIDMask | VisualScreenMask,
574 &matcher, &nItems);
575 }
576
577 if (this->OwnWindow)
578 {
579 // RESIZE THE WINDOW TO THE DESIRED SIZE
580 vtkDebugMacro(<< "Resizing the xwindow\n");
581 XResizeWindow(this->DisplayId,this->WindowId,
582 ((this->Size[0] > 0) ?
583 static_cast<unsigned int>(this->Size[0]) : 300),
584 ((this->Size[1] > 0) ?
585 static_cast<unsigned int>(this->Size[1]) : 300));
586 XSync(this->DisplayId,False);
587 }
588
589 // is GLX extension is supported?
590 if(!glXQueryExtension(this->DisplayId, NULL, NULL))
591 {
592 vtkErrorMacro("GLX not found. Aborting.");
593 if (this->HasObserver(vtkCommand::ExitEvent))
594 {
595 this->InvokeEvent(vtkCommand::ExitEvent, NULL);
596 return;
597 }
598 else
599 {
600 abort();
601 }
602 }
603
604 if (!this->Internal->ContextId)
605 {
606 this->Internal->ContextId =
607 glXCreateContext(this->DisplayId, v, 0, GL_TRUE);
608 }
609
610 if(!this->Internal->ContextId)
611 {
612 vtkErrorMacro("Cannot create GLX context. Aborting.");
613 if (this->HasObserver(vtkCommand::ExitEvent))
614 {
615 this->InvokeEvent(vtkCommand::ExitEvent, NULL);
616 return;
617 }
618 else
619 {
620 abort();
621 }
622 }
623
624 if(this->OwnWindow && !this->OffScreenRendering)
625 {
626 vtkDebugMacro(" Mapping the xwindow\n");
627 XMapWindow(this->DisplayId, this->WindowId);
628 XSync(this->DisplayId,False);
629 XGetWindowAttributes(this->DisplayId,
630 this->WindowId,&winattr);
631 // guarantee that the window is mapped before the program continues
632 // on to do the OpenGL rendering.
633 while (winattr.map_state == IsUnmapped)
634 {
635 XGetWindowAttributes(this->DisplayId,
636 this->WindowId,&winattr);
637 }
638 }
639 // free the visual info
640 if (v)
641 {
642 XFree(v);
643 }
644 this->Mapped = 1;
645 this->Size[0] = width;
646 this->Size[1] = height;
647
648 }
649
DestroyWindow()650 void vtkXOpenGLRenderWindow::DestroyWindow()
651 {
652 // free the cursors
653 if (this->DisplayId)
654 {
655 if (this->WindowId)
656 {
657 // we will only have a cursor defined if a CurrentCursor has been
658 // set > 0 or if the cursor has been hidden... if we undefine without
659 // checking, bad things can happen (BadWindow)
660 if (this->GetCurrentCursor() || this->CursorHidden)
661 {
662 XUndefineCursor(this->DisplayId,this->WindowId);
663 }
664 }
665 if (this->XCArrow)
666 {
667 XFreeCursor(this->DisplayId,this->XCArrow);
668 }
669 if (this->XCCrosshair)
670 {
671 XFreeCursor(this->DisplayId,this->XCCrosshair);
672 }
673 if (this->XCSizeAll)
674 {
675 XFreeCursor(this->DisplayId,this->XCSizeAll);
676 }
677 if (this->XCSizeNS)
678 {
679 XFreeCursor(this->DisplayId,this->XCSizeNS);
680 }
681 if (this->XCSizeWE)
682 {
683 XFreeCursor(this->DisplayId,this->XCSizeWE);
684 }
685 if (this->XCSizeNE)
686 {
687 XFreeCursor(this->DisplayId,this->XCSizeNE);
688 }
689 if (this->XCSizeNW)
690 {
691 XFreeCursor(this->DisplayId,this->XCSizeNW);
692 }
693 if (this->XCSizeSE)
694 {
695 XFreeCursor(this->DisplayId,this->XCSizeSE);
696 }
697 if (this->XCSizeSW)
698 {
699 XFreeCursor(this->DisplayId,this->XCSizeSW);
700 }
701 if (this->XCHand)
702 {
703 XFreeCursor(this->DisplayId,this->XCHand);
704 }
705 }
706
707 this->XCCrosshair = 0;
708 this->XCArrow = 0;
709 this->XCSizeAll = 0;
710 this->XCSizeNS = 0;
711 this->XCSizeWE = 0;
712 this->XCSizeNE = 0;
713 this->XCSizeNW = 0;
714 this->XCSizeSE = 0;
715 this->XCSizeSW = 0;
716 this->XCHand = 0;
717
718 if (this->OwnContext && this->Internal->ContextId)
719 {
720 this->MakeCurrent();
721 // tell each of the renderers that this render window/graphics context
722 // is being removed (the RendererCollection is removed by vtkRenderWindow's
723 // destructor)
724 vtkRenderer* ren;
725 this->Renderers->InitTraversal();
726 for ( ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject());
727 ren != NULL;
728 ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject()) )
729 {
730 ren->SetRenderWindow(NULL);
731 ren->SetRenderWindow(this);
732 }
733
734 if (this->Internal->ContextId)
735 {
736 /* first delete all the old lights */
737 for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+MAX_LIGHTS; cur_light++)
738 {
739 glDisable(static_cast<GLenum>(cur_light));
740 }
741
742 glFinish();
743 glXDestroyContext(this->DisplayId, this->Internal->ContextId);
744 }
745 }
746 this->Internal->ContextId = NULL;
747
748 // then close the old window if we own it
749 if (this->OwnWindow && this->DisplayId && this->WindowId)
750 {
751 XDestroyWindow(this->DisplayId,this->WindowId);
752 this->WindowId = static_cast<Window>(NULL);
753 }
754
755 // if we create the display, we'll delete it
756 if (this->OwnDisplay && this->DisplayId)
757 {
758 XCloseDisplay(this->DisplayId);
759 this->DisplayId = NULL;
760 }
761
762 if (this->Capabilities)
763 {
764 delete[] this->Capabilities;
765 this->Capabilities = 0;
766 }
767
768 // make sure all other code knows we're not mapped anymore
769 this->Mapped = 0;
770
771 }
772
CreateOffScreenWindow(int width,int height)773 void vtkXOpenGLRenderWindow::CreateOffScreenWindow(int width, int height)
774 {
775
776 XVisualInfo *v;
777
778 this->DoubleBuffer = 0;
779
780 // always prefer OSMESA if we built with it
781 #ifdef VTK_OPENGL_HAS_OSMESA
782 if(1)
783 {
784 if (!this->Internal->OffScreenWindow)
785 {
786 this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
787 this->Size[0] = width;
788 this->Size[1] = height;
789 this->OwnWindow = 1;
790 }
791 if (!this->Internal->OffScreenContextId)
792 {
793 this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
794 }
795 this->MakeCurrent();
796 }
797 else
798 #endif
799 {
800 if(!this->CreateHardwareOffScreenWindow(width,height))
801 {
802 // get the default display connection
803 if (!this->DisplayId)
804 {
805 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
806 if (this->DisplayId == NULL)
807 {
808 vtkErrorMacro(<< "bad X server connection. DISPLAY="
809 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
810 abort();
811 }
812 this->OwnDisplay = 1;
813 }
814
815 int v1, v2;
816 glXQueryVersion(this->DisplayId, &v1, &v2);
817
818 // check for GLX 1.3 or greater for Pbuffer offscreen support
819 if(v1 > 1 || (v1 == 1 && v2 >= 3))
820 {
821 if(!this->Internal->PbufferContextId)
822 {
823 // get FBConfig
824 GLXFBConfig* fb = vtkXOpenGLRenderWindowGetDesiredFBConfig(
825 this->DisplayId,this->StereoCapableWindow, this->MultiSamples,
826 this->DoubleBuffer,this->AlphaBitPlanes, GLX_PBUFFER_BIT,
827 this->StencilCapable);
828 if(fb)
829 {
830 XErrorHandler previousHandler = XSetErrorHandler(vtkXOGLPbufferErrorHandler);
831 this->Internal->PbufferContextId =
832 glXCreateNewContext(this->DisplayId, fb[0],
833 GLX_RGBA_TYPE, NULL, true);
834 int atts [] =
835 {
836 GLX_PBUFFER_WIDTH, width,
837 GLX_PBUFFER_HEIGHT, height,
838 0
839 };
840 this->Internal->Pbuffer = glXCreatePbuffer(this->DisplayId,
841 fb[0], atts);
842 glXMakeContextCurrent( this->DisplayId,
843 this->Internal->Pbuffer,
844 this->Internal->Pbuffer,
845 this->Internal->PbufferContextId );
846 XFree(fb);
847 XSetErrorHandler(previousHandler);
848 // failed to allocate Pbuffer, clean up
849 if(PbufferAllocFail)
850 {
851 //vtkglX::DestroyPbuffer(this->DisplayId, this->Internal->Pbuffer);
852 this->Internal->Pbuffer = 0;
853 if(this->Internal->PbufferContextId)
854 glXDestroyContext(this->DisplayId,
855 this->Internal->PbufferContextId);
856 this->Internal->PbufferContextId = NULL;
857 }
858 PbufferAllocFail = 0;
859 }
860 }
861 }
862
863 // GLX 1.3 doesn't exist or failed to allocate Pbuffer
864 // fallback on GLX 1.0 GLXPixmap offscreen support
865 if(!this->Internal->PbufferContextId && !this->Internal->PixmapContextId)
866 {
867 v = this->GetDesiredVisualInfo();
868 this->Internal->PixmapContextId = glXCreateContext(this->DisplayId,
869 v, 0, GL_FALSE);
870 this->Internal->pixmap=
871 XCreatePixmap(this->DisplayId,
872 XRootWindow(this->DisplayId,v->screen),
873 static_cast<unsigned int>(width),
874 static_cast<unsigned int>(height),
875 static_cast<unsigned int>(v->depth));
876
877 this->Internal->PixmapWindowId = glXCreateGLXPixmap(this->DisplayId, v, this->Internal->pixmap);
878 glXMakeCurrent(this->DisplayId,this->Internal->PixmapWindowId,
879 this->Internal->PixmapContextId);
880
881 if(v)
882 {
883 XFree(v);
884 }
885 }
886 } // if not hardware offscreen
887 }
888 this->Mapped = 0;
889 this->Size[0] = width;
890 this->Size[1] = height;
891
892
893 this->MakeCurrent();
894
895 // tell our renderers about us
896 vtkRenderer* ren;
897 for (this->Renderers->InitTraversal();
898 (ren = this->Renderers->GetNextItem());)
899 {
900 ren->SetRenderWindow(0);
901 ren->SetRenderWindow(this);
902 }
903
904 this->OpenGLInit();
905 }
906
DestroyOffScreenWindow()907 void vtkXOpenGLRenderWindow::DestroyOffScreenWindow()
908 {
909
910 // release graphic resources.
911 vtkRenderer *ren;
912 vtkCollectionSimpleIterator rit;
913 this->Renderers->InitTraversal(rit);
914 while ( (ren = this->Renderers->GetNextRenderer(rit)) )
915 {
916 ren->SetRenderWindow(NULL);
917 ren->SetRenderWindow(this);
918 }
919
920
921 #ifdef VTK_OPENGL_HAS_OSMESA
922 if (this->Internal->OffScreenContextId)
923 {
924 OSMesaDestroyContext(this->Internal->OffScreenContextId);
925 this->Internal->OffScreenContextId = NULL;
926 vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
927 this->Internal->OffScreenWindow = NULL;
928 }
929 else
930 #endif
931 {
932 if(this->OffScreenUseFrameBuffer)
933 {
934 this->DestroyHardwareOffScreenWindow();
935 }
936 else
937 {
938 if(this->Internal->PbufferContextId)
939 {
940 glXDestroyPbuffer(this->DisplayId, this->Internal->Pbuffer);
941 this->Internal->Pbuffer = 0;
942 glXDestroyContext(this->DisplayId, this->Internal->PbufferContextId);
943 this->Internal->PbufferContextId = NULL;
944 }
945 else if(this->Internal->PixmapContextId)
946 {
947 glXDestroyGLXPixmap(this->DisplayId, this->Internal->PixmapWindowId);
948 this->Internal->PixmapWindowId = 0;
949 XFreePixmap(this->DisplayId, this->Internal->pixmap);
950 glXDestroyContext( this->DisplayId, this->Internal->PixmapContextId);
951 this->Internal->PixmapContextId = NULL;
952 }
953 }
954 }
955 }
956
ResizeOffScreenWindow(int width,int height)957 void vtkXOpenGLRenderWindow::ResizeOffScreenWindow(int width, int height)
958 {
959 if(!this->OffScreenRendering)
960 {
961 return;
962 }
963
964 // Generally, we simply destroy and recreate the offscreen window/contexts.
965 // However, that's totally unnecessary for OSMesa. So we avoid that.
966 #ifdef VTK_OPENGL_HAS_OSMESA
967 if (this->Internal->OffScreenContextId && this->Internal->OffScreenWindow)
968 {
969 vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
970 this->Internal->OffScreenWindow = NULL;
971
972 // allocate new one.
973 this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
974 this->Size[0] = width;
975 this->Size[1] = height;
976 this->OwnWindow = 1;
977 return;
978 }
979 #endif
980
981 if(this->Internal->PixmapContextId ||
982 this->Internal->PbufferContextId ||
983 this->OffScreenUseFrameBuffer
984 )
985 {
986 this->DestroyOffScreenWindow();
987 this->CreateOffScreenWindow(width, height);
988 }
989 }
990
991
992 // Initialize the window for rendering.
WindowInitialize(void)993 void vtkXOpenGLRenderWindow::WindowInitialize (void)
994 {
995 this->CreateAWindow();
996
997 this->MakeCurrent();
998
999 // tell our renderers about us
1000 vtkRenderer* ren;
1001 for (this->Renderers->InitTraversal();
1002 (ren = this->Renderers->GetNextItem());)
1003 {
1004 ren->SetRenderWindow(0);
1005 ren->SetRenderWindow(this);
1006 }
1007
1008 this->OpenGLInit();
1009 }
1010
1011 // Initialize the rendering window.
Initialize(void)1012 void vtkXOpenGLRenderWindow::Initialize (void)
1013 {
1014 if(!this->OffScreenRendering && !this->Internal->ContextId)
1015 {
1016 // initialize the window
1017 this->WindowInitialize();
1018 }
1019 else if(this->OffScreenRendering &&
1020 ! (this->Internal->PixmapContextId ||
1021 this->Internal->PbufferContextId
1022 #ifdef VTK_OPENGL_HAS_OSMESA
1023 || this->Internal->OffScreenContextId
1024 #endif
1025 || this->OffScreenUseFrameBuffer
1026 ))
1027 {
1028 // initialize offscreen window
1029 int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
1030 int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
1031 this->CreateOffScreenWindow(width, height);
1032 }
1033 }
1034
Finalize(void)1035 void vtkXOpenGLRenderWindow::Finalize (void)
1036 {
1037
1038 // clean up offscreen stuff
1039 this->SetOffScreenRendering(0);
1040
1041 // clean and destroy window
1042 this->DestroyWindow();
1043
1044 }
1045
1046 // Change the window to fill the entire screen.
SetFullScreen(int arg)1047 void vtkXOpenGLRenderWindow::SetFullScreen(int arg)
1048 {
1049 int *temp;
1050
1051 if (this->OffScreenRendering)
1052 {
1053 return;
1054 }
1055
1056 if (this->FullScreen == arg) return;
1057
1058 if (!this->Mapped)
1059 {
1060 this->PrefFullScreen();
1061 return;
1062 }
1063
1064 // set the mode
1065 this->FullScreen = arg;
1066 if (this->FullScreen <= 0)
1067 {
1068 this->Position[0] = this->OldScreen[0];
1069 this->Position[1] = this->OldScreen[1];
1070 this->Size[0] = this->OldScreen[2];
1071 this->Size[1] = this->OldScreen[3];
1072 this->Borders = this->OldScreen[4];
1073 }
1074 else
1075 {
1076 // if window already up get its values
1077 if (this->WindowId)
1078 {
1079 XWindowAttributes attribs;
1080
1081 // Find the current window size
1082 XGetWindowAttributes(this->DisplayId,
1083 this->WindowId, &attribs);
1084
1085 this->OldScreen[2] = attribs.width;
1086 this->OldScreen[3] = attribs.height;;
1087
1088 temp = this->GetPosition();
1089 this->OldScreen[0] = temp[0];
1090 this->OldScreen[1] = temp[1];
1091
1092 this->OldScreen[4] = this->Borders;
1093 this->PrefFullScreen();
1094 }
1095 }
1096
1097 // remap the window
1098 this->WindowRemap();
1099
1100 this->Modified();
1101 }
1102
1103 // Set the preferred window size to full screen.
PrefFullScreen()1104 void vtkXOpenGLRenderWindow::PrefFullScreen()
1105 {
1106 // use full screen
1107 this->Position[0] = 0;
1108 this->Position[1] = 0;
1109
1110 if (this->OffScreenRendering)
1111 {
1112 this->Size[0] = 1280;
1113 this->Size[1] = 1024;
1114 }
1115 else
1116 {
1117 int *size;
1118 size = this->GetScreenSize();
1119 this->Size[0] = size[0];
1120 this->Size[1] = size[1];
1121 }
1122
1123 // don't show borders
1124 this->Borders = 0;
1125 }
1126
1127 // Resize the window.
WindowRemap()1128 void vtkXOpenGLRenderWindow::WindowRemap()
1129 {
1130 // shut everything down
1131 this->Finalize();
1132
1133 // set the default windowid
1134 this->WindowId = this->NextWindowId;
1135 this->NextWindowId = static_cast<Window>(NULL);
1136
1137 // set everything up again
1138 this->Initialize();
1139 }
1140
1141 // Begin the rendering process.
Start(void)1142 void vtkXOpenGLRenderWindow::Start(void)
1143 {
1144 this->Initialize();
1145
1146 // set the current window
1147 this->MakeCurrent();
1148 }
1149
1150
1151 // Specify the size of the rendering window.
SetSize(int width,int height)1152 void vtkXOpenGLRenderWindow::SetSize(int width,int height)
1153 {
1154 if ((this->Size[0] != width)||(this->Size[1] != height))
1155 {
1156 this->Size[0] = width;
1157 this->Size[1] = height;
1158
1159 if (this->Interactor)
1160 {
1161 this->Interactor->SetSize( width, height );
1162 }
1163
1164 if(this->OffScreenRendering)
1165 {
1166 this->ResizeOffScreenWindow(width,height);
1167 }
1168 else if(this->WindowId && this->Mapped)
1169 {
1170 XResizeWindow(this->DisplayId,this->WindowId,
1171 static_cast<unsigned int>(width),
1172 static_cast<unsigned int>(height));
1173 XSync(this->DisplayId,False);
1174 }
1175
1176 this->Modified();
1177 }
1178 }
1179
1180
1181
GetDesiredDepth()1182 int vtkXOpenGLRenderWindow::GetDesiredDepth()
1183 {
1184 XVisualInfo *v;
1185 int depth = 0;
1186
1187 // get the default visual to use
1188 v = this->GetDesiredVisualInfo();
1189
1190 if (v)
1191 {
1192 depth = v->depth;
1193 XFree(v);
1194 }
1195
1196 return depth;
1197 }
1198
1199 // Get a visual from the windowing system.
GetDesiredVisual()1200 Visual *vtkXOpenGLRenderWindow::GetDesiredVisual ()
1201 {
1202 XVisualInfo *v;
1203 Visual *vis=0;
1204
1205 // get the default visual to use
1206 v = this->GetDesiredVisualInfo();
1207
1208 if (v)
1209 {
1210 vis = v->visual;
1211 XFree(v);
1212 }
1213
1214 return vis;
1215 }
1216
1217
1218 // Get a colormap from the windowing system.
GetDesiredColormap()1219 Colormap vtkXOpenGLRenderWindow::GetDesiredColormap ()
1220 {
1221 XVisualInfo *v;
1222
1223 if (this->ColorMap) return this->ColorMap;
1224
1225 // get the default visual to use
1226 v = this->GetDesiredVisualInfo();
1227
1228 if (v)
1229 {
1230 this->ColorMap = XCreateColormap(this->DisplayId,
1231 XRootWindow(this->DisplayId, v->screen),
1232 v->visual, AllocNone);
1233 XFree(v);
1234 }
1235
1236 return this->ColorMap;
1237 }
1238
PrintSelf(ostream & os,vtkIndent indent)1239 void vtkXOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
1240 {
1241 this->Superclass::PrintSelf(os,indent);
1242
1243 os << indent << "ContextId: " << this->Internal->ContextId << "\n";
1244 #ifdef VTK_OPENGL_HAS_OSMESA
1245 os << indent << "OffScreenContextId: " << this->Internal->OffScreenContextId << "\n";
1246 #endif
1247 os << indent << "Color Map: " << this->ColorMap << "\n";
1248 os << indent << "Display Id: " << this->GetDisplayId() << "\n";
1249 os << indent << "Next Window Id: " << this->NextWindowId << "\n";
1250 os << indent << "Window Id: " << this->GetWindowId() << "\n";
1251 }
1252
1253 // the following can be useful for debugging XErrors
1254 // When uncommented (along with the lines in MakeCurrent)
1255 // it will cause a segfault upon an XError instead of
1256 // the normal XError handler
1257 // extern "C" {int vtkXError(Display *display, XErrorEvent *err)
1258 // {
1259 // // cause a segfault
1260 // *(float *)(0x01) = 1.0;
1261 // return 1;
1262 // }}
1263
MakeCurrent()1264 void vtkXOpenGLRenderWindow::MakeCurrent()
1265 {
1266 // when debugging XErrors uncomment the following lines
1267 // if (this->DisplayId)
1268 // {
1269 // XSynchronize(this->DisplayId,1);
1270 // }
1271 // XSetErrorHandler(vtkXError);
1272 #ifdef VTK_OPENGL_HAS_OSMESA
1273
1274 // set the current window
1275 if (this->OffScreenRendering && this->Internal->OffScreenContextId)
1276 {
1277 if (OSMesaMakeCurrent(this->Internal->OffScreenContextId,
1278 this->Internal->OffScreenWindow, GL_UNSIGNED_BYTE,
1279 this->Size[0], this->Size[1]) != GL_TRUE)
1280 {
1281 vtkWarningMacro("failed call to OSMesaMakeCurrent");
1282 }
1283 }
1284 else
1285 #endif
1286 if(this->OffScreenRendering && this->Internal->PbufferContextId)
1287 {
1288 if (((this->Internal->PbufferContextId != glXGetCurrentContext())
1289 || this->ForceMakeCurrent))
1290 {
1291 glXMakeContextCurrent(this->DisplayId, this->Internal->Pbuffer,
1292 this->Internal->Pbuffer,
1293 this->Internal->PbufferContextId);
1294 this->ForceMakeCurrent = 0;
1295 }
1296 }
1297 else
1298 if(this->OffScreenRendering && this->Internal->PixmapContextId)
1299 {
1300 if (((this->Internal->PixmapContextId != glXGetCurrentContext())
1301 || this->ForceMakeCurrent))
1302 {
1303 glXMakeCurrent(this->DisplayId,this->Internal->PixmapWindowId,
1304 this->Internal->PixmapContextId);
1305 this->ForceMakeCurrent = 0;
1306 }
1307 }
1308 else
1309 {
1310 if (this->Internal->ContextId &&
1311 ((this->Internal->ContextId != glXGetCurrentContext())
1312 || this->ForceMakeCurrent))
1313 {
1314 glXMakeCurrent(this->DisplayId,this->WindowId,
1315 this->Internal->ContextId);
1316 this->ForceMakeCurrent = 0;
1317 }
1318 }
1319 }
1320
1321 // ----------------------------------------------------------------------------
1322 // Description:
1323 // Tells if this window is the current OpenGL context for the calling thread.
IsCurrent()1324 bool vtkXOpenGLRenderWindow::IsCurrent()
1325 {
1326 bool result=false;
1327 #ifdef VTK_OPENGL_HAS_OSMESA
1328 if(this->OffScreenRendering && this->Internal->OffScreenContextId)
1329 {
1330 result=this->Internal->OffScreenContextId==OSMesaGetCurrentContext();
1331 }
1332 else
1333 {
1334 #endif
1335 if(this->OffScreenRendering && this->Internal->PixmapContextId)
1336 {
1337 result=this->Internal->PixmapContextId==glXGetCurrentContext();
1338 }
1339 else
1340 {
1341 if(this->Internal->ContextId)
1342 {
1343 result=this->Internal->ContextId==glXGetCurrentContext();
1344 }
1345 }
1346 #ifdef VTK_OPENGL_HAS_OSMESA
1347 }
1348 #endif
1349 return result;
1350 }
1351
SetForceMakeCurrent()1352 void vtkXOpenGLRenderWindow::SetForceMakeCurrent()
1353 {
1354 this->ForceMakeCurrent = 1;
1355 }
1356
1357 int vtkXOpenGLRenderWindowFoundMatch;
1358
1359 extern "C"
1360 {
vtkXOpenGLRenderWindowPredProc(Display * vtkNotUsed (disp),XEvent * event,char * arg)1361 Bool vtkXOpenGLRenderWindowPredProc(Display *vtkNotUsed(disp),
1362 XEvent *event,
1363 char *arg)
1364 {
1365 Window win = (Window)arg;
1366
1367 if (((reinterpret_cast<XAnyEvent *>(event))->window == win) &&
1368 ((event->type == ButtonPress)))
1369 {
1370 vtkXOpenGLRenderWindowFoundMatch = 1;
1371 }
1372
1373 return 0;
1374 }
1375 }
1376
GetGenericContext()1377 void *vtkXOpenGLRenderWindow::GetGenericContext()
1378 {
1379 #if defined(MESA) && defined(VTK_OPENGL_HAS_OSMESA)
1380 if (this->OffScreenRendering && this->Internal->OffScreenContextId)
1381 {
1382 return (void *)this->Internal->OffScreenContextId;
1383 }
1384 else
1385 #endif
1386 if(this->OffScreenRendering && this->Internal->PbufferContextId)
1387 {
1388 return static_cast<void *>(this->Internal->PbufferContextId);
1389 }
1390 else if(this->OffScreenRendering && this->Internal->PixmapContextId)
1391 {
1392 return static_cast<void *>(this->Internal->PixmapContextId);
1393 }
1394 else
1395 {
1396 static GC gc = static_cast<GC>(NULL);
1397 if (!gc)
1398 {
1399 gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0);
1400 }
1401 return static_cast<void *>(gc);
1402 }
1403
1404 }
1405
GetEventPending()1406 int vtkXOpenGLRenderWindow::GetEventPending()
1407 {
1408 XEvent report;
1409
1410 vtkXOpenGLRenderWindowFoundMatch = 0;
1411 if (this->OffScreenRendering)
1412 {
1413 return vtkXOpenGLRenderWindowFoundMatch;
1414 }
1415 XCheckIfEvent(this->DisplayId, &report, vtkXOpenGLRenderWindowPredProc,
1416 reinterpret_cast<char *>(this->WindowId));
1417 return vtkXOpenGLRenderWindowFoundMatch;
1418 }
1419
1420 // Get the size of the screen in pixels
GetScreenSize()1421 int *vtkXOpenGLRenderWindow::GetScreenSize()
1422 {
1423 // get the default display connection
1424 if (!this->DisplayId)
1425 {
1426 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
1427 if (this->DisplayId == NULL)
1428 {
1429 vtkErrorMacro(<< "bad X server connection. DISPLAY="
1430 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
1431 abort();
1432 }
1433 else
1434 {
1435 this->OwnDisplay = 1;
1436 }
1437 }
1438
1439 this->ScreenSize[0] =
1440 XDisplayWidth(this->DisplayId, XDefaultScreen(this->DisplayId));
1441 this->ScreenSize[1] =
1442 XDisplayHeight(this->DisplayId, XDefaultScreen(this->DisplayId));
1443
1444 return this->ScreenSize;
1445 }
1446
1447 // Get the position in screen coordinates (pixels) of the window.
GetPosition(void)1448 int *vtkXOpenGLRenderWindow::GetPosition(void)
1449 {
1450 XWindowAttributes attribs;
1451 int x,y;
1452 Window child;
1453
1454 // if we aren't mapped then just return the ivar
1455 if (!this->Mapped)
1456 {
1457 return this->Position;
1458 }
1459
1460 // Find the current window size
1461 XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs);
1462 x = attribs.x;
1463 y = attribs.y;
1464
1465 XTranslateCoordinates(this->DisplayId,this->WindowId,
1466 XRootWindowOfScreen(XScreenOfDisplay(
1467 this->DisplayId,0)),
1468 x,y,&this->Position[0],&this->Position[1],&child);
1469
1470 return this->Position;
1471 }
1472
1473 // Get this RenderWindow's X display id.
GetDisplayId()1474 Display *vtkXOpenGLRenderWindow::GetDisplayId()
1475 {
1476 vtkDebugMacro(<< "Returning DisplayId of " << static_cast<void *>(this->DisplayId) << "\n");
1477
1478 return this->DisplayId;
1479 }
1480
1481 // Get this RenderWindow's parent X window id.
GetParentId()1482 Window vtkXOpenGLRenderWindow::GetParentId()
1483 {
1484 vtkDebugMacro(<< "Returning ParentId of " << reinterpret_cast<void *>(this->ParentId) << "\n");
1485 return this->ParentId;
1486 }
1487
1488 // Get this RenderWindow's X window id.
GetWindowId()1489 Window vtkXOpenGLRenderWindow::GetWindowId()
1490 {
1491 vtkDebugMacro(<< "Returning WindowId of " << reinterpret_cast<void *>(this->WindowId) << "\n");
1492 return this->WindowId;
1493 }
1494
1495 // Move the window to a new position on the display.
SetPosition(int x,int y)1496 void vtkXOpenGLRenderWindow::SetPosition(int x, int y)
1497 {
1498 // if we aren't mapped then just set the ivars
1499 if (!this->Mapped)
1500 {
1501 if ((this->Position[0] != x)||(this->Position[1] != y))
1502 {
1503 this->Modified();
1504 }
1505 this->Position[0] = x;
1506 this->Position[1] = y;
1507 return;
1508 }
1509
1510 XMoveWindow(this->DisplayId,this->WindowId,x,y);
1511 XSync(this->DisplayId,False);
1512 }
1513
1514 // Sets the parent of the window that WILL BE created.
SetParentId(Window arg)1515 void vtkXOpenGLRenderWindow::SetParentId(Window arg)
1516 {
1517 // if (this->ParentId)
1518 // {
1519 // vtkErrorMacro("ParentId is already set.");
1520 // return;
1521 // }
1522
1523 vtkDebugMacro(<< "Setting ParentId to " << reinterpret_cast<void *>(arg) << "\n");
1524
1525 this->ParentId = arg;
1526 }
1527
1528 // Set this RenderWindow's X window id to a pre-existing window.
SetWindowId(Window arg)1529 void vtkXOpenGLRenderWindow::SetWindowId(Window arg)
1530 {
1531 vtkDebugMacro(<< "Setting WindowId to " << reinterpret_cast<void *>(arg) << "\n");
1532
1533 this->WindowId = arg;
1534
1535 if (this->CursorHidden)
1536 {
1537 this->CursorHidden = 0;
1538 this->HideCursor();
1539 }
1540 }
1541
1542 // Set this RenderWindow's X window id to a pre-existing window.
SetWindowInfo(char * info)1543 void vtkXOpenGLRenderWindow::SetWindowInfo(char *info)
1544 {
1545 int tmp;
1546
1547 // get the default display connection
1548 if (!this->DisplayId)
1549 {
1550 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
1551 if (this->DisplayId == NULL)
1552 {
1553 vtkErrorMacro(<< "bad X server connection. DISPLAY="
1554 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
1555 abort();
1556 }
1557 else
1558 {
1559 this->OwnDisplay = 1;
1560 }
1561 }
1562
1563 sscanf(info,"%i",&tmp);
1564
1565 this->SetWindowId(static_cast<Window>(tmp));
1566 }
1567
1568 // Set this RenderWindow's X window id to a pre-existing window.
SetNextWindowInfo(char * info)1569 void vtkXOpenGLRenderWindow::SetNextWindowInfo(char *info)
1570 {
1571 int tmp;
1572 sscanf(info,"%i",&tmp);
1573
1574 this->SetNextWindowId(static_cast<Window>(tmp));
1575 }
1576
1577 // Sets the X window id of the window that WILL BE created.
SetParentInfo(char * info)1578 void vtkXOpenGLRenderWindow::SetParentInfo(char *info)
1579 {
1580 int tmp;
1581
1582 // get the default display connection
1583 if (!this->DisplayId)
1584 {
1585 this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
1586 if (this->DisplayId == NULL)
1587 {
1588 vtkErrorMacro(<< "bad X server connection. DISPLAY="
1589 << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
1590 abort();
1591 }
1592 else
1593 {
1594 this->OwnDisplay = 1;
1595 }
1596 }
1597
1598 sscanf(info,"%i",&tmp);
1599
1600 this->SetParentId(static_cast<Window>(tmp));
1601 }
1602
SetWindowId(void * arg)1603 void vtkXOpenGLRenderWindow::SetWindowId(void *arg)
1604 {
1605 this->SetWindowId(reinterpret_cast<Window>(arg));
1606 }
SetParentId(void * arg)1607 void vtkXOpenGLRenderWindow::SetParentId(void *arg)
1608 {
1609 this->SetParentId(reinterpret_cast<Window>(arg));
1610 }
1611
ReportCapabilities()1612 const char* vtkXOpenGLRenderWindow::ReportCapabilities()
1613 {
1614 MakeCurrent();
1615
1616 if (!this->DisplayId)
1617 {
1618 return "display id not set";
1619 }
1620
1621 int scrnum = XDefaultScreen(this->DisplayId);
1622 const char *serverVendor = glXQueryServerString(this->DisplayId, scrnum,
1623 GLX_VENDOR);
1624 const char *serverVersion = glXQueryServerString(this->DisplayId, scrnum,
1625 GLX_VERSION);
1626 const char *serverExtensions = glXQueryServerString(this->DisplayId, scrnum,
1627 GLX_EXTENSIONS);
1628 const char *clientVendor = glXGetClientString(this->DisplayId, GLX_VENDOR);
1629 const char *clientVersion = glXGetClientString(this->DisplayId, GLX_VERSION);
1630 const char *clientExtensions = glXGetClientString(this->DisplayId,
1631 GLX_EXTENSIONS);
1632 const char *glxExtensions = glXQueryExtensionsString(this->DisplayId,scrnum);
1633 const char *glVendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
1634 const char *glRenderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
1635 const char *glVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
1636 const char *glExtensions = reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS));
1637
1638 vtksys_ios::ostringstream strm;
1639 strm << "server glx vendor string: " << serverVendor << endl;
1640 strm << "server glx version string: " << serverVersion << endl;
1641 strm << "server glx extensions: " << serverExtensions << endl;
1642 strm << "client glx vendor string: " << clientVendor << endl;
1643 strm << "client glx version string: " << clientVersion << endl;
1644 strm << "client glx extensions: " << clientExtensions << endl;
1645 strm << "glx extensions: " << glxExtensions << endl;
1646 strm << "OpenGL vendor string: " << glVendor << endl;
1647 strm << "OpenGL renderer string: " << glRenderer << endl;
1648 strm << "OpenGL version string: " << glVersion << endl;
1649 strm << "OpenGL extensions: " << glExtensions << endl;
1650 strm << "X Extensions: ";
1651
1652 int n = 0;
1653 char **extlist = XListExtensions(this->DisplayId, &n);
1654
1655 for (int i = 0; i < n; i++)
1656 {
1657 if (i != n-1)
1658 {
1659 strm << extlist[i] << ", ";
1660 }
1661 else
1662 {
1663 strm << extlist[i] << endl;
1664 }
1665 }
1666
1667 delete[] this->Capabilities;
1668
1669 size_t len = strm.str().length();
1670 this->Capabilities = new char[len + 1];
1671 strncpy(this->Capabilities, strm.str().c_str(), len);
1672 this->Capabilities[len] = 0;
1673
1674 return this->Capabilities;
1675 }
1676
SupportsOpenGL()1677 int vtkXOpenGLRenderWindow::SupportsOpenGL()
1678 {
1679 this->MakeCurrent();
1680 if (!this->DisplayId)
1681 {
1682 return 0;
1683 }
1684
1685 int value = 0;
1686 XVisualInfo *v = this->GetDesiredVisualInfo();
1687 if (v)
1688 {
1689 glXGetConfig(this->DisplayId, v, GLX_USE_GL, &value);
1690 XFree(v);
1691 }
1692
1693 return value;
1694 }
1695
1696
IsDirect()1697 int vtkXOpenGLRenderWindow::IsDirect()
1698 {
1699 this->MakeCurrent();
1700 this->UsingHardware = 0;
1701 if (this->OffScreenRendering && this->Internal->PbufferContextId)
1702 {
1703 this->UsingHardware = glXIsDirect(this->DisplayId,
1704 this->Internal->PbufferContextId) ? 1:0;
1705 }
1706 else if (this->OffScreenRendering && this->Internal->PixmapContextId)
1707 {
1708 this->UsingHardware = glXIsDirect(this->DisplayId,
1709 this->Internal->PixmapContextId) ? 1:0;
1710 }
1711 else if (this->DisplayId && this->Internal->ContextId)
1712 {
1713 this->UsingHardware = glXIsDirect(this->DisplayId,
1714 this->Internal->ContextId) ? 1:0;
1715 }
1716 return this->UsingHardware;
1717 }
1718
1719
SetWindowName(const char * cname)1720 void vtkXOpenGLRenderWindow::SetWindowName(const char * cname)
1721 {
1722 char *name = new char[ strlen(cname)+1 ];
1723 strcpy(name, cname);
1724 XTextProperty win_name_text_prop;
1725
1726 this->vtkOpenGLRenderWindow::SetWindowName( name );
1727
1728 if (this->Mapped)
1729 {
1730 if( XStringListToTextProperty( &name, 1, &win_name_text_prop ) == 0 )
1731 {
1732 XFree (win_name_text_prop.value);
1733 vtkWarningMacro(<< "Can't rename window");
1734 delete [] name;
1735 return;
1736 }
1737
1738 XSetWMName( this->DisplayId, this->WindowId, &win_name_text_prop );
1739 XSetWMIconName( this->DisplayId, this->WindowId, &win_name_text_prop );
1740 XFree (win_name_text_prop.value);
1741 }
1742 delete [] name;
1743 }
1744
1745
1746 // Specify the X window id to use if a WindowRemap is done.
SetNextWindowId(Window arg)1747 void vtkXOpenGLRenderWindow::SetNextWindowId(Window arg)
1748 {
1749 vtkDebugMacro(<< "Setting NextWindowId to " << reinterpret_cast<void *>(arg) << "\n");
1750
1751 this->NextWindowId = arg;
1752 }
1753
SetNextWindowId(void * arg)1754 void vtkXOpenGLRenderWindow::SetNextWindowId(void *arg)
1755 {
1756 this->SetNextWindowId(reinterpret_cast<Window>(arg));
1757 }
1758
1759
1760 // Set the X display id for this RenderWindow to use to a pre-existing
1761 // X display id.
SetDisplayId(Display * arg)1762 void vtkXOpenGLRenderWindow::SetDisplayId(Display *arg)
1763 {
1764 vtkDebugMacro(<< "Setting DisplayId to " << static_cast<void *>(arg) << "\n");
1765
1766 this->DisplayId = arg;
1767 this->OwnDisplay = 0;
1768
1769 }
SetDisplayId(void * arg)1770 void vtkXOpenGLRenderWindow::SetDisplayId(void *arg)
1771 {
1772 this->SetDisplayId(static_cast<Display *>(arg));
1773 this->OwnDisplay = 0;
1774 }
1775
Render()1776 void vtkXOpenGLRenderWindow::Render()
1777 {
1778 XWindowAttributes attribs;
1779
1780 // To avoid the expensive XGetWindowAttributes call,
1781 // compute size at the start of a render and use
1782 // the ivar other times.
1783 if (this->Mapped)
1784 {
1785 // Find the current window size
1786 XGetWindowAttributes(this->DisplayId,
1787 this->WindowId, &attribs);
1788
1789 this->Size[0] = attribs.width;
1790 this->Size[1] = attribs.height;
1791 }
1792
1793 // Now do the superclass stuff
1794 this->vtkOpenGLRenderWindow::Render();
1795 }
1796
1797 //----------------------------------------------------------------------------
HideCursor()1798 void vtkXOpenGLRenderWindow::HideCursor()
1799 {
1800 static char blankBits[] = {
1801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
1805
1806 static XColor black = { 0, 0, 0, 0, 0, 0 };
1807
1808 if (!this->DisplayId || !this->WindowId)
1809 {
1810 this->CursorHidden = 1;
1811 }
1812 else if (!this->CursorHidden)
1813 {
1814 Pixmap blankPixmap = XCreateBitmapFromData(this->DisplayId,
1815 this->WindowId,
1816 blankBits, 16, 16);
1817
1818 Cursor blankCursor = XCreatePixmapCursor(this->DisplayId, blankPixmap,
1819 blankPixmap, &black, &black,
1820 7, 7);
1821
1822 XDefineCursor(this->DisplayId, this->WindowId, blankCursor);
1823
1824 XFreePixmap(this->DisplayId, blankPixmap);
1825
1826 this->CursorHidden = 1;
1827 }
1828 }
1829
1830 //----------------------------------------------------------------------------
ShowCursor()1831 void vtkXOpenGLRenderWindow::ShowCursor()
1832 {
1833 if (!this->DisplayId || !this->WindowId)
1834 {
1835 this->CursorHidden = 0;
1836 }
1837 else if (this->CursorHidden)
1838 {
1839 XUndefineCursor(this->DisplayId, this->WindowId);
1840 this->CursorHidden = 0;
1841 }
1842 }
1843
1844
1845 //============================================================================
1846 // Stuff above this is almost a mirror of vtkXOpenGLRenderWindow.
1847 // The code specific to OpenGL Off-Screen stuff may eventually be
1848 // put in a supper class so this whole file could just be included
1849 // (mangled) from vtkXOpenGLRenderWindow like the other OpenGL classes.
1850 //============================================================================
1851
SetOffScreenRendering(int i)1852 void vtkXOpenGLRenderWindow::SetOffScreenRendering(int i)
1853 {
1854 if (this->OffScreenRendering == i)
1855 {
1856 return;
1857 }
1858
1859 // invoke super
1860 this->vtkRenderWindow::SetOffScreenRendering(i);
1861
1862 if(this->OffScreenRendering)
1863 {
1864 this->Internal->ScreenDoubleBuffer = this->DoubleBuffer;
1865 this->DoubleBuffer = 0;
1866 if(this->Mapped)
1867 {
1868 this->DestroyWindow();
1869 }
1870
1871 // delay initialization until Render
1872 }
1873 else
1874 {
1875 this->DestroyOffScreenWindow();
1876
1877 this->DoubleBuffer = this->Internal->ScreenDoubleBuffer;
1878
1879 // reset size based on screen window
1880 if(this->Mapped && this->WindowId)
1881 {
1882 XWindowAttributes a;
1883 XGetWindowAttributes(this->DisplayId, this->WindowId, &a);
1884
1885 this->Size[0] = a.width;
1886 this->Size[1] = a.height;
1887 }
1888 // force context switch as we might be going from osmesa to onscreen
1889 this->SetForceMakeCurrent();
1890 }
1891 }
1892
1893 // This probably has been moved to superclass.
GetGenericWindowId()1894 void *vtkXOpenGLRenderWindow::GetGenericWindowId()
1895 {
1896 #ifdef VTK_OPENGL_HAS_OSMESA
1897 if (this->OffScreenRendering && this->Internal->OffScreenWindow)
1898 {
1899 return reinterpret_cast<void*>(this->Internal->OffScreenWindow);
1900 }
1901 else
1902 #endif
1903 if(this->OffScreenRendering)
1904 {
1905 return reinterpret_cast<void*>(this->Internal->PixmapWindowId);
1906 }
1907 return reinterpret_cast<void*>(this->WindowId);
1908 }
1909
SetCurrentCursor(int shape)1910 void vtkXOpenGLRenderWindow::SetCurrentCursor(int shape)
1911 {
1912 if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) )
1913 {
1914 return;
1915 }
1916 this->Superclass::SetCurrentCursor(shape);
1917 if (!this->DisplayId || !this->WindowId)
1918 {
1919 return;
1920 }
1921
1922 if (shape == VTK_CURSOR_DEFAULT)
1923 {
1924 XUndefineCursor(this->DisplayId,this->WindowId);
1925 return;
1926 }
1927
1928 switch (shape)
1929 {
1930 case VTK_CURSOR_CROSSHAIR:
1931 if (!this->XCCrosshair)
1932 {
1933 this->XCCrosshair = XCreateFontCursor(this->DisplayId, XC_crosshair);
1934 }
1935 XDefineCursor(this->DisplayId, this->WindowId, this->XCCrosshair);
1936 break;
1937 case VTK_CURSOR_ARROW:
1938 if (!this->XCArrow)
1939 {
1940 this->XCArrow = XCreateFontCursor(this->DisplayId, XC_top_left_arrow);
1941 }
1942 XDefineCursor(this->DisplayId, this->WindowId, this->XCArrow);
1943 break;
1944 case VTK_CURSOR_SIZEALL:
1945 if (!this->XCSizeAll)
1946 {
1947 this->XCSizeAll = XCreateFontCursor(this->DisplayId, XC_fleur);
1948 }
1949 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeAll);
1950 break;
1951 case VTK_CURSOR_SIZENS:
1952 if (!this->XCSizeNS)
1953 {
1954 this->XCSizeNS = XCreateFontCursor(this->DisplayId,
1955 XC_sb_v_double_arrow);
1956 }
1957 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNS);
1958 break;
1959 case VTK_CURSOR_SIZEWE:
1960 if (!this->XCSizeWE)
1961 {
1962 this->XCSizeWE = XCreateFontCursor(this->DisplayId,
1963 XC_sb_h_double_arrow);
1964 }
1965 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeWE);
1966 break;
1967 case VTK_CURSOR_SIZENE:
1968 if (!this->XCSizeNE)
1969 {
1970 this->XCSizeNE = XCreateFontCursor(this->DisplayId,
1971 XC_top_right_corner);
1972 }
1973 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNE);
1974 break;
1975 case VTK_CURSOR_SIZENW:
1976 if (!this->XCSizeNW)
1977 {
1978 this->XCSizeNW = XCreateFontCursor(this->DisplayId,
1979 XC_top_left_corner);
1980 }
1981 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNW);
1982 break;
1983 case VTK_CURSOR_SIZESE:
1984 if (!this->XCSizeSE)
1985 {
1986 this->XCSizeSE = XCreateFontCursor(this->DisplayId,
1987 XC_bottom_right_corner);
1988 }
1989 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSE);
1990 break;
1991 case VTK_CURSOR_SIZESW:
1992 if (!this->XCSizeSW)
1993 {
1994 this->XCSizeSW = XCreateFontCursor(this->DisplayId,
1995 XC_bottom_left_corner);
1996 }
1997 XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSW);
1998 break;
1999 case VTK_CURSOR_HAND:
2000 if (!this->XCHand)
2001 {
2002 this->XCHand = XCreateFontCursor(this->DisplayId,
2003 XC_hand1);
2004 }
2005 XDefineCursor(this->DisplayId, this->WindowId, this->XCHand);
2006 break;
2007 }
2008 }
2009