vtkXOpenGLRenderWindow.cxx 55.2 KB
Newer Older
Ken Martin's avatar
Ken Martin committed
1 2
/*=========================================================================

Mathieu Malaterre's avatar
Mathieu Malaterre committed
3 4
  Program:   Visualization Toolkit
  Module:    vtkXOpenGLRenderWindow.cxx
Ken Martin's avatar
Ken Martin committed
5

Mathieu Malaterre's avatar
Mathieu Malaterre committed
6 7 8
  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
Ken Martin's avatar
Ken Martin committed
9

Mathieu Malaterre's avatar
Mathieu Malaterre committed
10 11 12
     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.
Ken Martin's avatar
Ken Martin committed
13 14

=========================================================================*/
15

Ken Martin's avatar
Ken Martin committed
16 17 18 19 20 21 22
#include "vtkXOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLProperty.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLCamera.h"
#include "vtkOpenGLLight.h"
#include "vtkOpenGLActor.h"
23
#include "vtkXRenderWindowInteractor.h"
24 25

#include "vtkOpenGL.h"
26

27 28
// Define GLX_GLXEXT_LEGACY to prevent glx.h from including the glxext.h
// provided by the system.
David C. Lonie's avatar
David C. Lonie committed
29 30 31 32 33 34 35 36 37
//#define GLX_GLXEXT_LEGACY

// New Workaround:
// The GLX_GLXEXT_LEGACY definition was added to work around system glxext.h
// files that used the GLintptr and GLsizeiptr types, but did not define them.
// However, this broke multisampling (See PR#15433). Instead of using that
// define, we're just defining the missing typedefs here.
typedef ptrdiff_t GLintptr;
typedef ptrdiff_t GLsizeiptr;
38
#include "GL/glx.h"
39

Clinton Stimpson's avatar
 
Clinton Stimpson committed
40
#include "vtkgl.h"
Ken Martin's avatar
Ken Martin committed
41

42
#include "vtkToolkits.h"
43

44
#ifdef VTK_USE_OSMESA
45
# include <GL/osmesa.h>
46
#endif
47

48
#include "vtkCommand.h"
49
#include "vtkIdList.h"
50 51
#include "vtkObjectFactory.h"
#include "vtkRendererCollection.h"
Clinton Stimpson's avatar
 
Clinton Stimpson committed
52
#include "vtkOpenGLExtensionManager.h"
Ken Martin's avatar
Ken Martin committed
53

54 55
#include "vtksys/SystemTools.hxx"

56
#include <sstream>
57

58 59 60 61
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>

62 63 64 65 66 67 68 69 70
class vtkXOpenGLRenderWindow;
class vtkRenderWindow;
class vtkXOpenGLRenderWindowInternal
{
  friend class vtkXOpenGLRenderWindow;
private:
  vtkXOpenGLRenderWindowInternal(vtkRenderWindow*);

  GLXContext ContextId;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
71 72 73 74

  // so we basically have 4 methods here for handling drawables
  // how about abstracting this a bit?

Clinton Stimpson's avatar
 
Clinton Stimpson committed
75 76 77 78 79
  // support for Pixmap based offscreen rendering
  Pixmap pixmap;
  GLXContext PixmapContextId;
  Window PixmapWindowId;

Clinton Stimpson's avatar
 
Clinton Stimpson committed
80

Clinton Stimpson's avatar
 
Clinton Stimpson committed
81 82 83 84
  // support for Pbuffer based offscreen rendering
  GLXContext PbufferContextId;
  vtkglX::GLXPbuffer Pbuffer;

Clinton Stimpson's avatar
 
Clinton Stimpson committed
85 86 87
  // store previous settings of on screen window
  int ScreenDoubleBuffer;
  int ScreenMapped;
88

89
#if defined( VTK_USE_OSMESA )
90 91 92
  // OffScreen stuff
  OSMesaContext OffScreenContextId;
  void *OffScreenWindow;
93
#endif
94 95 96 97 98 99
};

vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal(
  vtkRenderWindow *rw)
{
  this->ContextId = NULL;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
100 101 102

  this->PixmapContextId = NULL;
  this->PixmapWindowId = 0;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
103 104 105

  this->PbufferContextId = NULL;
  this->Pbuffer = 0;
106

Clinton Stimpson's avatar
 
Clinton Stimpson committed
107 108
  this->ScreenMapped = rw->GetMapped();
  this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
109

110
  // OpenGL specific
111
#ifdef VTK_USE_OSMESA
112 113
  this->OffScreenContextId = NULL;
  this->OffScreenWindow = NULL;
Andy Cedilnik's avatar
Andy Cedilnik committed
114
#endif
115 116
}

Brad King's avatar
Brad King committed
117
vtkStandardNewMacro(vtkXOpenGLRenderWindow);
Ken Martin's avatar
Ken Martin committed
118 119 120

#define MAX_LIGHTS 8

