Index: trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c	(revision 52559)
+++ trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.c	(revision 52560)
@@ -316,4 +316,96 @@
 }
 
+WindowInfo* renderspuWinCreate(GLint visBits, GLint id)
+{
+    WindowInfo* window = (WindowInfo *)crAlloc(sizeof (*window));
+    if (!window)
+    {
+        crWarning("crAlloc failed");
+        return NULL;
+    }
+
+    if (!renderspuWinInit(window, NULL, visBits, id))
+    {
+        crWarning("renderspuWinInit failed");
+        crFree(window);
+        return NULL;
+    }
+
+    return window;
+}
+
+void renderspuWinTermOnShutdown(WindowInfo *window)
+{
+    renderspuVBoxCompositorSet(window, NULL);
+    renderspuVBoxPresentBlitterCleanup(window);
+    renderspu_SystemDestroyWindow( window );
+    window->BltInfo.Base.id = -1;
+}
+
+static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
+{
+    ContextInfo *pCtx = (ContextInfo *) data1;
+    WindowInfo *pWindow = data2;
+    (void) key;
+
+    if (pCtx->currentWindow==pWindow)
+    {
+        WindowInfo* pDummy = renderspuGetDummyWindow(pCtx->BltInfo.Base.visualBits);
+        if (pDummy)
+        {
+            renderspuPerformMakeCurrent(pDummy, 0, pCtx);
+        }
+        else
+        {
+            crWarning("failed to get dummy window");
+            renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
+        }
+    }
+}
+
+void renderspuWinTerm( WindowInfo *window )
+{
+    if (!renderspuWinIsTermed(window))
+    {
+
+    GET_CONTEXT(pOldCtx);
+    WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
+    CRASSERT(!pOldCtx == !pOldWindow);
+    /* ensure no concurrent draws can take place */
+    renderspuWinTermOnShutdown(window);
+    /* check if this window is bound to some ctx. Note: window pointer is already freed here */
+    crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
+    /* restore current context */
+    {
+        GET_CONTEXT(pNewCtx);
+        WindowInfo * pNewWindow = pNewCtx ? pNewCtx->currentWindow : NULL;
+        CRASSERT(!pNewCtx == !pNewWindow);
+
+        if (pOldWindow == window)
+            renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
+        else if (pNewCtx != pOldCtx || pOldWindow != pNewWindow)
+        {
+            if (pOldCtx)
+                renderspuPerformMakeCurrent(pOldWindow, 0, pOldCtx);
+            else
+                renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
+        }
+    }
+
+    }
+}
+
+void renderspuWinCleanup(WindowInfo *window)
+{
+    renderspuWinTerm( window );
+    RTCritSectDelete(&window->CompositorLock);
+}
+
+void renderspuWinDestroy(WindowInfo *window)
+{
+    renderspuWinCleanup(window);
+    crFree(window);
+}
+
 WindowInfo* renderspuGetDummyWindow(GLint visBits)
 {
@@ -321,15 +413,8 @@
     if (!window)
     {
-        window = (WindowInfo *)crAlloc(sizeof (*window));
+        window = renderspuWinCreate(visBits, -1);
         if (!window)
         {
-            crWarning("crAlloc failed");
-            return NULL;
-        }
-
-        if (!renderspuWindowInit(window, NULL, visBits, -1))
-        {
-            crWarning("renderspuWindowInit failed");
-            crFree(window);
+            WARN(("renderspuWinCreate failed"));
             return NULL;
         }
@@ -446,5 +531,5 @@
 }
 
-GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id )
+GLboolean renderspuWinInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id )
 {
     crMemset(window, 0, sizeof (*window));
@@ -494,4 +579,6 @@
     window->visible = !!showIt;
 
+    window->cRefs = 1;
+
     CRASSERT(window->visual == visual);
     return GL_TRUE;
@@ -501,5 +588,5 @@
  * Window functions
  */
-GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
+GLboolean renderspuWinInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
 {
     VisualInfo *visual;
@@ -521,5 +608,5 @@
     */
     /* Have GLX/WGL/AGL create the window */
-    if (!renderspuWindowInitWithVisual( pWindow, visual, 0, id ))
+    if (!renderspuWinInitWithVisual( pWindow, visual, 0, id ))
     {
         crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
@@ -553,14 +640,9 @@
 
     /* Allocate WindowInfo */
-    window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
+    window = renderspuWinCreate(visBits, id);
+
     if (!window)
     {
-        crWarning( "Render SPU: Couldn't create a window" );
-        return -1;
-    }
-    
-    if (!renderspuWindowInit(window, dpyName, visBits, id))
-    {
-        crWarning("renderspuWindowInit failed");
+        crWarning("renderspuWinCreate failed");
         crFree(window);
         return -1;
@@ -577,58 +659,7 @@
 }
 
-static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
-{
-    ContextInfo *pCtx = (ContextInfo *) data1;
-    WindowInfo *pWindow = data2;
-    (void) key;
-
-    if (pCtx->currentWindow==pWindow)
-    {
-        WindowInfo* pDummy = renderspuGetDummyWindow(pCtx->BltInfo.Base.visualBits);
-        if (pDummy)
-        {
-            renderspuPerformMakeCurrent(pDummy, 0, pCtx);
-        }
-        else
-        {
-            crWarning("failed to get dummy window");
-            renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, pCtx->BltInfo.Base.id);
-        }
-    }
-}
-
-void renderspuWindowTermBase( WindowInfo *window )
-{
-    renderspuVBoxCompositorSet(window, NULL);
-    renderspuVBoxPresentBlitterCleanup(window);
-    renderspu_SystemDestroyWindow( window );
-    RTCritSectDelete(&window->CompositorLock);
-}
-
-void renderspuWindowTerm( WindowInfo *window )
-{
-    GET_CONTEXT(pOldCtx);
-    WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
-    CRASSERT(!pOldCtx == !pOldWindow);
-    /* ensure no concurrent draws can take place */
-    renderspuWindowTermBase(window);
-    /* check if this window is bound to some ctx. Note: window pointer is already freed here */
-    crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);
-    /* restore current context */
-    {
-        GET_CONTEXT(pNewCtx);
-        WindowInfo * pNewWindow = pNewCtx ? pNewCtx->currentWindow : NULL;
-        CRASSERT(!pNewCtx == !pNewWindow);
-
-        if (pOldWindow == window)
-            renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
-        else if (pNewCtx != pOldCtx || pOldWindow != pNewWindow)
-        {
-            if (pOldCtx)
-                renderspuPerformMakeCurrent(pOldWindow, 0, pOldCtx);
-            else
-                renderspuMakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
-        }
-    }
+void renderspuWinReleaseCb(void*pvWindow)
+{
+    renderspuWinRelease((WindowInfo*)pvWindow);
 }
 
@@ -647,8 +678,12 @@
     if (window) {
         crDebug("Render SPU: Destroy window (%d)", win);
-        renderspuWindowTerm( window );
+        /* since os-specific backend can hold its own reference to the window object (e.g. on OSX),
+         * we need to explicitly issue a window destroy command
+         * this ensures the backend will eventually release the reference,
+         * the window object itself will remain valid until its ref count reaches zero */
+        renderspuWinTerm( window );
 
         /* remove window info from hash table, and free it */
-        crHashtableDelete(render_spu.windowTable, win, crFree);
+        crHashtableDelete(render_spu.windowTable, win, renderspuWinReleaseCb);
 
     }
Index: trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.h	(revision 52559)
+++ trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu.h	(revision 52560)
@@ -98,4 +98,7 @@
 
     VisualInfo *visual;
+
+    volatile uint32_t cRefs;
+
     GLboolean mapPending;
     GLboolean visible;
@@ -432,10 +435,33 @@
 extern PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData, bool fRedraw );
 extern PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData );
