Commit d0e64da3 authored by Ken Martin's avatar Ken Martin

work on better resource management for OpenGL

new approach to ReleaseGraphicsResources where objects
that use opengl resources can register themselves
with their current window/context so that when either they
delete or the context is deleted the resources will be
cleared correctly.
parent a1a94d0c
Pipeline #26477 passed with stage
......@@ -41,6 +41,7 @@ PURPOSE. See the above copyright notice for more information.
#define vtkCocoaRenderWindow_h
#include "vtkRenderingOpenGL2Module.h" // For export macro
#include <stack> // for ivar
#include "vtkOpenGLRenderWindow.h"
class VTKRENDERINGOPENGL2_EXPORT vtkCocoaRenderWindow : public vtkOpenGLRenderWindow
......@@ -292,10 +293,21 @@ public:
void SetPixelFormat(void *pixelFormat);
void *GetPixelFormat();
// Description
// Ability to push and pop this window's context
// as the current context. The idea being to
// if needed make this window's context current
// and when done releasing resources restore
// the prior context
virtual void PushContext();
virtual void PopContext();
protected:
vtkCocoaRenderWindow();
~vtkCocoaRenderWindow();
std::stack<void *> ContextStack;
void CreateGLContext();
void CreateAWindow();
......
......@@ -358,6 +358,29 @@ void vtkCocoaRenderWindow::MakeCurrent()
}
}
void vtkCocoaRenderWindow::PushContext()
{
NSOpenGLContext *current = [NSOpenGLContext currentContext];
NSOpenGLContext *mine = static_cast<NSOpenGLContext *>(this->GetContextId());
this->ContextStack.push(current);
if (current != mine)
{
this->MakeCurrent();
}
}
void vtkCocoaRenderWindow::PopContext()
{
NSOpenGLContext *current = [NSOpenGLContext currentContext];
NSOpenGLContext *target =
static_cast<NSOpenGLContext *>(this->ContextStack.top());
this->ContextStack.pop();
if (target != current)
{
[target makeCurrentContext];
}
}
// ----------------------------------------------------------------------------
// Description:
// Tells if this window is the current OpenGL context for the calling thread.
......
......@@ -23,6 +23,7 @@
#include "vtkPixelBufferObject.h"
#include "vtkOpenGLBufferObject.h"
#include "vtkOpenGLError.h"
#include "vtkOpenGLResourceFreeCallback.h"
#include <cassert>
#include <vector>
......@@ -44,11 +45,19 @@ vtkFrameBufferObject::vtkFrameBufferObject()
this->LastSize[0] = this->LastSize[1] = -1;
this->SetActiveBuffer(0);
this->NumberOfRenderTargets = 1;
this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkFrameBufferObject>(this,
&vtkFrameBufferObject::ReleaseGraphicsResources);
}
//----------------------------------------------------------------------------
vtkFrameBufferObject::~vtkFrameBufferObject()
{
if (this->ResourceCallback)
{
this->ResourceCallback->Release();
delete this->ResourceCallback;
this->ResourceCallback = NULL;
}
this->DestroyFBO();
this->DestroyDepthBuffer();
this->DestroyColorBuffers();
......@@ -119,20 +128,33 @@ bool vtkFrameBufferObject::LoadRequiredExtensions(vtkOpenGLRenderWindow *)
return fbo && fboBlit;
}
//----------------------------------------------------------------------------
void vtkFrameBufferObject::SetContext(vtkOpenGLRenderWindow *renWin)
void vtkFrameBufferObject::ReleaseGraphicsResources(vtkWindow *)
{
// avoid pointless re-assignment
if (this->Context==renWin)
if (!this->ResourceCallback->IsReleasing())
{
this->ResourceCallback->Release();
return;
}
// free previous resources
this->DestroyDepthBuffer();
this->DestroyColorBuffers();
this->DestroyFBO();
this->Context = NULL;
this->Modified();
}
//----------------------------------------------------------------------------
void vtkFrameBufferObject::SetContext(vtkOpenGLRenderWindow *renWin)
{
// avoid pointless re-assignment
if (this->Context==renWin)
{
return;
}
this->ResourceCallback->RegisterGraphicsResources(renWin);
// all done if assigned null
if (!renWin)
{
......
......@@ -38,6 +38,8 @@ class vtkPixelBufferObject;
class vtkOpenGLRenderWindow;
class vtkShaderProgram;
class vtkOpenGLVertexArrayObject;
class vtkGenericOpenGLResourceFreeCallback;
class vtkWindow;
class VTKRENDERINGOPENGL2_EXPORT vtkFrameBufferObject : public vtkFrameBufferObjectBase
{
......@@ -167,12 +169,18 @@ public:
// prints detected errors to vtkErrorMacro.
int CheckFrameBufferStatus(unsigned int mode);
// Description:
// Deactivate and UnBind
virtual void ReleaseGraphicsResources(vtkWindow *win);
protected:
// Description:
// Load all necessary extensions.
static
bool LoadRequiredExtensions(vtkOpenGLRenderWindow *renWin);
vtkGenericOpenGLResourceFreeCallback *ResourceCallback;
// gen buffer (occurs when context is set)
void CreateFBO();
......
......@@ -37,6 +37,7 @@
#include "vtkOpenGLRenderPass.h"
#include "vtkOpenGLRenderWindow.h"
#include "vtkOpenGLRenderer.h"
#include "vtkOpenGLResourceFreeCallback.h"
#include "vtkOpenGLShaderCache.h"
#include "vtkOpenGLTexture.h"
#include "vtkOpenGLVertexArrayObject.h"
......@@ -112,11 +113,19 @@ vtkOpenGLPolyDataMapper::vtkOpenGLPolyDataMapper()
this->LastLightComplexity[&this->TriStripsEdges] = -1;
this->TimerQuery = 0;
this->ResourceCallback = new vtkOpenGLResourceFreeCallback<vtkOpenGLPolyDataMapper>(this,
&vtkOpenGLPolyDataMapper::ReleaseGraphicsResources);
}
//-----------------------------------------------------------------------------
vtkOpenGLPolyDataMapper::~vtkOpenGLPolyDataMapper()
{
if (this->ResourceCallback)
{
this->ResourceCallback->Release();
delete this->ResourceCallback;
this->ResourceCallback = NULL;
}
if (this->InternalColorTexture)
{ // Resources released previously.
this->InternalColorTexture->Delete();
......@@ -167,13 +176,10 @@ vtkOpenGLPolyDataMapper::~vtkOpenGLPolyDataMapper()
//-----------------------------------------------------------------------------
void vtkOpenGLPolyDataMapper::ReleaseGraphicsResources(vtkWindow* win)
{
vtkOpenGLRenderWindow *rwin =
vtkOpenGLRenderWindow::SafeDownCast(win);
if (rwin)
if (!this->ResourceCallback->IsReleasing())
{
// Ensure that the context is current before releasing any
// graphics resources tied to it.
rwin->MakeCurrent();
this->ResourceCallback->Release();
return;
}
this->VBO->ReleaseGraphicsResources();
......@@ -2514,6 +2520,9 @@ void vtkOpenGLPolyDataMapper::RenderPiece(vtkRenderer* ren, vtkActor *actor)
return;
}
this->ResourceCallback->RegisterGraphicsResources(
static_cast<vtkOpenGLRenderWindow *>(ren->GetRenderWindow()));
this->CurrentInput = this->GetInput();
if (this->CurrentInput == NULL)
......
......@@ -36,6 +36,7 @@ class vtkOpenGLBufferObject;
class vtkOpenGLVertexBufferObject;
class vtkTextureObject;
class vtkTransform;
class vtkGenericOpenGLResourceFreeCallback;
class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLPolyDataMapper : public vtkPolyDataMapper
{
......@@ -185,6 +186,8 @@ protected:
vtkOpenGLPolyDataMapper();
~vtkOpenGLPolyDataMapper();
vtkGenericOpenGLResourceFreeCallback *ResourceCallback;
// the following is all extra stuff to work around the
// fact that gl_PrimitiveID does not work correctly on
// Apple devices with AMD graphics hardware. See apple
......
......@@ -39,6 +39,7 @@
#include "vtkTextureObject.h"
#include "vtkTextureUnitManager.h"
#include "vtkUnsignedCharArray.h"
#include "vtkOpenGLResourceFreeCallback.h"
#include "vtkTextureObjectVS.h" // a pass through shader
......@@ -166,6 +167,16 @@ vtkOpenGLRenderWindow::~vtkOpenGLRenderWindow()
// ----------------------------------------------------------------------------
void vtkOpenGLRenderWindow::ReleaseGraphicsResources(vtkRenderWindow *renWin)
{
// release the registered resources
std::set<vtkGenericOpenGLResourceFreeCallback *>::iterator it
= this->Resources.begin();
while (it != this->Resources.end() )
{
(*it)->Release();
it = this->Resources.begin();
}
vtkCollectionSimpleIterator rsit;
this->Renderers->InitTraversal(rsit);
vtkRenderer *aren;
......
......@@ -26,6 +26,7 @@
#include "vtkRenderWindow.h"
#include <string> // for ivar
#include <map> // for ivar
#include <set> // for ivar
#include "vtkType.h" // for ivar
class vtkIdList;
......@@ -37,6 +38,7 @@ class vtkStdString;
class vtkTexture;
class vtkTextureObject;
class vtkTextureUnitManager;
class vtkGenericOpenGLResourceFreeCallback;
class VTKRENDERINGOPENGL2_EXPORT vtkOpenGLRenderWindow : public vtkRenderWindow
{
......@@ -292,6 +294,37 @@ public:
// in-between. This is what WindowRemap does.
virtual void Initialize(void) {};
std::set<vtkGenericOpenGLResourceFreeCallback *> Resources;
void RegisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback *cb) {
std::set<vtkGenericOpenGLResourceFreeCallback *>::iterator it
= this->Resources.find(cb);
if (it == this->Resources.end())
{
this->Resources.insert(cb);
}
}
void UnregisterGraphicsResources(vtkGenericOpenGLResourceFreeCallback *cb)