121
#ifdef VTK_USE_OSMESA
122
// a couple of routines for offscreen rendering
123
void vtkOSMesaDestroyWindow(void *Window)
124 125 126 127
{
  free(Window);
}

128
void *vtkOSMesaCreateWindow(int width, int height)
129 130 131 132 133
{
  return malloc(width*height*4);
}
#endif

Clinton Stimpson's avatar
 
Clinton Stimpson committed
134
vtkglX::GLXFBConfig* vtkXOpenGLRenderWindowTryForFBConfig(Display *DisplayId,
135 136 137 138
                                                          int drawable_type,
                                                          int doublebuff,
                                                          int stereo,
                                                          int multisamples,
139 140
                                                          int alphaBitPlanes,
                                                          int stencil)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
{
  int           index;
  static int    attributes[50];

  // setup the default stuff we ask for
  index = 0;
  attributes[index++] = vtkglX::DRAWABLE_TYPE;
  attributes[index++] = drawable_type;
  attributes[index++] = vtkglX::RENDER_TYPE;
  attributes[index++] = vtkglX::RGBA_BIT;
  attributes[index++] = GLX_RED_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_GREEN_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_BLUE_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_DEPTH_SIZE;
  attributes[index++] = 1;
  if (alphaBitPlanes)
    {
    attributes[index++] = GLX_ALPHA_SIZE;
    attributes[index++] = 1;
    }
  if (doublebuff)
    {
    attributes[index++] = GLX_DOUBLEBUFFER;
167
    attributes[index++] = True;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
168
    }
169
  if (stencil)
170
    {
171 172 173
    attributes[index++] = GLX_STENCIL_SIZE;
    attributes[index++] = 8;
    }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
174 175 176 177
  if (stereo)
    {
    // also try for STEREO
    attributes[index++] = GLX_STEREO;
178
    attributes[index++] = True;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
179 180 181 182 183 184 185 186 187 188
    }
  if (multisamples)
    {
#ifdef GLX_SAMPLE_BUFFERS_SGIS
    attributes[index++] = GLX_SAMPLE_BUFFERS_SGIS;
    attributes[index++] = 1;
    attributes[index++] = GLX_SAMPLES_SGIS;
    attributes[index++] = multisamples;
#endif
    }
189

Clinton Stimpson's avatar
 
Clinton Stimpson committed
190 191
  attributes[index++] = None;
  int tmp;
192
  vtkglX::GLXFBConfig* fb = vtkglX::ChooseFBConfig(DisplayId,
Francois Bertel's avatar
Francois Bertel committed
193
                                                   XDefaultScreen(DisplayId),
194
                                                   attributes, &tmp);
Clinton Stimpson's avatar
 
Clinton Stimpson committed
195 196 197
  return fb;
}

Ken Martin's avatar
Ken Martin committed
198
XVisualInfo *vtkXOpenGLRenderWindowTryForVisual(Display *DisplayId,
199 200
                                                int doublebuff, int stereo,
                                                int multisamples,
201 202
                                                int alphaBitPlanes,
                                                int stencil)
Ken Martin's avatar
Ken Martin committed
203 204
{
  int           index;
205
  static int    attributes[50];
Ken Martin's avatar
Ken Martin committed
206 207 208 209 210 211 212 213 214 215 216 217

  // setup the default stuff we ask for
  index = 0;
  attributes[index++] = GLX_RGBA;
  attributes[index++] = GLX_RED_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_GREEN_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_BLUE_SIZE;
  attributes[index++] = 1;
  attributes[index++] = GLX_DEPTH_SIZE;
  attributes[index++] = 1;
218 219 220 221 222
  if (alphaBitPlanes)
    {
    attributes[index++] = GLX_ALPHA_SIZE;
    attributes[index++] = 1;
    }
Ken Martin's avatar
Ken Martin committed
223 224 225
  if (doublebuff)
    {
    attributes[index++] = GLX_DOUBLEBUFFER;
226
    attributes[index++] = True;
Ken Martin's avatar
Ken Martin committed
227
    }
228 229 230 231 232
  if (stencil)
    {
    attributes[index++] = GLX_STENCIL_SIZE;
    attributes[index++] = 8;
    }
Ken Martin's avatar
Ken Martin committed
233 234 235 236
  if (stereo)
    {
    // also try for STEREO
    attributes[index++] = GLX_STEREO;
237
    attributes[index++] = True;
Ken Martin's avatar
Ken Martin committed
238 239 240 241 242 243 244 245 246 247
    }
  if (multisamples)
    {
#ifdef GLX_SAMPLE_BUFFERS_SGIS
    attributes[index++] = GLX_SAMPLE_BUFFERS_SGIS;
    attributes[index++] = 1;
    attributes[index++] = GLX_SAMPLES_SGIS;
    attributes[index++] = multisamples;
#endif
    }
248

Ken Martin's avatar
Ken Martin committed
249 250
  attributes[index++] = None;

Francois Bertel's avatar
Francois Bertel committed
251
  return glXChooseVisual(DisplayId, XDefaultScreen(DisplayId), attributes );
Ken Martin's avatar
Ken Martin committed
252 253
}

