Kaydet (Commit) 0bea1d80 authored tarafından Michael Meeks's avatar Michael Meeks

vcl: reset OpenGLContext(s) when yielding the last SolarMutex.

This should make OpenGL thread-safe to allow multiple threads to
render using VCL's OpenGL backend, and fix misc. associated driver
horrors, will give some performance cost for tight Yield loops.

Change-Id: Ib23702262fd9f0925a5ed8c642d0a26e92136b37
üst 3b52c449
...@@ -199,8 +199,14 @@ public: ...@@ -199,8 +199,14 @@ public:
OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader );
bool isCurrent(); bool isCurrent();
void clearCurrent(); static void clearCurrent();
/// reset all contexts dis-associating them with their underlying
/// resources before a potential thread switch.
static void resetAllContexts();
/// make this GL context current - so it is implicit in subsequent GL calls
void makeCurrent(); void makeCurrent();
/// reset the GL context so this context is not implicit in subsequent GL calls.
void resetCurrent(); void resetCurrent();
void swapBuffers(); void swapBuffers();
void sync(); void sync();
......
...@@ -21,8 +21,9 @@ ...@@ -21,8 +21,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "osl/module.hxx" #include <osl/module.hxx>
#include "tools/solarmutex.hxx" #include <tools/solarmutex.hxx>
#include <vcl/opengl/OpenGLContext.hxx>
#include "generic/geninst.h" #include "generic/geninst.h"
...@@ -53,7 +54,10 @@ void SalYieldMutex::release() ...@@ -53,7 +54,10 @@ void SalYieldMutex::release()
if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
{ {
if ( mnCount == 1 ) if ( mnCount == 1 )
{
OpenGLContext::resetAllContexts();
mnThreadId = 0; mnThreadId = 0;
}
mnCount--; mnCount--;
} }
m_mutex.release(); m_mutex.release();
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "vcl/window.hxx" #include "vcl/window.hxx"
#include "vcl/timer.hxx" #include "vcl/timer.hxx"
#include "vcl/svmain.hxx" #include "vcl/svmain.hxx"
#include "vcl/opengl/OpenGLContext.hxx"
#include "osx/saldata.hxx" #include "osx/saldata.hxx"
#include "osx/salinst.h" #include "osx/salinst.h"
...@@ -269,7 +270,10 @@ void SalYieldMutex::release() ...@@ -269,7 +270,10 @@ void SalYieldMutex::release()
if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) if ( mnThreadId == osl::Thread::getCurrentIdentifier() )
{ {
if ( mnCount == 1 ) if ( mnCount == 1 )
{
OpenGLContext::resetAllContexts();
mnThreadId = 0; mnThreadId = 0;
}
mnCount--; mnCount--;
} }
m_mutex.release(); m_mutex.release();
......
...@@ -82,6 +82,9 @@ OpenGLContext::OpenGLContext(): ...@@ -82,6 +82,9 @@ OpenGLContext::OpenGLContext():
else else
pSVData->maGDIData.mpFirstContext = this; pSVData->maGDIData.mpFirstContext = this;
pSVData->maGDIData.mpLastContext = this; pSVData->maGDIData.mpLastContext = this;
// FIXME: better hope we call 'makeCurrent' soon to preserve
// the invariant that the last item is the current context.
} }
OpenGLContext::~OpenGLContext() OpenGLContext::~OpenGLContext()
...@@ -1289,6 +1292,22 @@ void OpenGLContext::clearCurrent() ...@@ -1289,6 +1292,22 @@ void OpenGLContext::clearCurrent()
pCurrentCtx->ReleaseFramebuffers(); pCurrentCtx->ReleaseFramebuffers();
} }
void OpenGLContext::resetAllContexts()
{
ImplSVData* pSVData = ImplGetSVData();
// release all framebuffers from the old context so we can re-attach the
// texture in the new context
for (OpenGLContext* l = pSVData->maGDIData.mpLastContext; l;
l = l->mpPrevContext)
{
l->ReleaseFramebuffers();
if (l->isCurrent())
l->resetCurrent();
assert (!l->mpNextContext || l->mpNextContext->mpPrevContext == l);
}
}
void OpenGLContext::makeCurrent() void OpenGLContext::makeCurrent()
{ {
ImplSVData* pSVData = ImplGetSVData(); ImplSVData* pSVData = ImplGetSVData();
...@@ -1318,7 +1337,7 @@ void OpenGLContext::makeCurrent() ...@@ -1318,7 +1337,7 @@ void OpenGLContext::makeCurrent()
} }
#endif #endif
// move the context at the end of the contexts list // move the context to the end of the contexts list
static int nSwitch = 0; static int nSwitch = 0;
SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********"); SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********");
if( mpNextContext ) if( mpNextContext )
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <vcl/apptypes.hxx> #include <vcl/apptypes.hxx>
#include <vcl/opengl/OpenGLHelper.hxx> #include <vcl/opengl/OpenGLHelper.hxx>
#include <vcl/opengl/OpenGLContext.hxx>
#include <vcl/timer.hxx> #include <vcl/timer.hxx>
#include <opengl/salbmp.hxx> #include <opengl/salbmp.hxx>
...@@ -148,6 +149,8 @@ void SalYieldMutex::release() ...@@ -148,6 +149,8 @@ void SalYieldMutex::release()
{ {
if ( mnCount == 1 ) if ( mnCount == 1 )
{ {
OpenGLContext::resetAllContexts();
// If we don't call these message, the Output from the // If we don't call these message, the Output from the
// Java clients doesn't come in the right order // Java clients doesn't come in the right order
GdiFlush(); GdiFlush();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment