summaryrefslogtreecommitdiff
path: root/src/VBox/HostServices/SharedOpenGL/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL/render')
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu.c976
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu.h176
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c60
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c311
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h21
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m1482
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_config.c9
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c519
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c129
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c291
10 files changed, 2771 insertions, 1203 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;
}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu.h b/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
index d39af70d..1d7704c1 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu.h
@@ -27,8 +27,22 @@
#include "cr_spu.h"
#include "cr_hash.h"
#include "cr_server.h"
+#include "cr_blitter.h"
+#include "cr_compositor.h"
#include <iprt/cdefs.h>
+#include <iprt/critsect.h>
+#if defined(GLX) /* @todo: unify windows and glx thread creation code */
+#include <iprt/thread.h>
+#include <iprt/semaphore.h>
+
+/* special window id used for representing the command window CRWindowInfo */
+#define CR_RENDER_WINCMD_ID (INT32_MAX-2)
+AssertCompile(CR_RENDER_WINCMD_ID != CR_RENDER_DEFAULT_WINDOW_ID);
+/* CRHashTable is using unsigned long keys, we use it to trore X Window -> CRWindowInfo association */
+AssertCompile(sizeof (Window) == sizeof (unsigned long));
+#endif
+
#define MAX_VISUALS 32
@@ -76,19 +90,32 @@ typedef struct {
/**
* Window info
*/
-typedef struct {
+typedef struct WindowInfo {
int x, y;
- int width, height;
- int id; /**< integer window ID */
+// int width, height;
+// int id; /**< integer window ID */
+ CR_BLITTER_WINDOW BltInfo;
+
VisualInfo *visual;
GLboolean mapPending;
GLboolean visible;
GLboolean everCurrent; /**< has this window ever been bound? */
+ GLboolean fCompositorPresentEmpty;
char *title;
+
+ const VBOXVR_SCR_COMPOSITOR *pCompositor;
+ /* the composotor lock is used to synchronize the current compositor access,
+ * i.e. the compositor can be accessed by a gui refraw thread,
+ * while chromium thread might try to set a new compositor
+ * note that the compositor internally has its own lock to be used for accessing its data
+ * see CrVrScrCompositorLock/Unlock; renderspu and crserverlib would use it for compositor data access */
+ RTCRITSECT CompositorLock;
+ PCR_BLITTER pBlitter;
#if defined(WINDOWS)
HDC nativeWindow; /**< for render_to_app_window */
HWND hWnd;
HDC device_context;
+ HDC redraw_device_context;
HRGN hRgn;
#elif defined(DARWIN)
# ifndef VBOX_WITH_COCOA_QT
@@ -124,7 +151,8 @@ typedef struct {
* Context Info
*/
typedef struct _ContextInfo {
- int id; /**< integer context ID */
+// int id; /**< integer context ID */
+ CR_BLITTER_CONTEXT BltInfo;
VisualInfo *visual;
GLboolean everCurrent;
GLboolean haveWindowPosARB;
@@ -142,6 +170,7 @@ typedef struct _ContextInfo {
#endif
struct _ContextInfo *shared;
char *extensionString;
+ volatile uint32_t cRefs;
} ContextInfo;
/**
@@ -152,6 +181,44 @@ typedef struct {
GLuint count;
} Barrier;
+#ifdef GLX
+typedef enum
+{
+ CR_RENDER_WINCMD_TYPE_UNDEFINED = 0,
+ /* create the window (not used for now) */
+ CR_RENDER_WINCMD_TYPE_WIN_CREATE,
+ /* destroy the window (not used for now) */
+ CR_RENDER_WINCMD_TYPE_WIN_DESTROY,
+ /* notify the WinCmd thread about window creation */
+ CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE,
+ /* notify the WinCmd thread about window destroy */
+ CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY,
+ /* nop used to synchronize with the WinCmd thread */
+ CR_RENDER_WINCMD_TYPE_NOP,
+ /* exit Win Cmd thread */
+ CR_RENDER_WINCMD_TYPE_EXIT,
+} CR_RENDER_WINCMD_TYPE;
+
+typedef struct CR_RENDER_WINCMD
+{
+ /* command type */
+ CR_RENDER_WINCMD_TYPE enmCmd;
+ /* command result */
+ int rc;
+ /* valid for WIN_CREATE & WIN_DESTROY only */
+ WindowInfo *pWindow;
+} CR_RENDER_WINCMD, *PCR_RENDER_WINCMD;
+#endif
+
+#ifdef RT_OS_DARWIN
+typedef void (*PFNDELETE_OBJECT)(GLhandleARB obj);
+typedef void (*PFNGET_ATTACHED_OBJECTS)( GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj );
+typedef GLhandleARB (*PFNGET_HANDLE)(GLenum pname);
+typedef void (*PFNGET_INFO_LOG)( GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog );
+typedef void (*PFNGET_OBJECT_PARAMETERFV)( GLhandleARB obj, GLenum pname, GLfloat * params );
+typedef void (*PFNGET_OBJECT_PARAMETERIV)( GLhandleARB obj, GLenum pname, GLint * params );
+#endif
+
/**
* Renderspu state info
*/
@@ -159,9 +226,6 @@ typedef struct {
SPUDispatchTable self;
int id;
- unsigned int window_id;
- unsigned int context_id;
-
/** config options */
/*@{*/
char *window_title;
@@ -204,6 +268,10 @@ typedef struct {
CRHashTable *windowTable;
CRHashTable *contextTable;
+ CRHashTable *dummyWindowTable;
+
+ ContextInfo *defaultSharedContext;
+
#ifndef CHROMIUM_THREADSAFE
ContextInfo *currentContext;
#endif
@@ -217,6 +285,9 @@ typedef struct {
char *swap_master_url;
CRConnection **swap_conns;
+ SPUDispatchTable blitterDispatch;
+ CRHashTable *blitterTable;
+
#ifdef USE_OSMESA
/** Off screen rendering hooks. */
int use_osmesa;
@@ -230,13 +301,34 @@ typedef struct {
void (*OSMesaDestroyContext)( OSMesaContext ctx );
#endif
+#if defined(GLX)
+ RTTHREAD hWinCmdThread;
+ VisualInfo WinCmdVisual;
+ WindowInfo WinCmdWindow;
+ RTSEMEVENT hWinCmdCompleteEvent;
+ /* display connection used to send data to the WinCmd thread */
+ Display *pCommunicationDisplay;
+ Atom WinCmdAtom;
+ /* X Window -> CRWindowInfo table */
+ CRHashTable *pWinToInfoTable;
+#endif
+
#ifdef RT_OS_WINDOWS
DWORD dwWinThreadId;
HANDLE hWinThreadReadyEvent;
#endif
#ifdef RT_OS_DARWIN
-# ifndef VBOX_WITH_COCOA_QT
+# ifdef VBOX_WITH_COCOA_QT
+ PFNDELETE_OBJECT pfnDeleteObject;
+ PFNGET_ATTACHED_OBJECTS pfnGetAttachedObjects;
+ PFNGET_HANDLE pfnGetHandle;
+ PFNGET_INFO_LOG pfnGetInfoLog;
+ PFNGET_OBJECT_PARAMETERFV pfnGetObjectParameterfv;
+ PFNGET_OBJECT_PARAMETERIV pfnGetObjectParameteriv;
+
+ CR_GLSL_CACHE GlobalShaders;
+# else
RgnHandle hRootVisibleRegion;
RTSEMFASTMUTEX syncMutex;
EventHandlerUPP hParentEventHandler;
@@ -247,8 +339,6 @@ typedef struct {
bool fInit;
# endif
#endif /* RT_OS_DARWIN */
-
- int force_hidden_wdn_create;
} RenderSPU;
#ifdef RT_OS_WINDOWS
@@ -279,11 +369,22 @@ extern uint64_t render_spu_parent_window_id;
#ifdef CHROMIUM_THREADSAFE
extern CRtsd _RenderTSD;
-#define GET_CONTEXT(T) ContextInfo *T = (ContextInfo *) crGetTSD(&_RenderTSD)
+#define GET_CONTEXT_VAL() ((ContextInfo *) crGetTSD(&_RenderTSD))
+#define SET_CONTEXT_VAL(_v) do { \
+ crSetTSD(&_RenderTSD, (_v)); \
+ } while (0)
#else
-#define GET_CONTEXT(T) ContextInfo *T = render_spu.currentContext
+#define GET_CONTEXT_VAL() (render_spu.currentContext)
+#define SET_CONTEXT_VAL(_v) do { \
+ render_spu.currentContext = (_v); \
+ } while (0)
+
#endif
+#define GET_CONTEXT(T) ContextInfo *T = GET_CONTEXT_VAL()
+
+
+extern void renderspuSetDefaultSharedContext(ContextInfo *pCtx);
extern void renderspuSetVBoxConfiguration( RenderSPU *spu );
extern void renderspuMakeVisString( GLbitfield visAttribs, char *s );
extern VisualInfo *renderspuFindVisual(const char *displayName, GLbitfield visAttribs );
@@ -297,26 +398,41 @@ extern void renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h );
extern void renderspu_SystemGetWindowGeometry( WindowInfo *window, GLint *x, GLint *y, GLint *w, GLint *h );
extern void renderspu_SystemGetMaxWindowSize( WindowInfo *window, GLint *w, GLint *h );
extern void renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y );
-extern void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint* pRects);
-extern void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window);
-#ifdef RT_OS_DARWIN
-extern void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects);
-# ifdef VBOX_WITH_COCOA_QT
-extern void renderspu_SystemFlush();
-extern void renderspu_SystemFinish();
-extern void renderspu_SystemBindFramebufferEXT(GLenum target, GLuint framebuffer);
-extern void renderspu_SystemCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-extern void renderspu_SystemGetIntegerv(GLenum pname, GLint *params);
-extern void renderspu_SystemReadBuffer(GLenum mode);
-extern void renderspu_SystemDrawBuffer(GLenum mode);
-# endif
-#endif
+extern void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects);
+extern int renderspu_SystemInit();
+extern int renderspu_SystemTerm();
+extern void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext);
extern void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt );
extern void renderspu_SystemMakeCurrent( WindowInfo *window, GLint windowInfor, ContextInfo *context );
extern void renderspu_SystemSwapBuffers( WindowInfo *window, GLint flags );
extern void renderspu_SystemReparentWindow(WindowInfo *window);
+extern void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry );
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable);
extern void renderspu_GCWindow(void);
extern int renderspuCreateFunctions( SPUNamedFunctionTable table[] );
+extern void renderspuVBoxCompositorSet( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor);
+extern void renderspuVBoxCompositorClearAll();
+extern int renderspuVBoxCompositorLock(WindowInfo *window);
+extern int renderspuVBoxCompositorUnlock(WindowInfo *window);
+extern const struct VBOXVR_SCR_COMPOSITOR * renderspuVBoxCompositorAcquire( WindowInfo *window);
+extern int renderspuVBoxCompositorTryAcquire(WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR **ppCompositor);
+extern void renderspuVBoxCompositorRelease( WindowInfo *window);
+extern void renderspuVBoxPresentCompositionGeneric( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry, int32_t i32MakeCurrentUserData );
+extern PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window );
+void renderspuVBoxPresentBlitterCleanup( WindowInfo *window );
+extern int renderspuVBoxPresentBlitterEnter( PCR_BLITTER pBlitter, int32_t i32MakeCurrentUserData );
+extern PCR_BLITTER renderspuVBoxPresentBlitterGetAndEnter( WindowInfo *window, int32_t i32MakeCurrentUserData );
+extern PCR_BLITTER renderspuVBoxPresentBlitterEnsureCreated( WindowInfo *window, int32_t i32MakeCurrentUserData );
+extern void renderspuWindowTerm( WindowInfo *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);
+extern void renderspuVBoxCompositorBlitStretched ( const struct VBOXVR_SCR_COMPOSITOR * pCompositor, PCR_BLITTER pBlitter, GLfloat scaleX, GLfloat scaleY);
+extern GLint renderspuCreateContextEx(const char *dpyName, GLint visBits, GLint id, GLint shareCtx);
+extern GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id );
extern GLint RENDER_APIENTRY renderspuWindowCreate( const char *dpyName, GLint visBits );
void RENDER_APIENTRY renderspuWindowDestroy( GLint win );
@@ -324,11 +440,17 @@ extern GLint RENDER_APIENTRY renderspuCreateContext( const char *dpyname, GLint
extern void RENDER_APIENTRY renderspuMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx);
extern void RENDER_APIENTRY renderspuSwapBuffers( GLint window, GLint flags );
+extern uint32_t renderspuContextMarkDeletedAndRelease( ContextInfo *context );
+
+ContextInfo * renderspuDefaultSharedContextAcquire();
+void renderspuDefaultSharedContextRelease(ContextInfo * pCtx);
+uint32_t renderspuContextRelease(ContextInfo *context);
+uint32_t renderspuContextRetain(ContextInfo *context);
+
#ifdef __cplusplus
extern "C" {
#endif
DECLEXPORT(void) renderspuSetWindowId(uint64_t winId);
-DECLEXPORT(void) renderspuSetRootVisibleRegion(GLint cRects, GLint *pRects);
DECLEXPORT(void) renderspuReparentWindow(GLint window);
#ifdef __cplusplus
}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
index 822e56b9..3d14fa3b 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_agl.c
@@ -65,6 +65,9 @@
DEBUG_MSG_RESULT(result, text); \
}
+static void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window);
+static void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects);
+
/* In some case (like compiz which doesn't provide us with clipping regions) we
* have to make sure that *all* open OpenGL windows are clipped to the main
* application window. This is done here when called from the event handler
@@ -340,7 +343,7 @@ renderspuWindowAttachContext(WindowInfo *wi, WindowRef window,
if(!context || !wi)
return render_spu.ws.aglSetCurrentContext( NULL );
-/* DEBUG_MSG_POETZSCH (("WindowAttachContext %d\n", wi->id));*/
+/* DEBUG_MSG_POETZSCH (("WindowAttachContext %d\n", wi->BltInfo.Base.id));*/
/* Flush old context first */
if (context->currentWindow->window != window)
@@ -349,7 +352,7 @@ renderspuWindowAttachContext(WindowInfo *wi, WindowRef window,
* dummy context. */
if (wi->bufferName == -1)
{
- DEBUG_MSG_POETZSCH (("WindowAttachContext: create context %d\n", wi->id));
+ DEBUG_MSG_POETZSCH (("WindowAttachContext: create context %d\n", wi->BltInfo.Base.id));
/* Use the same visual bits as those in the context structure */
AGLPixelFormat pix;
if( !renderspuChoosePixelFormat(context, &pix) )
@@ -519,10 +522,10 @@ renderspu_SystemWindowSize(WindowInfo *window, GLint w, GLint h)
status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemWindowSize): SendEventToEventTarget Failed");
- DEBUG_MSG_POETZSCH (("Size %d visible %d\n", window->id, IsWindowVisible (window->window)));
+ DEBUG_MSG_POETZSCH (("Size %d visible %d\n", window->BltInfo.Base.id, IsWindowVisible (window->window)));
/* save the new size */
- window->width = w;
- window->height = h;
+ window->BltInfo.width = w;
+ window->BltInfo.height = h;
}
void
@@ -602,8 +605,11 @@ renderspu_SystemShowWindow(WindowInfo *window, GLboolean showIt)
status = PostEventToQueue(GetMainEventQueue(), evt, kEventPriorityStandard);
CHECK_CARBON_RC_RETURN_VOID (status, "Render SPU (renderspu_SystemShowWindow): PostEventToQueue Failed");
}
- /* Save the new value */
- window->visible = showIt;
+}
+
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR * pCompositor, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+{
+ renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
}
void
@@ -611,11 +617,13 @@ renderspu_SystemMakeCurrent(WindowInfo *window, GLint nativeWindow,
ContextInfo *context)
{
Boolean result;
-/* DEBUG_MSG_POETZSCH (("makecurrent %d: \n", window->id));*/
+/* DEBUG_MSG_POETZSCH (("makecurrent %d: \n", window->BltInfo.Base.id));*/
CRASSERT(render_spu.ws.aglSetCurrentContext);
//crDebug( "renderspu_SystemMakeCurrent( %x, %i, %x )", window, nativeWindow, context );
+ nativeWindow = 0;
+
if(window && context)
{
CRASSERT(window->window);
@@ -669,7 +677,7 @@ renderspu_SystemSwapBuffers(WindowInfo *window, GLint flags)
crError("Render SPU (renderspu_SystemSwapBuffers): SwapBuffers got a null context from the window");
RTSemFastMutexRequest(render_spu.syncMutex);
-// DEBUG_MSG_POETZSCH (("Swapped %d context %x visible: %d\n", window->id, context->context, IsWindowVisible (window->window)));
+// DEBUG_MSG_POETZSCH (("Swapped %d context %x visible: %d\n", window->BltInfo.Base.id, context->context, IsWindowVisible (window->window)));
if (context->visual &&
context->visual->visAttribs & CR_DOUBLE_BIT)
render_spu.ws.aglSwapBuffers(context->context);
@@ -695,7 +703,7 @@ renderspu_SystemSwapBuffers(WindowInfo *window, GLint flags)
}
}
-void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint* pRects)
+void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects)
{
CRASSERT(window);
CRASSERT(window->window);
@@ -730,7 +738,7 @@ void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint
renderspu_SystemWindowApplyVisibleRegion(window);
}
-void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects)
+static void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects)
{
/* Remember the visible region of the root window if there is one */
if (render_spu.hRootVisibleRegion)
@@ -757,7 +765,7 @@ void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *pRects)
}
/*Assumes that all regions are in the guest coordinates system*/
-void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
+static void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
{
ContextInfo *c = renderspuGetWindowContext(window);
RgnHandle rgn;
@@ -777,8 +785,8 @@ void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
* currently process. */
SetRectRgn(rgn,
window->x, window->y,
- window->x + window->width,
- window->y + window->height);
+ window->x + window->BltInfo.width,
+ window->y + window->BltInfo.height);
SectRgn(render_spu.hRootVisibleRegion, rgn, rgn);
/* Because the clipping is done in the coordinate space of the OpenGL
* window we have to remove the x/y position from the newly created
@@ -790,7 +798,7 @@ void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
/* If there is not root clipping region is available, create a base
* region with the size of the target window. This covers all
* needed/possible space. */
- SetRectRgn(rgn, 0, 0, window->width, window->height);
+ SetRectRgn(rgn, 0, 0, window->BltInfo.width, window->BltInfo.height);
}
/* Now intersect the window clipping region with a additional region e.g.
@@ -838,8 +846,8 @@ renderspu_SystemVBoxCreateWindow(VisualInfo *visual, GLboolean showIt,
windowRect.left = window->x;
windowRect.top = window->y;
- windowRect.right = window->x + window->width;
- windowRect.bottom = window->y + window->height;
+ windowRect.right = window->x + window->BltInfo.width;
+ windowRect.bottom = window->y + window->BltInfo.height;
status = CreateNewWindow(winClass, winAttr, &windowRect, &window->window);
CHECK_CARBON_RC_RETURN (status, "Render SPU (renderspu_SystemVBoxCreateWindow): CreateNewWindow Failed", GL_FALSE);
@@ -848,7 +856,7 @@ renderspu_SystemVBoxCreateWindow(VisualInfo *visual, GLboolean showIt,
CFStringRef title_string;
title_string = CFStringCreateWithCStringNoCopy(NULL, window->title,
kCFStringEncodingMacRoman, NULL);
- SetWindowTitleWithCFString(window->window, title_string);
+ SetWindowTitleWithCFString(window->BltInfo.window, title_string);
CFRelease(title_string);
/* The parent has to be in its own group */
@@ -873,8 +881,22 @@ renderspu_SystemVBoxCreateWindow(VisualInfo *visual, GLboolean showIt,
renderspu_SystemShowWindow(window, GL_TRUE);
crDebug("Render SPU (renderspu_SystemVBoxCreateWindow): actual window (x, y, width, height): %d, %d, %d, %d",
- window->x, window->y, window->width, window->height);
+ window->x, window->y, window->BltInfo.width, window->BltInfo.height);
return GL_TRUE;
}
+int renderspu_SystemInit()
+{
+ return VINF_SUCCESS;
+}
+
+int renderspu_SystemTerm()
+{
+ return VINF_SUCCESS;
+}
+
+void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
+{
+
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
index a3b7b157..f9492a2d 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa.c
@@ -3,7 +3,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,6 +21,9 @@
#include <iprt/string.h>
#include <iprt/path.h>
+#include <cr_string.h>
+#include <cr_mem.h>
+
GLboolean renderspu_SystemInitVisual(VisualInfo *pVisInfo)
{
CRASSERT(pVisInfo);
@@ -82,7 +85,7 @@ GLboolean renderspu_SystemVBoxCreateWindow(VisualInfo *pVisInfo, GLboolean fShow
NativeNSViewRef pParentWin = (NativeNSViewRef)(uint32_t)render_spu_parent_window_id;
#endif /* __LP64__ */
- cocoaViewCreate(&pWinInfo->window, pParentWin, pVisInfo->visAttribs);
+ cocoaViewCreate(&pWinInfo->window, pWinInfo, pParentWin, pVisInfo->visAttribs);
if (fShowIt)
renderspu_SystemShowWindow(pWinInfo, fShowIt);
@@ -151,15 +154,22 @@ void renderspu_SystemShowWindow(WindowInfo *pWinInfo, GLboolean fShowIt)
cocoaViewShow(pWinInfo->window, fShowIt);
}
-void renderspu_SystemMakeCurrent(WindowInfo *pWinInfo, GLint nativeWindow, ContextInfo *pCtxInfo)
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
{
- CRASSERT(pWinInfo);
- CRASSERT(pCtxInfo);
+ cocoaViewPresentComposition(window->window, pChangedEntry);
+}
+void renderspu_SystemMakeCurrent(WindowInfo *pWinInfo, GLint nativeWindow, ContextInfo *pCtxInfo)
+{
/* if(pWinInfo->visual != pCtxInfo->visual)*/
/* printf ("visual mismatch .....................\n");*/
- cocoaViewMakeCurrentContext(pWinInfo->window, pCtxInfo->context);
+ nativeWindow = 0;
+
+ if (pWinInfo && pCtxInfo)
+ cocoaViewMakeCurrentContext(pWinInfo->window, pCtxInfo->context);
+ else
+ cocoaViewMakeCurrentContext(NULL, NULL);
}
void renderspu_SystemSwapBuffers(WindowInfo *pWinInfo, GLint flags)
@@ -169,53 +179,308 @@ void renderspu_SystemSwapBuffers(WindowInfo *pWinInfo, GLint flags)
cocoaViewDisplay(pWinInfo->window);
}
-void renderspu_SystemWindowVisibleRegion(WindowInfo *pWinInfo, GLint cRects, GLint* paRects)
+void renderspu_SystemWindowVisibleRegion(WindowInfo *pWinInfo, GLint cRects, const GLint* paRects)
{
CRASSERT(pWinInfo);
cocoaViewSetVisibleRegion(pWinInfo->window, cRects, paRects);
}
-void renderspu_SystemSetRootVisibleRegion(GLint cRects, GLint *paRects)
+void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *pWinInfo)
{
}
-void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *pWinInfo)
+int renderspu_SystemInit()
{
+ return VINF_SUCCESS;
}
-void renderspu_SystemFlush()
+int renderspu_SystemTerm()
{
- cocoaFlush();
+ CrGlslTerm(&render_spu.GlobalShaders);
+ return VINF_SUCCESS;
}
-void renderspu_SystemFinish()
+static SPUNamedFunctionTable * renderspuFindEntry(SPUNamedFunctionTable *aFunctions, const char *pcszName)
{
- cocoaFinish();
+ SPUNamedFunctionTable *pCur;
+
+ for (pCur = aFunctions ; pCur->name != NULL ; pCur++)
+ {
+ if (!crStrcmp( pcszName, pCur->name ) )
+ {
+ return pCur;
+ }
+ }
+
+ AssertFailed();
+
+ return NULL;
}
-void renderspu_SystemBindFramebufferEXT(GLenum target, GLuint framebuffer)
+typedef struct CR_RENDER_CTX_INFO
{
- cocoaBindFramebufferEXT(target, framebuffer);
+ ContextInfo * pContext;
+ WindowInfo * pWindow;
+} CR_RENDER_CTX_INFO;
+
+void renderspuCtxInfoInitCurrent(CR_RENDER_CTX_INFO *pInfo)
+{
+ GET_CONTEXT(pCurCtx);
+ pInfo->pContext = pCurCtx;
+ pInfo->pWindow = pCurCtx->currentWindow;
}
-void renderspu_SystemCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
+void renderspuCtxInfoRestoreCurrent(CR_RENDER_CTX_INFO *pInfo)
{
- cocoaCopyPixels(x, y, width, height, type);
+ GET_CONTEXT(pCurCtx);
+ if (pCurCtx == pInfo->pContext && (!pCurCtx || pCurCtx->currentWindow == pInfo->pWindow))
+ return;
+ renderspuPerformMakeCurrent(pInfo->pWindow, 0, pInfo->pContext);
}
-void renderspu_SystemGetIntegerv(GLenum pname, GLint * params)
+GLboolean renderspuCtxSetCurrentWithAnyWindow(ContextInfo * pContext, CR_RENDER_CTX_INFO *pInfo)
{
- cocoaGetIntegerv(pname, params);
+ WindowInfo * window;
+ renderspuCtxInfoInitCurrent(pInfo);
+
+ if (pInfo->pContext == pContext)
+ return GL_TRUE;
+
+ window = pContext->currentWindow;
+ if (!window)
+ {
+ window = renderspuGetDummyWindow(pContext->BltInfo.Base.visualBits);
+ if (!window)
+ {
+ crWarning("renderspuGetDummyWindow failed");
+ return GL_FALSE;
+ }
+ }
+
+ Assert(window);
+
+ renderspuPerformMakeCurrent(window, 0, pContext);
+ return GL_TRUE;
}
-void renderspu_SystemReadBuffer(GLenum mode)
+void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
{
- cocoaReadBuffer(mode);
+ CRASSERT(fromContext != toContext);
+
+ if (!CrGlslIsInited(&render_spu.GlobalShaders))
+ {
+ CrGlslInit(&render_spu.GlobalShaders, &render_spu.blitterDispatch);
+ }
+
+ if (fromContext)
+ {
+ if (CrGlslNeedsCleanup(&render_spu.GlobalShaders))
+ {
+ CR_RENDER_CTX_INFO Info;
+ if (renderspuCtxSetCurrentWithAnyWindow(fromContext, &Info))
+ {
+ CrGlslCleanup(&render_spu.GlobalShaders);
+ renderspuCtxInfoRestoreCurrent(&Info);
+ }
+ else
+ crWarning("renderspuCtxSetCurrentWithAnyWindow failed!");
+ }
+ }
+ else
+ {
+ CRASSERT(!CrGlslNeedsCleanup(&render_spu.GlobalShaders));
+ }
+
+ CRASSERT(!CrGlslNeedsCleanup(&render_spu.GlobalShaders));
+
+ if (toContext)
+ {
+ CR_RENDER_CTX_INFO Info;
+ if (renderspuCtxSetCurrentWithAnyWindow(toContext, &Info))
+ {
+ int rc = CrGlslProgGenAllNoAlpha(&render_spu.GlobalShaders);
+ if (!RT_SUCCESS(rc))
+ crWarning("CrGlslProgGenAllNoAlpha failed, rc %d", rc);
+
+ renderspuCtxInfoRestoreCurrent(&Info);
+ }
+ else
+ crWarning("renderspuCtxSetCurrentWithAnyWindow failed!");
+ }
+}
+
+AssertCompile(sizeof (GLhandleARB) == sizeof (void*));
+
+static VBoxGLhandleARB crHndlSearchVBox(GLhandleARB hNative)
+{
+ CRASSERT(!(((uintptr_t)hNative) >> 32));
+ return (VBoxGLhandleARB)((uintptr_t)hNative);
+}
+
+static GLhandleARB crHndlSearchNative(VBoxGLhandleARB hVBox)
+{
+ return (GLhandleARB)((uintptr_t)hVBox);
+}
+
+static VBoxGLhandleARB crHndlAcquireVBox(GLhandleARB hNative)
+{
+ CRASSERT(!(((uintptr_t)hNative) >> 32));
+ return (VBoxGLhandleARB)((uintptr_t)hNative);
}
-void renderspu_SystemDrawBuffer(GLenum mode)
+static GLhandleARB crHndlReleaseVBox(VBoxGLhandleARB hVBox)
{
- cocoaDrawBuffer(mode);
+ return (GLhandleARB)((uintptr_t)hVBox);
}
+static void SPU_APIENTRY renderspu_SystemDeleteObjectARB(VBoxGLhandleARB obj)
+{
+ GLhandleARB hNative = crHndlReleaseVBox(obj);
+ if (!hNative)
+ {
+ crWarning("no native for %d", obj);
+ return;
+ }
+
+ render_spu.pfnDeleteObject(hNative);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetAttachedObjectsARB( VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * pCount, VBoxGLhandleARB * obj )
+{
+ GLhandleARB *paAttachments;
+ GLhandleARB hNative = crHndlSearchNative(containerObj);
+ GLsizei count, i;
+
+ if (pCount)
+ *pCount = 0;
+
+ if (!hNative)
+ {
+ crWarning("no native for %d", obj);
+ return;
+ }
+
+ paAttachments = crCalloc(maxCount * sizeof (*paAttachments));
+ if (!paAttachments)
+ {
+ crWarning("crCalloc failed");
+ return;
+ }
+
+ render_spu.pfnGetAttachedObjects(hNative, maxCount, &count, paAttachments);
+ if (pCount)
+ *pCount = count;
+ if (count > maxCount)
+ {
+ crWarning("count too big");
+ count = maxCount;
+ }
+
+ for (i = 0; i < count; ++i)
+ {
+ obj[i] = crHndlSearchVBox(paAttachments[i]);
+ CRASSERT(obj[i]);
+ }
+
+ crFree(paAttachments);
+}
+
+static VBoxGLhandleARB SPU_APIENTRY renderspu_SystemGetHandleARB(GLenum pname)
+{
+ GLhandleARB hNative = render_spu.pfnGetHandle(pname);
+ VBoxGLhandleARB hVBox;
+ if (!hNative)
+ {
+ crWarning("pfnGetHandle failed");
+ return 0;
+ }
+ hVBox = crHndlAcquireVBox(hNative);
+ CRASSERT(hVBox);
+ return hVBox;
+}
+
+static void SPU_APIENTRY renderspu_SystemGetInfoLogARB( VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog )
+{
+ GLhandleARB hNative = crHndlSearchNative(obj);
+ if (!hNative)
+ {
+ crWarning("invalid handle!");
+ return;
+ }
+
+ render_spu.pfnGetInfoLog(hNative, maxLength, length, infoLog);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetObjectParameterfvARB( VBoxGLhandleARB obj, GLenum pname, GLfloat * params )
+{
+ GLhandleARB hNative = crHndlSearchNative(obj);
+ if (!hNative)
+ {
+ crWarning("invalid handle!");
+ return;
+ }
+
+ render_spu.pfnGetObjectParameterfv(hNative, pname, params);
+}
+
+static void SPU_APIENTRY renderspu_SystemGetObjectParameterivARB( VBoxGLhandleARB obj, GLenum pname, GLint * params )
+{
+ GLhandleARB hNative = crHndlSearchNative(obj);
+ if (!hNative)
+ {
+ crWarning("invalid handle!");
+ return;
+ }
+
+ render_spu.pfnGetObjectParameteriv(hNative, pname, params);
+}
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+ SPUNamedFunctionTable * pEntry;
+
+ pEntry = renderspuFindEntry(aFunctions, "DeleteObjectARB");
+ if (pEntry)
+ {
+ render_spu.pfnDeleteObject = (PFNDELETE_OBJECT)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemDeleteObjectARB;
+ }
+
+ pEntry = renderspuFindEntry(aFunctions, "GetAttachedObjectsARB");
+ if (pEntry)
+ {
+ render_spu.pfnGetAttachedObjects = (PFNGET_ATTACHED_OBJECTS)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemGetAttachedObjectsARB;
+ }
+
+ pEntry = renderspuFindEntry(aFunctions, "GetHandleARB");
+ if (pEntry)
+ {
+ render_spu.pfnGetHandle = (PFNGET_HANDLE)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemGetHandleARB;
+ }
+
+ pEntry = renderspuFindEntry(aFunctions, "GetInfoLogARB");
+ if (pEntry)
+ {
+ render_spu.pfnGetInfoLog = (PFNGET_INFO_LOG)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemGetInfoLogARB;
+ }
+
+ pEntry = renderspuFindEntry(aFunctions, "GetObjectParameterfvARB");
+ if (pEntry)
+ {
+ render_spu.pfnGetObjectParameterfv = (PFNGET_OBJECT_PARAMETERFV)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemGetObjectParameterfvARB;
+ }
+
+ pEntry = renderspuFindEntry(aFunctions, "GetObjectParameterivARB");
+ if (pEntry)
+ {
+ render_spu.pfnGetObjectParameteriv = (PFNGET_OBJECT_PARAMETERIV)pEntry->fn;
+ pEntry->fn = (SPUGenericFunction)renderspu_SystemGetObjectParameterivARB;
+ }
+
+ return cFunctions;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
index 2380f289..546f98b6 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.h
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009-2011 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -21,9 +21,14 @@
#include <iprt/cdefs.h>
#include <VBox/VBoxCocoa.h>
#include <OpenGL/OpenGL.h>
+#include <cr_vreg.h>
+#include <cr_compositor.h>
+
RT_C_DECLS_BEGIN
+struct WindowInfo;
+
ADD_COCOA_NATIVE_REF(NSView);
ADD_COCOA_NATIVE_REF(NSOpenGLContext);
@@ -32,7 +37,7 @@ void cocoaGLCtxCreate(NativeNSOpenGLContextRef *ppCtx, GLbitfield fVisParams, Na
void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx);
/* View management */
-void cocoaViewCreate(NativeNSViewRef *ppView, NativeNSViewRef pParentView, GLbitfield fVisParams);
+void cocoaViewCreate(NativeNSViewRef *ppView, struct WindowInfo *pWinInfo, NativeNSViewRef pParentView, GLbitfield fVisParams);
void cocoaViewReparent(NativeNSViewRef pView, NativeNSViewRef pParentView);
void cocoaViewDestroy(NativeNSViewRef pView);
void cocoaViewDisplay(NativeNSViewRef pView);
@@ -42,16 +47,8 @@ void cocoaViewSetSize(NativeNSViewRef pView, int w, int h);
void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int *pH);
void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx);
-void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, GLint* paRects);
-
-/* OpenGL wrapper */
-void cocoaFlush(void);
-void cocoaFinish(void);
-void cocoaBindFramebufferEXT(GLenum target, GLuint framebuffer);
-void cocoaCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-void cocoaGetIntegerv(GLenum pname, GLint *params);
-void cocoaReadBuffer(GLenum mode);
-void cocoaDrawBuffer(GLenum mode);
+void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, const GLint* paRects);
+void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry);
RT_C_DECLS_END
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
index eb2e5787..db2c00c8 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
@@ -4,7 +4,7 @@
*/
/*
- * Copyright (C) 2009-2011 Oracle Corporation
+ * Copyright (C) 2009-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -18,6 +18,7 @@
#include "renderspu_cocoa_helper.h"
#import <Cocoa/Cocoa.h>
+#undef PVM
#include "chromium.h" /* For the visual bits of chromium */
@@ -25,6 +26,17 @@
#include <iprt/string.h>
#include <iprt/mem.h>
#include <iprt/time.h>
+#include <iprt/assert.h>
+
+#include <cr_vreg.h>
+#include <cr_error.h>
+#include <cr_blitter.h>
+#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
+# include <cr_pixeldata.h>
+#endif
+
+
+#include "renderspu.h"
/** @page pg_opengl_cocoa OpenGL - Cocoa Window System Helper
*
@@ -74,6 +86,7 @@
/* Debug macros */
#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
#if 0
+# define CR_RENDER_FORCE_PRESENT_MAIN_THREAD /* force present schedule to main thread */
# define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
# define DEBUG_VERBOSE /* Define this to get some debug info about the messages flow. */
#endif
@@ -81,9 +94,16 @@
#ifdef DEBUG_misha
# define DEBUG_MSG(text) \
printf text
+# define DEBUG_WARN(text) do { \
+ crWarning text ; \
+ Assert(0); \
+ } while (0)
#else
# define DEBUG_MSG(text) \
do {} while (0)
+# define DEBUG_WARN(text) do { \
+ crWarning text ; \
+ } while (0)
#endif
#ifdef DEBUG_VERBOSE
@@ -159,6 +179,114 @@
} \
while(0);
+static NSOpenGLContext * vboxCtxGetCurrent()
+{
+ GET_CONTEXT(pCtxInfo);
+ if (pCtxInfo)
+ {
+ Assert(pCtxInfo->context);
+ return pCtxInfo->context;
+ }
+
+ return nil;
+}
+
+static bool vboxCtxSyncCurrentInfo()
+{
+ GET_CONTEXT(pCtxInfo);
+ NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
+ NSView *pView = pCtx ? [pCtx view] : nil;
+ bool fAdjusted = false;
+ if (pCtxInfo)
+ {
+ WindowInfo *pWinInfo = pCtxInfo->currentWindow;
+ Assert(pWinInfo);
+ if (pCtxInfo->context != pCtx
+ || pWinInfo->window != pView)
+ {
+ renderspu_SystemMakeCurrent(pWinInfo, 0, pCtxInfo);
+ fAdjusted = true;
+ }
+ }
+ else
+ {
+ if (pCtx)
+ {
+ [NSOpenGLContext clearCurrentContext];
+ fAdjusted = true;
+ }
+ }
+
+ return fAdjusted;
+}
+
+typedef struct VBOX_CR_RENDER_CTX_INFO
+{
+ bool fIsValid;
+ NSOpenGLContext *pCtx;
+ NSView *pView;
+} VBOX_CR_RENDER_CTX_INFO, *PVBOX_CR_RENDER_CTX_INFO;
+
+static void vboxCtxEnter(NSOpenGLContext*pCtx, PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
+{
+ NSOpenGLContext *pOldCtx = vboxCtxGetCurrent();
+ NSView *pOldView = (pOldCtx ? [pOldCtx view] : nil);
+ NSView *pView = [pCtx view];
+ bool fNeedCtxSwitch = (pOldCtx != pCtx || pOldView != pView);
+ Assert(pCtx);
+ // Assert(pOldCtx == m_pGLCtx);
+ // Assert(pOldView == self);
+ // Assert(fNeedCtxSwitch);
+ if (fNeedCtxSwitch)
+ {
+ if(pOldCtx != nil)
+ glFlush();
+
+ [pCtx makeCurrentContext];
+
+ pCtxInfo->fIsValid = true;
+ pCtxInfo->pCtx = pOldCtx;
+ pCtxInfo->pView = pView;
+ }
+ else
+ {
+ pCtxInfo->fIsValid = false;
+ }
+}
+
+static void vboxCtxLeave(PVBOX_CR_RENDER_CTX_INFO pCtxInfo)
+{
+ if (pCtxInfo->fIsValid)
+ {
+ NSOpenGLContext *pOldCtx = pCtxInfo->pCtx;
+ NSView *pOldView = pCtxInfo->pView;
+
+ glFlush();
+ if (pOldCtx != nil)
+ {
+ if ([pOldCtx view] != pOldView)
+ {
+ [pOldCtx setView: pOldView];
+ }
+
+ [pOldCtx makeCurrentContext];
+
+#ifdef DEBUG
+ {
+ NSOpenGLContext *pTstOldCtx = [NSOpenGLContext currentContext];
+ NSView *pTstOldView = (pTstOldCtx ? [pTstOldCtx view] : nil);
+ Assert(pTstOldCtx == pOldCtx);
+ Assert(pTstOldView == pOldView);
+ }
+#endif
+ }
+ else
+ {
+ [NSOpenGLContext clearCurrentContext];
+ }
+ }
+}
+
/** Custom OpenGL context class.
*
* This implementation doesn't allow to set a view to the
@@ -193,25 +321,12 @@
NSOpenGLContext *m_pSharedGLCtx;
RTTHREAD mThread;
-#ifdef FBO
GLuint m_FBOId;
- /* FBO handling */
- GLuint m_FBOTexBackId;
- GLuint m_FBOTexFrontId;
- GLuint m_FBOAttBackId;
- GLuint m_FBOAttFrontId;
- GLuint m_FBODepthStencilPackedId;
- NSSize m_FBOTexSize;
-
- bool m_fFrontDrawing;
-#endif
/** The corresponding dock tile view of this OpenGL view & all helper
* members. */
DockOverlayView *m_DockTileView;
- GLuint m_FBOThumbId;
- GLuint m_FBOThumbTexId;
GLfloat m_FBOThumbScaleX;
GLfloat m_FBOThumbScaleY;
uint64_t m_uiDockUpdateTime;
@@ -225,9 +340,17 @@
NSSize m_Size;
/** This is necessary for clipping on the root window */
- NSPoint m_RootShift;
-}
-- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView;
+ NSRect m_RootRect;
+ float m_yInvRootOffset;
+
+ CR_BLITTER *m_pBlitter;
+ WindowInfo *m_pWinInfo;
+ bool m_fNeedViewportUpdate;
+ bool m_fNeedCtxUpdate;
+ bool m_fDataVisible;
+ bool m_fEverSized;
+}
+- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo;
- (void)setGLCtx:(NSOpenGLContext*)pCtx;
- (NSOpenGLContext*)glCtx;
@@ -238,28 +361,30 @@
- (void)setPos:(NSPoint)pos;
- (NSPoint)pos;
+- (bool)isEverSized;
- (void)setSize:(NSSize)size;
- (NSSize)size;
-- (void)updateViewport;
-- (void)reshape;
+- (void)updateViewportCS;
+- (void)vboxReshapePerform;
+- (void)vboxReshapeOnResizePerform;
+- (void)vboxReshapeOnReparentPerform;
-- (void)createFBO;
-- (void)deleteFBO;
+- (void)createDockTile;
+- (void)deleteDockTile;
-- (bool)isCurrentFBO;
-- (void)updateFBO;
- (void)makeCurrentFBO;
- (void)swapFBO;
-- (void)flushFBO;
-- (void)stateInfo:(GLenum)pname withParams:(GLint*)params;
-- (void)finishFBO;
-- (void)bindFBO:(GLenum)target withFrameBuffer:(GLuint)framebuffer;
-- (void)tryDraw;
-- (void)renderFBOToView;
-- (void)renderFBOToDockTile;
+- (void)vboxTryDraw;
+- (void)vboxTryDrawUI;
+- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor;
+- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry;
+- (void)vboxBlitterSyncWindow;
- (void)clearVisibleRegions;
-- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects;
+- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects;
- (NSView*)dockTileScreen;
- (void)reshapeDockTile;
@@ -465,7 +590,7 @@
{
DEBUG_MSG(("OCTX(%p): setView: new view: %p\n", (void*)self, (void*)view));
-#ifdef FBO
+#if 1 /* def FBO */
m_pView = view;;
#else
[super setView: view];
@@ -474,7 +599,7 @@
-(NSView*)view
{
-#ifdef FBO
+#if 1 /* def FBO */
return m_pView;
#else
return [super view];
@@ -597,10 +722,16 @@
/* Reposition this window with the help of the OverlayView. Perform the
* call in the OpenGL thread. */
/*
- [m_pOverlayView performSelector:@selector(reshape) onThread:m_Thread withObject:nil waitUntilDone:YES];
+ [m_pOverlayView performSelector:@selector(vboxReshapePerform) onThread:m_Thread withObject:nil waitUntilDone:YES];
*/
- [m_pOverlayView reshape];
+ if ([m_pOverlayView isEverSized])
+ {
+ if([NSThread isMainThread])
+ [m_pOverlayView vboxReshapePerform];
+ else
+ [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
+ }
}
- (void)parentWindowChanged:(NSWindow*)pWindow
@@ -622,10 +753,17 @@
/* Reshape the overlay view after a short waiting time to let the main
* window resize itself properly. */
/*
- [m_pOverlayView performSelector:@selector(reshape) withObject:nil afterDelay:0.2];
- [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(reshape) userInfo:nil repeats:NO];
+ [m_pOverlayView performSelector:@selector(vboxReshapePerform) withObject:nil afterDelay:0.2];
+ [NSTimer scheduledTimerWithTimeInterval:0.2 target:m_pOverlayView selector:@selector(vboxReshapePerform) userInfo:nil repeats:NO];
*/
- [m_pOverlayView reshape];
+
+ if ([m_pOverlayView isEverSized])
+ {
+ if([NSThread isMainThread])
+ [m_pOverlayView vboxReshapePerform];
+ else
+ [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
+ }
}
}
@@ -638,30 +776,27 @@
********************************************************************************/
@implementation OverlayView
-- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView
+- (id)initWithFrame:(NSRect)frame thread:(RTTHREAD)aThread parentView:(NSView*)pParentView winInfo:(WindowInfo*)pWinInfo
{
m_pParentView = pParentView;
/* Make some reasonable defaults */
m_pGLCtx = nil;
m_pSharedGLCtx = nil;
mThread = aThread;
-#ifdef FBO
m_FBOId = 0;
- m_FBOTexBackId = 0;
- m_FBOTexFrontId = 0;
- m_FBOAttBackId = GL_COLOR_ATTACHMENT0_EXT;
- m_FBOAttFrontId = GL_COLOR_ATTACHMENT1_EXT;
- m_FBODepthStencilPackedId = 0;
- m_FBOTexSize = NSZeroSize;
-#endif
- m_FBOThumbId = 0;
- m_FBOThumbTexId = 0;
m_cClipRects = 0;
m_paClipRects = NULL;
m_Pos = NSZeroPoint;
m_Size = NSMakeSize(1, 1);
- m_RootShift = NSZeroPoint;
-
+ m_RootRect = NSMakeRect(0, 0, m_Size.width, m_Size.height);
+ m_yInvRootOffset = 0;
+ m_pBlitter = nil;
+ m_pWinInfo = pWinInfo;
+ m_fNeedViewportUpdate = true;
+ m_fNeedCtxUpdate = true;
+ m_fDataVisible = false;
+ m_fEverSized = false;
+
self = [super initWithFrame:frame];
DEBUG_MSG(("OVIW(%p): init OverlayView\n", (void*)self));
@@ -671,15 +806,10 @@
- (void)cleanupData
{
- [self deleteFBO];
-
- if (m_pGLCtx)
- {
- if ([m_pGLCtx view] == self)
- [m_pGLCtx clearDrawable];
-
- m_pGLCtx = nil;
- }
+ [self deleteDockTile];
+
+ [self setGLCtx:nil];
+
if (m_pSharedGLCtx)
{
if ([m_pSharedGLCtx view] == self)
@@ -688,6 +818,12 @@
[m_pSharedGLCtx release];
m_pSharedGLCtx = nil;
+
+ CrBltTerm(m_pBlitter);
+
+ RTMemFree(m_pBlitter);
+
+ m_pBlitter = nil;
}
[self clearVisibleRegions];
@@ -704,7 +840,7 @@
- (void)drawRect:(NSRect)aRect
{
- /* Do nothing */
+ [self vboxTryDrawUI];
}
- (void)setGLCtx:(NSOpenGLContext*)pCtx
@@ -715,9 +851,15 @@
/* ensure the context drawable is cleared to avoid holding a reference to inexistent view */
if (m_pGLCtx)
+ {
[m_pGLCtx clearDrawable];
+ [m_pGLCtx release];
+ /*[m_pGLCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
+ }
m_pGLCtx = pCtx;
+ if (pCtx)
+ [pCtx retain];
}
- (NSOpenGLContext*)glCtx
@@ -755,7 +897,16 @@
m_Pos = pos;
- [self reshape];
+ if (m_fEverSized)
+ [self performSelectorOnMainThread:@selector(vboxReshapePerform) withObject:nil waitUntilDone:NO];
+
+ /* we need to redwar on regions change, however the compositor now is cleared
+ * because all compositor&window data-related modifications are performed with compositor cleared
+ * the renderspu client will re-set the compositor after modifications are complete
+ * this way we indicate renderspu generic code not to ignore the empty compositor */
+ /* generally this should not be needed for setPos because compositor should not be zeroed with it,
+ * in any way setting this flag here should not hurt as it will be re-set on next present */
+ m_pWinInfo->fCompositorPresentEmpty = GL_TRUE;
}
- (NSPoint)pos
@@ -763,26 +914,29 @@
return m_Pos;
}
+- (bool)isEverSized
+{
+ return m_fEverSized;
+}
+
- (void)setSize:(NSSize)size
{
+ NSOpenGLContext *pCurCtx;
+ NSView *pCurView;
m_Size = size;
+
+ m_fEverSized = true;
-#ifdef FBO
- if (m_FBOId)
- {
- DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
- [self reshape];
- [self updateFBO];
- /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
- [self updateViewport];
- }
- else
-#endif
- {
- DEBUG_MSG(("OVIW(%p): setSize (no FBO): new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
- [self reshape];
- [self updateFBO];
- }
+ DEBUG_MSG(("OVIW(%p): setSize: new size: %dx%d\n", (void*)self, (int)size.width, (int)size.height));
+ [self performSelectorOnMainThread:@selector(vboxReshapeOnResizePerform) withObject:nil waitUntilDone:NO];
+
+ /* we need to redwar on regions change, however the compositor now is cleared
+ * because all compositor&window data-related modifications are performed with compositor cleared
+ * the renderspu client will re-set the compositor after modifications are complete
+ * this way we indicate renderspu generic code not to ignore the empty compositor */
+ /* generally this should not be needed for setSize because compositor should not be zeroed with it,
+ * in any way setting this flag here should not hurt as it will be re-set on next present */
+ m_pWinInfo->fCompositorPresentEmpty = GL_TRUE;
}
- (NSSize)size
@@ -790,44 +944,47 @@
return m_Size;
}
-- (void)updateViewport
+- (void)updateViewportCS
{
- NSRect r;
-
DEBUG_MSG(("OVIW(%p): updateViewport\n", (void*)self));
-#ifdef FBO
- if (m_pSharedGLCtx)
+ /* Update the viewport for our OpenGL view */
+ [m_pSharedGLCtx update];
+
+ [self vboxBlitterSyncWindow];
+
+ /* Clear background to transparent */
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+- (void)vboxReshapeOnResizePerform
+{
+ [self vboxReshapePerform];
+
+ [self createDockTile];
+ /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
+ m_fNeedViewportUpdate = true;
+#if 0
+ pCurCtx = [NSOpenGLContext currentContext];
+ if (pCurCtx && pCurCtx == m_pGLCtx && (pCurView = [pCurCtx view]) == self)
+ {
+ [m_pGLCtx update];
+ m_fNeedCtxUpdate = false;
+ }
+ else
{
- /* Update the viewport for our OpenGL view */
- DEBUG_MSG(("OVIW(%p): makeCurrent (shared) %p\n", (void*)self, (void*)m_pSharedGLCtx));
- [m_pSharedGLCtx makeCurrentContext];
- [m_pSharedGLCtx update];
-
- r = [self frame];
- /* Setup all matrices */
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- glViewport(0, 0, r.size.width, r.size.height);
- glOrtho(0, r.size.width, 0, r.size.height, -1, 1);
- DEBUG_MSG_1(("OVIW(%p): frame[%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.x, (int)r.size.width, (int)r.size.height));
- DEBUG_MSG_1(("OVIW(%p): m_Pos(%i,%i) m_Size(%i,%i)\n", (void*)self, (int)m_Pos.x, (int)m_Pos.y, (int)m_Size.width, (int)m_Size.height));
- DEBUG_MSG_1(("OVIW(%p): m_RootShift(%i, %i)\n", (void*)self, (int)m_RootShift.x, (int)m_RootShift.y));
- glMatrixMode(GL_TEXTURE);
- glLoadIdentity();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
-
- /* Clear background to transparent */
- glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
-
- DEBUG_MSG(("OVIW(%p): makeCurrent (non shared) %p\n", (void*)self, (void*)m_pGLCtx));
- [m_pGLCtx makeCurrentContext];
+ /* do it in a lazy way */
+ m_fNeedCtxUpdate = true;
}
#endif
}
-- (void)reshape
+- (void)vboxReshapeOnReparentPerform
+{
+ [self createDockTile];
+}
+
+- (void)vboxReshapePerform
{
NSRect parentFrame = NSZeroRect;
NSPoint parentPos = NSZeroPoint;
@@ -835,38 +992,60 @@
NSRect childFrame = NSZeroRect;
NSRect newFrame = NSZeroRect;
- DEBUG_MSG(("OVIW(%p): reshape\n", (void*)self));
-
- /* Getting the right screen coordinates of the parents frame is a little bit
- * complicated. */
+ DEBUG_MSG(("OVIW(%p): vboxReshapePerform\n", (void*)self));
+
parentFrame = [m_pParentView frame];
- parentPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:NSMakePoint(parentFrame.origin.x, parentFrame.origin.y + parentFrame.size.height)]];
- parentFrame.origin.x = parentPos.x;
- parentFrame.origin.y = parentPos.y;
-
- /* Calculate the new screen coordinates of the overlay window. */
+ DEBUG_MSG(("FIXED parentFrame [%f:%f], [%f:%f]\n", parentFrame.origin.x, parentFrame.origin.y, parentFrame.size.width, parentFrame.size.height));
+ parentPos = parentFrame.origin;
+ parentPos.y += parentFrame.size.height;
+ DEBUG_MSG(("FIXED(view) parentPos [%f:%f]\n", parentPos.x, parentPos.y));
+ parentPos = [m_pParentView convertPoint:parentPos toView:nil];
+ DEBUG_MSG(("FIXED parentPos(win) [%f:%f]\n", parentPos.x, parentPos.y));
+ parentPos = [[m_pParentView window] convertBaseToScreen:parentPos];
+ DEBUG_MSG(("FIXED parentPos(screen) [%f:%f]\n", parentPos.x, parentPos.y));
+ parentFrame.origin = parentPos;
+
childPos = NSMakePoint(m_Pos.x, m_Pos.y + m_Size.height);
- childPos = [[m_pParentView window] convertBaseToScreen:[[m_pParentView superview] convertPointToBase:childPos]];
-
- /* Make a frame out of it. */
+ DEBUG_MSG(("FIXED(view) childPos [%f:%f]\n", childPos.x, childPos.y));
+ childPos = [m_pParentView convertPoint:childPos toView:nil];
+ DEBUG_MSG(("FIXED(win) childPos [%f:%f]\n", childPos.x, childPos.y));
+ childPos = [[m_pParentView window] convertBaseToScreen:childPos];
+ DEBUG_MSG(("FIXED childPos(screen) [%f:%f]\n", childPos.x, childPos.y));
childFrame = NSMakeRect(childPos.x, childPos.y, m_Size.width, m_Size.height);
+ DEBUG_MSG(("FIXED childFrame [%f:%f], [%f:%f]\n", childFrame.origin.x, childFrame.origin.y, childFrame.size.width, childFrame.size.height));
/* We have to make sure that the overlay window will not be displayed out
* of the parent window. So intersect both frames & use the result as the new
* frame for the window. */
newFrame = NSIntersectionRect(parentFrame, childFrame);
- /* Later we have to correct the texture position in the case the window is
- * out of the parents window frame. So save the shift values for later use. */
- if (parentFrame.origin.x > childFrame.origin.x)
- m_RootShift.x = parentFrame.origin.x - childFrame.origin.x;
- else
- m_RootShift.x = 0;
- if (parentFrame.origin.y > childFrame.origin.y)
- m_RootShift.y = parentFrame.origin.y - childFrame.origin.y;
- else
- m_RootShift.y = 0;
+ DEBUG_MSG(("[%#p]: parentFrame pos[%f : %f] size[%f : %f]\n",
+ (void*)self,
+ parentFrame.origin.x, parentFrame.origin.y,
+ parentFrame.size.width, parentFrame.size.height));
+ DEBUG_MSG(("[%#p]: childFrame pos[%f : %f] size[%f : %f]\n",
+ (void*)self,
+ childFrame.origin.x, childFrame.origin.y,
+ childFrame.size.width, childFrame.size.height));
+
+ DEBUG_MSG(("[%#p]: newFrame pos[%f : %f] size[%f : %f]\n",
+ (void*)self,
+ newFrame.origin.x, newFrame.origin.y,
+ newFrame.size.width, newFrame.size.height));
+ /* Later we have to correct the texture position in the case the window is
+ * out of the parents window frame. So save the shift values for later use. */
+ m_RootRect.origin.x = newFrame.origin.x - childFrame.origin.x;
+ m_RootRect.origin.y = childFrame.size.height + childFrame.origin.y - (newFrame.size.height + newFrame.origin.y);
+ m_RootRect.size = newFrame.size;
+ m_yInvRootOffset = newFrame.origin.y - childFrame.origin.y;
+
+ DEBUG_MSG(("[%#p]: m_RootRect pos[%f : %f] size[%f : %f]\n",
+ (void*)self,
+ m_RootRect.origin.x, m_RootRect.origin.y,
+ m_RootRect.size.width, m_RootRect.size.height));
+
+
/*
NSScrollView *pScrollView = [[[m_pParentView window] contentView] enclosingScrollView];
if (pScrollView)
@@ -888,220 +1067,37 @@
[self reshapeDockTile];
/* Make sure the context is updated according */
- [self updateViewport];
-}
-
-- (void)createFBO
-{
- GLint oldTexId = 0;
- GLint oldFBId = 0;
- NSView *pDockScreen = nil;
- GLint maxTexSize = 0;
- GLfloat imageAspectRatio = 0;
- GLint filter = GL_NEAREST;
-
- [self deleteFBO];
-
-#ifdef FBO
- DEBUG_MSG(("OVIW(%p): createFBO\n", (void*)self));
-
- glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &oldTexId);
- glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &oldFBId);
-
- /* If not previously setup generate IDs for FBO and its associated texture. */
- if (!m_FBOId)
- {
- /* Make sure the framebuffer extension is supported */
- const GLubyte* strExt;
- GLboolean isFBO;
- /* Get the extension name string. It is a space-delimited list of the
- * OpenGL extensions that are supported by the current renderer. */
- strExt = glGetString(GL_EXTENSIONS);
- isFBO = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_object", strExt);
- if (!isFBO)
- {
- DEBUG_MSG(("Your system does not support the GL_EXT_framebuffer_object extension\n"));
- }
- isFBO = gluCheckExtension((const GLubyte*)"GL_EXT_framebuffer_blit", strExt);
- if (!isFBO)
- {
- DEBUG_MSG(("Your system does not support the GL_EXT_framebuffer_blit extension\n"));
- }
-
- /* Create FBO object */
- glGenFramebuffersEXT(1, &m_FBOId);
- /* & the texture as well the depth/stencil render buffer */
- glGenTextures(1, &m_FBOTexBackId);
- glGenTextures(1, &m_FBOTexFrontId);
- DEBUG_MSG(("OVIW(%p): gen numbers: FBOId=%d FBOTexBackId=%d FBOTexFrontId=%d\n", (void*)self, m_FBOId, m_FBOTexBackId, m_FBOTexFrontId));
-
- glGenRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
- }
-
- m_FBOTexSize = m_Size;
- /* Bind to FBO */
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
-
- /*
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- */
-
- imageAspectRatio = m_FBOTexSize.width / m_FBOTexSize.height;
-
- /* Sanity check against maximum OpenGL texture size. If bigger adjust to
- * maximum possible size while maintain the aspect ratio. */
- glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTexSize);
- if (m_FBOTexSize.width > maxTexSize || m_FBOTexSize.height > maxTexSize)
+ /* [self updateViewport]; */
+ if (m_pSharedGLCtx)
{
- filter = GL_LINEAR;
- if (imageAspectRatio > 1)
- {
- m_FBOTexSize.width = maxTexSize;
- m_FBOTexSize.height = maxTexSize / imageAspectRatio;
- }
- else
- {
- m_FBOTexSize.width = maxTexSize * imageAspectRatio;
- m_FBOTexSize.height = maxTexSize;
- }
+ VBOX_CR_RENDER_CTX_INFO CtxInfo;
+ vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
+
+ [self updateViewportCS];
+
+ vboxCtxLeave(&CtxInfo);
}
+}
- DEBUG_MSG(("OVIW(%p): tex size is: %dx%d\n", (void*)self, (int)m_FBOTexSize.width, (int)m_FBOTexSize.height));
-
- /* Initialize FBO Textures */
- /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
- * others are also valid, but might incur a costly software translation. */
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexBackId);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexFrontId);
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width, m_FBOTexSize.height, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
-
- /* Now attach the textures to the FBO as its color destinations */
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, m_FBOAttBackId, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexBackId, 0);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, m_FBOAttFrontId, GL_TEXTURE_RECTANGLE_ARB, m_FBOTexFrontId, 0);
-
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, m_FBOTexSize.width, m_FBOTexSize.height);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, m_FBODepthStencilPackedId);
-
- /* Bind the FBOs for reading and drawing. */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
-
- /* Explicitly clear the textures otherwise they would contain old memory stuff. */
- glDrawBuffer(m_FBOAttBackId);
- glClear(GL_COLOR_BUFFER_BIT);
- glDrawBuffer(m_FBOAttFrontId);
- glClear(GL_COLOR_BUFFER_BIT);
-
- /* Now initially reading/drawing to the back buffer. */
- glReadBuffer(m_FBOAttBackId);
- glDrawBuffer(m_FBOAttBackId);
-
- /* Make sure the FBO was created successfully. */
- if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
- DEBUG_MSG(("OVIW(%p): Framebuffer Object creation or update failed!\n", (void*)self));
-
-// glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, oldTexId);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)oldFBId ? (GLuint)oldFBId : m_FBOId);
-
- /* Is there a dock tile preview enabled in the GUI? If so setup a
+- (void)createDockTile
+{
+ NSView *pDockScreen = nil;
+ [self deleteDockTile];
+
+ /* Is there a dock tile preview enabled in the GUI? If so setup a
* additional thumbnail view for the dock tile. */
- pDockScreen = [self dockTileScreen];
- if (pDockScreen)
+ pDockScreen = [self dockTileScreen];
+ if (pDockScreen)
{
- if (!m_FBOThumbId)
- {
- glGenFramebuffersEXT(1, &m_FBOThumbId);
- glGenTextures(1, &m_FBOThumbTexId);
- }
-
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOThumbId);
- /* Initialize FBO Texture */
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP);
-
- /* The GPUs like the GL_BGRA / GL_UNSIGNED_INT_8_8_8_8_REV combination
- * others are also valid, but might incur a costly software translation. */
- glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, m_FBOTexSize.width * m_FBOThumbScaleX, m_FBOTexSize.height * m_FBOThumbScaleY, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
-
- /* Now attach texture to the FBO as its color destination */
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_RECTANGLE_ARB, m_FBOThumbTexId, 0);
-
- /* Make sure the FBO was created successfully. */
- if (GL_FRAMEBUFFER_COMPLETE_EXT != glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT))
- DEBUG_MSG(("OVIW(%p): Framebuffer \"Thumb\" Object creation or update failed!\n", (void*)self));
-
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, oldTexId);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (GLuint)oldFBId ? (GLuint)oldFBId : m_FBOId);
-
m_DockTileView = [[DockOverlayView alloc] init];
[self reshapeDockTile];
[pDockScreen addSubview:m_DockTileView];
}
-
- /* Initialize with one big visual region over the full size */
- [self clearVisibleRegions];
- m_cClipRects = 1;
- m_paClipRects = (GLint*)RTMemAlloc(sizeof(GLint) * 4);
- m_paClipRects[0] = 0;
- m_paClipRects[1] = 0;
- m_paClipRects[2] = m_FBOTexSize.width;
- m_paClipRects[3] = m_FBOTexSize.height;
-#endif
}
-- (void)deleteFBO
+- (void)deleteDockTile
{
- DEBUG_MSG(("OVIW(%p): deleteFBO\n", (void*)self));
-
- if (m_pSharedGLCtx)
- {
- DEBUG_MSG(("OVIW(%p): makeCurrent (shared) %p\n", (void*)self, (void*)m_pSharedGLCtx));
- [m_pSharedGLCtx makeCurrentContext];
- [m_pSharedGLCtx update];
-
- glEnable(GL_TEXTURE_RECTANGLE_ARB);
- glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
- }
-
- if (m_pGLCtx)
- {
- DEBUG_MSG(("OVIW(%p): makeCurrent (non shared) %p\n", (void*)self, (void*)m_pGLCtx));
- [m_pGLCtx makeCurrentContext];
-
-#ifdef FBO
- if (m_FBODepthStencilPackedId > 0)
- {
- glDeleteRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
- m_FBODepthStencilPackedId = 0;
- }
- if (m_FBOTexBackId > 0)
- {
- glDeleteTextures(1, &m_FBOTexBackId);
- m_FBOTexBackId = 0;
- }
- if (m_FBOTexFrontId > 0)
- {
- glDeleteTextures(1, &m_FBOTexFrontId);
- m_FBOTexFrontId = 0;
- }
- if (m_FBOId > 0)
- {
- if ([self isCurrentFBO])
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-
- glDeleteFramebuffersEXT(1, &m_FBOId);
- m_FBOId = 0;
- }
-#endif
- }
-
- if (m_DockTileView != nil)
+ if (m_DockTileView != nil)
{
[m_DockTileView removeFromSuperview];
[m_DockTileView release];
@@ -1109,32 +1105,10 @@
}
}
-- (void)updateFBO
-{
- DEBUG_MSG(("OVIW(%p): updateFBO\n", (void*)self));
-
- [self makeCurrentFBO];
-
- if (m_pGLCtx)
- {
-#ifdef FBO
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- [self createFBO];
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
-#endif
- [m_pGLCtx update];
- }
-}
-
- (void)makeCurrentFBO
{
DEBUG_MSG(("OVIW(%p): makeCurrentFBO\n", (void*)self));
-#ifdef FBO
- DEBUG_MSG(("OVIW(%p): FBOId=%d CTX=%p\n", (void*)self, m_FBOId, (void*)m_pGLCtx));
- if([NSOpenGLContext currentContext] != 0)
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
-#endif
if (m_pGLCtx)
{
if ([m_pGLCtx view] != self)
@@ -1151,352 +1125,325 @@
{
[m_pGLCtx makeCurrentContext];
CHECK_GL_ERROR();
- /*
- [m_pGLCtx update];
- */
+ if (m_fNeedCtxUpdate == true)
+ {
+ [m_pGLCtx update];
+ m_fNeedCtxUpdate = false;
+ }
}
+
+ if (!m_FBOId)
+ {
+ glGenFramebuffersEXT(1, &m_FBOId);
+ Assert(m_FBOId);
+ }
+
}
-#ifdef FBO
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, m_FBOId);
-#endif
}
-- (bool)isCurrentFBO
+- (bool)vboxSharedCtxCreate
{
-#ifdef FBO
- GLint curFBOId = 0;
-
- glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &curFBOId);
- DEBUG_MSG_1(("OVIW(%p): isCurrentFBO: curFBOId=%d FBOId=%d\n", (void*)self, curFBOId, m_FBOId));
- return (GLuint)curFBOId == m_FBOId;
-#else
- return false;
-#endif
-}
-
-- (void)tryDraw
-{
- if ([self lockFocusIfCanDraw])
+ if (m_pSharedGLCtx)
+ return true;
+
+ Assert(!m_pBlitter);
+ m_pBlitter = RTMemAlloc(sizeof (*m_pBlitter));
+ if (!m_pBlitter)
{
- [self renderFBOToView];
- [self unlockFocus];
+ DEBUG_WARN(("m_pBlitter allocation failed"));
+ return false;
+ }
+
+ int rc = CrBltInit(m_pBlitter, NULL, false, false, &render_spu.GlobalShaders, &render_spu.blitterDispatch);
+ if (RT_SUCCESS(rc))
+ {
+ DEBUG_MSG(("blitter created successfully for view 0x%p\n", (void*)self));
}
+ else
+ {
+ DEBUG_WARN(("CrBltInit failed, rc %d", rc));
+ RTMemFree(m_pBlitter);
+ m_pBlitter = NULL;
+ return false;
+ }
+
+ GLint opaque = 0;
+ /* Create a shared context out of the main context. Use the same pixel format. */
+ NSOpenGLContext *pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
+
+ /* Set the new context as non opaque */
+ [pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
+ /* Set this view as the drawable for the new context */
+ [pSharedGLCtx setView: self];
+ m_fNeedViewportUpdate = true;
+
+ m_pSharedGLCtx = pSharedGLCtx;
+
+ return true;
}
-- (void)swapFBO
+- (void)vboxTryDraw
{
- GLint sw = 0;
- GLint readFBOId = 0;
- GLint drawFBOId = 0;
- GLint readId = 0;
- GLint drawId = 0;
-
- DEBUG_MSG(("OVIW(%p): swapFBO\n", (void*)self));
-
-#ifdef FBO
- /* Don't use flush buffers cause we are using FBOs here! */
-
- /* Before we swap make sure everything is done (This is really
- * important. Don't remove.) */
glFlush();
+
+ /* issue to the gui thread */
+ [self setNeedsDisplay:YES];
+}
+
+- (void)vboxTryDrawUI
+{
+ const VBOXVR_SCR_COMPOSITOR *pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
+ if (!m_fDataVisible && !pCompositor)
+ return;
- /* Fetch the current used read and draw buffers. */
- glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFBOId);
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFBOId);
- glGetIntegerv(GL_READ_BUFFER, &readId);
- glGetIntegerv(GL_DRAW_BUFFER, &drawId);
-
- /* Do the swapping of our internal ids */
- sw = m_FBOTexFrontId;
- m_FBOTexFrontId = m_FBOTexBackId;
- m_FBOTexBackId = sw;
- sw = m_FBOAttFrontId;
- m_FBOAttFrontId = m_FBOAttBackId;
- m_FBOAttBackId = sw;
-
- DEBUG_MSG_1(("read FBO: %d draw FBO: %d readId: %d drawId: %d\n", readFBOId, drawFBOId, readId, drawId));
- /* We also have to swap the real ids on the current context. */
- if ((GLuint)readFBOId == m_FBOId)
+ VBOXVR_SCR_COMPOSITOR TmpCompositor;
+
+ if (pCompositor)
{
- if ((GLuint)readId == m_FBOAttFrontId)
- glReadBuffer(m_FBOAttBackId);
- if ((GLuint)readId == m_FBOAttBackId)
- glReadBuffer(m_FBOAttFrontId);
+ if (!m_pSharedGLCtx)
+ {
+ Assert(!m_fDataVisible);
+ renderspuVBoxCompositorRelease(m_pWinInfo);
+ if (![self vboxSharedCtxCreate])
+ {
+ DEBUG_WARN(("vboxSharedCtxCreate failed\n"));
+ return;
+ }
+
+ Assert(m_pSharedGLCtx);
+
+ pCompositor = renderspuVBoxCompositorAcquire(m_pWinInfo);
+ Assert(!m_fDataVisible);
+ if (!pCompositor)
+ return;
+ }
}
- if ((GLuint)drawFBOId == m_FBOId)
+ else
{
- if ((GLuint)drawId == m_FBOAttFrontId)
- glDrawBuffer(m_FBOAttBackId);
- if ((GLuint)drawId == m_FBOAttBackId)
- glDrawBuffer(m_FBOAttFrontId);
+ CrVrScrCompositorInit(&TmpCompositor, NULL);
+ pCompositor = &TmpCompositor;
+ }
+
+ if ([self lockFocusIfCanDraw])
+ {
+ [self vboxPresent:pCompositor];
+ if (pCompositor != &TmpCompositor)
+ renderspuVBoxCompositorRelease(m_pWinInfo);
+
+ [self unlockFocus];
+ }
+ else
+ {
+ [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(vboxTryDrawUI) userInfo:nil repeats:NO];
}
-
- if (m_cClipRects)
- [self tryDraw];
-#else
- [m_pGLCtx flushBuffer];
-#endif
}
-- (void)flushFBO
+- (void)swapFBO
{
- GLint drawId = 0;
- GLint FBOId = 0;
-
- DEBUG_MSG(("OVIW(%p): flushFBO\n", (void*)self));
-
- glFlush();
-#ifdef FBO
- /* If at any time OpenGl operations where done in the front buffer, we need
- * to reflect this in the FBO as well. This is something which on real
- * hardware happens and unfortunately some applications rely on it (grrr ... Compiz). */
- if ( m_fFrontDrawing
- && [self isCurrentFBO])
- {
- /* Only reset if we aren't currently front. */
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &FBOId);
- glGetIntegerv(GL_DRAW_BUFFER, &drawId);
- if (!( (GLuint)FBOId == m_FBOId
- && (GLuint)drawId == m_FBOAttFrontId))
- m_fFrontDrawing = false;
- if (m_cClipRects)
- [self tryDraw];
- }
-#endif
+ [m_pGLCtx flushBuffer];
}
-- (void)finishFBO
+- (void)vboxPresent:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
{
- DEBUG_MSG(("OVIW(%p): finishFBO\n", (void*)self));
+ VBOX_CR_RENDER_CTX_INFO CtxInfo;
+
+ DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));
+
+ Assert(pCompositor);
- glFinish();
-#ifdef FBO
- if (m_cClipRects && [self isCurrentFBO])
- [self tryDraw];
-#endif
+ vboxCtxEnter(m_pSharedGLCtx, &CtxInfo);
+
+ [self vboxPresentCS:pCompositor];
+
+ vboxCtxLeave(&CtxInfo);
}
-- (void)stateInfo:(GLenum)pname withParams:(GLint*)params
+- (void)vboxPresentCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
{
- GLint test;
-// DEBUG_MSG_1(("StateInfo requested: %d\n", pname));
-
- glGetIntegerv(pname, params);
-#ifdef FBO
- switch(pname)
- {
- case GL_FRAMEBUFFER_BINDING_EXT:
- case GL_READ_FRAMEBUFFER_BINDING:
- case GL_READ_FRAMEBUFFER_EXT:
- case GL_DRAW_FRAMEBUFFER_EXT:
{
- if ((GLuint)*params == m_FBOId)
- *params = 0;
- break;
- }
- case GL_READ_BUFFER:
- {
- glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &test);
- if ((GLuint)test == m_FBOId)
+ if ([m_pSharedGLCtx view] != self)
{
- if ((GLuint)*params == m_FBOAttFrontId)
- *params = GL_FRONT;
- else
- if ((GLuint)*params == m_FBOAttBackId)
- *params = GL_BACK;
+ DEBUG_MSG(("OVIW(%p): not current view of shared ctx! Switching ...\n", (void*)self));
+ [m_pSharedGLCtx setView: self];
+ m_fNeedViewportUpdate = true;
}
- break;
- }
- case GL_DRAW_BUFFER:
- {
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &test);
- if ((GLuint)test == m_FBOId)
+
+ if (m_fNeedViewportUpdate)
{
- if ((GLuint)*params == m_FBOAttFrontId)
- *params = GL_FRONT;
- else
- if ((GLuint)*params == m_FBOAttBackId)
- *params = GL_BACK;
+ [self updateViewportCS];
+ m_fNeedViewportUpdate = false;
}
- break;
- }
- }
+
+ /* Render FBO content to the dock tile when necessary. */
+ [self vboxPresentToDockTileCS:pCompositor];
+ /* change to #if 0 to see thumbnail image */
+#if 1
+ [self vboxPresentToViewCS:pCompositor];
+#else
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ [m_pSharedGLCtx flushBuffer];
#endif
+
+ }
}
-- (void)readBuffer:(GLenum)mode
+DECLINLINE(void) vboxNSRectToRect(const NSRect *pR, RTRECT *pRect)
{
-#ifdef FBO
- /*
- if ([self isCurrentFBO])
- */
- {
- if (mode == GL_FRONT)
- {
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
- glReadBuffer(m_FBOAttFrontId);
- }
- else if (mode == GL_BACK)
- {
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
- glReadBuffer(m_FBOAttBackId);
- }
- else
- glReadBuffer(mode);
- }
-#else
- glReadBuffer(mode);
-#endif
+ pRect->xLeft = (int)pR->origin.x;
+ pRect->yTop = (int)pR->origin.y;
+ pRect->xRight = (int)(pR->origin.x + pR->size.width);
+ pRect->yBottom = (int)(pR->origin.y + pR->size.height);
}
-- (void)drawBuffer:(GLenum)mode
+DECLINLINE(void) vboxNSRectToRectUnstretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
{
-#ifdef FBO
- /*
- if ([self isCurrentFBO])
- */
- {
- if (mode == GL_FRONT)
- {
- DEBUG_MSG(("OVIW(%p): front\n", (void*)self));
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
- glDrawBuffer(m_FBOAttFrontId);
- m_fFrontDrawing = true;
- }
- else if (mode == GL_BACK)
- {
- DEBUG_MSG(("OVIW(%p): back\n", (void*)self));
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_FBOId);
- glDrawBuffer(m_FBOAttBackId);
- }
- else
- {
- DEBUG_MSG(("OVIW(%p): other: %d\n", (void*)self, mode));
- glDrawBuffer(mode);
- }
- }
-#else
- glDrawBuffer(mode);
-#endif
+ pRect->xLeft = (int)(pR->origin.x / xStretch);
+ pRect->yTop = (int)(pR->origin.y / yStretch);
+ pRect->xRight = (int)((pR->origin.x + pR->size.width) / xStretch);
+ pRect->yBottom = (int)((pR->origin.y + pR->size.height) / yStretch);
}
-- (void)bindFBO:(GLenum)target withFrameBuffer:(GLuint)framebuffer
+DECLINLINE(void) vboxNSRectToRectStretched(const NSRect *pR, RTRECT *pRect, float xStretch, float yStretch)
{
-#ifdef FBO
- if (framebuffer != 0)
- glBindFramebufferEXT(target, framebuffer);
- else
- glBindFramebufferEXT(target, m_FBOId);
-#else
- glBindFramebufferEXT(target, framebuffer);
-#endif
+ pRect->xLeft = (int)(pR->origin.x * xStretch);
+ pRect->yTop = (int)(pR->origin.y * yStretch);
+ pRect->xRight = (int)((pR->origin.x + pR->size.width) * xStretch);
+ pRect->yBottom = (int)((pR->origin.y + pR->size.height) * yStretch);
}
-- (void)renderFBOToView
+- (void)vboxPresentToViewCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
{
- GLint opaque = 0;
- GLint i = 0;
- GLint oldReadFBOId = 0;
- GLint oldDrawFBOId = 0;
- GLint oldReadId = 0;
- GLint oldDrawId = 0;
-
- DEBUG_MSG(("OVIW(%p): renderFBOToView\n", (void*)self));
-
-#ifdef FBO
-
- /* Fetch the current used read and draw buffers. */
- glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &oldReadFBOId);
- glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &oldDrawFBOId);
- glGetIntegerv(GL_READ_BUFFER, &oldReadId);
- glGetIntegerv(GL_DRAW_BUFFER, &oldDrawId);
+ NSRect r = [self frame];
+ float xStretch, yStretch;
+ DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
- if (!m_pSharedGLCtx)
- {
- /* Create a shared context out of the main context. Use the same pixel format. */
- m_pSharedGLCtx = [[NSOpenGLContext alloc] initWithFormat:[(OverlayOpenGLContext*)m_pGLCtx openGLPixelFormat] shareContext:m_pGLCtx];
-
- /* Set the new context as non opaque */
- [m_pSharedGLCtx setValues:&opaque forParameter:NSOpenGLCPSurfaceOpacity];
- /* Set this view as the drawable for the new context */
- [m_pSharedGLCtx setView: self];
- [self updateViewport];
- }
-
- if (m_pSharedGLCtx)
+#if 1 /* Set to 0 to see the docktile instead of the real output */
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ glDrawBuffer(GL_BACK);
+
+ /* Clear background to transparent */
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ m_fDataVisible = false;
+
+ CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
{
- NSRect r = [self frame];
- DEBUG_MSG(("OVIW(%p): rF2V frame: [%i, %i, %i, %i]\n", (void*)self, (int)r.origin.x, (int)r.origin.y, (int)r.size.width, (int)r.size.height));
-
- if (m_FBOTexFrontId > 0)
+ 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))
{
- if ([m_pSharedGLCtx view] != self)
- {
- DEBUG_MSG(("OVIW(%p): not current view of shared ctx! Switching ...\n", (void*)self));
- [m_pSharedGLCtx setView: self];
- [self updateViewport];
+ uint32_t i;
+ int rc = CrBltEnter(m_pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ for (i = 0; i < cRegions; ++i)
+ {
+ const RTRECT * pSrcRect = &paSrcRegions[i];
+ const RTRECT * pDstRect = &paDstRegions[i];
+ RTRECT DstRect, RestrictDstRect;
+ RTRECT SrcRect, RestrictSrcRect;
+
+ vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
+ VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
+
+ if (VBoxRectIsZero(&DstRect))
+ continue;
+
+ VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
+
+ vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
+ VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
+ VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
+
+ if (VBoxRectIsZero(&SrcRect))
+ continue;
+
+ pSrcRect = &SrcRect;
+ pDstRect = &DstRect;
+
+ const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+
+ CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags | CRBLT_F_NOALPHA);
+
+ m_fDataVisible = true;
+ }
+ CrBltLeave(m_pBlitter);
}
-
- [m_pSharedGLCtx makeCurrentContext];
-
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
- glReadBuffer(m_FBOAttFrontId);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
- glDrawBuffer(GL_BACK);
-
- /* Render FBO content to the dock tile when necessary. */
- [self renderFBOToDockTile];
-
-#if 1 /* Set to 0 to see the docktile instead of the real output */
- /* Clear background to transparent */
- glClear(GL_COLOR_BUFFER_BIT);
-
- /* Blit the content of the FBO to the screen. */
- for (i = 0; i < m_cClipRects; ++i)
+ else
{
- GLint x1 = m_paClipRects[4*i];
- GLint y1 = r.size.height - m_paClipRects[4*i+1];
- GLint x2 = m_paClipRects[4*i+2];
- GLint y2 = r.size.height - m_paClipRects[4*i+3];
- glBlitFramebufferEXT(x1, y1 + m_RootShift.y, x2, y2 + m_RootShift.y,
- x1 - m_RootShift.x, y1, x2 - m_RootShift.x, y2,
- GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ DEBUG_WARN(("CrBltEnter failed rc %d", rc));
}
+ }
+ else
+ {
+ Assert(0);
+ DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
+ }
+ }
#endif
/*
glFinish();
*/
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
[m_pSharedGLCtx flushBuffer];
+}
- [m_pGLCtx makeCurrentContext];
- /* Reset to previous buffer bindings. */
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, oldReadFBOId);
- glReadBuffer(oldReadId);
- glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, oldDrawFBOId);
- glDrawBuffer(oldDrawId);
- }
- }
-#else
- [m_pGLCtx flushBuffer];
-#endif
+- (void)presentComposition:(const VBOXVR_SCR_COMPOSITOR_ENTRY*)pChangedEntry
+{
+ [self vboxTryDraw];
+}
+
+- (void)vboxBlitterSyncWindow
+{
+ CR_BLITTER_WINDOW WinInfo;
+ NSRect r;
+
+ if (!m_pBlitter)
+ return;
+
+ memset(&WinInfo, 0, sizeof (WinInfo));
+
+ r = [self frame];
+ WinInfo.width = r.size.width;
+ WinInfo.height = r.size.height;
+
+ Assert(WinInfo.width == m_RootRect.size.width);
+ Assert(WinInfo.height == m_RootRect.size.height);
+
+ /*CrBltMuralSetCurrentInfo(m_pBlitter, NULL);*/
+
+ CrBltMuralSetCurrentInfo(m_pBlitter, &WinInfo);
+ CrBltCheckUpdateViewport(m_pBlitter);
}
-- (void)renderFBOToDockTile
+#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
+static int g_cVBoxTgaCtr = 0;
+#endif
+- (void)vboxPresentToDockTileCS:(const VBOXVR_SCR_COMPOSITOR*)pCompositor
{
NSRect r = [self frame];
NSRect rr = NSZeroRect;
GLint i = 0;
NSDockTile *pDT = nil;
+ float xStretch, yStretch;
-#ifdef FBO
- if ( m_FBOThumbId
- && m_FBOThumbTexId
- && [m_DockTileView thumbBitmap] != nil)
+ if ([m_DockTileView thumbBitmap] != nil)
{
/* Only update after at least 200 ms, cause glReadPixels is
* heavy performance wise. */
uint64_t uiNewTime = RTTimeMilliTS();
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR CIter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
if (uiNewTime - m_uiDockUpdateTime > 200)
{
m_uiDockUpdateTime = uiNewTime;
@@ -1516,22 +1463,73 @@
glGetTexImage(GL_TEXTURE_RECTANGLE_ARB, 0, GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8_REV, pixels);
#endif
+ glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, 0);
+ glDrawBuffer(GL_BACK);
+
/* Clear background to transparent */
glClear(GL_COLOR_BUFFER_BIT);
rr = [m_DockTileView frame];
-
- for (i = 0; i < m_cClipRects; ++i)
+
+ CrVrScrCompositorGetStretching(pCompositor, &xStretch, &yStretch);
+
+ CrVrScrCompositorConstIterInit(pCompositor, &CIter);
+ while ((pEntry = CrVrScrCompositorConstIterNext(&CIter)) != NULL)
{
- GLint x1 = m_paClipRects[4*i];
- GLint y1 = r.size.height - m_paClipRects[4*i+1];
- GLint x2 = m_paClipRects[4*i+2];
- GLint y2 = r.size.height - m_paClipRects[4*i+3];
-
- glBlitFramebufferEXT(x1, y1 + m_RootShift.y, x2, y2 + m_RootShift.y,
- x1 * m_FBOThumbScaleX, y1 * m_FBOThumbScaleY, x2 * m_FBOThumbScaleX, y2 * m_FBOThumbScaleY,
- GL_COLOR_BUFFER_BIT, GL_LINEAR);
+ 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;
+ int rc = CrBltEnter(m_pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ for (i = 0; i < cRegions; ++i)
+ {
+ const RTRECT * pSrcRect = &paSrcRegions[i];
+ const RTRECT * pDstRect = &paDstRegions[i];
+ RTRECT SrcRect, DstRect, RestrictSrcRect, RestrictDstRect;
+
+ vboxNSRectToRect(&m_RootRect, &RestrictDstRect);
+ VBoxRectIntersected(&RestrictDstRect, pDstRect, &DstRect);
+
+ VBoxRectTranslate(&DstRect, -RestrictDstRect.xLeft, -RestrictDstRect.yTop);
+
+ VBoxRectScale(&DstRect, m_FBOThumbScaleX, m_FBOThumbScaleY);
+
+ if (VBoxRectIsZero(&DstRect))
+ continue;
+
+ vboxNSRectToRectUnstretched(&m_RootRect, &RestrictSrcRect, xStretch, yStretch);
+ VBoxRectTranslate(&RestrictSrcRect, -CrVrScrCompositorEntryRectGet(pEntry)->xLeft, -CrVrScrCompositorEntryRectGet(pEntry)->yTop);
+ VBoxRectIntersected(&RestrictSrcRect, pSrcRect, &SrcRect);
+
+ if (VBoxRectIsZero(&SrcRect))
+ continue;
+
+ pSrcRect = &SrcRect;
+ pDstRect = &DstRect;
+
+ const CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+
+ CrBltBlitTexMural(m_pBlitter, true, CrTdTexGet(pTexData), pSrcRect, pDstRect, 1, fFlags);
+ }
+ CrBltLeave(m_pBlitter);
+ }
+ else
+ {
+ DEBUG_WARN(("CrBltEnter failed rc %d", rc));
+ }
+ }
+ else
+ {
+ Assert(0);
+ DEBUG_MSG_1(("BlitStretched: CrVrScrCompositorEntryRegionsGet failed rc %d\n", rc));
+ }
}
+
glFinish();
glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, 0);
@@ -1540,23 +1538,24 @@
* happens. We have to lock this access, in the case the dock
* is updated currently. */
[m_DockTileView lock];
- glReadPixels(0, 0, rr.size.width, rr.size.height,
+ glReadPixels(0, m_RootRect.size.height - rr.size.height, rr.size.width, rr.size.height,
GL_BGRA,
GL_UNSIGNED_INT_8_8_8_8,
[[m_DockTileView thumbBitmap] bitmapData]);
[m_DockTileView unlock];
-
- glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_FBOId);
- glReadBuffer(m_FBOAttFrontId);
+
+#ifdef VBOX_WITH_CRDUMPER_THUMBNAIL
+ ++g_cVBoxTgaCtr;
+ crDumpNamedTGAF((GLint)rr.size.width, (GLint)rr.size.height,
+ [[m_DockTileView thumbBitmap] bitmapData], "/Users/leo/vboxdumps/dump%d.tga", g_cVBoxTgaCtr);
+#endif
pDT = [[NSApplication sharedApplication] dockTile];
/* Send a display message to the dock tile in the main thread */
[[[NSApplication sharedApplication] dockTile] performSelectorOnMainThread:@selector(display) withObject:nil waitUntilDone:NO];
-
}
}
-#endif
}
- (void)clearVisibleRegions
@@ -1569,7 +1568,7 @@
m_cClipRects = 0;
}
-- (void)setVisibleRegions:(GLint)cRects paRects:(GLint*)paRects
+- (void)setVisibleRegions:(GLint)cRects paRects:(const GLint*)paRects
{
GLint cOldRects = m_cClipRects;
@@ -1589,8 +1588,12 @@
m_cClipRects = cRects;
memcpy(m_paClipRects, paRects, sizeof(GLint) * 4 * cRects);
}
- else if (cOldRects)
- [self tryDraw];
+
+ /* we need to redwar on regions change, however the compositor now is cleared
+ * because all compositor&window data-related modifications are performed with compositor cleared
+ * the renderspu client will re-set the compositor after modifications are complete
+ * this way we indicate renderspu generic code not to ignore the empty compositor */
+ m_pWinInfo->fCompositorPresentEmpty = GL_TRUE;
}
- (NSView*)dockTileScreen
@@ -1615,11 +1618,12 @@
if (pView != nil)
{
NSRect dockFrame = [pView frame];
+ /* todo: this is not correct, we should use framebuffer size here, while parent view frame size may differ in case of scrolling */
NSRect parentFrame = [m_pParentView frame];
m_FBOThumbScaleX = (float)dockFrame.size.width / parentFrame.size.width;
m_FBOThumbScaleY = (float)dockFrame.size.height / parentFrame.size.height;
- newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_RootShift.y) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
+ newFrame = NSMakeRect((int)(m_Pos.x * m_FBOThumbScaleX), (int)(dockFrame.size.height - (m_Pos.y + m_Size.height - m_yInvRootOffset) * m_FBOThumbScaleY), (int)(m_Size.width * m_FBOThumbScaleX), (int)(m_Size.height * m_FBOThumbScaleY));
/*
NSRect newFrame = NSMakeRect ((int)roundf(m_Pos.x * m_FBOThumbScaleX), (int)roundf(dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (int)roundf(m_Size.width * m_FBOThumbScaleX), (int)roundf(m_Size.height * m_FBOThumbScaleY));
NSRect newFrame = NSMakeRect ((m_Pos.x * m_FBOThumbScaleX), (dockFrame.size.height - (m_Pos.y + m_Size.height) * m_FBOThumbScaleY), (m_Size.width * m_FBOThumbScaleX), (m_Size.height * m_FBOThumbScaleY));
@@ -1727,9 +1731,8 @@ void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
- /*
[pCtx release];
- */
+ /*[pCtx performSelectorOnMainThread:@selector(release) withObject:nil waitUntilDone:NO];*/
[pPool release];
}
@@ -1739,12 +1742,12 @@ void cocoaGLCtxDestroy(NativeNSOpenGLContextRef pCtx)
* View management
*
********************************************************************************/
-void cocoaViewCreate(NativeNSViewRef *ppView, NativeNSViewRef pParentView, GLbitfield fVisParams)
+void cocoaViewCreate(NativeNSViewRef *ppView, WindowInfo *pWinInfo, NativeNSViewRef pParentView, GLbitfield fVisParams)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
/* Create our worker view */
- OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView];
+ OverlayView* pView = [[OverlayView alloc] initWithFrame:NSZeroRect thread:RTThreadSelf() parentView:pParentView winInfo:pWinInfo];
if (pView)
{
@@ -1778,7 +1781,8 @@ void cocoaViewReparent(NativeNSViewRef pView, NativeNSViewRef pParentView)
if (pParentView != nil)
{
[[pParentView window] addChildWindow:[pOView overlayWin] ordered:NSWindowAbove];
- [pOView createFBO];
+ if ([pOView isEverSized])
+ [pOView performSelectorOnMainThread:@selector(vboxReshapeOnReparentPerform) withObject:nil waitUntilDone:NO];
}
}
@@ -1886,162 +1890,58 @@ void cocoaViewGetGeometry(NativeNSViewRef pView, int *pX, int *pY, int *pW, int
[pPool release];
}
-void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx)
-{
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
- DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", (void*)pView, (void*)pCtx));
-
- [(OverlayView*)pView setGLCtx:pCtx];
- [(OverlayView*)pView makeCurrentFBO];
-
- [pPool release];
-}
-
-void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, GLint* paRects)
+void cocoaViewPresentComposition(NativeNSViewRef pView, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
- [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
-
- [pPool release];
-}
-
-/********************************************************************************
-*
-* Additional OpenGL wrapper
-*
-********************************************************************************/
-static void performSelectorOnView(SEL selector)
-{
- NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
-
- if (pCtx)
- {
- NSView *pView = [pCtx view];
- if (pView)
- {
- if ([pView respondsToSelector:selector])
- [pView performSelector:selector];
- }
- }
-}
-
-static void performSelectorOnViewOneArg(SEL selector, id arg1)
-{
- NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
-
- if (pCtx)
- {
- NSView *pView = [pCtx view];
- if (pView)
- {
- if ([pView respondsToSelector:selector])
- [pView performSelector:selector withObject:arg1];
- }
- }
-}
-
-static void performSelectorOnViewTwoArgs(SEL selector, id arg1, id arg2)
-{
- NSOpenGLContext *pCtx = [NSOpenGLContext currentContext];
-
- if (pCtx)
+ NSOpenGLContext *pCtx;
+
+ /* view should not necesserily have a context set */
+ pCtx = [(OverlayView*)pView glCtx];
+ if (!pCtx)
{
- NSView *pView = [pCtx view];
- if (pView)
+ ContextInfo * pCtxInfo = renderspuDefaultSharedContextAcquire();
+ if (!pCtxInfo)
{
- if ([pView respondsToSelector:selector])
- [pView performSelector:selector withObject:arg1 withObject:arg2];
+ DEBUG_WARN(("renderspuDefaultSharedContextAcquire returned NULL"));
+
+ [pPool release];
+ return;
}
+
+ pCtx = pCtxInfo->context;
+
+ [(OverlayView*)pView setGLCtx:pCtx];
}
-}
-
-void cocoaFlush(void)
-{
- NSOpenGLContext *pCtx = nil;
-
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
- DEBUG_MSG_1(("glFlush called\n"));
-
- performSelectorOnView(@selector(flushFBO));
-
- [pPool release];
-}
-
-void cocoaFinish(void)
-{
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
- DEBUG_MSG_1(("glFinish called\n"));
-
- performSelectorOnView(@selector(finishFBO));
-
- [pPool release];
-}
-
-void cocoaBindFramebufferEXT(GLenum target, GLuint framebuffer)
-{
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
- DEBUG_MSG_1(("glBindFramebufferEXT called target: %d fb: %d\n", target, framebuffer));
-
- performSelectorOnViewTwoArgs(@selector(bindFBO:withFrameBuffer:), (id)target, (id)framebuffer);
-
- [pPool release];
-}
-
-void cocoaCopyPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type)
-{
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
- GLbitfield mask = GL_COLOR_BUFFER_BIT;
-
- DEBUG_MSG_1(("glCopyPixels called: %d,%d-%dx%d type: %d\n", x, y, width, height, type));
-
-#ifdef FBO
- if (type == GL_DEPTH)
- mask = GL_DEPTH_BUFFER_BIT;
- else if (type == GL_STENCIL)
- mask = GL_STENCIL_BUFFER_BIT;
- glBlitFramebufferEXT(x, y, x + width, y + height, x, y, x + width, y + height, mask, GL_NEAREST);
-#else
- glCopyPixels(x, y, width, height, type);
-#endif
-
- [pPool release];
-}
-
-void cocoaGetIntegerv(GLenum pname, GLint *params)
-{
- NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
-
-// DEBUG_MSG_1(("getIntergerv called: %d\n", pname));
-
- performSelectorOnViewTwoArgs(@selector(stateInfo:withParams:), (id)pname, (id)params);
+
+ [(OverlayView*)pView presentComposition:pChangedEntry];
[pPool release];
}
-void cocoaReadBuffer(GLenum mode)
+void cocoaViewMakeCurrentContext(NativeNSViewRef pView, NativeNSOpenGLContextRef pCtx)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
- DEBUG_MSG_1(("glReadBuffer called: %d\n", mode));
+ DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", (void*)pView, (void*)pCtx));
- performSelectorOnViewOneArg(@selector(readBuffer:), (id)mode);
+ if (pView)
+ {
+ [(OverlayView*)pView setGLCtx:pCtx];
+ [(OverlayView*)pView makeCurrentFBO];
+ }
+ else
+ {
+ [NSOpenGLContext clearCurrentContext];
+ }
[pPool release];
}
-void cocoaDrawBuffer(GLenum mode)
+void cocoaViewSetVisibleRegion(NativeNSViewRef pView, GLint cRects, const GLint* paRects)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
- DEBUG_MSG_1(("glDrawBuffer called: %d\n", mode));
-
- performSelectorOnViewOneArg(@selector(drawBuffer:), (id)mode);
+ [(OverlayView*)pView setVisibleRegions:cRects paRects:paRects];
[pPool release];
}
-
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_config.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_config.c
index 734e7a1a..49d745a6 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_config.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_config.c
@@ -15,13 +15,13 @@
static void set_window_geometry( RenderSPU *render_spu, const char *response )
{
- float x, y, w, h;
+ int x, y, w, h;
CRASSERT(response[0] == '[');
- sscanf( response, "[ %f, %f, %f, %f ]", &x, &y, &w, &h );
+ sscanf( response, "[ %d, %d, %d, %d ]", &x, &y, &w, &h );
render_spu->defaultX = (int) x;
render_spu->defaultY = (int) y;
- render_spu->defaultWidth = (int) w;
- render_spu->defaultHeight = (int) h;
+ render_spu->defaultWidth = (unsigned int) w;
+ render_spu->defaultHeight = (unsigned int) h;
}
static void set_default_visual( RenderSPU *render_spu, const char *response )
@@ -321,7 +321,6 @@ SPUOptions renderSPUOptions[] = {
void renderspuSetVBoxConfiguration( RenderSPU *render_spu )
{
- CRConnection *conn;
int a;
for (a=0; a<256; a++)
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
index eceb96f3..9bdcf293 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_glx.c
@@ -85,6 +85,7 @@ renderDestroyWindow( Display *dpy, Window w )
return WindowExistsFlag;
}
+#if 0
/*
* Garbage collection function.
* Loop over all known windows and check if corresponding X window still
@@ -109,6 +110,7 @@ renderspu_GCWindow(void)
}
}
}
+#endif
static Colormap
GetLUTColormap( Display *dpy, XVisualInfo *vi )
@@ -401,6 +403,314 @@ chooseFBConfig( Display *dpy, int screen, GLbitfield visAttribs )
}
#endif /* GLX_VERSION_1_3 */
+static const char * renderspuGetDisplayName()
+{
+ const char *dpyName;
+
+ if (render_spu.display_string[0])
+ dpyName = render_spu.display_string;
+ else
+ {
+ crWarning("Render SPU: no display..");
+ dpyName = NULL;
+ }
+ return dpyName;
+}
+
+static int renderspuWinCmdWinCreate(WindowInfo *pWindow)
+{
+ return VERR_NOT_IMPLEMENTED;
+}
+
+static int renderspuWinCmdWinDestroy(WindowInfo *pWindow)
+{
+ return VERR_NOT_IMPLEMENTED;
+}
+
+static int renderspuWinCmdInit()
+{
+ const char * dpyName;
+ int rc = VERR_GENERAL_FAILURE;
+
+ if (!crHashtableAllocRegisterKey(render_spu.windowTable, CR_RENDER_WINCMD_ID))
+ {
+ crError("CR_RENDER_WINCMD_ID %d is occupied already", CR_RENDER_WINCMD_ID);
+ return VERR_INVALID_STATE;
+ }
+
+ render_spu.pWinToInfoTable = crAllocHashtable();
+ if (render_spu.pWinToInfoTable)
+ {
+ dpyName = renderspuGetDisplayName();
+ if (dpyName)
+ {
+ GLboolean bRc = renderspuInitVisual(&render_spu.WinCmdVisual, dpyName, render_spu.default_visual);
+ if (bRc)
+ {
+ bRc = renderspuWindowInitWithVisual(&render_spu.WinCmdWindow, &render_spu.WinCmdVisual, GL_FALSE, CR_RENDER_WINCMD_ID);
+ if (bRc)
+ {
+ XSelectInput(render_spu.WinCmdVisual.dpy, render_spu.WinCmdWindow.window, StructureNotifyMask);
+ render_spu.WinCmdAtom = XInternAtom(render_spu.WinCmdVisual.dpy, "VBoxWinCmd", False);
+ CRASSERT(render_spu.WinCmdAtom != None);
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ crError("renderspuWindowInitWithVisual failed");
+ }
+ /* there is no visual destroy impl currently
+ * @todo: implement */
+ }
+ else
+ {
+ crError("renderspuInitVisual failed");
+ }
+ }
+ else
+ {
+ crError("Render SPU: no display, aborting");
+ }
+ crFreeHashtable(render_spu.pWinToInfoTable, NULL);
+ render_spu.pWinToInfoTable = NULL;
+ }
+ else
+ {
+ crError("crAllocHashtable failed");
+ }
+ return rc;
+}
+
+static void renderspuWinCmdTerm()
+{
+ /* 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);
+ crFreeHashtable(render_spu.pWinToInfoTable, NULL);
+ /* we do not have visual destroy functionality
+ * @todo implement */
+}
+
+
+static bool renderspuWinCmdProcess(CR_RENDER_WINCMD* pWinCmd)
+{
+ bool fExit = false;
+ /* process commands */
+ switch (pWinCmd->enmCmd)
+ {
+ case CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE:
+ crHashtableAdd(render_spu.pWinToInfoTable, pWinCmd->pWindow->window, pWinCmd->pWindow);
+ XSelectInput(render_spu.WinCmdVisual.dpy, pWinCmd->pWindow->window, ExposureMask);
+ pWinCmd->rc = VINF_SUCCESS;
+ break;
+ case CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY:
+ crHashtableDelete(render_spu.pWinToInfoTable, pWinCmd->pWindow->window, NULL);
+ pWinCmd->rc = VINF_SUCCESS;
+ break;
+ case CR_RENDER_WINCMD_TYPE_NOP:
+ pWinCmd->rc = VINF_SUCCESS;
+ break;
+ case CR_RENDER_WINCMD_TYPE_EXIT:
+ renderspuWinCmdTerm();
+ pWinCmd->rc = VINF_SUCCESS;
+ fExit = true;
+ pWinCmd->rc = VINF_SUCCESS;
+ break;
+ case CR_RENDER_WINCMD_TYPE_WIN_CREATE:
+ pWinCmd->rc = renderspuWinCmdWinCreate(pWinCmd->pWindow);
+ break;
+ case CR_RENDER_WINCMD_TYPE_WIN_DESTROY:
+ pWinCmd->rc = renderspuWinCmdWinDestroy(pWinCmd->pWindow);
+ break;
+ default:
+ crError("unknown WinCmd command! %d", pWinCmd->enmCmd);
+ pWinCmd->rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ RTSemEventSignal(render_spu.hWinCmdCompleteEvent);
+ return fExit;
+}
+
+static DECLCALLBACK(int) renderspuWinCmdThreadProc(RTTHREAD ThreadSelf, void *pvUser)
+{
+ int rc;
+ bool fExit = false;
+ crDebug("RenderSPU: Window thread started (%x)", crThreadID());
+
+ rc = renderspuWinCmdInit();
+
+ /* notify the main cmd thread that we have started */
+ RTSemEventSignal(render_spu.hWinCmdCompleteEvent);
+
+ if (!RT_SUCCESS(rc))
+ {
+ CRASSERT(!render_spu.pWinToInfoTable);
+ return rc;
+ }
+
+ do
+ {
+ XEvent event;
+ XNextEvent(render_spu.WinCmdVisual.dpy, &event);
+
+ switch (event.type)
+ {
+ case ClientMessage:
+ {
+ CRASSERT(event.xclient.window == render_spu.WinCmdWindow.window);
+ if (event.xclient.window == render_spu.WinCmdWindow.window)
+ {
+ if (render_spu.WinCmdAtom == event.xclient.message_type)
+ {
+ CR_RENDER_WINCMD *pWinCmd;
+ memcpy(&pWinCmd, event.xclient.data.b, sizeof (pWinCmd));
+ fExit = renderspuWinCmdProcess(pWinCmd);
+ }
+ }
+
+ break;
+ }
+ case Expose:
+ {
+ if (!event.xexpose.count)
+ {
+ WindowInfo *pWindow = (WindowInfo*)crHashtableSearch(render_spu.pWinToInfoTable, event.xexpose.window);
+ if (pWindow)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR * pCompositor;
+
+ pCompositor = renderspuVBoxCompositorAcquire(pWindow);
+ if (pCompositor)
+ {
+ renderspuVBoxPresentCompositionGeneric(pWindow, pCompositor, NULL, 0);
+ renderspuVBoxCompositorRelease(pWindow);
+ }
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ } while (!fExit);
+
+ return 0;
+}
+
+static int renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE enmCmd, WindowInfo *pWindow)
+{
+ Status status;
+ XEvent event;
+ CR_RENDER_WINCMD WinCmd, *pWinCmd;
+ int rc;
+
+ pWinCmd = &WinCmd;
+ pWinCmd->enmCmd = enmCmd;
+ pWinCmd->rc = VERR_GENERAL_FAILURE;
+ pWinCmd->pWindow = pWindow;
+
+ memset(&event, 0, sizeof (event));
+ event.type = ClientMessage;
+ event.xclient.window = render_spu.WinCmdWindow.window;
+ event.xclient.message_type = render_spu.WinCmdAtom;
+ event.xclient.format = 8;
+ memcpy(event.xclient.data.b, &pWinCmd, sizeof (pWinCmd));
+
+ status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, StructureNotifyMask, &event);
+ if (!status)
+ {
+ Assert(0);
+ crWarning("XSendEvent returned null");
+ return VERR_GENERAL_FAILURE;
+ }
+
+ XFlush(render_spu.pCommunicationDisplay);
+ rc = RTSemEventWaitNoResume(render_spu.hWinCmdCompleteEvent, RT_INDEFINITE_WAIT);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTSemEventWaitNoResume failed rc %d", rc);
+ return rc;
+ }
+ return pWinCmd->rc;
+}
+
+int renderspu_SystemInit()
+{
+ const char * dpyName;
+ int rc = VERR_GENERAL_FAILURE;
+
+ if (!render_spu.use_glxchoosevisual) {
+ /* sometimes want to set this option with ATI drivers */
+ render_spu.ws.glXChooseVisual = NULL;
+ }
+
+ /* setup communication display connection */
+ dpyName = renderspuGetDisplayName();
+ if (!dpyName)
+ {
+ crWarning("no display name, aborting");
+ return VERR_GENERAL_FAILURE;
+ }
+
+ render_spu.pCommunicationDisplay = XOpenDisplay(dpyName);
+ if (!render_spu.pCommunicationDisplay)
+ {
+ crWarning( "Couldn't open X display named '%s'", dpyName );
+ return VERR_GENERAL_FAILURE;
+ }
+
+ if ( !render_spu.ws.glXQueryExtension( render_spu.pCommunicationDisplay, NULL, NULL ) )
+ {
+ crWarning( "Render SPU: Display %s doesn't support GLX", dpyName );
+ return VERR_GENERAL_FAILURE;
+ }
+
+ rc = RTSemEventCreate(&render_spu.hWinCmdCompleteEvent);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTThreadCreate(&render_spu.hWinCmdThread, renderspuWinCmdThreadProc, NULL, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VBoxCrWinCmd");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventWait(render_spu.hWinCmdCompleteEvent, RT_INDEFINITE_WAIT);
+ if (RT_SUCCESS(rc))
+ {
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ crWarning("RTSemEventWait failed rc %d", rc);
+ }
+
+ RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
+ }
+ else
+ {
+ crWarning("RTThreadCreate failed rc %d", rc);
+ }
+ RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
+ }
+ else
+ {
+ crWarning("RTSemEventCreate failed rc %d", rc);
+ }
+
+ return rc;
+}
+
+int renderspu_SystemTerm()
+{
+ int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_EXIT, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("renderspuWinCmdSubmit EXIT failed rc %d", rc);
+ return rc;
+ }
+
+ RTThreadWait(render_spu.hWinCmdThread, RT_INDEFINITE_WAIT, NULL);
+ RTSemEventDestroy(render_spu.hWinCmdCompleteEvent);
+ return VINF_SUCCESS;
+}
GLboolean
renderspu_SystemInitVisual( VisualInfo *visual )
@@ -418,20 +728,15 @@ renderspu_SystemInitVisual( VisualInfo *visual )
}
#endif
- if (render_spu.display_string[0])
- dpyName = render_spu.display_string;
- else if (visual->displayName[0])
- dpyName = visual->displayName;
- else
- dpyName = NULL;
-
+ dpyName = renderspuGetDisplayName();
if (!dpyName)
{
crWarning("Render SPU: no display, aborting");
return GL_FALSE;
}
- crDebug("Render SPU: Opening display %s", dpyName);
+
+ crInfo("Render SPU: Opening display %s", dpyName);
if (dpyName &&
(crStrncmp(dpyName, "localhost:11", 12) == 0 ||
@@ -640,15 +945,15 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
window->x = 0;
window->y = 0;
- window->width = xwa.width;
- window->height = xwa.height;
+ window->BltInfo.width = xwa.width;
+ window->BltInfo.height = xwa.height;
}
/* i've changed default window size to be 0,0 but X doesn't like it */
- /*CRASSERT(window->width >= 1);
- CRASSERT(window->height >= 1);*/
- if (window->width < 1) window->width = 1;
- if (window->height < 1) window->height = 1;
+ /*CRASSERT(window->BltInfo.width >= 1);
+ CRASSERT(window->BltInfo.height >= 1);*/
+ if (window->BltInfo.width < 1) window->BltInfo.width = 1;
+ if (window->BltInfo.height < 1) window->BltInfo.height = 1;
/*
* Get a colormap.
@@ -707,7 +1012,7 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
crDebug("Render SPU: VBox parent window_id is: %x", render_spu_parent_window_id);
window->window = XCreateWindow(dpy, render_spu_parent_window_id,
window->x, window->y,
- window->width, window->height,
+ window->BltInfo.width, window->BltInfo.height,
0, visual->visual->depth, InputOutput,
visual->visual->visual, flags, &swa);
}
@@ -720,7 +1025,7 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
crDebug("Render SPU: Creating global window, parent: %x", RootWindow(dpy, visual->visual->screen));
window->window = XCreateWindow(dpy, RootWindow(dpy, visual->visual->screen),
window->x, window->y,
- window->width, window->height,
+ window->BltInfo.width, window->BltInfo.height,
0, visual->visual->depth, InputOutput,
visual->visual->visual, flags, &swa);
}
@@ -790,8 +1095,8 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
hints.x = window->x;
hints.y = window->y;
- hints.width = window->width;
- hints.height = window->height;
+ hints.width = window->BltInfo.width;
+ hints.height = window->BltInfo.height;
hints.min_width = hints.width;
hints.min_height = hints.height;
hints.max_width = hints.width;
@@ -825,7 +1130,6 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
XIfEvent( dpy, &event, WaitForMapNotify,
(char *) window->window );
}
- window->visible = showIt;
if ((window->visual->visAttribs & CR_DOUBLE_BIT) && render_spu.nvSwapGroup) {
/* NOTE:
@@ -835,7 +1139,7 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
* app window is in a separate swap group while all the back-end windows
* which form a mural are in the same swap group.
*/
- GLuint group = 0; /*render_spu.nvSwapGroup + window->id;*/
+ GLuint group = 0; /*render_spu.nvSwapGroup + window->BltInfo.Base.id;*/
GLuint barrier = 0;
JoinSwapGroup(dpy, visual->visual->screen, window->window, group, barrier);
}
@@ -844,9 +1148,15 @@ createWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
* End GLX code
*/
crDebug( "Render SPU: actual window x, y, width, height: %d, %d, %d, %d",
- window->x, window->y, window->width, window->height );
+ window->x, window->y, window->BltInfo.width, window->BltInfo.height );
XSync(dpy, 0);
+
+ if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
+ {
+ int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_CREATE, window);
+ AssertRC(rc);
+ }
return GL_TRUE;
}
@@ -860,15 +1170,15 @@ createPBuffer( VisualInfo *visual, WindowInfo *window )
window->y = 0;
window->nativeWindow = 0;
- CRASSERT(window->width > 0);
- CRASSERT(window->height > 0);
+ CRASSERT(window->BltInfo.width > 0);
+ CRASSERT(window->BltInfo.height > 0);
#ifdef GLX_VERSION_1_3
{
int attribs[100], i = 0, w, h;
CRASSERT(visual->fbconfig);
- w = window->width;
- h = window->height;
+ w = window->BltInfo.width;
+ h = window->BltInfo.height;
attribs[i++] = GLX_PRESERVED_CONTENTS;
attribs[i++] = True;
attribs[i++] = GLX_PBUFFER_WIDTH;
@@ -896,8 +1206,8 @@ GLboolean
renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, WindowInfo *window )
{
if (visual->visAttribs & CR_PBUFFER_BIT) {
- window->width = render_spu.defaultWidth;
- window->height = render_spu.defaultHeight;
+ window->BltInfo.width = render_spu.defaultWidth;
+ window->BltInfo.height = render_spu.defaultHeight;
return createPBuffer(visual, window);
}
else {
@@ -938,6 +1248,11 @@ renderspu_SystemDestroyWindow( WindowInfo *window )
* window. I know...personal responsibility and all...
*/
if (!window->nativeWindow) {
+ if (window->BltInfo.Base.id != CR_RENDER_WINCMD_ID)
+ {
+ int rc = renderspuWinCmdSubmit(CR_RENDER_WINCMD_TYPE_WIN_ON_DESTROY, window);
+ AssertRC(rc);
+ }
XDestroyWindow(window->visual->dpy, window->window);
XSync(window->visual->dpy, 0);
}
@@ -1000,7 +1315,7 @@ renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, Context
if (visual->visual)
crDebug("Render SPU: Created %s context (%d) on display %s for visAttribs 0x%x",
is_direct ? "DIRECT" : "INDIRECT",
- context->id,
+ context->BltInfo.Base.id,
DisplayString(visual->dpy),
visual->visAttribs);
@@ -1152,18 +1467,18 @@ renderspu_SystemDestroyContext( ContextInfo *context )
static void
check_buffer_size( WindowInfo *window )
{
- if (window->width != window->in_buffer_width
- || window->height != window->in_buffer_height
+ if (window->BltInfo.width != window->in_buffer_width
+ || window->BltInfo.height != window->in_buffer_height
|| ! window->buffer) {
crFree(window->buffer);
- window->buffer = crCalloc(window->width * window->height
+ window->buffer = crCalloc(window->BltInfo.width * window->BltInfo.height
* 4 * sizeof (GLubyte));
- window->in_buffer_width = window->width;
- window->in_buffer_height = window->height;
+ window->in_buffer_width = window->BltInfo.width;
+ window->in_buffer_height = window->BltInfo.height;
- crDebug("Render SPU: dimensions changed to %d x %d", window->width, window->height);
+ crDebug("Render SPU: dimensions changed to %d x %d", window->BltInfo.width, window->BltInfo.height);
}
}
#endif
@@ -1176,7 +1491,6 @@ renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
Bool b;
CRASSERT(render_spu.ws.glXMakeCurrent);
- window->appWindow = nativeWindow;
/*crDebug("%s nativeWindow=0x%x", __FUNCTION__, (int) nativeWindow);*/
@@ -1185,16 +1499,20 @@ renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
check_buffer_size(window);
render_spu.OSMesaMakeCurrent( (OSMesaContext) context->context,
window->buffer, GL_UNSIGNED_BYTE,
- window->width, window->height);
+ window->BltInfo.width, window->BltInfo.height);
return;
}
#endif
+ nativeWindow = 0;
+
if (window && context) {
+ window->appWindow = nativeWindow;
+
if (window->visual != context->visual) {
crDebug("Render SPU: MakeCurrent visual mismatch (win(%d) bits:0x%x != ctx(%d) bits:0x%x); remaking window.",
- window->id, window->visual->visAttribs,
- context->id, context->visual->visAttribs);
+ window->BltInfo.Base.id, window->visual->visAttribs,
+ context->BltInfo.Base.id, context->visual->visAttribs);
/*
* XXX have to revisit this issue!!!
*
@@ -1273,7 +1591,7 @@ renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
if (vid != (int) context->visual->visual->visualid) {
crWarning("Render SPU: Can't bind context %d to CRUT/native window "
"0x%x because of different X visuals (0x%x != 0x%x)!",
- context->id, (int) nativeWindow,
+ context->BltInfo.Base.id, (int) nativeWindow,
vid, (int) context->visual->visual->visualid);
crWarning("Render SPU: Trying to recreate GLX context to match.");
/* Try to recreate the GLX context so that it uses the same
@@ -1327,7 +1645,7 @@ renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
crWarning("glXMakeCurrent(%p, 0x%x, %p) failed! (winId %d, ctxId %d)",
window->visual->dpy,
(int) window->window, (void *) context->context,
- window->id, context->id );
+ window->BltInfo.Base.id, context->BltInfo.Base.id );
}
/*CRASSERT(b);*/
}
@@ -1344,6 +1662,18 @@ renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow,
}
#endif
}
+ else
+ {
+ GET_CONTEXT(pCurCtx);
+ if (pCurCtx)
+ {
+ b = render_spu.ws.glXMakeCurrent( pCurCtx->currentWindow->visual->dpy, None, NULL);
+ if (!b) {
+ crWarning("glXMakeCurrent(%p, None, NULL) failed!", pCurCtx->currentWindow->visual->dpy);
+ }
+ }
+
+ }
#if 0
/* XXX disabled for now due to problem with threadtest.conf */
@@ -1360,8 +1690,8 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
{
#ifdef USE_OSMESA
if (render_spu.use_osmesa) {
- window->width = w;
- window->height = h;
+ window->BltInfo.width = w;
+ window->BltInfo.height = h;
check_buffer_size(window);
return;
}
@@ -1394,7 +1724,7 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
}
}
- if (window->width != w || window->height != h) {
+ if (window->BltInfo.width != w || window->BltInfo.height != h) {
/* Only resize if the new dimensions really are different */
#ifdef CHROMIUM_THREADSAFE
ContextInfo *currentContext = (ContextInfo *) crGetTSD(&_RenderTSD);
@@ -1403,10 +1733,10 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
#endif
/* Can't resize pbuffers, so destroy it and make a new one */
render_spu.ws.glXDestroyPbuffer(window->visual->dpy, window->window);
- window->width = w;
- window->height = h;
+ window->BltInfo.width = w;
+ window->BltInfo.height = h;
crDebug("Render SPU: Creating new %d x %d PBuffer (id=%d)",
- w, h, window->id);
+ w, h, window->BltInfo.Base.id);
if (!createPBuffer(window->visual, window)) {
crWarning("Render SPU: Unable to create PBuffer (out of VRAM?)!");
}
@@ -1419,6 +1749,15 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
}
}
else {
+ if (!w || !h)
+ {
+ /* X can not handle zero sizes */
+ if (window->visible)
+ {
+ renderspu_SystemShowWindow( window, GL_FALSE );
+ }
+ return;
+ }
/* Resize ordinary X window */
/*
* This is ugly, but it seems to be the only thing that works.
@@ -1432,6 +1771,16 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
crDebug("Render SPU: XResizeWindow (%x, %x, %d, %d)", window->visual->dpy, window->window, w, h);
XResizeWindow(window->visual->dpy, window->window, w, h);
XSync(window->visual->dpy, 0);
+
+ if (!window->BltInfo.width || !window->BltInfo.height)
+ {
+ /* we have hidden the window instead of sizing it to (0;0) since X is unable to handle zero sizes */
+ if (window->visible)
+ {
+ renderspu_SystemShowWindow( window, GL_TRUE );
+ return;
+ }
+ }
#if 0
for (attempt = 0; attempt < 3; attempt++) { /* try three times max */
XWindowAttributes attribs;
@@ -1444,10 +1793,6 @@ renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
}
#endif
}
-
- /* finally, save the new size */
- window->width = w;
- window->height = h;
}
@@ -1457,8 +1802,8 @@ renderspu_SystemGetWindowGeometry( WindowInfo *window,
{
#ifdef USE_OSMESA
if (render_spu.use_osmesa) {
- *w = window->width;
- *h = window->height;
+ *w = window->BltInfo.width;
+ *h = window->BltInfo.height;
return;
}
#endif
@@ -1470,8 +1815,8 @@ renderspu_SystemGetWindowGeometry( WindowInfo *window,
{
*x = 0;
*y = 0;
- *w = window->width;
- *h = window->height;
+ *w = window->BltInfo.width;
+ *h = window->BltInfo.height;
}
else
{
@@ -1544,7 +1889,7 @@ renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
}
void
-renderspu_SystemWindowVisibleRegion( WindowInfo *window, GLint cRects, GLint *pRects )
+renderspu_SystemWindowVisibleRegion( WindowInfo *window, GLint cRects, const GLint *pRects )
{
#ifdef USE_OSMESA
if (render_spu.use_osmesa)
@@ -1609,18 +1954,64 @@ renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
{
if (showIt)
{
- XMapWindow( window->visual->dpy, window->window );
- XSync(window->visual->dpy, 0);
+ if (window->BltInfo.width && window->BltInfo.height)
+ {
+ XMapWindow( window->visual->dpy, window->window );
+ XSync(window->visual->dpy, 0);
+ }
}
else
{
XUnmapWindow( window->visual->dpy, window->window );
XSync(window->visual->dpy, 0);
}
- window->visible = showIt;
}
}
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+{
+ /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
+ * here it forces rendering in WinCmd thread rather than a Main thread.
+ * it is used for debugging only in any way actually.
+ * @todo: change to some more generic macro name */
+#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
+ const struct VBOXVR_SCR_COMPOSITOR *pCompositor;
+ /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
+ int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
+ if (RT_SUCCESS(rc))
+ {
+ renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
+ renderspuVBoxCompositorRelease(window);
+ }
+ else if (rc == VERR_SEM_BUSY)
+#endif
+ {
+ Status status;
+ XEvent event;
+ render_spu.self.Flush();
+ renderspuVBoxPresentBlitterEnsureCreated(window, 0);
+
+ crMemset(&event, 0, sizeof (event));
+ event.type = Expose;
+ event.xexpose.window = window->window;
+ event.xexpose.width = window->BltInfo.width;
+ event.xexpose.height = window->BltInfo.height;
+ status = XSendEvent(render_spu.pCommunicationDisplay, render_spu.WinCmdWindow.window, False, 0, &event);
+ if (!status)
+ {
+ Assert(0);
+ crWarning("XSendEvent returned null");
+ }
+ XFlush(render_spu.pCommunicationDisplay);
+ }
+#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
+ else
+ {
+ /* this is somewhat we do not expect */
+ crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
+ }
+#endif
+}
static void
MarkWindow(WindowInfo *w)
@@ -1632,7 +2023,7 @@ MarkWindow(WindowInfo *w)
gcValues.function = GXnoop;
gc = XCreateGC(w->visual->dpy, w->nativeWindow, GCFunction, &gcValues);
}
- XDrawLine(w->visual->dpy, w->nativeWindow, gc, 0, 0, w->width, w->height);
+ XDrawLine(w->visual->dpy, w->nativeWindow, gc, 0, 0, w->BltInfo.width, w->BltInfo.height);
}
@@ -1683,3 +2074,13 @@ void renderspu_SystemReparentWindow(WindowInfo *window)
XReparentWindow(window->visual->dpy, window->window, parent, window->x, window->y);
XSync(window->visual->dpy, False);
}
+
+void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
+{
+
+}
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+ return cFunctions;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
index d22af98f..6d46faf8 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_init.c
@@ -9,6 +9,7 @@
#include "cr_error.h"
#include "cr_string.h"
#include "cr_url.h"
+#include "cr_environment.h"
#include "renderspu.h"
#include <stdio.h>
@@ -94,16 +95,17 @@ static DWORD WINAPI renderSPUWindowThreadProc(void* unused)
if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW)
{
LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam;
- HWND *phWnd;
+ HWND hWnd;
+ WindowInfo *pWindow = (WindowInfo *)pCS->lpCreateParams;
CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams);
- phWnd = pCS->lpCreateParams;
-
- *phWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style,
+ hWnd = CreateWindowEx(pCS->dwExStyle, pCS->lpszName, pCS->lpszClass, pCS->style,
pCS->x, pCS->y, pCS->cx, pCS->cy,
pCS->hwndParent, pCS->hMenu, pCS->hInstance, &render_spu);
+ pWindow->hWnd = hWnd;
+
SetEvent(render_spu.hWinThreadReadyEvent);
}
else if (msg.message == WM_VBOX_RENDERSPU_DESTROY_WINDOW)
@@ -138,6 +140,8 @@ renderSPUInit( int id, SPU *child, SPU *self,
int numFuncs, numSpecial;
GLint defaultWin, defaultCtx;
WindowInfo *windowInfo;
+ const char * pcpwSetting;
+ int rc;
(void) child;
(void) context_id;
@@ -188,20 +192,39 @@ renderSPUInit( int id, SPU *child, SPU *self,
numFuncs += numSpecial;
-#ifdef GLX
- if (!render_spu.use_glxchoosevisual) {
- /* sometimes want to set this option with ATI drivers */
- render_spu.ws.glXChooseVisual = NULL;
+ render_spu.contextTable = crAllocHashtableEx(1, INT32_MAX);
+ render_spu.windowTable = crAllocHashtableEx(1, INT32_MAX);
+
+ render_spu.dummyWindowTable = crAllocHashtable();
+
+ pcpwSetting = crGetenv("CR_RENDER_ENABLE_SINGLE_PRESENT_CONTEXT");
+ if (pcpwSetting)
+ {
+ if (pcpwSetting[0] == '0')
+ pcpwSetting = NULL;
}
-#endif
- render_spu.window_id = 0;
- render_spu.context_id = 0;
- render_spu.contextTable = crAllocHashtable();
- render_spu.windowTable = crAllocHashtable();
+ if (pcpwSetting)
+ {
+ /* TODO: need proper blitter synchronization, do not use so far!
+ * the problem is that rendering can be done in multiple thread: the main command (hgcm) thread and the redraw thread
+ * we currently use per-window synchronization, while we'll need a per-blitter synchronization if one blitter is used for multiple windows
+ * this is not done currently */
+ crWarning("TODO: need proper blitter synchronization, do not use so far!");
+ render_spu.blitterTable = crAllocHashtable();
+ CRASSERT(render_spu.blitterTable);
+ }
+ else
+ render_spu.blitterTable = NULL;
CRASSERT(render_spu.default_visual & CR_RGB_BIT);
-
+
+ rc = renderspu_SystemInit();
+ if (!RT_SUCCESS(rc))
+ {
+ crError("renderspu_SystemInit failed rc %d", rc);
+ return NULL;
+ }
#ifdef USE_OSMESA
if (render_spu.use_osmesa) {
if (!crLoadOSMesa(&render_spu.OSMesaCreateContext,
@@ -249,8 +272,8 @@ renderSPUInit( int id, SPU *child, SPU *self,
*/
crDebug("Render SPU: Creating default window (visBits=0x%x, id=0)",
render_spu.default_visual);
- defaultWin = renderspuWindowCreate( NULL, render_spu.default_visual );
- if (defaultWin != 0) {
+ defaultWin = renderspuWindowCreateEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_WINDOW_ID );
+ if (defaultWin != CR_RENDER_DEFAULT_WINDOW_ID) {
crError("Render SPU: Couldn't get a double-buffered, RGB visual with Z!");
return NULL;
}
@@ -258,13 +281,16 @@ renderSPUInit( int id, SPU *child, SPU *self,
crDebug("Render SPU: Creating default context, visBits=0x%x",
render_spu.default_visual );
- defaultCtx = renderspuCreateContext( NULL, render_spu.default_visual, 0 );
- CRASSERT(defaultCtx == 0);
+ defaultCtx = renderspuCreateContextEx( NULL, render_spu.default_visual, CR_RENDER_DEFAULT_CONTEXT_ID, 0 );
+ if (defaultCtx != CR_RENDER_DEFAULT_CONTEXT_ID) {
+ crError("Render SPU: failed to create default context!");
+ return NULL;
+ }
renderspuMakeCurrent( defaultWin, 0, defaultCtx );
/* Get windowInfo for the default window */
- windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, 0);
+ windowInfo = (WindowInfo *) crHashtableSearch(render_spu.windowTable, CR_RENDER_DEFAULT_WINDOW_ID);
CRASSERT(windowInfo);
windowInfo->mapPending = GL_TRUE;
@@ -347,17 +373,21 @@ renderSPUInit( int id, SPU *child, SPU *self,
render_spu.gather_conns = NULL;
+ numFuncs = renderspu_SystemPostprocessFunctions(_cr_render_table, numFuncs, RT_ELEMENTS(_cr_render_table));
+
crDebug("Render SPU: ---------- End of Init -------------");
return &render_functions;
}
-
static void renderSPUSelfDispatch(SPUDispatchTable *self)
{
crSPUInitDispatchTable( &(render_spu.self) );
crSPUCopyDispatchTable( &(render_spu.self), self );
+ crSPUInitDispatchTable( &(render_spu.blitterDispatch) );
+ crSPUCopyDispatchTable( &(render_spu.blitterDispatch), self );
+
render_spu.server = (CRServer *)(self->server);
{
@@ -377,8 +407,7 @@ static void renderSPUSelfDispatch(SPUDispatchTable *self)
static void DeleteContextCallback( void *data )
{
ContextInfo *context = (ContextInfo *) data;
- renderspu_SystemDestroyContext(context);
- crFree(context);
+ renderspuContextMarkDeletedAndRelease(context);
}
static void DeleteWindowCallback( void *data )
@@ -388,12 +417,45 @@ static void DeleteWindowCallback( void *data )
crFree(window);
}
+static void DeleteBlitterCallback( void *data )
+{
+ PCR_BLITTER pBlitter = (PCR_BLITTER) data;
+ CrBltTerm(pBlitter);
+ crFree(pBlitter);
+}
+
+static void renderspuBlitterCleanupCB(unsigned long key, void *data1, void *data2)
+{
+ WindowInfo *window = (WindowInfo *) data1;
+ CRASSERT(window);
+
+ renderspuVBoxPresentBlitterCleanup( window );
+}
+
static int renderSPUCleanup(void)
{
+ renderspuVBoxCompositorClearAll();
+
+ if (render_spu.blitterTable)
+ {
+ crFreeHashtable(render_spu.blitterTable, DeleteBlitterCallback);
+ render_spu.blitterTable = NULL;
+ }
+ else
+ {
+ crHashtableWalk(render_spu.windowTable, renderspuBlitterCleanupCB, NULL);
+
+ crHashtableWalk(render_spu.dummyWindowTable, renderspuBlitterCleanupCB, NULL);
+ }
+
+ renderspuSetDefaultSharedContext(NULL);
+
crFreeHashtable(render_spu.contextTable, DeleteContextCallback);
render_spu.contextTable = NULL;
crFreeHashtable(render_spu.windowTable, DeleteWindowCallback);
render_spu.windowTable = NULL;
+ crFreeHashtable(render_spu.dummyWindowTable, DeleteWindowCallback);
+ render_spu.dummyWindowTable = NULL;
crFreeHashtable(render_spu.barrierHash, crFree);
render_spu.barrierHash = NULL;
@@ -482,26 +544,3 @@ DECLEXPORT(void) renderspuSetWindowId(uint64_t winId)
{
render_spu_parent_window_id = winId;
}
-
-static void renderspuWindowVisibleRegionCB(unsigned long key, void *data1, void *data2)
-{
- WindowInfo *window = (WindowInfo *) data1;
- CRASSERT(window);
-
- renderspu_SystemWindowApplyVisibleRegion(window);
-}
-
-DECLEXPORT(void) renderspuSetRootVisibleRegion(GLint cRects, GLint *pRects)
-{
-#ifdef RT_OS_DARWIN
- renderspu_SystemSetRootVisibleRegion(cRects, pRects);
-
- crHashtableWalk(render_spu.windowTable, renderspuWindowVisibleRegionCB, NULL);
-#endif
-}
-
-#ifndef RT_OS_DARWIN
-void renderspu_SystemWindowApplyVisibleRegion(WindowInfo *window)
-{
-}
-#endif
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
index c1a903f0..1bd745a8 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_wgl.c
@@ -425,7 +425,49 @@ MainWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
/* int w,h; */
switch ( uMsg ) {
+ case WM_PAINT:
+ {
+ WindowInfo *pWindow = (WindowInfo *)GetWindowLongPtr(hWnd, GWLP_USERDATA);
+ if (pWindow)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR * pCompositor;
+
+ pCompositor = renderspuVBoxCompositorAcquire(pWindow);
+ if (pCompositor)
+ {
+ HDC hDC;
+ PAINTSTRUCT Paint;
+
+ Assert(pWindow->device_context);
+ hDC = BeginPaint(pWindow->hWnd, &Paint);
+ if (hDC)
+ {
+ BOOL bRc;
+ pWindow->redraw_device_context = hDC;
+ renderspuVBoxPresentCompositionGeneric(pWindow, pCompositor, NULL, 1);
+
+ bRc = EndPaint(pWindow->hWnd, &Paint);
+
+ pWindow->redraw_device_context = NULL;
+
+ renderspuVBoxCompositorRelease(pWindow);
+
+ if (!bRc)
+ {
+ DWORD winEr = GetLastError();
+ crWarning("EndPaint failed, winEr %d", winEr);
+ }
+ }
+ else
+ {
+ DWORD winEr = GetLastError();
+ crWarning("BeginPaint failed, winEr %d", winEr);
+ }
+ }
+ }
+ break;
+ }
case WM_SIZE:
/* w = LOWORD( lParam );
* h = HIWORD( lParam ); */
@@ -557,7 +599,11 @@ bSetupPixelFormatEXT( HDC hdc, GLbitfield visAttribs)
crDebug("Render SPU: wglChoosePixelFormatEXT (vis 0x%x, LastError 0x%x, pixelFormat 0x%x", vis, GetLastError(), pixelFormat);
+#ifdef VBOX_CR_SERVER_FORCE_WGL
render_spu.ws.wglSetPixelFormat( hdc, pixelFormat, &ppfd );
+#else
+ SetPixelFormat( hdc, pixelFormat, &ppfd );
+#endif
crDebug("Render SPU: wglSetPixelFormat (Last error 0x%x)", GetLastError());
@@ -616,6 +662,7 @@ bSetupPixelFormatNormal( HDC hdc, GLbitfield visAttribs )
* by our faker library, otherwise we have to call the GDI
* versions.
*/
+#ifdef VBOX_CR_SERVER_FORCE_WGL
if (crGetenv( "CR_WGL_DO_NOT_USE_GDI" ) != NULL)
{
pixelformat = render_spu.ws.wglChoosePixelFormat( hdc, ppfd );
@@ -633,6 +680,7 @@ bSetupPixelFormatNormal( HDC hdc, GLbitfield visAttribs )
render_spu.ws.wglDescribePixelFormat( hdc, pixelformat, sizeof(*ppfd), ppfd );
}
else
+#endif
{
/* Okay, we were loaded manually. Call the GDI functions. */
pixelformat = ChoosePixelFormat( hdc, ppfd );
@@ -782,27 +830,27 @@ GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, Wi
int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
- window->width = GetSystemMetrics( SM_CXSCREEN ) ;
- window->height = GetSystemMetrics( SM_CYSCREEN ) ;
+ window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
+ window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
- crDebug( "Render SPU: Window Dims: %d, %d", window->width, window->height );
+ crDebug( "Render SPU: Window Dims: %d, %d", window->BltInfo.width, window->BltInfo.height );
window->x = render_spu->defaultX - smCxFixedFrame - 1;
window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
- window_plus_caption_width = window->width + 2 * smCxFixedFrame;
- window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
+ window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
+ window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
#else
/* Since it's undecorated, we don't have to do anything fancy
* with these parameters. */
- window->width = GetSystemMetrics( SM_CXSCREEN ) ;
- window->height = GetSystemMetrics( SM_CYSCREEN ) ;
+ window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
+ window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
window->x = 0;
window->y = 0;
- window_plus_caption_width = window->width;
- window_plus_caption_height = window->height;
+ window_plus_caption_width = window->BltInfo.width;
+ window_plus_caption_height = window->BltInfo.height;
#endif
}
@@ -819,8 +867,8 @@ GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, Wi
smCyCaption = GetSystemMetrics( SM_CYCAPTION );
crDebug( "Render SPU: Got the Caption " );
- window_plus_caption_width = window->width + 2 * smCxFixedFrame;
- window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
+ window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
+ window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
window->x = render_spu.defaultX - smCxFixedFrame;
window->y = render_spu.defaultY - smCyFixedFrame - smCyCaption;
@@ -845,11 +893,11 @@ GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, Wi
if (!showIt)
{
renderspu_SystemShowWindow( window, 0 );
- if (window->height <= 0 || window->width <= 0)
+ if (window->BltInfo.height <= 0 || window->BltInfo.width <= 0)
{
renderspu_SystemWindowSize(window,
- window->width > 0 ? window->width : 4,
- window->height > 0 ? window->height : 4);
+ window->BltInfo.width > 0 ? window->BltInfo.width : 4,
+ window->BltInfo.height > 0 ? window->BltInfo.height : 4);
}
}
else
@@ -878,6 +926,11 @@ GLboolean renderspu_SystemCreateWindow( VisualInfo *visual, GLboolean showIt, Wi
ShowCursor( FALSE );
window->device_context = GetDC( window->hWnd );
+ if (!window->device_context)
+ {
+ DWORD winEr = GetLastError();
+ crWarning("GetDC failed, winEr %d", winEr);
+ }
crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
@@ -998,27 +1051,27 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
int smCyFixedFrame = GetSystemMetrics( SM_CXFIXEDFRAME ) + 1;
int smCyCaption = GetSystemMetrics( SM_CYCAPTION );
- window->width = GetSystemMetrics( SM_CXSCREEN ) ;
- window->height = GetSystemMetrics( SM_CYSCREEN ) ;
+ window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
+ window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
- crDebug( "Render SPU: Window Dims: %d, %d", window->width, window->height );
+ crDebug( "Render SPU: Window Dims: %d, %d", window->BltInfo.width, window->BltInfo.height );
window->x = render_spu->defaultX - smCxFixedFrame - 1;
window->y = render_spu->defaultY - smCyFixedFrame - smCyCaption;
- window_plus_caption_width = window->width + 2 * smCxFixedFrame;
- window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
+ window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
+ window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
#else
/* Since it's undecorated, we don't have to do anything fancy
* with these parameters. */
- window->width = GetSystemMetrics( SM_CXSCREEN ) ;
- window->height = GetSystemMetrics( SM_CYSCREEN ) ;
+ window->BltInfo.width = GetSystemMetrics( SM_CXSCREEN ) ;
+ window->BltInfo.height = GetSystemMetrics( SM_CYSCREEN ) ;
window->x = 0;
window->y = 0;
- window_plus_caption_width = window->width;
- window_plus_caption_height = window->height;
+ window_plus_caption_width = window->BltInfo.width;
+ window_plus_caption_height = window->BltInfo.height;
#endif
}
@@ -1034,8 +1087,8 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
smCyCaption = GetSystemMetrics( SM_CYCAPTION );
crDebug( "Render SPU: Got the Caption " );
- window_plus_caption_width = window->width + 2 * smCxFixedFrame;
- window_plus_caption_height = window->height + 2 * smCyFixedFrame + smCyCaption;
+ window_plus_caption_width = window->BltInfo.width + 2 * smCxFixedFrame;
+ window_plus_caption_height = window->BltInfo.height + 2 * smCyFixedFrame + smCyCaption;
window->x = render_spu.defaultX;
window->y = render_spu.defaultY;
@@ -1046,13 +1099,13 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
WINDOW_NAME, WINDOW_NAME,
window_style,
window->x, window->y,
- window->width,
- window->height,
+ window->BltInfo.width,
+ window->BltInfo.height,
(void*) render_spu_parent_window_id, NULL, hinstance, &render_spu );*/
{
CREATESTRUCT cs;
- cs.lpCreateParams = &window->hWnd;
+ cs.lpCreateParams = window;
cs.dwExStyle = WS_EX_NOACTIVATE | WS_EX_NOPARENTNOTIFY;
cs.lpszName = WINDOW_NAME;
@@ -1060,8 +1113,8 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
cs.style = window_style;
cs.x = window->x;
cs.y = window->y;
- cs.cx = window->width;
- cs.cy = window->height;
+ cs.cx = window->BltInfo.width;
+ cs.cy = window->BltInfo.height;
cs.hwndParent = (void*) render_spu_parent_window_id;
cs.hMenu = NULL;
cs.hInstance = hinstance;
@@ -1110,16 +1163,20 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
if (!showIt)
{
renderspu_SystemShowWindow( window, 0 );
- if (window->height <= 0 || window->width <= 0)
+ if (window->BltInfo.height <= 0 || window->BltInfo.width <= 0)
{
renderspu_SystemWindowSize(window,
- window->width > 0 ? window->width : 4,
- window->height > 0 ? window->height : 4);
+ window->BltInfo.width > 0 ? window->BltInfo.width : 4,
+ window->BltInfo.height > 0 ? window->BltInfo.height : 4);
}
}
else
{
+#ifdef DEBUG_misha
+ crWarning( "Render SPU: Showing the window" );
+#else
crDebug( "Render SPU: Showing the window" );
+#endif
crDebug("renderspu_SystemCreateWindow: showwindow: %x", window->hWnd);
}
@@ -1127,7 +1184,7 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
/* Intel drivers require a window to be visible for proper 3D rendering,
* so set it visible and handle the visibility with visible regions (see below) */
- if (window->id)
+ if (window->BltInfo.Base.id != CR_RENDER_DEFAULT_WINDOW_ID)
{
ShowWindow( window->hWnd, SW_SHOWNORMAL );
}
@@ -1140,17 +1197,22 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
//SetForegroundWindow( visual->hWnd );
SetWindowPos( window->hWnd, HWND_TOP, window->x, window->y,
- window->width, window->height,
+ window->BltInfo.width, window->BltInfo.height,
( render_spu.fullscreen ?
(SWP_SHOWWINDOW | SWP_NOSENDCHANGING | SWP_NOREDRAW | SWP_NOACTIVATE ) : SWP_NOACTIVATE
) );
crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
- window->x, window->y, window->width, window->height);
+ window->x, window->y, window->BltInfo.width, window->BltInfo.height);
if ( render_spu.fullscreen )
ShowCursor( FALSE );
window->device_context = GetDC( window->hWnd );
+ if (!window->device_context)
+ {
+ DWORD winEr = GetLastError();
+ crWarning("GetDC failed, winEr %d", winEr);
+ }
crDebug( "Render SPU: Got the DC: 0x%x", window->device_context );
@@ -1160,16 +1222,52 @@ GLboolean renderspu_SystemVBoxCreateWindow( VisualInfo *visual, GLboolean showIt
return GL_FALSE;
}
+ /* set the window pointer data at the last step to ensure our WM_PAINT callback does not do anything until we are fully initialized */
+ {
+ LONG_PTR oldVal = SetWindowLongPtr(window->hWnd, GWLP_USERDATA, (LONG_PTR)window);
+ DWORD winEr = GetLastError();
+ Assert(!oldVal && winEr == NO_ERROR);
+ }
+
return GL_TRUE;
}
+static void renderspuWindowRgnApply(WindowInfo *window)
+{
+ HRGN hRgn = window->hRgn;
+ if (hRgn)
+ {
+ /* note: according to the docs, SetWindowRgn owns the regions after it is called,
+ * and the regions will be freed automatically when needed,
+ * i.e. the caller should not do that.
+ * this is why we need to make a copy of the regions to be passed in */
+
+ int result;
+ hRgn = CreateRectRgn(0, 0, 0, 0);
+ if (!hRgn)
+ {
+ WARN(("CreateRectRgn failed"));
+ return;
+ }
+
+ result = CombineRgn(hRgn, window->hRgn, NULL, RGN_COPY);
+ if (result == ERROR)
+ {
+ WARN(("CombineRgn failed"));
+ return;
+ }
+ }
+
+ SetWindowRgn(window->hWnd, hRgn, true);
+}
+
/* Either show or hide the render SPU's window. */
void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
{
if (showIt)
{
crDebug("SHOW renderspu_SystemShowWindow: %x", window->hWnd);
- SetWindowRgn(window->hWnd, window->hRgn, true);
+ renderspuWindowRgnApply(window);
}
else
{
@@ -1177,11 +1275,44 @@ void renderspu_SystemShowWindow( WindowInfo *window, GLboolean showIt )
crDebug("HIDE renderspu_SystemShowWindow: %x", window->hWnd);
hRgn = CreateRectRgn(0, 0, 0, 0);
SetWindowRgn(window->hWnd, hRgn, true);
- DeleteObject(hRgn);
+ /* note: according to the docs, SetWindowRgn owns the regions after it is called,
+ * and the regions will be freed automatically when needed,
+ * i.e. the caller should not do that */
}
window->visible = showIt;
}
+void renderspu_SystemVBoxPresentComposition( WindowInfo *window, const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pChangedEntry )
+{
+ /* the CR_RENDER_FORCE_PRESENT_MAIN_THREAD is actually inherited from cocoa backend impl,
+ * here it forces rendering in WinCmd thread rather than a Main thread.
+ * it is used for debugging only in any way actually.
+ * @todo: change to some more generic macro name */
+#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
+ const struct VBOXVR_SCR_COMPOSITOR *pCompositor;
+ /* we do not want to be blocked with the GUI thread here, so only draw her eif we are really able to do that w/o bllocking */
+ int rc = renderspuVBoxCompositorTryAcquire(window, &pCompositor);
+ if (RT_SUCCESS(rc))
+ {
+ renderspuVBoxPresentCompositionGeneric(window, pCompositor, pChangedEntry, 0);
+ renderspuVBoxCompositorRelease(window);
+ }
+ else if (rc == VERR_SEM_BUSY)
+#endif
+ {
+ render_spu.self.Flush();
+ renderspuVBoxPresentBlitterEnsureCreated(window, 0);
+ RedrawWindow(window->hWnd, NULL, NULL, RDW_INTERNALPAINT);
+ }
+#ifndef CR_RENDER_FORCE_PRESENT_MAIN_THREAD
+ else
+ {
+ /* this is somewhat we do not expect */
+ crWarning("renderspuVBoxCompositorTryAcquire failed rc %d", rc);
+ }
+#endif
+}
+
GLboolean renderspu_SystemCreateContext( VisualInfo *visual, ContextInfo *context, ContextInfo *sharedContext )
{
(void) sharedContext;
@@ -1215,29 +1346,20 @@ void renderspu_SystemDestroyContext( ContextInfo *context )
static GLboolean renderspuChkActivateSharedContext(ContextInfo *sharedContext)
{
- GLint crWindow;
WindowInfo *window;
if (sharedContext->hRC)
return GL_TRUE;
- CRASSERT(sharedContext->id);
+ CRASSERT(sharedContext->BltInfo.Base.id);
if (sharedContext->shared)
renderspuChkActivateSharedContext(sharedContext->shared);
- crWindow = renderspuWindowCreate(sharedContext->visual->displayName, sharedContext->visual->visAttribs);
- if (!crWindow)
- {
- crError("renderspuChkActivateSharedContext: renderspuWindowCreate failed!");
- return GL_FALSE;
- }
-
- window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, crWindow);
+ window = renderspuGetDummyWindow(sharedContext->visual->visAttribs);
if (!window)
{
- crError("renderspuChkActivateSharedContext: crHashtableSearch failed!");
- renderspuWindowDestroy(crWindow);
+ crError("renderspuChkActivateSharedContext: renderspuGetDummyWindow failed!");
return GL_FALSE;
}
@@ -1249,12 +1371,9 @@ static GLboolean renderspuChkActivateSharedContext(ContextInfo *sharedContext)
if (!sharedContext->hRC)
{
crError( "Render SPU: (renderspuChkActivateSharedContext) Couldn't create the context for the window (error 0x%x)", GetLastError() );
- renderspuWindowDestroy(crWindow);
return GL_FALSE;
}
- sharedContext->currentWindow = window;
-
return GL_TRUE;
}
@@ -1274,12 +1393,12 @@ void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, Contex
/*@todo Chromium has no correct code to remove window ids and associated info from
* various tables. This is hack which just hides the root case.
*/
- crDebug("Recreating window in renderspu_SystemMakeCurrent\n");
+ crWarning("Recreating window in renderspu_SystemMakeCurrent\n");
renderspu_SystemDestroyWindow( window );
renderspu_SystemVBoxCreateWindow( context->visual, window->visible, window );
}
- if (render_spu.render_to_app_window && nativeWindow)
+ if (0/*render_spu.render_to_app_window && nativeWindow*/)
{
/* The render_to_app_window option
* is set and we've got a nativeWindow
@@ -1320,6 +1439,7 @@ void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, Contex
else
{
if (!context->hRC) {
+ CRASSERT(!nativeWindow);
if (context->shared)
{
/* first make sure we have shared context created */
@@ -1337,11 +1457,16 @@ void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, Contex
&& context->hRC)
{
/* share lists */
- render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
+ BOOL bRc = render_spu.ws.wglShareLists(context->shared->hRC, context->hRC);
+ if (!bRc)
+ {
+ DWORD winEr = GetLastError();
+ crWarning("wglShareLists failed, winEr %d", winEr);
+ }
}
/*Requery ext function pointers, we skip dummy ctx as it should never be used with ext functions*/
- if (0 && context->id)
+ if (0 && context->BltInfo.Base.id)
{
int numFuncs, i;
SPUNamedFunctionTable ext_table[1000];
@@ -1366,7 +1491,7 @@ void renderspu_SystemMakeCurrent( WindowInfo *window, GLint nativeWindow, Contex
}
/*crDebug("MakeCurrent 0x%x, 0x%x", window->device_context, context->hRC);*/
- if (!render_spu.ws.wglMakeCurrent(window->device_context, context->hRC))
+ if (!render_spu.ws.wglMakeCurrent(!nativeWindow ? window->device_context : window->redraw_device_context, context->hRC))
{
DWORD err = GetLastError();
crError("Render SPU: (MakeCurrent) failed to make 0x%x, 0x%x current with 0x%x error.", window->device_context, context->hRC, err);
@@ -1400,8 +1525,8 @@ void renderspu_SystemWindowSize( WindowInfo *window, GLint w, GLint h )
crDebug("Render SPU: SetWindowSize (%x, %d, %d, %d, %d)", window->hWnd, window->x, window->y, w, h);
}
/* save the new size */
- window->width = w;
- window->height = h;
+ window->BltInfo.width = w;
+ window->BltInfo.height = h;
}
@@ -1443,18 +1568,18 @@ void renderspu_SystemWindowPosition( WindowInfo *window, GLint x, GLint y )
/*SetWindowRgn(window->visual->hWnd, NULL, false);*/
if (!SetWindowPos( window->hWnd, HWND_TOP,
- x, y, window->width, window->height, winprop )) {
- crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, x, y, window->width, window->height);
+ x, y, window->BltInfo.width, window->BltInfo.height, winprop )) {
+ crWarning("!!!FAILED!!! Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd, x, y, window->BltInfo.width, window->BltInfo.height);
} else {
crDebug("Render SPU: SetWindowPos (%x, %d, %d, %d, %d)", window->hWnd,
- x, y, window->width, window->height);
+ x, y, window->BltInfo.width, window->BltInfo.height);
}
/* save the new position */
window->x = x;
window->y = y;
}
-void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint* pRects)
+void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, const GLint* pRects)
{
GLint i;
HRGN hRgn, hTmpRgn;
@@ -1477,12 +1602,12 @@ void renderspu_SystemWindowVisibleRegion(WindowInfo *window, GLint cRects, GLint
DeleteObject(hTmpRgn);
}
+ window->hRgn = hRgn;
+
if (window->visible)
- SetWindowRgn(window->hWnd, hRgn, true);
+ renderspuWindowRgnApply(window);
crDebug("Render SPU: SetWindowRgn (%x, cRects=%i)", window->hWnd, cRects);
-
- window->hRgn = hRgn;
}
static void renderspuHandleWindowMessages( HWND hWnd )
@@ -1502,7 +1627,7 @@ void renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
int return_value;
/* peek at the windows message queue */
- renderspuHandleWindowMessages( w->hWnd );
+// renderspuHandleWindowMessages( w->hWnd );
/* render_to_app_window:
* w->nativeWindow will only be non-zero if the
@@ -1511,14 +1636,18 @@ void renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
* structure.
*/
if (render_spu.render_to_app_window && w->nativeWindow) {
+#ifdef VBOX_CR_SERVER_FORCE_WGL
return_value = render_spu.ws.wglSwapBuffers( w->nativeWindow );
+#else
+ return_value = SwapBuffers( w->nativeWindow );
+#endif
} else {
/*
HRGN hRgn1, hRgn2, hRgn3;
HWND hWndParent;
LONG ws;
- hRgn1 = CreateRectRgn(0, 0, w->width, w->height);
+ hRgn1 = CreateRectRgn(0, 0, w->BltInfo.width, w->BltInfo.height);
hRgn2 = CreateRectRgn(50, 50, 100, 100);
hRgn3 = CreateRectRgn(0, 0, 0, 0);
CombineRgn(hRgn3, hRgn1, hRgn2, RGN_DIFF);
@@ -1554,7 +1683,11 @@ void renderspu_SystemSwapBuffers( WindowInfo *w, GLint flags )
return_value, NULLREGION, SIMPLEREGION, COMPLEXREGION, ERROR);
crDebug("rcClip(%d, %d, %d, %d)", rcClip.left, rcClip.top, rcClip.right, rcClip.bottom);
*/
+#ifdef VBOX_CR_SERVER_FORCE_WGL
return_value = render_spu.ws.wglSwapBuffers( w->device_context );
+#else
+ return_value = SwapBuffers( w->device_context );
+#endif
}
if (!return_value)
{
@@ -1570,3 +1703,23 @@ void renderspu_SystemReparentWindow(WindowInfo *window)
{
SetParent(window->hWnd, (HWND)render_spu_parent_window_id);
}
+
+int renderspu_SystemInit()
+{
+ return VINF_SUCCESS;
+}
+
+int renderspu_SystemTerm()
+{
+ return VINF_SUCCESS;
+}
+
+void renderspu_SystemDefaultSharedContextChanged(ContextInfo *fromContext, ContextInfo *toContext)
+{
+
+}
+
+uint32_t renderspu_SystemPostprocessFunctions(SPUNamedFunctionTable *aFunctions, uint32_t cFunctions, uint32_t cTable)
+{
+ return cFunctions;
+}