Clinton Stimpson's avatar
 
Clinton Stimpson committed
254
vtkglX::GLXFBConfig *vtkXOpenGLRenderWindowGetDesiredFBConfig(
255 256 257
  Display *DisplayId,
  int &win_stereo,
  int &win_multisamples,
258
  int &win_doublebuffer,
259
  int &win_alphaplanes,
260 261
  int drawable_type,
  int &stencil)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
262 263 264 265
{
  vtkglX::GLXFBConfig   *fbc = NULL;
  int           multi;
  int           stereo = 0;
266

Clinton Stimpson's avatar
 
Clinton Stimpson committed
267 268 269 270 271
  // try every possibility stoping when we find one that works
  for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
    {
    for (multi = win_multisamples; !fbc && multi >= 0; multi--)
      {
272
      if (fbc)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
273 274 275 276
        {
        XFree(fbc);
        }
      fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
277 278 279
                                                 drawable_type,
                                                 win_doublebuffer,
                                                 stereo, multi,
280 281
                                                 win_alphaplanes,
                                                 stencil);
Clinton Stimpson's avatar
 
Clinton Stimpson committed
282 283 284 285 286 287 288 289 290 291 292
      if (fbc && win_stereo && !stereo)
        {
        // requested a stereo capable window but we could not get one
        win_stereo = 0;
        }
      }
    }
  for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
    {
    for (multi = win_multisamples; !fbc && multi >= 0; multi--)
      {
293
      if (fbc)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
294 295 296 297
        {
        XFree(fbc);
        }
      fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
298
                                                 drawable_type,
299
                                                 !win_doublebuffer,
300
                                                 stereo, multi,
301 302
                                                 win_alphaplanes,
                                                 stencil);
Clinton Stimpson's avatar
 
Clinton Stimpson committed
303 304 305 306 307 308 309 310 311 312 313 314 315 316
      if (fbc)
        {
        win_doublebuffer = !win_doublebuffer;
        }
      if (fbc && win_stereo && !stereo)
        {
        // requested a stereo capable window but we could not get one
        win_stereo = 0;
        }
      }
    }
  return ( fbc );
}

Ken Martin's avatar
Ken Martin committed
317 318 319
XVisualInfo *vtkXOpenGLRenderWindow::GetDesiredVisualInfo()
{
  XVisualInfo   *v = NULL;
320
  int           alpha;
Ken Martin's avatar
Ken Martin committed
321 322
  int           multi;
  int           stereo = 0;
323 324
  int           stencil;

325
  // get the default display connection
Ken Martin's avatar
Ken Martin committed
326 327
  if (!this->DisplayId)
    {
328
    this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
329 330

    if (this->DisplayId == NULL)
Ken Martin's avatar
Ken Martin committed
331
      {
332
      vtkErrorMacro(<< "bad X server connection. DISPLAY="
Ben Boeckel's avatar
Ben Boeckel committed
333 334
        << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
      abort();
Ken Martin's avatar
Ken Martin committed
335
      }
336

Ken Martin's avatar
Ken Martin committed
337 338 339 340
    this->OwnDisplay = 1;
    }

  // try every possibility stoping when we find one that works
341
  for (stencil = this->StencilCapable; !v && stencil >= 0; stencil--)
Ken Martin's avatar
Ken Martin committed
342
    {
343
    for (alpha = this->AlphaBitPlanes; !v && alpha >= 0; alpha--)
Ken Martin's avatar
Ken Martin committed
344
      {
345
      for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
346
        {
347
        for (multi = this->MultiSamples; !v && multi >= 0; multi--)
348
          {
349
          if (v)
350 351 352 353
            {
            XFree(v);
            }
          v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
354 355
                                                 this->DoubleBuffer,
                                                 stereo, multi, alpha,
356 357 358 359 360 361 362 363
                                                 stencil);
          if (v)
            {
            this->StereoCapableWindow = stereo;
            this->MultiSamples = multi;
            this->AlphaBitPlanes = alpha;
            this->StencilCapable = stencil;
            }
364
          }
365
        }
Ken Martin's avatar
Ken Martin committed
366 367
      }
    }
368
  for (stencil = this->StencilCapable; !v && stencil >= 0; stencil--)
Ken Martin's avatar
Ken Martin committed
369
    {
370
    for (alpha = this->AlphaBitPlanes; !v && alpha >= 0; alpha--)
Ken Martin's avatar
Ken Martin committed
371
      {
372
      for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
373
        {
374
        for (multi = this->MultiSamples; !v && multi >= 0; multi--)
375
          {
376
          v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
377
                                                 !this->DoubleBuffer,
378 379 380 381 382 383 384 385 386 387
                                                 stereo, multi, alpha,
                                                 stencil);
          if (v)
            {
            this->DoubleBuffer = !this->DoubleBuffer;
            this->StereoCapableWindow = stereo;
            this->MultiSamples = multi;
            this->AlphaBitPlanes = alpha;
            this->StencilCapable = stencil;
            }
388
          }
389
        }
Ken Martin's avatar
Ken Martin committed
390 391
      }
    }
