You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/Rendering/OpenGL/vtkOSOpenGLRenderWindow.cxx

565 lines
13 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkOSOpenGLRenderWindow.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 "vtkOSOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLProperty.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLCamera.h"
#include "vtkOpenGLLight.h"
#include "vtkOpenGLActor.h"
#include <GL/gl.h>
#include "vtkgl.h"
#ifdef VTK_USE_OSMESA
# include <GL/osmesa.h>
#endif
#include "vtkCommand.h"
#include "vtkIdList.h"
#include "vtkObjectFactory.h"
#include "vtkRendererCollection.h"
#include "vtkOpenGLExtensionManager.h"
#include "vtksys/SystemTools.hxx"
#include <sstream>
class vtkOSOpenGLRenderWindow;
class vtkRenderWindow;
class vtkOSOpenGLRenderWindowInternal
{
friend class vtkOSOpenGLRenderWindow;
private:
vtkOSOpenGLRenderWindowInternal(vtkRenderWindow*);
// store previous settings of on screen window
int ScreenDoubleBuffer;
int ScreenMapped;
// OffScreen stuff
OSMesaContext OffScreenContextId;
void *OffScreenWindow;
};
vtkOSOpenGLRenderWindowInternal::vtkOSOpenGLRenderWindowInternal(
vtkRenderWindow *rw)
{
this->ScreenMapped = rw->GetMapped();
this->ScreenDoubleBuffer = rw->GetDoubleBuffer();
// OpenGL specific
this->OffScreenContextId = NULL;
this->OffScreenWindow = NULL;
}
vtkStandardNewMacro(vtkOSOpenGLRenderWindow);
// a couple of routines for offscreen rendering
void vtkOSMesaDestroyWindow(void *Window)
{
free(Window);
}
void *vtkOSMesaCreateWindow(int width, int height)
{
return malloc(width*height*4);
}
vtkOSOpenGLRenderWindow::vtkOSOpenGLRenderWindow()
{
// this->ParentId = (Window)NULL;
this->ScreenSize[0] = 1280;
this->ScreenSize[1] = 1024;
this->OwnDisplay = 0;
this->CursorHidden = 0;
this->ForceMakeCurrent = 0;
this->OwnWindow = 0;
this->Internal = new vtkOSOpenGLRenderWindowInternal(this);
this->Capabilities = 0;
}
// free up memory & close the window
vtkOSOpenGLRenderWindow::~vtkOSOpenGLRenderWindow()
{
// 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 vtkOSOpenGLRenderWindow::Frame()
{
this->MakeCurrent();
glFlush();
}
//
// 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 vtkOSOpenGLRenderWindow::SetStereoCapableWindow(int capable)
{
if (!this->Internal->OffScreenContextId)
{
vtkOpenGLRenderWindow::SetStereoCapableWindow(capable);
}
else
{
vtkWarningMacro(<< "Requesting a StereoCapableWindow must be performed "
<< "before the window is realized, i.e. before a render.");
}
}
void vtkOSOpenGLRenderWindow::CreateAWindow()
{
this->CreateOffScreenWindow(this->ScreenSize[0], this->ScreenSize[1]);
}
void vtkOSOpenGLRenderWindow::DestroyWindow()
{
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()) )
{
ren->SetRenderWindow(NULL);
ren->SetRenderWindow(this);
}
delete[] this->Capabilities;
this->Capabilities = 0;
this->DestroyOffScreenWindow();
// make sure all other code knows we're not mapped anymore
this->Mapped = 0;
}
void vtkOSOpenGLRenderWindow::CreateOffScreenWindow(int width, int height)
{
this->DoubleBuffer = 0;
if (!this->Internal->OffScreenWindow)
{
this->Internal->OffScreenWindow = vtkOSMesaCreateWindow(width,height);
this->OwnWindow = 1;
}
if (!this->Internal->OffScreenContextId)
{
this->Internal->OffScreenContextId = OSMesaCreateContext(GL_RGBA, NULL);
}
this->MakeCurrent();
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 vtkOSOpenGLRenderWindow::DestroyOffScreenWindow()
{
// release graphic resources.
vtkRenderer *ren;
vtkCollectionSimpleIterator rit;
this->Renderers->InitTraversal(rit);
while ( (ren = this->Renderers->GetNextRenderer(rit)) )
{
ren->SetRenderWindow(NULL);
ren->SetRenderWindow(this);
}
if (this->Internal->OffScreenContextId)
{
OSMesaDestroyContext(this->Internal->OffScreenContextId);
this->Internal->OffScreenContextId = NULL;
vtkOSMesaDestroyWindow(this->Internal->OffScreenWindow);
this->Internal->OffScreenWindow = NULL;
}
}
void vtkOSOpenGLRenderWindow::ResizeOffScreenWindow(int width, int height)
{
if(this->Internal->OffScreenContextId)
{
this->DestroyOffScreenWindow();
this->CreateOffScreenWindow(width, height);
}
}
// Initialize the window for rendering.
void vtkOSOpenGLRenderWindow::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 vtkOSOpenGLRenderWindow::Initialize (void)
{
if(! (this->Internal->OffScreenContextId))
{
// 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 vtkOSOpenGLRenderWindow::Finalize (void)
{
// clean up offscreen stuff
this->SetOffScreenRendering(0);
// clean and destroy window
this->DestroyWindow();
}
// Change the window to fill the entire screen.
void vtkOSOpenGLRenderWindow::SetFullScreen(int arg)
{
(void)arg;
this->Modified();
}
// Resize the window.
void vtkOSOpenGLRenderWindow::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 vtkOSOpenGLRenderWindow::Start(void)
{
this->Initialize();
// set the current window
this->MakeCurrent();
}
// Specify the size of the rendering window.
void vtkOSOpenGLRenderWindow::SetSize(int width,int height)
{
if ((this->Size[0] != width)||(this->Size[1] != height))
{
this->Superclass::SetSize(width, height);
this->ResizeOffScreenWindow(width, height);
this->Modified();
}
}
void vtkOSOpenGLRenderWindow::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "OffScreenContextId: " << this->Internal->OffScreenContextId << "\n";
// os << indent << "Color Map: " << this->ColorMap << "\n";
// os << indent << "Next Window Id: " << this->NextWindowId << "\n";
// os << indent << "Window Id: " << this->GetWindowId() << "\n";
}
void vtkOSOpenGLRenderWindow::MakeCurrent()
{
// set the current window
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");
}
}
}
// ----------------------------------------------------------------------------
// Description:
// Tells if this window is the current OpenGL context for the calling thread.
bool vtkOSOpenGLRenderWindow::IsCurrent()
{
bool result=false;
if(this->Internal->OffScreenContextId)
{
result=this->Internal->OffScreenContextId==OSMesaGetCurrentContext();
}
return result;
}
void vtkOSOpenGLRenderWindow::SetForceMakeCurrent()
{
this->ForceMakeCurrent = 1;
}
void *vtkOSOpenGLRenderWindow::GetGenericContext()
{
return (void *)this->Internal->OffScreenContextId;
}
int vtkOSOpenGLRenderWindow::GetEventPending()
{
return 0;
}
// Get the size of the screen in pixels
int *vtkOSOpenGLRenderWindow::GetScreenSize()
{
this->ScreenSize[0] = 1280;
this->ScreenSize[1] = 1024;
return this->ScreenSize;
}
// Get the position in screen coordinates (pixels) of the window.
int *vtkOSOpenGLRenderWindow::GetPosition(void)
{
return this->Position;
}
// Move the window to a new position on the display.
void vtkOSOpenGLRenderWindow::SetPosition(int x, int y)
{
if ((this->Position[0] != x)||(this->Position[1] != y))
{
this->Modified();
}
this->Position[0] = x;
this->Position[1] = y;
}
// Set this RenderWindow's X window id to a pre-existing window.
void vtkOSOpenGLRenderWindow::SetWindowInfo(char *info)
{
int tmp;
this->OwnDisplay = 1;
sscanf(info,"%i",&tmp);
}
// Set this RenderWindow's X window id to a pre-existing window.
void vtkOSOpenGLRenderWindow::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 vtkOSOpenGLRenderWindow::SetParentInfo(char *info)
{
int tmp;
// get the default display connection
this->OwnDisplay = 1;
sscanf(info,"%i",&tmp);
// this->SetParentId(tmp);
}
void vtkOSOpenGLRenderWindow::SetWindowId(void *arg)
{
(void)arg;
// this->SetWindowId((Window)arg);
}
void vtkOSOpenGLRenderWindow::SetParentId(void *arg)
{
(void)arg;
// this->SetParentId((Window)arg);
}
const char* vtkOSOpenGLRenderWindow::ReportCapabilities()
{
MakeCurrent();
// int scrnum = DefaultScreen(this->DisplayId);
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);
std::ostringstream strm;
strm << "OpenGL vendor string: " << glVendor << endl;
strm << "OpenGL renderer string: " << glRenderer << endl;
strm << "OpenGL version string: " << glVersion << endl;
strm << "OpenGL extensions: " << glExtensions << 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;
}
int vtkOSOpenGLRenderWindow::SupportsOpenGL()
{
MakeCurrent();
return 1;
}
int vtkOSOpenGLRenderWindow::IsDirect()
{
MakeCurrent();
return 0;
}
void vtkOSOpenGLRenderWindow::SetWindowName(const char * cname)
{
char *name = new char[ strlen(cname)+1 ];
strcpy(name, cname);
vtkOpenGLRenderWindow::SetWindowName( name );
delete [] name;
}
// Specify the X window id to use if a WindowRemap is done.
/*void vtkOSOpenGLRenderWindow::SetNextWindowId(Window arg)
{
vtkDebugMacro(<< "Setting NextWindowId to " << (void *)arg << "\n");
this->NextWindowId = arg;
}*/
void vtkOSOpenGLRenderWindow::SetNextWindowId(void *arg)
{
(void)arg;
// this->SetNextWindowId((Window)arg);
}
// Set the X display id for this RenderWindow to use to a pre-existing
// X display id.
/*void vtkOSOpenGLRenderWindow::SetDisplayId(Display *arg)
{
vtkDebugMacro(<< "Setting DisplayId to " << (void *)arg << "\n");
this->DisplayId = arg;
this->OwnDisplay = 0;
}*/
/*void vtkOSOpenGLRenderWindow::SetDisplayId(void *arg)
{
this->SetDisplayId((Display *)arg);
this->OwnDisplay = 0;
}*/
//============================================================================
// Stuff above this is almost a mirror of vtkOSOpenGLRenderWindow.
// 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 vtkOSOpenGLRenderWindow like the other OpenGL classes.
//============================================================================
void vtkOSOpenGLRenderWindow::SetOffScreenRendering(int i)
{
if (this->OffScreenRendering == i)
{
return;
}
// invoke super
this->vtkRenderWindow::SetOffScreenRendering(i);
this->Internal->ScreenDoubleBuffer = this->DoubleBuffer;
this->DoubleBuffer = 0;
if(this->Mapped)
{
this->DestroyWindow();
}
// delay initialization until Render
}
// This probably has been moved to superclass.
void *vtkOSOpenGLRenderWindow::GetGenericWindowId()
{
return (void *)this->Internal->OffScreenWindow;
}
void vtkOSOpenGLRenderWindow::SetCurrentCursor(int shape)
{
if ( this->InvokeEvent(vtkCommand::CursorChangedEvent,&shape) )
{
return;
}
this->Superclass::SetCurrentCursor(shape);
}