Cloned library of VTK-5.0.0 with extra build files for internal package management.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1536 lines
39 KiB

/*=========================================================================
Program: Visualization Toolkit
Module: $RCSfile: vtkXOpenGLRenderWindow.cxx,v $
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.
=========================================================================*/
#ifndef VTK_IMPLEMENT_MESA_CXX
#include "vtkXOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLProperty.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLCamera.h"
#include "vtkOpenGLLight.h"
#include "vtkOpenGLActor.h"
#include "vtkOpenGLPolyDataMapper.h"
#include <GL/gl.h>
#include "GL/glx.h"
#else
#include "MangleMesaInclude/osmesa.h"
#endif
#include "vtkToolkits.h"
#ifndef VTK_IMPLEMENT_MESA_CXX
#ifdef VTK_OPENGL_HAS_OSMESA
#include <GL/osmesa.h>
#endif
#endif
#include "vtkCommand.h"
#include "vtkIdList.h"
#include "vtkObjectFactory.h"
#include "vtkRendererCollection.h"
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/cursorfont.h>
class vtkXOpenGLRenderWindow;
class vtkRenderWindow;
class vtkXOpenGLRenderWindowInternal
{
friend class vtkXOpenGLRenderWindow;
private:
vtkXOpenGLRenderWindowInternal(vtkRenderWindow*);
GLXContext ContextId;
#if defined( VTK_OPENGL_HAS_OSMESA )
// OffScreen stuff
OSMesaContext OffScreenContextId;
void *OffScreenWindow;
int ScreenMapped;
// Looks like this just stores DoubleBuffer.
int ScreenDoubleBuffer;
#endif
};
#ifdef VTK_OPENGL_HAS_OSMESA
vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal(
vtkRenderWindow *rw)
#else
vtkXOpenGLRenderWindowInternal::vtkXOpenGLRenderWindowInternal(
vtkRenderWindow * vtkNotUsed(rw))
#endif
{
this->ContextId = NULL;
// OpenGL specific
#ifdef VTK_OPENGL_HAS_OSMESA
this->OffScreenContextId = NULL;
this->OffScreenWindow = NULL;
this->ScreenMapped = rw->GetMapped();
this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
#endif
}
#ifndef VTK_IMPLEMENT_MESA_CXX
vtkCxxRevisionMacro(vtkXOpenGLRenderWindow, "$Revision: 1.54 $");
vtkStandardNewMacro(vtkXOpenGLRenderWindow);
#endif
#define MAX_LIGHTS 8
#ifdef VTK_OPENGL_HAS_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
XVisualInfo *vtkXOpenGLRenderWindowTryForVisual(Display *DisplayId,
int doublebuff, int stereo,
int multisamples,
int alphaBitPlanes)
{
int index;
static int attributes[50];
// 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;
if (alphaBitPlanes)
{
attributes[index++] = GLX_ALPHA_SIZE;
attributes[index++] = 1;
}
if (doublebuff)
{
attributes[index++] = GLX_DOUBLEBUFFER;
}
if (stereo)
{
// also try for STEREO
attributes[index++] = GLX_STEREO;
}
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;
return glXChooseVisual(DisplayId, DefaultScreen(DisplayId), attributes );
}
XVisualInfo *vtkXOpenGLRenderWindow::GetDesiredVisualInfo()
{
XVisualInfo *v = NULL;
int multi;
int stereo = 0;
// get the default display connection
if (!this->DisplayId)
{
this->DisplayId = XOpenDisplay((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
this->OwnDisplay = 1;
}
// try every possibility stoping when we find one that works
for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
{
for (multi = this->MultiSamples; !v && multi >= 0; multi--)
{
if (v)
{
XFree(v);
}
v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
this->DoubleBuffer,
stereo, multi,
this->AlphaBitPlanes);
if (v && this->StereoCapableWindow && !stereo)
{
// requested a stereo capable window but we could not get one
this->StereoCapableWindow = 0;
}
}
}
for (stereo = this->StereoCapableWindow; !v && stereo >= 0; stereo--)
{
for (multi = this->MultiSamples; !v && multi >= 0; multi--)
{
if (v)
{
XFree(v);
}
v = vtkXOpenGLRenderWindowTryForVisual(this->DisplayId,
!this->DoubleBuffer,
stereo, multi,
this->AlphaBitPlanes);
if (v)
{
this->DoubleBuffer = !this->DoubleBuffer;
}
if (v && this->StereoCapableWindow && !stereo)
{
// requested a stereo capable window but we could not get one
this->StereoCapableWindow = 0;
}
}
}
if (!v)
{
vtkErrorMacro(<< "Could not find a decent visual\n");
}
return ( v );
}
vtkXOpenGLRenderWindow::vtkXOpenGLRenderWindow()
{
this->ParentId = (Window)NULL;
this->ScreenSize[0] = 0;
this->ScreenSize[1] = 0;
this->OwnDisplay = 0;
this->CursorHidden = 0;
this->ForceMakeCurrent = 0;
this->UsingHardware = 0;
this->DisplayId = (Display *)NULL;
this->WindowId = (Window)NULL;
this->NextWindowId = (Window)NULL;
this->ColorMap = (Colormap)0;
this->OwnWindow = 0;
this->Internal = new vtkXOpenGLRenderWindowInternal(this);
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->Capabilities = 0;
}
// free up memory & close the window
vtkXOpenGLRenderWindow::~vtkXOpenGLRenderWindow()
{
// close-down all system-specific drawing resources
this->Finalize();
delete this->Internal;
}
// End the rendering process and display the image.
void vtkXOpenGLRenderWindow::Frame(void)
{
this->MakeCurrent();
glFlush();
if (!this->AbortRender && this->DoubleBuffer && this->SwapBuffers)
{
glXSwapBuffers(this->DisplayId, this->WindowId);
vtkDebugMacro(<< " glXSwapBuffers\n");
}
}
//
// 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->WindowId)
{
vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
}
else
{
vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
<< "before the window is realized, i.e. before a render.");
}
}
// Initialize the window for rendering.
void vtkXOpenGLRenderWindow::WindowInitialize (void)
{
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 = (int)(this->Position[0]);
xsh.y = (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;
if ( ! this->OffScreenRendering)
{
// get the default display connection
if (!this->DisplayId)
{
this->DisplayId = XOpenDisplay((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
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();
this->ColorMap = XCreateColormap(this->DisplayId,
RootWindow( 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 = RootWindow(this->DisplayId, v->screen);
}
this->WindowId =
XCreateWindow(this->DisplayId,
this->ParentId,
x, y, width, 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 = DefaultScreen(DisplayId);
v = XGetVisualInfo(this->DisplayId, VisualIDMask | VisualScreenMask,
&matcher, &nItems);
}
// RESIZE THE WINDOW TO THE DESIRED SIZE
vtkDebugMacro(<< "Resizing the xwindow\n");
XResizeWindow(this->DisplayId,this->WindowId,
((this->Size[0] > 0) ?
(int)(this->Size[0]) : 300),
((this->Size[1] > 0) ?
(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();
}
}
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();
}
}
this->MakeCurrent();
if(this->OwnWindow)
{
vtkDebugMacro(" Mapping the xwindow\n");
XMapWindow(this->DisplayId, this->WindowId);
XSync(this->DisplayId,False);
XGetWindowAttributes(this->DisplayId,
this->WindowId,&winattr);
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;
}
else
{
this->DoubleBuffer = 0;
#ifdef VTK_OPENGL_HAS_OSMESA
if (!this->Internal->OffScreenWindow)
{
this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
this->Size[0] = width;
this->Size[1] = height;
this->OwnWindow = 1;
}
this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
#endif
this->MakeCurrent();
this->Mapped = 0;
}
// tell our renderers about us
vtkRenderer* ren;
for (this->Renderers->InitTraversal();
(ren = this->Renderers->GetNextItem());)
{
ren->SetRenderWindow(0);
ren->SetRenderWindow(this);
}
this->OpenGLInit();
glAlphaFunc(GL_GREATER,0);
}
// Initialize the rendering window.
void vtkXOpenGLRenderWindow::Initialize (void)
{
// make sure we havent already been initialized
if (this->Internal->ContextId
#ifdef VTK_OPENGL_HAS_OSMESA
|| this->Internal->OffScreenContextId
#endif
)
{
return;
}
// now initialize the window
this->WindowInitialize();
}
void vtkXOpenGLRenderWindow::Finalize (void)
{
vtkRenderer *ren;
GLuint txId;
short cur_light;
// 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->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);
}
}
this->XCArrow = 0;
this->XCSizeAll = 0;
this->XCSizeNS = 0;
this->XCSizeWE = 0;
this->XCSizeNE = 0;
this->XCSizeNW = 0;
this->XCSizeSE = 0;
this->XCSizeSW = 0;
// make sure we have been initialized
if (this->Internal->ContextId
#ifdef VTK_OPENGL_HAS_OSMESA
|| this->Internal->OffScreenContextId
#endif
)
{
this->MakeCurrent();
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
this->Renderers->InitTraversal();
for ( ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject());
ren != NULL;
ren = vtkOpenGLRenderer::SafeDownCast(this->Renderers->GetNextItemAsObject()) )
{
ren->SetRenderWindow(NULL);
}
/* first delete all the old lights */
for (cur_light = GL_LIGHT0; cur_light < GL_LIGHT0+MAX_LIGHTS; cur_light++)
{
glDisable((GLenum)cur_light);
}
/* now delete all textures */
glDisable(GL_TEXTURE_2D);
for (int i = 1; i < this->TextureResourceIds->GetNumberOfIds(); i++)
{
txId = (GLuint) this->TextureResourceIds->GetId(i);
#ifdef GL_VERSION_1_1
if (glIsTexture(txId))
{
glDeleteTextures(1, &txId);
}
#else
if (glIsList(txId))
{
glDeleteLists(txId,1);
}
#endif
}
glFinish();
#ifdef VTK_OPENGL_HAS_OSMESA
if (this->OffScreenRendering && this->Internal->OffScreenContextId)
{
OSMesaDestroyContext(this->Internal->OffScreenContextId);
this->Internal->OffScreenContextId = NULL;
vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
this->Internal->OffScreenWindow = NULL;
}
else
#endif
{
glXDestroyContext( this->DisplayId, this->Internal->ContextId);
this->Internal->ContextId = NULL;
// then close the old window
if (this->OwnWindow && this->DisplayId && this->WindowId)
{
XDestroyWindow(this->DisplayId,this->WindowId);
this->WindowId = (Window)NULL;
}
}
}
if (this->DisplayId)
{
XSync(this->DisplayId,0);
}
// if we create the display, we'll delete it
if (this->OwnDisplay && this->DisplayId)
{
XCloseDisplay(this->DisplayId);
this->DisplayId = NULL;
}
if (this->Capabilities)
{
delete[] this->Capabilities;
this->Capabilities = 0;
}
// make sure all other code knows we're not mapped anymore
this->Mapped = 0;
}
// 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();
// if full screen then grab the keyboard
if (this->FullScreen)
{
XGrabKeyboard(this->DisplayId,this->WindowId,
False,GrabModeAsync,GrabModeAsync,CurrentTime);
}
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 = (Window)NULL;
// set everything up again
this->Initialize();
}
// Begin the rendering process.
void vtkXOpenGLRenderWindow::Start(void)
{
// if the renderer has not been initialized, do so now
if (!this->Internal->ContextId
#ifdef VTK_OPENGL_HAS_OSMESA
&& !this->Internal->OffScreenContextId
#endif
)
{
this->Initialize();
}
// set the current window
this->MakeCurrent();
}
// Specify the size of the rendering window.
void vtkXOpenGLRenderWindow::SetSize(int x,int y)
{
if ((this->Size[0] != x)||(this->Size[1] != y))
{
this->Modified();
this->Size[0] = x;
this->Size[1] = y;
}
if (this->OffScreenRendering
#ifdef VTK_OPENGL_HAS_OSMESA
&& this->Internal->OffScreenWindow
#endif
)
{
vtkRenderer *ren;
// Disconnect renderers from this render window.
// Done to release graphic resources.
vtkCollectionSimpleIterator rit;
this->Renderers->InitTraversal(rit);
while ( (ren = this->Renderers->GetNextRenderer(rit)) )
{
ren->SetRenderWindow(NULL);
}
#ifdef VTK_OPENGL_HAS_OSMESA
OSMesaDestroyContext(this->Internal->OffScreenContextId);
this->Internal->OffScreenContextId = NULL;
vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
this->Internal->OffScreenWindow = NULL;
#endif
this->WindowInitialize();
this->Renderers->InitTraversal(rit);
while ( (ren = this->Renderers->GetNextRenderer(rit)) )
{
ren->SetRenderWindow(this);
}
}
else
{
// if we arent mappen then just set the ivars
if (!this->Mapped)
{
return;
}
XResizeWindow(this->DisplayId,this->WindowId,x,y);
XSync(this->DisplayId,False);
}
}
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,
RootWindow( 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_OPENGL_HAS_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_OPENGL_HAS_OSMESA
// set the current window
if (this->OffScreenRendering)
{
if (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;
}
}
}
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(MESA) && defined(VTK_OPENGL_HAS_OSMESA)
if (this->OffScreenRendering)
{
return (void *)this->Internal->OffScreenContextId;
}
else
#endif
{
static GC gc = (GC) NULL;
if (!gc) gc = XCreateGC(this->DisplayId, this->WindowId, 0, 0);
return (void *) gc;
}
}
int vtkXOpenGLRenderWindow::GetEventPending()
{
XEvent report;
vtkXOpenGLRenderWindowFoundMatch = 0;
#if defined(VTK_OPENGL_HAS_OSMESA)
if (this->OffScreenRendering)
{
return vtkXOpenGLRenderWindowFoundMatch;
}
#endif
XCheckIfEvent(this->DisplayId, &report, vtkXOpenGLRenderWindowPredProc,
(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((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
else
{
this->OwnDisplay = 1;
}
}
this->ScreenSize[0] =
DisplayWidth(this->DisplayId, DefaultScreen(this->DisplayId));
this->ScreenSize[1] =
DisplayHeight(this->DisplayId, DefaultScreen(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,
RootWindowOfScreen(ScreenOfDisplay(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()
{
// get the default display connection
if (!this->DisplayId)
{
this->DisplayId = XOpenDisplay((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
this->OwnDisplay = 1;
}
vtkDebugMacro(<< "Returning DisplayId of " << (void *)this->DisplayId << "\n");
return this->DisplayId;
}
// Get this RenderWindow's parent X window id.
Window vtkXOpenGLRenderWindow::GetParentId()
{
vtkDebugMacro(<< "Returning ParentId of " << (void *)this->ParentId << "\n");
return this->ParentId;
}
// Get this RenderWindow's X window id.
Window vtkXOpenGLRenderWindow::GetWindowId()
{
vtkDebugMacro(<< "Returning WindowId of " << (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 " << (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 " << (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((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
else
{
this->OwnDisplay = 1;
}
}
sscanf(info,"%i",&tmp);
this->SetWindowId(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((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((char *)NULL);
if (this->DisplayId == NULL)
{
vtkErrorMacro(<< "bad X server connection.\n");
}
else
{
this->OwnDisplay = 1;
}
}
sscanf(info,"%i",&tmp);
this->SetParentId(tmp);
}
void vtkXOpenGLRenderWindow::SetWindowId(void *arg)
{
this->SetWindowId((Window)arg);
}
void vtkXOpenGLRenderWindow::SetParentId(void *arg)
{
this->SetParentId((Window)arg);
}
const char* vtkXOpenGLRenderWindow::ReportCapabilities()
{
MakeCurrent();
if (!this->DisplayId)
{
return "display id not set";
}
int scrnum = DefaultScreen(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 *clientExtensions = glXGetClientString(this->DisplayId, GLX_EXTENSIONS);
const char *glxExtensions = glXQueryExtensionsString(this->DisplayId, scrnum);
const char *glVendor = (const char *) glGetString(GL_VENDOR);
const char *glRenderer = (const char *) glGetString(GL_RENDERER);
const char *glVersion = (const char *) glGetString(GL_VERSION);
const char *glExtensions = (const char *) glGetString(GL_EXTENSIONS);
ostrstream 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 << "client glx extensions: " << clientExtensions << 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: " << glExtensions << endl;
strm << "X Extensions: ";
int n = 0;
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;
}
}
strm << ends;
delete[] this->Capabilities;
this->Capabilities = strm.str();
return this->Capabilities;
}
int vtkXOpenGLRenderWindow::SupportsOpenGL()
{
MakeCurrent();
if (!this->DisplayId)
{
return 0;
}
int value = 0;
XVisualInfo *v = this->GetDesiredVisualInfo();
if (v)
{
glXGetConfig(this->DisplayId, v, GLX_USE_GL, &value);
}
return value;
}
int vtkXOpenGLRenderWindow::IsDirect()
{
MakeCurrent();
if (!this->DisplayId || !this->Internal->ContextId)
{
return 0;
}
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;
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 " << (void *)arg << "\n");
this->NextWindowId = arg;
}
void vtkXOpenGLRenderWindow::SetNextWindowId(void *arg)
{
this->SetNextWindowId((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 " << (void *)arg << "\n");
this->DisplayId = arg;
this->OwnDisplay = 0;
}
void vtkXOpenGLRenderWindow::SetDisplayId(void *arg)
{
this->SetDisplayId((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;
}
#ifdef VTK_OPENGL_HAS_OSMESA
// invoke super
this->vtkRenderWindow::SetOffScreenRendering(i);
// setup everything
if (i)
{
this->Internal->ScreenDoubleBuffer = this->DoubleBuffer;
this->DoubleBuffer = 0;
this->Internal->ScreenMapped = this->Mapped;
this->Mapped = 0;
if (!this->Internal->OffScreenWindow)
{
this->WindowInitialize();
}
}
else
{
if (this->Internal->OffScreenWindow)
{
OSMesaDestroyContext(this->Internal->OffScreenContextId);
this->Internal->OffScreenContextId = NULL;
vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
this->Internal->OffScreenWindow = NULL;
}
this->DoubleBuffer = this->Internal->ScreenDoubleBuffer;
this->Mapped = this->Internal->ScreenMapped;
this->MakeCurrent();
// reset the size based on the screen window
this->GetSize();
this->WindowInitialize();
}
#endif
}
// This probably has been moved to superclass.
void *vtkXOpenGLRenderWindow::GetGenericWindowId()
{
#ifdef VTK_OPENGL_HAS_OSMESA
if (this->OffScreenRendering)
{
return (void *)this->Internal->OffScreenWindow;
}
#endif
return (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_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;
}
}