392
  if (!v)
Ken Martin's avatar
Ken Martin committed
393 394 395 396 397 398 399 400
    {
    vtkErrorMacro(<< "Could not find a decent visual\n");
    }
  return ( v );
}

vtkXOpenGLRenderWindow::vtkXOpenGLRenderWindow()
{
401
  this->ParentId = static_cast<Window>(NULL);
Ken Martin's avatar
Ken Martin committed
402 403 404 405
  this->ScreenSize[0] = 0;
  this->ScreenSize[1] = 0;
  this->OwnDisplay = 0;
  this->CursorHidden = 0;
406
  this->ForceMakeCurrent = 0;
407
  this->UsingHardware = 0;
408 409 410 411
  this->DisplayId = static_cast<Display *>(NULL);
  this->WindowId = static_cast<Window>(NULL);
  this->NextWindowId = static_cast<Window>(NULL);
  this->ColorMap = static_cast<Colormap>(0);
Ken Martin's avatar
Ken Martin committed
412
  this->OwnWindow = 0;
413

414
  this->Internal = new vtkXOpenGLRenderWindowInternal(this);
Ken Martin's avatar
Ken Martin committed
415

416 417 418 419 420 421 422 423 424 425
  this->XCCrosshair = 0;
  this->XCArrow     = 0;
  this->XCSizeAll   = 0;
  this->XCSizeNS    = 0;
  this->XCSizeWE    = 0;
  this->XCSizeNE    = 0;
  this->XCSizeNW    = 0;
  this->XCSizeSE    = 0;
  this->XCSizeSW    = 0;
  this->XCHand      = 0;
426 427

  this->Capabilities = 0;
428

Ken Martin's avatar
Ken Martin committed
429 430 431 432 433
}

// free up memory & close the window
vtkXOpenGLRenderWindow::~vtkXOpenGLRenderWindow()
{
434
  // close-down all system-specific drawing resources
435
  this->Finalize();
436 437 438 439 440

  vtkRenderer *ren;
  vtkCollectionSimpleIterator rit;
  this->Renderers->InitTraversal(rit);
  while ( (ren = this->Renderers->GetNextRenderer(rit)) )
441 442 443
    {
    ren->SetRenderWindow(NULL);
    }
Ken Martin's avatar
Ken Martin committed
444

445
  delete this->Internal;
Ken Martin's avatar
Ken Martin committed
446 447 448
}

// End the rendering process and display the image.
449
void vtkXOpenGLRenderWindow::Frame()
Ken Martin's avatar
Ken Martin committed
450 451
{
  this->MakeCurrent();
452 453
  if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers
      && this->WindowId!=0)
Ken Martin's avatar
Ken Martin committed
454 455 456 457
    {
    glXSwapBuffers(this->DisplayId, this->WindowId);
    vtkDebugMacro(<< " glXSwapBuffers\n");
    }
458 459 460 461
  else
    {
    glFlush();
    }
Ken Martin's avatar
Ken Martin committed
462
}
463

464 465 466 467 468 469 470 471 472
bool vtkXOpenGLRenderWindow::InitializeFromCurrentContext()
{
  GLXContext currentContext = glXGetCurrentContext();
  if (currentContext != NULL)
    {
    this->SetDisplayId((void*)glXGetCurrentDisplay());
    this->SetWindowId((void*)glXGetCurrentDrawable());
    this->Internal->ContextId = currentContext;
    this->OpenGLInit();
473
    this->OwnContext = 0;
474 475 476 477 478
    return true;
    }
  return false;
}

Ken Martin's avatar
Ken Martin committed
479 480 481 482 483 484
//
// Set the variable that indicates that we want a stereo capable window
// be created. This method can only be called before a window is realized.
//
void vtkXOpenGLRenderWindow::SetStereoCapableWindow(int capable)
{
485 486
  if (!this->Internal->ContextId && !this->Internal->PixmapContextId
      && !this->Internal->PbufferContextId
487
#if defined( VTK_USE_OSMESA )
488
      && !this->Internal->OffScreenContextId
Clinton Stimpson's avatar
 
Clinton Stimpson committed
489 490
#endif
    )
Ken Martin's avatar
Ken Martin committed
491
    {
Ken Martin's avatar
Ken Martin committed
492
    vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
Ken Martin's avatar
Ken Martin committed
493 494 495 496 497 498 499 500
    }
  else
    {
    vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
                    << "before the window is realized, i.e. before a render.");
    }
}

Clinton Stimpson's avatar
 
