summaryrefslogtreecommitdiff
path: root/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL/render/renderspu.c')
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu.c976
1 files changed, 823 insertions, 153 deletions
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
index 1446473e..b907c6a9 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu.c
@@ -9,9 +9,14 @@
#include "cr_error.h"
#include "cr_mem.h"
#include "cr_spu.h"
+#include "cr_environment.h"
#include "renderspu.h"
#include "cr_extstring.h"
+#include <iprt/asm.h>
+
+uint32_t renderspuContextRelease(ContextInfo *context);
+uint32_t renderspuContextRetain(ContextInfo *context);
static void
DoSync(void)
@@ -78,6 +83,12 @@ renderspuMakeVisString( GLbitfield visAttribs, char *s )
crStrcat(s, ", PBuffer");
}
+GLboolean renderspuInitVisual(VisualInfo *pVisInfo, const char *displayName, GLbitfield visAttribs)
+{
+ pVisInfo->displayName = crStrdup(displayName);
+ pVisInfo->visAttribs = visAttribs;
+ return renderspu_SystemInitVisual(pVisInfo);
+}
/*
* Find a VisualInfo which matches the given display name and attribute
@@ -115,9 +126,7 @@ renderspuFindVisual(const char *displayName, GLbitfield visAttribs)
/* create a new visual */
i = render_spu.numVisuals;
- render_spu.visuals[i].displayName = crStrdup(displayName);
- render_spu.visuals[i].visAttribs = visAttribs;
- if (renderspu_SystemInitVisual(&(render_spu.visuals[i]))) {
+ if (renderspuInitVisual(&(render_spu.visuals[i]), displayName, visAttribs)) {
render_spu.numVisuals++;
return &(render_spu.visuals[i]);
}
@@ -127,79 +136,212 @@ renderspuFindVisual(const char *displayName, GLbitfield visAttribs)
}
}
-/*
- * Context functions
- */
-
-GLint RENDER_APIENTRY
-renderspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx)
+static ContextInfo * renderspuCreateContextInternal(const char *dpyName, GLint visBits, GLint idCtx, ContextInfo * sharedContext)
{
- ContextInfo *context, *sharedContext = NULL;
+ ContextInfo *context;
VisualInfo *visual;
- if (shareCtx > 0) {
- sharedContext
- = (ContextInfo *) crHashtableSearch(render_spu.contextTable, shareCtx);
+ if (idCtx <= 0)
+ {
+ idCtx = (GLint)crHashtableAllocKeys(render_spu.contextTable, 1);
+ if (idCtx <= 0)
+ {
+ crWarning("failed to allocate context id");
+ return NULL;
+ }
}
+ else
+ {
+ if (crHashtableIsKeyUsed(render_spu.contextTable, idCtx))
+ {
+ crWarning("the specified ctx key %d is in use", idCtx);
+ return NULL;
+ }
+ }
+
if (!dpyName || crStrlen(render_spu.display_string)>0)
dpyName = render_spu.display_string;
visual = renderspuFindVisual(dpyName, visBits);
if (!visual)
- return -1;
+ return NULL;
context = (ContextInfo *) crCalloc(sizeof(ContextInfo));
if (!context)
- return -1;
- context->id = render_spu.context_id;
+ return NULL;
+ context->BltInfo.Base.id = idCtx;
context->shared = sharedContext;
if (!renderspu_SystemCreateContext(visual, context, sharedContext))
- return -1;
+ return NULL;
- crHashtableAdd(render_spu.contextTable, render_spu.context_id, context);
- render_spu.context_id++;
+ crHashtableAdd(render_spu.contextTable, idCtx, context);
+ context->BltInfo.Base.visualBits = visual->visAttribs;
/*
crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d",
- dpyName, visBits, context->id);
+ dpyName, visBits, context->BltInfo.Base.id);
*/
- return context->id;
-}
+ if (sharedContext)
+ renderspuContextRetain(sharedContext);
+ context->cRefs = 1;
-static void RENDER_APIENTRY
-renderspuDestroyContext( GLint ctx )
+ return context;
+}
+
+GLint renderspuCreateContextEx(const char *dpyName, GLint visBits, GLint id, GLint shareCtx)
{
- ContextInfo *context;
+ ContextInfo *context, *sharedContext = NULL;
- CRASSERT(ctx);
+ if (shareCtx) {
+ sharedContext
+ = (ContextInfo *) crHashtableSearch(render_spu.contextTable, shareCtx);
+ CRASSERT(sharedContext);
+ }
- context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
- CRASSERT(context);
+ context = renderspuCreateContextInternal(dpyName, visBits, id, sharedContext);
+ if (context)
+ return context->BltInfo.Base.id;
+ return -1;
+}
+
+/*
+ * Context functions
+ */
+
+GLint RENDER_APIENTRY
+renderspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx)
+{
+ return renderspuCreateContextEx(dpyName, visBits, 0, shareCtx);
+}
+
+static void renderspuDestroyContextTerminate( ContextInfo *context )
+{
+ CRASSERT(context->BltInfo.Base.id == -1);
renderspu_SystemDestroyContext( context );
if (context->extensionString) {
crFree(context->extensionString);
context->extensionString = NULL;
}
- crHashtableDelete(render_spu.contextTable, ctx, crFree);
+
+ if (context->shared)
+ renderspuContextRelease( context->shared );
+
+ crFree(context);
}
+uint32_t renderspuContextRetain( ContextInfo *context )
+{
+ Assert(context->cRefs);
+ return ASMAtomicIncU32(&context->cRefs);
+}
-void RENDER_APIENTRY
-renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
+uint32_t renderspuContextRelease( ContextInfo *context )
{
- WindowInfo *window;
- ContextInfo *context;
+ uint32_t cRefs = ASMAtomicDecU32(&context->cRefs);
+ if (!cRefs)
+ renderspuDestroyContextTerminate( context );
+ else
+ CRASSERT(cRefs < UINT32_MAX/2);
+ return cRefs;
+}
- /*
- crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx);
- */
+uint32_t renderspuContextMarkDeletedAndRelease( ContextInfo *context )
+{
+ /* invalidate the context id to mark it as deleted */
+ context->BltInfo.Base.id = -1;
+
+ /* some drivers do not like when the base (shared) context is deleted before its referals,
+ * this is why we keep a context refference counting the base (shared) context will be destroyed as soon as*/
+ return renderspuContextRelease( context );
+}
+
+ContextInfo * renderspuDefaultSharedContextAcquire()
+{
+ ContextInfo * pCtx = render_spu.defaultSharedContext;
+ if (!pCtx)
+ return NULL;
+
+ renderspuContextRetain(pCtx);
+ return pCtx;
+}
+
+void renderspuDefaultSharedContextRelease(ContextInfo * pCtx)
+{
+ renderspuContextRelease(pCtx);
+}
+
+
+static void RENDER_APIENTRY
+renderspuDestroyContext( GLint ctx )
+{
+ ContextInfo *context, *curCtx;
+
+ CRASSERT(ctx);
+
+ if (ctx == CR_RENDER_DEFAULT_CONTEXT_ID)
+ {
+ crWarning("request to destroy a default context, ignoring");
+ return;
+ }
- window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow);
context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
+ if (!context)
+ {
+ crWarning("request to delete inexistent context");
+ return;
+ }
+
+ if (render_spu.defaultSharedContext == context)
+ {
+ renderspuSetDefaultSharedContext(NULL);
+ }
+
+ curCtx = GET_CONTEXT_VAL();
+// CRASSERT(curCtx);
+ if (curCtx == context)
+ {
+ renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID );
+ curCtx = GET_CONTEXT_VAL();
+ Assert(curCtx);
+ Assert(curCtx != context);
+ }
+
+ crHashtableDelete(render_spu.contextTable, ctx, NULL);
+
+ renderspuContextMarkDeletedAndRelease(context);
+}
+
+WindowInfo* renderspuGetDummyWindow(GLint visBits)
+{
+ WindowInfo *window = (WindowInfo *) crHashtableSearch(render_spu.dummyWindowTable, visBits);
+ if (!window)
+ {
+ window = (WindowInfo *)crAlloc(sizeof (*window));
+ if (!window)
+ {
+ crWarning("crAlloc failed");
+ return NULL;
+ }
+
+ if (!renderspuWindowInit(window, NULL, visBits, -1))
+ {
+ crWarning("renderspuWindowInit failed");
+ crFree(window);
+ return NULL;
+ }
+
+ crHashtableAdd(render_spu.dummyWindowTable, visBits, window);
+ }
+
+ return window;
+}
+
+void renderspuPerformMakeCurrent(WindowInfo *window, GLint nativeWindow, ContextInfo *context)
+{
if (window && context)
{
#ifdef CHROMIUM_THREADSAFE
@@ -210,12 +352,12 @@ renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
context->currentWindow = window;
if (!window)
{
- crDebug("Render SPU: MakeCurrent invalid window id: %d", crWindow);
+ crDebug("Render SPU: MakeCurrent invalid window id: %d", window->BltInfo.Base.id);
return;
}
if (!context)
{
- crDebug("Render SPU: MakeCurrent invalid context id: %d", ctx);
+ crDebug("Render SPU: MakeCurrent invalid context id: %d", context->BltInfo.Base.id);
return;
}
@@ -236,9 +378,9 @@ renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
context->haveWindowPosARB = GL_FALSE;
context->everCurrent = GL_TRUE;
}
- if (crWindow == 0 && window->mapPending &&
+ if (window->BltInfo.Base.id == CR_RENDER_DEFAULT_WINDOW_ID && window->mapPending &&
!render_spu.render_to_app_window && !render_spu.render_to_crut_window) {
- /* Window[0] is special, it's the default window and normally hidden.
+ /* Window[CR_RENDER_DEFAULT_CONTEXT_ID] is special, it's the default window and normally hidden.
* If the mapPending flag is set, then we should now make the window
* visible.
*/
@@ -247,60 +389,75 @@ renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
}
window->everCurrent = GL_TRUE;
}
- else
+ else if (!window && !context)
{
+ renderspu_SystemMakeCurrent( NULL, 0, NULL );
#ifdef CHROMIUM_THREADSAFE
crSetTSD(&_RenderTSD, NULL);
#else
render_spu.currentContext = NULL;
#endif
}
+ else
+ {
+ crError("renderspuMakeCurrent invalid ids: crWindow(%d), ctx(%d)",
+ window ? window->BltInfo.Base.id : 0,
+ context ? context->BltInfo.Base.id : 0);
+ }
}
-
-/*
- * Window functions
- */
-
-GLint RENDER_APIENTRY
-renderspuWindowCreate( const char *dpyName, GLint visBits )
+void RENDER_APIENTRY
+renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
{
- WindowInfo *window;
- VisualInfo *visual;
- GLboolean showIt;
+ WindowInfo *window = NULL;
+ ContextInfo *context = NULL;
- if (!dpyName || crStrlen(render_spu.display_string) > 0)
- dpyName = render_spu.display_string;
+ /*
+ crDebug("%s win=%d native=0x%x ctx=%d", __FUNCTION__, crWindow, (int) nativeWindow, ctx);
+ */
- visual = renderspuFindVisual( dpyName, visBits );
- if (!visual)
+ if (crWindow)
{
- crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
- return -1;
+ window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow);
+ if (!window)
+ {
+ crWarning("invalid window %d specified", crWindow);
+ return;
+ }
}
- /* Allocate WindowInfo */
- window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
- if (!window)
+ if (ctx)
{
- crWarning( "Render SPU: Couldn't create a window" );
- return -1;
+ context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
+ if (!context)
+ {
+ crWarning("invalid context %d specified", ctx);
+ return;
+ }
}
- crHashtableAdd(render_spu.windowTable, render_spu.window_id, window);
- window->id = render_spu.window_id;
- render_spu.window_id++;
+ if (!context != !window)
+ {
+ crWarning("either window %d or context %d are zero", crWindow, ctx);
+ return;
+ }
+
+ renderspuPerformMakeCurrent(window, nativeWindow, context);
+}
+
+GLboolean renderspuWindowInitWithVisual( WindowInfo *window, VisualInfo *visual, GLboolean showIt, GLint id )
+{
+ crMemset(window, 0, sizeof (*window));
+ RTCritSectInit(&window->CompositorLock);
+ window->fCompositorPresentEmpty = GL_FALSE;
+ window->pCompositor = NULL;
+
+ window->BltInfo.Base.id = id;
window->x = render_spu.defaultX;
window->y = render_spu.defaultY;
- window->width = render_spu.defaultWidth;
- window->height = render_spu.defaultHeight;
-
- if (render_spu.force_hidden_wdn_create
- || ((render_spu.render_to_app_window || render_spu.render_to_crut_window) && !crGetenv("CRNEWSERVER")))
- showIt = 0;
- else
- showIt = window->id > 0;
+ window->BltInfo.width = render_spu.defaultWidth;
+ window->BltInfo.height = render_spu.defaultHeight;
/* Set window->title, replacing %i with the window ID number */
{
@@ -310,7 +467,7 @@ renderspuWindowCreate( const char *dpyName, GLint visBits )
window->title = crAlloc(crStrlen(render_spu.window_title) + 10);
for (i = 0; render_spu.window_title[i] != '%'; i++)
window->title[i] = render_spu.window_title[i];
- k = sprintf(window->title + i, "%d", window->id);
+ k = sprintf(window->title + i, "%d", window->BltInfo.Base.id);
CRASSERT(k < 10);
i++; /* skip the 'i' after the '%' */
j = i + k;
@@ -321,21 +478,103 @@ renderspuWindowCreate( const char *dpyName, GLint visBits )
window->title = crStrdup(render_spu.window_title);
}
}
-
+
+ window->BltInfo.Base.visualBits = visual->visAttribs;
+
+
/*
- crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->id);
+ crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
*/
/* Have GLX/WGL/AGL create the window */
if (!renderspu_SystemVBoxCreateWindow( visual, showIt, window ))
{
- crFree(window);
crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
- return -1;
+ return GL_FALSE;
}
+
+ window->visible = !!showIt;
CRASSERT(window->visual == visual);
+ return GL_TRUE;
+}
+
+/*
+ * Window functions
+ */
+GLboolean renderspuWindowInit(WindowInfo *pWindow, const char *dpyName, GLint visBits, GLint id)
+{
+ VisualInfo *visual;
+
+ crMemset(pWindow, 0, sizeof (*pWindow));
- return window->id;
+ if (!dpyName || crStrlen(render_spu.display_string) > 0)
+ dpyName = render_spu.display_string;
+
+ visual = renderspuFindVisual( dpyName, visBits );
+ if (!visual)
+ {
+ crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
+ return GL_FALSE;
+ }
+
+ /*
+ crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
+ */
+ /* Have GLX/WGL/AGL create the window */
+ if (!renderspuWindowInitWithVisual( pWindow, visual, 0, id ))
+ {
+ crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id )
+{
+ WindowInfo *window;
+
+ if (id <= 0)
+ {
+ id = (GLint)crHashtableAllocKeys(render_spu.windowTable, 1);
+ if (id <= 0)
+ {
+ crWarning("failed to allocate window id");
+ return -1;
+ }
+ }
+ else
+ {
+ if (crHashtableIsKeyUsed(render_spu.windowTable, id))
+ {
+ crWarning("the specified window key %d is in use", id);
+ return -1;
+ }
+ }
+
+ /* Allocate WindowInfo */
+ window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
+ if (!window)
+ {
+ crWarning( "Render SPU: Couldn't create a window" );
+ return -1;
+ }
+
+ if (!renderspuWindowInit(window, dpyName, visBits, id))
+ {
+ crWarning("renderspuWindowInit failed");
+ crFree(window);
+ return -1;
+ }
+
+ crHashtableAdd(render_spu.windowTable, id, window);
+ return window->BltInfo.Base.id;
+}
+
+GLint RENDER_APIENTRY
+renderspuWindowCreate( const char *dpyName, GLint visBits )
+{
+ return renderspuWindowCreateEx( dpyName, visBits, 0 );
}
static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, void *data2)
@@ -346,7 +585,46 @@ static void renderspuCheckCurrentCtxWindowCB(unsigned long key, void *data1, voi
if (pCtx->currentWindow==pWindow)
{
- renderspuMakeCurrent(0, 0, pCtx->id);
+ 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 renderspuWindowTerm( WindowInfo *window )
+{
+ GET_CONTEXT(pOldCtx);
+ WindowInfo * pOldWindow = pOldCtx ? pOldCtx->currentWindow : NULL;
+ CRASSERT(!pOldCtx == !pOldWindow);
+ /* ensure no concurrent draws can take place */
+ renderspuVBoxCompositorSet(window, NULL);
+ renderspuVBoxPresentBlitterCleanup(window);
+ renderspu_SystemDestroyWindow( window );
+ RTCritSectDelete(&window->CompositorLock);
+ /* 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);
+ }
}
}
@@ -354,28 +632,21 @@ void
RENDER_APIENTRY renderspuWindowDestroy( GLint win )
{
WindowInfo *window;
- GET_CONTEXT(pOldCtx);
CRASSERT(win >= 0);
+ if (win == CR_RENDER_DEFAULT_WINDOW_ID)
+ {
+ crWarning("request to destroy a default mural, ignoring");
+ return;
+ }
window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
if (window) {
crDebug("Render SPU: Destroy window (%d)", win);
- renderspu_SystemDestroyWindow( window );
+ renderspuWindowTerm( window );
+
/* remove window info from hash table, and free it */
crHashtableDelete(render_spu.windowTable, win, crFree);
- /* 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);
- if (pNewCtx!=pOldCtx)
- {
- renderspuMakeCurrent(pOldCtx&&pOldCtx->currentWindow ? pOldCtx->currentWindow->id:0, 0,
- pOldCtx ? pOldCtx->id:0);
- }
- }
}
else {
crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
@@ -390,7 +661,17 @@ renderspuWindowSize( GLint win, GLint w, GLint h )
CRASSERT(win >= 0);
window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
if (window) {
- renderspu_SystemWindowSize( window, w, h );
+ if (w != window->BltInfo.width
+ || h != window->BltInfo.height)
+ {
+ /* window is resized, compositor data is no longer valid
+ * this set also ensures all redraw operations are done in the redraw thread
+ * and that no redraw is started until new Present request comes containing a valid presentation data */
+ renderspuVBoxCompositorSet( window, NULL);
+ renderspu_SystemWindowSize( window, w, h );
+ window->BltInfo.width = w;
+ window->BltInfo.height = h;
+ }
}
else {
crDebug("Render SPU: Attempt to resize invalid window (%d)", win);
@@ -416,17 +697,41 @@ renderspuWindowPosition( GLint win, GLint x, GLint y )
}
}
+#ifdef DEBUG_misha
+# define CR_DBG_DUMP_VISIBLE_REGIONS
+#endif
+
+#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
+static void renderspuDbgDumpVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
+{
+ GLint i;
+ const RTRECT *pRtRects = (const RTRECT *)((const void*)pRects);
+
+ crInfo("Window %d, Vidible Regions%d", win, cRects);
+ for (i = 0; i < cRects; ++i)
+ {
+ crInfo("%d: (%d,%d), (%d,%d)", i, pRtRects[i].xLeft, pRtRects[i].yTop, pRtRects[i].xRight, pRtRects[i].yBottom);
+ }
+ crInfo("======");
+}
+#endif
+
static void RENDER_APIENTRY
-renderspuWindowVisibleRegion(GLint win, GLint cRects, GLint *pRects)
+renderspuWindowVisibleRegion(GLint win, GLint cRects, const GLint *pRects)
{
WindowInfo *window;
CRASSERT(win >= 0);
+
+#ifdef CR_DBG_DUMP_VISIBLE_REGIONS
+ renderspuDbgDumpVisibleRegion(win, cRects, pRects);
+#endif
+
window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
if (window) {
renderspu_SystemWindowVisibleRegion( window, cRects, pRects );
}
else {
- crDebug("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
+ crWarning("Render SPU: Attempt to set VisibleRegion for invalid window (%d)", win);
}
}
@@ -437,6 +742,7 @@ renderspuWindowShow( GLint win, GLint flag )
CRASSERT(win >= 0);
window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
if (window) {
+ GLboolean visible;
if (window->nativeWindow) {
/* We're rendering back to the native app window instead of the
* new window which we (the Render SPU) created earlier.
@@ -444,13 +750,367 @@ renderspuWindowShow( GLint win, GLint flag )
*/
flag = 0;
}
- renderspu_SystemShowWindow( window, (GLboolean) flag );
+
+ visible = !!flag;
+
+ if (window->visible != visible)
+ {
+ renderspu_SystemShowWindow( window, visible );
+ window->visible = visible;
+ }
}
else {
crDebug("Render SPU: Attempt to hide/show invalid window (%d)", win);
}
}
+static void RENDER_APIENTRY
+renderspuVBoxPresentComposition( GLint win, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+{
+ WindowInfo *window;
+ CRASSERT(win >= 0);
+ window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
+ if (window) {
+ if (pCompositor && CrVrScrCompositorIsEmpty(pCompositor) && !window->fCompositorPresentEmpty)
+ pCompositor = NULL;
+
+ if (pCompositor)
+ window->fCompositorPresentEmpty = GL_FALSE;
+
+ renderspuVBoxCompositorSet( window, pCompositor);
+ if (pCompositor)
+ {
+ renderspu_SystemVBoxPresentComposition(window, pChangedEntry);
+ }
+ }
+ else {
+ crDebug("Render SPU: Attempt to PresentComposition for invalid window (%d)", win);
+ }
+}
+
+void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY)
+{
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
+ {
+ uint32_t cRegions;
+ const RTRECT *paSrcRegions, *paDstRegions;
+ int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
+ uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
+ if (RT_SUCCESS(rc))
+ {
+ uint32_t i;
+ for (i = 0; i < cRegions; ++i)
+ {
+ RTRECT DstRect;
+ const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ DstRect.xLeft = paDstRegions[i].xLeft * scaleX;
+ DstRect.yTop = paDstRegions[i].yTop * scaleY;
+ DstRect.xRight = paDstRegions[i].xRight * scaleX;
+ DstRect.yBottom = paDstRegions[i].yBottom * scaleY;
+ CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), &paSrcRegions[i], &DstRect, 1, fFlags);
+ }
+ }
+ else
+ {
+ crWarning("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
+ }
+ }
+}
+
+void renderspuVBoxCompositorBlit ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter)
+{
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
+ {
+ uint32_t cRegions;
+ const RTRECT *paSrcRegions, *paDstRegions;
+ int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRegions, &paSrcRegions, &paDstRegions, NULL);
+ uint32_t fFlags = CrVrScrCompositorEntryFlagsCombinedGet(pCompositor, pEntry);
+ if (RT_SUCCESS(rc))
+ {
+ const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ CrBltBlitTexMural(pBlitter, true, CrTdTexGet(pTexData), paSrcRegions, paDstRegions, cRegions, fFlags);
+ }
+ else
+ {
+ crWarning("Blit: CrVrScrCompositorEntryRegionsGet failed rc %d", rc);
+ }
+ }
+}
+
+void renderspuVBoxPresentBlitterCleanup( WindowInfo *window )
+{
+ if (!window->pBlitter)
+ return;
+
+ if (render_spu.blitterTable)
+ {
+ const CR_BLITTER_WINDOW * pBltInfo = CrBltMuralGetCurrentInfo(window->pBlitter);
+ if (pBltInfo && pBltInfo->Base.id == window->BltInfo.Base.id)
+ {
+ CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
+ }
+ }
+ else
+ {
+ CRASSERT(CrBltMuralGetCurrentInfo(window->pBlitter)->Base.id == window->BltInfo.Base.id);
+ CrBltMuralSetCurrentInfo(window->pBlitter, NULL);
+ CrBltTerm(window->pBlitter);
+ }
+ window->pBlitter = NULL;
+}
+
+PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
+{
+ PCR_BLITTER pBlitter = window->pBlitter;
+ if (!pBlitter)
+ {
+ if (render_spu.blitterTable)
+ {
+ crHashtableLock(render_spu.blitterTable);
+ pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
+ }
+
+ if (!pBlitter)
+ {
+ int rc;
+ ContextInfo * pDefaultCtxInfo;
+
+ pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
+ if (!pBlitter)
+ {
+ crWarning("failed to allocate blitter");
+ return NULL;
+ }
+
+ pDefaultCtxInfo = renderspuDefaultSharedContextAcquire();
+ if (!pDefaultCtxInfo)
+ {
+ crWarning("no default ctx info!");
+ crFree(pBlitter);
+ return NULL;
+ }
+
+ rc = CrBltInit(pBlitter, &pDefaultCtxInfo->BltInfo, true, true, NULL, &render_spu.blitterDispatch);
+
+ /* we can release it either way, since it will be retained when used as a shared context */
+ renderspuDefaultSharedContextRelease(pDefaultCtxInfo);
+
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltInit failed, rc %d", rc);
+ crFree(pBlitter);
+ return NULL;
+ }
+
+ if (render_spu.blitterTable)
+ {
+ crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
+ }
+ }
+
+ if (render_spu.blitterTable)
+ crHashtableUnlock(render_spu.blitterTable);
+
+ Assert(pBlitter);
+ window->pBlitter = pBlitter;
+ }
+
+ CrBltMuralSetCurrentInfo(pBlitter, &window->BltInfo);
+ return pBlitter;
+}
+
+int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData)
+{
+ int rc;
+
+ CrBltSetMakeCurrentUserData(pBlitter, i32MakeCurrentUserData);
+
+ rc = CrBltEnter(pBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltEnter failed, rc %d", rc);
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+
+PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData )
+{
+ PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet(window);
+ if (pBlitter)
+ {
+ int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
+ if (RT_SUCCESS(rc))
+ {
+ return pBlitter;
+ }
+ }
+ return NULL;
+}
+
+PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData )
+{
+ if (!window->pBlitter)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR * pTmpCompositor;
+ /* just use compositor lock to synchronize */
+ pTmpCompositor = renderspuVBoxCompositorAcquire(window);
+ CRASSERT(pTmpCompositor);
+ if (pTmpCompositor)
+ {
+ PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGet( window );
+ if (pBlitter)
+ {
+ if (!CrBltIsEverEntered(pBlitter))
+ {
+ int rc = renderspuVBoxPresentBlitterEnter(pBlitter, i32MakeCurrentUserData);
+ if (RT_SUCCESS(rc))
+ {
+ CrBltLeave(pBlitter);
+ }
+ else
+ {
+ crWarning("renderspuVBoxPresentBlitterEnter failed rc %d", rc);
+ }
+ }
+ }
+ else
+ {
+ crWarning("renderspuVBoxPresentBlitterGet failed");
+ }
+
+ renderspuVBoxCompositorRelease(window);
+ }
+ else
+ {
+ crWarning("renderspuVBoxCompositorAcquire failed");
+ }
+ }
+ return window->pBlitter;
+}
+
+void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData )
+{
+ PCR_BLITTER pBlitter = renderspuVBoxPresentBlitterGetAndEnter(window, i32MakeCurrentUserData);
+ if (!pBlitter)
+ return;
+
+ renderspuVBoxCompositorBlit(pCompositor, pBlitter);
+
+ renderspu_SystemSwapBuffers(window, 0);
+
+ CrBltLeave(pBlitter);
+}
+
+void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
+{
+ int rc;
+ /* renderspuVBoxCompositorSet can be invoked from the chromium thread only and is not reentrant,
+ * no need to synch here
+ * the lock is actually needed to ensure we're in synch with the redraw thread */
+ if (window->pCompositor == pCompositor)
+ return;
+ rc = RTCritSectEnter(&window->CompositorLock);
+ if (RT_SUCCESS(rc))
+ {
+ window->pCompositor = pCompositor;
+ RTCritSectLeave(&window->CompositorLock);
+ return;
+ }
+ else
+ {
+ crWarning("RTCritSectEnter failed rc %d", rc);
+ }
+}
+
+static void renderspuVBoxCompositorClearAllCB(unsigned long key, void *data1, void *data2)
+{
+ WindowInfo *window = (WindowInfo *) data1;
+ renderspuVBoxCompositorSet(window, NULL);
+}
+
+void renderspuVBoxCompositorClearAll()
+{
+ /* we need to clear window compositor, which is not that trivial though,
+ * since the lock order used in presentation thread is compositor lock() -> hash table lock (aquired for id->window resolution)
+ * this is why, to prevent potential deadlocks, we use crHashtableWalkUnlocked that does not hold the table lock
+ * we are can be sure noone will modify the table here since renderspuVBoxCompositorClearAll can be called in the command (hgcm) thread only,
+ * and the table can be modified from that thread only as well */
+ crHashtableWalkUnlocked(render_spu.windowTable, renderspuVBoxCompositorClearAllCB, NULL);
+}
+
+const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window)
+{
+ int rc = RTCritSectEnter(&window->CompositorLock);
+ if (RT_SUCCESS(rc))
+ {
+ const VBOXVR_SCR_COMPOSITOR * pCompositor = window->pCompositor;
+ if (pCompositor)
+ return pCompositor;
+
+ /* if no compositor is set, release the lock and return */
+ RTCritSectLeave(&window->CompositorLock);
+ }
+ else
+ {
+ crWarning("RTCritSectEnter failed rc %d", rc);
+ }
+ return NULL;
+}
+
+int renderspuVBoxCompositorLock(WindowInfo *window)
+{
+ int rc = RTCritSectEnter(&window->CompositorLock);
+ AssertRC(rc);
+ return rc;
+}
+
+int renderspuVBoxCompositorUnlock(WindowInfo *window)
+{
+ int rc = RTCritSectLeave(&window->CompositorLock);
+ AssertRC(rc);
+ return rc;
+}
+
+int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor)
+{
+ int rc = RTCritSectTryEnter(&window->CompositorLock);
+ if (RT_SUCCESS(rc))
+ {
+ *ppCompositor = window->pCompositor;
+ if (*ppCompositor)
+ return VINF_SUCCESS;
+
+ /* if no compositor is set, release the lock and return */
+ RTCritSectLeave(&window->CompositorLock);
+ rc = VERR_INVALID_STATE;
+ }
+ else
+ {
+ *ppCompositor = NULL;
+ }
+ return rc;
+}
+
+void renderspuVBoxCompositorRelease( WindowInfo *window)
+{
+ int rc;
+ Assert(window->pCompositor);
+ if (CrVrScrCompositorIsEmpty(window->pCompositor) && RTCritSectGetRecursion(&window->CompositorLock) == 1)
+ window->pCompositor = NULL;
+ rc = RTCritSectLeave(&window->CompositorLock);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTCritSectLeave failed rc %d", rc);
+ }
+}
+
/*
* Set the current raster position to the given window coordinate.
@@ -691,7 +1351,20 @@ static void RENDER_APIENTRY renderspuSemaphoreVCR( GLuint name )
/*
* Misc functions
*/
+void renderspuSetDefaultSharedContext(ContextInfo *pCtx)
+{
+ if (pCtx == render_spu.defaultSharedContext)
+ return;
+ renderspu_SystemDefaultSharedContextChanged(render_spu.defaultSharedContext, pCtx);
+
+ if (render_spu.defaultSharedContext)
+ renderspuContextRelease(render_spu.defaultSharedContext);
+
+ if (pCtx)
+ renderspuContextRetain(pCtx);
+ render_spu.defaultSharedContext = pCtx;
+}
static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint value)
@@ -699,9 +1372,17 @@ static void RENDER_APIENTRY renderspuChromiumParameteriCR(GLenum target, GLint v
switch (target)
{
- case GL_HOST_WND_CREATED_HIDDEN:
- render_spu.force_hidden_wdn_create = value ? GL_TRUE : GL_FALSE;
+ case GL_HH_SET_DEFAULT_SHARED_CTX:
+ {
+ ContextInfo * pCtx = NULL;
+ if (value)
+ pCtx = (ContextInfo *)crHashtableSearch(render_spu.contextTable, value);
+ else
+ crWarning("invalid default shared context id %d", value);
+
+ renderspuSetDefaultSharedContext(pCtx);
break;
+ }
default:
// crWarning("Unhandled target in renderspuChromiumParameteriCR()");
break;
@@ -841,7 +1522,7 @@ renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
case GL_WINDOW_SIZE_CR:
/* XXX this is old code that should be removed.
- * NOTE: we can only resize the default (id=0) window!!!
+ * NOTE: we can only resize the default (id=CR_RENDER_DEFAULT_WINDOW_ID) window!!!
*/
{
GLint w, h;
@@ -851,7 +1532,7 @@ renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
CRASSERT(values);
w = ((GLint*)values)[0];
h = ((GLint*)values)[1];
- window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, 0);
+ window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
if (window)
{
renderspu_SystemWindowSize(window, w, h);
@@ -859,9 +1540,16 @@ renderspuChromiumParametervCR(GLenum target, GLenum type, GLsizei count,
}
break;
+ case GL_HH_SET_TMPCTX_MAKE_CURRENT:
+ if (type == GL_BYTE && count == sizeof (void*))
+ memcpy(&render_spu.blitterDispatch.MakeCurrent, values, count);
+ else
+ WARN(("unexpected type(%#x) - count(%d) pair", type, count));
+ break;
+
default:
#if 0
- crWarning("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target);
+ WARN(("Unhandled target in renderspuChromiumParametervCR(0x%x)", (int) target));
#endif
break;
}
@@ -923,6 +1611,21 @@ renderspuGetChromiumParametervCR(GLenum target, GLuint index, GLenum type,
}
}
break;
+ case GL_WINDOW_VISIBILITY_CR:
+ {
+ GLint *vis = (GLint *) values;
+ WindowInfo *window;
+ CRASSERT(type == GL_INT);
+ CRASSERT(count == 1);
+ CRASSERT(values);
+ vis[0] = 0; /* default */
+ window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, index);
+ if (window)
+ {
+ vis[0] = window->visible;
+ }
+ }
+ break;
default:
; /* nothing - silence compiler */
}
@@ -1001,6 +1704,9 @@ renderspuGetString(GLenum pname)
return NULL;
}
+ if (!context)
+ return (const GLubyte *)nativeExt;
+
crExt = crStrjoin3(crExtensions, " ", crAppOnlyExtensions);
s1 = crStrIntersect(nativeExt, crExt);
remove_trailing_space(s1);
@@ -1043,6 +1749,13 @@ renderspuGetString(GLenum pname)
return NULL;
}
+static void renderspuReparentWindowCB(unsigned long key, void *data1, void *data2)
+{
+ WindowInfo *pWindow = (WindowInfo *)data1;
+
+ renderspu_SystemReparentWindow(pWindow);
+}
+
DECLEXPORT(void) renderspuReparentWindow(GLint window)
{
WindowInfo *pWindow;
@@ -1057,46 +1770,13 @@ DECLEXPORT(void) renderspuReparentWindow(GLint window)
}
renderspu_SystemReparentWindow(pWindow);
-}
-
-#if defined(DARWIN)
-# ifdef VBOX_WITH_COCOA_QT
-void renderspuFlush()
-{
- renderspu_SystemFlush();
-}
-
-void renderspuFinish()
-{
- renderspu_SystemFinish();
-}
-
-void renderspuBindFramebufferEXT(GLenum target, GLuint framebuffer)
-{
- renderspu_SystemBindFramebufferEXT(target, framebuffer);
-}
-void renderspuCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
-{
- renderspu_SystemCopyPixels(x, y, width, height, type);
-}
-
-void renderspuGetIntegerv(GLenum pname, GLint * params)
-{
- renderspu_SystemGetIntegerv(pname, params);
-}
-
-void renderspuDrawBuffer(GLenum mode)
-{
- renderspu_SystemDrawBuffer(mode);
-}
-
-void renderspuReadBuffer(GLenum mode)
-{
- renderspu_SystemReadBuffer(mode);
+ /* special case: reparent all internal windows as well */
+ if (window == CR_RENDER_DEFAULT_WINDOW_ID)
+ {
+ crHashtableWalk(render_spu.dummyWindowTable, renderspuReparentWindowCB, NULL);
+ }
}
-# endif
-#endif
#define FILLIN( NAME, FUNC ) \
table[i].name = crStrdup(NAME); \
@@ -1134,16 +1814,6 @@ renderspuCreateFunctions(SPUNamedFunctionTable table[])
FILLIN( "ChromiumParametervCR", renderspuChromiumParametervCR );
FILLIN( "GetChromiumParametervCR", renderspuGetChromiumParametervCR );
FILLIN( "GetString", renderspuGetString );
-#if defined(DARWIN)
-# ifdef VBOX_WITH_COCOA_QT
- FILLIN( "Flush", renderspuFlush );
- FILLIN( "Finish", renderspuFinish );
- FILLIN( "BindFramebufferEXT", renderspuBindFramebufferEXT );
- FILLIN( "CopyPixels", renderspuCopyPixels );
- FILLIN( "GetIntegerv", renderspuGetIntegerv );
- FILLIN( "ReadBuffer", renderspuReadBuffer );
- FILLIN( "DrawBuffer", renderspuDrawBuffer );
-# endif
-#endif
+ FILLIN( "VBoxPresentComposition", renderspuVBoxPresentComposition );
return i;
}