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