Clinton Stimpson committed
501
static int PbufferAllocFail = 0;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
502
extern "C"
Clinton Stimpson's avatar
 
Clinton Stimpson committed
503
{
504
  int vtkXOGLPbufferErrorHandler(Display*, XErrorEvent*)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
505 506 507 508
  {
    PbufferAllocFail = 1;
    return 1;
  }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
509
}
Clinton Stimpson's avatar
 
Clinton Stimpson committed
510 511

void vtkXOpenGLRenderWindow::CreateAWindow()
Ken Martin's avatar
Ken Martin committed
512
{
513 514 515 516 517 518 519 520
  XVisualInfo  *v, matcher;
  XSetWindowAttributes  attr;
  int x, y, width, height, nItems;
  XWindowAttributes winattr;
  XSizeHints xsh;

  xsh.flags = USSize;
  if ((this->Position[0] >= 0)&&(this->Position[1] >= 0))
Ken Martin's avatar
Ken Martin committed
521
    {
522 523 524 525
    xsh.flags |= USPosition;
    xsh.x =  static_cast<int>(this->Position[0]);
    xsh.y =  static_cast<int>(this->Position[1]);
    }
526

527 528 529 530 531 532 533 534
  x = ((this->Position[0] >= 0) ? this->Position[0] : 5);
  y = ((this->Position[1] >= 0) ? this->Position[1] : 5);
  width = ((this->Size[0] > 0) ? this->Size[0] : 300);
  height = ((this->Size[1] > 0) ? this->Size[1] : 300);

  xsh.width  = width;
  xsh.height = height;

535
  // get the default display connection
536 537 538
  if (!this->DisplayId)
    {
    this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
539
    if (this->DisplayId == NULL)
540
      {
541
      vtkErrorMacro(<< "bad X server connection. DISPLAY="
Ben Boeckel's avatar
Ben Boeckel committed
542 543
        << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
      abort();
Ken Martin's avatar
Ken Martin committed
544
      }
545 546 547 548 549 550 551 552 553
    this->OwnDisplay = 1;
    }

  attr.override_redirect = False;
  if (this->Borders == 0.0)
    {
    attr.override_redirect = True;
    }

554
  // create our own window ?
555 556 557 558 559
  this->OwnWindow = 0;
  if (!this->WindowId)
    {
    v = this->GetDesiredVisualInfo();
    this->ColorMap = XCreateColormap(this->DisplayId,
Francois Bertel's avatar
Francois Bertel committed
560 561
                                     XRootWindow(this->DisplayId,v->screen),
                                     v->visual, AllocNone);
562

563 564 565 566
    attr.background_pixel = 0;
    attr.border_pixel = 0;
    attr.colormap = this->ColorMap;
    attr.event_mask = StructureNotifyMask | ExposureMask;
567

568 569
    // get a default parent if one has not been set.
    if (! this->ParentId)
570
      {
Francois Bertel's avatar
Francois Bertel committed
571
      this->ParentId = XRootWindow(this->DisplayId, v->screen);
572
      }
573
    this->WindowId =
574 575
      XCreateWindow(this->DisplayId,
                    this->ParentId,
Francois Bertel's avatar
Francois Bertel committed
576 577 578
                    x, y, static_cast<unsigned int>(width),
                    static_cast<unsigned int>(height), 0, v->depth,
                    InputOutput, v->visual,
579 580
                    CWBackPixel | CWBorderPixel | CWColormap |
                    CWOverrideRedirect | CWEventMask,
581 582 583 584 585 586 587 588 589 590 591 592
                    &attr);
    XStoreName(this->DisplayId, this->WindowId, this->WindowName);
    XSetNormalHints(this->DisplayId,this->WindowId,&xsh);
    this->OwnWindow = 1;
    }
  else
    {
    XChangeWindowAttributes(this->DisplayId,this->WindowId,
                            CWOverrideRedirect, &attr);
    XGetWindowAttributes(this->DisplayId,
                         this->WindowId,&winattr);
    matcher.visualid = XVisualIDFromVisual(winattr.visual);
Francois Bertel's avatar
Francois Bertel committed
593
    matcher.screen = XDefaultScreen(DisplayId);
594 595 596
    v = XGetVisualInfo(this->DisplayId, VisualIDMask | VisualScreenMask,
                       &matcher, &nItems);
    }
597

598 599 600 601 602
  if (this->OwnWindow)
    {
    // RESIZE THE WINDOW TO THE DESIRED SIZE
    vtkDebugMacro(<< "Resizing the xwindow\n");
    XResizeWindow(this->DisplayId,this->WindowId,
603
                  ((this->Size[0] > 0) ?
Francois Bertel's avatar
Francois Bertel committed
604
                   static_cast<unsigned int>(this->Size[0]) : 300),
605
                  ((this->Size[1] > 0) ?
Francois Bertel's avatar
Francois Bertel committed
606
                   static_cast<unsigned int>(this->Size[1]) : 300));
607 608 609 610
    XSync(this->DisplayId,False);
    }

  // is GLX extension is supported?
611
  if(!glXQueryExtension(this->DisplayId, NULL, NULL))
612 613 614
    {
    vtkErrorMacro("GLX not found.  Aborting.");
    if (this->HasObserver(vtkCommand::ExitEvent))
615
      {
616 617
      this->InvokeEvent(vtkCommand::ExitEvent, NULL);
      return;
618
      }
619
    else
Ken Martin's avatar
Ken Martin committed
620
      {
621 622 623 624 625 626
      abort();
      }
    }

  if (!this->Internal->ContextId)
    {
627
    this->Internal->ContextId =
628 629 630 631 632 633 634 635 636 637
      glXCreateContext(this->DisplayId, v, 0, GL_TRUE);
    }

  if(!this->Internal->ContextId)
    {
    vtkErrorMacro("Cannot create GLX context.  Aborting.");
    if (this->HasObserver(vtkCommand::ExitEvent))
      {
      this->InvokeEvent(vtkCommand::ExitEvent, NULL);
      return;
Ken Martin's avatar
Ken Martin committed
638
      }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
639 640
    else
      {
641
      abort();
Mathieu Malaterre's avatar
Mathieu Malaterre committed
642
      }
643 644
    }

645
  if(this->OwnWindow && !this->OffScreenRendering)
646 647 648 649 650 651
    {
    vtkDebugMacro(" Mapping the xwindow\n");
    XMapWindow(this->DisplayId, this->WindowId);
    XSync(this->DisplayId,False);
    XGetWindowAttributes(this->DisplayId,
                         this->WindowId,&winattr);
652
    // guarantee that the window is mapped before the program continues
653 654
    // on to do the OpenGL rendering.
    while (winattr.map_state == IsUnmapped)
655
      {
656 657
      XGetWindowAttributes(this->DisplayId,
                           this->WindowId,&winattr);
658
      }
659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
    }
  // free the visual info
  if (v)
    {
    XFree(v);
    }
  this->Mapped = 1;
  this->Size[0] = width;
  this->Size[1] = height;

}

void vtkXOpenGLRenderWindow::DestroyWindow()
{
  // free the cursors
  if (this->DisplayId)
    {
    if (this->WindowId)
677
      {
678 679 680 681
      // we will only have a cursor defined if a CurrentCursor has been
      // set > 0 or if the cursor has been hidden... if we undefine without
      // checking, bad things can happen (BadWindow)
      if (this->GetCurrentCursor() || this->CursorHidden)
682
        {
683
        XUndefineCursor(this->DisplayId,this->WindowId);
684
        }
685
      }
686
    if (this->XCArrow)
687
      {
688
      XFreeCursor(this->DisplayId,this->XCArrow);
689
      }
690 691 692 693
    if (this->XCCrosshair)
      {
      XFreeCursor(this->DisplayId,this->XCCrosshair);
      }
694
    if (this->XCSizeAll)
695
      {
696
      XFreeCursor(this->DisplayId,this->XCSizeAll);
697
      }
698
    if (this->XCSizeNS)
699
      {
700 701 702 703 704 705 706 707 708 709 710 711 712
      XFreeCursor(this->DisplayId,this->XCSizeNS);
      }
    if (this->XCSizeWE)
      {
      XFreeCursor(this->DisplayId,this->XCSizeWE);
      }
    if (this->XCSizeNE)
      {
      XFreeCursor(this->DisplayId,this->XCSizeNE);
      }
    if (this->XCSizeNW)
      {
      XFreeCursor(this->DisplayId,this->XCSizeNW);
713
      }
714
    if (this->XCSizeSE)
715
      {
716 717 718 719 720 721 722 723 724
      XFreeCursor(this->DisplayId,this->XCSizeSE);
      }
    if (this->XCSizeSW)
      {
      XFreeCursor(this->DisplayId,this->XCSizeSW);
      }
    if (this->XCHand)
      {
      XFreeCursor(this->DisplayId,this->XCHand);
725
      }
726
    }
727

728 729 730 731 732 733 734 735 736 737
  this->XCCrosshair = 0;
  this->XCArrow     = 0;
  this->XCSizeAll   = 0;
  this->XCSizeNS    = 0;
  this->XCSizeWE    = 0;
  this->XCSizeNE    = 0;
  this->XCSizeNW    = 0;
  this->XCSizeSE    = 0;
  this->XCSizeSW    = 0;
  this->XCHand      = 0;
738

739 740 741 742 743 744 745 746 747 748 749
  if (this->OwnContext && this->Internal->ContextId)
    {
      this->MakeCurrent();
    // tell each of the renderers that this render window/graphics context
    // is being removed (the RendererCollection is removed by vtkRenderWindow's
    // destructor)
    vtkRenderer* ren;
    this->Renderers->InitTraversal();
    for ( ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject());
          ren != NULL;
          ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject())  )
750
      {
751 752
      ren->SetRenderWindow(NULL);
      ren->SetRenderWindow(this);
753 754
      }

755
    if (this->Internal->ContextId)
756
      {
757 758
      /* first delete all the old lights */
      for (short cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+MAX_LIGHTS; cur_light++)
759
        {
760
        glDisable(static_cast<GLenum>(cur_light));
761
        }
762 763 764 765

      /* now delete all textures */
      glDisable(GL_TEXTURE_2D);
      for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++)
766
        {
767 768 769 770 771 772 773 774 775 776 777
        GLuint txId = static_cast<GLuint>(this->TextureResourceIds->GetId(i));
#ifdef GL_VERSION_1_1
        if (glIsTexture(txId))
          {
          glDeleteTextures(1, &txId);
          }
#else
        if (glIsList(txId))
          {
          glDeleteLists(txId,1);
          }
778
#endif
779
        }
780

781 782 783
      glFinish();
      glXDestroyContext(this->DisplayId, this->Internal->ContextId);
      }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
