include/vcl/opengl/OpenGLContext.hxx | 8 +++- vcl/Executable_vcldemo.mk | 7 ++- vcl/generic/app/geninst.cxx | 8 +++- vcl/inc/unx/gtk/gtkinst.hxx | 5 -- vcl/osx/salinst.cxx | 4 ++ vcl/source/opengl/OpenGLContext.cxx | 21 ++++++++++ vcl/unx/gtk/app/gtkinst.cxx | 14 ------- vcl/win/source/app/salinst.cxx | 3 + vcl/workben/vcldemo.cxx | 67 ++++++++++++++++++++++++++++++----- 9 files changed, 104 insertions(+), 33 deletions(-)
New commits: commit fb97ade682fffa577b28b76b08e6b3c9737723e9 Author: Michael Meeks <[email protected]> Date: Tue Jan 6 16:09:09 2015 +0000 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 diff --git a/include/vcl/opengl/OpenGLContext.hxx b/include/vcl/opengl/OpenGLContext.hxx index a98f825..30e5261 100644 --- a/include/vcl/opengl/OpenGLContext.hxx +++ b/include/vcl/opengl/OpenGLContext.hxx @@ -222,8 +222,14 @@ public: OpenGLProgram* UseProgram( const OUString& rVertexShader, const OUString& rFragmentShader ); 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(); + /// reset the GL context so this context is not implicit in subsequent GL calls. void resetCurrent(); void swapBuffers(); void sync(); diff --git a/vcl/generic/app/geninst.cxx b/vcl/generic/app/geninst.cxx index cf2f301..5ac4936 100644 --- a/vcl/generic/app/geninst.cxx +++ b/vcl/generic/app/geninst.cxx @@ -21,8 +21,9 @@ #include <stdio.h> #include <stdlib.h> -#include "osl/module.hxx" -#include "tools/solarmutex.hxx" +#include <osl/module.hxx> +#include <tools/solarmutex.hxx> +#include <vcl/opengl/OpenGLContext.hxx> #include "generic/geninst.h" @@ -53,7 +54,10 @@ void SalYieldMutex::release() if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) { if ( mnCount == 1 ) + { + OpenGLContext::resetAllContexts(); mnThreadId = 0; + } mnCount--; } m_mutex.release(); diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index 5e81c6b..63735b9 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -31,6 +31,7 @@ #include "vcl/window.hxx" #include "vcl/timer.hxx" #include "vcl/svmain.hxx" +#include "vcl/opengl/OpenGLContext.hxx" #include "osx/saldata.hxx" #include "osx/salinst.h" @@ -269,7 +270,10 @@ void SalYieldMutex::release() if ( mnThreadId == osl::Thread::getCurrentIdentifier() ) { if ( mnCount == 1 ) + { + OpenGLContext::resetAllContexts(); mnThreadId = 0; + } mnCount--; } m_mutex.release(); diff --git a/vcl/source/opengl/OpenGLContext.cxx b/vcl/source/opengl/OpenGLContext.cxx index 578cc02..81029c3 100644 --- a/vcl/source/opengl/OpenGLContext.cxx +++ b/vcl/source/opengl/OpenGLContext.cxx @@ -82,6 +82,9 @@ OpenGLContext::OpenGLContext(): else pSVData->maGDIData.mpFirstContext = 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() @@ -1290,6 +1293,22 @@ void OpenGLContext::clearCurrent() 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() { ImplSVData* pSVData = ImplGetSVData(); @@ -1319,7 +1338,7 @@ void OpenGLContext::makeCurrent() } #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; SAL_INFO("vcl.opengl", "******* CONTEXT SWITCH " << ++nSwitch << " *********"); if( mpNextContext ) diff --git a/vcl/win/source/app/salinst.cxx b/vcl/win/source/app/salinst.cxx index 9e284eb..1091856 100644 --- a/vcl/win/source/app/salinst.cxx +++ b/vcl/win/source/app/salinst.cxx @@ -28,6 +28,7 @@ #include <vcl/apptypes.hxx> #include <vcl/opengl/OpenGLHelper.hxx> +#include <vcl/opengl/OpenGLContext.hxx> #include <vcl/timer.hxx> #include <opengl/salbmp.hxx> @@ -148,6 +149,8 @@ void SalYieldMutex::release() { if ( mnCount == 1 ) { + OpenGLContext::resetAllContexts(); + // If we don't call these message, the Output from the // Java clients doesn't come in the right order GdiFlush(); commit 26ea69b37ebf0df035c494d7ac831cb15db1f1b3 Author: Michael Meeks <[email protected]> Date: Tue Jan 6 16:08:37 2015 +0000 vcl: cleanup shared SalYieldMutex from GtkYieldMutex. Change-Id: I6ace72606ba666322c045d28bea713443c0fc45f diff --git a/vcl/inc/unx/gtk/gtkinst.hxx b/vcl/inc/unx/gtk/gtkinst.hxx index ceda303..3cabea3 100644 --- a/vcl/inc/unx/gtk/gtkinst.hxx +++ b/vcl/inc/unx/gtk/gtkinst.hxx @@ -41,10 +41,7 @@ class GtkYieldMutex : public SalYieldMutex std::list<sal_uLong> aYieldStack; public: - GtkYieldMutex(); - virtual void acquire() SAL_OVERRIDE; - virtual void release() SAL_OVERRIDE; - + GtkYieldMutex() {} void ThreadsEnter(); void ThreadsLeave(); }; diff --git a/vcl/unx/gtk/app/gtkinst.cxx b/vcl/unx/gtk/app/gtkinst.cxx index c2f56aa..7854adf 100644 --- a/vcl/unx/gtk/app/gtkinst.cxx +++ b/vcl/unx/gtk/app/gtkinst.cxx @@ -288,20 +288,6 @@ SalPrinter* GtkInstance::CreatePrinter( SalInfoPrinter* pInfoPrinter ) #endif } -GtkYieldMutex::GtkYieldMutex() -{ -} - -void GtkYieldMutex::acquire() -{ - SalYieldMutex::acquire(); -} - -void GtkYieldMutex::release() -{ - SalYieldMutex::release(); -} - /* * These methods always occur in pairs * A ThreadsEnter is followed by a ThreadsLeave commit 51d6e6dd676051c10b6299fa55e192aaf4f49339 Author: Michael Meeks <[email protected]> Date: Tue Jan 6 16:07:07 2015 +0000 vcldemo: extend threaded rendering test. Change-Id: I81e31e1e7442fd0c6d8d720dbd0e9d5cb82bf52b diff --git a/vcl/workben/vcldemo.cxx b/vcl/workben/vcldemo.cxx index 8ea37fd..8c46e59 100644 --- a/vcl/workben/vcldemo.cxx +++ b/vcl/workben/vcldemo.cxx @@ -14,6 +14,7 @@ #include <com/sun/star/registry/XSimpleRegistry.hpp> #include <com/sun/star/ucb/UniversalContentBroker.hpp> +#include <osl/time.h> #include <vcl/vclmain.hxx> #include <vcl/layout.hxx> #include <salhelper/thread.hxx> @@ -1200,12 +1201,14 @@ class DemoWin : public WorkWindow bool testThreads; class RenderThread : public salhelper::Thread { - DemoWin &mrWin; + DemoWin &mrWin; + TimeValue maDelay; public: - RenderThread(DemoWin &rWin) + RenderThread(DemoWin &rWin, sal_uInt32 nDelaySecs) : Thread("vcldemo render thread") , mrWin(rWin) { + maDelay.Seconds = nDelaySecs; launch(); } virtual ~RenderThread() @@ -1214,6 +1217,8 @@ class DemoWin : public WorkWindow } virtual void execute() { + osl_waitThread(&maDelay); + SolarMutexGuard aGuard; fprintf (stderr, "render from a different thread\n"); mrWin.Paint(Rectangle()); @@ -1242,7 +1247,10 @@ public: { if (testThreads) { // render this window asynchronously in a new thread - mxThread = new RenderThread(*this); + sal_uInt32 nDelaySecs = 0; + if (rMEvt.GetButtons() & MOUSE_RIGHT) + nDelaySecs = 5; + mxThread = new RenderThread(*this, nDelaySecs); } else { // spawn another window @@ -1388,6 +1396,12 @@ public: bWidgets = true; else if (aArg == "--threads") bThreads = true; + else if (aArg.startsWith("--")) + { + fprintf(stderr,"Unknown argument '%s'\n", + rtl::OUStringToOString(aArg, RTL_TEXTENCODING_UTF8).getStr()); + return showHelp(aRenderer); + } } DemoWin aMainWin(aRenderer, bThreads); commit 6c94733a8a7e8b0278e3d090180e08706978ba2f Author: Michael Meeks <[email protected]> Date: Tue Jan 6 15:09:53 2015 +0000 vcldemo: add threading mode. Change-Id: I6ad5524c518a79cac7ec343398242515ef0bbb5f diff --git a/vcl/Executable_vcldemo.mk b/vcl/Executable_vcldemo.mk index 44f13b2..9d2e55e 100644 --- a/vcl/Executable_vcldemo.mk +++ b/vcl/Executable_vcldemo.mk @@ -25,12 +25,13 @@ $(eval $(call gb_Executable_set_include,vcldemo,\ $(eval $(call gb_Executable_use_libraries,vcldemo,\ basegfx \ + comphelper \ + cppu \ + cppuhelper \ tl \ sal \ + salhelper \ vcl \ - cppu \ - cppuhelper \ - comphelper \ )) $(eval $(call gb_Executable_add_exception_objects,vcldemo,\ diff --git a/vcl/workben/vcldemo.cxx b/vcl/workben/vcldemo.cxx index 1b5a709..8ea37fd 100644 --- a/vcl/workben/vcldemo.cxx +++ b/vcl/workben/vcldemo.cxx @@ -16,6 +16,7 @@ #include <vcl/vclmain.hxx> #include <vcl/layout.hxx> +#include <salhelper/thread.hxx> #include <tools/urlobj.hxx> #include <tools/stream.hxx> @@ -1196,16 +1197,42 @@ class DemoWin : public WorkWindow { DemoRenderer &mrRenderer; bool underTesting; + bool testThreads; + + class RenderThread : public salhelper::Thread { + DemoWin &mrWin; + public: + RenderThread(DemoWin &rWin) + : Thread("vcldemo render thread") + , mrWin(rWin) + { + launch(); + } + virtual ~RenderThread() + { + join(); + } + virtual void execute() + { + SolarMutexGuard aGuard; + fprintf (stderr, "render from a different thread\n"); + mrWin.Paint(Rectangle()); + } + }; + rtl::Reference<RenderThread> mxThread; + public: - DemoWin(DemoRenderer &rRenderer) : + DemoWin(DemoRenderer &rRenderer, bool bThreads) : WorkWindow(NULL, WB_APP | WB_STDWORK), - mrRenderer(rRenderer) + mrRenderer(rRenderer), + testThreads(bThreads) { mrRenderer.addInvalidate(this); underTesting = false; } virtual ~DemoWin() { + mxThread.clear(); mrRenderer.removeInvalidate(this); } virtual void MouseButtonDown(const MouseEvent& rMEvt) SAL_OVERRIDE @@ -1213,9 +1240,16 @@ public: mrRenderer.SetSizePixel(GetSizePixel()); if (!mrRenderer.MouseButtonDown(rMEvt)) { - DemoWin *pNewWin = new DemoWin(mrRenderer); - pNewWin->SetText("Another interactive VCL demo window"); - pNewWin->Show(); + if (testThreads) + { // render this window asynchronously in a new thread + mxThread = new RenderThread(*this); + } + else + { // spawn another window + DemoWin *pNewWin = new DemoWin(mrRenderer, testThreads); + pNewWin->SetText("Another interactive VCL demo window"); + pNewWin->Show(); + } } } virtual void KeyInput(const KeyEvent& rKEvt) SAL_OVERRIDE @@ -1314,7 +1348,8 @@ class DemoApp : public Application fprintf(stderr," %s\n", rtl::OUStringToOString(aRenderers, RTL_TEXTENCODING_UTF8).getStr()); fprintf(stderr," --test <iterCount> - create benchmark data\n"); - fprintf(stderr, " --widgets - launch the widget test.\n"); + fprintf(stderr," --widgets - launch the widget test.\n"); + fprintf(stderr," --threads - render from multiple threads.\n"); fprintf(stderr, "\n"); return 0; } @@ -1326,7 +1361,7 @@ public: { try { - bool bWidgets = false; + bool bWidgets = false, bThreads = false; DemoRenderer aRenderer; for (sal_Int32 i = 0; i < GetCommandLineParamCount(); i++) @@ -1351,9 +1386,11 @@ public: } else if (aArg == "--widgets") bWidgets = true; + else if (aArg == "--threads") + bThreads = true; } - DemoWin aMainWin(aRenderer); + DemoWin aMainWin(aRenderer, bThreads); boost::scoped_ptr<DemoWidgets> aWidgets; aMainWin.SetText("Interactive VCL demo #1"); _______________________________________________ Libreoffice-commits mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
