Commit c15a4dac authored by Ken Martin's avatar Ken Martin Committed by Kitware Robot
Browse files

Merge topic 'updated_supports_opengl'

fee87449 Try using pbuffer as drawable for checking openGL support
1f4ff9d8 Improve testing for OpenGL support
aa456d97 Fix handling of failed pixel formats
affc0d94 Update SupportsOpenGL for X Windows
3a8e4497 Try to cleanup the release graphcis resources some
804902b1 Update Cocoas check for OpenGL support
d9b727cc

 Start working on better checking for OpenGL2 support
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !933
parents 5589c067 fee87449
......@@ -163,6 +163,23 @@ vtkRenderer::~vtkRenderer()
}
}
void vtkRenderer::ReleaseGraphicsResources(vtkWindow *renWin)
{
if(this->BackgroundTexture != 0)
{
this->BackgroundTexture->ReleaseGraphicsResources(renWin);
}
vtkProp *aProp;
vtkCollectionSimpleIterator pit;
this->Props->InitTraversal(pit);
for ( aProp = this->Props->GetNextProp(pit);
aProp != NULL;
aProp = this->Props->GetNextProp(pit) )
{
aProp->ReleaseGraphicsResources(renWin);
}
}
// Concrete render method.
void vtkRenderer::Render(void)
{
......
......@@ -505,7 +505,7 @@ public:
vtkBooleanMacro(TexturedBackground,bool);
// method to release graphics resources in any derived renderers.
virtual void ReleaseGraphicsResources(vtkWindow *) { }
virtual void ReleaseGraphicsResources(vtkWindow *);
// Description:
// Turn on/off rendering of shadows if supported
......
......@@ -47,6 +47,13 @@ int TestVBOPLYMapper(int argc, char *argv[])
vtkNew<vtkLightKit> lightKit;
lightKit->AddLightsToRenderer(renderer.Get());
if (!renderWindow->SupportsOpenGL())
{
cerr << "The platform does not support OpenGL as required\n";
cerr << renderWindow->ReportCapabilities();
return 1;
}
const char* fileName = vtkTestUtilities::ExpandDataFileName(argc, argv,
"Data/dragon.ply");
vtkNew<vtkPLYReader> reader;
......
......@@ -277,20 +277,8 @@ void vtkCocoaRenderWindow::DestroyWindow()
if (this->OwnContext && this->GetContextId())
{
this->MakeCurrent();
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
vtkCollectionSimpleIterator rsit;
vtkRenderer *ren;
for ( this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
ren->SetRenderWindow(this);
}
this->ReleaseGraphicsResources();
}
this->ReleaseGraphicsResources(this);
}
this->SetContextId(NULL);
this->SetPixelFormat(NULL);
......@@ -482,12 +470,25 @@ const char* vtkCocoaRenderWindow::ReportCapabilities()
//----------------------------------------------------------------------------
int vtkCocoaRenderWindow::SupportsOpenGL()
{
#ifdef GLEW_OK
this->CreateGLContext();
this->MakeCurrent();
if (!this->GetContextId() || !this->GetPixelFormat())
GLenum result = glewInit();
bool m_valid = (result == GLEW_OK);
if (!m_valid)
{
return 0;
}
return 1;
if (GLEW_VERSION_3_2 || (GLEW_VERSION_2_1 && GLEW_EXT_gpu_shader4))
{
return 1;
}
#endif
return 0;
}
//----------------------------------------------------------------------------
......
......@@ -368,7 +368,7 @@ void vtkEGLRenderWindow::ResizeWindow(int width, int height)
void vtkEGLRenderWindow::DestroyWindow()
{
vtkInternals* impl = this->Internals;
this->ReleaseGraphicsResources();
this->ReleaseGraphicsResources(this);
if (this->OwnWindow && this->Mapped && impl->Display != EGL_NO_DISPLAY)
{
// make sure all other code knows we're not mapped anymore
......
......@@ -83,15 +83,7 @@ void vtkGenericOpenGLRenderWindow::Finalize()
// 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);
}
this->ReleaseGraphicsResources(this);
}
void vtkGenericOpenGLRenderWindow::Frame()
......
......@@ -92,19 +92,8 @@ void vtkIOSRenderWindow::DestroyWindow()
if (this->OwnContext && this->GetContextId())
{
this->MakeCurrent();
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
vtkCollectionSimpleIterator rsit;
vtkRenderer *ren;
for ( this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
ren->SetRenderWindow(this);
}
}
this->ReleaseGraphicsResources(this);
}
this->SetContextId(NULL);
this->SetPixelFormat(NULL);
......
......@@ -153,20 +153,7 @@ void vtkOSOpenGLRenderWindow::CreateAWindow()
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);
}
this->ReleaseGraphicsResources(this);
delete[] this->Capabilities;
this->Capabilities = 0;
......@@ -224,17 +211,7 @@ void vtkOSOpenGLRenderWindow::DestroyOffScreenWindow()
// this call invokes Renderer's ReleaseGraphicsResources
// method which only invokes ReleaseGraphicsResources on
// rendering passes.
this->ReleaseGraphicsResources();
vtkRenderer *ren;
vtkCollectionSimpleIterator rit;
this->Renderers->InitTraversal(rit);
while ( (ren = this->Renderers->GetNextRenderer(rit)) )
{
ren->SetRenderWindow(NULL);
ren->SetRenderWindow(this);
}
this->ReleaseGraphicsResources(this);
if (this->Internal->OffScreenContextId)
{
......
......@@ -141,7 +141,7 @@ vtkOpenGLRenderWindow::~vtkOpenGLRenderWindow()
}
// ----------------------------------------------------------------------------
void vtkOpenGLRenderWindow::ReleaseGraphicsResources()
void vtkOpenGLRenderWindow::ReleaseGraphicsResources(vtkRenderWindow *renWin)
{
vtkCollectionSimpleIterator rsit;
this->Renderers->InitTraversal(rsit);
......@@ -150,16 +150,16 @@ void vtkOpenGLRenderWindow::ReleaseGraphicsResources()
{
if (aren->GetRenderWindow() == this)
{
aren->ReleaseGraphicsResources(this);
aren->ReleaseGraphicsResources(renWin);
}
}
if(this->DrawPixelsTextureObject != 0)
{
this->DrawPixelsTextureObject->ReleaseGraphicsResources(this);
this->DrawPixelsTextureObject->ReleaseGraphicsResources(renWin);
}
this->ShaderCache->ReleaseGraphicsResources(this);
this->ShaderCache->ReleaseGraphicsResources(renWin);
if (this->TextureResourceIds.size())
{
......@@ -536,10 +536,13 @@ void vtkOpenGLRenderWindow::OpenGLInitContext()
if (!GLEW_VERSION_3_2)
{
if (!GLEW_VERSION_2_1)
if (!GLEW_VERSION_2_1 || !GLEW_EXT_gpu_shader4)
{
vtkErrorMacro("GL version 2.1 is not supported by your graphics driver.");
//m_valid = false;
vtkErrorMacro("GL version 2.1 with the gpu_shader4 extension is not "
"supported by your graphics driver but is required for the new "
"OpenGL rendering backend. Please update your OpenGL driver. "
"If you are using Mesa please make sure you have version 10.6.5 or "
"later and make sure your driver in Mesa supports OpenGL 3.2.");
return;
}
vtkWarningMacro(
......
......@@ -298,7 +298,8 @@ protected:
// Description:
// Free up any graphics resources associated with this window
virtual void ReleaseGraphicsResources();
// a value of NULL means the context may already be destroyed
virtual void ReleaseGraphicsResources(vtkRenderWindow *);
// Description:
// Set the texture unit manager.
......
......@@ -516,6 +516,7 @@ void vtkOpenGLRenderer::ReleaseGraphicsResources(vtkWindow *w)
{
this->ShadowMapPass->ReleaseGraphicsResources(w);
}
this->Superclass::ReleaseGraphicsResources(w);
}
void vtkOpenGLRenderer::UpdatePickId()
......
......@@ -115,14 +115,7 @@ void vtkWin32OpenGLRenderWindow::CleanUpRenderers()
// tell each of the renderers that this render window/graphics context
// is being removed (the RendererCollection is removed by vtkRenderWindow's
// destructor)
vtkRenderer *ren;
vtkCollectionSimpleIterator rsit;
for (this->Renderers->InitTraversal(rsit);
(ren = this->Renderers->GetNextRenderer(rsit));)
{
ren->SetRenderWindow(NULL);
}
this->ReleaseGraphicsResources();
this->ReleaseGraphicsResources(this);
}
LRESULT APIENTRY vtkWin32OpenGLRenderWindow::WndProc(HWND hWnd, UINT message,
......@@ -386,29 +379,82 @@ void vtkWin32OpenGLRenderWindow::Frame(void)
}
}
void vtkWin32OpenGLRenderWindow::VTKRegisterClass()
{
// has the class been registered ?
WNDCLASS wndClass;
#ifdef UNICODE
if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass))
#else
if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass))
#endif
{
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc;
wndClass.cbClsExtra = 0;
wndClass.hInstance = this->ApplicationInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = NULL;
#ifdef UNICODE
wndClass.lpszClassName = L"vtkOpenGL";
#else
wndClass.lpszClassName = "vtkOpenGL";
#endif
// vtk doesn't use the first extra vtkLONG's worth of bytes,
// but app writers may want them, so we provide them. VTK
// does use the second vtkLONG's worth of bytes of extra space.
wndClass.cbWndExtra = 2 * sizeof(vtkLONG);
RegisterClass(&wndClass);
}
}
int vtkWin32OpenGLRenderWindow::SupportsOpenGL()
{
MakeCurrent();
if (!this->DeviceContext)
#ifdef GLEW_OK
this->InitializeApplication();
this->VTKRegisterClass();
// Create a dummy window, needed for calling wglGetProcAddress.
#ifdef UNICODE
HWND tempId = CreateWindow(L"vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0);
#else
HWND tempId = CreateWindow("vtkOpenGL", 0, 0, 0, 0, 1, 1, 0, 0, this->ApplicationInstance, 0);
#endif
HDC tempDC = GetDC(tempId);
PIXELFORMATDESCRIPTOR tempPfd;
memset(&tempPfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
tempPfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
tempPfd.nVersion = 1;
tempPfd.dwFlags = PFD_SUPPORT_OPENGL | PFD_DRAW_TO_WINDOW;
tempPfd.iPixelType = PFD_TYPE_RGBA;
int tempPixelFormat = ChoosePixelFormat(tempDC, &tempPfd);
SetPixelFormat(tempDC, tempPixelFormat, &tempPfd);
HGLRC tempContext = wglCreateContext(tempDC);
wglMakeCurrent(tempDC, tempContext);
GLenum result = glewInit();
bool m_valid = (result == GLEW_OK);
if (!m_valid)
{
return 0;
}
int pixelFormat = GetPixelFormat(this->DeviceContext);
PIXELFORMATDESCRIPTOR pfd;
DescribePixelFormat(this->DeviceContext, pixelFormat,
sizeof(PIXELFORMATDESCRIPTOR), &pfd);
if (GLEW_VERSION_3_2 || (GLEW_VERSION_2_1 && GLEW_EXT_gpu_shader4))
{
return 1;
}
return (pfd.dwFlags & PFD_SUPPORT_OPENGL) ? 1:0;
#endif
return 0;
}
int vtkWin32OpenGLRenderWindow::IsDirect()
{
MakeCurrent();
this->MakeCurrent();
if (!this->DeviceContext)
{
return 0;
......@@ -427,7 +473,7 @@ int vtkWin32OpenGLRenderWindow::IsDirect()
const char* vtkWin32OpenGLRenderWindow::ReportCapabilities()
{
MakeCurrent();
this->MakeCurrent();
if (!this->DeviceContext)
{
......@@ -542,9 +588,7 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
// features like multisamples.
PIXELFORMATDESCRIPTOR pfd;
int pixelFormat = 0;
wglChoosePixelFormatARBType wglChoosePixelFormatARB =
reinterpret_cast<wglChoosePixelFormatARBType>(wglGetProcAddress("wglChoosePixelFormatARB"));
if ((dwFlags & PFD_DRAW_TO_WINDOW) && wglChoosePixelFormatARB)
if (wglChoosePixelFormatARB)
{
int attrib[] = {
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
......@@ -568,10 +612,12 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
attrib[n+1] = 8;
n += 2;
}
unsigned int stereoAttributeIndex = 0;
if (dwFlags & PFD_STEREO)
{
attrib[n] = WGL_STEREO_ARB;
attrib[n+1] = TRUE;
stereoAttributeIndex = n+1;
n += 2;
}
unsigned int multiSampleAttributeIndex = 0;
......@@ -586,19 +632,27 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
n += 4;
}
unsigned int numFormats;
if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats))
if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats)
|| numFormats == 0)
{
// If the requested number of multisamples does not work, try
// scaling down the number of multisamples a few times.
if (multiSampleAttributeIndex)
{
attrib[multiSampleAttributeIndex] /= 2;
if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats))
if (!wglChoosePixelFormatARB(hDC, attrib, 0, 1,
&pixelFormat, &numFormats) || numFormats == 0)
{
attrib[multiSampleAttributeIndex] /= 2;
wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats);
}
}
// try dropping stereo
if (stereoAttributeIndex && numFormats == 0)
{
attrib[stereoAttributeIndex] = FALSE;
wglChoosePixelFormatARB(hDC, attrib, 0, 1, &pixelFormat, &numFormats);
}
}
DescribePixelFormat(hDC, pixelFormat, sizeof(pfd), &pfd);
......@@ -615,16 +669,17 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
}
}
}
else
{
vtkErrorMacro("failed to get wglChoosePixelFormatARB");
}
// If we got a valid pixel format in the process, we are done.
// Otherwise, we use the old approach of using ChoosePixelFormat.
// see if we can get a 3.2 context
if (pixelFormat)
{
this->SetupPalette(hDC);
// create a context
#define USE_32_CONTEXT
#ifdef USE_32_CONTEXT
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB =
reinterpret_cast<PFNWGLCREATECONTEXTATTRIBSARBPROC>(wglGetProcAddress("wglCreateContextAttribsARB"));
if (wglCreateContextAttribsARB)
......@@ -634,8 +689,8 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
WGL_CONTEXT_MINOR_VERSION_ARB, 2,
WGL_CONTEXT_FLAGS_ARB, 0,
// WGL_CONTEXT_PROFILE_MASK_ARB,
// WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
// WGL_CONTEXT_PROFILE_MASK_ARB,
// WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB,
// WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB,
0 // End of attributes list
};
......@@ -647,7 +702,6 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
this->SetContextSupportsOpenGL32(true);
}
else
#endif
{
this->ContextId = wglCreateContext(hDC);
}
......@@ -664,110 +718,13 @@ void vtkWin32OpenGLRenderWindow::SetupPixelFormatPaletteAndContext(
::DestroyWindow(tempId); // windows api
// If we got a valid pixel format in the process, we are done.
// Otherwise, we use the old approach of using ChoosePixelFormat.
if (pixelFormat)
{
return;
}
BYTE bpp_byte = static_cast<BYTE>(bpp);
BYTE zbpp_byte = static_cast<BYTE>(zbpp);
PIXELFORMATDESCRIPTOR pfd2 = {
sizeof(PIXELFORMATDESCRIPTOR), /* size */
1, /* version */
dwFlags, /* support double-buffering */
PFD_TYPE_RGBA, /* color type */
bpp_byte, /* preferred color depth */
0, 0, 0, 0, 0, 0, /* color bits (ignored) */
static_cast<BYTE>(this->AlphaBitPlanes ? bpp/4 : 0), /* no alpha buffer */
0, /* alpha bits (ignored) */
0, /* no accumulation buffer */
0, 0, 0, 0, /* accum bits (ignored) */
zbpp_byte, /* depth buffer */
static_cast<BYTE>(this->StencilCapable), /* stencil buffer */
0, /* no auxiliary buffers */
PFD_MAIN_PLANE, /* main layer */
0, /* reserved */
0, 0, 0, /* no layer, visible, damage masks */
};
// Only try to set pixel format if we do not currently have one
int currentPixelFormat = GetPixelFormat(hDC);
// if there is a current pixel format, then make sure it
// supports OpenGL
if (currentPixelFormat != 0)
{
DescribePixelFormat(hDC, currentPixelFormat,sizeof(pfd2), &pfd2);
if (!(pfd2.dwFlags & PFD_SUPPORT_OPENGL))
{ // @note see https://msdn.microsoft.com/en-us/library/windows/desktop/dd369049(v=vs.85).aspx
// "Once a window's pixel format is set, it cannot be changed."
vtkErrorMacro("Call to DescribePixelFormat failed. "
"Illegal duplicate invocation or no OpenGL support.");
if (this->HasObserver(vtkCommand::ExitEvent))
{
this->InvokeEvent(vtkCommand::ExitEvent, NULL);
return;
}
}
}
else
{
// hDC has no current PixelFormat, so
pixelFormat = ChoosePixelFormat(hDC, &pfd2);
if (pixelFormat == 0)
{
#ifdef UNICODE
MessageBox(WindowFromDC(hDC), L"ChoosePixelFormat failed.", L"Error",
MB_ICONERROR | MB_OK);
#else
MessageBox(WindowFromDC(hDC), "ChoosePixelFormat failed.", "Error",
MB_ICONERROR | MB_OK);
#endif
if (this->HasObserver(vtkCommand::ExitEvent))
{
this->InvokeEvent(vtkCommand::ExitEvent, NULL);
return;
}
else
{
exit(1);
}
}
DescribePixelFormat(hDC, pixelFormat,sizeof(pfd2), &pfd2);
if (SetPixelFormat(hDC, pixelFormat, &pfd2) != TRUE)
{
// int err = GetLastError();
#ifdef UNICODE
MessageBox(WindowFromDC(hDC), L"SetPixelFormat failed.", L"Error",
MB_ICONERROR | MB_OK);
#else
MessageBox(WindowFromDC(hDC), "SetPixelFormat failed.", "Error",
MB_ICONERROR | MB_OK);
#endif
if (this->HasObserver(vtkCommand::ExitEvent))
{
this->InvokeEvent(vtkCommand::ExitEvent, NULL);
return;
}
else
{
exit(1);
}
}
}
if (debug && (dwFlags & PFD_STEREO) && !(pfd2.dwFlags & PFD_STEREO))
// Otherwise fail as the OpenGL does not support even 2.1
if (!pixelFormat)
{
vtkGenericWarningMacro("No Stereo Available!");
this->StereoCapableWindow = 0;
vtkErrorMacro("failed to get valid pixel format.");
}
this->SetupPalette(hDC);
// create a context
this->ContextId = wglCreateContext(hDC);
if (this->ContextId == NULL)
{
vtkErrorMacro("wglCreateContext failed in CreateAWindow(), error: " << GetLastError());
}
return;
}
void vtkWin32OpenGLRenderWindow::SetupPalette(HDC hDC)
......@@ -923,34 +880,7 @@ void vtkWin32OpenGLRenderWindow::InitializeApplication()
void vtkWin32OpenGLRenderWindow::CreateAWindow()
{
WNDCLASS wndClass;
// has the class been registered ?
#ifdef UNICODE
if (!GetClassInfo(this->ApplicationInstance,L"vtkOpenGL",&wndClass))
#else
if (!GetClassInfo(this->ApplicationInstance,"vtkOpenGL",&wndClass))
#endif
{
wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS;
wndClass.lpfnWndProc = vtkWin32OpenGLRenderWindow::WndProc;
wndClass.cbClsExtra = 0;
wndClass.hInstance = this->ApplicationInstance;
wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);