784
    }
785
    this->Internal->ContextId = NULL;
786

787 788 789 790 791 792 793 794 795 796 797 798 799 800
  // then close the old window if we own it
  if (this->OwnWindow && this->DisplayId && this->WindowId)
    {
    XDestroyWindow(this->DisplayId,this->WindowId);
    this->WindowId = static_cast<Window>(NULL);
    }

  // if we create the display, we'll delete it
  if (this->OwnDisplay && this->DisplayId)
    {
    XCloseDisplay(this->DisplayId);
    this->DisplayId = NULL;
    }

801 802
  delete[] this->Capabilities;
  this->Capabilities = 0;
803

804 805 806
  // make sure all other code knows we're not mapped anymore
  this->Mapped = 0;

807 808
}

Clinton Stimpson's avatar
 
Clinton Stimpson committed
809 810
void vtkXOpenGLRenderWindow::CreateOffScreenWindow(int width, int height)
{
811

Clinton Stimpson's avatar
 
Clinton Stimpson committed
812
  XVisualInfo  *v;
813

Clinton Stimpson's avatar
 
Clinton Stimpson committed
814 815 816
  this->DoubleBuffer = 0;

  // always prefer OSMESA if we built with it
817
#ifdef VTK_USE_OSMESA
Clinton Stimpson's avatar
 
Clinton Stimpson committed
818
  if(1)
819
    {
Clinton Stimpson's avatar
 
Clinton Stimpson committed
820 821 822 823
    if (!this->Internal->OffScreenWindow)
      {
      this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
      this->Size[0] = width;
824
      this->Size[1] = height;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
825
      this->OwnWindow = 1;
826
      }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
827 828 829 830 831
    if (!this->Internal->OffScreenContextId)
      {
      this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
      }
    this->MakeCurrent();
832
    }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
833 834 835
  else
#endif
    {
836
    if(!this->CreateHardwareOffScreenWindow(width,height))
Clinton Stimpson's avatar
 
Clinton Stimpson committed
837
      {
838
      // get the default display connection
839
      if (!this->DisplayId)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
840
        {
841
        this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
842
        if (this->DisplayId == NULL)
843
          {
844
          vtkErrorMacro(<< "bad X server connection. DISPLAY="
Ben Boeckel's avatar
Ben Boeckel committed
845 846
            << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
          abort();
847 848
          }
        this->OwnDisplay = 1;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
849 850
        }

851 852
      int v1, v2;
      glXQueryVersion(this->DisplayId, &v1, &v2);
Clinton Stimpson's avatar
 
Clinton Stimpson committed
853

854 855
      // check for GLX 1.3 or greater for Pbuffer offscreen support
      if(v1 > 1 || (v1 == 1 && v2 >= 3))
Clinton Stimpson's avatar
 
Clinton Stimpson committed
856
        {
857
        if(!this->Internal->PbufferContextId)
858
          {
859 860 861 862 863 864
          // Load GLX 1.3
          vtkOpenGLExtensionManager *manager=vtkOpenGLExtensionManager::New();
          int loaded = vtkgl::LoadExtension("GLX_VERSION_1_3", manager);
          manager->Delete();

          if(loaded)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
865
            {
866 867 868
            // get FBConfig
            vtkglX::GLXFBConfig* fb = vtkXOpenGLRenderWindowGetDesiredFBConfig(
              this->DisplayId,this->StereoCapableWindow, this->MultiSamples,
869 870
              this->DoubleBuffer,this->AlphaBitPlanes, vtkglX::PBUFFER_BIT,
              this->StencilCapable);
871
            if(fb)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
872
              {
873
              XErrorHandler previousHandler = XSetErrorHandler(vtkXOGLPbufferErrorHandler);
874
              this->Internal->PbufferContextId =
875 876
                vtkglX::CreateNewContext(this->DisplayId, fb[0],
                                         vtkglX::RGBA_TYPE, NULL, true);
877
              int atts [] =
878 879 880 881 882 883 884 885
                {
                  vtkglX::PBUFFER_WIDTH, width,
                  vtkglX::PBUFFER_HEIGHT, height,
                  0
                };
              this->Internal->Pbuffer = vtkglX::CreatePbuffer(this->DisplayId,
                                                              fb[0], atts);
              vtkglX::MakeContextCurrent( this->DisplayId,
886
                                          this->Internal->Pbuffer,
887 888 889 890
                                          this->Internal->Pbuffer,
                                          this->Internal->PbufferContextId );
              XFree(fb);
              XSetErrorHandler(previousHandler);
891

892 893 894 895 896 897 898 899 900 901 902
              // failed to allocate Pbuffer, clean up
              if(PbufferAllocFail)
                {
                //vtkglX::DestroyPbuffer(this->DisplayId, this->Internal->Pbuffer);
                this->Internal->Pbuffer = 0;
                if(this->Internal->PbufferContextId)
                  glXDestroyContext(this->DisplayId,
                                    this->Internal->PbufferContextId);
                this->Internal->PbufferContextId = NULL;
                }
              PbufferAllocFail = 0;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
903 904 905 906
              }
            }
          }
        }
907

908 909 910
      // GLX 1.3 doesn't exist or failed to allocate Pbuffer
      // fallback on GLX 1.0 GLXPixmap offscreen support
      if(!this->Internal->PbufferContextId && !this->Internal->PixmapContextId)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
911
        {
912 913 914
        v = this->GetDesiredVisualInfo();
        this->Internal->PixmapContextId = glXCreateContext(this->DisplayId,
                                                           v, 0, GL_FALSE);
Francois Bertel's avatar
Francois Bertel committed
915 916 917 918 919 920
        this->Internal->pixmap=
          XCreatePixmap(this->DisplayId,
                        XRootWindow(this->DisplayId,v->screen),
                        static_cast<unsigned int>(width),
                        static_cast<unsigned int>(height),
                        static_cast<unsigned int>(v->depth));
921 922 923 924 925 926 927 928 929

        this->Internal->PixmapWindowId = glXCreateGLXPixmap(this->DisplayId, v, this->Internal->pixmap);
        glXMakeCurrent(this->DisplayId,this->Internal->PixmapWindowId,
                       this->Internal->PixmapContextId);

        if(v)
          {
          XFree(v);
          }
Clinton Stimpson's avatar
 
Clinton Stimpson committed
930
        }
931
      } // if not hardware offscreen
Clinton Stimpson's avatar
 
Clinton Stimpson committed
932
    }
Francois Bertel's avatar
Francois Bertel committed
933
  this->Mapped = 0;
Clinton Stimpson's avatar
 
Clinton Stimpson committed
934 935
  this->Size[0] = width;
  this->Size[1] = height;
936 937


Clinton Stimpson's avatar
 
Clinton Stimpson committed
938 939 940 941
  this->MakeCurrent();

  // tell our renderers about us
  vtkRenderer* ren;
942
  for (this->Renderers->InitTraversal();
Clinton Stimpson's avatar
 
Clinton Stimpson committed
943 944 945 946 947 948 949 950 951 952 953
       (ren = this->Renderers->GetNextItem());)
    {
    ren->SetRenderWindow(0);
    ren->SetRenderWindow(this);
    }

  this->OpenGLInit();
}

void vtkXOpenGLRenderWindow::DestroyOffScreenWindow()
{
954

Clinton Stimpson's avatar
 
Clinton Stimpson committed
955 956 957 958 959 960 961 962 963 964 965
  // release graphic resources.
  vtkRenderer *ren;
  vtkCollectionSimpleIterator rit;
  this->Renderers->InitTraversal(rit);
  while ( (ren = this->Renderers->GetNextRenderer(rit)) )
    {
    ren->SetRenderWindow(NULL);
    ren->SetRenderWindow(this);
    }


966
#ifdef VTK_USE_OSMESA
Clinton Stimpson's avatar
 
Clinton Stimpson committed
967 968 969 970 971 972 973 974 975 976
  if (this->Internal->OffScreenContextId)
    {
    OSMesaDestroyContext(this->Internal->OffScreenContextId);
    this->Internal->OffScreenContextId = NULL;
    vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
    this->Internal->OffScreenWindow = NULL;
    }
  else
#endif
    {
977
    if(this->OffScreenUseFrameBuffer)
Clinton Stimpson's avatar
 
Clinton Stimpson committed
978
      {
979
      this->DestroyHardwareOffScreenWindow();
980
      }
981
    else
982
      {
983 984 985 986 987 988 989 990 991 992 993 994 995 996 997
      if(this->Internal->PbufferContextId)
        {
        vtkglX::DestroyPbuffer(this->DisplayId, this->Internal->Pbuffer);
        this->