-void renderspuWindowTermBase( WindowInfo *window );
-extern void renderspuWindowTerm( WindowInfo *window );
+WindowInfo* renderspuWinCreate(GLint visBits, GLint id);
+void renderspuWinTermOnShutdown(WindowInfo *window);
+void renderspuWinTerm( WindowInfo *window );
+void renderspuWinCleanup(WindowInfo *window);
+void renderspuWinDestroy(WindowInfo *window);
+GLboolean renderspuWinInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id );
+GLboolean renderspuWinInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id);
+
+DECLINLINE(void) renderspuWinRetain(WindowInfo *window)
+{
+    ASMAtomicIncU32(&window->cRefs);
+}
+
+DECLINLINE(bool) renderspuWinIsTermed(WindowInfo *window)
+{
+    return window->BltInfo.Base.id < 0;
+}
+
+DECLINLINE(void) renderspuWinRelease(WindowInfo *window)
+{
+    uint32_t cRefs = ASMAtomicDecU32(&window->cRefs);
+    if (!cRefs)
+    {
+        renderspuWinDestroy(window);
+    }
+}
+
 extern WindowInfo* renderspuGetDummyWindow(GLint visBits);
 extern void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow, ContextInfo *context);
-extern GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id);
-extern GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id );
 extern GLboolean renderspuInitVisual(VisualInfo *pVisInfo, const char *displayName, GLbitfield visAttribs);
 extern void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter);
