text: /*=========================================================================
  
    Program:   Visualization Toolkit
    Module:    vtkXOpenGLRenderWindow.cxx
  
    Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
    All rights reserved.
    See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
  
       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.
  
  =========================================================================*/
  
  #include "vtkXOpenGLRenderWindow.h"
  #include "vtkOpenGLRenderer.h"
  
  #include "vtk_glew.h"
  // Define GLX_GLXEXT_LEGACY to prevent glx.h from including the glxext.h
  // provided by the system.
  //#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;
  #include "GL/glx.h"
  
  
  #ifndef GLAPI
  #define GLAPI extern
  #endif
  
  #ifndef GLAPIENTRY
  #define GLAPIENTRY
  #endif
  
  #ifndef APIENTRY
  #define APIENTRY GLAPIENTRY
  #endif
  
  #include "vtkToolkits.h"
  
  #ifdef VTK_USE_OSMESA
  #include <GL/osmesa.h>
  
  typedef OSMesaContext GLAPIENTRY (*OSMesaCreateContextAttribs_func)( const int *attribList, OSMesaContext sharelist );
  #endif
  
  #include "vtkCommand.h"
  #include "vtkIdList.h"
  #include "vtkNew.h"
  #include "vtkObjectFactory.h"
  #include "vtkOpenGLShaderCache.h"
  #include "vtkRendererCollection.h"
  #include "vtkRenderWindowInteractor.h"
  #include "vtkStringOutputWindow.h"
  
  #include "vtksys/SystemTools.hxx"
  
  #include <sstream>
  
  #include <X11/Xlib.h>
  #include <X11/Xutil.h>
  #include <X11/cursorfont.h>
  
  #define GLX_CONTEXT_MAJOR_VERSION_ARB       0x2091
  #define GLX_CONTEXT_MINOR_VERSION_ARB       0x2092
  typedef GLXContext (*glXCreateContextAttribsARBProc)(Display*, GLXFBConfig, GLXContext, Bool, const int*);
  
  class vtkXOpenGLRenderWindow;
  class vtkRenderWindow;
  class vtkXOpenGLRenderWindowInternal
  {
    friend class vtkXOpenGLRenderWindow;
  private:
    vtkXOpenGLRenderWindowInternal(vtkRenderWindow*);
  
    GLXContext ContextId;
    GLXFBConfig FBConfig;
  
    // store previous settings of on screen window
    int ScreenDoubleBuffer;
    int ScreenMapped;
  
  #if defined( VTK_USE_OSMESA )
    // OffScreen stuff
    OSMesaContext OffScreenContextId;
    void *OffScreenWindow;
  #endif
  };
  
  vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal(
    vtkRenderWindow *rw)
  {
    this->ContextId = NULL;
    this->FBConfig = None;
  
    this->ScreenMapped = rw->GetMapped();
    this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
  
    // OpenGL specific
  #ifdef VTK_USE_OSMESA
    this->OffScreenContextId = NULL;
    this->OffScreenWindow = NULL;
  #endif
  }
  
  vtkStandardNewMacro(vtkXOpenGLRenderWindow);
  
  #define MAX_LIGHTS 8
  
  #ifdef VTK_USE_OSMESA
  // a couple of routines for offscreen rendering
  void vtkOSMesaDestroyWindow(void *window)
  {
    free(window);
  }
  
  void *vtkOSMesaCreateWindow(int width, int height)
  {
    return malloc(width*height*4);
  }
  #endif
  
  GLXFBConfig vtkXOpenGLRenderWindowTryForFBConfig(Display *DisplayId,
                                                    int drawable_type,
                                                    int doublebuff,
                                                    int stereo,
                                                    int multisamples,
                                                    int stencil)
  {
    int           index;
    static int    attributes[50];
  
    // setup the default stuff we ask for
    index = 0;
    attributes[index++] = GLX_DRAWABLE_TYPE;
    attributes[index++] = drawable_type;
    attributes[index++] = GLX_RENDER_TYPE;
    attributes[index++] = GLX_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;
    attributes[index++] = GLX_ALPHA_SIZE;
    attributes[index++] = 1;
    if (doublebuff)
    {
      attributes[index++] = GLX_DOUBLEBUFFER;
      attributes[index++] = True;
    }
    if (stencil)
    {
      attributes[index++] = GLX_STENCIL_SIZE;
      attributes[index++] = 8;
    }
    if (stereo)
    {
      // also try for STEREO
      attributes[index++] = GLX_STEREO;
      attributes[index++] = True;
    }
    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
    }
  
    attributes[index++] = None;
  
    // cout << "Trying config: " << endl
    //      << "         DisplayId : " << DisplayId << endl
    //      << "     drawable_type : " << drawable_type << endl
    //      << "        doublebuff : " << doublebuff << endl
    //      << "            stereo : " << stereo << endl
    //      << "      multisamples : " << multisamples << endl
    //      << "    alphaBitPlanes : " << alphaBitPlanes << endl
    //      << "           stencil : " << stencil << endl;
    int tmp;
    GLXFBConfig* fb = glXChooseFBConfig(DisplayId, XDefaultScreen(DisplayId),
                                        attributes, &tmp);
    if (fb && tmp > 0)
    {
      // cout << "            STATUS : SUCCESS!!!" << endl;
      GLXFBConfig result = fb[0];
      XFree(fb);
      return result;
    }
    // cout << "            STATUS : FAILURE!!!" << endl;
    return None;
  }
  
  XVisualInfo *vtkXOpenGLRenderWindowTryForVisual(Display *DisplayId,
                                                  int doublebuff, int stereo,
                                                  int multisamples,
                                                  int stencil)
  {
    GLXFBConfig fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
         GLX_WINDOW_BIT,
         doublebuff,
         stereo, multisamples,
         stencil);
  
    XVisualInfo *v = glXGetVisualFromFBConfig( DisplayId, fbc);
  
    return v;
  }
  
  GLXFBConfig vtkXOpenGLRenderWindowGetDesiredFBConfig(
    Display *DisplayId,
    int &win_stereo,
    int &win_multisamples,
    int &win_doublebuffer,
    int drawable_type,
    int &stencil)
  {
    GLXFBConfig   fbc = None;
    int           multi;
    int           stereo = 0;
  
    // try every possibility stoping when we find one that works
    // start by adjusting stereo and multisamples
    for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
    {
      for (multi = win_multisamples; !fbc && multi >= 0; multi--)
      {
        fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
                                                   drawable_type,
                                                   win_doublebuffer,
                                                   stereo, multi,
                                                   stencil);
        if (fbc)
        {
          // found a valid config
          win_stereo = stereo;
          win_multisamples = multi;
          return fbc;
        }
      }
    }
  
    // OK adjusting stereo and multisamples did not work
    // try flipping the double buffer requirement and try again
    for (stereo = win_stereo; !fbc && stereo >= 0; stereo--)
    {
      for (multi = win_multisamples; !fbc && multi >= 0; multi--)
      {
        fbc = vtkXOpenGLRenderWindowTryForFBConfig(DisplayId,
                                                   drawable_type,
                                                   !win_doublebuffer,
                                                   stereo, multi,
                                                   stencil);
        // we found a valid result
        if (fbc)
        {
          win_doublebuffer = !win_doublebuffer;
          win_stereo = stereo;
          win_multisamples = multi;
          return fbc;
        }
      }
    }
  
    // we failed
    return ( None );
  }
  
  XVisualInfo *vtkXOpenGLRenderWindow::GetDesiredVisualInfo()
  {
    XVisualInfo   *v = NULL;
  
    // get the default display connection
    if (!this->DisplayId)
    {
      this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
  
      if (this->DisplayId == NULL)
      {
        vtkErrorMacro(<< "bad X server connection. DISPLAY="
          << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
        abort();
      }
  
      this->OwnDisplay = 1;
    }
    this->Internal->FBConfig =
      vtkXOpenGLRenderWindowGetDesiredFBConfig(
        this->DisplayId,
        this->StereoCapableWindow,
        this->MultiSamples,
        this->DoubleBuffer,
        GLX_WINDOW_BIT,
        this->StencilCapable);
  
    if (!this->Internal->FBConfig)
    {
      vtkErrorMacro(<< "Could not find a decent config\n");
    }
    else
    {
      v = glXGetVisualFromFBConfig( this->DisplayId,
        this->Internal->FBConfig);
      if (!v)
      {
        vtkErrorMacro(<< "Could not find a decent visual\n");
      }
    }
    return ( v );
  }
  
  vtkXOpenGLRenderWindow::vtkXOpenGLRenderWindow()
  {
    this->ParentId = static_cast<Window>(NULL);
    this->ScreenSize[0] = 0;
    this->ScreenSize[1] = 0;
    this->OwnDisplay = 0;
    this->CursorHidden = 0;
    this->ForceMakeCurrent = 0;
    this->UsingHardware = 0;
    this->DisplayId = static_cast<Display *>(NULL);
    this->WindowId = static_cast<Window>(NULL);
    this->NextWindowId = static_cast<Window>(NULL);
    this->ColorMap = static_cast<Colormap>(0);
    this->OwnWindow = 0;
  
    this->Internal = new vtkXOpenGLRenderWindowInternal(this);
  
    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;
  }
  
  // free up memory & close the window
  vtkXOpenGLRenderWindow::~vtkXOpenGLRenderWindow()
  {
    // close-down all system-specific drawing resources
    this->Finalize();
  
    vtkRenderer *ren;
    vtkCollectionSimpleIterator rit;
    this->Renderers->InitTraversal(rit);
    while ( (ren = this->Renderers->GetNextRenderer(rit)) )
    {
      ren->SetRenderWindow(NULL);
    }
  
    delete this->Internal;
  }
  
  // End the rendering process and display the image.
  void vtkXOpenGLRenderWindow::Frame()
  {
    this->MakeCurrent();
    if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers
        && this->WindowId!=0)
    {
      glXSwapBuffers(this->DisplayId, this->WindowId);
      vtkDebugMacro(<< " glXSwapBuffers\n");
    }
  }
  
  bool vtkXOpenGLRenderWindow::InitializeFromCurrentContext()
  {
    GLXContext currentContext = glXGetCurrentContext();
    if (currentContext != NULL)
    {
      this->SetDisplayId((void*)glXGetCurrentDisplay());
      this->SetWindowId((void*)glXGetCurrentDrawable());
      this->Internal->ContextId = currentContext;
      return this->Superclass::InitializeFromCurrentContext();
    }
    return false;
  }
  
  //
  // 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)
  {
    if (!this->Internal->ContextId
  #if defined( VTK_USE_OSMESA )
        && !this->Internal->OffScreenContextId
  #endif
      )
    {
      vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
    }
    else
    {
      vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
                      << "before the window is realized, i.e. before a render.");
    }
  }
  
  static int PbufferAllocFail = 0;
  extern "C"
  {
    int vtkXOGLPbufferErrorHandler(Display*, XErrorEvent*)
    {
      PbufferAllocFail = 1;
      return 1;
    }
  }
  
  extern "C"
  {
    int vtkXOGLContextCreationErrorHandler(Display*, XErrorEvent*)
    {
      return 1;
    }
  }
  
  void vtkXOpenGLRenderWindow::CreateAWindow()
  {
    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))
    {
      xsh.flags |= USPosition;
      xsh.x =  static_cast<int>(this->Position[0]);
      xsh.y =  static_cast<int>(this->Position[1]);
    }
  
    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;
  
    // get the default display connection
    if (!this->DisplayId)
    {
      this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
      if (this->DisplayId == NULL)
      {
        vtkErrorMacro(<< "bad X server connection. DISPLAY="
          << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
        abort();
      }
      this->OwnDisplay = 1;
    }
  
    attr.override_redirect = False;
    if (this->Borders == 0.0)
    {
      attr.override_redirect = True;
    }
  
    // create our own window ?
    this->OwnWindow = 0;
    if (!this->WindowId)
    {
      v = this->GetDesiredVisualInfo();
      if (!v)
      {
        vtkErrorMacro(<< "Could not find a decent visual\n");
        abort();
      }
      this->ColorMap = XCreateColormap(this->DisplayId,
                                       XRootWindow(this->DisplayId,v->screen),
                                       v->visual, AllocNone);
  
      attr.background_pixel = 0;
      attr.border_pixel = 0;
      attr.colormap = this->ColorMap;
      attr.event_mask = StructureNotifyMask | ExposureMask;
  
      // get a default parent if one has not been set.
      if (! this->ParentId)
      {
        this->ParentId = XRootWindow(this->DisplayId, v->screen);
      }
      this->WindowId =
        XCreateWindow(this->DisplayId,
                      this->ParentId,
                      x, y, static_cast<unsigned int>(width),
                      static_cast<unsigned int>(height), 0, v->depth,
                      InputOutput, v->visual,
                      CWBackPixel | CWBorderPixel | CWColormap |
                      CWOverrideRedirect | CWEventMask,
                      &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);
      matcher.screen = XDefaultScreen(DisplayId);
      v = XGetVisualInfo(this->DisplayId, VisualIDMask | VisualScreenMask,
                         &matcher, &nItems);
  
      // if FBConfig is not set, try to find it based on the window
      if (!this->Internal->FBConfig)
      {
        int fbcount = 0;
        GLXFBConfig* fbc = glXGetFBConfigs(this->DisplayId, matcher.screen, &fbcount);
        if ( fbc )
        {
          int i;
          for (i=0; i<fbcount; ++i)
          {
            XVisualInfo *vi = glXGetVisualFromFBConfig( this->DisplayId, fbc[i] );
            if ( vi && vi->visualid == matcher.visualid)
            {
              this->Internal->FBConfig = fbc[i];
            }
          }
          XFree(fbc);
        }
      }
  
    }
  
    if (this->OwnWindow)
    {
      // RESIZE THE WINDOW TO THE DESIRED SIZE
      vtkDebugMacro(<< "Resizing the xwindow\n");
      XResizeWindow(this->DisplayId,this->WindowId,
                    ((this->Size[0] > 0) ?
                     static_cast<unsigned int>(this->Size[0]) : 300),
                    ((this->Size[1] > 0) ?
                     static_cast<unsigned int>(this->Size[1]) : 300));
      XSync(this->DisplayId,False);
    }
  
    // is GLX extension is supported?
    if(!glXQueryExtension(this->DisplayId, NULL, NULL))
    {
      vtkErrorMacro("GLX not found.  Aborting.");
      if (this->HasObserver(vtkCommand::ExitEvent))
      {
        this->InvokeEvent(vtkCommand::ExitEvent, NULL);
        return;
      }
      else
      {
        abort();
      }
    }
  
    // try for 32 context
    if (this->Internal->FBConfig)
    {
      // NOTE: It is not necessary to create or make current to a context before
      // calling glXGetProcAddressARB
      glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0;
      glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc)
        glXGetProcAddressARB( (const GLubyte *) "glXCreateContextAttribsARB" );
  
      int context_attribs[] =
        {
        GLX_CONTEXT_MAJOR_VERSION_ARB, 3,
        GLX_CONTEXT_MINOR_VERSION_ARB, 2,
        //GLX_CONTEXT_FLAGS_ARB        , GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
        0
        };
  
      if (glXCreateContextAttribsARB)
      {
        XErrorHandler previousHandler = XSetErrorHandler(vtkXOGLContextCreationErrorHandler);
        this->Internal->ContextId = 0;
        // we believe that these later versions are all compatible with
        // OpenGL 3.2 so get a more recent context if we can.
        int attemptedVersions[] = {4,5, 4,4, 4,3, 4,2, 4,1, 4,0, 3,3, 3,2};
        for (int i = 0; i < 8 && !this->Internal->ContextId; i++)
        {
          context_attribs[1] = attemptedVersions[i*2];
          context_attribs[3] = attemptedVersions[i*2+1];
          this->Internal->ContextId =
            glXCreateContextAttribsARB( this->DisplayId,
              this->Internal->FBConfig, 0,
              GL_TRUE, context_attribs );
          // Sync to ensure any errors generated are processed.
          XSync( this->DisplayId, False );
        }
        XSetErrorHandler(previousHandler);
        if ( this->Internal->ContextId )
        {
          this->SetContextSupportsOpenGL32(true);
        }
      }
    }
  
    // old failsafe
    if (this->Internal->ContextId == NULL)
    {
      this->Internal->ContextId =
        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;
      }
      else
      {
        abort();
      }
    }
  
    if(this->OwnWindow && !this->OffScreenRendering)
    {
      vtkDebugMacro(" Mapping the xwindow\n");
      XMapWindow(this->DisplayId, this->WindowId);
      XSync(this->DisplayId,False);
      XGetWindowAttributes(this->DisplayId,
                           this->WindowId,&winattr);
      // guarantee that the window is mapped before the program continues
      // on to do the OpenGL rendering.
      while (winattr.map_state == IsUnmapped)
      {
        XGetWindowAttributes(this->DisplayId,
                             this->WindowId,&winattr);
      }
    }
    // 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)
      {
        // 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)
        {
          XUndefineCursor(this->DisplayId,this->WindowId);
        }
      }
      if (this->XCArrow)
      {
        XFreeCursor(this->DisplayId,this->XCArrow);
      }
      if (this->XCCrosshair)
      {
        XFreeCursor(this->DisplayId,this->XCCrosshair);
      }
      if (this->XCSizeAll)
      {
        XFreeCursor(this->DisplayId,this->XCSizeAll);
      }
      if (this->XCSizeNS)
      {
        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);
      }
      if (this->XCSizeSE)
      {
        XFreeCursor(this->DisplayId,this->XCSizeSE);
      }
      if (this->XCSizeSW)
      {
        XFreeCursor(this->DisplayId,this->XCSizeSW);
      }
      if (this->XCHand)
      {
        XFreeCursor(this->DisplayId,this->XCHand);
      }
    }
  
    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;
  
    if (this->OwnContext && this->Internal->ContextId)
    {
      this->MakeCurrent();
      this->ReleaseGraphicsResources(this);
  
      if (this->Internal->ContextId)
      {
        glFinish();
        glXDestroyContext(this->DisplayId, this->Internal->ContextId);
        glXMakeCurrent(this->DisplayId, None, NULL);
      }
    }
      this->Internal->ContextId = NULL;
  
    // 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);
    }
  
    this->CloseDisplay();
  
    // make sure all other code knows we're not mapped anymore
    this->Mapped = 0;
  
  }
  
  void vtkXOpenGLRenderWindow::CreateOffScreenWindow(int width, int height)
  {
  
    this->DoubleBuffer = 0;
  
    // always prefer OSMESA if we built with it
  #ifdef VTK_USE_OSMESA
    if(1)
    {
      if (!this->Internal->OffScreenWindow)
      {
        this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
        this->Size[0] = width;
        this->Size[1] = height;
        this->OwnWindow = 1;
      }
  
  #if (OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 1102) && defined(OSMESA_CONTEXT_MAJOR_VERSION)
      static const int attribs[] = {
         OSMESA_FORMAT, OSMESA_RGBA,
         OSMESA_DEPTH_BITS, 32,
         OSMESA_STENCIL_BITS, 0,
         OSMESA_ACCUM_BITS, 0,
         OSMESA_PROFILE, OSMESA_CORE_PROFILE,
         OSMESA_CONTEXT_MAJOR_VERSION, 3,
         OSMESA_CONTEXT_MINOR_VERSION, 2,
         0 };
  
      OSMesaCreateContextAttribs_func OSMesaCreateContextAttribs =
         (OSMesaCreateContextAttribs_func)
         OSMesaGetProcAddress("OSMesaCreateContextAttribs");
  
      if (OSMesaCreateContextAttribs != NULL)
      {
        this->Internal->OffScreenContextId = OSMesaCreateContextAttribs(attribs, NULL);
      }
  #endif
      // if we still have no context fall back to the generic signature
      if (!this->Internal->OffScreenContextId)
      {
        this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
      }
      this->MakeCurrent();
    }
    else
  #endif
    {
      if(!this->CreateHardwareOffScreenWindow(width,height))
      {
        vtkErrorMacro(<< "failed to create offscreen window");
      } // if not hardware offscreen
    }
    this->Mapped = 0;
    this->Size[0] = width;
    this->Size[1] = height;
  
  
    this->MakeCurrent();
  
    // tell our renderers about us
    vtkRenderer* ren;
    for (this->Renderers->InitTraversal();
         (ren = this->Renderers->GetNextItem());)
    {
      ren->SetRenderWindow(0);
      ren->SetRenderWindow(this);
    }
  
    this->OpenGLInit();
  }
  
  void vtkXOpenGLRenderWindow::DestroyOffScreenWindow()
  {
    // release graphic resources.
    this->ReleaseGraphicsResources(this);
  
  #ifdef VTK_USE_OSMESA
    if (this->Internal->OffScreenContextId)
    {
      OSMesaDestroyContext(this->Internal->OffScreenContextId);
      this->Internal->OffScreenContextId = NULL;
      vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
      this->Internal->OffScreenWindow = NULL;
    }
    else
  #endif
    {
      if(this->OffScreenUseFrameBuffer)
      {
        this->DestroyHardwareOffScreenWindow();
      }
    }
  }
  
  void vtkXOpenGLRenderWindow::ResizeOffScreenWindow(int width, int height)
  {
    if(!this->OffScreenRendering)
    {
      return;
    }
  
    // Generally, we simply destroy and recreate the offscreen window/contexts.
    // However, that's totally unnecessary for OSMesa. So we avoid that.
  #ifdef VTK_USE_OSMESA
    if (this->Internal->OffScreenContextId && this->Internal->OffScreenWindow)
    {
      vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
      this->Internal->OffScreenWindow = NULL;
  
      // allocate new one.
      this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
      this->Size[0] = width;
      this->Size[1] = height;
      this->OwnWindow = 1;
      return;
    }
  #endif
  
    if(this->OffScreenUseFrameBuffer)
    {
      this->DestroyOffScreenWindow();
      this->CreateOffScreenWindow(width, height);
    }
  }
  
  // Initialize the window for rendering.
  void vtkXOpenGLRenderWindow::WindowInitialize (void)
  {
    this->CreateAWindow();
  
    this->MakeCurrent();
  
    // tell our renderers about us
    vtkRenderer* ren;
    for (this->Renderers->InitTraversal();
         (ren = this->Renderers->GetNextItem());)
    {
      ren->SetRenderWindow(0);
      ren->SetRenderWindow(this);
    }
  
    this->OpenGLInit();
  }
  
  // Initialize the rendering window.
  void vtkXOpenGLRenderWindow::Initialize (void)
  {
    if(!this->OffScreenRendering && !this->Internal->ContextId)
    {
      // initialize the window
      this->WindowInitialize();
    }
    else if(this->OffScreenRendering &&
            ! (this->OffScreenUseFrameBuffer
  #ifdef VTK_USE_OSMESA
               || this->Internal->OffScreenContextId
  #endif
              ))
    {
      // initialize offscreen window
      int width = ((this->Size[0] > 0) ? this->Size[0] : 300);
      int height = ((this->Size[1] > 0) ? this->Size[1] : 300);
      this->CreateOffScreenWindow(width, height);
    }
  }
  
  void vtkXOpenGLRenderWindow::Finalize (void)
  {
  
    // clean up offscreen stuff
    this->SetOffScreenRendering(0);
  
    // clean and destroy window
    this->DestroyWindow();
  
  }
  
  // Change the window to fill the entire screen.
  void vtkXOpenGLRenderWindow::SetFullScreen(int arg)
  {
    int *temp;
  
    if (this->OffScreenRendering)
    {
      return;
    }
  
    if (this->FullScreen == arg) return;
  
    if (!this->Mapped)
    {
      this->PrefFullScreen();
      return;
    }
  
    // set the mode
    this->FullScreen = arg;
    if (this->FullScreen <= 0)
    {
      this->Position[0] = this->OldScreen[0];
      this->Position[1] = this->OldScreen[1];
      this->Size[0] = this->OldScreen[2];
      this->Size[1] = this->OldScreen[3];
      this->Borders = this->OldScreen[4];
    }
    else
    {
      // if window already up get its values
      if (this->WindowId)
      {
        XWindowAttributes attribs;
  
        //  Find the current window size
        XGetWindowAttributes(this->DisplayId,
                             this->WindowId, &attribs);
  
        this->OldScreen[2] = attribs.width;
        this->OldScreen[3] = attribs.height;;
  
        temp = this->GetPosition();
        this->OldScreen[0] = temp[0];
        this->OldScreen[1] = temp[1];
  
        this->OldScreen[4] = this->Borders;
        this->PrefFullScreen();
      }
    }
  
    // remap the window
    this->WindowRemap();
  
    this->Modified();
  }
  
  // Set the preferred window size to full screen.
  void vtkXOpenGLRenderWindow::PrefFullScreen()
  {
    // use full screen
    this->Position[0] = 0;
    this->Position[1] = 0;
  
    if (this->OffScreenRendering)
    {
      this->Size[0] = 1280;
      this->Size[1] = 1024;
    }
    else
    {
      int *size;
      size = this->GetScreenSize();
      this->Size[0] = size[0];
      this->Size[1] = size[1];
    }
  
    // don't show borders
    this->Borders = 0;
  }
  
  // Resize the window.
  void vtkXOpenGLRenderWindow::WindowRemap()
  {
    // shut everything down
    this->Finalize();
  
    // set the default windowid
    this->WindowId = this->NextWindowId;
    this->NextWindowId = static_cast<Window>(NULL);
  
    // set everything up again
    this->Initialize();
  }
  
  // Begin the rendering process.
  void vtkXOpenGLRenderWindow::Start(void)
  {
    this->Initialize();
  
    // set the current window
    this->MakeCurrent();
  }
  
  
  // Specify the size of the rendering window.
  void vtkXOpenGLRenderWindow::SetSize(int width,int height)
  {
    if ((this->Size[0] != width)||(this->Size[1] != height))
    {
      this->Superclass::SetSize(width, height);
  
      if (this->Interactor)
      {
        this->Interactor->SetSize( width, height );
      }
  
      if(this->OffScreenRendering)
      {
        this->ResizeOffScreenWindow(width,height);
      }
      else if(this->WindowId && this->Mapped)
      {
        XResizeWindow(this->DisplayId,this->WindowId,
                      static_cast<unsigned int>(width),
                      static_cast<unsigned int>(height));
        // this is an async call so we wait until we
        // know it has been resized. To avoid infinite
        // loops we put in a count limit just to be safe
        XWindowAttributes attribs;
        int count = 20000;
        do
        {
          XSync(this->DisplayId,False);
  
          //  Find the current window size
          XGetWindowAttributes(this->DisplayId,
                               this->WindowId, &attribs);
          count--;
        }
        while (count && (attribs.width != width || attribs.height != height));
        if (!count)
        {
          vtkWarningMacro("warning window did not resize in the allotted time");
        }
      }
  
      this->Modified();
    }
  }
  
  
  
  int vtkXOpenGLRenderWindow::GetDesiredDepth()
  {
    XVisualInfo *v;
    int depth = 0;
  
    // get the default visual to use
    v = this->GetDesiredVisualInfo();
  
    if (v)
    {
      depth = v->depth;
      XFree(v);
    }
  
    return depth;
  }
  
  // Get a visual from the windowing system.
  Visual *vtkXOpenGLRenderWindow::GetDesiredVisual ()
  {
    XVisualInfo *v;
    Visual *vis=0;
  
    // get the default visual to use
    v = this->GetDesiredVisualInfo();
  
    if (v)
    {
      vis = v->visual;
      XFree(v);
    }
  
    return vis;
  }
  
  
  // Get a colormap from the windowing system.
  Colormap vtkXOpenGLRenderWindow::GetDesiredColormap ()
  {
    XVisualInfo *v;
  
    if (this->ColorMap) return this->ColorMap;
  
    // get the default visual to use
    v = this->GetDesiredVisualInfo();
  
    if (v)
    {
      this->ColorMap = XCreateColormap(this->DisplayId,
                                       XRootWindow(this->DisplayId, v->screen),
                                       v->visual, AllocNone);
      XFree(v);
    }
  
    return this->ColorMap;
  }
  
  void vtkXOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
  {
    this->Superclass::PrintSelf(os,indent);
  
    os << indent << "ContextId: " << this->Internal->ContextId << "\n";
  #ifdef VTK_USE_OSMESA
    os << indent << "OffScreenContextId: " << this->Internal->OffScreenContextId << "\n";
  #endif
    os << indent << "Color Map: " << this->ColorMap << "\n";
    os << indent << "Display Id: " << this->GetDisplayId() << "\n";
    os << indent << "Next Window Id: " << this->NextWindowId << "\n";
    os << indent << "Window Id: " << this->GetWindowId() << "\n";
  }
  
  // the following can be useful for debugging XErrors
  // When uncommented (along with the lines in MakeCurrent)
  // it will cause a segfault upon an XError instead of
  // the normal XError handler
   // extern "C" {int vtkXError(Display *display, XErrorEvent *err)
   // {
   // // cause a segfault
   //   *(float *)(0x01) = 1.0;
   //   return 1;
   // }}
  
  void vtkXOpenGLRenderWindow::MakeCurrent()
  {
    // when debugging XErrors uncomment the following lines
     // if (this->DisplayId)
     //   {
     //     XSynchronize(this->DisplayId,1);
     //   }
     //  XSetErrorHandler(vtkXError);
  #ifdef VTK_USE_OSMESA
  
    // set the current window
    if (this->OffScreenRendering && this->Internal->OffScreenContextId)
    {
      if (OSMesaMakeCurrent(this->Internal->OffScreenContextId,
                            this->Internal->OffScreenWindow, GL_UNSIGNED_BYTE,
                            this->Size[0], this->Size[1]) != GL_TRUE)
      {
        vtkWarningMacro("failed call to OSMesaMakeCurrent");
      }
    }
    else
  #endif
    {
      if (this->Internal->ContextId &&
          ((this->Internal->ContextId != glXGetCurrentContext())
           || this->ForceMakeCurrent))
      {
        glXMakeCurrent(this->DisplayId,this->WindowId,
                       this->Internal->ContextId);
        this->ForceMakeCurrent = 0;
      }
    }
  }
  
  // ----------------------------------------------------------------------------
  // Description:
  // Tells if this window is the current OpenGL context for the calling thread.
  bool vtkXOpenGLRenderWindow::IsCurrent()
  {
    bool result=false;
  #ifdef VTK_USE_OSMESA
    if(this->OffScreenRendering && this->Internal->OffScreenContextId)
    {
      result=this->Internal->OffScreenContextId==OSMesaGetCurrentContext();
    }
    else
  #endif
    {
      if(this->Internal->ContextId)
      {
        result=this->Internal->ContextId==glXGetCurrentContext();
      }
    }
    return result;
  }
  
  void vtkXOpenGLRenderWindow::PushContext()
  {
  #ifdef VTK_USE_OSMESA
    this->MakeCurrent();
    return;
  #else
    GLXContext current = glXGetCurrentContext();
    this->ContextStack.push(current);
    this->DisplayStack.push(glXGetCurrentDisplay());
    this->DrawableStack.push(glXGetCurrentDrawable());
    if(this->Internal->ContextId != current)
    {
      this->MakeCurrent();
    }
  #endif
  }
  
  void vtkXOpenGLRenderWindow::PopContext()
  {
  #ifndef VTK_USE_OSMESA
    GLXContext current = glXGetCurrentContext();
    GLXContext target = static_cast<GLXContext>(this->ContextStack.top());
    this->ContextStack.pop();
    if (target != current)
    {
      glXMakeCurrent(this->DisplayStack.top(),
        this->DrawableStack.top(),
        target);
    }
    this->DisplayStack.pop();
    this->DrawableStack.pop();
  #endif
  }
  
  
  void vtkXOpenGLRenderWindow::SetForceMakeCurrent()
  {
    this->ForceMakeCurrent = 1;
  }
  
  int vtkXOpenGLRenderWindowFoundMatch;
  
  extern "C"
  {
    Bool vtkXOpenGLRenderWindowPredProc(Display *vtkNotUsed(disp),
                                        XEvent *event,
                                        char *arg)
    {
      Window win = (Window)arg;
  
      if (((reinterpret_cast<XAnyEvent *>(event))->window == win) &&
          ((event->type == ButtonPress)))
      {
        vtkXOpenGLRenderWindowFoundMatch = 1;
      }
  
      return 0;
    }
  }
  
  void *vtkXOpenGLRenderWindow::GetGenericContext()
  {
  #if defined(VTK_USE_OSMESA)
    if (this->OffScreenRendering && this->Internal->OffScreenContextId)
    {
      return (void *)this->Internal->OffScreenContextId;
    }
  #endif
    static GC gc = static_cast<GC>(NULL);
    if (!gc)
    {
      gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0);
    }
    return static_cast<void *>(gc);
  }
  
  int vtkXOpenGLRenderWindow::GetEventPending()
  {
    XEvent report;
  
    vtkXOpenGLRenderWindowFoundMatch = 0;
    if (this->OffScreenRendering)
    {
      return vtkXOpenGLRenderWindowFoundMatch;
    }
    XCheckIfEvent(this->DisplayId, &report, vtkXOpenGLRenderWindowPredProc,
                  reinterpret_cast<char *>(this->WindowId));
    return vtkXOpenGLRenderWindowFoundMatch;
  }
  
  // Get the size of the screen in pixels
  int *vtkXOpenGLRenderWindow::GetScreenSize()
  {
    // get the default display connection
    if (!this->DisplayId)
    {
      this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
      if (this->DisplayId == NULL)
      {
        vtkErrorMacro(<< "bad X server connection. DISPLAY="
          << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
        abort();
      }
      else
      {
        this->OwnDisplay = 1;
      }
    }
  
    this->ScreenSize[0] =
      XDisplayWidth(this->DisplayId, XDefaultScreen(this->DisplayId));
    this->ScreenSize[1] =
      XDisplayHeight(this->DisplayId, XDefaultScreen(this->DisplayId));
  
    return this->ScreenSize;
  }
  
  // Get the position in screen coordinates (pixels) of the window.
  int *vtkXOpenGLRenderWindow::GetPosition(void)
  {
    XWindowAttributes attribs;
    int x,y;
    Window child;
  
    // if we aren't mapped then just return the ivar
    if (!this->Mapped)
    {
      return this->Position;
    }
  
    //  Find the current window size
    XGetWindowAttributes(this->DisplayId, this->WindowId, &attribs);
    x = attribs.x;
    y = attribs.y;
  
    XTranslateCoordinates(this->DisplayId,this->WindowId,
                          XRootWindowOfScreen(XScreenOfDisplay(
                                                this->DisplayId,0)),
                          x,y,&this->Position[0],&this->Position[1],&child);
  
    return this->Position;
  }
  
  // Get this RenderWindow's X display id.
  Display *vtkXOpenGLRenderWindow::GetDisplayId()
  {
    vtkDebugMacro(<< "Returning DisplayId of " << static_cast<void *>(this->DisplayId) << "\n");
  
    return this->DisplayId;
  }
  
  // Get this RenderWindow's parent X window id.
  Window vtkXOpenGLRenderWindow::GetParentId()
  {
    vtkDebugMacro(<< "Returning ParentId of " << reinterpret_cast<void *>(this->ParentId) << "\n");
    return this->ParentId;
  }
  
  // Get this RenderWindow's X window id.
  Window vtkXOpenGLRenderWindow::GetWindowId()
  {
    vtkDebugMacro(<< "Returning WindowId of " << reinterpret_cast<void *>(this->WindowId) << "\n");
    return this->WindowId;
  }
  
  // Move the window to a new position on the display.
  void vtkXOpenGLRenderWindow::SetPosition(int x, int y)
  {
    // if we aren't mapped then just set the ivars
    if (!this->Mapped)
    {
      if ((this->Position[0] != x)||(this->Position[1] != y))
      {
        this->Modified();
      }
      this->Position[0] = x;
      this->Position[1] = y;
      return;
    }
  
    XMoveWindow(this->DisplayId,this->WindowId,x,y);
    XSync(this->DisplayId,False);
  }
  
  // Sets the parent of the window that WILL BE created.
  void vtkXOpenGLRenderWindow::SetParentId(Window arg)
  {
  //   if (this->ParentId)
  //     {
  //     vtkErrorMacro("ParentId is already set.");
  //     return;
  //     }
  
    vtkDebugMacro(<< "Setting ParentId to " << reinterpret_cast<void *>(arg) << "\n");
  
    this->ParentId = arg;
  }
  
  // Set this RenderWindow's X window id to a pre-existing window.
  void vtkXOpenGLRenderWindow::SetWindowId(Window arg)
  {
    vtkDebugMacro(<< "Setting WindowId to " << reinterpret_cast<void *>(arg) << "\n");
  
    this->WindowId = arg;
  
    if (this->CursorHidden)
    {
      this->CursorHidden = 0;
      this->HideCursor();
    }
  }
  
  // Set this RenderWindow's X window id to a pre-existing window.
  void vtkXOpenGLRenderWindow::SetWindowInfo(char *info)
  {
    int tmp;
  
    // get the default display connection
    if (!this->DisplayId)
    {
      this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
      if (this->DisplayId == NULL)
      {
        vtkErrorMacro(<< "bad X server connection. DISPLAY="
          << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
        abort();
      }
      else
      {
        this->OwnDisplay = 1;
      }
    }
  
    sscanf(info,"%i",&tmp);
  
    this->SetWindowId(static_cast<Window>(tmp));
  }
  
  // Set this RenderWindow's X window id to a pre-existing window.
  void vtkXOpenGLRenderWindow::SetNextWindowInfo(char *info)
  {
    int tmp;
    sscanf(info,"%i",&tmp);
  
    this->SetNextWindowId(static_cast<Window>(tmp));
  }
  
  // Sets the X window id of the window that WILL BE created.
  void vtkXOpenGLRenderWindow::SetParentInfo(char *info)
  {
    int tmp;
  
    // get the default display connection
    if (!this->DisplayId)
    {
      this->DisplayId = XOpenDisplay(static_cast<char *>(NULL));
      if (this->DisplayId == NULL)
      {
        vtkErrorMacro(<< "bad X server connection. DISPLAY="
          << vtksys::SystemTools::GetEnv("DISPLAY") << ". Aborting.\n");
        abort();
      }
      else
      {
        this->OwnDisplay = 1;
      }
    }
  
    sscanf(info,"%i",&tmp);
  
    this->SetParentId(static_cast<Window>(tmp));
  }
  
  void vtkXOpenGLRenderWindow::SetWindowId(void *arg)
  {
    this->SetWindowId(reinterpret_cast<Window>(arg));
  }
  void vtkXOpenGLRenderWindow::SetParentId(void *arg)
  {
    this->SetParentId(reinterpret_cast<Window>(arg));
  }
  
  const char* vtkXOpenGLRenderWindow::ReportCapabilities()
  {
    MakeCurrent();
  
    if (!this->DisplayId)
    {
      return "display id not set";
    }
  
    int scrnum = XDefaultScreen(this->DisplayId);
    const char *serverVendor = glXQueryServerString(this->DisplayId, scrnum,
                                                    GLX_VENDOR);
    const char *serverVersion = glXQueryServerString(this->DisplayId, scrnum,
                                                     GLX_VERSION);
    const char *serverExtensions = glXQueryServerString(this->DisplayId, scrnum,
                                                        GLX_EXTENSIONS);
    const char *clientVendor = glXGetClientString(this->DisplayId, GLX_VENDOR);
    const char *clientVersion = glXGetClientString(this->DisplayId, GLX_VERSION);
    const char *glxExtensions = glXQueryExtensionsString(this->DisplayId,scrnum);
    const char *glVendor = reinterpret_cast<const char *>(glGetString(GL_VENDOR));
    const char *glRenderer = reinterpret_cast<const char *>(glGetString(GL_RENDERER));
    const char *glVersion = reinterpret_cast<const char *>(glGetString(GL_VERSION));
  
    std::ostringstream strm;
    strm << "server glx vendor string:  " << serverVendor << endl;
    strm << "server glx version string:  " << serverVersion << endl;
    strm << "server glx extensions:  " << serverExtensions << endl;
    strm << "client glx vendor string:  " << clientVendor << endl;
    strm << "client glx version string:  " << clientVersion << endl;
    strm << "glx extensions:  " << glxExtensions << endl;
    strm << "OpenGL vendor string:  " << glVendor << endl;
    strm << "OpenGL renderer string:  " << glRenderer << endl;
    strm << "OpenGL version string:  " << glVersion << endl;
    strm << "OpenGL extensions:  " << endl;
    int n = 0;
    glGetIntegerv(GL_NUM_EXTENSIONS, &n);
    for (int i = 0; i < n; i++)
    {
      const char *ext = (const char *)glGetStringi(GL_EXTENSIONS, i);
      strm << "  " << ext << endl;
    }
  
    strm << "X Extensions:  ";
  
    char **extlist = XListExtensions(this->DisplayId, &n);
  
    for (int i = 0; i < n; i++)
    {
      if (i != n-1)
      {
        strm << extlist[i] << ", ";
      }
      else
      {
        strm << extlist[i] << endl;
      }
    }
  
    delete[] this->Capabilities;
  
    size_t len = strm.str().length();
    this->Capabilities = new char[len + 1];
    strncpy(this->Capabilities, strm.str().c_str(), len);
    this->Capabilities[len] = 0;
  
    return this->Capabilities;
  }
  
  void vtkXOpenGLRenderWindow::CloseDisplay()
  {
    // if we create the display, we'll delete it
    if (this->OwnDisplay && this->DisplayId)
    {
      XCloseDisplay(this->DisplayId);
      this->DisplayId = NULL;
      this->OwnDisplay = 0;
    }
  }
  
  int vtkXOpenGLRenderWindow::IsDirect()
  {
    this->MakeCurrent();
    this->UsingHardware = 0;
    if (this->DisplayId && this->Internal->ContextId)
    {
      this->UsingHardware = glXIsDirect(this->DisplayId,
                                        this->Internal->ContextId) ? 1:0;
    }
    return this->UsingHardware;
  }
  
  
  void vtkXOpenGLRenderWindow::SetWindowName(const char * cname)
  {
    char *name = new char[ strlen(cname)+1 ];
    strcpy(name, cname);
    XTextProperty win_name_text_prop;
  
    this->vtkOpenGLRenderWindow::SetWindowName( name );
  
    if (this->Mapped)
    {
      if( XStringListToTextProperty( &name, 1, &win_name_text_prop ) == 0 )
      {
        XFree (win_name_text_prop.value);
        vtkWarningMacro(<< "Can't rename window");
        delete [] name;
        return;
      }
  
      XSetWMName( this->DisplayId, this->WindowId, &win_name_text_prop );
      XSetWMIconName( this->DisplayId, this->WindowId, &win_name_text_prop );
      XFree (win_name_text_prop.value);
    }
    delete [] name;
  }
  
  
  // Specify the X window id to use if a WindowRemap is done.
  void vtkXOpenGLRenderWindow::SetNextWindowId(Window arg)
  {
    vtkDebugMacro(<< "Setting NextWindowId to " << reinterpret_cast<void *>(arg) << "\n");
  
    this->NextWindowId = arg;
  }
  
  void vtkXOpenGLRenderWindow::SetNextWindowId(void *arg)
  {
    this->SetNextWindowId(reinterpret_cast<Window>(arg));
  }
  
  
  // Set the X display id for this RenderWindow to use to a pre-existing
  // X display id.
  void vtkXOpenGLRenderWindow::SetDisplayId(Display  *arg)
  {
    vtkDebugMacro(<< "Setting DisplayId to " << static_cast<void *>(arg) << "\n");
  
    this->DisplayId = arg;
    this->OwnDisplay = 0;
  
  }
  void vtkXOpenGLRenderWindow::SetDisplayId(void *arg)
  {
    this->SetDisplayId(static_cast<Display *>(arg));
    this->OwnDisplay = 0;
  }
  
  void vtkXOpenGLRenderWindow::Render()
  {
    XWindowAttributes attribs;
  
    // To avoid the expensive XGetWindowAttributes call,
    // compute size at the start of a render and use
    // the ivar other times.
    if (this->Mapped)
    {
      //  Find the current window size
      XGetWindowAttributes(this->DisplayId,
                           this->WindowId, &attribs);
  
      this->Size[0] = attribs.width;
      this->Size[1] = attribs.height;
    }
  
    // Now do the superclass stuff
    this->vtkOpenGLRenderWindow::Render();
  }
  
  //----------------------------------------------------------------------------
  void vtkXOpenGLRenderWindow::HideCursor()
  {
    static char blankBits[] = {
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  
    static XColor black = { 0, 0, 0, 0, 0, 0 };
  
    if (!this->DisplayId || !this->WindowId)
    {
      this->CursorHidden = 1;
    }
    else if (!this->CursorHidden)
    {
      Pixmap blankPixmap = XCreateBitmapFromData(this->DisplayId,
                                                 this->WindowId,
                                                 blankBits, 16, 16);
  
      Cursor blankCursor = XCreatePixmapCursor(this->DisplayId, blankPixmap,
                                               blankPixmap, &black, &black,
                                               7, 7);
  
      XDefineCursor(this->DisplayId, this->WindowId, blankCursor);
  
      XFreePixmap(this->DisplayId, blankPixmap);
  
      this->CursorHidden = 1;
    }
  }
  
  //----------------------------------------------------------------------------
  void vtkXOpenGLRenderWindow::ShowCursor()
  {
    if (!this->DisplayId || !this->WindowId)
    {
      this->CursorHidden = 0;
    }
    else if (this->CursorHidden)
    {
      XUndefineCursor(this->DisplayId, this->WindowId);
      this->CursorHidden = 0;
    }
  }
  
  
  //============================================================================
  // Stuff above this is almost a mirror of vtkXOpenGLRenderWindow.
  // The code specific to OpenGL Off-Screen stuff may eventually be
  // put in a supper class so this whole file could just be included
  // (mangled) from vtkXOpenGLRenderWindow like the other OpenGL classes.
  //============================================================================
  
  void vtkXOpenGLRenderWindow::SetOffScreenRendering(int i)
  {
    if (this->OffScreenRendering == i)
    {
      return;
    }
  
    // invoke super
    this->vtkRenderWindow::SetOffScreenRendering(i);
  
    if(this->OffScreenRendering)
    {
      this->Internal->ScreenDoubleBuffer = this->DoubleBuffer;
      this->DoubleBuffer = 0;
      if(this->Mapped)
      {
        this->DestroyWindow();
      }
  
      // delay initialization until Render
    }
    else
    {
      this->DestroyOffScreenWindow();
  
      this->DoubleBuffer = this->Internal->ScreenDoubleBuffer;
  
      // reset size based on screen window
      if(this->Mapped && this->WindowId)
      {
        XWindowAttributes a;
        XGetWindowAttributes(this->DisplayId, this->WindowId, &a);
  
        this->Size[0] = a.width;
        this->Size[1] = a.height;
      }
      // force context switch as we might be going from osmesa to onscreen
      this->SetForceMakeCurrent();
    }
  }
  
  // This probably has been moved to superclass.
  void *vtkXOpenGLRenderWindow::GetGenericWindowId()
  {
  #ifdef VTK_USE_OSMESA
    if (this->OffScreenRendering && this->Internal->OffScreenWindow)
    {
      return reinterpret_cast<void*>(this->Internal->OffScreenWindow);
    }
  #endif
    return reinterpret_cast<void*>(this->WindowId);
  }
  
  void vtkXOpenGLRenderWindow::SetCurrentCursor(int shape)
  {
    if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) )
    {
      return;
    }
    this->Superclass::SetCurrentCursor(shape);
    if (!this->DisplayId || !this->WindowId)
    {
      return;
    }
  
    if (shape == VTK_CURSOR_DEFAULT)
    {
      XUndefineCursor(this->DisplayId,this->WindowId);
      return;
    }
  
    switch (shape)
    {
      case VTK_CURSOR_CROSSHAIR:
        if (!this->XCCrosshair)
        {
          this->XCCrosshair = XCreateFontCursor(this->DisplayId, XC_crosshair);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCCrosshair);
        break;
      case VTK_CURSOR_ARROW:
        if (!this->XCArrow)
        {
          this->XCArrow = XCreateFontCursor(this->DisplayId, XC_top_left_arrow);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCArrow);
        break;
      case VTK_CURSOR_SIZEALL:
        if (!this->XCSizeAll)
        {
          this->XCSizeAll = XCreateFontCursor(this->DisplayId, XC_fleur);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeAll);
        break;
      case VTK_CURSOR_SIZENS:
        if (!this->XCSizeNS)
        {
          this->XCSizeNS = XCreateFontCursor(this->DisplayId,
                                             XC_sb_v_double_arrow);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNS);
        break;
      case VTK_CURSOR_SIZEWE:
        if (!this->XCSizeWE)
        {
          this->XCSizeWE = XCreateFontCursor(this->DisplayId,
                                             XC_sb_h_double_arrow);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeWE);
        break;
      case VTK_CURSOR_SIZENE:
        if (!this->XCSizeNE)
        {
          this->XCSizeNE = XCreateFontCursor(this->DisplayId,
                                             XC_top_right_corner);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNE);
        break;
      case VTK_CURSOR_SIZENW:
        if (!this->XCSizeNW)
        {
          this->XCSizeNW = XCreateFontCursor(this->DisplayId,
                                             XC_top_left_corner);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeNW);
        break;
      case VTK_CURSOR_SIZESE:
        if (!this->XCSizeSE)
        {
          this->XCSizeSE = XCreateFontCursor(this->DisplayId,
                                             XC_bottom_right_corner);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSE);
        break;
      case VTK_CURSOR_SIZESW:
        if (!this->XCSizeSW)
        {
          this->XCSizeSW = XCreateFontCursor(this->DisplayId,
                                             XC_bottom_left_corner);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCSizeSW);
        break;
      case VTK_CURSOR_HAND:
        if (!this->XCHand)
        {
          this->XCHand = XCreateFontCursor(this->DisplayId,
                                           XC_hand1);
        }
        XDefineCursor(this->DisplayId, this->WindowId, this->XCHand);
        break;
    }
  }
  