Index: trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m	(revision 52559)
+++ trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m	(revision 52560)
@@ -1413,4 +1413,7 @@
         [self performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];
     }
+    
+    renderspuWinRelease(m_pWinInfo);
+    
     DEBUG_FUNC_LEAVE();
 }
@@ -2479,4 +2482,6 @@
     /* make sure all tasks are run, to preserve the order */
     [pRunner runTasksSyncIfPossible];
+    
+    renderspuWinRetain(pWinInfo);
 
     if (renderspuCalloutAvailable())
@@ -2501,4 +2506,7 @@
 #endif
     }
+    
+    if (!*ppView)
+        renderspuWinRelease(pWinInfo);
     
     [pPool release];
Index: trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c	(revision 52559)
+++ trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c	(revision 52560)
@@ -448,5 +448,5 @@
             if (bRc)
             {
-                bRc = renderspuWindowInitWithVisual(&render_spu.WinCmdWindow, &render_spu.WinCmdVisual, GL_FALSE, CR_RENDER_WINCMD_ID);
+                bRc = renderspuWinInitWithVisual(&render_spu.WinCmdWindow, &render_spu.WinCmdVisual, GL_FALSE, CR_RENDER_WINCMD_ID);
                 if (bRc)
                 {
@@ -458,5 +458,5 @@
                 else
                 {
-                    crError("renderspuWindowInitWithVisual failed");
+                    crError("renderspuWinInitWithVisual failed");
                 }
                 /* there is no visual destroy impl currently
@@ -486,5 +486,5 @@
     /* the window is not in the table, this will just ensure the key is freed */
     crHashtableDelete(render_spu.windowTable, CR_RENDER_WINCMD_ID, NULL);
-    renderspuWindowTerm(&render_spu.WinCmdWindow);
+    renderspuWinCleanup(&render_spu.WinCmdWindow);
     crFreeHashtable(render_spu.pWinToInfoTable, NULL);
     /* we do not have visual destroy functionality 
Index: trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
===================================================================
--- trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c	(revision 52559)
+++ trunk/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c	(revision 52560)
@@ -428,6 +428,6 @@
 {
     WindowInfo *window = (WindowInfo *) data;
-    renderspuWindowTermBase(window);
-    crFree(window);
+    renderspuWinTermOnShutdown(window);
+    renderspuWinRelease(window);
 }
 
