summaryrefslogtreecommitdiff
path: root/src/VBox/HostServices/SharedOpenGL
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL')
-rw-r--r--src/VBox/HostServices/SharedOpenGL/Makefile.kmk19
-rw-r--r--src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp4
-rw-r--r--src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestApp.cpp2
-rw-r--r--src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp4
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp429
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py144
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py40
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server.h585
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_bufferobject.c14
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c52
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c129
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c264
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py11
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py13
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c59
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py4
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c38
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c55
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c41
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c2411
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c1062
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c591
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp840
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp4787
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py2
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp755
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py31
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_special15
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c26
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c53
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c328
-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
-rw-r--r--src/VBox/HostServices/SharedOpenGL/unpacker/unpack_framebuffer.c2
-rw-r--r--src/VBox/HostServices/SharedOpenGL/unpacker/unpack_misc.c11
-rw-r--r--src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c27
-rw-r--r--src/VBox/HostServices/SharedOpenGL/unpacker/unpack_visibleregion.c2
-rw-r--r--src/VBox/HostServices/SharedOpenGL/unpacker/unpacker_special1
46 files changed, 14268 insertions, 2557 deletions
diff --git a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
index 104aa6fd..971c1c9a 100644
--- a/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
+++ b/src/VBox/HostServices/SharedOpenGL/Makefile.kmk
@@ -131,8 +131,10 @@ VBoxOGLcrserverlib_SOURCES := \
crserverlib/server_getshaders.c \
crserverlib/server_framebuffer.c \
crserverlib/server_glsl.c \
- crserverlib/server_muralfbo.c \
+ crserverlib/server_muralfbo.cpp \
crserverlib/server_texture.c \
+ crserverlib/server_presenter.cpp \
+ crserverlib/server_rpw.cpp \
$(VBOX_PATH_CROGL_GENFILES)/server_dispatch.c \
$(VBOX_PATH_CROGL_GENFILES)/server_retval.c \
$(VBOX_PATH_CROGL_GENFILES)/server_get.c \
@@ -149,6 +151,13 @@ endif
ifdef VBOX_WITH_CRHGSMI
VBoxOGLcrserverlib_DEFS += ifdef VBOX_WITH_CRHGSMI
endif
+ifdef VBOX_WITH_CRDUMPER
+VBoxOGLcrserverlib_DEFS += VBOX_WITH_CRDUMPER
+endif
+ifdef VBOX_WITH_CRSERVER_DUMPER
+VBoxOGLcrserverlib_DEFS += VBOX_WITH_CRSERVER_DUMPER
+endif
+
#
# Generate files for VBoxOGLcrserverlib
@@ -165,7 +174,7 @@ $(VBOX_PATH_CROGL_GENFILES)/server_retval.c: $(addprefix $(PATH_SUB_CURRENT)/crs
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
-$(VBOX_PATH_CROGL_GENFILES)/server_get.c: $(addprefix $(PATH_SUB_CURRENT)/crserverlib/, server_get.py server_special get_components.py) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
+$(VBOX_PATH_CROGL_GENFILES)/server_get.c: $(addprefix $(PATH_SUB_CURRENT)/crserverlib/, server_get.py server_special) $(VBOX_CROGL_API_FILES) | $$(dir $$@)
$(call MSG_GENERATE,python,$@,$<)
$(QUIET)$(call VBOX_CROGL_PYTHON_ENV,$(VBOX_PATH_CROGL_PYTHON_INCLUDE),$@) $(VBOX_BLD_PYTHON) $< $(VBOX_PATH_CROGL_GLAPI) $(<D)
@@ -255,6 +264,12 @@ VBoxOGLrenderspu_OBJCFLAGS.darwin = -Wno-shadow
VBoxOGLrenderspu_SOURCES.darwin = \
render/renderspu_cocoa.c \
render/renderspu_cocoa_helper.m
+ifdef VBOX_WITH_CRHGSMI
+VBoxOGLrenderspu_DEFS += VBOX_WITH_CRHGSMI
+endif
+ifdef VBOX_WITH_VDMA
+VBoxOGLrenderspu_DEFS += VBOX_WITH_VDMA
+endif
VBoxOGLrenderspu_LDFLAGS.darwin += -install_name $(VBOX_DYLD_EXECUTABLE_PATH)/VBoxOGLrenderspu.dylib
VBoxOGLrenderspu_LIBS = \
$(PATH_STAGE_LIB)/VBoxOGLhostspuload$(VBOX_SUFF_LIB) \
diff --git a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
index 2ed4a5a3..228ccaeb 100644
--- a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTest.cpp
@@ -4,7 +4,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;
@@ -31,7 +31,7 @@
bool RTCALL VBoxOglIs3DAccelerationSupported()
{
- if (RTEnvGet("VBOX_CROGL_FORCE_SUPPORTED"))
+ if (RTEnvExist("VBOX_CROGL_FORCE_SUPPORTED"))
{
LogRel(("VBOX_CROGL_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
return true;
diff --git a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestApp.cpp b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestApp.cpp
index a4b3a40f..9d594581 100644
--- a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestApp.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestApp.cpp
@@ -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;
diff --git a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
index 2f50de62..0693ed8a 100644
--- a/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/OpenGLTest/OpenGLTestDarwin.cpp
@@ -5,7 +5,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;
@@ -31,7 +31,7 @@
bool RTCALL VBoxOglIs3DAccelerationSupported()
{
- if (RTEnvGet("VBOX_CROGL_FORCE_SUPPORTED"))
+ if (RTEnvExist("VBOX_CROGL_FORCE_SUPPORTED"))
{
LogRel(("VBOX_CROGL_FORCE_SUPPORTED is specified, skipping 3D test, and treating as supported\n"));
return true;
diff --git a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
index b63f788a..77ddf197 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
+++ b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2006-2008 Oracle Corporation
+ * Copyright (C) 2006-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,50 +18,31 @@
#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
-#ifdef RT_OS_WINDOWS
-# include <iprt/alloc.h>
-# include <iprt/string.h>
-# include <iprt/assert.h>
-# include <iprt/stream.h>
-# include <VBox/vmm/ssm.h>
-# include <VBox/hgcmsvc.h>
-# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
-# include "cr_server.h"
-# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
-# include <VBox/log.h>
-
-# include <VBox/com/com.h>
-# include <VBox/com/string.h>
-# include <VBox/com/array.h>
-# include <VBox/com/Guid.h>
-# include <VBox/com/ErrorInfo.h>
-# include <VBox/com/EventQueue.h>
-# include <VBox/com/VirtualBox.h>
-# include <VBox/com/assert.h>
-
-#else
-# include <VBox/com/VirtualBox.h>
-# include <iprt/assert.h>
-# include <VBox/vmm/ssm.h>
-# include <VBox/hgcmsvc.h>
-# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
-
-# include "cr_server.h"
-# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
-# include <VBox/log.h>
-# include <VBox/com/ErrorInfo.h>
-#endif /* RT_OS_WINDOWS */
+#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
-#include <VBox/com/errorprint.h>
-#include <iprt/thread.h>
+#include <iprt/assert.h>
+#include <iprt/asm.h>
#include <iprt/critsect.h>
+#include <iprt/mem.h>
#include <iprt/semaphore.h>
-#include <iprt/asm.h>
+#include <iprt/stream.h>
+#include <iprt/string.h>
+#include <iprt/thread.h>
+
+#include <VBox/hgcmsvc.h>
+#include <VBox/log.h>
+#include <VBox/com/ErrorInfo.h>
+#include <VBox/com/VirtualBox.h>
+#include <VBox/com/errorprint.h>
+#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
+#include <VBox/vmm/ssm.h>
#include "cr_mem.h"
+#include "cr_server.h"
PVBOXHGCMSVCHELPERS g_pHelpers;
static IConsole* g_pConsole = NULL;
+static uint32_t g_u32ScreenCount = 0;
static PVM g_pVM = NULL;
#ifndef RT_OS_WINDOWS
@@ -244,6 +225,29 @@ static int svcPresentFBOTearDown(void)
return rc;
}
+static DECLCALLBACK(void) svcNotifyEventCB(int32_t screenId, uint32_t uEvent, void*pvData)
+{
+ ComPtr<IDisplay> pDisplay;
+ ComPtr<IFramebuffer> pFramebuffer;
+ LONG xo, yo;
+
+ if (!g_pConsole)
+ {
+ crWarning("Console not defined!");
+ return;
+ }
+
+ CHECK_ERROR2_STMT(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), return);
+
+ CHECK_ERROR2_STMT(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), return);
+
+ if (!pFramebuffer)
+ return;
+
+ pFramebuffer->Notify3DEvent(uEvent, (BYTE*)pvData);
+}
+
+
static DECLCALLBACK(int) svcUnload (void *)
{
int rc = VINF_SUCCESS;
@@ -364,7 +368,7 @@ static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClie
LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32));
/*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/
- /*VboxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
+ /*VBoxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
{
const char *pMatch = &gszVBoxOGLSSMMagic[0];
char current;
@@ -472,7 +476,7 @@ static CRVBOXSVCBUFFER_t* svcGetBuffer(uint32_t iBuffer, uint32_t cbBufferSize)
{
if (pBuffer->uiId == iBuffer)
{
- if (pBuffer->uiSize!=cbBufferSize)
+ if (cbBufferSize && pBuffer->uiSize!=cbBufferSize)
{
static int shown=0;
@@ -892,6 +896,30 @@ static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32
break;
}
+ case SHCRGL_GUEST_FN_GET_CAPS:
+ {
+ Log(("svcCall: SHCRGL_GUEST_FN_GET_CAPS\n"));
+
+ /* Verify parameter count and types. */
+ if (cParms != SHCRGL_CPARMS_GET_CAPS)
+ {
+ rc = VERR_INVALID_PARAMETER;
+ }
+ else
+ if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
+ {
+ rc = VERR_INVALID_PARAMETER;
+ }
+ else
+ {
+ /* Execute the function. */
+ rc = crVBoxServerClientGetCaps(u32ClientID, &paParms[0].u.uint32);
+ AssertRC(rc);
+ }
+
+ break;
+ }
+
default:
{
rc = VERR_NOT_IMPLEMENTED;
@@ -904,10 +932,36 @@ static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32
g_pHelpers->pfnCallComplete (callHandle, rc);
}
+static void crScreenshotHandle(CRVBOXHGCMTAKESCREENSHOT *pScreenshot, uint32_t idScreen, uint64_t u64Now)
+{
+ if (!pScreenshot->pfnScreenshotBegin || pScreenshot->pfnScreenshotBegin(pScreenshot->pvContext, idScreen, u64Now))
+ {
+ CR_SCREENSHOT Screenshot;
+
+ int rc = crServerVBoxScreenshotGet(idScreen, pScreenshot->u32Width, pScreenshot->u32Height, pScreenshot->u32Pitch, pScreenshot->pvBuffer, &Screenshot);
+ if (RT_SUCCESS(rc))
+ {
+ if (pScreenshot->pfnScreenshotPerform)
+ pScreenshot->pfnScreenshotPerform(pScreenshot->pvContext, idScreen,
+ 0, 0, 32,
+ Screenshot.Img.pitch, Screenshot.Img.width, Screenshot.Img.height,
+ (uint8_t*)Screenshot.Img.pvData, u64Now);
+ crServerVBoxScreenshotRelease(&Screenshot);
+ }
+ else
+ {
+ Assert(rc == VERR_INVALID_STATE);
+ }
+
+ if (pScreenshot->pfnScreenshotEnd)
+ pScreenshot->pfnScreenshotEnd(pScreenshot->pvContext, idScreen, u64Now);
+ }
+}
+
/*
* We differentiate between a function handler for the guest and one for the host.
*/
-static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+static int svcHostCallPerform(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
{
int rc = VINF_SUCCESS;
@@ -990,6 +1044,11 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
+ crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+
+ g_pConsole = pConsole;
+ g_u32ScreenCount = monitorCount;
+
rc = crVBoxServerSetScreenCount(monitorCount);
AssertRCReturn(rc, rc);
@@ -1013,7 +1072,7 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
}
}
- g_pConsole = pConsole;
+ crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
rc = VINF_SUCCESS;
}
@@ -1064,16 +1123,15 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
}
if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
- || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */
)
{
rc = VERR_INVALID_PARAMETER;
break;
}
- Assert(sizeof(RTRECT)==4*sizeof(GLint));
+ Assert(sizeof (RTRECT) == 4 * sizeof (GLint));
- rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (GLint*)paParms[0].u.pointer.addr);
+ rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr);
break;
}
case SHCRGL_HOST_FN_SCREEN_CHANGED:
@@ -1105,6 +1163,8 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc);
+ crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+
if (!pFramebuffer)
{
rc = crVBoxServerUnmapScreen(screenId);
@@ -1112,28 +1172,130 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
}
else
{
- CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
+#if 0
+ CHECK_ERROR_RET(pFramebuffer, Lock(), rc);
+#endif
- if (!winId)
- {
- /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
- rc = crVBoxServerUnmapScreen(screenId);
- AssertRCReturn(rc, rc);
- }
- else
- {
- CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
- CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
+ do {
+ /* determine if the framebuffer is functional */
+ rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, NULL);
- rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
- AssertRCReturn(rc, rc);
- }
+ if (rc == S_OK)
+ CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId));
+
+ if (!winId)
+ {
+ /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
+ rc = crVBoxServerUnmapScreen(screenId);
+ AssertRCReturn(rc, rc);
+ }
+ else
+ {
+ CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w));
+ CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h));
+
+ rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
+ AssertRCReturn(rc, rc);
+ }
+ } while (0);
+#if 0
+ CHECK_ERROR_RET(pFramebuffer, Unlock(), rc);
+#endif
}
+ crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
+
rc = VINF_SUCCESS;
}
break;
}
+ case SHCRGL_HOST_FN_TAKE_SCREENSHOT:
+ {
+ if (cParms != 1)
+ {
+ LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
+ {
+ AssertMsgFailed(("invalid param\n"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (!paParms->u.pointer.addr)
+ {
+ AssertMsgFailed(("invalid param\n"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT))
+ {
+ AssertMsgFailed(("invalid param\n"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr;
+ uint64_t u64Now = RTTimeProgramMilliTS();
+
+ if (pScreenshot->u32Screen == CRSCREEN_ALL)
+ {
+ for (uint32_t i = 0; i < g_u32ScreenCount; ++i)
+ {
+ crScreenshotHandle(pScreenshot, i, u64Now);
+ }
+ }
+ else if (pScreenshot->u32Screen < g_u32ScreenCount)
+ {
+ crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now);
+ }
+ else
+ {
+ AssertMsgFailed(("invalid screen id\n"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+ break;
+ }
+ case SHCRGL_HOST_FN_DEV_RESIZE:
+ {
+ Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n"));
+
+ /* Verify parameter count and types. */
+ if (cParms != SHCRGL_CPARMS_DEV_RESIZE)
+ {
+ LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
+ {
+ AssertMsgFailed(("invalid param\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (!paParms->u.pointer.addr)
+ {
+ AssertMsgFailed(("invalid param\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE))
+ {
+ AssertMsgFailed(("invalid param\n"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr;
+
+ rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM);
+ break;
+ }
case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
{
Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
@@ -1162,6 +1324,8 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
break;
}
+ crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+
rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32,
paParms[1].u.uint32, /* x */
paParms[2].u.uint32, /* y */
@@ -1170,9 +1334,52 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
if (!RT_SUCCESS(rc))
{
LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
+ }
+
+ crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
+
+ break;
+ }
+ case SHCRGL_HOST_FN_VIEWPORT_CHANGED2:
+ {
+ Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
+
+ /* Verify parameter count and types. */
+ if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
+ {
+ LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR
+ || !paParms[0].u.pointer.addr
+ || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT))
+ {
+ LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d",
+ paParms[0].type,
+ paParms[0].u.pointer.addr,
+ paParms[0].u.pointer.size));
+ rc = VERR_INVALID_PARAMETER;
break;
}
+ crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
+
+ CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr;
+
+ rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen,
+ pViewportInfo->x, /* x */
+ pViewportInfo->y, /* y */
+ pViewportInfo->width, /* w */
+ pViewportInfo->height /* h */);
+ if (!RT_SUCCESS(rc))
+ {
+ LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
+ }
+
+ crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
+
break;
}
case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
@@ -1207,9 +1414,7 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
}
else /* Execute the function. */
{
- rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
-
- if (RT_SUCCESS(rc))
+ if (pOutputRedirect->H3DORBegin != NULL)
{
CROutputRedirect outputRedirect;
outputRedirect.pvContext = pOutputRedirect->pvContext;
@@ -1220,11 +1425,44 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
rc = crVBoxServerOutputRedirectSet(&outputRedirect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
+ }
+ }
+ else
+ {
+ /* Redirection is disabled. */
+ crVBoxServerSetOffscreenRendering(GL_FALSE);
+ crVBoxServerOutputRedirectSet(NULL);
}
}
}
break;
}
+ case SHCRGL_HOST_FN_WINDOWS_SHOW:
+ {
+ /* Verify parameter count and types. */
+ if (cParms != 1)
+ {
+ WARN(("invalid parameter"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
+ {
+ WARN(("invalid parameter"));
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ rc = crServerVBoxWindowsShow(paParms[0].u.uint32);
+ if (!RT_SUCCESS(rc))
+ WARN(("crServerVBoxWindowsShow failed rc %d", rc));
+
+ break;
+ }
default:
rc = VERR_NOT_IMPLEMENTED;
break;
@@ -1234,6 +1472,73 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa
return rc;
}
+int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl)
+{
+ if ((cbCtl - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM))
+ {
+ WARN(("invalid param size"));
+ return VERR_INVALID_PARAMETER;
+ }
+ uint32_t cParams = (cbCtl - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM);
+ return svcHostCallPerform(pCtl->u32Function, cParams, (VBOXHGCMSVCPARM*)(pCtl + 1));
+}
+
+static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+{
+ switch (u32Function)
+ {
+ case SHCRGL_HOST_FN_CTL:
+ {
+ if (cParms != 1)
+ {
+ WARN(("cParams != 1"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
+ {
+ WARN(("invalid param type"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL))
+ {
+ WARN(("invalid param size"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr;
+ switch (pCtl->enmType)
+ {
+ case VBOXCRCMDCTL_TYPE_HGCM:
+ {
+ return crVBoxServerHostCtl(pCtl, paParms->u.pointer.size);
+ }
+ case VBOXCRCMDCTL_TYPE_DISABLE:
+ {
+ if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL))
+ WARN(("invalid param size"));
+ return crVBoxServerHgcmDisable();
+ }
+ case VBOXCRCMDCTL_TYPE_ENABLE:
+ {
+ if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_ENABLE))
+ WARN(("invalid param size"));
+ VBOXCRCMDCTL_ENABLE *pEnable = (VBOXCRCMDCTL_ENABLE*)pCtl;
+ return crVBoxServerHgcmEnable(pEnable->hRHCmd, pEnable->pfnRHCmd);
+ }
+ default:
+ WARN(("invalid function"));
+ return VERR_INVALID_PARAMETER;
+ }
+ WARN(("should not be here!"));
+ return VERR_INTERNAL_ERROR;
+ }
+ default:
+ return svcHostCallPerform(u32Function, cParms, paParms);
+ }
+}
+
extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
{
int rc = VINF_SUCCESS;
@@ -1272,6 +1577,8 @@ extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *pt
return VERR_NOT_SUPPORTED;
rc = svcPresentFBOInit();
+
+ crServerVBoxSetNotifyEventCB(svcNotifyEventCB);
}
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py
deleted file mode 100644
index e1909d71..00000000
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_components.py
+++ /dev/null
@@ -1,144 +0,0 @@
-# Copyright (c) 2001, Stanford University
-# All rights reserved.
-#
-# See the file LICENSE.txt for information on redistributing this software.
-
-num_components = {
- 'GL_AMBIENT' : 4,
- 'GL_DIFFUSE' : 4,
- 'GL_SPECULAR' : 4,
- 'GL_POSITION' : 4,
- 'GL_SPOT_DIRECTION' : 3,
- 'GL_SPOT_EXPONENT' : 1,
- 'GL_SPOT_CUTOFF' : 1,
- 'GL_CONSTANT_ATTENUATION' : 1,
- 'GL_LINEAR_ATTENUATION' : 1,
- 'GL_QUADRATIC_ATTENUATION' : 1,
- 'GL_EMISSION' : 4,
- 'GL_SHININESS' : 1,
- 'GL_COLOR_INDEXES' : 3,
- 'GL_TEXTURE_ENV_MODE' : 1,
- 'GL_TEXTURE_ENV_COLOR' : 4,
- 'GL_TEXTURE_GEN_MODE' : 1,
- 'GL_OBJECT_PLANE' : 4,
- 'GL_EYE_PLANE' : 4,
- 'GL_TEXTURE_MAG_FILTER' : 1,
- 'GL_TEXTURE_MIN_FILTER' : 1,
- 'GL_TEXTURE_WRAP_S' : 1,
- 'GL_TEXTURE_WRAP_T' : 1,
- 'GL_TEXTURE_BORDER_COLOR' : 4,
- 'GL_TEXTURE_WIDTH': 1,
- 'GL_TEXTURE_HEIGHT': 1,
- 'GL_TEXTURE_DEPTH': 1,
- # 'GL_TEXTURE_INTERNAL_FORMAT': 1, THIS CONFLICTS WITH GL_TEXTURE_COMPONENTS!
- 'GL_TEXTURE_BORDER': 1,
- 'GL_TEXTURE_RED_SIZE': 1,
- 'GL_TEXTURE_GREEN_SIZE': 1,
- 'GL_TEXTURE_BLUE_SIZE': 1,
- 'GL_TEXTURE_ALPHA_SIZE': 1,
- 'GL_TEXTURE_LUMINANCE_SIZE': 1,
- 'GL_TEXTURE_INTENSITY_SIZE': 1,
- 'GL_TEXTURE_COMPONENTS': 1,
- 'GL_TEXTURE_RESIDENT': 1
-}
-
-num_extended_components = {
- 'GL_TEXTURE_MAX_ANISOTROPY_EXT': ( 1, 'CR_EXT_texture_filter_anisotropic' ),
- 'GL_TEXTURE_WRAP_R': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_TEXTURE_PRIORITY': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_TEXTURE_MIN_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_TEXTURE_MAX_LOD': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_TEXTURE_BASE_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_TEXTURE_MAX_LEVEL': ( 1, 'CR_OPENGL_VERSION_1_2'),
- 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_AB_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_CD_DOT_PRODUCT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_MUX_SUM_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_SCALE_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_BIAS_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_AB_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_CD_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_SUM_OUTPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_INPUT_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_MAPPING_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_COMBINER_COMPONENT_USAGE_NV': ( 1, 'CR_NV_register_combiners'),
- 'GL_CONSTANT_COLOR0_NV': ( 4, 'CR_NV_register_combiners'),
- 'GL_CONSTANT_COLOR1_NV': ( 4, 'CR_NV_register_combiners'),
- 'GL_COMBINE_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_COMBINE_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_SOURCE2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND0_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND1_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND2_RGB_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND0_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND1_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_OPERAND2_ALPHA_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_RGB_SCALE_ARB': (1, 'CR_ARB_texture_env_combine'),
- 'GL_ALPHA_SCALE': (1, 'CR_ARB_texture_env_combine'),
- 'GL_DEPTH_TEXTURE_MODE_ARB': (1, 'CR_ARB_depth_texture'),
- 'GL_TEXTURE_DEPTH_SIZE_ARB': (1, 'CR_ARB_depth_texture'),
- 'GL_TEXTURE_COMPARE_MODE_ARB': (1, 'CR_ARB_shadow'),
- 'GL_TEXTURE_COMPARE_FUNC_ARB': (1, 'CR_ARB_shadow'),
- 'GL_TEXTURE_COMPARE_FAIL_VALUE_ARB': (1, 'CR_ARB_shadow_ambient'),
- 'GL_GENERATE_MIPMAP_SGIS': (1, 'CR_SGIS_generate_mipmap'),
- 'GL_TEXTURE_LOD_BIAS_EXT': (1, 'CR_EXT_texture_lod_bias'),
- 'GL_VERTEX_ATTRIB_ARRAY_POINTER_ARB': (1, 'CR_any_vertex_program'),
- 'GL_CURRENT_VERTEX_ATTRIB_ARB': (4, 'CR_any_vertex_program'),
- 'GL_VERTEX_ATTRIB_ARRAY_ENABLED_ARB': (1, 'CR_any_vertex_program'),
- 'GL_VERTEX_ATTRIB_ARRAY_SIZE_ARB': (1, 'CR_any_vertex_program'),
- 'GL_VERTEX_ATTRIB_ARRAY_STRIDE_ARB': (1, 'CR_any_vertex_program'),
- 'GL_VERTEX_ATTRIB_ARRAY_TYPE_ARB': (1, 'CR_any_vertex_program'),
- 'GL_VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB': (1, 'CR_any_vertex_program'),
- 'GL_TRACK_MATRIX_NV': (24, 'CR_any_vertex_program'),
- 'GL_TRACK_MATRIX_TRANSFORM_NV': (24, 'CR_any_vertex_program'),
- 'GL_BUFFER_SIZE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
- 'GL_BUFFER_USAGE_ARB': (1, 'CR_ARB_vertex_buffer_object'),
- 'GL_BUFFER_ACCESS_ARB': (1, 'CR_ARB_vertex_buffer_object'),
- 'GL_BUFFER_MAPPED_ARB': (1, 'CR_ARB_vertex_buffer_object'),
- 'GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING_ARB': (1, 'CR_ARB_vertex_buffer_object'),
- 'GL_QUERY_COUNTER_BITS_ARB': (1, 'CR_ARB_occlusion_query'),
- 'GL_QUERY_RESULT_AVAILABLE_ARB': (1, 'CR_ARB_occlusion_query'),
- 'GL_QUERY_RESULT_ARB': (1, 'CR_ARB_occlusion_query'),
- 'GL_CURRENT_QUERY_ARB': (1, 'CR_ARB_occlusion_query'),
- 'GL_TEXTURE_COMPRESSED_IMAGE_SIZE': (1, 'CR_ARB_texture_compression'),
- 'GL_TEXTURE_COMPRESSED': (1, 'CR_ARB_texture_compression'),
- 'GL_COORD_REPLACE_ARB': (1, 'CR_ARB_point_sprite'),
-}
-
-print """static unsigned int lookupComponents( GLenum pname )
-{
- switch( pname )
- {
-"""
-comps = num_components.keys();
-comps.sort();
-for comp in comps:
- print '\t\t\tcase %s: return %d;' % (comp,num_components[comp])
-
-comps = num_extended_components.keys();
-comps.sort();
-for comp in comps:
- (nc, ifdef) = num_extended_components[comp]
- print '#ifdef %s' % ifdef
- print '\t\t\tcase %s: return %d;' % (comp,nc)
- print '#endif /* %s */' % ifdef
-
-print """
- default:
- crError( "Unknown parameter name in lookupComponents: %d", (int) pname );
- break;
- }
- /* NOTREACHED */
- return 0;
-}
-"""
-
-
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py
index 8475344a..f8d281dc 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/get_sizes.py
@@ -393,8 +393,10 @@ extensions_num_get_values = {
# Point sprite (2.0) #
'GL_POINT_SPRITE': (1, 'CR_OPENGL_VERSION_2_0'),
# Separate stencil (2.0) #
- 'GL_STENCIL_BACK_FAIL': (1, 'CR_OPENGL_VERSION_2_0'),
'GL_STENCIL_BACK_FUNC': (1, 'CR_OPENGL_VERSION_2_0'),
+ 'GL_STENCIL_BACK_REF': (1, 'CR_OPENGL_VERSION_2_0'),
+ 'GL_STENCIL_BACK_VALUE_MASK': (1, 'CR_OPENGL_VERSION_2_0'),
+ 'GL_STENCIL_BACK_FAIL': (1, 'CR_OPENGL_VERSION_2_0'),
'GL_STENCIL_BACK_PASS_DEPTH_FAIL': (1, 'CR_OPENGL_VERSION_2_0'),
'GL_STENCIL_BACK_PASS_DEPTH_PASS': (1, 'CR_OPENGL_VERSION_2_0'),
# Frame buffer object EXT #
@@ -404,22 +406,52 @@ extensions_num_get_values = {
'GL_MAX_RENDERBUFFER_SIZE_EXT': (1, 'CR_EXT_framebuffer_object'),
# ARB_shader_objects
'GL_CURRENT_PROGRAM': (1, 'CR_ARB_shader_objects'),
+ # EXT_framebuffer_blit
+ 'GL_READ_FRAMEBUFFER_BINDING_EXT': (1, 'CR_EXT_framebuffer_blit'),
+ 'GL_DRAW_FRAMEBUFFER_BINDING_EXT': (1, 'CR_EXT_framebuffer_blit'),
+ # EXT_stencil_two_side
+ 'GL_ACTIVE_STENCIL_FACE_EXT': (1, 'CR_EXT_stencil_two_side'),
}
get_keys = num_get_values.keys() + extensions_num_get_values.keys()
get_keys.sort()
+max_keyvalues = 0
-print "struct nv_struct { GLenum pname; unsigned int num_values; } num_values_array[] = {"
+print """
+static struct nv_struct { GLenum pname; unsigned int num_values;
+#ifdef VBOX_WITH_CRDUMPER
+const char* pszName;
+#endif
+} num_values_array[] = {
+"""
for key in get_keys:
try:
- print '\t{ %s, %d },' % (key, num_get_values[key])
+ keyvalues = num_get_values[key]
+ if max_keyvalues < keyvalues:
+ max_keyvalues = keyvalues
+ print """
+ \t{ %s, %d
+#ifdef VBOX_WITH_CRDUMPER
+ , "%s"
+#endif
+ },
+ """ % (key, keyvalues, key)
except KeyError:
(nv, ifdef) = extensions_num_get_values[key]
+ if max_keyvalues < nv:
+ max_keyvalues = nv
print '#ifdef %s' % ifdef
- print '\t{ %s, %d },' % (key, nv)
+ print """
+ \t{ %s, %d
+ #ifdef VBOX_WITH_CRDUMPER
+ , "%s"
+ #endif
+ },
+ """ % (key, nv, key)
print '#endif /* %s */' % ifdef
print "\t{ 0, 0 }"
print "};"
+print "#define CR_MAX_GET_VALUES %d" % max_keyvalues
print """
static unsigned int __numValues( GLenum pname )
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
index 4e14a86e..677bcf0e 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server.h
@@ -14,10 +14,16 @@
#include "state/cr_currentpointers.h"
#include "cr_server.h"
+#include <cr_htable.h>
+#include <cr_compositor.h>
#ifdef VBOX_WITH_CRHGSMI
# include <VBox/VBoxVideo.h>
+#include <iprt/cdefs.h>
+
+RT_C_DECLS_BEGIN
+
extern uint8_t* g_pvVRamBase;
extern uint32_t g_cbVRam;
extern HCRHGSMICMDCOMPLETION g_hCrHgsmiCompletion;
@@ -37,9 +43,10 @@ DECLINLINE(void) crServerCrHgsmiCmdComplete(struct VBOXVDMACMD_CHROMIUM_CMD *pCm
}
#define VBOXCRHGSMI_CMD_COMPLETE(_pData, _rc) do { \
+ Assert(CRVBOXHGSMI_CMDDATA_IS_HGSMICMD(_pData)); \
CRVBOXHGSMI_CMDDATA_ASSERT_ISSET(_pData); \
CRVBOXHGSMI_CMDDATA_RC(_pData, _rc); \
- crServerCrHgsmiCmdComplete((_pData)->pCmd, VINF_SUCCESS); \
+ crServerCrHgsmiCmdComplete((_pData)->pHgsmiCmd, VINF_SUCCESS); \
} while (0)
#define VBOXCRHGSMI_CMD_CHECK_COMPLETE(_pData, _rc) do { \
@@ -108,8 +115,12 @@ GLboolean crServerClientInBeginEnd(const CRClient *client);
GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID);
GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID);
-
-void crServerCreateInfoDeleteCB(void *data);
+GLint crServerMuralInit(CRMuralInfo *mural, GLboolean fGuestWindow, GLint visBits, GLint preloadWinID);
+void crServerMuralTerm(CRMuralInfo *mural);
+GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height);
+void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y);
+void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *pRects );
+void crServerMuralShow( CRMuralInfo *mural, GLint state );
GLint crServerGenerateID(GLint *pCounter);
@@ -117,15 +128,577 @@ GLint crServerSPUWindowID(GLint serverWindow);
GLuint crServerTranslateProgramID(GLuint id);
-void crServerSetupOutputRedirect(CRMuralInfo *mural);
+CRMuralInfo * crServerGetDummyMural(GLint visualBits);
+
void crServerCheckMuralGeometry(CRMuralInfo *mural);
+void crServerCheckAllMuralGeometry(CRMuralInfo *pMI);
GLboolean crServerSupportRedirMuralFBO(void);
-void crServerRedirMuralFBO(CRMuralInfo *mural, GLboolean redir);
-void crServerCreateMuralFBO(CRMuralInfo *mural);
+
+void crVBoxServerMuralFbResizeBegin(HCR_FRAMEBUFFER hFb);
+void crVBoxServerMuralFbResizeEnd(HCR_FRAMEBUFFER hFb);
+
+void crVBoxServerNotifyEvent(int32_t idScreen, uint32_t uEvent, void*pvData);
+
+void crServerRedirMuralFbClear(CRMuralInfo *mural);
+
+void crServerWindowReparent(CRMuralInfo *pMural);
+
+void crServerRedirMuralFBO(CRMuralInfo *mural, bool fEnabled);
void crServerDeleteMuralFBO(CRMuralInfo *mural);
void crServerPresentFBO(CRMuralInfo *mural);
GLboolean crServerIsRedirectedToFBO();
+GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer);
+void crServerMuralFBOSwapBuffers(CRMuralInfo *mural);
+
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled();
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb);
+HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized();
+HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb);
+
+int CrFbRegionsClear(HCR_FRAMEBUFFER hFb);
+
+
+#define CR_SERVER_FBO_BB_IDX(_mural) ((_mural)->iBbBuffer)
+#define CR_SERVER_FBO_FB_IDX(_mural) (((_mural)->iBbBuffer + 1) % ((_mural)->cBuffers))
+/* returns a valid index to be used for negative _idx, i.e. for GL_NONE cases */
+//#define CR_SERVER_FBO_ADJUST_IDX(_mural, _idx) ((_idx) >= 0 ? (_idx) : CR_SERVER_FBO_BB_IDX(_mural))
+/* just a helper that uses CR_SERVER_FBO_ADJUST_IDX for getting mural's FBO id for buffer index*/
+//#define CR_SERVER_FBO_FOR_IDX(_mural, _idx) ((_mural)->aidFBOs[CR_SERVER_FBO_ADJUST_IDX((_mural), (_idx))])
+//#define CR_SERVER_FBO_TEX_FOR_IDX(_mural, _idx) ((_mural)->aidColorTexs[CR_SERVER_FBO_ADJUST_IDX((_mural), (_idx))])
+#define CR_SERVER_FBO_FOR_IDX(_mural, _idx) ((_idx) >= 0 ? (_mural)->aidFBOs[(_idx)] : 0)
+#define CR_SERVER_FBO_TEX_FOR_IDX(_mural, _idx) ((_idx) >= 0 ? (_mural)->aidColorTexs[(_idx)] : 0)
int32_t crVBoxServerInternalClientRead(CRClient *pClient, uint8_t *pBuffer, uint32_t *pcbBuffer);
+void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo );
+
+PCR_BLITTER crServerVBoxBlitterGet();
+PCR_BLITTER crServerVBoxBlitterGetInitialized();
+
+DECLINLINE(void) crServerVBoxBlitterWinInit(CR_BLITTER_WINDOW *win, CRMuralInfo *mural)
+{
+ win->Base.id = mural->spuWindow;
+ win->Base.visualBits = mural->CreateInfo.realVisualBits;
+ win->width = mural->width;
+ win->height = mural->height;
+}
+
+DECLINLINE(void) crServerVBoxBlitterCtxInit(CR_BLITTER_CONTEXT *ctx, CRContextInfo *ctxInfo)
+{
+ ctx->Base.id = ctxInfo->SpuContext;
+ if (ctx->Base.id < 0)
+ ctx->Base.id = cr_server.MainContextInfo.SpuContext;
+ ctx->Base.visualBits = cr_server.curClient->currentCtxInfo->CreateInfo.realVisualBits;
+}
+
+/* display worker thread.
+ * see comments for CR_SERVER_RPW struct definition in cr_server.h */
+DECLINLINE(void) crServerXchgI8(int8_t *pu8Val1, int8_t *pu8Val2)
+{
+ int8_t tmp;
+ tmp = *pu8Val1;
+ *pu8Val1 = *pu8Val2;
+ *pu8Val2 = tmp;
+}
+
+#ifdef DEBUG
+# define CR_GLERR_CHECK(_op) do { \
+ GLenum status; \
+ while ((status = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR) {/*Assert(0);*/} \
+ _op \
+ while ((status = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR) {Assert(0);} \
+ } while (0)
+#else
+# define CR_GLERR_CHECK(_op) do { \
+ _op \
+ } while (0)
+#endif
+
+#ifdef DEBUG_misha
+# define CR_SERVER_RPW_DEBUG
+#endif
+/* *
+ * _name : Draw, Submitted, Worker, Gpu
+ */
+
+#ifdef CR_SERVER_RPW_DEBUG
+# define crServerRpwEntryDbgVerify(_pE) crServerRpwEntryDbgDoVerify(_pE)
+#else
+# define crServerRpwEntryDbgVerify(_pE) do {} while (0)
+#endif
+
+
+#define CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _name) ((_pEntry)->iTex##_name > 0)
+
+#define CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(_pEntry, _name) do { \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _name)); \
+ (_pEntry)->iTex##_name = -(_pEntry)->iTex##_name; \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ } while (0)
+
+#define CR_SERVER_RPW_ENTRY_TEX_PROMOTE(_pEntry, _fromName, _toName) do { \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
+ Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
+ crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ } while (0)
+
+#define CR_SERVER_RPW_ENTRY_TEX_XCHG_VALID(_pEntry, _fromName, _toName) do { \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
+ crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ } while (0)
+
+
+#define CR_SERVER_RPW_ENTRY_TEX_PROMOTE_KEEPVALID(_pEntry, _fromName, _toName) do { \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
+ Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
+ crServerXchgI8(&(_pEntry)->iTex##_fromName, &(_pEntry)->iTex##_toName); \
+ (_pEntry)->iTex##_fromName = -(_pEntry)->iTex##_fromName; \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _fromName)); \
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(_pEntry, _toName)); \
+ crServerRpwEntryDbgVerify(_pEntry); \
+ } while (0)
+
+#define CR_SERVER_RPW_ENTRY_TEX(_pEntry, _name) ((_pEntry)->aidWorkerTexs[(_pEntry)->iTex##_name - 1])
+
+#define CR_SERVER_RPW_ENTRY_PBO_NEXT_ID(_i) (((_i) + 1) % 2)
+#define CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(_pEntry) ((_pEntry)->iCurPBO >= 0)
+#define CR_SERVER_RPW_ENTRY_PBO_CUR(_pEntry) ((_pEntry)->aidPBOs[(_pEntry)->iCurPBO])
+#define CR_SERVER_RPW_ENTRY_PBO_COMPLETED(_pEntry) ((_pEntry)->aidPBOs[CR_SERVER_RPW_ENTRY_PBO_NEXT_ID((_pEntry)->iCurPBO)])
+#define CR_SERVER_RPW_ENTRY_PBO_FLIP(_pEntry) do { \
+ (_pEntry)->iCurPBO = CR_SERVER_RPW_ENTRY_PBO_NEXT_ID((_pEntry)->iCurPBO); \
+ } while (0)
+
+#ifdef CR_SERVER_RPW_DEBUG
+DECLINLINE(void) crServerRpwEntryDbgDoVerify(CR_SERVER_RPW_ENTRY *pEntry)
+{
+ int tstMask = 0;
+ int8_t iVal;
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw));
+
+#define CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(_v) do { \
+ iVal = RT_ABS(_v); \
+ Assert(iVal > 0); \
+ Assert(iVal < 5); \
+ Assert(!(tstMask & (1 << iVal))); \
+ tstMask |= (1 << iVal); \
+ } while (0)
+
+ CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexDraw);
+ CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexSubmitted);
+ CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexWorker);
+ CR_VERVER_RPW_ENTRY_DBG_CHECKVAL(pEntry->iTexGpu);
+ Assert(tstMask == 0x1E);
+}
+#endif
+
+DECLINLINE(bool) crServerRpwIsInitialized(const CR_SERVER_RPW *pWorker)
+{
+ return !!pWorker->ctxId;
+}
+int crServerRpwInit(CR_SERVER_RPW *pWorker);
+int crServerRpwTerm(CR_SERVER_RPW *pWorker);
+DECLINLINE(bool) crServerRpwEntryIsInitialized(const CR_SERVER_RPW_ENTRY *pEntry)
+{
+ return !!pEntry->pfnData;
+}
+int crServerRpwEntryInit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height, PFNCR_SERVER_RPW_DATA pfnData);
+int crServerRpwEntryCleanup(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
+int crServerRpwEntryResize(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height);
+int crServerRpwEntrySubmit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
+int crServerRpwEntryWaitComplete(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
+int crServerRpwEntryCancel(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry);
+DECLINLINE(void) crServerRpwEntryDrawSettingsToTex(const CR_SERVER_RPW_ENTRY *pEntry, VBOXVR_TEXTURE *pTex)
+{
+ pTex->width = pEntry->Size.cx;
+ pTex->height = pEntry->Size.cy;
+ pTex->target = GL_TEXTURE_2D;
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw));
+ pTex->hwid = CR_SERVER_RPW_ENTRY_TEX(pEntry, Draw);
+}
+/**/
+
+typedef struct CR_SERVER_CTX_SWITCH
+{
+ GLuint idDrawFBO, idReadFBO;
+ CRContext *pNewCtx;
+ CRContext *pOldCtx;
+} CR_SERVER_CTX_SWITCH;
+
+DECLINLINE(void) crServerCtxSwitchPrepare(CR_SERVER_CTX_SWITCH *pData, CRContext *pNewCtx)
+{
+ CRMuralInfo *pCurrentMural = cr_server.currentMural;
+ CRContextInfo *pCurCtxInfo = cr_server.currentCtxInfo;
+ GLuint idDrawFBO, idReadFBO;
+ CRContext *pCurCtx = pCurCtxInfo ? pCurCtxInfo->pContext : NULL;
+
+ CRASSERT(pCurCtx == crStateGetCurrent());
+
+ if (pCurrentMural)
+ {
+ idDrawFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurDrawBuffer);
+ idReadFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurReadBuffer);
+ }
+ else
+ {
+ idDrawFBO = 0;
+ idReadFBO = 0;
+ }
+
+ crStateSwitchPrepare(pNewCtx, pCurCtx, idDrawFBO, idReadFBO);
+
+ pData->idDrawFBO = idDrawFBO;
+ pData->idReadFBO = idReadFBO;
+ pData->pNewCtx = pNewCtx;
+ pData->pOldCtx = pCurCtx;
+}
+
+DECLINLINE(void) crServerCtxSwitchPostprocess(CR_SERVER_CTX_SWITCH *pData)
+{
+ crStateSwitchPostprocess(pData->pOldCtx, pData->pNewCtx, pData->idDrawFBO, pData->idReadFBO);
+}
+
+void crServerInitTmpCtxDispatch();
+
+int crServerVBoxParseNumerics(const char *pszStr, const int defaultVal);
+
+typedef struct CR_FBMAP
+{
+ uint8_t Map[(CR_MAX_GUEST_MONITORS+7)/8];
+} CR_FBMAP;
+
+DECLINLINE(void) CrFBmInit(CR_FBMAP *pMap)
+{
+ memset(pMap, 0, sizeof (*pMap));
+}
+
+DECLINLINE(bool) CrFBmIsSet(CR_FBMAP *pMap, uint32_t i)
+{
+ return ASMBitTest(&pMap->Map, i);
+}
+
+DECLINLINE(void) CrFBmSet(CR_FBMAP *pMap, uint32_t i)
+{
+ ASMBitSet(&pMap->Map, i);
+}
+
+DECLINLINE(void) CrFBmSetAtomic(CR_FBMAP *pMap, uint32_t i)
+{
+ ASMAtomicBitSet(&pMap->Map, i);
+}
+
+DECLINLINE(void) CrFBmClear(CR_FBMAP *pMap, uint32_t i)
+{
+ ASMBitClear(&pMap->Map, i);
+}
+
+/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
+int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap);
+/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
+void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap);
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled();
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb);
+HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen);
+int CrPMgrModeVrdp(bool fEnable);
+int CrPMgrModeRootVr(bool fEnable);
+int CrPMgrModeWinVisible(bool fEnable);
+int CrPMgrRootVrUpdate();
+int CrPMgrViewportUpdate(uint32_t idScreen);
+int CrPMgrScreenChanged(uint32_t idScreen);
+int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb);
+int CrPMgrSaveState(PSSMHANDLE pSSM);
+int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version);
+HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen);
+/*cleanup stuff*/
+
+int CrPMgrInit();
+void CrPMgrTerm();
+
+typedef DECLCALLBACKPTR(bool, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB)(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
+
+bool CrFbHas3DData(HCR_FRAMEBUFFER hFb);
+void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext);
+int CrFbResize(HCR_FRAMEBUFFER hFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM);
+int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pPrects, CR_BLITTER_IMG *pImg);
+bool CrFbIsEnabled(HCR_FRAMEBUFFER hFb);
+int CrFbEntryCreateForTexId(HCR_FRAMEBUFFER hFb, GLuint idTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry);
+int CrFbEntryCreateForTexData(HCR_FRAMEBUFFER hFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry);
+void CrFbEntryAddRef(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+void CrFbEntryRelease(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb);
+void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb);
+const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(HCR_FRAMEBUFFER hFb);
+const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry);
+
+/* start doing modifications to the framebuffer */
+int CrFbUpdateBegin(HCR_FRAMEBUFFER hFb);
+/*below commands can only be used in Framebuffer update mode, i.e. after the CrFbUpdateBegin succeeded */
+int CrFbEntryRegions(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry);
+
+/* complete doing modifications to the framebuffer */
+void CrFbUpdateEnd(HCR_FRAMEBUFFER hFb);
+
+int CrFbEntryRegionsAdd(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated);
+int CrFbEntryRegionsSet(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated);
+
+int CrFbEntryTexDataUpdate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex);
+
+CRHTABLE_HANDLE CrFbDDataAllocSlot(HCR_FRAMEBUFFER hFb);
+
+typedef DECLCALLBACKPTR(void, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB)(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext);
+
+void CrFbDDataReleaseSlot(HCR_FRAMEBUFFER hFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext);
+int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData);
+void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot);
+void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot);
+
+CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex);
+void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased);
+
+int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd);
+
+//#define VBOX_WITH_CRSERVER_DUMPER
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+void crServerDumpCheckTerm();
+int crServerDumpCheckInit();
+void crServerDumpBuffer(int idx);
+void crServerDumpTextures();
+void crServerDumpTexture(const VBOXVR_TEXTURE *pTex);
+void crServerDumpShader(GLint id);
+void crServerDumpProgram(GLint id);
+void crServerDumpCurrentProgram();
+void crServerDumpRecompileDumpCurrentProgram();
+void crServerRecompileCurrentProgram();
+void crServerDumpCurrentProgramUniforms();
+void crServerDumpCurrentProgramAttribs();
+void crServerDumpFramesCheck();
+void crServerDumpState();
+void crServerDumpDrawel(const char*pszFormat, ...);
+void crServerDumpDrawelv(GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal);
+
+extern int64_t g_CrDbgDumpPid;
+extern unsigned long g_CrDbgDumpEnabled;
+extern unsigned long g_CrDbgDumpDraw;
+extern unsigned long g_CrDbgDumpDrawFramesSettings;
+extern unsigned long g_CrDbgDumpDrawFramesAppliedSettings;
+extern unsigned long g_CrDbgDumpDrawFramesCount;
+
+extern uint32_t g_CrDbgDumpVertattrFixupOn;
+
+bool crServerDumpFilterDmp(unsigned long event, CR_DUMPER *pDumper);
+bool crServerDumpFilterOpEnter(unsigned long event, CR_DUMPER *pDumper);
+void crServerDumpFilterOpLeave(unsigned long event, CR_DUMPER *pDumper);
+
+//#define CR_SERVER_DUMP_MASK_OP 0x0000fffc
+//#define CR_SERVER_DUMP_OFF_OP 2
+//
+//#define CR_SERVER_DUMP_MASK_DIR 0x00000003
+//#define CR_SERVER_DUMP_OFF_DIR 0
+//
+//#define CR_SERVER_DUMP_MASK_DMP 0xffff0000
+//#define CR_SERVER_DUMP_OFF_DMP 16
+//
+//#define CR_SERVER_DUMP_MAKE_OP(_v) (1 << ((_v) + CR_SERVER_DUMP_OFF_OP))
+//#define CR_SERVER_DUMP_MAKE_DIR(_v) (1 << ((_v) + CR_SERVER_DUMP_OFF_DIR))
+//#define CR_SERVER_DUMP_MAKE_DMP(_v) (1 << ((_v) + CR_SERVER_DUMP_OFF_DMP))
+//
+//#define CR_SERVER_DUMP_GET_OP(_v) ((_v) & CR_SERVER_DUMP_MASK_OP)
+//#define CR_SERVER_DUMP_GET_DMP(_v) ((_v) & CR_SERVER_DUMP_MASK_DMP)
+//#define CR_SERVER_DUMP_GET_DIR(_v) ((_v) & CR_SERVER_DUMP_MASK_DIR)
+//
+//#define CR_SERVER_DUMP_ISANY_OP(_v1, _v2) (!!(CR_SERVER_DUMP_GET_OP(_v1) & CR_SERVER_DUMP_GET_OP(_v2)))
+//#define CR_SERVER_DUMP_ISANY_DIR(_v1, _v2) (!!(CR_SERVER_DUMP_GET_DIR(_v1) & CR_SERVER_DUMP_GET_DIR(_v2)))
+//#define CR_SERVER_DUMP_ISANY_DMP(_v1, _v2) (!!(CR_SERVER_DUMP_GET_DMP(_v1) & CR_SERVER_DUMP_GET_DMP(_v2)))
+//
+//#define CR_SERVER_DUMP_ISANY_OP(_v1, _v2) ((CR_SERVER_DUMP_GET_OP(_v1) & CR_SERVER_DUMP_GET_OP(_v2)) == CR_SERVER_DUMP_GET_OP(_v2))
+//#define CR_SERVER_DUMP_ISANY_DIR(_v1, _v2) ((CR_SERVER_DUMP_GET_DIR(_v1) & CR_SERVER_DUMP_GET_DIR(_v2)) == CR_SERVER_DUMP_GET_DIR(_v2))
+//#define CR_SERVER_DUMP_ISANY_DMP(_v1, _v2) ((CR_SERVER_DUMP_GET_DMP(_v1) & CR_SERVER_DUMP_GET_DMP(_v2)) == CR_SERVER_DUMP_GET_DMP(_v2))
+//
+//#define CR_SERVER_DUMP_F_DIR_ENTER CR_SERVER_DUMP_MAKE_DIR(0)
+//#define CR_SERVER_DUMP_F_DIR_LEAVE CR_SERVER_DUMP_MAKE_DIR(1)
+//
+//#define CR_SERVER_DUMP_F_OP_DRAW CR_SERVER_DUMP_MAKE_OP(0)
+//#define CR_SERVER_DUMP_F_OP_SWAPBUFFERS CR_SERVER_DUMP_MAKE_OP(1)
+//#define CR_SERVER_DUMP_F_OP_LINK_PROGRAM CR_SERVER_DUMP_MAKE_OP(2)
+//#define CR_SERVER_DUMP_F_OP_COMPILE_PROGRAM CR_SERVER_DUMP_MAKE_OP(3)
+//
+//#define CR_SERVER_DUMP_F_DMP_BUFF CR_SERVER_DUMP_MAKE_DMP(0)
+//#define CR_SERVER_DUMP_F_DMP_TEX CR_SERVER_DUMP_MAKE_DMP(0)
+//#define CR_SERVER_DUMP_F_DMP_PROGRAM CR_SERVER_DUMP_MAKE_DMP(0)
+//#define CR_SERVER_DUMP_F_DMP_PROGRAM_UNIFORMS CR_SERVER_DUMP_MAKE_DMP(0)
+//#define CR_SERVER_DUMP_F_DMP_STATE CR_SERVER_DUMP_MAKE_DMP(0)
+//
+//#define CR_SERVER_DUMP_GET_OP(_v) ((_v) & CR_SERVER_DUMP_MASK_OP)
+//#define CR_SERVER_DUMP_GET_DMP(_v) ((_v) & CR_SERVER_DUMP_MASK_DMP)
+//#define CR_SERVER_DUMP_GET_DIR(_v) ((_v) & CR_SERVER_DUMP_MASK_DIR)
+
+#define CR_SERVER_DUMP_F_DRAW_BUFF_ENTER 0x00000001
+#define CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE 0x00000002
+#define CR_SERVER_DUMP_F_DRAW_STATE_ENTER 0x00000004
+#define CR_SERVER_DUMP_F_DRAW_STATE_LEAVE 0x00000008
+#define CR_SERVER_DUMP_F_DRAW_TEX_ENTER 0x00000010
+#define CR_SERVER_DUMP_F_DRAW_TEX_LEAVE 0x00000020
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER 0x00000040
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_LEAVE 0x00000080
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER 0x00000100
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_LEAVE 0x00000200
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER 0x00000400
+#define CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_LEAVE 0x00000800
+
+#define CR_SERVER_DUMP_F_DRAW_ENTER_ALL (CR_SERVER_DUMP_F_DRAW_BUFF_ENTER \
+ | CR_SERVER_DUMP_F_DRAW_TEX_ENTER \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER \
+ | CR_SERVER_DUMP_F_DRAW_STATE_ENTER \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER)
+
+#define CR_SERVER_DUMP_F_DRAW_LEAVE_ALL (CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE \
+ | CR_SERVER_DUMP_F_DRAW_TEX_LEAVE \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_LEAVE \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_LEAVE \
+ | CR_SERVER_DUMP_F_DRAW_STATE_LEAVE \
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_LEAVE)
+
+#define CR_SERVER_DUMP_F_DRAW_ALL (CR_SERVER_DUMP_F_DRAW_ENTER_ALL | CR_SERVER_DUMP_F_DRAW_LEAVE_ALL)
+
+#define CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER 0x00010000
+#define CR_SERVER_DUMP_F_SWAPBUFFERS_LEAVE 0x00020000
+#define CR_SERVER_DUMP_F_TEXPRESENT 0x00040000
+#define CR_SERVER_DUMP_F_DRAWEL 0x00100000
+#define CR_SERVER_DUMP_F_COMPILE_SHADER 0x01000000
+#define CR_SERVER_DUMP_F_SHADER_SOURCE 0x02000000
+#define CR_SERVER_DUMP_F_LINK_PROGRAM 0x04000000
+
+
+#define CR_SERVER_DUMP_DEFAULT_FILTER_OP(_ev) ((((_ev) & g_CrDbgDumpDraw) != 0) \
+ || ((_ev) == CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER && g_CrDbgDumpDrawFramesCount))
+
+#define CR_SERVER_DUMP_DEFAULT_FILTER_DMP(_ev) (((_ev) & g_CrDbgDumpDraw) != 0)
+
+#define CR_SERVER_DUMP_FILTER_OP(_ev, _pDumper) (g_CrDbgDumpEnabled \
+ && (!g_CrDbgDumpPid \
+ || (g_CrDbgDumpPid > 0 && ((uint64_t)g_CrDbgDumpPid) == cr_server.curClient->pid) \
+ || (g_CrDbgDumpPid < 0 && ((uint64_t)(-g_CrDbgDumpPid)) != cr_server.curClient->pid)) \
+ && crServerDumpFilterOpEnter((_ev), (_pDumper)))
+#define CR_SERVER_DUMP_FILTER_DMP(_ev, _pDumper) (crServerDumpFilterDmp((_ev), (_pDumper)))
+
+#define CR_SERVER_DUMP_DRAW_ENTER() do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_DRAW_ENTER_ALL, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==ENTER[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_STATE_ENTER, cr_server.Recorder.pDumper)) { crServerDumpState(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgram(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgramUniforms(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgramAttribs(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_TEX_ENTER, cr_server.Recorder.pDumper)) { crServerDumpTextures(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_BUFF_ENTER, cr_server.Recorder.pDumper)) { crServerDumpBuffer(-1); } \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done ENTER[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_DRAW_ENTER_ALL, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_DRAW_LEAVE() do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_DRAW_LEAVE_ALL, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==LEAVE[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_TEX_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpTextures(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpBuffer(-1); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgramUniforms(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgramAttribs(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_PROGRAM_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpCurrentProgram(); } \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_DRAW_STATE_LEAVE, cr_server.Recorder.pDumper)) { crServerDumpState(); } \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done LEAVE[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_DRAW_LEAVE_ALL, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_COMPILE_SHADER(_id) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_COMPILE_SHADER, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpShader((_id)); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_COMPILE_SHADER, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_SHADER_SOURCE(_id) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_SHADER_SOURCE, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpShader((_id)); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_SHADER_SOURCE, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_LINK_PROGRAM(_id) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_LINK_PROGRAM, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpProgram((_id)); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_LINK_PROGRAM, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_SWAPBUFFERS_ENTER() do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==ENTER[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ if (CR_SERVER_DUMP_FILTER_DMP(CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER, cr_server.Recorder.pDumper)) { crServerDumpBuffer(CR_SERVER_FBO_BB_IDX(cr_server.currentMural)); } \
+ if (g_CrDbgDumpDrawFramesCount) { crServerDumpFramesCheck(); } \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done ENTER[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_TEXPRESENT(_pTex) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_TEXPRESENT, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpTexture((_pTex)); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_TEXPRESENT, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_SWAPBUFFERS_LEAVE() do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_SWAPBUFFERS_LEAVE, cr_server.Recorder.pDumper)) break; \
+ crDmpStrF(cr_server.Recorder.pDumper, "==LEAVE[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done LEAVE[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_SWAPBUFFERS_LEAVE, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_DRAWEL_F(_msg) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_DRAWEL, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpDrawel _msg; \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_DRAWEL, cr_server.Recorder.pDumper); \
+ } while (0)
+
+#define CR_SERVER_DUMP_DRAWEL_V(_index, _pszElFormat, _cbEl, _pvVal, _cVal) do { \
+ if (!CR_SERVER_DUMP_FILTER_OP(CR_SERVER_DUMP_F_DRAWEL, cr_server.Recorder.pDumper)) break; \
+ crServerDumpCheckInit(); \
+ crDmpStrF(cr_server.Recorder.pDumper, "==[%d] %s==", (uint32_t)cr_server.curClient->pid, __FUNCTION__); \
+ crServerDumpDrawelv((_index), (_pszElFormat), (_cbEl), (_pvVal), (_cVal)); \
+ crServerDumpFilterOpLeave(CR_SERVER_DUMP_F_DRAWEL, cr_server.Recorder.pDumper); \
+ } while (0)
+#else /* if !defined VBOX_WITH_CRSERVER_DUMPER */
+#define CR_SERVER_DUMP_DRAW_ENTER() do {} while (0)
+#define CR_SERVER_DUMP_DRAW_LEAVE() do {} while (0)
+#define CR_SERVER_DUMP_COMPILE_SHADER(_id) do {} while (0)
+#define CR_SERVER_DUMP_LINK_PROGRAM(_id) do {} while (0)
+#define CR_SERVER_DUMP_TEXPRESENT(_pTex) do {} while (0)
+#define CR_SERVER_DUMP_SWAPBUFFERS_ENTER() do {} while (0)
+#define CR_SERVER_DUMP_SWAPBUFFERS_LEAVE() do {} while (0)
+#define CR_SERVER_DUMP_SHADER_SOURCE(_id) do {} while (0)
+#define CR_SERVER_DUMP_DRAWEL_F(_msg) do {} while (0)
+#define CR_SERVER_DUMP_DRAWEL_V(_index, _pszElFormat, _cbEl, _pvVal, _cVal) do {} while (0)
+#endif /* !VBOX_WITH_CRSERVER_DUMPER */
+
+RT_C_DECLS_END
+
#endif /* CR_SERVER_H */
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_bufferobject.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_bufferobject.c
index 9210d83b..e3c0100c 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_bufferobject.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_bufferobject.c
@@ -27,11 +27,18 @@ crServerDispatchGenBuffersARB(GLsizei n, GLuint *buffers)
{
GLuint *local_buffers = (GLuint *) crAlloc( n * sizeof(*local_buffers) );
(void) buffers;
- cr_server.head_spu->dispatch_table.GenBuffersARB( n, local_buffers );
+
+ crStateGenBuffersARB(n, local_buffers);
+
crServerReturnValue( local_buffers, n * sizeof(*local_buffers) );
crFree( local_buffers );
}
+void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteBuffersARB( GLsizei n, const GLuint * buffer )
+{
+ crStateDeleteBuffersARB( n, buffer );
+}
+
void SERVER_DISPATCH_APIENTRY
crServerDispatchGetBufferPointervARB(GLenum target, GLenum pname, GLvoid **params)
{
@@ -69,8 +76,9 @@ crServerDispatchBindBufferARB(GLenum target, GLuint buffer)
GLboolean SERVER_DISPATCH_APIENTRY
crServerDispatchIsBufferARB(GLuint buffer)
{
- GLboolean retval;
- retval = cr_server.head_spu->dispatch_table.IsBufferARB(crStateGetBufferHWID(buffer));
+ /* since GenBuffersARB issued to host ogl only on bind + some other ops, the host drivers may not know about them
+ * so use state data*/
+ GLboolean retval = crStateIsBufferARB(buffer);
crServerReturnValue( &retval, sizeof(retval) );
return retval; /* WILL PROBABLY BE IGNORED */
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
index a6e6103f..64ef9462 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_clear.c
@@ -427,18 +427,25 @@ crServerDispatchSwapBuffers( GLint window, GLint flags )
ctx = crStateGetCurrent();
+ CRASSERT(cr_server.curClient && cr_server.curClient->currentMural == mural);
+
if (ctx->framebufferobject.drawFB
|| (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT))
- cr_server.curClient->currentMural->bFbDraw = GL_FALSE;
+ mural->bFbDraw = GL_FALSE;
+
+ CR_SERVER_DUMP_SWAPBUFFERS_ENTER();
if (crServerIsRedirectedToFBO())
{
+ crServerMuralFBOSwapBuffers(mural);
crServerPresentFBO(mural);
}
else
{
cr_server.head_spu->dispatch_table.SwapBuffers( mural->spuWindow, flags );
}
+
+ CR_SERVER_DUMP_SWAPBUFFERS_LEAVE();
}
void SERVER_DISPATCH_APIENTRY
@@ -447,20 +454,19 @@ crServerDispatchFlush(void)
CRContext *ctx = crStateGetCurrent();
cr_server.head_spu->dispatch_table.Flush();
- if (!cr_server.curClient->currentMural) /* <- on window destroy this will be zero */
- return;
-
- if (cr_server.curClient->currentMural->bFbDraw && crServerIsRedirectedToFBO())
+ if (cr_server.curClient && cr_server.curClient->currentMural)
{
-#ifdef DEBUG_misha
- CRASSERT(0);
-#endif
- crServerPresentFBO(cr_server.curClient->currentMural);
- }
+ CRMuralInfo *mural = cr_server.curClient->currentMural;
+ if (mural->bFbDraw)
+ {
+ if (crServerIsRedirectedToFBO())
+ crServerPresentFBO(mural);
+ }
- if (ctx->framebufferobject.drawFB
- || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT))
- cr_server.curClient->currentMural->bFbDraw = GL_FALSE;
+ if (ctx->framebufferobject.drawFB
+ || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT))
+ mural->bFbDraw = GL_FALSE;
+ }
}
void SERVER_DISPATCH_APIENTRY
@@ -470,15 +476,17 @@ crServerDispatchFinish(void)
cr_server.head_spu->dispatch_table.Finish();
- if (cr_server.curClient->currentMural->bFbDraw && crServerIsRedirectedToFBO())
+ if (cr_server.curClient && cr_server.curClient->currentMural)
{
-#ifdef DEBUG_misha
- CRASSERT(0);
-#endif
- crServerPresentFBO(cr_server.curClient->currentMural);
- }
+ CRMuralInfo *mural = cr_server.curClient->currentMural;
+ if (mural->bFbDraw)
+ {
+ if (crServerIsRedirectedToFBO())
+ crServerPresentFBO(mural);
+ }
- if (ctx->framebufferobject.drawFB
- || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT))
- cr_server.curClient->currentMural->bFbDraw = GL_FALSE;
+ if (ctx->framebufferobject.drawFB
+ || (ctx->buffer.drawBuffer != GL_FRONT && ctx->buffer.drawBuffer != GL_FRONT_LEFT))
+ mural->bFbDraw = GL_FALSE;
+ }
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
index 1621dcfc..c4b0ab93 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_config.c
@@ -50,14 +50,67 @@ setDefaults(void)
cr_server.uniqueWindows = 0;
- cr_server.idsPool.freeWindowID = 1;
- cr_server.idsPool.freeContextID = 1;
- cr_server.idsPool.freeClientID = 1;
-
cr_server.screenCount = 0;
- cr_server.bForceOffscreenRendering = GL_FALSE;
cr_server.bUsePBOForReadback = GL_FALSE;
- cr_server.bUseOutputRedirect = GL_FALSE;
+ cr_server.bWindowsInitiallyHidden = GL_FALSE;
+
+ cr_server.pfnNotifyEventCB = NULL;
+}
+
+int crServerVBoxParseNumerics(const char *pszStr, const int defaultVal)
+{
+ int result = 0;
+ bool neg = false;
+ unsigned char iDigit = 0;
+ if (!pszStr || pszStr[0] == '\0')
+ return defaultVal;
+
+ for (;;)
+ {
+ if (pszStr[0] == '\0')
+ return defaultVal;
+
+ if (pszStr[0] == ' ' || pszStr[0] == '\t' || pszStr[0] == '\n')
+ {
+ ++pszStr;
+ continue;
+ }
+
+ if (pszStr[0] == '-')
+ {
+ if (neg)
+ return defaultVal;
+
+ neg = true;
+ ++pszStr;
+ continue;
+ }
+
+ break;
+ }
+
+ for (;;)
+ {
+ unsigned char digit;
+ if (pszStr[0] == '\0')
+ {
+ if (!iDigit)
+ return defaultVal;
+ break;
+ }
+
+ digit = pszStr[0] - '0';
+ if (digit > 9)
+ return defaultVal;
+
+ result *= 10;
+ result += digit;
+ ++iDigit;
+
+ ++pszStr;
+ }
+
+ return !neg ? result : -result;
}
void crServerSetVBoxConfiguration()
@@ -79,6 +132,7 @@ void crServerSetVBoxConfiguration()
char hostname[1024];
char **clientchain, **clientlist;
GLint dims[4];
+ const char * env;
defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
CRASSERT(defaultMural);
@@ -155,6 +209,37 @@ void crServerSetVBoxConfiguration()
cr_server.head_spu =
crSPULoadChain(num_spus, spu_ids, spu_names, spu_dir, &cr_server);
+ env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
+ if (env != NULL && env[0] != '\0')
+ {
+ unsigned int bits = (unsigned int)crServerVBoxParseNumerics(env, 0);
+ if (bits <= CR_ALL_BITS)
+ cr_server.fVisualBitsDefault = bits;
+ else
+ crWarning("invalid bits option %c", bits);
+ }
+ else
+ cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;
+
+ env = crGetenv("CR_SERVER_CAPS");
+ if (env && env[0] != '\0')
+ {
+ cr_server.u32Caps = crServerVBoxParseNumerics(env, 0);
+ cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT | CR_VBOX_CAP_CMDVBVA);
+ }
+ else
+ {
+ cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_CMDVBVA*/;
+#ifdef DEBUG_misha
+ cr_server.u32Caps |= CR_VBOX_CAP_CMDVBVA;
+#endif
+
+ }
+
+ crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
+ cr_server.u32Caps,
+ cr_server.fVisualBitsDefault);
+
/* Need to do this as early as possible */
cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]);
@@ -258,6 +343,7 @@ void crServerSetVBoxConfigurationHGCM()
char *spu_dir = NULL;
int i;
GLint dims[4];
+ const char * env;
defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
CRASSERT(defaultMural);
@@ -272,6 +358,37 @@ void crServerSetVBoxConfigurationHGCM()
if (!cr_server.head_spu)
return;
+
+ env = crGetenv( "CR_SERVER_DEFAULT_VISUAL_BITS" );
+ if (env != NULL && env[0] != '\0')
+ {
+ unsigned int bits = (unsigned int)crServerVBoxParseNumerics(env, 0);
+ if (bits <= CR_ALL_BITS)
+ cr_server.fVisualBitsDefault = bits;
+ else
+ crWarning("invalid bits option %c", bits);
+ }
+ else
+ cr_server.fVisualBitsDefault = CR_RGB_BIT | CR_ALPHA_BIT | CR_DOUBLE_BIT;
+
+ env = crGetenv("CR_SERVER_CAPS");
+ if (env && env[0] != '\0')
+ {
+ cr_server.u32Caps = crServerVBoxParseNumerics(env, 0);
+ cr_server.u32Caps &= ~(CR_VBOX_CAP_TEX_PRESENT | CR_VBOX_CAP_CMDVBVA);
+ }
+ else
+ {
+ cr_server.u32Caps = CR_VBOX_CAP_TEX_PRESENT/* | CR_VBOX_CAP_CMDVBVA*/;
+#ifdef DEBUG_misha
+ cr_server.u32Caps |= CR_VBOX_CAP_CMDVBVA;
+#endif
+ }
+
+ crInfo("Cfg: u32Caps(%#x), fVisualBitsDefault(%#x)",
+ cr_server.u32Caps,
+ cr_server.fVisualBitsDefault);
+
cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_POSITION_CR, 0, GL_INT, 2, &dims[0]);
cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, &dims[2]);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
index 5c2ce040..afa2a208 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_context.c
@@ -27,6 +27,8 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
CRContextInfo *pContextInfo;
GLboolean fFirst = GL_FALSE;
+ dpyName = "";
+
if (shareCtx > 0) {
crWarning("CRServer: context sharing not implemented.");
shareCtx = 0;
@@ -39,16 +41,23 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
return -1;
}
- pContextInfo->CreateInfo.visualBits = visualBits;
+ pContextInfo->currentMural = NULL;
+
+ pContextInfo->CreateInfo.requestedVisualBits = visualBits;
+
+ if (cr_server.fVisualBitsDefault)
+ visualBits = cr_server.fVisualBitsDefault;
+
+ pContextInfo->CreateInfo.realVisualBits = visualBits;
/* Since the Cr server serialized all incoming clients/contexts into
* one outgoing GL stream, we only need to create one context for the
* head SPU. We'll only have to make it current once too, below.
*/
if (cr_server.firstCallCreateContext) {
- cr_server.MainContextInfo.CreateInfo.visualBits = visualBits;
+ cr_server.MainContextInfo.CreateInfo.realVisualBits = visualBits;
cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
- CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, shareCtx);
+ CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, shareCtx);
if (cr_server.MainContextInfo.SpuContext < 0) {
crWarning("crServerDispatchCreateContext() failed.");
crFree(pContextInfo);
@@ -58,16 +67,19 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
CRASSERT(cr_server.MainContextInfo.pContext);
cr_server.firstCallCreateContext = GL_FALSE;
fFirst = GL_TRUE;
+
+ cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext);
}
else {
/* second or third or ... context */
- if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.visualBits) != visualBits)) {
+ if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.realVisualBits) != visualBits)) {
int oldSpuContext;
-
+ /* should never be here */
+ CRASSERT(0);
/* the new context needs new visual attributes */
- cr_server.MainContextInfo.CreateInfo.visualBits |= visualBits;
- crDebug("crServerDispatchCreateContext requires new visual (0x%x).",
- cr_server.MainContextInfo.CreateInfo.visualBits);
+ cr_server.MainContextInfo.CreateInfo.realVisualBits |= visualBits;
+ crWarning("crServerDispatchCreateContext requires new visual (0x%x).",
+ cr_server.MainContextInfo.CreateInfo.realVisualBits);
/* Here, we used to just destroy the old rendering context.
* Unfortunately, this had the side effect of destroying
@@ -82,7 +94,7 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
/* create new rendering context with suitable visual */
oldSpuContext = cr_server.MainContextInfo.SpuContext;
cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
- CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
+ CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
/* destroy old rendering context */
cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext);
if (cr_server.MainContextInfo.SpuContext < 0) {
@@ -90,12 +102,16 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
crFree(pContextInfo);
return -1;
}
+
+ /* we do not need to clean up the old default context explicitly, since the above cr_server.head_spu->dispatch_table.DestroyContext call
+ * will do that for us */
+ cr_server.head_spu->dispatch_table.ChromiumParameteriCR(GL_HH_SET_DEFAULT_SHARED_CTX, cr_server.MainContextInfo.SpuContext);
}
}
if (cr_server.bUseMultipleContexts) {
pContextInfo->SpuContext = cr_server.head_spu->dispatch_table.
- CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
+ CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
if (pContextInfo->SpuContext < 0) {
crWarning("crServerDispatchCreateContext() failed.");
crStateEnableDiffOnMakeCurrent(GL_TRUE);
@@ -120,10 +136,10 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
if (newCtx) {
crStateSetCurrentPointers( newCtx, &(cr_server.current) );
crStateResetCurrentPointers(&(cr_server.current));
- retVal = preloadCtxID<0 ? crServerGenerateID(&cr_server.idsPool.freeContextID) : preloadCtxID;
+ retVal = preloadCtxID<0 ? (GLint)crHashtableAllocKeys( cr_server.contextTable, 1 ) : preloadCtxID;
pContextInfo->pContext = newCtx;
- pContextInfo->CreateInfo.visualBits = visualBits;
+ Assert(pContextInfo->CreateInfo.realVisualBits == visualBits);
pContextInfo->CreateInfo.externalID = retVal;
pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
crHashtableAdd(cr_server.contextTable, retVal, pContextInfo);
@@ -139,25 +155,6 @@ GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLi
}
}
- {
- /* As we're using only one host context to serve all client contexts, newly created context will still
- * hold last error value from any previous failed opengl call. Proper solution would be to redirect any
- * client glGetError calls to our state tracker, but right now it's missing quite a lot of checks and doesn't
- * reflect host driver/gpu specific issues. Thus we just reset last opengl error at context creation.
- */
- GLint err;
-
- err = cr_server.head_spu->dispatch_table.GetError();
- if (err!=GL_NO_ERROR)
- {
-#ifdef DEBUG_misha
- crDebug("Cleared gl error %#x on context creation", err);
-#else
- crWarning("Cleared gl error %#x on context creation", err);
-#endif
- }
- }
-
crServerReturnValue( &retVal, sizeof(retVal) );
return retVal;
@@ -179,6 +176,14 @@ static int crServerRemoveClientContext(CRClient *pClient, GLint ctx)
return false;
}
+static void crServerCleanupMuralCtxUsageCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo *mural = (CRMuralInfo *) data1;
+ CRContext *ctx = (CRContext *) data2;
+
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(mural, ctx);
+}
+
void SERVER_DISPATCH_APIENTRY
crServerDispatchDestroyContext( GLint ctx )
{
@@ -198,6 +203,15 @@ crServerDispatchDestroyContext( GLint ctx )
crDebug("CRServer: DestroyContext context %d", ctx);
+ if (cr_server.currentCtxInfo == crCtxInfo)
+ {
+ CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ crServerPerformMakeCurrent(dummyMural, &cr_server.MainContextInfo);
+ CRASSERT(cr_server.currentCtxInfo == &cr_server.MainContextInfo);
+ }
+
+ crHashtableWalk(cr_server.muralTable, crServerCleanupMuralCtxUsageCB, crCtx);
+ crCtxInfo->currentMural = NULL;
crHashtableDelete(cr_server.contextTable, ctx, NULL);
crStateDestroyContext( crCtx );
@@ -268,82 +282,56 @@ crServerDispatchDestroyContext( GLint ctx )
pNode = pNode->next;
}
- if (cr_server.currentCtxInfo == crCtxInfo)
- {
- cr_server.currentCtxInfo = &cr_server.MainContextInfo;
- }
+ CRASSERT(cr_server.currentCtxInfo != crCtxInfo);
}
-void SERVER_DISPATCH_APIENTRY
-crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
+void crServerPerformMakeCurrent( CRMuralInfo *mural, CRContextInfo *ctxInfo )
{
- CRMuralInfo *mural, *oldMural;
- CRContextInfo *ctxInfo = NULL;
+ CRMuralInfo *oldMural;
CRContext *ctx, *oldCtx = NULL;
-
- if (context >= 0 && window >= 0) {
- mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
- if (!mural)
- {
- crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window);
- return;
- }
-
- /* Update the state tracker's current context */
- ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context);
- if (!ctxInfo) {
- crWarning("CRserver: NULL context in MakeCurrent %d", context);
- return;
- }
- }
- else {
-#if 0
- oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
- if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO())
- {
- if (!crStateGetCurrent()->framebufferobject.drawFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- }
- if (!crStateGetCurrent()->framebufferobject.readFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- }
- }
-
- ctxInfo = &cr_server.MainContextInfo;
- window = -1;
- mural = NULL;
-#endif
- cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
- return;
- }
+ GLuint idDrawFBO, idReadFBO;
+ GLint context = ctxInfo->CreateInfo.externalID;
+ GLint window = mural->CreateInfo.externalID;
cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE;
ctx = ctxInfo->pContext;
CRASSERT(ctx);
- oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
+ oldMural = cr_server.currentMural;
/* Ubuntu 11.04 hosts misbehave if context window switch is
* done with non-default framebuffer object settings.
- * crStateSwichPrepare & crStateSwichPostprocess are supposed to work around this problem
- * crStateSwichPrepare restores the FBO state to its default values before the context window switch,
- * while crStateSwichPostprocess restores it back to the original values */
- oldCtx = crStateSwichPrepare(ctx, cr_server.bUseMultipleContexts, oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO() ? oldMural->idFBO : 0);
-
- /*
- crDebug("**** %s client %d curCtx=%d curWin=%d", __func__,
- cr_server.curClient->number, ctxPos, window);
- */
- cr_server.curClient->currentContextNumber = context;
- cr_server.curClient->currentCtxInfo = ctxInfo;
- cr_server.curClient->currentMural = mural;
- cr_server.curClient->currentWindow = window;
+ * crStateSwitchPrepare & crStateSwitchPostprocess are supposed to work around this problem
+ * crStateSwitchPrepare restores the FBO state to its default values before the context window switch,
+ * while crStateSwitchPostprocess restores it back to the original values */
+ oldCtx = crStateGetCurrent();
+ if (oldMural && oldMural->fRedirected && crServerSupportRedirMuralFBO())
+ {
+ idDrawFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurDrawBuffer);
+ idReadFBO = CR_SERVER_FBO_FOR_IDX(oldMural, oldMural->iCurReadBuffer);
+ }
+ else
+ {
+ idDrawFBO = 0;
+ idReadFBO = 0;
+ }
+ crStateSwitchPrepare(cr_server.bUseMultipleContexts ? NULL : ctx, oldCtx, idDrawFBO, idReadFBO);
- CRASSERT(cr_server.curClient->currentCtxInfo);
- CRASSERT(cr_server.curClient->currentCtxInfo->pContext);
+ if (cr_server.curClient)
+ {
+ /*
+ crDebug("**** %s client %d curCtx=%d curWin=%d", __func__,
+ cr_server.curClient->number, ctxPos, window);
+ */
+ cr_server.curClient->currentContextNumber = context;
+ cr_server.curClient->currentCtxInfo = ctxInfo;
+ cr_server.curClient->currentMural = mural;
+ cr_server.curClient->currentWindow = window;
+
+ CRASSERT(cr_server.curClient->currentCtxInfo);
+ CRASSERT(cr_server.curClient->currentCtxInfo->pContext);
+ }
/* This is a hack to force updating the 'current' attribs */
crStateUpdateColorBits();
@@ -380,26 +368,58 @@ crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
* used though.
*/
cr_server.head_spu->dispatch_table.MakeCurrent( mural->spuWindow,
- nativeWindow,
+ 0,
ctxInfo->SpuContext >= 0
? ctxInfo->SpuContext
: cr_server.MainContextInfo.SpuContext);
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(mural, ctx);
+ if (cr_server.currentCtxInfo)
+ cr_server.currentCtxInfo->currentMural = NULL;
+ ctxInfo->currentMural = mural;
+
cr_server.firstCallMakeCurrent = GL_FALSE;
cr_server.currentCtxInfo = ctxInfo;
cr_server.currentWindow = window;
- cr_server.currentNativeWindow = nativeWindow;
+ cr_server.currentNativeWindow = 0;
+ cr_server.currentMural = mural;
}
/* This used to be earlier, after crStateUpdateColorBits() call */
crStateMakeCurrent( ctx );
- crStateSwichPostprocess(oldCtx, cr_server.bUseMultipleContexts, mural->bUseFBO && crServerSupportRedirMuralFBO() ? mural->idFBO : 0);
+ if (mural && mural->fRedirected && crServerSupportRedirMuralFBO())
+ {
+ GLuint id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
+ if (id != mural->iCurDrawBuffer)
+ {
+ crDebug("DBO draw buffer changed on make current");
+ mural->iCurDrawBuffer = id;
+ }
+
+ id = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
+ if (id != mural->iCurReadBuffer)
+ {
+ crDebug("DBO read buffer changed on make current");
+ mural->iCurReadBuffer = id;
+ }
+
+ idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
+ idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
+ }
+ else
+ {
+ idDrawFBO = 0;
+ idReadFBO = 0;
+ }
+ crStateSwitchPostprocess(ctx, cr_server.bUseMultipleContexts ? NULL : oldCtx, idDrawFBO, idReadFBO);
if (!ctx->framebufferobject.drawFB
- && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT))
+ && (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT)
+ && cr_server.curClient)
cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
- if (!mural->bUseFBO)
+ if (!mural->fRedirected)
{
ctx->buffer.width = mural->width;
ctx->buffer.height = mural->height;
@@ -411,3 +431,51 @@ crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
}
}
+
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchMakeCurrent( GLint window, GLint nativeWindow, GLint context )
+{
+ CRMuralInfo *mural;
+ CRContextInfo *ctxInfo = NULL;
+
+ if (context >= 0 && window >= 0) {
+ mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
+ if (!mural)
+ {
+ crWarning("CRServer: invalid window %d passed to crServerDispatchMakeCurrent()", window);
+ return;
+ }
+
+ /* Update the state tracker's current context */
+ ctxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, context);
+ if (!ctxInfo) {
+ crWarning("CRserver: NULL context in MakeCurrent %d", context);
+ return;
+ }
+ }
+ else {
+#if 0
+ oldMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, cr_server.currentWindow);
+ if (oldMural && oldMural->bUseFBO && crServerSupportRedirMuralFBO())
+ {
+ if (!crStateGetCurrent()->framebufferobject.drawFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+ }
+ if (!crStateGetCurrent()->framebufferobject.readFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+ }
+ }
+
+ ctxInfo = &cr_server.MainContextInfo;
+ window = -1;
+ mural = NULL;
+#endif
+ cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
+ return;
+ }
+
+ crServerPerformMakeCurrent( mural, ctxInfo );
+}
+
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
index cacc3530..9e5b5397 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch.py
@@ -46,6 +46,7 @@ keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
for func_name in keys:
current = 0
array = ""
+ condition = ""
m = re.search( r"^(Color|Normal)([1234])(ub|b|us|s|ui|i|f|d)$", func_name )
if m :
current = 1
@@ -68,6 +69,7 @@ for func_name in keys:
name = "texCoord"
type = m.group(3) + m.group(2)
array = "[texture-GL_TEXTURE0_ARB]"
+ condition = "if (texture >= GL_TEXTURE0_ARB && texture < GL_TEXTURE0_ARB + CR_MAX_TEXTURE_UNITS)"
m = re.match( r"^(Index)(ub|b|us|s|ui|i|f|d)$", func_name )
if m :
current = 1
@@ -91,18 +93,23 @@ for func_name in keys:
name = string.lower( m.group(1)[:1] ) + m.group(1)[1:]
type = m.group(3) + m.group(2)
array = "[index]"
+ condition = "if (index < CR_MAX_VERTEX_ATTRIBS)"
if func_name == "VertexAttrib4NubARB":
current = 1
name = "vertexAttrib"
type = "ub4"
array = "[index]"
+ condition = "if (index < CR_MAX_VERTEX_ATTRIBS)"
if current:
params = apiutil.Parameters(func_name)
print 'void SERVER_DISPATCH_APIENTRY crServerDispatch%s( %s )' % ( func_name, apiutil.MakeDeclarationString(params) )
print '{'
- print '\tcr_server.head_spu->dispatch_table.%s( %s );' % (func_name, apiutil.MakeCallString(params) )
- print "\tcr_server.current.c.%s.%s%s = cr_unpackData;" % (name,type,array)
+ print '\t%s' % (condition)
+ print '\t{'
+ print '\t\tcr_server.head_spu->dispatch_table.%s( %s );' % (func_name, apiutil.MakeCallString(params) )
+ print "\t\tcr_server.current.c.%s.%s%s = cr_unpackData;" % (name,type,array)
+ print '\t}'
print '}\n'
print """
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py
index f1db1f05..9ac9895a 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_dispatch_header.py
@@ -22,6 +22,11 @@ print """
#include "chromium.h"
#include "state/cr_statetypes.h"
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
"""
keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
@@ -36,4 +41,10 @@ for func_name in keys:
print '%s SERVER_DISPATCH_APIENTRY crServerDispatch%s( %s );' % (return_type, func_name, apiutil.MakeDeclarationString( params ))
-print '#endif /* SERVER_DISPATCH_HEADER */'
+print """
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* SERVER_DISPATCH_HEADER */
+"""
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c
index cc609377..da25dbb0 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_framebuffer.c
@@ -5,7 +5,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;
@@ -28,7 +28,9 @@ crServerDispatchGenFramebuffersEXT(GLsizei n, GLuint *framebuffers)
{
GLuint *local_buffers = (GLuint *) crAlloc(n * sizeof(*local_buffers));
(void) framebuffers;
- cr_server.head_spu->dispatch_table.GenFramebuffersEXT(n, local_buffers);
+
+ crStateGenFramebuffersEXT(n, local_buffers);
+
crServerReturnValue(local_buffers, n * sizeof(*local_buffers));
crFree(local_buffers);
}
@@ -38,7 +40,9 @@ crServerDispatchGenRenderbuffersEXT(GLsizei n, GLuint *renderbuffers)
{
GLuint *local_buffers = (GLuint *) crAlloc(n * sizeof(*local_buffers));
(void) renderbuffers;
- cr_server.head_spu->dispatch_table.GenFramebuffersEXT(n, local_buffers);
+
+ crStateGenRenderbuffersEXT(n, local_buffers);
+
crServerReturnValue(local_buffers, n * sizeof(*local_buffers));
crFree(local_buffers);
}
@@ -71,29 +75,54 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchBindFramebufferEXT(GLenum target,
if (0==framebuffer)
{
CRContext *ctx = crStateGetCurrent();
- if (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT)
+ if (ctx->buffer.drawBuffer == GL_FRONT || ctx->buffer.drawBuffer == GL_FRONT_LEFT || ctx->buffer.drawBuffer == GL_FRONT_RIGHT)
cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
}
if (0==framebuffer && crServerIsRedirectedToFBO())
{
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(target, cr_server.curClient->currentMural->idFBO);
+ CRMuralInfo *mural = cr_server.curClient->currentMural;
+ if (target == GL_FRAMEBUFFER)
+ {
+ GLuint idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
+ GLuint idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
+ if (idDrawFBO == idReadFBO)
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_FRAMEBUFFER, idDrawFBO);
+ else
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
+ }
+ }
+ else if (target == GL_READ_FRAMEBUFFER)
+ {
+ GLuint idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, idReadFBO);
+ }
+ else if (target == GL_DRAW_FRAMEBUFFER)
+ {
+ GLuint idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, idDrawFBO);
+ }
+ else
+ {
+ crWarning("unknown target %d", target);
+ }
#ifdef DEBUG_misha
- Assert(0);
cr_server.head_spu->dispatch_table.GetIntegerv(GL_READ_FRAMEBUFFER_BINDING_EXT, &rfb);
cr_server.head_spu->dispatch_table.GetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING_EXT, &dfb);
if (GL_FRAMEBUFFER_EXT == target)
{
- Assert(rfb == cr_server.curClient->currentMural->idFBO);
- Assert(dfb == cr_server.curClient->currentMural->idFBO);
+ Assert(rfb == CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+ Assert(dfb == CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
}
else if (GL_READ_FRAMEBUFFER_EXT == target)
{
- Assert(rfb == cr_server.curClient->currentMural->idFBO);
+ Assert(rfb == CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
}
else if (GL_DRAW_FRAMEBUFFER_EXT == target)
{
- Assert(dfb == cr_server.curClient->currentMural->idFBO);
+ Assert(dfb == CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
}
else
{
@@ -163,16 +192,18 @@ crServerDispatchGetFramebufferAttachmentParameterivEXT(GLenum target, GLenum att
GLboolean SERVER_DISPATCH_APIENTRY crServerDispatchIsFramebufferEXT( GLuint framebuffer )
{
- GLboolean retval;
- retval = cr_server.head_spu->dispatch_table.IsFramebufferEXT(crStateGetFramebufferHWID(framebuffer));
+ /* since GenFramebuffers/Renderbuffers issued to host ogl only on bind + some other ops, the host drivers may not know about them
+ * so use state data*/
+ GLboolean retval = crStateIsFramebufferEXT(framebuffer);
crServerReturnValue( &retval, sizeof(retval) );
return retval; /* WILL PROBABLY BE IGNORED */
}
GLboolean SERVER_DISPATCH_APIENTRY crServerDispatchIsRenderbufferEXT( GLuint renderbuffer )
{
- GLboolean retval;
- retval = cr_server.head_spu->dispatch_table.IsRenderbufferEXT(crStateGetRenderbufferHWID(renderbuffer));
+ /* since GenFramebuffers/Renderbuffers issued to host ogl only on bind + some other ops, the host drivers may not know about them
+ * so use state data*/
+ GLboolean retval = crStateIsRenderbufferEXT(renderbuffer);
crServerReturnValue( &retval, sizeof(retval) );
return retval; /* WILL PROBABLY BE IGNORED */
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
index 89391d6c..58d4953e 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_get.py
@@ -108,8 +108,6 @@ convert_bufferid = [
'GetVertexAttribivNV'
];
-from get_components import *;
-
keys = apiutil.GetDispatchedFunctions(sys.argv[1]+"/APIspec.txt")
for func_name in keys:
#(return_type, arg_names, arg_types) = gl_mapping[func_name]
@@ -142,5 +140,5 @@ for func_name in keys:
if func_name in no_pnames:
print '\tcrServerReturnValue( &(%s[0]), %d*sizeof(%s) );' % (local_argname, max_components[func_name], local_argtype );
else:
- print '\tcrServerReturnValue( &(%s[0]), lookupComponents(pname)*sizeof(%s) );' % (local_argname, local_argtype );
+ print '\tcrServerReturnValue( &(%s[0]), crStateHlpComponentsCount(pname)*sizeof(%s) );' % (local_argname, local_argtype );
print '}\n'
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
index 12677f84..20acbc05 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_getshaders.c
@@ -5,7 +5,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;
@@ -46,6 +46,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetActiveAttrib(GLuint program, GL
zero.length = 0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* zero out just the header to ensure it initially contains zero size values */
+ memset(pLocal, 0, sizeof (*pLocal));
cr_server.head_spu->dispatch_table.GetActiveAttrib(crStateGetProgramHWID(program), index, bufSize, &pLocal->length, &pLocal->size, &pLocal->type, (char*)&pLocal[1]);
crServerReturnValue(pLocal, pLocal->length+1+sizeof(crGetActive_t));
crFree(pLocal);
@@ -62,6 +64,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetActiveUniform(GLuint program, G
zero.length = 0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* zero out just the header to ensure it initially contains zero size values */
+ memset(pLocal, 0, sizeof (*pLocal));
cr_server.head_spu->dispatch_table.GetActiveUniform(crStateGetProgramHWID(program), index, bufSize, &pLocal->length, &pLocal->size, &pLocal->type, (char*)&pLocal[1]);
crServerReturnValue(pLocal, pLocal->length+1+sizeof(crGetActive_t));
crFree(pLocal);
@@ -77,6 +81,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedShaders(GLuint program,
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
cr_server.head_spu->dispatch_table.GetAttachedShaders(crStateGetProgramHWID(program), maxCount, pLocal, (GLuint*)&pLocal[1]);
{
@@ -91,17 +97,19 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedShaders(GLuint program,
crFree(pLocal);
}
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(GLhandleARB containerObj, GLsizei maxCount, GLsizei * count, GLhandleARB * obj)
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(VBoxGLhandleARB containerObj, GLsizei maxCount, GLsizei * count, VBoxGLhandleARB * obj)
{
GLsizei *pLocal;
- pLocal = (GLsizei*) crAlloc(maxCount*sizeof(GLhandleARB)+sizeof(GLsizei));
+ pLocal = (GLsizei*) crAlloc(maxCount*sizeof(VBoxGLhandleARB)+sizeof(GLsizei));
if (!pLocal)
{
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
- cr_server.head_spu->dispatch_table.GetAttachedObjectsARB(crStateGetProgramHWID(containerObj), maxCount, pLocal, (GLhandleARB*)&pLocal[1]);
+ /* initial (fallback )value */
+ *pLocal = 0;
+ cr_server.head_spu->dispatch_table.GetAttachedObjectsARB(crStateGetProgramHWID(containerObj), maxCount, pLocal, (VBoxGLhandleARB*)&pLocal[1]);
{
GLsizei i;
@@ -111,13 +119,13 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetAttachedObjectsARB(GLhandleARB
ids[i] = crStateGLSLShaderHWIDtoID(ids[i]);
}
- crServerReturnValue(pLocal, (*pLocal)*sizeof(GLhandleARB)+sizeof(GLsizei));
+ crServerReturnValue(pLocal, (*pLocal)*sizeof(VBoxGLhandleARB)+sizeof(GLsizei));
crFree(pLocal);
}
AssertCompile(sizeof(GLsizei) == 4);
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetInfoLogARB(GLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetInfoLogARB(VBoxGLhandleARB obj, GLsizei maxLength, GLsizei * length, GLcharARB * infoLog)
{
GLsizei *pLocal;
GLuint hwid;
@@ -128,6 +136,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetInfoLogARB(GLhandleARB obj, GLs
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
/*@todo: recheck*/
hwid = crStateGetProgramHWID(obj);
if (!hwid) hwid = crStateGetShaderHWID(obj);
@@ -147,6 +157,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetShaderInfoLog(GLuint shader, GL
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
cr_server.head_spu->dispatch_table.GetShaderInfoLog(crStateGetShaderHWID(shader), bufSize, pLocal, (char*)&pLocal[1]);
crServerReturnValue(pLocal, pLocal[0]+sizeof(GLsizei));
crFree(pLocal);
@@ -162,6 +174,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetProgramInfoLog(GLuint program,
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
cr_server.head_spu->dispatch_table.GetProgramInfoLog(crStateGetProgramHWID(program), bufSize, pLocal, (char*)&pLocal[1]);
CRASSERT(pLocal[0] <= bufSize);
crServerReturnValue(pLocal, pLocal[0]+sizeof(GLsizei));
@@ -178,6 +192,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetShaderSource(GLuint shader, GLs
GLsizei zero=0;
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
cr_server.head_spu->dispatch_table.GetShaderSource(crStateGetShaderHWID(shader), bufSize, pLocal, (char*)&pLocal[1]);
CRASSERT(pLocal[0] <= bufSize);
crServerReturnValue(pLocal, pLocal[0]+sizeof(GLsizei));
@@ -199,6 +215,8 @@ crServerDispatchGetUniformsLocations(GLuint program, GLsizei maxcbData, GLsizei
crServerReturnValue(&zero, sizeof(zero));
}
+ /* initial (fallback )value */
+ *pLocal = 0;
crStateGLSLProgramCacheUniforms(program, maxcbData, pLocal, (char*)&pLocal[1]);
crServerReturnValue(pLocal, (*pLocal)+sizeof(GLsizei));
@@ -207,8 +225,8 @@ crServerDispatchGetUniformsLocations(GLuint program, GLsizei maxcbData, GLsizei
static GLint __GetUniformSize(GLuint program, GLint location)
{
- GLint size;
- GLenum type;
+ GLint size = 0;
+ GLenum type = 0;
/*@todo: check if index and location is the same*/
cr_server.head_spu->dispatch_table.GetActiveUniform(crStateGetProgramHWID(program), location, 0, NULL, &size, &type, NULL);
@@ -286,7 +304,7 @@ GLboolean SERVER_DISPATCH_APIENTRY crServerDispatchIsProgram(GLuint program)
return retval; /* ignored */
}
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( GLhandleARB obj, GLenum pname, GLfloat * params )
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( VBoxGLhandleARB obj, GLenum pname, GLfloat * params )
{
GLfloat local_params[1];
GLuint hwid = crStateGetProgramHWID(obj);
@@ -305,7 +323,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterfvARB( GLhandleA
crServerReturnValue( &(local_params[0]), 1*sizeof(GLfloat) );
}
-void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterivARB( GLhandleARB obj, GLenum pname, GLint * params )
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetObjectParameterivARB( VBoxGLhandleARB obj, GLenum pname, GLint * params )
{
GLint local_params[1];
GLuint hwid = crStateGetProgramHWID(obj);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
index c11d2d00..25d4b91e 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_glsl.c
@@ -5,7 +5,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;
@@ -29,13 +29,29 @@
void SERVER_DISPATCH_APIENTRY crServerDispatchShaderSource(GLuint shader, GLsizei count, const char ** string, const GLint * length)
{
/*@todo?crStateShaderSource(shader...);*/
+#ifdef DEBUG_misha
+ GLenum err = cr_server.head_spu->dispatch_table.GetError();
+#endif
cr_server.head_spu->dispatch_table.ShaderSource(crStateGetShaderHWID(shader), count, string, length);
+#ifdef DEBUG_misha
+ err = cr_server.head_spu->dispatch_table.GetError();
+ CRASSERT(err == GL_NO_ERROR);
+#endif
+ CR_SERVER_DUMP_SHADER_SOURCE(shader);
}
void SERVER_DISPATCH_APIENTRY crServerDispatchCompileShader(GLuint shader)
{
+#ifdef DEBUG_misha
+ GLint iCompileStatus = GL_FALSE;
+#endif
crStateCompileShader(shader);
cr_server.head_spu->dispatch_table.CompileShader(crStateGetShaderHWID(shader));
+#ifdef DEBUG_misha
+ cr_server.head_spu->dispatch_table.GetShaderiv(crStateGetShaderHWID(shader), GL_COMPILE_STATUS, &iCompileStatus);
+ Assert(iCompileStatus == GL_TRUE);
+#endif
+ CR_SERVER_DUMP_COMPILE_SHADER(shader);
}
void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteShader(GLuint shader)
@@ -64,6 +80,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchLinkProgram(GLuint program)
{
crStateLinkProgram(program);
cr_server.head_spu->dispatch_table.LinkProgram(crStateGetProgramHWID(program));
+ CR_SERVER_DUMP_LINK_PROGRAM(program);
}
void SERVER_DISPATCH_APIENTRY crServerDispatchUseProgram(GLuint program)
@@ -94,23 +111,14 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchBindAttribLocation(GLuint program,
cr_server.head_spu->dispatch_table.BindAttribLocation(crStateGetProgramHWID(program), index, name);
}
-void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteObjectARB(GLhandleARB obj)
+void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteObjectARB(VBoxGLhandleARB obj)
{
- GLuint hwid = crStateGetProgramHWID(obj);
-
- if (!hwid)
- {
- hwid = crStateGetShaderHWID(obj);
- CRASSERT(hwid);
- crStateDeleteShader(obj);
- }
- else
- {
- crStateDeleteProgram(obj);
- }
+ GLuint hwid = crStateDeleteObjectARB(obj);
if (hwid)
cr_server.head_spu->dispatch_table.DeleteObjectARB(hwid);
+ else
+ crWarning("zero hwid for object %d", obj);
}
GLint SERVER_DISPATCH_APIENTRY crServerDispatchGetAttribLocation( GLuint program, const char * name )
@@ -121,9 +129,9 @@ GLint SERVER_DISPATCH_APIENTRY crServerDispatchGetAttribLocation( GLuint program
return retval; /* WILL PROBABLY BE IGNORED */
}
-GLhandleARB SERVER_DISPATCH_APIENTRY crServerDispatchGetHandleARB( GLenum pname )
+VBoxGLhandleARB SERVER_DISPATCH_APIENTRY crServerDispatchGetHandleARB( GLenum pname )
{
- GLhandleARB retval;
+ VBoxGLhandleARB retval;
retval = cr_server.head_spu->dispatch_table.GetHandleARB(pname);
if (pname==GL_PROGRAM_OBJECT_ARB)
{
@@ -141,4 +149,19 @@ GLint SERVER_DISPATCH_APIENTRY crServerDispatchGetUniformLocation(GLuint program
return retval; /* WILL PROBABLY BE IGNORED */
}
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetProgramiv( GLuint program, GLenum pname, GLint * params )
+{
+ GLint local_params[1];
+ (void) params;
+ cr_server.head_spu->dispatch_table.GetProgramiv(crStateGetProgramHWID(program), pname, local_params);
+ crServerReturnValue( &(local_params[0]), 1*sizeof(GLint) );
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetShaderiv( GLuint shader, GLenum pname, GLint * params )
+{
+ GLint local_params[1];
+ (void) params;
+ cr_server.head_spu->dispatch_table.GetShaderiv( crStateGetShaderHWID(shader), pname, local_params );
+ crServerReturnValue( &(local_params[0]), 1*sizeof(GLint) );
+}
#endif /* #ifdef CR_OPENGL_VERSION_2_0 */
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
index 3079c15b..6c3d9bd0 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_lists.c
@@ -60,6 +60,7 @@ GLuint crServerTranslateProgramID( GLuint id )
void SERVER_DISPATCH_APIENTRY
crServerDispatchNewList( GLuint list, GLenum mode )
{
+ Assert(0);
if (mode == GL_COMPILE_AND_EXECUTE)
crWarning("using glNewList(GL_COMPILE_AND_EXECUTE) can confuse the crserver");
@@ -68,10 +69,37 @@ crServerDispatchNewList( GLuint list, GLenum mode )
cr_server.head_spu->dispatch_table.NewList( list, mode );
}
+static void crServerQueryHWState()
+{
+ GLuint fbFbo, bbFbo;
+ CRClient *client = cr_server.curClient;
+ CRMuralInfo *mural = client ? client->currentMural : NULL;
+ if (mural && mural->fRedirected)
+ {
+ fbFbo = mural->aidFBOs[CR_SERVER_FBO_FB_IDX(mural)];
+ bbFbo = mural->aidFBOs[CR_SERVER_FBO_BB_IDX(mural)];
+ }
+ else
+ {
+ fbFbo = bbFbo = 0;
+ }
+ crStateQueryHWState(fbFbo, bbFbo);
+}
+
void SERVER_DISPATCH_APIENTRY crServerDispatchEndList(void)
{
+ CRContext *g = crStateGetCurrent();
+ CRListsState *l = &(g->lists);
+
cr_server.head_spu->dispatch_table.EndList();
crStateEndList();
+
+#ifndef IN_GUEST
+ if (l->mode==GL_COMPILE)
+ {
+ crServerQueryHWState();
+ }
+#endif
}
void SERVER_DISPATCH_APIENTRY
@@ -83,7 +111,7 @@ crServerDispatchCallList( GLuint list )
/* we're not compiling, so execute the list now */
/* Issue the list as-is */
cr_server.head_spu->dispatch_table.CallList( list );
- crStateQueryHWState();
+ crServerQueryHWState();
}
else {
/* we're compiling glCallList into another list - just pass it through */
@@ -211,7 +239,7 @@ crServerDispatchCallLists( GLsizei n, GLenum type, const GLvoid *lists )
/* we're not compiling, so execute the list now */
/* Issue the list as-is */
cr_server.head_spu->dispatch_table.CallLists( n, type, lists );
- crStateQueryHWState();
+ crServerQueryHWState();
}
else {
/* we're compiling glCallList into another list - just pass it through */
@@ -264,6 +292,12 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchDeleteTextures( GLsizei n, const G
newTextures[i] = crStateGetTextureHWID(textures[i]);
}
+ for (i = 0; i < n; ++i)
+ {
+ crDebug("DeleteTexture: %d, pid %d, ctx %d", textures[i], (uint32_t)cr_server.curClient->pid, cr_server.currentCtxInfo->pContext->id);
+ }
+
+
crStateDeleteTextures(n, textures);
cr_server.head_spu->dispatch_table.DeleteTextures(n, newTextures);
crFree(newTextures);
@@ -280,12 +314,13 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchPrioritizeTextures( GLsizei n, con
return;
}
+ crStatePrioritizeTextures(n, textures, priorities);
+
for (i = 0; i < n; i++)
{
newTextures[i] = crStateGetTextureHWID(textures[i]);
}
- crStatePrioritizeTextures(n, textures, priorities);
cr_server.head_spu->dispatch_table.PrioritizeTextures(n, newTextures, priorities);
crFree(newTextures);
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
index f914569e..1a7e360c 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
@@ -12,7 +12,9 @@
#include "cr_string.h"
#include "cr_mem.h"
#include "cr_hash.h"
+#include "cr_vreg.h"
#include "cr_environment.h"
+#include "cr_pixeldata.h"
#include "server_dispatch.h"
#include "state/cr_texture.h"
#include "render/renderspu.h"
@@ -25,6 +27,7 @@
#endif
#include <iprt/assert.h>
#include <VBox/err.h>
+#include <VBox/log.h>
#ifdef VBOXCR_LOGFPS
#include <iprt/timer.h>
@@ -56,6 +59,8 @@ CRServer cr_server;
int tearingdown = 0; /* can't be static */
+static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd);
+
DECLINLINE(int32_t) crVBoxServerClientGet(uint32_t u32ClientID, CRClient **ppClient)
{
CRClient *pClient = NULL;
@@ -118,11 +123,22 @@ static void deleteContextInfoCallback( void *data )
crFree(c);
}
+static void deleteMuralInfoCallback( void *data )
+{
+ CRMuralInfo *m = (CRMuralInfo *) data;
+ if (m->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID) /* <- do not do term for default mural as it does not contain any info to be freed,
+ * and renderspu will destroy it up itself*/
+ {
+ crServerMuralTerm(m);
+ }
+ crFree(m);
+}
static void crServerTearDown( void )
{
GLint i;
CRClientNode *pNode, *pNext;
+ GLboolean fOldEnableDiff;
/* avoid a race condition */
if (tearingdown)
@@ -138,6 +154,17 @@ static void crServerTearDown( void )
crFree( cr_server.overlap_intens );
cr_server.overlap_intens = NULL;
+ /* needed to make sure window dummy mural not get created on mural destruction
+ * and generally this should be zeroed up */
+ cr_server.currentCtxInfo = NULL;
+ cr_server.currentWindow = -1;
+ cr_server.currentNativeWindow = 0;
+ cr_server.currentMural = NULL;
+
+ /* sync our state with renderspu,
+ * do it before mural & context deletion to avoid deleting currently set murals/contexts*/
+ cr_server.head_spu->dispatch_table.MakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
+
/* Deallocate all semaphores */
crFreeHashtable(cr_server.semaphores, crFree);
cr_server.semaphores = NULL;
@@ -149,12 +176,28 @@ static void crServerTearDown( void )
/* Free all context info */
crFreeHashtable(cr_server.contextTable, deleteContextInfoCallback);
- /* Free context/window creation info */
- crFreeHashtable(cr_server.pWindowCreateInfoTable, crServerCreateInfoDeleteCB);
+ /* synchronize with reality */
+ fOldEnableDiff = crStateEnableDiffOnMakeCurrent(GL_FALSE);
+ if(cr_server.MainContextInfo.pContext)
+ crStateMakeCurrent(cr_server.MainContextInfo.pContext);
+ crStateEnableDiffOnMakeCurrent(fOldEnableDiff);
/* Free vertex programs */
crFreeHashtable(cr_server.programTable, crFree);
+ /* Free murals */
+ crFreeHashtable(cr_server.muralTable, deleteMuralInfoCallback);
+
+ CrPMgrTerm();
+
+ if (CrBltIsInitialized(&cr_server.Blitter))
+ {
+ CrBltTerm(&cr_server.Blitter);
+ }
+
+ /* Free dummy murals */
+ crFreeHashtable(cr_server.dummyMuralTable, deleteMuralInfoCallback);
+
for (i = 0; i < cr_server.numClients; i++) {
if (cr_server.clients[i]) {
CRConnection *conn = cr_server.clients[i]->conn;
@@ -174,6 +217,11 @@ static void crServerTearDown( void )
}
cr_server.pCleanupClient = NULL;
+ if (crServerRpwIsInitialized(&cr_server.RpwWorker))
+ {
+ crServerRpwTerm(&cr_server.RpwWorker);
+ }
+
#if 1
/* disable these two lines if trying to get stack traces with valgrind */
crSPUUnloadChain(cr_server.head_spu);
@@ -183,6 +231,10 @@ static void crServerTearDown( void )
crStateDestroy();
crNetTearDown();
+
+ VBoxVrListClear(&cr_server.RootVr);
+
+ VBoxVrTerm();
}
static void crServerClose( unsigned int id )
@@ -226,8 +278,15 @@ void
crServerInit(int argc, char *argv[])
{
int i;
+ const char*env;
char *mothership = NULL;
CRMuralInfo *defaultMural;
+ int rc = VBoxVrInit();
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("VBoxVrInit failed, rc %d", rc);
+ return;
+ }
for (i = 1 ; i < argc ; i++)
{
@@ -294,6 +353,7 @@ crServerInit(int argc, char *argv[])
*/
cr_server.muralTable = crAllocHashtable();
defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
+ defaultMural->spuWindow = CR_RENDER_DEFAULT_WINDOW_ID;
crHashtableAdd(cr_server.muralTable, 0, defaultMural);
cr_server.programTable = crAllocHashtable();
@@ -311,9 +371,39 @@ crServerInit(int argc, char *argv[])
cr_server.contextTable = crAllocHashtable();
cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
+ cr_server.dummyMuralTable = crAllocHashtable();
+
+ CrPMgrInit();
+
+ cr_server.fRootVrOn = GL_FALSE;
+ VBoxVrListInit(&cr_server.RootVr);
+ crMemset(&cr_server.RootVrCurPoint, 0, sizeof (cr_server.RootVrCurPoint));
+
+ crMemset(&cr_server.RpwWorker, 0, sizeof (cr_server.RpwWorker));
+
+ env = crGetenv("CR_SERVER_BFB");
+ if (env)
+ {
+ cr_server.fBlitterMode = env[0] - '0';
+ }
+ else
+ {
+ cr_server.fBlitterMode = CR_SERVER_BFB_DISABLED;
+ }
+ crMemset(&cr_server.Blitter, 0, sizeof (cr_server.Blitter));
+
crServerInitDispatch();
+ crServerInitTmpCtxDispatch();
crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+ crMemset(&cr_server.Recorder, 0, sizeof (cr_server.Recorder));
+ crMemset(&cr_server.RecorderBlitter, 0, sizeof (cr_server.RecorderBlitter));
+ crMemset(&cr_server.DbgPrintDumper, 0, sizeof (cr_server.DbgPrintDumper));
+ crMemset(&cr_server.HtmlDumper, 0, sizeof (cr_server.HtmlDumper));
+ cr_server.pDumper = NULL;
+#endif
+
crUnpackSetReturnPointer( &(cr_server.return_ptr) );
crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
@@ -332,6 +422,13 @@ void crVBoxServerTearDown(void)
GLboolean crVBoxServerInit(void)
{
CRMuralInfo *defaultMural;
+ const char*env;
+ int rc = VBoxVrInit();
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("VBoxVrInit failed, rc %d", rc);
+ return GL_FALSE;
+ }
#if DEBUG_FP_EXCEPTIONS
{
@@ -367,6 +464,7 @@ GLboolean crVBoxServerInit(void)
*/
cr_server.muralTable = crAllocHashtable();
defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
+ defaultMural->spuWindow = CR_RENDER_DEFAULT_WINDOW_ID;
crHashtableAdd(cr_server.muralTable, 0, defaultMural);
cr_server.programTable = crAllocHashtable();
@@ -385,8 +483,27 @@ GLboolean crVBoxServerInit(void)
* Default context
*/
cr_server.contextTable = crAllocHashtable();
-// cr_server.pContextCreateInfoTable = crAllocHashtable();
- cr_server.pWindowCreateInfoTable = crAllocHashtable();
+
+ cr_server.dummyMuralTable = crAllocHashtable();
+
+ CrPMgrInit();
+
+ cr_server.fRootVrOn = GL_FALSE;
+ VBoxVrListInit(&cr_server.RootVr);
+ crMemset(&cr_server.RootVrCurPoint, 0, sizeof (cr_server.RootVrCurPoint));
+
+ crMemset(&cr_server.RpwWorker, 0, sizeof (cr_server.RpwWorker));
+
+ env = crGetenv("CR_SERVER_BFB");
+ if (env)
+ {
+ cr_server.fBlitterMode = env[0] - '0';
+ }
+ else
+ {
+ cr_server.fBlitterMode = CR_SERVER_BFB_DISABLED;
+ }
+ crMemset(&cr_server.Blitter, 0, sizeof (cr_server.Blitter));
crServerSetVBoxConfigurationHGCM();
@@ -394,8 +511,17 @@ GLboolean crVBoxServerInit(void)
return GL_FALSE;
crServerInitDispatch();
+ crServerInitTmpCtxDispatch();
crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+ crMemset(&cr_server.Recorder, 0, sizeof (cr_server.Recorder));
+ crMemset(&cr_server.RecorderBlitter, 0, sizeof (cr_server.RecorderBlitter));
+ crMemset(&cr_server.DbgPrintDumper, 0, sizeof (cr_server.DbgPrintDumper));
+ crMemset(&cr_server.HtmlDumper, 0, sizeof (cr_server.HtmlDumper));
+ cr_server.pDumper = NULL;
+#endif
+
/*Check for PBO support*/
if (crStateGetCurrent()->extensions.ARB_pixel_buffer_object)
{
@@ -405,6 +531,38 @@ GLboolean crVBoxServerInit(void)
return GL_TRUE;
}
+static int32_t crVBoxServerAddClientObj(uint32_t u32ClientID, CRClient **ppNewClient)
+{
+ CRClient *newClient;
+
+ if (cr_server.numClients>=CR_MAX_CLIENTS)
+ {
+ if (ppNewClient)
+ *ppNewClient = NULL;
+ return VERR_MAX_THRDS_REACHED;
+ }
+
+ newClient = (CRClient *) crCalloc(sizeof(CRClient));
+ crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
+
+ newClient->spu_id = 0;
+ newClient->currentCtxInfo = &cr_server.MainContextInfo;
+ newClient->currentContextNumber = -1;
+ newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
+ cr_server.tcpip_port,
+ cr_server.mtu, 0);
+ newClient->conn->u32ClientID = u32ClientID;
+
+ cr_server.clients[cr_server.numClients++] = newClient;
+
+ crServerAddToRunQueue(newClient);
+
+ if (ppNewClient)
+ *ppNewClient = newClient;
+
+ return VINF_SUCCESS;
+}
+
int32_t crVBoxServerAddClient(uint32_t u32ClientID)
{
CRClient *newClient;
@@ -614,6 +772,23 @@ int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t
return crVBoxServerInternalClientRead(pClient, pBuffer, pcbBuffer);
}
+extern DECLEXPORT(int32_t) crVBoxServerClientGetCaps(uint32_t u32ClientID, uint32_t *pu32Caps)
+{
+ *pu32Caps = cr_server.u32Caps;
+ return VINF_SUCCESS;
+}
+
+static int32_t crVBoxServerClientObjSetVersion(CRClient *pClient, uint32_t vMajor, uint32_t vMinor)
+{
+ pClient->conn->vMajor = vMajor;
+ pClient->conn->vMinor = vMinor;
+
+ if (vMajor != CR_PROTOCOL_VERSION_MAJOR
+ || vMinor != CR_PROTOCOL_VERSION_MINOR)
+ return VERR_NOT_SUPPORTED;
+ return VINF_SUCCESS;
+}
+
int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
{
CRClient *pClient=NULL;
@@ -630,15 +805,14 @@ int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint
}
if (!pClient) return VERR_INVALID_PARAMETER;
- pClient->conn->vMajor = vMajor;
- pClient->conn->vMinor = vMinor;
+ return crVBoxServerClientObjSetVersion(pClient, vMajor, vMinor);
+}
- if (vMajor != CR_PROTOCOL_VERSION_MAJOR
- || vMinor != CR_PROTOCOL_VERSION_MINOR)
- {
- return VERR_NOT_SUPPORTED;
- }
- else return VINF_SUCCESS;
+static int32_t crVBoxServerClientObjSetPID(CRClient *pClient, uint64_t pid)
+{
+ pClient->pid = pid;
+
+ return VINF_SUCCESS;
}
int32_t crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid)
@@ -657,9 +831,7 @@ int32_t crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid)
}
if (!pClient) return VERR_INVALID_PARAMETER;
- pClient->pid = pid;
-
- return VINF_SUCCESS;
+ return crVBoxServerClientObjSetPID(pClient, pid);
}
int
@@ -690,13 +862,16 @@ static void crVBoxServerSaveMuralCB(unsigned long key, void *data1, void *data2)
rc = SSMR3PutMem(pSSM, &key, sizeof(key));
CRASSERT(rc == VINF_SUCCESS);
- rc = SSMR3PutMem(pSSM, pMI, sizeof(*pMI));
+ rc = SSMR3PutMem(pSSM, pMI, RT_OFFSETOF(CRMuralInfo, CreateInfo));
CRASSERT(rc == VINF_SUCCESS);
if (pMI->pVisibleRects)
{
rc = SSMR3PutMem(pSSM, pMI->pVisibleRects, 4*sizeof(GLint)*pMI->cVisibleRects);
}
+
+ rc = SSMR3PutMem(pSSM, pMI->ctxUsage, sizeof (pMI->ctxUsage));
+ CRASSERT(rc == VINF_SUCCESS);
}
/* @todo add hashtable walker with result info and intermediate abort */
@@ -708,6 +883,9 @@ static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *d
CRASSERT(pCreateInfo && pSSM);
+ /* Don't store default mural create info */
+ if (!key) return;
+
rc = SSMR3PutMem(pSSM, &key, sizeof(key));
CRASSERT(rc == VINF_SUCCESS);
@@ -721,10 +899,22 @@ static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *d
}
}
+static void crVBoxServerSaveCreateInfoFromMuralInfoCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo *pMural = (CRMuralInfo *)data1;
+ CRCreateInfo_t CreateInfo;
+ CreateInfo.pszDpyName = pMural->CreateInfo.pszDpyName;
+ CreateInfo.visualBits = pMural->CreateInfo.requestedVisualBits;
+ CreateInfo.externalID = pMural->CreateInfo.externalID;
+ crVBoxServerSaveCreateInfoCB(key, &CreateInfo, data2);
+}
+
static void crVBoxServerSaveCreateInfoFromCtxInfoCB(unsigned long key, void *data1, void *data2)
{
CRContextInfo *pContextInfo = (CRContextInfo *)data1;
- CRCreateInfo_t CreateInfo = pContextInfo->CreateInfo;
+ CRCreateInfo_t CreateInfo;
+ CreateInfo.pszDpyName = pContextInfo->CreateInfo.pszDpyName;
+ CreateInfo.visualBits = pContextInfo->CreateInfo.requestedVisualBits;
/* saved state contains internal id */
CreateInfo.externalID = pContextInfo->pContext->id;
crVBoxServerSaveCreateInfoCB(key, &CreateInfo, data2);
@@ -739,40 +929,672 @@ static void crVBoxServerSyncTextureCB(unsigned long key, void *data1, void *data
crStateTextureObjectDiff(pContext, NULL, NULL, pTexture, GL_TRUE);
}
+typedef struct CRVBOX_SAVE_STATE_GLOBAL
+{
+ /* context id -> mural association
+ * on context data save, each context will be made current with the corresponding mural from this table
+ * thus saving the mural front & back buffer data */
+ CRHashTable *contextMuralTable;
+ /* mural id -> context info
+ * for murals that do not have associated context in contextMuralTable
+ * we still need to save*/
+ CRHashTable *additionalMuralContextTable;
+
+ PSSMHANDLE pSSM;
+
+ int rc;
+} CRVBOX_SAVE_STATE_GLOBAL, *PCRVBOX_SAVE_STATE_GLOBAL;
+
+
+typedef struct CRVBOX_CTXWND_CTXWALKER_CB
+{
+ PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
+ CRHashTable *usedMuralTable;
+ GLuint cAdditionalMurals;
+} CRVBOX_CTXWND_CTXWALKER_CB, *PCRVBOX_CTXWND_CTXWALKER_CB;
+
+static void crVBoxServerBuildAdditionalWindowContextMapCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo * pMural = (CRMuralInfo *) data1;
+ PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+ CRContextInfo *pContextInfo = NULL;
+
+ if (!pMural->CreateInfo.externalID)
+ {
+ CRASSERT(!key);
+ return;
+ }
+
+ if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
+ {
+ Assert(crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
+ return;
+ }
+
+ Assert(!crHashtableGetDataKey(pData->pGlobal->contextMuralTable, pMural, NULL));
+
+ if (cr_server.MainContextInfo.CreateInfo.realVisualBits == pMural->CreateInfo.realVisualBits)
+ {
+ pContextInfo = &cr_server.MainContextInfo;
+ }
+ else
+ {
+ crWarning("different visual bits not implemented!");
+ pContextInfo = &cr_server.MainContextInfo;
+ }
+
+ crHashtableAdd(pData->pGlobal->additionalMuralContextTable, pMural->CreateInfo.externalID, pContextInfo);
+}
+
+
+typedef struct CRVBOX_CTXWND_WNDWALKER_CB
+{
+ PCRVBOX_SAVE_STATE_GLOBAL pGlobal;
+ CRHashTable *usedMuralTable;
+ CRContextInfo *pContextInfo;
+ CRMuralInfo * pMural;
+} CRVBOX_CTXWND_WNDWALKER_CB, *PCRVBOX_CTXWND_WNDWALKER_CB;
+
+static void crVBoxServerBuildContextWindowMapWindowWalkerCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo * pMural = (CRMuralInfo *) data1;
+ PCRVBOX_CTXWND_WNDWALKER_CB pData = (PCRVBOX_CTXWND_WNDWALKER_CB)data2;
+
+ Assert(pData->pMural != pMural);
+ Assert(pData->pContextInfo);
+
+ if (pData->pMural)
+ return;
+
+ if (!pMural->CreateInfo.externalID)
+ {
+ CRASSERT(!key);
+ return;
+ }
+
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pData->pContextInfo->pContext))
+ return;
+
+ if (crHashtableSearch(pData->usedMuralTable, pMural->CreateInfo.externalID))
+ return;
+
+ CRASSERT(pMural->CreateInfo.realVisualBits == pData->pContextInfo->CreateInfo.realVisualBits);
+ pData->pMural = pMural;
+}
+
+static void crVBoxServerBuildContextUsedWindowMapCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo *pContextInfo = (CRContextInfo *)data1;
+ PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+
+ if (!pContextInfo->currentMural)
+ return;
+
+ crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pContextInfo->currentMural);
+ crHashtableAdd(pData->usedMuralTable, pContextInfo->currentMural->CreateInfo.externalID, pContextInfo->currentMural);
+}
+
+CRMuralInfo * crServerGetDummyMural(GLint visualBits)
+{
+ CRMuralInfo * pMural = (CRMuralInfo *)crHashtableSearch(cr_server.dummyMuralTable, visualBits);
+ if (!pMural)
+ {
+ GLint id;
+ pMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
+ if (!pMural)
+ {
+ crWarning("crCalloc failed!");
+ return NULL;
+ }
+ id = crServerMuralInit(pMural, GL_FALSE, visualBits, 0);
+ if (id < 0)
+ {
+ crWarning("crServerMuralInit failed!");
+ crFree(pMural);
+ return NULL;
+ }
+
+ crHashtableAdd(cr_server.dummyMuralTable, visualBits, pMural);
+ }
+
+ return pMural;
+}
+
+static void crVBoxServerBuildContextUnusedWindowMapCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo *pContextInfo = (CRContextInfo *)data1;
+ PCRVBOX_CTXWND_CTXWALKER_CB pData = (PCRVBOX_CTXWND_CTXWALKER_CB)data2;
+ CRMuralInfo * pMural = NULL;
+
+ if (pContextInfo->currentMural)
+ return;
+
+ Assert(crHashtableNumElements(pData->pGlobal->contextMuralTable) <= crHashtableNumElements(cr_server.muralTable) - 1);
+ if (crHashtableNumElements(pData->pGlobal->contextMuralTable) < crHashtableNumElements(cr_server.muralTable) - 1)
+ {
+ CRVBOX_CTXWND_WNDWALKER_CB MuralData;
+ MuralData.pGlobal = pData->pGlobal;
+ MuralData.usedMuralTable = pData->usedMuralTable;
+ MuralData.pContextInfo = pContextInfo;
+ MuralData.pMural = NULL;
+
+ crHashtableWalk(cr_server.muralTable, crVBoxServerBuildContextWindowMapWindowWalkerCB, &MuralData);
+
+ pMural = MuralData.pMural;
+
+ }
+
+ if (!pMural)
+ {
+ pMural = crServerGetDummyMural(pContextInfo->CreateInfo.realVisualBits);
+ if (!pMural)
+ {
+ crWarning("crServerGetDummyMural failed");
+ return;
+ }
+ }
+ else
+ {
+ crHashtableAdd(pData->usedMuralTable, pMural->CreateInfo.externalID, pMural);
+ ++pData->cAdditionalMurals;
+ }
+
+ crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pMural);
+}
+
+static void crVBoxServerBuildSaveStateGlobal(PCRVBOX_SAVE_STATE_GLOBAL pGlobal)
+{
+ CRVBOX_CTXWND_CTXWALKER_CB Data;
+ GLuint cMurals;
+ pGlobal->contextMuralTable = crAllocHashtable();
+ pGlobal->additionalMuralContextTable = crAllocHashtable();
+ /* 1. go through all contexts and match all having currentMural set */
+ Data.pGlobal = pGlobal;
+ Data.usedMuralTable = crAllocHashtable();
+ Data.cAdditionalMurals = 0;
+ crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUsedWindowMapCB, &Data);
+
+ cMurals = crHashtableNumElements(pGlobal->contextMuralTable);
+ CRASSERT(cMurals <= crHashtableNumElements(cr_server.contextTable));
+ CRASSERT(cMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
+ CRASSERT(cMurals == crHashtableNumElements(Data.usedMuralTable));
+ if (cMurals < crHashtableNumElements(cr_server.contextTable))
+ {
+ Data.cAdditionalMurals = 0;
+ crHashtableWalk(cr_server.contextTable, crVBoxServerBuildContextUnusedWindowMapCB, &Data);
+ }
+
+ CRASSERT(crHashtableNumElements(pGlobal->contextMuralTable) == crHashtableNumElements(cr_server.contextTable));
+ CRASSERT(cMurals + Data.cAdditionalMurals <= crHashtableNumElements(cr_server.muralTable) - 1);
+ if (cMurals + Data.cAdditionalMurals < crHashtableNumElements(cr_server.muralTable) - 1)
+ {
+ crHashtableWalk(cr_server.muralTable, crVBoxServerBuildAdditionalWindowContextMapCB, &Data);
+ CRASSERT(cMurals + Data.cAdditionalMurals + crHashtableNumElements(pGlobal->additionalMuralContextTable) == crHashtableNumElements(cr_server.muralTable) - 1);
+ }
+
+ crFreeHashtable(Data.usedMuralTable, NULL);
+}
+
+static void crVBoxServerFBImageDataTerm(CRFBData *pData)
+{
+ GLuint i;
+ for (i = 0; i < pData->cElements; ++i)
+ {
+ CRFBDataElement * pEl = &pData->aElements[i];
+ if (pEl->pvData)
+ {
+ crFree(pEl->pvData);
+ /* sanity */
+ pEl->pvData = NULL;
+ }
+ }
+ pData->cElements = 0;
+}
+
+static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInfo, CRMuralInfo *pMural, GLboolean fWrite, uint32_t version, GLuint overrideWidth, GLuint overrideHeight)
+{
+ CRContext *pContext;
+ GLuint i;
+ GLfloat *pF;
+ CRFBDataElement *pEl;
+ GLuint width;
+ GLuint height;
+
+ crMemset(pData, 0, sizeof (*pData));
+
+ pContext = pCtxInfo->pContext;
+
+ /* the version should be always actual when we do reads,
+ * i.e. it could differ on writes when snapshot is getting loaded */
+ CRASSERT(fWrite || version == SHCROGL_SSM_VERSION);
+
+ width = overrideWidth ? overrideWidth : pMural->width;
+ height = overrideHeight ? overrideHeight : pMural->height;
+
+ if (!width || !height)
+ return VINF_SUCCESS;
+
+ if (pMural)
+ {
+ if (fWrite)
+ {
+ if (!pContext->framebufferobject.drawFB)
+ pData->idOverrrideFBO = CR_SERVER_FBO_FOR_IDX(pMural, pMural->iCurDrawBuffer);
+ }
+ else
+ {
+ if (!pContext->framebufferobject.readFB)
+ pData->idOverrrideFBO = CR_SERVER_FBO_FOR_IDX(pMural, pMural->iCurReadBuffer);
+ }
+ }
+ pData->cElements = 0;
+
+ pEl = &pData->aElements[pData->cElements];
+ pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+ pEl->enmBuffer = pData->aElements[1].idFBO ? GL_COLOR_ATTACHMENT0 : GL_FRONT;
+ pEl->posX = 0;
+ pEl->posY = 0;
+ pEl->width = width;
+ pEl->height = height;
+ pEl->enmFormat = GL_RGBA;
+ pEl->enmType = GL_UNSIGNED_BYTE;
+ pEl->cbData = width * height * 4;
+ pEl->pvData = crCalloc(pEl->cbData);
+ if (!pEl->pvData)
+ {
+ crVBoxServerFBImageDataTerm(pData);
+ crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
+ return VERR_NO_MEMORY;
+ }
+ ++pData->cElements;
+
+ /* there is a lot of code that assumes we have double buffering, just assert here to print a warning in the log
+ * so that we know that something irregular is going on */
+ CRASSERT(pCtxInfo->CreateInfo.requestedVisualBits & CR_DOUBLE_BIT);
+ if ((pCtxInfo->CreateInfo.requestedVisualBits & CR_DOUBLE_BIT)
+ || version < SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL /* <- older version had a typo which lead to back always being used,
+ * no matter what the visual bits are */
+ )
+ {
+ pEl = &pData->aElements[pData->cElements];
+ pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_BB_IDX(pMural)] : 0;
+ pEl->enmBuffer = pData->aElements[1].idFBO ? GL_COLOR_ATTACHMENT0 : GL_BACK;
+ pEl->posX = 0;
+ pEl->posY = 0;
+ pEl->width = width;
+ pEl->height = height;
+ pEl->enmFormat = GL_RGBA;
+ pEl->enmType = GL_UNSIGNED_BYTE;
+ pEl->cbData = width * height * 4;
+ pEl->pvData = crCalloc(pEl->cbData);
+ if (!pEl->pvData)
+ {
+ crVBoxServerFBImageDataTerm(pData);
+ crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
+ return VERR_NO_MEMORY;
+ }
+ ++pData->cElements;
+ }
+
+ if (version < SHCROGL_SSM_VERSION_WITH_SAVED_DEPTH_STENCIL_BUFFER)
+ return VINF_SUCCESS;
+
+
+ if (version < SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL)
+ {
+/* if (pCtxInfo->CreateInfo.requestedVisualBits & CR_DEPTH_BIT) */ /* <- older version had a typo which lead to back always being used,
+ * no matter what the visual bits are */
+ {
+ AssertCompile(sizeof (GLfloat) == 4);
+ pEl = &pData->aElements[pData->cElements];
+ pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+ pEl->enmBuffer = 0; /* we do not care */
+ pEl->posX = 0;
+ pEl->posY = 0;
+ pEl->width = width;
+ pEl->height = height;
+ pEl->enmFormat = GL_DEPTH_COMPONENT;
+ pEl->enmType = GL_FLOAT;
+ pEl->cbData = width * height * 4;
+ pEl->pvData = crCalloc(pEl->cbData);
+ if (!pEl->pvData)
+ {
+ crVBoxServerFBImageDataTerm(pData);
+ crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
+ return VERR_NO_MEMORY;
+ }
+
+ /* init to default depth value, just in case */
+ pF = (GLfloat*)pEl->pvData;
+ for (i = 0; i < width * height; ++i)
+ {
+ pF[i] = 1.;
+ }
+ ++pData->cElements;
+ }
+
+ /* if (pCtxInfo->CreateInfo.requestedVisualBits & CR_STENCIL_BIT) */ /* <- older version had a typo which lead to back always being used,
+ * no matter what the visual bits are */
+ {
+ AssertCompile(sizeof (GLuint) == 4);
+ pEl = &pData->aElements[pData->cElements];
+ pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+ pEl->enmBuffer = 0; /* we do not care */
+ pEl->posX = 0;
+ pEl->posY = 0;
+ pEl->width = width;
+ pEl->height = height;
+ pEl->enmFormat = GL_STENCIL_INDEX;
+ pEl->enmType = GL_UNSIGNED_INT;
+ pEl->cbData = width * height * 4;
+ pEl->pvData = crCalloc(pEl->cbData);
+ if (!pEl->pvData)
+ {
+ crVBoxServerFBImageDataTerm(pData);
+ crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
+ return VERR_NO_MEMORY;
+ }
+ ++pData->cElements;
+ }
+ return VINF_SUCCESS;
+ }
+
+ if ((pCtxInfo->CreateInfo.requestedVisualBits & CR_STENCIL_BIT)
+ || (pCtxInfo->CreateInfo.requestedVisualBits & CR_DEPTH_BIT))
+ {
+ pEl = &pData->aElements[pData->cElements];
+ pEl->idFBO = pMural && pMural->fRedirected ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
+ pEl->enmBuffer = 0; /* we do not care */
+ pEl->posX = 0;
+ pEl->posY = 0;
+ pEl->width = width;
+ pEl->height = height;
+ pEl->enmFormat = GL_DEPTH_STENCIL;
+ pEl->enmType = GL_UNSIGNED_INT_24_8;
+ pEl->cbData = width * height * 4;
+ pEl->pvData = crCalloc(pEl->cbData);
+ if (!pEl->pvData)
+ {
+ crVBoxServerFBImageDataTerm(pData);
+ crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
+ return VERR_NO_MEMORY;
+ }
+ ++pData->cElements;
+ }
+ return VINF_SUCCESS;
+}
+
+static int crVBoxServerFBImageDataInit(CRFBData *pData, CRContextInfo *pCtxInfo, CRMuralInfo *pMural, GLboolean fWrite)
+{
+ return crVBoxServerFBImageDataInitEx(pData, pCtxInfo, pMural, fWrite, SHCROGL_SSM_VERSION, 0, 0);
+}
+
+static int crVBoxServerSaveFBImage(PSSMHANDLE pSSM)
+{
+ CRContextInfo *pCtxInfo;
+ CRContext *pContext;
+ CRMuralInfo *pMural;
+ int32_t rc;
+ GLuint i;
+ struct
+ {
+ CRFBData data;
+ CRFBDataElement buffer[3]; /* CRFBData::aElements[1] + buffer[3] gives 4: back, front, depth and stencil */
+ } Data;
+
+ Assert(sizeof (Data) >= RT_OFFSETOF(CRFBData, aElements[4]));
+
+ pCtxInfo = cr_server.currentCtxInfo;
+ pContext = pCtxInfo->pContext;
+ pMural = pCtxInfo->currentMural;
+
+ rc = crVBoxServerFBImageDataInit(&Data.data, pCtxInfo, pMural, GL_FALSE);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crVBoxServerFBImageDataInit failed rc %d", rc);
+ return rc;
+ }
+
+ rc = crStateAcquireFBImage(pContext, &Data.data);
+ AssertRCReturn(rc, rc);
+
+ for (i = 0; i < Data.data.cElements; ++i)
+ {
+ CRFBDataElement * pEl = &Data.data.aElements[i];
+ rc = SSMR3PutMem(pSSM, pEl->pvData, pEl->cbData);
+ AssertRCReturn(rc, rc);
+ }
+
+ crVBoxServerFBImageDataTerm(&Data.data);
+
+ return VINF_SUCCESS;
+}
+
+#define CRSERVER_ASSERTRC_RETURN_VOID(_rc) do { \
+ if(!RT_SUCCESS((_rc))) { \
+ AssertFailed(); \
+ return; \
+ } \
+ } while (0)
+
+static void crVBoxServerSaveAdditionalMuralsCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo *pContextInfo = (CRContextInfo *) data1;
+ PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
+ CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
+ PSSMHANDLE pSSM = pData->pSSM;
+ CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
+ CRMuralInfo *pInitialCurMural = pContextInfo->currentMural;
+
+ crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
+
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ pData->rc = SSMR3PutMem(pSSM, &pContextInfo->CreateInfo.externalID, sizeof(pContextInfo->CreateInfo.externalID));
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ crServerPerformMakeCurrent(pMural, pContextInfo);
+
+ pData->rc = crVBoxServerSaveFBImage(pSSM);
+
+ /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
+ crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
+ pContextInfo->currentMural = pInitialCurMural;
+
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+}
+
static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
{
CRContextInfo *pContextInfo = (CRContextInfo *) data1;
CRContext *pContext = pContextInfo->pContext;
- PSSMHANDLE pSSM = (PSSMHANDLE) data2;
- int32_t rc;
+ PCRVBOX_SAVE_STATE_GLOBAL pData = (PCRVBOX_SAVE_STATE_GLOBAL)data2;
+ PSSMHANDLE pSSM = pData->pSSM;
+ CRMuralInfo *pMural = (CRMuralInfo*)crHashtableSearch(pData->contextMuralTable, key);
+ CRMuralInfo *pContextCurrentMural = pContextInfo->currentMural;
+ const int32_t i32Dummy = 0;
+
+ AssertCompile(sizeof (i32Dummy) == sizeof (pMural->CreateInfo.externalID));
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
CRASSERT(pContext && pSSM);
+ CRASSERT(pMural);
+ CRASSERT(pMural->CreateInfo.externalID);
/* We could have skipped saving the key and use similar callback to load context states back,
* but there's no guarantee we'd traverse hashtable in same order after loading.
*/
- rc = SSMR3PutMem(pSSM, &key, sizeof(key));
- CRASSERT(rc == VINF_SUCCESS);
+ pData->rc = SSMR3PutMem(pSSM, &key, sizeof(key));
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+#ifdef DEBUG_misha
+ {
+ unsigned long id;
+ if (!crHashtableGetDataKey(cr_server.contextTable, pContextInfo, &id))
+ crWarning("No client id for server ctx %d", pContextInfo->CreateInfo.externalID);
+ else
+ CRASSERT(id == key);
+ }
+#endif
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
- if (cr_server.curClient)
+ if (pContextInfo->currentMural
+ || crHashtableSearch(cr_server.muralTable, pMural->CreateInfo.externalID) /* <- this is not a dummy mural */
+ )
+ {
+ CRASSERT(pMural->CreateInfo.externalID);
+ CRASSERT(!crHashtableSearch(cr_server.dummyMuralTable, pMural->CreateInfo.externalID));
+ pData->rc = SSMR3PutMem(pSSM, &pMural->CreateInfo.externalID, sizeof(pMural->CreateInfo.externalID));
+ }
+ else
+ {
+ /* this is a dummy mural */
+ CRASSERT(!pMural->width);
+ CRASSERT(!pMural->height);
+ CRASSERT(crHashtableSearch(cr_server.dummyMuralTable, pMural->CreateInfo.externalID));
+ pData->rc = SSMR3PutMem(pSSM, &i32Dummy, sizeof(pMural->CreateInfo.externalID));
+ }
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ CRASSERT(CR_STATE_SHAREDOBJ_USAGE_IS_SET(pMural, pContext));
+ CRASSERT(pContextInfo->currentMural == pMural || !pContextInfo->currentMural);
+ CRASSERT(cr_server.curClient);
+
+ crServerPerformMakeCurrent(pMural, pContextInfo);
+#endif
+
+ pData->rc = crStateSaveContext(pContext, pSSM);
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ pData->rc = crVBoxServerSaveFBImage(pSSM);
+ CRSERVER_ASSERTRC_RETURN_VOID(pData->rc);
+
+ /* restore the initial current mural */
+ pContextInfo->currentMural = pContextCurrentMural;
+}
+
+#if 0
+typedef struct CR_SERVER_CHECK_BUFFERS
+{
+ CRBufferObject *obj;
+ CRContext *ctx;
+}CR_SERVER_CHECK_BUFFERS, *PCR_SERVER_CHECK_BUFFERS;
+
+static void crVBoxServerCheckConsistencyContextBuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo* pContextInfo = (CRContextInfo*)data1;
+ CRContext *ctx = pContextInfo->pContext;
+ PCR_SERVER_CHECK_BUFFERS pBuffers = (PCR_SERVER_CHECK_BUFFERS)data2;
+ CRBufferObject *obj = pBuffers->obj;
+ CRBufferObjectState *b = &(ctx->bufferobject);
+ int j, k;
+
+ if (obj == b->arrayBuffer)
+ {
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
+ }
+ if (obj == b->elementsBuffer)
+ {
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
+ }
+#ifdef CR_ARB_pixel_buffer_object
+ if (obj == b->packBuffer)
+ {
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
+ }
+ if (obj == b->unpackBuffer)
+ {
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
+ }
+#endif
+
+#ifdef CR_ARB_vertex_buffer_object
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
{
- unsigned long id;
- if (!crHashtableGetDataKey(cr_server.contextTable, pContextInfo, &id))
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, &ctx->client.array);
+ if (obj == cp->buffer)
{
- crWarning("No client id for server ctx %d", pContext->id);
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
}
- else
+ }
+
+ for (k=0; k<ctx->client.vertexArrayStackDepth; ++k)
+ {
+ CRVertexArrays *pArray = &ctx->client.vertexArrayStack[k];
+ for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
{
- crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, id);
+ CRClientPointer *cp = crStateGetClientPointerByIndex(j, pArray);
+ if (obj == cp->buffer)
+ {
+ Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
+ pBuffers->ctx = ctx;
+ }
}
}
#endif
+}
- rc = crStateSaveContext(pContext, pSSM);
- CRASSERT(rc == VINF_SUCCESS);
+static void crVBoxServerCheckConsistencyBuffersCB(unsigned long key, void *data1, void *data2)
+{
+ CRBufferObject *obj = (CRBufferObject *)data1;
+ CR_SERVER_CHECK_BUFFERS Buffers = {0};
+ Buffers.obj = obj;
+ crHashtableWalk(cr_server.contextTable, crVBoxServerCheckConsistencyContextBuffersCB, (void*)&Buffers);
}
+//static void crVBoxServerCheckConsistency2CB(unsigned long key, void *data1, void *data2)
+//{
+// CRContextInfo* pContextInfo1 = (CRContextInfo*)data1;
+// CRContextInfo* pContextInfo2 = (CRContextInfo*)data2;
+//
+// CRASSERT(pContextInfo1->pContext);
+// CRASSERT(pContextInfo2->pContext);
+//
+// if (pContextInfo1 == pContextInfo2)
+// {
+// CRASSERT(pContextInfo1->pContext == pContextInfo2->pContext);
+// return;
+// }
+//
+// CRASSERT(pContextInfo1->pContext != pContextInfo2->pContext);
+// CRASSERT(pContextInfo1->pContext->shared);
+// CRASSERT(pContextInfo2->pContext->shared);
+// CRASSERT(pContextInfo1->pContext->shared == pContextInfo2->pContext->shared);
+// if (pContextInfo1->pContext->shared != pContextInfo2->pContext->shared)
+// return;
+//
+// crHashtableWalk(pContextInfo1->pContext->shared->buffersTable, crVBoxServerCheckConsistencyBuffersCB, pContextInfo2);
+//}
+static void crVBoxServerCheckSharedCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo* pContextInfo = (CRContextInfo*)data1;
+ void **ppShared = (void**)data2;
+ if (!*ppShared)
+ *ppShared = pContextInfo->pContext->shared;
+ else
+ Assert(pContextInfo->pContext->shared == *ppShared);
+}
+
+static void crVBoxServerCheckConsistency()
+{
+ CRSharedState *pShared = NULL;
+ crHashtableWalk(cr_server.contextTable, crVBoxServerCheckSharedCB, (void*)&pShared);
+ Assert(pShared);
+ if (pShared)
+ {
+ crHashtableWalk(pShared->buffersTable, crVBoxServerCheckConsistencyBuffersCB, NULL);
+ }
+}
+#endif
+
static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
@@ -781,8 +1603,18 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
uint32_t ui32;
GLboolean b;
unsigned long key;
+ GLenum err;
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
- unsigned long ctxID=-1, winID=-1;
+ CRClient *curClient;
+ CRMuralInfo *curMural = NULL;
+ CRContextInfo *curCtxInfo = NULL;
+#endif
+ CRVBOX_SAVE_STATE_GLOBAL Data;
+
+ crMemset(&Data, 0, sizeof (Data));
+
+#if 0
+ crVBoxServerCheckConsistency();
#endif
/* We shouldn't be called if there's no clients at all*/
@@ -811,6 +1643,14 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
return VINF_SUCCESS;
}
+#ifdef DEBUG_misha
+#define CR_DBG_STR_STATE_SAVE_START "VBox.Cr.StateSaveStart"
+#define CR_DBG_STR_STATE_SAVE_STOP "VBox.Cr.StateSaveStop"
+
+ if (cr_server.head_spu->dispatch_table.StringMarkerGREMEDY)
+ cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_SAVE_START), CR_DBG_STR_STATE_SAVE_START);
+#endif
+
/* Save rendering contexts creation info */
ui32 = crHashtableNumElements(cr_server.contextTable);
rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
@@ -818,50 +1658,71 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
crHashtableWalk(cr_server.contextTable, crVBoxServerSaveCreateInfoFromCtxInfoCB, pSSM);
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ curClient = cr_server.curClient;
/* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
- if (cr_server.curClient)
+ if (curClient)
{
- ctxID = cr_server.curClient->currentContextNumber;
- winID = cr_server.curClient->currentWindow;
+ curCtxInfo = cr_server.curClient->currentCtxInfo;
+ curMural = cr_server.curClient->currentMural;
}
-#endif
-
- /* Save contexts state tracker data */
- /* @todo For now just some blind data dumps,
- * but I've a feeling those should be saved/restored in a very strict sequence to
- * allow diff_api to work correctly.
- * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
- */
- crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
-
-#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
- /* Restore original win and ctx IDs*/
- if (cr_server.curClient)
+ else if (cr_server.numClients)
{
- crServerDispatchMakeCurrent(winID, 0, ctxID);
+ cr_server.curClient = cr_server.clients[0];
}
#endif
+ /* first save windows info */
/* Save windows creation info */
- ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
- rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
+ ui32 = crHashtableNumElements(cr_server.muralTable);
+ /* There should be default mural always */
+ CRASSERT(ui32>=1);
+ rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
AssertRCReturn(rc, rc);
- crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
+ crHashtableWalk(cr_server.muralTable, crVBoxServerSaveCreateInfoFromMuralInfoCB, pSSM);
/* Save cr_server.muralTable
* @todo we don't need it all, just geometry info actually
*/
- ui32 = crHashtableNumElements(cr_server.muralTable);
- /* There should be default mural always */
- CRASSERT(ui32>=1);
rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
AssertRCReturn(rc, rc);
crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
- /* Save starting free context and window IDs */
- rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
+ /* we need to save front & backbuffer data for each mural first create a context -> mural association */
+ crVBoxServerBuildSaveStateGlobal(&Data);
+
+ rc = crStateSaveGlobals(pSSM);
AssertRCReturn(rc, rc);
+ Data.pSSM = pSSM;
+ /* Save contexts state tracker data */
+ /* @todo For now just some blind data dumps,
+ * but I've a feeling those should be saved/restored in a very strict sequence to
+ * allow diff_api to work correctly.
+ * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
+ */
+ crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, &Data);
+ AssertRCReturn(Data.rc, Data.rc);
+
+ ui32 = crHashtableNumElements(Data.additionalMuralContextTable);
+ rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
+ AssertRCReturn(rc, rc);
+
+ crHashtableWalk(Data.additionalMuralContextTable, crVBoxServerSaveAdditionalMuralsCB, &Data);
+ AssertRCReturn(Data.rc, Data.rc);
+
+#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
+ cr_server.curClient = curClient;
+ /* Restore original win and ctx IDs*/
+ if (curClient && curMural && curCtxInfo)
+ {
+ crServerPerformMakeCurrent(curMural, curCtxInfo);
+ }
+ else
+ {
+ cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
+ }
+#endif
+
/* Save clients info */
for (i = 0; i < cr_server.numClients; i++)
{
@@ -881,7 +1742,7 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
AssertRCReturn(rc, rc);
- if (pClient->currentCtxInfo && pClient->currentCtxInfo->pContext && pClient->currentContextNumber>=0)
+ if (pClient->currentCtxInfo && pClient->currentCtxInfo->pContext && pClient->currentContextNumber > 0)
{
b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtxInfo, &key);
CRASSERT(b);
@@ -889,7 +1750,7 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
AssertRCReturn(rc, rc);
}
- if (pClient->currentMural && pClient->currentWindow>=0)
+ if (pClient->currentMural && pClient->currentWindow > 0)
{
b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
CRASSERT(b);
@@ -899,8 +1760,21 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
}
}
+ rc = CrPMgrSaveState(pSSM);
+ AssertRCReturn(rc, rc);
+
+ /* all context gl error states should have now be synced with chromium erro states,
+ * reset the error if any */
+ while ((err = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR)
+ crWarning("crServer: glGetError %d after saving snapshot", err);
+
cr_server.bIsInSavingState = GL_FALSE;
+#ifdef DEBUG_misha
+ if (cr_server.head_spu->dispatch_table.StringMarkerGREMEDY)
+ cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_SAVE_STOP), CR_DBG_STR_STATE_SAVE_STOP);
+#endif
+
return VINF_SUCCESS;
}
@@ -912,11 +1786,527 @@ static DECLCALLBACK(CRContext*) crVBoxServerGetContextCB(void* pvData)
return pContextInfo->pContext;
}
+typedef struct CR_SERVER_LOADSTATE_READER
+{
+ PSSMHANDLE pSSM;
+ uint32_t cbBuffer;
+ uint32_t cbData;
+ uint32_t offData;
+ uint8_t *pu8Buffer;
+} CR_SERVER_LOADSTATE_READER;
+
+static void crServerLsrInit(CR_SERVER_LOADSTATE_READER *pReader, PSSMHANDLE pSSM)
+{
+ memset(pReader, 0, sizeof (*pReader));
+ pReader->pSSM = pSSM;
+}
+
+static void crServerLsrTerm(CR_SERVER_LOADSTATE_READER *pReader)
+{
+ if (pReader->pu8Buffer)
+ RTMemFree(pReader->pu8Buffer);
+
+ /* sanity */
+ memset(pReader, 0, sizeof (*pReader));
+}
+
+static int crServerLsrDataGetMem(CR_SERVER_LOADSTATE_READER *pReader, void *pvBuffer, uint32_t cbBuffer)
+{
+ int rc = VINF_SUCCESS;
+ uint32_t cbRemaining = cbBuffer;
+ if (pReader->cbData)
+ {
+ uint8_t cbData = RT_MIN(pReader->cbData, cbBuffer);
+ memcpy(pvBuffer, pReader->pu8Buffer + pReader->offData, cbData);
+ pReader->cbData -= cbData;
+ pReader->offData += cbData;
+
+ cbRemaining -= cbData;
+ pvBuffer = ((uint8_t*)pvBuffer) + cbData;
+ }
+
+ if (cbRemaining)
+ {
+ rc = SSMR3GetMem(pReader->pSSM, pvBuffer, cbRemaining);
+ AssertRC(rc);
+ }
+
+ return rc;
+}
+
+static int crServerLsrDataGetU32(CR_SERVER_LOADSTATE_READER *pReader, uint32_t *pu32)
+{
+ return crServerLsrDataGetMem(pReader, pu32, sizeof (*pu32));
+}
+
+static int crServerLsrDataPutMem(CR_SERVER_LOADSTATE_READER *pReader, void *pvBuffer, uint32_t cbBuffer)
+{
+ if (!pReader->cbData && pReader->cbBuffer >= cbBuffer)
+ {
+ pReader->offData = 0;
+ pReader->cbData = cbBuffer;
+ memcpy(pReader->pu8Buffer, pvBuffer, cbBuffer);
+ }
+ else if (pReader->offData >= cbBuffer)
+ {
+ pReader->offData -= cbBuffer;
+ pReader->cbData += cbBuffer;
+ memcpy(pReader->pu8Buffer + pReader->offData, pvBuffer, cbBuffer);
+ }
+ else
+ {
+ uint8_t *pu8Buffer = pReader->pu8Buffer;
+
+ pReader->pu8Buffer = (uint8_t*)RTMemAlloc(cbBuffer + pReader->cbData);
+ if (!pReader->pu8Buffer)
+ {
+ crWarning("failed to allocate mem %d", cbBuffer + pReader->cbData);
+ return VERR_NO_MEMORY;
+ }
+
+ memcpy(pReader->pu8Buffer, pvBuffer, cbBuffer);
+ if (pu8Buffer)
+ {
+ memcpy(pReader->pu8Buffer + cbBuffer, pu8Buffer + pReader->offData, pReader->cbData);
+ RTMemFree(pu8Buffer);
+ }
+ else
+ {
+ Assert(!pReader->cbData);
+ }
+ pReader->offData = 0;
+ pReader->cbData += cbBuffer;
+ }
+
+ return VINF_SUCCESS;
+}
+
+/* data to be skipped */
+
+typedef struct CR_SERVER_BUGGY_MURAL_DATA_2
+{
+ void*ListHead_pNext;
+ void*ListHead_pPrev;
+ uint32_t cEntries;
+} CR_SERVER_BUGGY_MURAL_DATA_2;
+typedef struct CR_SERVER_BUGGY_MURAL_DATA_1
+{
+ /* VBOXVR_COMPOSITOR_ENTRY Ce; */
+ void*Ce_Node_pNext;
+ void*Ce_Node_pPrev;
+ CR_SERVER_BUGGY_MURAL_DATA_2 Vr;
+ /* VBOXVR_TEXTURE Tex; */
+ uint32_t Tex_width;
+ uint32_t Tex_height;
+ uint32_t Tex_target;
+ uint32_t Tex_hwid;
+ /* RTPOINT Pos; */
+ uint32_t Pos_x;
+ uint32_t Pos_y;
+ uint32_t fChanged;
+ uint32_t cRects;
+ void* paSrcRects;
+ void* paDstRects;
+} CR_SERVER_BUGGY_MURAL_DATA_1;
+
+typedef struct CR_SERVER_BUGGY_MURAL_DATA_4
+{
+ uint32_t u32Magic;
+ int32_t cLockers;
+ RTNATIVETHREAD NativeThreadOwner;
+ int32_t cNestings;
+ uint32_t fFlags;
+ void* EventSem;
+ R3R0PTRTYPE(PRTLOCKVALRECEXCL) pValidatorRec;
+ RTHCPTR Alignment;
+} CR_SERVER_BUGGY_MURAL_DATA_4;
+
+typedef struct CR_SERVER_BUGGY_MURAL_DATA_3
+{
+ void*Compositor_List_pNext;
+ void*Compositor_List_pPrev;
+ void*Compositor_pfnEntryRemoved;
+ float StretchX;
+ float StretchY;
+ uint32_t cRects;
+ uint32_t cRectsBuffer;
+ void*paSrcRects;
+ void*paDstRects;
+ CR_SERVER_BUGGY_MURAL_DATA_4 CritSect;
+} CR_SERVER_BUGGY_MURAL_DATA_3;
+
+typedef struct CR_SERVER_BUGGY_MURAL_DATA
+{
+ uint8_t fRootVrOn;
+ CR_SERVER_BUGGY_MURAL_DATA_1 RootVrCEntry;
+ CR_SERVER_BUGGY_MURAL_DATA_3 RootVrCompositor;
+} CR_SERVER_BUGGY_MURAL_DATA;
+
+AssertCompile(sizeof (CR_SERVER_BUGGY_MURAL_DATA) < sizeof (CRClient));
+
+static int32_t crVBoxServerLoadMurals(CR_SERVER_LOADSTATE_READER *pReader, uint32_t version)
+{
+ unsigned long key;
+ uint32_t ui, uiNumElems;
+ bool fBuggyMuralData = false;
+ /* Load windows */
+ int32_t rc = crServerLsrDataGetU32(pReader, &uiNumElems);
+ AssertRCReturn(rc, rc);
+ for (ui=0; ui<uiNumElems; ++ui)
+ {
+ CRCreateInfo_t createInfo;
+ char psz[200];
+ GLint winID;
+ unsigned long key;
+
+ rc = crServerLsrDataGetMem(pReader, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+ rc = crServerLsrDataGetMem(pReader, &createInfo, sizeof(createInfo));
+ AssertRCReturn(rc, rc);
+
+ CRASSERT(!pReader->cbData);
+
+ if (createInfo.pszDpyName)
+ {
+ rc = SSMR3GetStrZEx(pReader->pSSM, psz, 200, NULL);
+ AssertRCReturn(rc, rc);
+ createInfo.pszDpyName = psz;
+ }
+
+ winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
+ CRASSERT((int64_t)winID == (int64_t)key);
+ }
+
+ /* Load cr_server.muralTable */
+ rc = SSMR3GetU32(pReader->pSSM, &uiNumElems);
+ AssertRCReturn(rc, rc);
+ for (ui=0; ui<uiNumElems; ++ui)
+ {
+ CRMuralInfo muralInfo;
+ CRMuralInfo *pActualMural = NULL;
+
+ rc = crServerLsrDataGetMem(pReader, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
+ rc = crServerLsrDataGetMem(pReader, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
+ AssertRCReturn(rc, rc);
+
+ if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
+ muralInfo.bFbDraw = GL_TRUE;
+
+ if (!ui && version == SHCROGL_SSM_VERSION_WITH_BUGGY_MURAL_INFO)
+ {
+ /* Lookahead buffer used to determine whether the data erroneously stored root visible regions data */
+ union
+ {
+ void * apv[1];
+ CR_SERVER_BUGGY_MURAL_DATA Data;
+ /* need to chak spuWindow, so taking the offset of filed following it*/
+ uint8_t au8[RT_OFFSETOF(CRMuralInfo, screenId)];
+ RTRECT aVisRects[sizeof (CR_SERVER_BUGGY_MURAL_DATA) / sizeof (RTRECT)];
+ } LaBuf;
+
+ do {
+ /* first value is bool (uint8_t) value followed by pointer-size-based alignment.
+ * the mural memory is zero-initialized initially, so we can be sure the padding is zeroed */
+ rc = crServerLsrDataGetMem(pReader, &LaBuf, sizeof (LaBuf));
+ AssertRCReturn(rc, rc);
+ if (LaBuf.apv[0] != NULL && LaBuf.apv[0] != ((void*)1))
+ break;
+
+ /* check that the pointers are either valid or NULL */
+ if(LaBuf.Data.RootVrCEntry.Ce_Node_pNext && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Ce_Node_pNext))
+ break;
+ if(LaBuf.Data.RootVrCEntry.Ce_Node_pPrev && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Ce_Node_pPrev))
+ break;
+ if(LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext))
+ break;
+ if(LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev))
+ break;
+
+ /* the entry can can be the only one within the (mural) compositor,
+ * so its compositor entry node can either contain NULL pNext and pPrev,
+ * or both of them pointing to compositor's list head */
+ if (LaBuf.Data.RootVrCEntry.Ce_Node_pNext != LaBuf.Data.RootVrCEntry.Ce_Node_pPrev)
+ break;
+
+ /* can either both or none be NULL */
+ if (!LaBuf.Data.RootVrCEntry.Ce_Node_pNext != !LaBuf.Data.RootVrCEntry.Ce_Node_pPrev)
+ break;
+
+ if (!LaBuf.Data.fRootVrOn)
+ {
+ if (LaBuf.Data.RootVrCEntry.Ce_Node_pNext || LaBuf.Data.RootVrCEntry.Ce_Node_pPrev)
+ break;
+
+ /* either non-initialized (zeroed) or empty list */
+ if (LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext != LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev)
+ break;
+
+ if (LaBuf.Data.RootVrCEntry.Vr.cEntries)
+ break;
+ }
+ else
+ {
+ /* the entry should be initialized */
+ if (!LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext)
+ break;
+ if (!LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev)
+ break;
+
+ if (LaBuf.Data.RootVrCEntry.Vr.cEntries)
+ {
+ /* entry should be in compositor list*/
+ if (LaBuf.Data.RootVrCEntry.Ce_Node_pPrev == NULL)
+ break;
+ CRASSERT(LaBuf.Data.RootVrCEntry.Ce_Node_pNext);
+ }
+ else
+ {
+ /* entry should NOT be in compositor list*/
+ if (LaBuf.Data.RootVrCEntry.Ce_Node_pPrev != NULL)
+ break;
+ CRASSERT(!LaBuf.Data.RootVrCEntry.Ce_Node_pNext);
+ }
+ }
+
+#if 0
+ if (muralInfo.pVisibleRects)
+ {
+ int j;
+ int cRects = RT_MIN(muralInfo.cVisibleRects, RT_ELEMENTS(LaBuf.aVisRects));
+ CRASSERT(cRects);
+ for (j = 0; j < cRects; ++j)
+ {
+ PRTRECT pRect = &LaBuf.aVisRects[j];
+ if (pRect->xLeft >= pRect->xRight)
+ break;
+ if (pRect->yTop >= pRect->yBottom)
+ break;
+ if (pRect->xLeft < 0 || pRect->xRight < 0
+ || pRect->yTop < 0 || pRect->yBottom < 0)
+ break;
+ if (pRect->xLeft > (GLint)muralInfo.width
+ || pRect->xRight > (GLint)muralInfo.width)
+ break;
+ if (pRect->yTop > (GLint)muralInfo.height
+ || pRect->yBottom > (GLint)muralInfo.height)
+ break;
+ }
+
+ if (j < cRects)
+ {
+ fBuggyMuralData = true;
+ break;
+ }
+ }
+
+ if (muralInfo.pVisibleRects)
+ {
+ /* @todo: do we actually need any further checks here? */
+ fBuggyMuralData = true;
+ break;
+ }
+
+ /* no visible regions*/
+
+ if (ui == uiNumElems - 1)
+ {
+ /* this is the last mural, next it goes idsPool, whose content can not match the above template again */
+ fBuggyMuralData = true;
+ break;
+ }
+
+ /* next it goes a next mural info */
+// if (!fExpectPtr)
+// {
+// CRMuralInfo *pNextSpuWindowInfoMural = (CRMuralInfo*)((void*)&LaBuf);
+// if (!pNextSpuWindowInfoMural->spuWindow)
+// fBuggyMuralData = true;
+//
+// break;
+// }
+#endif
+ /* fExpectPtr == true, the valid pointer values should not match possible mural width/height/position */
+ fBuggyMuralData = true;
+ break;
+
+ } while (0);
+
+ rc = crServerLsrDataPutMem(pReader, &LaBuf, sizeof (LaBuf));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (fBuggyMuralData)
+ {
+ CR_SERVER_BUGGY_MURAL_DATA Tmp;
+ rc = crServerLsrDataGetMem(pReader, &Tmp, sizeof (Tmp));
+ AssertRCReturn(rc, rc);
+ }
+
+ if (muralInfo.pVisibleRects)
+ {
+ muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
+ if (!muralInfo.pVisibleRects)
+ {
+ return VERR_NO_MEMORY;
+ }
+
+ rc = crServerLsrDataGetMem(pReader, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
+ AssertRCReturn(rc, rc);
+ }
+
+ pActualMural = (CRMuralInfo *)crHashtableSearch(cr_server.muralTable, key);
+ CRASSERT(pActualMural);
+
+ if (version >= SHCROGL_SSM_VERSION_WITH_WINDOW_CTX_USAGE)
+ {
+ rc = crServerLsrDataGetMem(pReader, pActualMural->ctxUsage, sizeof (pActualMural->ctxUsage));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
+
+ /* Restore windows geometry info */
+ crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
+ crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
+ /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
+ if (muralInfo.bReceivedRects)
+ {
+ crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
+ }
+ crServerDispatchWindowShow(key, muralInfo.bVisible);
+
+ if (muralInfo.pVisibleRects)
+ {
+ crFree(muralInfo.pVisibleRects);
+ }
+ }
+
+ CRASSERT(RT_SUCCESS(rc));
+ return VINF_SUCCESS;
+}
+
+static int crVBoxServerLoadFBImage(PSSMHANDLE pSSM, uint32_t version,
+ CRContextInfo* pContextInfo, CRMuralInfo *pMural)
+{
+ CRContext *pContext = pContextInfo->pContext;
+ int32_t rc = VINF_SUCCESS;
+ GLuint i;
+ /* can apply the data right away */
+ struct
+ {
+ CRFBData data;
+ CRFBDataElement buffer[3]; /* CRFBData::aElements[1] + buffer[3] gives 4: back, front, depth and stencil */
+ } Data;
+
+ Assert(sizeof (Data) >= RT_OFFSETOF(CRFBData, aElements[4]));
+
+ if (version >= SHCROGL_SSM_VERSION_WITH_SAVED_DEPTH_STENCIL_BUFFER)
+ {
+ if (!pMural->width || !pMural->height)
+ return VINF_SUCCESS;
+
+ rc = crVBoxServerFBImageDataInitEx(&Data.data, pContextInfo, pMural, GL_TRUE, version, 0, 0);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crVBoxServerFBImageDataInit failed rc %d", rc);
+ return rc;
+ }
+ }
+ else
+ {
+ GLint storedWidth, storedHeight;
+
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+ {
+ CRASSERT(cr_server.currentCtxInfo == pContextInfo);
+ CRASSERT(cr_server.currentMural == pMural);
+ storedWidth = pMural->width;
+ storedHeight = pMural->height;
+ }
+ else
+ {
+ storedWidth = pContext->buffer.storedWidth;
+ storedHeight = pContext->buffer.storedHeight;
+ }
+
+ if (!storedWidth || !storedHeight)
+ return VINF_SUCCESS;
+
+ rc = crVBoxServerFBImageDataInitEx(&Data.data, pContextInfo, pMural, GL_TRUE, version, storedWidth, storedHeight);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crVBoxServerFBImageDataInit failed rc %d", rc);
+ return rc;
+ }
+ }
+
+ CRASSERT(Data.data.cElements);
+
+ for (i = 0; i < Data.data.cElements; ++i)
+ {
+ CRFBDataElement * pEl = &Data.data.aElements[i];
+ rc = SSMR3GetMem(pSSM, pEl->pvData, pEl->cbData);
+ AssertRCReturn(rc, rc);
+ }
+
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+ {
+ CRBufferState *pBuf = &pContext->buffer;
+ /* can apply the data right away */
+ CRASSERT(cr_server.currentCtxInfo == &cr_server.MainContextInfo);
+ CRASSERT(cr_server.currentMural);
+
+ cr_server.head_spu->dispatch_table.MakeCurrent( pMural->spuWindow,
+ 0,
+ pContextInfo->SpuContext >= 0
+ ? pContextInfo->SpuContext
+ : cr_server.MainContextInfo.SpuContext);
+ crStateApplyFBImage(pContext, &Data.data);
+ CRASSERT(!pBuf->pFrontImg);
+ CRASSERT(!pBuf->pBackImg);
+ crVBoxServerFBImageDataTerm(&Data.data);
+
+ crServerPresentFBO(pMural);
+
+ CRASSERT(cr_server.currentMural);
+ cr_server.head_spu->dispatch_table.MakeCurrent( cr_server.currentMural->spuWindow,
+ 0,
+ cr_server.currentCtxInfo->SpuContext >= 0
+ ? cr_server.currentCtxInfo->SpuContext
+ : cr_server.MainContextInfo.SpuContext);
+ }
+ else
+ {
+ CRBufferState *pBuf = &pContext->buffer;
+ CRASSERT(!pBuf->pFrontImg);
+ CRASSERT(!pBuf->pBackImg);
+ CRASSERT(Data.data.cElements); /* <- older versions always saved front and back, and we filtered out the null-sized buffers above */
+
+ if (Data.data.cElements)
+ {
+ CRFBData *pLazyData = crAlloc(RT_OFFSETOF(CRFBData, aElements[Data.data.cElements]));
+ if (!RT_SUCCESS(rc))
+ {
+ crVBoxServerFBImageDataTerm(&Data.data);
+ crWarning("crAlloc failed");
+ return VERR_NO_MEMORY;
+ }
+
+ crMemcpy(pLazyData, &Data.data, RT_OFFSETOF(CRFBData, aElements[Data.data.cElements]));
+ pBuf->pFrontImg = pLazyData;
+ }
+ }
+
+ CRASSERT(RT_SUCCESS(rc));
+ return VINF_SUCCESS;
+}
+
DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
{
int32_t rc, i;
uint32_t ui, uiNumElems;
unsigned long key;
+ GLenum err;
+ CR_SERVER_LOADSTATE_READER Reader;
if (!cr_server.bIsInLoadingState)
{
@@ -941,6 +2331,16 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
}
+ crServerLsrInit(&Reader, pSSM);
+
+#ifdef DEBUG_misha
+#define CR_DBG_STR_STATE_LOAD_START "VBox.Cr.StateLoadStart"
+#define CR_DBG_STR_STATE_LOAD_STOP "VBox.Cr.StateLoadStop"
+
+ if (cr_server.head_spu->dispatch_table.StringMarkerGREMEDY)
+ cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_LOAD_START), CR_DBG_STR_STATE_LOAD_START);
+#endif
+
/* Load and recreate rendering contexts */
rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
@@ -974,11 +2374,44 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
pContext->shared->id=-1;
}
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
+ {
+ CRASSERT(!Reader.pu8Buffer);
+ /* we have a mural data here */
+ rc = crVBoxServerLoadMurals(&Reader, version);
+ AssertRCReturn(rc, rc);
+ CRASSERT(!Reader.pu8Buffer);
+ }
+
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA && uiNumElems)
+ {
+ /* set the current client to allow doing crServerPerformMakeCurrent later */
+ CRASSERT(cr_server.numClients);
+ cr_server.curClient = cr_server.clients[0];
+ }
+
+ rc = crStateLoadGlobals(pSSM, version);
+ AssertRCReturn(rc, rc);
+
+ if (uiNumElems)
+ {
+ /* ensure we have main context set up as current */
+ CRMuralInfo *pMural;
+ CRASSERT(cr_server.MainContextInfo.SpuContext > 0);
+ CRASSERT(!cr_server.currentCtxInfo);
+ CRASSERT(!cr_server.currentMural);
+ pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ CRASSERT(pMural);
+ crServerPerformMakeCurrent(pMural, &cr_server.MainContextInfo);
+ }
+
/* Restore context state data */
for (ui=0; ui<uiNumElems; ++ui)
{
CRContextInfo* pContextInfo;
CRContext *pContext;
+ CRMuralInfo *pMural = NULL;
+ int32_t winId = 0;
rc = SSMR3GetMem(pSSM, &key, sizeof(key));
AssertRCReturn(rc, rc);
@@ -988,82 +2421,91 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
CRASSERT(pContextInfo->pContext);
pContext = pContextInfo->pContext;
- rc = crStateLoadContext(pContext, cr_server.contextTable, crVBoxServerGetContextCB, pSSM, version);
- AssertRCReturn(rc, rc);
- }
-
- /* Load windows */
- rc = SSMR3GetU32(pSSM, &uiNumElems);
- AssertRCReturn(rc, rc);
- for (ui=0; ui<uiNumElems; ++ui)
- {
- CRCreateInfo_t createInfo;
- char psz[200];
- GLint winID;
- unsigned long key;
-
- rc = SSMR3GetMem(pSSM, &key, sizeof(key));
- AssertRCReturn(rc, rc);
- rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
- AssertRCReturn(rc, rc);
-
- if (createInfo.pszDpyName)
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
{
- rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
+ rc = SSMR3GetMem(pSSM, &winId, sizeof(winId));
AssertRCReturn(rc, rc);
- createInfo.pszDpyName = psz;
+
+ if (winId)
+ {
+ pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, winId);
+ CRASSERT(pMural);
+ }
+ else
+ {
+ /* null winId means a dummy mural, get it */
+ pMural = crServerGetDummyMural(pContextInfo->CreateInfo.realVisualBits);
+ CRASSERT(pMural);
+ }
}
- winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
- CRASSERT((int64_t)winID == (int64_t)key);
+ rc = crStateLoadContext(pContext, cr_server.contextTable, crVBoxServerGetContextCB, pSSM, version);
+ AssertRCReturn(rc, rc);
+
+ /*Restore front/back buffer images*/
+ rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
+ AssertRCReturn(rc, rc);
}
- /* Load cr_server.muralTable */
- rc = SSMR3GetU32(pSSM, &uiNumElems);
- AssertRCReturn(rc, rc);
- for (ui=0; ui<uiNumElems; ++ui)
+ if (version > SHCROGL_SSM_VERSION_WITH_BUGGY_FB_IMAGE_DATA)
{
- CRMuralInfo muralInfo;
+ CRContextInfo *pContextInfo;
+ CRMuralInfo *pMural;
+ GLint ctxId;
- rc = SSMR3GetMem(pSSM, &key, sizeof(key));
- AssertRCReturn(rc, rc);
- rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
+ rc = SSMR3GetU32(pSSM, &uiNumElems);
AssertRCReturn(rc, rc);
+ for (ui=0; ui<uiNumElems; ++ui)
+ {
+ CRbitvalue initialCtxUsage[CR_MAX_BITARRAY];
+ CRMuralInfo *pInitialCurMural;
- if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
- muralInfo.bFbDraw = GL_TRUE;
+ rc = SSMR3GetMem(pSSM, &key, sizeof(key));
+ AssertRCReturn(rc, rc);
- if (muralInfo.pVisibleRects)
- {
- muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
- if (!muralInfo.pVisibleRects)
+ rc = SSMR3GetMem(pSSM, &ctxId, sizeof(ctxId));
+ AssertRCReturn(rc, rc);
+
+ pMural = (CRMuralInfo*)crHashtableSearch(cr_server.muralTable, key);
+ CRASSERT(pMural);
+ if (ctxId)
{
- return VERR_NO_MEMORY;
+ pContextInfo = (CRContextInfo *)crHashtableSearch(cr_server.contextTable, ctxId);
+ CRASSERT(pContextInfo);
}
+ else
+ pContextInfo = &cr_server.MainContextInfo;
- rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
+ crMemcpy(initialCtxUsage, pMural->ctxUsage, sizeof (initialCtxUsage));
+ pInitialCurMural = pContextInfo->currentMural;
+
+ rc = crVBoxServerLoadFBImage(pSSM, version, pContextInfo, pMural);
AssertRCReturn(rc, rc);
- }
- /* Restore windows geometry info */
- crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
- crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
- /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
- if (muralInfo.bReceivedRects)
- {
- crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
+ /* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
+ crMemcpy(pMural->ctxUsage, initialCtxUsage, sizeof (initialCtxUsage));
+ pContextInfo->currentMural = pInitialCurMural;
}
- crServerDispatchWindowShow(key, muralInfo.bVisible);
- if (muralInfo.pVisibleRects)
- {
- crFree(muralInfo.pVisibleRects);
- }
+ CRASSERT(!uiNumElems || cr_server.currentCtxInfo == &cr_server.MainContextInfo);
+
+ cr_server.curClient = NULL;
+ cr_server.bForceMakeCurrentOnClientSwitch = GL_TRUE;
}
+ else
+ {
+ CRServerFreeIDsPool_t dummyIdsPool;
- /* Load starting free context and window IDs */
- rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
- CRASSERT(rc == VINF_SUCCESS);
+ CRASSERT(!Reader.pu8Buffer);
+
+ /* we have a mural data here */
+ rc = crVBoxServerLoadMurals(&Reader, version);
+ AssertRCReturn(rc, rc);
+
+ /* not used any more, just read it out and ignore */
+ rc = crServerLsrDataGetMem(&Reader, &dummyIdsPool, sizeof(dummyIdsPool));
+ CRASSERT(rc == VINF_SUCCESS);
+ }
/* Load clients info */
for (i = 0; i < cr_server.numClients; i++)
@@ -1074,21 +2516,21 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
CRClient client;
unsigned long ctxID=-1, winID=-1;
- rc = SSMR3GetU32(pSSM, &ui);
+ rc = crServerLsrDataGetU32(&Reader, &ui);
AssertRCReturn(rc, rc);
/* If this assert fires, then we should search correct client in the list first*/
CRASSERT(ui == pClient->conn->u32ClientID);
if (version>=4)
{
- rc = SSMR3GetU32(pSSM, &pClient->conn->vMajor);
+ rc = crServerLsrDataGetU32(&Reader, &pClient->conn->vMajor);
AssertRCReturn(rc, rc);
- rc = SSMR3GetU32(pSSM, &pClient->conn->vMinor);
+ rc = crServerLsrDataGetU32(&Reader, &pClient->conn->vMinor);
AssertRCReturn(rc, rc);
}
- rc = SSMR3GetMem(pSSM, &client, sizeof(client));
+ rc = crServerLsrDataGetMem(&Reader, &client, sizeof(client));
CRASSERT(rc == VINF_SUCCESS);
client.conn = pClient->conn;
@@ -1105,9 +2547,9 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
cr_server.curClient = pClient;
- if (client.currentCtxInfo && client.currentContextNumber>=0)
+ if (client.currentCtxInfo && client.currentContextNumber > 0)
{
- rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
+ rc = crServerLsrDataGetMem(&Reader, &ctxID, sizeof(ctxID));
AssertRCReturn(rc, rc);
client.currentCtxInfo = (CRContextInfo*) crHashtableSearch(cr_server.contextTable, ctxID);
CRASSERT(client.currentCtxInfo);
@@ -1116,9 +2558,9 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
//pClient->currentContextNumber = ctxID;
}
- if (client.currentMural && client.currentWindow>=0)
+ if (client.currentMural && client.currentWindow > 0)
{
- rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
+ rc = crServerLsrDataGetMem(&Reader, &winID, sizeof(winID));
AssertRCReturn(rc, rc);
client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
CRASSERT(client.currentMural);
@@ -1126,6 +2568,8 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
//pClient->currentWindow = winID;
}
+ CRASSERT(!Reader.cbData);
+
/* Restore client active context and window */
crServerDispatchMakeCurrent(winID, 0, ctxID);
@@ -1195,40 +2639,68 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
cr_server.curClient = NULL;
+ if (version >= SHCROGL_SSM_VERSION_WITH_SCREEN_INFO)
{
- GLenum err = crServerDispatchGetError();
-
- if (err != GL_NO_ERROR)
- {
- crWarning("crServer: glGetError %d after loading snapshot", err);
- }
+ rc = CrPMgrLoadState(pSSM, version);
+ AssertRCReturn(rc, rc);
}
+ while ((err = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR)
+ crWarning("crServer: glGetError %d after loading snapshot", err);
+
cr_server.bIsInLoadingState = GL_FALSE;
+#if 0
+ crVBoxServerCheckConsistency();
+#endif
+
+#ifdef DEBUG_misha
+ if (cr_server.head_spu->dispatch_table.StringMarkerGREMEDY)
+ cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_LOAD_STOP), CR_DBG_STR_STATE_LOAD_STOP);
+#endif
+
+ CRASSERT(!Reader.cbData);
+ crServerLsrTerm(&Reader);
+
return VINF_SUCCESS;
}
#define SCREEN(i) (cr_server.screen[i])
#define MAPPED(screen) ((screen).winID != 0)
-static void crVBoxServerReparentMuralCB(unsigned long key, void *data1, void *data2)
+extern DECLEXPORT(void) crServerVBoxSetNotifyEventCB(PFNCRSERVERNOTIFYEVENT pfnCb)
{
- CRMuralInfo *pMI = (CRMuralInfo*) data1;
- int *sIndex = (int*) data2;
+ cr_server.pfnNotifyEventCB = pfnCb;
+}
- if (pMI->screenId == *sIndex)
+void crVBoxServerNotifyEvent(int32_t idScreen, uint32_t uEvent, void*pvData)
+{
+ /* this is something unexpected, but just in case */
+ if (idScreen >= cr_server.screenCount)
{
- renderspuReparentWindow(pMI->spuWindow);
+ crWarning("invalid screen id %d", idScreen);
+ return;
}
+
+ cr_server.pfnNotifyEventCB(idScreen, uEvent, pvData);
}
-static void crVBoxServerCheckMuralCB(unsigned long key, void *data1, void *data2)
+void crServerWindowReparent(CRMuralInfo *pMural)
+{
+ pMural->fHasParentWindow = !!cr_server.screen[pMural->screenId].winID;
+
+ renderspuReparentWindow(pMural->spuWindow);
+}
+
+static void crVBoxServerReparentMuralCB(unsigned long key, void *data1, void *data2)
{
CRMuralInfo *pMI = (CRMuralInfo*) data1;
- (void) data2;
+ int *sIndex = (int*) data2;
- crServerCheckMuralGeometry(pMI);
+ if (pMI->screenId == *sIndex)
+ {
+ crServerWindowReparent(pMI);
+ }
}
DECLEXPORT(int32_t) crVBoxServerSetScreenCount(int sCount)
@@ -1269,9 +2741,14 @@ DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex)
renderspuSetWindowId(0);
crHashtableWalk(cr_server.muralTable, crVBoxServerReparentMuralCB, &sIndex);
+
+ crHashtableWalk(cr_server.dummyMuralTable, crVBoxServerReparentMuralCB, &sIndex);
+
+ CrPMgrScreenChanged((uint32_t)sIndex);
}
renderspuSetWindowId(SCREEN(0).winID);
+
return VINF_SUCCESS;
}
@@ -1296,9 +2773,9 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
renderspuSetWindowId(SCREEN(sIndex).winID);
crHashtableWalk(cr_server.muralTable, crVBoxServerReparentMuralCB, &sIndex);
- renderspuSetWindowId(SCREEN(0).winID);
- crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
+ crHashtableWalk(cr_server.dummyMuralTable, crVBoxServerReparentMuralCB, &sIndex);
+ renderspuSetWindowId(SCREEN(0).winID);
#ifndef WINDOWS
/*Restore FB content for clients, which have current window on a screen being remapped*/
@@ -1310,7 +2787,7 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
cr_server.curClient = cr_server.clients[i];
if (cr_server.curClient->currentCtxInfo
&& cr_server.curClient->currentCtxInfo->pContext
- && (cr_server.curClient->currentCtxInfo->pContext->buffer.pFrontImg || cr_server.curClient->currentCtxInfo->pContext->buffer.pBackImg)
+ && (cr_server.curClient->currentCtxInfo->pContext->buffer.pFrontImg)
&& cr_server.curClient->currentMural
&& cr_server.curClient->currentMural->screenId == sIndex
&& cr_server.curClient->currentCtxInfo->pContext->buffer.storedHeight == h
@@ -1318,25 +2795,74 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
{
int clientWindow = cr_server.curClient->currentWindow;
int clientContext = cr_server.curClient->currentContextNumber;
+ CRFBData *pLazyData = (CRFBData *)cr_server.curClient->currentCtxInfo->pContext->buffer.pFrontImg;
if (clientWindow && clientWindow != cr_server.currentWindow)
{
crServerDispatchMakeCurrent(clientWindow, 0, clientContext);
}
- crStateApplyFBImage(cr_server.curClient->currentCtxInfo->pContext);
+ crStateApplyFBImage(cr_server.curClient->currentCtxInfo->pContext, pLazyData);
+ crStateFreeFBImageLegacy(cr_server.curClient->currentCtxInfo->pContext);
}
}
cr_server.curClient = NULL;
}
#endif
+ CrPMgrScreenChanged((uint32_t)sIndex);
+
return VINF_SUCCESS;
}
-DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, GLint *pRects)
+DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, const RTRECT *pRects)
{
- renderspuSetRootVisibleRegion(cRects, pRects);
+ int32_t rc = VINF_SUCCESS;
+ GLboolean fOldRootVrOn = cr_server.fRootVrOn;
+
+ /* non-zero rects pointer indicate rects are present and switched on
+ * i.e. cRects==0 and pRects!=NULL means root visible regioning is ON and there are no visible regions,
+ * while pRects==NULL means root visible regioning is OFF, i.e. everything is visible */
+ if (pRects)
+ {
+ crMemset(&cr_server.RootVrCurPoint, 0, sizeof (cr_server.RootVrCurPoint));
+ rc = VBoxVrListRectsSet(&cr_server.RootVr, cRects, pRects, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("VBoxVrListRectsSet failed! rc %d", rc);
+ return rc;
+ }
+
+ cr_server.fRootVrOn = GL_TRUE;
+ }
+ else
+ {
+ if (!cr_server.fRootVrOn)
+ return VINF_SUCCESS;
+
+ VBoxVrListClear(&cr_server.RootVr);
+
+ cr_server.fRootVrOn = GL_FALSE;
+ }
+
+ if (!fOldRootVrOn != !cr_server.fRootVrOn)
+ {
+ rc = CrPMgrModeRootVr(cr_server.fRootVrOn);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrPMgrModeRootVr failed rc %d", rc);
+ return rc;
+ }
+ }
+ else if (cr_server.fRootVrOn)
+ {
+ rc = CrPMgrRootVrUpdate();
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrPMgrRootVrUpdate failed rc %d", rc);
+ return rc;
+ }
+ }
return VINF_SUCCESS;
}
@@ -1348,21 +2874,7 @@ DECLEXPORT(void) crVBoxServerSetPresentFBOCB(PFNCRSERVERPRESENTFBO pfnPresentFBO
DECLEXPORT(int32_t) crVBoxServerSetOffscreenRendering(GLboolean value)
{
- if (cr_server.bForceOffscreenRendering==value)
- {
- return VINF_SUCCESS;
- }
-
- if (value && !crServerSupportRedirMuralFBO())
- {
- return VERR_NOT_SUPPORTED;
- }
-
- cr_server.bForceOffscreenRendering=value;
-
- crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
-
- return VINF_SUCCESS;
+ return CrPMgrModeVrdp(value);
}
DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallbacks)
@@ -1371,74 +2883,502 @@ DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallb
if (pCallbacks)
{
cr_server.outputRedirect = *pCallbacks;
- cr_server.bUseOutputRedirect = true;
}
else
{
- cr_server.bUseOutputRedirect = false;
+ memset (&cr_server.outputRedirect, 0, sizeof (cr_server.outputRedirect));
}
- // @todo dynamically intercept already existing output:
- // crHashtableWalk(cr_server.muralTable, crVBoxServerOutputRedirectCB, NULL);
+ return VINF_SUCCESS;
+}
+
+DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
+{
+ CRScreenViewportInfo *pViewport;
+ RTRECT NewRect;
+ int rc;
+
+ crDebug("crVBoxServerSetScreenViewport(%i)", sIndex);
+
+ if (sIndex<0 || sIndex>=cr_server.screenCount)
+ {
+ crWarning("crVBoxServerSetScreenViewport: invalid screen id %d", sIndex);
+ return VERR_INVALID_PARAMETER;
+ }
+
+ NewRect.xLeft = x;
+ NewRect.yTop = y;
+ NewRect.xRight = x + w;
+ NewRect.yBottom = y + h;
+
+ pViewport = &cr_server.screenVieport[sIndex];
+ /*always do viewport updates no matter whether the rectangle actually changes,
+ * this is needed to ensure window is adjusted properly on OSX */
+ pViewport->Rect = NewRect;
+ rc = CrPMgrViewportUpdate((uint32_t)sIndex);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrPMgrViewportUpdate failed %d", rc);
+ return rc;
+ }
return VINF_SUCCESS;
}
-static void crVBoxServerUpdateScreenViewportCB(unsigned long key, void *data1, void *data2)
+static void crVBoxServerDefaultContextSet()
{
- CRMuralInfo *mural = (CRMuralInfo*) data1;
- int *sIndex = (int*) data2;
+ GLint spuWindow, spuCtx;
- if (mural->screenId != *sIndex)
- return;
+ if (cr_server.MainContextInfo.SpuContext)
+ {
+ CRMuralInfo *pMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ if (!pMural)
+ {
+ WARN(("dummy mural is NULL"));
+ spuCtx = CR_RENDER_DEFAULT_CONTEXT_ID;
+ spuWindow = CR_RENDER_DEFAULT_WINDOW_ID;
+ }
+ else
+ {
+ spuCtx = cr_server.MainContextInfo.SpuContext;
+ spuWindow = pMural->CreateInfo.realVisualBits;
+ }
+ }
+ else
+ {
+ spuCtx = CR_RENDER_DEFAULT_CONTEXT_ID;
+ spuWindow = CR_RENDER_DEFAULT_WINDOW_ID;
+ }
- crServerCheckMuralGeometry(mural);
+ cr_server.head_spu->dispatch_table.MakeCurrent(spuWindow, 0, spuCtx);
}
+#ifdef VBOX_WITH_CRHGSMI
-DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
+static int32_t crVBoxServerCmdVbvaCrCmdProcess(struct VBOXCMDVBVA_CRCMD_CMD *pCmd, uint32_t cbCmd)
{
- CRScreenViewportInfo *pVieport;
- GLboolean fPosChanged, fSizeChanged;
+ int32_t rc;
+ uint32_t cBuffers = pCmd->cBuffers;
+ uint32_t cParams;
+ uint32_t cbHdr;
+ CRVBOXHGSMIHDR *pHdr;
+ uint32_t u32Function;
+ uint32_t u32ClientID;
+ CRClient *pClient;
- crDebug("crVBoxServerSetScreenViewport(%i)", sIndex);
+ if (!g_pvVRamBase)
+ {
+ WARN(("g_pvVRamBase is not initialized"));
+ return VERR_INVALID_STATE;
+ }
- if (sIndex<0 || sIndex>=cr_server.screenCount)
+ if (!cBuffers)
{
- crWarning("crVBoxServerSetScreenViewport: invalid screen id %d", sIndex);
+ WARN(("zero buffers passed in!"));
return VERR_INVALID_PARAMETER;
}
- pVieport = &cr_server.screenVieport[sIndex];
- fPosChanged = (pVieport->x != x || pVieport->y != y);
- fSizeChanged = (pVieport->w != w || pVieport->h != h);
+ cParams = cBuffers-1;
- if (!fPosChanged && !fSizeChanged)
+ if (cbCmd != RT_OFFSETOF(VBOXCMDVBVA_CRCMD_CMD, aBuffers[cBuffers]))
{
- crDebug("crVBoxServerSetScreenViewport: no changes");
- return VINF_SUCCESS;
+ WARN(("invalid buffer size"));
+ return VERR_INVALID_PARAMETER;
}
- if (fPosChanged)
+ cbHdr = pCmd->aBuffers[0].cbBuffer;
+ pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR);
+ if (!pHdr)
{
- pVieport->x = x;
- pVieport->y = y;
+ WARN(("invalid header buffer!"));
+ return VERR_INVALID_PARAMETER;
+ }
- crHashtableWalk(cr_server.muralTable, crVBoxServerUpdateScreenViewportCB, &sIndex);
+ if (cbHdr < sizeof (*pHdr))
+ {
+ WARN(("invalid header buffer size!"));
+ return VERR_INVALID_PARAMETER;
}
- if (fSizeChanged)
+ u32Function = pHdr->u32Function;
+ u32ClientID = pHdr->u32ClientID;
+
+ switch (u32Function)
{
- pVieport->w = w;
- pVieport->h = h;
+ case SHCRGL_GUEST_FN_WRITE:
+ {
+ Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
+
+ /* @todo: Verify */
+ if (cParams == 1)
+ {
+ CRVBOXHGSMIWRITE* pFnCmd = (CRVBOXHGSMIWRITE*)pHdr;
+ VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+ /* Fetch parameters. */
+ uint32_t cbBuffer = pBuf->cbBuffer;
+ uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+ if (cbHdr < sizeof (*pFnCmd))
+ {
+ crWarning("invalid write cmd buffer size!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ CRASSERT(cbBuffer);
+ if (!pBuffer)
+ {
+ crWarning("invalid buffer data received from guest!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ rc = crVBoxServerClientGet(u32ClientID, &pClient);
+ if (RT_FAILURE(rc))
+ {
+ break;
+ }
+
+ /* This should never fire unless we start to multithread */
+ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+ pClient->conn->pBuffer = pBuffer;
+ pClient->conn->cbBuffer = cbBuffer;
+ CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, false);
+ rc = crVBoxServerInternalClientWriteRead(pClient);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+ return rc;
+ }
+ else
+ {
+ crWarning("invalid number of args");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+ break;
+ }
+
+ case SHCRGL_GUEST_FN_INJECT:
+ {
+ Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
+
+ /* @todo: Verify */
+ if (cParams == 1)
+ {
+ CRVBOXHGSMIINJECT *pFnCmd = (CRVBOXHGSMIINJECT*)pHdr;
+ /* Fetch parameters. */
+ uint32_t u32InjectClientID = pFnCmd->u32ClientID;
+ VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+ uint32_t cbBuffer = pBuf->cbBuffer;
+ uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+ if (cbHdr < sizeof (*pFnCmd))
+ {
+ crWarning("invalid inject cmd buffer size!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ CRASSERT(cbBuffer);
+ if (!pBuffer)
+ {
+ crWarning("invalid buffer data received from guest!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ rc = crVBoxServerClientGet(u32InjectClientID, &pClient);
+ if (RT_FAILURE(rc))
+ {
+ break;
+ }
+
+ /* This should never fire unless we start to multithread */
+ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+ pClient->conn->pBuffer = pBuffer;
+ pClient->conn->cbBuffer = cbBuffer;
+ CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, false);
+ rc = crVBoxServerInternalClientWriteRead(pClient);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+ return rc;
+ }
+
+ crWarning("invalid number of args");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ case SHCRGL_GUEST_FN_READ:
+ {
+ Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
+
+ /* @todo: Verify */
+ if (cParams == 1)
+ {
+ CRVBOXHGSMIREAD *pFnCmd = (CRVBOXHGSMIREAD*)pHdr;
+ VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+ /* Fetch parameters. */
+ uint32_t cbBuffer = pBuf->cbBuffer;
+ uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+ if (cbHdr < sizeof (*pFnCmd))
+ {
+ crWarning("invalid read cmd buffer size!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+
+ if (!pBuffer)
+ {
+ crWarning("invalid buffer data received from guest!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ rc = crVBoxServerClientGet(u32ClientID, &pClient);
+ if (RT_FAILURE(rc))
+ {
+ break;
+ }
+
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+ rc = crVBoxServerInternalClientRead(pClient, pBuffer, &cbBuffer);
+
+ /* Return the required buffer size always */
+ pFnCmd->cbBuffer = cbBuffer;
+
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+ /* the read command is never pended, complete it right away */
+ pHdr->result = rc;
+
+ return VINF_SUCCESS;
+ }
+
+ crWarning("invalid number of args");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ case SHCRGL_GUEST_FN_WRITE_READ:
+ {
+ Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
+
+ /* @todo: Verify */
+ if (cParams == 2)
+ {
+ CRVBOXHGSMIWRITEREAD *pFnCmd = (CRVBOXHGSMIWRITEREAD*)pHdr;
+ VBOXCMDVBVA_CRCMD_BUFFER *pBuf = &pCmd->aBuffers[1];
+ VBOXCMDVBVA_CRCMD_BUFFER *pWbBuf = &pCmd->aBuffers[2];
+
+ /* Fetch parameters. */
+ uint32_t cbBuffer = pBuf->cbBuffer;
+ uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
+
+ uint32_t cbWriteback = pWbBuf->cbBuffer;
+ char *pWriteback = VBOXCRHGSMI_PTR_SAFE(pWbBuf->offBuffer, cbWriteback, char);
+
+ if (cbHdr < sizeof (*pFnCmd))
+ {
+ crWarning("invalid write_read cmd buffer size!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+
+ CRASSERT(cbBuffer);
+ if (!pBuffer)
+ {
+ crWarning("invalid write buffer data received from guest!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ CRASSERT(cbWriteback);
+ if (!pWriteback)
+ {
+ crWarning("invalid writeback buffer data received from guest!");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+ rc = crVBoxServerClientGet(u32ClientID, &pClient);
+ if (RT_FAILURE(rc))
+ {
+ pHdr->result = rc;
+ return VINF_SUCCESS;
+ }
+
+ /* This should never fire unless we start to multithread */
+ CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+
+ pClient->conn->pBuffer = pBuffer;
+ pClient->conn->cbBuffer = cbBuffer;
+ CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback, false);
+ rc = crVBoxServerInternalClientWriteRead(pClient);
+ CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
+ return rc;
+ }
+
+ crWarning("invalid number of args");
+ rc = VERR_INVALID_PARAMETER;
+ break;
+ }
+
+ case SHCRGL_GUEST_FN_SET_VERSION:
+ {
+ crWarning("invalid function");
+ rc = VERR_NOT_IMPLEMENTED;
+ break;
+ }
+
+ case SHCRGL_GUEST_FN_SET_PID:
+ {
+ crWarning("invalid function");
+ rc = VERR_NOT_IMPLEMENTED;
+ break;
+ }
+
+ default:
+ {
+ crWarning("invalid function");
+ rc = VERR_NOT_IMPLEMENTED;
+ break;
+ }
- /* no need to do anything here actually */
}
+
+ /* we can be on fail only here */
+ CRASSERT(RT_FAILURE(rc));
+ pHdr->result = rc;
+
+ return rc;
+}
+
+static DECLCALLBACK(int) crVBoxCrCmdEnable(HVBOXCRCMDSVR hSvr, VBOXCRCMD_SVRENABLE_INFO *pInfo)
+{
+ cr_server.CrCmdClientInfo = *pInfo;
+
+ crVBoxServerDefaultContextSet();
+
return VINF_SUCCESS;
}
+static DECLCALLBACK(int) crVBoxCrCmdDisable(HVBOXCRCMDSVR hSvr)
+{
+ cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0);
+
+ memset(&cr_server.CrCmdClientInfo, 0, sizeof (cr_server.CrCmdClientInfo));
+
+ return VINF_SUCCESS;
+}
+
+static DECLCALLBACK(int) crVBoxCrCmdHostCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
+{
+ return crVBoxServerHostCtl((VBOXCRCMDCTL*)pCmd, cbCmd);
+}
+
+static DECLCALLBACK(int) crVBoxCrCmdGuestCtl(HVBOXCRCMDSVR hSvr, uint8_t* pCmd, uint32_t cbCmd)
+{
+ VBOXCMDVBVA_3DCTL *pCtl = (VBOXCMDVBVA_3DCTL*)pCmd;
+ if (cbCmd < sizeof (VBOXCMDVBVA_3DCTL))
+ {
+ WARN(("invalid buffer size"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ switch (pCtl->u32Type)
+ {
+ case VBOXCMDVBVA3DCTL_TYPE_CONNECT:
+ {
+ VBOXCMDVBVA_3DCTL_CONNECT *pConnect = (VBOXCMDVBVA_3DCTL_CONNECT*)pCtl;
+
+ return VERR_NOT_SUPPORTED;
+ }
+ case VBOXCMDVBVA3DCTL_TYPE_DISCONNECT:
+ {
+ return VERR_NOT_SUPPORTED;
+ }
+ case VBOXCMDVBVA3DCTL_TYPE_CMD:
+ {
+ VBOXCMDVBVA_3DCTL_CMD *p3DCmd;
+ if (cbCmd < sizeof (VBOXCMDVBVA_3DCTL_CMD))
+ {
+ WARN(("invalid size"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ p3DCmd = (VBOXCMDVBVA_3DCTL_CMD*)pCmd;
+
+ return crVBoxCrCmdCmd(NULL, &p3DCmd->Cmd, cbCmd - RT_OFFSETOF(VBOXCMDVBVA_3DCTL_CMD, Cmd));
+ }
+ default:
+ WARN(("invalid function"));
+ return VERR_INVALID_PARAMETER;
+ }
+}
+
+static DECLCALLBACK(int) crVBoxCrCmdSaveState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM)
+{
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+static DECLCALLBACK(int) crVBoxCrCmdLoadState(HVBOXCRCMDSVR hSvr, PSSMHANDLE pSSM, uint32_t u32Version)
+{
+ AssertFailed();
+ return VERR_NOT_IMPLEMENTED;
+}
+
+
+static DECLCALLBACK(int) crVBoxCrCmdCmd(HVBOXCRCMDSVR hSvr, PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
+{
+ AssertFailed();
+ switch (pCmd->u8OpCode)
+ {
+ case VBOXCMDVBVA_OPTYPE_CRCMD:
+ {
+ VBOXCMDVBVA_CRCMD *pCrCmdDr;
+ VBOXCMDVBVA_CRCMD_CMD *pCrCmd;
+ int rc;
+ pCrCmdDr = (VBOXCMDVBVA_CRCMD*)pCmd;
+ pCrCmd = &pCrCmdDr->Cmd;
+ if (cbCmd < sizeof (VBOXCMDVBVA_CRCMD))
+ {
+ WARN(("invalid buffer size"));
+ pCmd->u.i8Result = -1;
+ break;
+ }
+ rc = crVBoxServerCmdVbvaCrCmdProcess(pCrCmd, cbCmd - RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd));
+ if (RT_SUCCESS(rc))
+ {
+ /* success */
+ pCmd->u.i8Result = 0;
+ }
+ else
+ {
+ WARN(("crVBoxServerCmdVbvaCrCmdProcess failed, rc %d", rc));
+ pCmd->u.i8Result = -1;
+ }
+ break;
+ }
+ case VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID:
+ {
+ crVBoxServerCrCmdBltProcess(pCmd, cbCmd);
+ break;
+ }
+ default:
+ WARN(("unsupported command"));
+ pCmd->u.i8Result = -1;
+ }
+ return VINF_SUCCESS;
+}
-#ifdef VBOX_WITH_CRHGSMI
/* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
*
* For now we need the notion of CrHgdmi commands in the crserver_lib to be able to complete it asynchronously once it is really processed.
@@ -1452,8 +3392,11 @@ DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t
*
* NOTE: it is ALWAYS responsibility of the crVBoxServerCrHgsmiCmd to complete the command!
* */
+
+
int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd)
{
+
int32_t rc;
uint32_t cBuffers = pCmd->cBuffers;
uint32_t cParams;
@@ -1465,14 +3408,16 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
if (!g_pvVRamBase)
{
- crWarning("g_pvVRamBase is not initialized");
+ WARN(("g_pvVRamBase is not initialized"));
+
crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_STATE);
return VINF_SUCCESS;
}
if (!cBuffers)
{
- crWarning("zero buffers passed in!");
+ WARN(("zero buffers passed in!"));
+
crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
return VINF_SUCCESS;
}
@@ -1483,14 +3428,16 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR);
if (!pHdr)
{
- crWarning("invalid header buffer!");
+ WARN(("invalid header buffer!"));
+
crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
return VINF_SUCCESS;
}
if (cbHdr < sizeof (*pHdr))
{
- crWarning("invalid header buffer size!");
+ WARN(("invalid header buffer size!"));
+
crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
return VINF_SUCCESS;
}
@@ -1502,7 +3449,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
{
case SHCRGL_GUEST_FN_WRITE:
{
- crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
+ Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
/* @todo: Verify */
if (cParams == 1)
@@ -1540,7 +3487,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
pClient->conn->pBuffer = pBuffer;
pClient->conn->cbBuffer = cbBuffer;
- CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
+ CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, true);
rc = crVBoxServerInternalClientWriteRead(pClient);
CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
return rc;
@@ -1556,7 +3503,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
case SHCRGL_GUEST_FN_INJECT:
{
- crDebug(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
+ Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
/* @todo: Verify */
if (cParams == 1)
@@ -1595,7 +3542,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
pClient->conn->pBuffer = pBuffer;
pClient->conn->cbBuffer = cbBuffer;
- CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
+ CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr, true);
rc = crVBoxServerInternalClientWriteRead(pClient);
CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
return rc;
@@ -1608,7 +3555,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
case SHCRGL_GUEST_FN_READ:
{
- crDebug(("svcCall: SHCRGL_GUEST_FN_READ\n"));
+ Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
/* @todo: Verify */
if (cParams == 1)
@@ -1651,6 +3598,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
/* the read command is never pended, complete it right away */
pHdr->result = rc;
+
crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
return VINF_SUCCESS;
}
@@ -1662,7 +3610,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
case SHCRGL_GUEST_FN_WRITE_READ:
{
- crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
+ Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
/* @todo: Verify */
if (cParams == 2)
@@ -1715,7 +3663,7 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
pClient->conn->pBuffer = pBuffer;
pClient->conn->cbBuffer = cbBuffer;
- CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback);
+ CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback, true);
rc = crVBoxServerInternalClientWriteRead(pClient);
CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
return rc;
@@ -1752,8 +3700,24 @@ int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t c
/* we can be on fail only here */
CRASSERT(RT_FAILURE(rc));
pHdr->result = rc;
+
crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
return rc;
+
+}
+
+static DECLCALLBACK(bool) crVBoxServerHasData()
+{
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+ for (;
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ if (CrFbHas3DData(hFb))
+ return true;
+ }
+
+ return false;
}
int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl)
@@ -1767,6 +3731,14 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)pCtl;
g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase;
g_cbVRam = pSetup->cbVRam;
+ pSetup->CrCmdServerInfo.hSvr = NULL;
+ pSetup->CrCmdServerInfo.pfnEnable = crVBoxCrCmdEnable;
+ pSetup->CrCmdServerInfo.pfnDisable = crVBoxCrCmdDisable;
+ pSetup->CrCmdServerInfo.pfnCmd = crVBoxCrCmdCmd;
+ pSetup->CrCmdServerInfo.pfnHostCtl = crVBoxCrCmdHostCtl;
+ pSetup->CrCmdServerInfo.pfnGuestCtl = crVBoxCrCmdGuestCtl;
+ pSetup->CrCmdServerInfo.pfnSaveState = crVBoxCrCmdSaveState;
+ pSetup->CrCmdServerInfo.pfnLoadState = crVBoxCrCmdLoadState;
rc = VINF_SUCCESS;
break;
}
@@ -1774,11 +3746,14 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END:
rc = VINF_SUCCESS;
break;
- case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION:
+ case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_MAINCB:
{
- PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION)pCtl;
+ PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_MAINCB)pCtl;
g_hCrHgsmiCompletion = pSetup->hCompletion;
g_pfnCrHgsmiCompletion = pSetup->pfnCompletion;
+
+ pSetup->MainInterface.pfnHasData = crVBoxServerHasData;
+
rc = VINF_SUCCESS;
break;
}
@@ -1795,4 +3770,40 @@ int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t c
* or Hgcm Host Fast Call commands that do require completion. All this details are hidden here */
return rc;
}
+
+int32_t crVBoxServerHgcmEnable(HVBOXCRCMDCTL_REMAINING_HOST_COMMAND hRHCmd, PFNVBOXCRCMDCTL_REMAINING_HOST_COMMAND pfnRHCmd)
+{
+ int rc = VINF_SUCCESS;
+ uint8_t* pCtl;
+ uint32_t cbCtl;
+
+ if (cr_server.numClients)
+ {
+ WARN(("cr_server.numClients(%d) is not NULL", cr_server.numClients));
+ return VERR_INVALID_STATE;
+ }
+
+ for (pCtl = pfnRHCmd(hRHCmd, &cbCtl, rc); pCtl; pCtl = pfnRHCmd(hRHCmd, &cbCtl, rc))
+ {
+ rc = crVBoxCrCmdHostCtl(NULL, pCtl, cbCtl);
+ }
+
+ crVBoxServerDefaultContextSet();
+
+ return VINF_SUCCESS;
+}
+
+int32_t crVBoxServerHgcmDisable()
+{
+ if (cr_server.numClients)
+ {
+ WARN(("cr_server.numClients(%d) is not NULL", cr_server.numClients));
+ return VERR_INVALID_STATE;
+ }
+
+ cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0);
+
+ return VINF_SUCCESS;
+}
+
#endif
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
index 20a71e3f..e9385996 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_misc.c
@@ -49,7 +49,40 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchGetChromiumParametervCR(GLenum tar
CRASSERT(bytes >= 0);
CRASSERT(bytes < 4096);
- cr_server.head_spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, local_storage );
+ switch (target)
+ {
+ case GL_DBG_CHECK_BREAK_CR:
+ {
+ if (bytes > 0)
+ {
+ GLubyte *pbRc = local_storage;
+ GLuint *puRc = (GLuint *)(bytes >=4 ? local_storage : NULL);
+ int rc;
+ memset(local_storage, 0, bytes);
+ if (cr_server.RcToGuestOnce)
+ {
+ rc = cr_server.RcToGuestOnce;
+ cr_server.RcToGuestOnce = 0;
+ }
+ else
+ {
+ rc = cr_server.RcToGuest;
+ }
+ if (puRc)
+ *puRc = rc;
+ else
+ *pbRc = !!rc;
+ }
+ else
+ {
+ crWarning("zero bytes for GL_DBG_CHECK_BREAK_CR");
+ }
+ break;
+ }
+ default:
+ cr_server.head_spu->dispatch_table.GetChromiumParametervCR( target, index, type, count, local_storage );
+ break;
+ }
crServerReturnValue( local_storage, bytes );
}
@@ -96,13 +129,13 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
break;
case GL_GATHER_CONNECT_CR:
- /*
+ /*
* We want the last connect to go through,
* otherwise we might deadlock in CheckWindowSize()
* in the readback spu
*/
gather_connect_count++;
- if (cr_server.only_swap_once && (gather_connect_count != cr_server.numClients))
+ if (cr_server.only_swap_once && (gather_connect_count != cr_server.numClients))
{
break;
}
@@ -122,8 +155,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
const GLfloat *v = (const GLfloat *) values;
const int eye = v[1] == 0.0 ? 0 : 1;
crMatrixInitFromFloats(&cr_server.viewMatrix[eye], v + 2);
-
- crDebug("Got GL_SERVER_VIEW_MATRIX_CR:\n"
+
+ crDebug("Got GL_SERVER_VIEW_MATRIX_CR:\n"
" %f %f %f %f\n"
" %f %f %f %f\n"
" %f %f %f %f\n"
@@ -160,8 +193,8 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
const GLfloat *v = (const GLfloat *) values;
const int eye = v[1] == 0.0 ? 0 : 1;
crMatrixInitFromFloats(&cr_server.projectionMatrix[eye], v + 2);
-
- crDebug("Got GL_SERVER_PROJECTION_MATRIX_CR:\n"
+
+ crDebug("Got GL_SERVER_PROJECTION_MATRIX_CR:\n"
" %f %f %f %f\n"
" %f %f %f %f\n"
" %f %f %f %f\n"
@@ -196,7 +229,7 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
float right = 2.0f * znear / x + left;
float bottom = znear * (b - 1.0f) / y;
float top = 2.0f * znear / y + bottom;
- crDebug("Frustum: left, right, bottom, top, near, far: %f, %f, %f, %f, %f, %f", left, right, bottom, top, znear, zfar);
+ crDebug("Frustum: left, right, bottom, top, near, far: %f, %f, %f, %f, %f, %f", left, right, bottom, top, znear, zfar);
}
else {
/* Todo: Add debug output for orthographic projection*/
@@ -206,6 +239,10 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParametervCR(GLenum target
cr_server.projectionOverride = GL_TRUE;
break;
+ case GL_HH_SET_TMPCTX_MAKE_CURRENT:
+ /*we should not receive it from the guest! */
+ break;
+
default:
/* Pass the parameter info to the head SPU */
cr_server.head_spu->dispatch_table.ChromiumParametervCR( target, type, count, values );
@@ -238,6 +275,12 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParameteriCR(GLenum target
case GL_SERVER_CURRENT_EYE_CR:
cr_server.currentEye = value ? 1 : 0;
break;
+ case GL_HOST_WND_CREATED_HIDDEN_CR:
+ cr_server.bWindowsInitiallyHidden = value ? 1 : 0;
+ break;
+ case GL_HH_SET_DEFAULT_SHARED_CTX:
+ crWarning("Recieved GL_HH_SET_DEFAULT_SHARED_CTX from guest, ignoring");
+ break;
default:
/* Pass the parameter info to the head SPU */
cr_server.head_spu->dispatch_table.ChromiumParameteriCR( target, value );
@@ -263,14 +306,6 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchChromiumParameterfCR(GLenum target
}
}
-void crServerCreateInfoDeleteCB(void *data)
-{
- CRCreateInfo_t *pCreateInfo = (CRCreateInfo_t *) data;
- if (pCreateInfo->pszDpyName)
- crFree(pCreateInfo->pszDpyName);
- crFree(pCreateInfo);
-}
-
GLint crServerGenerateID(GLint *pCounter)
{
return (*pCounter)++;
@@ -284,14 +319,14 @@ static int copynum=0;
#endif
# ifdef DEBUG_misha
-# define CR_CHECK_BLITS
+//# define CR_CHECK_BLITS
# include <iprt/assert.h>
# undef CRASSERT /* iprt assert's int3 are inlined that is why are more convenient to use since they can be easily disabled individually */
# define CRASSERT Assert
# endif
-void SERVER_DISPATCH_APIENTRY
+void SERVER_DISPATCH_APIENTRY
crServerDispatchCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
/*@todo pbo/fbo disabled for now as it's slower, check on other gpus*/
@@ -392,7 +427,7 @@ crServerDispatchCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLi
gl->CopyTexImage2D(target, level, GL_RGBA, x, y, width, -height, 0);
gl->GenFramebuffersEXT(1, &fboID);
gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboID);
- gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target,
+ gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, target,
ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid, level);
status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT)
@@ -460,7 +495,7 @@ crServerDispatchCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLi
gl->GetTexImage(target, level, GL_BGRA, GL_UNSIGNED_BYTE, img1);
-
+
for (dRow=yoffset, sRow=y-height-1; dRow<yoffset-height; dRow++, sRow--)
{
gl->CopyTexSubImage2D(target, level, xoffset, dRow, x, sRow, width, 1);
@@ -632,18 +667,252 @@ void crDbgDumpTexImage2D(const char* pszDesc, GLint texTarget, GLint texName, GL
}
#endif
-void SERVER_DISPATCH_APIENTRY
+PCR_BLITTER crServerVBoxBlitterGet()
+{
+ if (!CrBltIsInitialized(&cr_server.Blitter))
+ {
+ CR_BLITTER_CONTEXT Ctx;
+ int rc;
+ CRASSERT(cr_server.MainContextInfo.SpuContext);
+ Ctx.Base.id = cr_server.MainContextInfo.SpuContext;
+ Ctx.Base.visualBits = cr_server.MainContextInfo.CreateInfo.realVisualBits;
+ rc = CrBltInit(&cr_server.Blitter, &Ctx, true, true, NULL, &cr_server.TmpCtxDispatch);
+ if (RT_SUCCESS(rc))
+ {
+ CRASSERT(CrBltIsInitialized(&cr_server.Blitter));
+ }
+ else
+ {
+ crWarning("CrBltInit failed, rc %d", rc);
+ CRASSERT(!CrBltIsInitialized(&cr_server.Blitter));
+ return NULL;
+ }
+ }
+
+ if (!CrBltMuralGetCurrentInfo(&cr_server.Blitter)->Base.id)
+ {
+ CRMuralInfo *dummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ CR_BLITTER_WINDOW DummyInfo;
+ CRASSERT(dummy);
+ crServerVBoxBlitterWinInit(&DummyInfo, dummy);
+ CrBltMuralSetCurrentInfo(&cr_server.Blitter, &DummyInfo);
+ }
+
+ return &cr_server.Blitter;
+}
+
+PCR_BLITTER crServerVBoxBlitterGetInitialized()
+{
+ if (CrBltIsInitialized(&cr_server.Blitter))
+ return &cr_server.Blitter;
+ return NULL;
+}
+
+
+int crServerVBoxBlitterTexInit(CRContext *ctx, CRMuralInfo *mural, PVBOXVR_TEXTURE pTex, GLboolean fDraw)
+{
+ CRTextureObj *tobj;
+ CRFramebufferObjectState *pBuf = &ctx->framebufferobject;
+ GLenum enmBuf;
+ CRFBOAttachmentPoint *pAp;
+ GLuint idx;
+ CRTextureLevel *tl;
+ CRFramebufferObject *pFBO = fDraw ? pBuf->drawFB : pBuf->readFB;
+
+ if (!pFBO)
+ {
+ GLuint hwid;
+
+ if (!mural->fRedirected)
+ return VERR_NOT_IMPLEMENTED;
+
+ enmBuf = fDraw ? ctx->buffer.drawBuffer : ctx->buffer.readBuffer;
+ switch (enmBuf)
+ {
+ case GL_BACK:
+ case GL_BACK_RIGHT:
+ case GL_BACK_LEFT:
+ hwid = mural->aidColorTexs[CR_SERVER_FBO_BB_IDX(mural)];
+ break;
+ case GL_FRONT:
+ case GL_FRONT_RIGHT:
+ case GL_FRONT_LEFT:
+ hwid = mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)];
+ break;
+ default:
+ crWarning("unsupported enum buf");
+ return VERR_NOT_IMPLEMENTED;
+ break;
+ }
+
+ if (!hwid)
+ {
+ crWarning("offscreen render tex hwid is null");
+ return VERR_INVALID_STATE;
+ }
+
+ pTex->width = mural->width;
+ pTex->height = mural->height;
+ pTex->target = GL_TEXTURE_2D;
+ pTex->hwid = hwid;
+ return VINF_SUCCESS;
+ }
+
+ enmBuf = fDraw ? pFBO->drawbuffer[0] : pFBO->readbuffer;
+ idx = enmBuf - GL_COLOR_ATTACHMENT0_EXT;
+ if (idx >= CR_MAX_COLOR_ATTACHMENTS)
+ {
+ crWarning("idx is invalid %d, using 0", idx);
+ }
+
+ pAp = &pFBO->color[idx];
+
+ if (!pAp->name)
+ {
+ crWarning("no collor draw attachment");
+ return VERR_INVALID_STATE;
+ }
+
+ if (pAp->level)
+ {
+ crWarning("non-zero level not implemented");
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ tobj = (CRTextureObj*)crHashtableSearch(ctx->shared->textureTable, pAp->name);
+ if (!tobj)
+ {
+ crWarning("no texture object found for name %d", pAp->name);
+ return VERR_INVALID_STATE;
+ }
+
+ if (tobj->target != GL_TEXTURE_2D && tobj->target != GL_TEXTURE_RECTANGLE_NV)
+ {
+ crWarning("non-texture[rect|2d] not implemented");
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ CRASSERT(tobj->hwid);
+
+ tl = tobj->level[0];
+ pTex->width = tl->width;
+ pTex->height = tl->height;
+ pTex->target = tobj->target;
+ pTex->hwid = tobj->hwid;
+
+ return VINF_SUCCESS;
+}
+
+int crServerVBoxBlitterBlitCurrentCtx(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ PCR_BLITTER pBlitter;
+ CR_BLITTER_CONTEXT Ctx;
+ CRMuralInfo *mural;
+ CRContext *ctx = crStateGetCurrent();
+ PVBOXVR_TEXTURE pDrawTex, pReadTex;
+ VBOXVR_TEXTURE DrawTex, ReadTex;
+ int rc;
+ GLuint idDrawFBO, idReadFBO;
+ CR_BLITTER_WINDOW BltInfo;
+
+ if (mask != GL_COLOR_BUFFER_BIT)
+ {
+ crWarning("not supported blit mask %d", mask);
+ return VERR_NOT_IMPLEMENTED;
+ }
+
+ if (!cr_server.curClient)
+ {
+ crWarning("no current client");
+ return VERR_INVALID_STATE;
+ }
+ mural = cr_server.curClient->currentMural;
+ if (!mural)
+ {
+ crWarning("no current mural");
+ return VERR_INVALID_STATE;
+ }
+
+ rc = crServerVBoxBlitterTexInit(ctx, mural, &DrawTex, GL_TRUE);
+ if (RT_SUCCESS(rc))
+ {
+ pDrawTex = &DrawTex;
+ }
+ else
+ {
+ crWarning("crServerVBoxBlitterTexInit failed for draw");
+ return rc;
+ }
+
+ rc = crServerVBoxBlitterTexInit(ctx, mural, &ReadTex, GL_FALSE);
+ if (RT_SUCCESS(rc))
+ {
+ pReadTex = &ReadTex;
+ }
+ else
+ {
+// crWarning("crServerVBoxBlitterTexInit failed for read");
+ return rc;
+ }
+
+ pBlitter = crServerVBoxBlitterGet();
+ if (!pBlitter)
+ {
+ crWarning("crServerVBoxBlitterGet failed");
+ return VERR_GENERAL_FAILURE;
+ }
+
+ crServerVBoxBlitterWinInit(&BltInfo, mural);
+
+ crServerVBoxBlitterCtxInit(&Ctx, cr_server.curClient->currentCtxInfo);
+
+ CrBltMuralSetCurrentInfo(pBlitter, &BltInfo);
+
+ idDrawFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer);
+ idReadFBO = CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer);
+
+ crStateSwitchPrepare(NULL, ctx, idDrawFBO, idReadFBO);
+
+ rc = CrBltEnter(pBlitter);
+ if (RT_SUCCESS(rc))
+ {
+ RTRECT ReadRect, DrawRect;
+ ReadRect.xLeft = srcX0;
+ ReadRect.yTop = srcY0;
+ ReadRect.xRight = srcX1;
+ ReadRect.yBottom = srcY1;
+ DrawRect.xLeft = dstX0;
+ DrawRect.yTop = dstY0;
+ DrawRect.xRight = dstX1;
+ DrawRect.yBottom = dstY1;
+ CrBltBlitTexTex(pBlitter, pReadTex, &ReadRect, pDrawTex, &DrawRect, 1, CRBLT_FLAGS_FROM_FILTER(filter));
+ CrBltLeave(pBlitter);
+ }
+ else
+ {
+ crWarning("CrBltEnter failed rc %d", rc);
+ }
+
+ crStateSwitchPostprocess(ctx, NULL, idDrawFBO, idReadFBO);
+
+ return rc;
+}
+
+void SERVER_DISPATCH_APIENTRY
crServerDispatchBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
+ CRContext *ctx = crStateGetCurrent();
+ bool fTryBlitter = false;
#ifdef CR_CHECK_BLITS
// {
SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
GLint rfb=0, dfb=0, dtex=0, dlev=-1, rtex=0, rlev=-1, rb=0, db=0, ppb=0, pub=0, vp[4], otex, dstw, dsth;
GLint sdtex=0, srtex=0;
GLenum dStatus, rStatus;
- CRContext *ctx = crStateGetCurrent();
CRTextureObj *tobj = 0;
CRTextureLevel *tl = 0;
@@ -847,10 +1116,60 @@ crServerDispatchBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint
gl->BindTexture(GL_TEXTURE_2D, otex);
#endif
+ if (srcY0 > srcY1)
+ {
+ /* work around Intel driver bug on Linux host */
+ if (1 || dstY0 > dstY1)
+ {
+ /* use srcY1 < srcY2 && dstY1 < dstY2 whenever possible to avoid GPU driver bugs */
+ int32_t tmp = srcY0;
+ srcY0 = srcY1;
+ srcY1 = tmp;
+ tmp = dstY0;
+ dstY0 = dstY1;
+ dstY1 = tmp;
+ }
+ }
+
+ if (srcX0 > srcX1)
+ {
+ if (dstX0 > dstX1)
+ {
+ /* use srcX1 < srcX2 && dstX1 < dstX2 whenever possible to avoid GPU driver bugs */
+ int32_t tmp = srcX0;
+ srcX0 = srcX1;
+ srcX1 = tmp;
+ tmp = dstX0;
+ dstX0 = dstX1;
+ dstX1 = tmp;
+ }
+ }
+
+ if (cr_server.fBlitterMode)
+ {
+ fTryBlitter = true;
+ }
+
+ if (fTryBlitter)
+ {
+ int rc = crServerVBoxBlitterBlitCurrentCtx(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ if (RT_SUCCESS(rc))
+ goto my_exit;
+ }
+
+ if (ctx->viewport.scissorTest)
+ cr_server.head_spu->dispatch_table.Disable(GL_SCISSOR_TEST);
+
cr_server.head_spu->dispatch_table.BlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1,
mask, filter);
+ if (ctx->viewport.scissorTest)
+ cr_server.head_spu->dispatch_table.Enable(GL_SCISSOR_TEST);
+
+
+my_exit:
+
//#ifdef CR_CHECK_BLITS
// crDbgDumpTexImage2D("<== src tex:", GL_TEXTURE_2D, rtex, true);
// crDbgDumpTexImage2D("<== dst tex:", GL_TEXTURE_2D, dtex, true);
@@ -863,6 +1182,7 @@ crServerDispatchBlitFramebufferEXT(GLint srcX0, GLint srcY0, GLint srcX1, GLint
gl->BindTexture(GL_TEXTURE_2D, otex);
crFree(img);
#endif
+ return;
}
void SERVER_DISPATCH_APIENTRY crServerDispatchDrawBuffer( GLenum mode )
@@ -871,27 +1191,69 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchDrawBuffer( GLenum mode )
if (!crStateGetCurrent()->framebufferobject.drawFB)
{
- if (mode == GL_FRONT || mode == GL_FRONT_LEFT)
+ if (mode == GL_FRONT || mode == GL_FRONT_LEFT || mode == GL_FRONT_RIGHT)
cr_server.curClient->currentMural->bFbDraw = GL_TRUE;
- if (cr_server.curClient->currentMural->bUseFBO && crServerIsRedirectedToFBO()
- && cr_server.curClient->currentMural->idFBO)
+ if (crServerIsRedirectedToFBO()
+ && cr_server.curClient->currentMural->aidFBOs[0])
{
+ CRMuralInfo *mural = cr_server.curClient->currentMural;
+ GLint iBufferNeeded = -1;
switch (mode)
{
case GL_BACK:
case GL_BACK_LEFT:
+ case GL_BACK_RIGHT:
mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
break;
case GL_FRONT:
case GL_FRONT_LEFT:
- crDebug("Setting GL_FRONT with FBO mode! (0x%x)", mode);
+ case GL_FRONT_RIGHT:
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_FB_IDX(mural);
+ break;
+ case GL_NONE:
+ crDebug("DrawBuffer: GL_NONE");
+ break;
+ case GL_AUX0:
+ crDebug("DrawBuffer: GL_AUX0");
+ break;
+ case GL_AUX1:
+ crDebug("DrawBuffer: GL_AUX1");
+ break;
+ case GL_AUX2:
+ crDebug("DrawBuffer: GL_AUX2");
+ break;
+ case GL_AUX3:
+ crDebug("DrawBuffer: GL_AUX3");
+ break;
+ case GL_LEFT:
+ crWarning("DrawBuffer: GL_LEFT not supported properly");
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
+ break;
+ case GL_RIGHT:
+ crWarning("DrawBuffer: GL_RIGHT not supported properly");
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
+ break;
+ case GL_FRONT_AND_BACK:
+ crWarning("DrawBuffer: GL_FRONT_AND_BACK not supported properly");
mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
break;
default:
- crWarning("unexpected mode! 0x%x", mode);
+ crWarning("DrawBuffer: unexpected mode! 0x%x", mode);
+ iBufferNeeded = mural->iCurDrawBuffer;
break;
}
+
+ if (iBufferNeeded != mural->iCurDrawBuffer)
+ {
+ mural->iCurDrawBuffer = iBufferNeeded;
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, iBufferNeeded));
+ }
}
}
@@ -902,25 +1264,661 @@ void SERVER_DISPATCH_APIENTRY crServerDispatchReadBuffer( GLenum mode )
{
crStateReadBuffer( mode );
- if (cr_server.curClient->currentMural->bUseFBO && crServerIsRedirectedToFBO()
- && cr_server.curClient->currentMural->idFBO
+ if (crServerIsRedirectedToFBO()
+ && cr_server.curClient->currentMural->aidFBOs[0]
&& !crStateGetCurrent()->framebufferobject.readFB)
{
+ CRMuralInfo *mural = cr_server.curClient->currentMural;
+ GLint iBufferNeeded = -1;
switch (mode)
{
case GL_BACK:
case GL_BACK_LEFT:
+ case GL_BACK_RIGHT:
mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
break;
case GL_FRONT:
case GL_FRONT_LEFT:
- crWarning("GL_FRONT not supported for FBO mode!");
+ case GL_FRONT_RIGHT:
mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_FB_IDX(mural);
+ break;
+ case GL_NONE:
+ crDebug("ReadBuffer: GL_NONE");
+ break;
+ case GL_AUX0:
+ crDebug("ReadBuffer: GL_AUX0");
+ break;
+ case GL_AUX1:
+ crDebug("ReadBuffer: GL_AUX1");
+ break;
+ case GL_AUX2:
+ crDebug("ReadBuffer: GL_AUX2");
+ break;
+ case GL_AUX3:
+ crDebug("ReadBuffer: GL_AUX3");
+ break;
+ case GL_LEFT:
+ crWarning("ReadBuffer: GL_LEFT not supported properly");
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
+ break;
+ case GL_RIGHT:
+ crWarning("ReadBuffer: GL_RIGHT not supported properly");
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
+ break;
+ case GL_FRONT_AND_BACK:
+ crWarning("ReadBuffer: GL_FRONT_AND_BACK not supported properly");
+ mode = GL_COLOR_ATTACHMENT0;
+ iBufferNeeded = CR_SERVER_FBO_BB_IDX(mural);
break;
default:
- crWarning("unexpected mode! 0x%x", mode);
+ crWarning("ReadBuffer: unexpected mode! 0x%x", mode);
+ iBufferNeeded = mural->iCurDrawBuffer;
break;
}
+
+ Assert(CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+ if (iBufferNeeded != mural->iCurReadBuffer)
+ {
+ mural->iCurReadBuffer = iBufferNeeded;
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, iBufferNeeded));
+ }
}
cr_server.head_spu->dispatch_table.ReadBuffer( mode );
}
+
+GLenum SERVER_DISPATCH_APIENTRY crServerDispatchGetError( void )
+{
+ GLenum retval, err;
+ CRContext *ctx = crStateGetCurrent();
+ retval = ctx->error;
+
+ err = cr_server.head_spu->dispatch_table.GetError();
+ if (retval == GL_NO_ERROR)
+ retval = err;
+ else
+ ctx->error = GL_NO_ERROR;
+
+ /* our impl has a single error flag, so we just loop here to reset all error flags to no_error */
+ while (err != GL_NO_ERROR)
+ err = cr_server.head_spu->dispatch_table.GetError();
+
+ crServerReturnValue( &retval, sizeof(retval) );
+ return retval; /* WILL PROBABLY BE IGNORED */
+}
+
+void SERVER_DISPATCH_APIENTRY
+crServerMakeTmpCtxCurrent( GLint window, GLint nativeWindow, GLint context )
+{
+ CRContext *pCtx = crStateGetCurrent();
+ CRContext *pCurCtx = NULL;
+ GLuint idDrawFBO = 0, idReadFBO = 0;
+ int fDoPrePostProcess = 0;
+
+ if (pCtx)
+ {
+ CRMuralInfo *pCurrentMural = cr_server.currentMural;
+
+ pCurCtx = cr_server.currentCtxInfo ? cr_server.currentCtxInfo->pContext : cr_server.MainContextInfo.pContext;
+ Assert(pCurCtx == pCtx);
+
+ if (!context)
+ {
+ if (pCurrentMural)
+ {
+ Assert(cr_server.currentCtxInfo);
+ context = cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext;
+ window = pCurrentMural->spuWindow;
+ }
+ else
+ {
+ CRMuralInfo * pDummy;
+ Assert(!cr_server.currentCtxInfo);
+ pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ context = cr_server.MainContextInfo.SpuContext;
+ window = pDummy->spuWindow;
+ }
+
+
+ fDoPrePostProcess = -1;
+ }
+ else
+ {
+ fDoPrePostProcess = 1;
+ }
+
+ if (pCurrentMural)
+ {
+ idDrawFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurDrawBuffer);
+ idReadFBO = CR_SERVER_FBO_FOR_IDX(pCurrentMural, pCurrentMural->iCurReadBuffer);
+ }
+ else
+ {
+ idDrawFBO = 0;
+ idReadFBO = 0;
+ }
+ }
+ else
+ {
+ /* this is a GUI thread, so no need to do anything here */
+ }
+
+ if (fDoPrePostProcess > 0)
+ crStateSwitchPrepare(NULL, pCurCtx, idDrawFBO, idReadFBO);
+
+ cr_server.head_spu->dispatch_table.MakeCurrent( window, nativeWindow, context);
+
+ if (fDoPrePostProcess < 0)
+ crStateSwitchPostprocess(pCurCtx, NULL, idDrawFBO, idReadFBO);
+}
+
+void crServerInitTmpCtxDispatch()
+{
+ MakeCurrentFunc_t pfnMakeCurrent;
+
+ crSPUInitDispatchTable(&cr_server.TmpCtxDispatch);
+ crSPUCopyDispatchTable(&cr_server.TmpCtxDispatch, &cr_server.head_spu->dispatch_table);
+ cr_server.TmpCtxDispatch.MakeCurrent = crServerMakeTmpCtxCurrent;
+
+ pfnMakeCurrent = crServerMakeTmpCtxCurrent;
+ cr_server.head_spu->dispatch_table.ChromiumParametervCR(GL_HH_SET_TMPCTX_MAKE_CURRENT, GL_BYTE, sizeof (void*), &pfnMakeCurrent);
+
+}
+
+/* dump stuff */
+#ifdef VBOX_WITH_CRSERVER_DUMPER
+
+/* first four bits are buffer dump config
+ * second four bits are texture dump config
+ * config flags:
+ * 1 - blit on enter
+ * 2 - blit on exit
+ *
+ *
+ * Example:
+ *
+ * 0x03 - dump buffer on enter and exit
+ * 0x22 - dump texture and buffer on exit */
+
+int64_t g_CrDbgDumpPid = 0;
+unsigned long g_CrDbgDumpEnabled = 0;
+unsigned long g_CrDbgDumpDraw = 0
+#if 0
+ | CR_SERVER_DUMP_F_COMPILE_SHADER
+ | CR_SERVER_DUMP_F_LINK_PROGRAM
+#endif
+ ;
+#if 0
+ | CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
+ | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER
+ | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
+ | CR_SERVER_DUMP_F_DRAW_STATE_ENTER
+ | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER
+ | CR_SERVER_DUMP_F_DRAWEL
+ | CR_SERVER_DUMP_F_SHADER_SOURCE
+ ;
+#endif
+unsigned long g_CrDbgDumpDrawFramesSettings = CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
+ | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
+ | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
+ | CR_SERVER_DUMP_F_COMPILE_SHADER
+ | CR_SERVER_DUMP_F_LINK_PROGRAM
+ | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER;
+unsigned long g_CrDbgDumpDrawFramesAppliedSettings = 0;
+unsigned long g_CrDbgDumpDrawFramesSavedInitSettings = 0;
+unsigned long g_CrDbgDumpDrawFramesCount = 0;
+
+uint32_t g_CrDbgDumpDrawCount = 0;
+uint32_t g_CrDbgDumpDumpOnCount = 10;
+uint32_t g_CrDbgDumpDumpOnCountEnabled = 0;
+uint32_t g_CrDbgDumpDumpOnCountPerform = 0;
+uint32_t g_CrDbgDumpDrawFlags = CR_SERVER_DUMP_F_COMPILE_SHADER
+ | CR_SERVER_DUMP_F_SHADER_SOURCE
+ | CR_SERVER_DUMP_F_COMPILE_SHADER
+ | CR_SERVER_DUMP_F_LINK_PROGRAM
+ | CR_SERVER_DUMP_F_DRAW_BUFF_ENTER
+ | CR_SERVER_DUMP_F_DRAW_BUFF_LEAVE
+ | CR_SERVER_DUMP_F_DRAW_TEX_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_UNIFORMS_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ATTRIBS_ENTER
+ | CR_SERVER_DUMP_F_DRAW_PROGRAM_ENTER
+ | CR_SERVER_DUMP_F_DRAW_STATE_ENTER
+ | CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER
+ | CR_SERVER_DUMP_F_DRAWEL
+ | CR_SERVER_DUMP_F_TEXPRESENT;
+
+void crServerDumpCheckTerm()
+{
+ if (!CrBltIsInitialized(&cr_server.RecorderBlitter))
+ return;
+
+ CrBltTerm(&cr_server.RecorderBlitter);
+}
+
+int crServerDumpCheckInit()
+{
+ int rc;
+ CR_BLITTER_WINDOW BltWin;
+ CR_BLITTER_CONTEXT BltCtx;
+ CRMuralInfo *pBlitterMural;
+
+ if (!CrBltIsInitialized(&cr_server.RecorderBlitter))
+ {
+ pBlitterMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ if (!pBlitterMural)
+ {
+ crWarning("crServerGetDummyMural failed");
+ return VERR_GENERAL_FAILURE;
+ }
+
+ crServerVBoxBlitterWinInit(&BltWin, pBlitterMural);
+ crServerVBoxBlitterCtxInit(&BltCtx, &cr_server.MainContextInfo);
+
+ rc = CrBltInit(&cr_server.RecorderBlitter, &BltCtx, true, true, NULL, &cr_server.TmpCtxDispatch);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltInit failed rc %d", rc);
+ return rc;
+ }
+
+ rc = CrBltMuralSetCurrentInfo(&cr_server.RecorderBlitter, &BltWin);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("CrBltMuralSetCurrentInfo failed rc %d", rc);
+ return rc;
+ }
+ }
+
+#if 0
+ crDmpDbgPrintInit(&cr_server.DbgPrintDumper);
+ cr_server.pDumper = &cr_server.DbgPrintDumper.Base;
+#else
+ if (!crDmpHtmlIsInited(&cr_server.HtmlDumper))
+ {
+ static int cCounter = 0;
+// crDmpHtmlInit(&cr_server.HtmlDumper, "S:\\projects\\virtualbox\\3d\\dumps\\1", "index.html");
+ crDmpHtmlInitF(&cr_server.HtmlDumper, "/Users/oracle-mac/vbox/dump/1", "index%d.html", cCounter);
+ cr_server.pDumper = &cr_server.HtmlDumper.Base;
+ ++cCounter;
+ }
+#endif
+
+ crRecInit(&cr_server.Recorder, &cr_server.RecorderBlitter, &cr_server.TmpCtxDispatch, cr_server.pDumper);
+ return VINF_SUCCESS;
+}
+
+void crServerDumpShader(GLint id)
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecDumpShader(&cr_server.Recorder, ctx, id, 0);
+}
+
+void crServerDumpProgram(GLint id)
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecDumpProgram(&cr_server.Recorder, ctx, id, 0);
+}
+
+void crServerDumpCurrentProgram()
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecDumpCurrentProgram(&cr_server.Recorder, ctx);
+}
+
+void crServerDumpRecompileDumpCurrentProgram()
+{
+ crDmpStrF(cr_server.Recorder.pDumper, "==Dump(1)==");
+ crServerRecompileCurrentProgram();
+ crServerDumpCurrentProgramUniforms();
+ crServerDumpCurrentProgramAttribs();
+ crDmpStrF(cr_server.Recorder.pDumper, "Done Dump(1)");
+ crServerRecompileCurrentProgram();
+ crDmpStrF(cr_server.Recorder.pDumper, "Dump(2)");
+ crServerRecompileCurrentProgram();
+ crServerDumpCurrentProgramUniforms();
+ crServerDumpCurrentProgramAttribs();
+ crDmpStrF(cr_server.Recorder.pDumper, "Done Dump(2)");
+}
+
+void crServerRecompileCurrentProgram()
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecRecompileCurrentProgram(&cr_server.Recorder, ctx);
+}
+
+void crServerDumpCurrentProgramUniforms()
+{
+ CRContext *ctx = crStateGetCurrent();
+ crDmpStrF(cr_server.Recorder.pDumper, "==Uniforms==");
+ crRecDumpCurrentProgramUniforms(&cr_server.Recorder, ctx);
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done Uniforms==");
+}
+
+void crServerDumpCurrentProgramAttribs()
+{
+ CRContext *ctx = crStateGetCurrent();
+ crDmpStrF(cr_server.Recorder.pDumper, "==Attribs==");
+ crRecDumpCurrentProgramAttribs(&cr_server.Recorder, ctx);
+ crDmpStrF(cr_server.Recorder.pDumper, "==Done Attribs==");
+}
+
+void crServerDumpState()
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecDumpGlGetState(&cr_server.Recorder, ctx);
+ crRecDumpGlEnableState(&cr_server.Recorder, ctx);
+}
+
+void crServerDumpDrawel(const char*pszFormat, ...)
+{
+ CRContext *ctx = crStateGetCurrent();
+ va_list pArgList;
+ va_start(pArgList, pszFormat);
+ crRecDumpVertAttrV(&cr_server.Recorder, ctx, pszFormat, pArgList);
+ va_end(pArgList);
+}
+
+void crServerDumpDrawelv(GLuint idx, const char*pszElFormat, uint32_t cbEl, const void *pvVal, uint32_t cVal)
+{
+ CRContext *ctx = crStateGetCurrent();
+ crRecDumpVertAttrv(&cr_server.Recorder, ctx, idx, pszElFormat, cbEl, pvVal, cVal);
+}
+
+void crServerDumpBuffer(int idx)
+{
+ CRContextInfo *pCtxInfo = cr_server.currentCtxInfo;
+ CR_BLITTER_WINDOW BltWin;
+ CR_BLITTER_CONTEXT BltCtx;
+ CRContext *ctx = crStateGetCurrent();
+ GLint idFBO;
+ GLint idTex;
+ VBOXVR_TEXTURE RedirTex;
+ int rc = crServerDumpCheckInit();
+ idx = idx >= 0 ? idx : crServerMuralFBOIdxFromBufferName(cr_server.currentMural, pCtxInfo->pContext->buffer.drawBuffer);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerDumpCheckInit failed, rc %d", rc);
+ return;
+ }
+
+ if (idx < 0)
+ {
+ crWarning("neg idx, unsupported");
+ return;
+ }
+
+ idFBO = CR_SERVER_FBO_FOR_IDX(cr_server.currentMural, idx);
+ idTex = CR_SERVER_FBO_TEX_FOR_IDX(cr_server.currentMural, idx);
+
+ crServerVBoxBlitterWinInit(&BltWin, cr_server.currentMural);
+ crServerVBoxBlitterCtxInit(&BltCtx, pCtxInfo);
+
+ RedirTex.width = cr_server.currentMural->fboWidth;
+ RedirTex.height = cr_server.currentMural->fboHeight;
+ RedirTex.target = GL_TEXTURE_2D;
+ RedirTex.hwid = idTex;
+
+ crRecDumpBuffer(&cr_server.Recorder, ctx, &BltCtx, &BltWin, idFBO, idTex ? &RedirTex : NULL);
+}
+
+void crServerDumpTexture(const VBOXVR_TEXTURE *pTex)
+{
+ CRContextInfo *pCtxInfo = cr_server.currentCtxInfo;
+ CR_BLITTER_WINDOW BltWin;
+ CR_BLITTER_CONTEXT BltCtx;
+ CRContext *ctx = crStateGetCurrent();
+ int rc = crServerDumpCheckInit();
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerDumpCheckInit failed, rc %d", rc);
+ return;
+ }
+
+ crServerVBoxBlitterWinInit(&BltWin, cr_server.currentMural);
+ crServerVBoxBlitterCtxInit(&BltCtx, pCtxInfo);
+
+ crRecDumpTextureF(&cr_server.Recorder, pTex, &BltCtx, &BltWin, "Tex (%d x %d), hwid (%d) target %#x", pTex->width, pTex->height, pTex->hwid, pTex->target);
+}
+
+void crServerDumpTextures()
+{
+ CRContextInfo *pCtxInfo = cr_server.currentCtxInfo;
+ CR_BLITTER_WINDOW BltWin;
+ CR_BLITTER_CONTEXT BltCtx;
+ CRContext *ctx = crStateGetCurrent();
+ int rc = crServerDumpCheckInit();
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerDumpCheckInit failed, rc %d", rc);
+ return;
+ }
+
+ crServerVBoxBlitterWinInit(&BltWin, cr_server.currentMural);
+ crServerVBoxBlitterCtxInit(&BltCtx, pCtxInfo);
+
+ crRecDumpTextures(&cr_server.Recorder, ctx, &BltCtx, &BltWin);
+}
+
+void crServerDumpFilterOpLeave(unsigned long event, CR_DUMPER *pDumper)
+{
+ if (CR_SERVER_DUMP_F_DRAW_LEAVE_ALL & event)
+ {
+ g_CrDbgDumpDumpOnCountPerform = 0;
+ }
+}
+
+bool crServerDumpFilterOpEnter(unsigned long event, CR_DUMPER *pDumper)
+{
+ if ((CR_SERVER_DUMP_F_SWAPBUFFERS_ENTER & event)
+ || (CR_SERVER_DUMP_F_TEXPRESENT & event))
+ {
+ if (g_CrDbgDumpDumpOnCountEnabled == 1)
+ g_CrDbgDumpDumpOnCountEnabled = 2;
+ else if (g_CrDbgDumpDumpOnCountEnabled)
+ {
+ g_CrDbgDumpDumpOnCountEnabled = 0;
+ if (cr_server.pDumper == &cr_server.HtmlDumper.Base)
+ {
+ crDmpHtmlTerm(&cr_server.HtmlDumper);
+ cr_server.pDumper = NULL;
+ }
+ }
+
+ g_CrDbgDumpDrawCount = 0;
+ }
+ else if (CR_SERVER_DUMP_F_DRAW_ENTER_ALL & event)
+ {
+ if (g_CrDbgDumpDumpOnCountEnabled == 2)
+ {
+ if (g_CrDbgDumpDumpOnCount == g_CrDbgDumpDrawCount)
+ {
+ g_CrDbgDumpDumpOnCountPerform = 1;
+ }
+ ++g_CrDbgDumpDrawCount;
+ }
+ }
+ if (g_CrDbgDumpDumpOnCountPerform)
+ {
+ if (g_CrDbgDumpDrawFlags & event)
+ return true;
+ }
+ return CR_SERVER_DUMP_DEFAULT_FILTER_OP(event);
+}
+
+bool crServerDumpFilterDmp(unsigned long event, CR_DUMPER *pDumper)
+{
+ if (g_CrDbgDumpDumpOnCountPerform)
+ {
+ if (g_CrDbgDumpDrawFlags & event)
+ return true;
+ }
+ return CR_SERVER_DUMP_DEFAULT_FILTER_DMP(event);
+}
+
+void crServerDumpFramesCheck()
+{
+ if (!g_CrDbgDumpDrawFramesCount)
+ return;
+
+ if (!g_CrDbgDumpDrawFramesAppliedSettings)
+ {
+ if (!g_CrDbgDumpDrawFramesSettings)
+ {
+ crWarning("g_CrDbgDumpDrawFramesSettings is NULL, bump will not be started");
+ g_CrDbgDumpDrawFramesCount = 0;
+ return;
+ }
+
+ g_CrDbgDumpDrawFramesSavedInitSettings = g_CrDbgDumpDraw;
+ g_CrDbgDumpDrawFramesAppliedSettings = g_CrDbgDumpDrawFramesSettings;
+ g_CrDbgDumpDraw = g_CrDbgDumpDrawFramesSettings;
+ crDmpStrF(cr_server.Recorder.pDumper, "***Starting draw dump for %d frames, settings(0x%x)", g_CrDbgDumpDrawFramesCount, g_CrDbgDumpDraw);
+ return;
+ }
+
+ --g_CrDbgDumpDrawFramesCount;
+
+ if (!g_CrDbgDumpDrawFramesCount)
+ {
+ crDmpStrF(cr_server.Recorder.pDumper, "***Stop draw dump");
+ g_CrDbgDumpDraw = g_CrDbgDumpDrawFramesSavedInitSettings;
+ g_CrDbgDumpDrawFramesAppliedSettings = 0;
+ }
+}
+#endif
+
+GLvoid crServerSpriteCoordReplEnable(GLboolean fEnable)
+{
+ CRContext *g = crStateGetCurrent();
+ CRTextureState *t = &(g->texture);
+ GLuint curTextureUnit = t->curTextureUnit;
+ GLuint curTextureUnitRestore = curTextureUnit;
+ GLuint i;
+
+ for (i = 0; i < g->limits.maxTextureUnits; ++i)
+ {
+ if (g->point.coordReplacement[i])
+ {
+ if (i != curTextureUnit)
+ {
+ curTextureUnit = i;
+ cr_server.head_spu->dispatch_table.ActiveTextureARB( i + GL_TEXTURE0_ARB );
+ }
+
+ cr_server.head_spu->dispatch_table.TexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, (GLint)fEnable);
+ }
+ }
+
+ if (curTextureUnit != curTextureUnitRestore)
+ {
+ cr_server.head_spu->dispatch_table.ActiveTextureARB( curTextureUnitRestore + GL_TEXTURE0_ARB );
+ }
+}
+
+GLvoid SERVER_DISPATCH_APIENTRY crServerDispatchDrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+#ifdef DEBUG
+ GLenum status = cr_server.head_spu->dispatch_table.CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
+ Assert(GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_TRUE);
+ CR_SERVER_DUMP_DRAW_ENTER();
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.DrawArrays(mode, first, count););
+ CR_SERVER_DUMP_DRAW_LEAVE();
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+GLvoid SERVER_DISPATCH_APIENTRY crServerDispatchDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)
+{
+#ifdef DEBUG
+ GLenum status = cr_server.head_spu->dispatch_table.CheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER_EXT);
+ Assert(GL_FRAMEBUFFER_COMPLETE == status);
+#endif
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_TRUE);
+ CR_SERVER_DUMP_DRAW_ENTER();
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.DrawElements(mode, count, type, indices););
+ CR_SERVER_DUMP_DRAW_LEAVE();
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchEnd( void )
+{
+ CRContext *g = crStateGetCurrent();
+ GLenum mode = g->current.mode;
+
+ crStateEnd();
+ cr_server.head_spu->dispatch_table.End();
+
+ CR_SERVER_DUMP_DRAW_LEAVE();
+
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_FALSE);
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchBegin(GLenum mode)
+{
+#ifdef DEBUG
+ CRContext *ctx = crStateGetCurrent();
+ SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
+
+ if (ctx->program.vpProgramBinding)
+ {
+ AssertRelease(ctx->program.currentVertexProgram);
+
+ if (ctx->program.currentVertexProgram->isARBprogram)
+ {
+ GLint pid=-1;
+ gl->GetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_BINDING_ARB, &pid);
+
+ if (pid != ctx->program.currentVertexProgram->id)
+ {
+ crWarning("pid(%d) != ctx->program.currentVertexProgram->id(%d)", pid, ctx->program.currentVertexProgram->id);
+ }
+ AssertRelease(pid == ctx->program.currentVertexProgram->id);
+ }
+ else
+ {
+ GLint pid=-1;
+
+ gl->GetIntegerv(GL_VERTEX_PROGRAM_BINDING_NV, &pid);
+ if (pid != ctx->program.currentVertexProgram->id)
+ {
+ crWarning("pid(%d) != ctx->program.currentVertexProgram->id(%d)", pid, ctx->program.currentVertexProgram->id);
+ }
+ AssertRelease(pid == ctx->program.currentVertexProgram->id);
+ }
+ }
+ else if (ctx->glsl.activeProgram)
+ {
+ GLint pid=-1;
+
+ gl->GetIntegerv(GL_CURRENT_PROGRAM, &pid);
+ crDebug("pid %i, state: id %i, hwid %i", pid, ctx->glsl.activeProgram->id, ctx->glsl.activeProgram->hwid);
+ if (pid != ctx->glsl.activeProgram->hwid)
+ {
+ crWarning("pid(%d) != ctx->glsl.activeProgram->hwid(%d)", pid, ctx->glsl.activeProgram->hwid);
+ }
+ AssertRelease(pid == ctx->glsl.activeProgram->hwid);
+ }
+#endif
+
+ if (mode == GL_POINTS)
+ crServerSpriteCoordReplEnable(GL_TRUE);
+
+ CR_SERVER_DUMP_DRAW_ENTER();
+
+ crStateBegin(mode);
+ cr_server.head_spu->dispatch_table.Begin(mode);
+}
+
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
deleted file mode 100644
index f42ed0c7..00000000
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.c
+++ /dev/null
@@ -1,591 +0,0 @@
-/* $Id: server_muralfbo.c $ */
-
-/** @file
- * VBox crOpenGL: Window to FBO redirect support.
- */
-
-/*
- * Copyright (C) 2010 Oracle Corporation
- *
- * This file is part of VirtualBox Open Source Edition (OSE), as
- * available from http://www.virtualbox.org. This file is free software;
- * you can redistribute it and/or modify it under the terms of the GNU
- * General Public License (GPL) as published by the Free Software
- * Foundation, in version 2 as it comes in the "COPYING" file of the
- * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
- * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
- */
-
-#include "server.h"
-#include "cr_string.h"
-#include "cr_mem.h"
-#include "render/renderspu.h"
-
-static int crServerGetPointScreen(GLint x, GLint y)
-{
- int i;
-
- for (i=0; i<cr_server.screenCount; ++i)
- {
- if ((x>=cr_server.screen[i].x && x<cr_server.screen[i].x+(int)cr_server.screen[i].w)
- && (y>=cr_server.screen[i].y && y<cr_server.screen[i].y+(int)cr_server.screen[i].h))
- {
- return i;
- }
- }
-
- return -1;
-}
-
-static GLboolean crServerMuralCoverScreen(CRMuralInfo *mural, int sId)
-{
- return mural->gX < cr_server.screen[sId].x
- && mural->gX+(int)mural->width > cr_server.screen[sId].x+(int)cr_server.screen[sId].w
- && mural->gY < cr_server.screen[sId].y
- && mural->gY+(int)mural->height > cr_server.screen[sId].y+(int)cr_server.screen[sId].h;
-}
-
-/* Called when a new CRMuralInfo is created
- * or when OutputRedirect status is changed.
- */
-void crServerSetupOutputRedirect(CRMuralInfo *mural)
-{
- /* Unset the previous redirect. */
- if (mural->pvOutputRedirectInstance)
- {
- cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
- mural->pvOutputRedirectInstance = NULL;
- }
-
- /* Setup a new redirect. */
- if (cr_server.bUseOutputRedirect)
- {
- /* Query supported formats. */
- uint32_t cbFormats = 4096;
- char *pachFormats = (char *)crAlloc(cbFormats);
-
- if (pachFormats)
- {
- int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
- 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
- pachFormats, cbFormats, &cbFormats);
- if (RT_SUCCESS(rc))
- {
- if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
- {
- cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
- &mural->pvOutputRedirectInstance,
- "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
- }
- }
-
- crFree(pachFormats);
- }
-
- /* If this is not NULL then there was a supported format. */
- if (mural->pvOutputRedirectInstance)
- {
- cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
- mural->hX, mural->hY,
- mural->width, mural->height);
- // @todo the code assumes that RTRECT == four of GLInts
- cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
- mural->cVisibleRects, (RTRECT *)mural->pVisibleRects);
- }
- }
-}
-
-void crServerCheckMuralGeometry(CRMuralInfo *mural)
-{
- int tlS, brS, trS, blS;
- int overlappingScreenCount, primaryS, i;
-
- if (!mural->width || !mural->height)
- return;
-
- if (cr_server.screenCount<2 && !cr_server.bForceOffscreenRendering)
- {
- CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
- CRASSERT(cr_server.screenCount>0);
-
- mural->hX = mural->gX-cr_server.screen[0].x;
- mural->hY = mural->gY-cr_server.screen[0].y;
-
- cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
-
- return;
- }
-
- tlS = crServerGetPointScreen(mural->gX, mural->gY);
- brS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY+mural->height-1);
-
- if (tlS==brS && tlS>=0)
- {
- overlappingScreenCount = 1;
- primaryS = tlS;
- }
- else
- {
- trS = crServerGetPointScreen(mural->gX+mural->width-1, mural->gY);
- blS = crServerGetPointScreen(mural->gX, mural->gY+mural->height-1);
-
- primaryS = -1; overlappingScreenCount = 0;
- for (i=0; i<cr_server.screenCount; ++i)
- {
- if ((i==tlS) || (i==brS) || (i==trS) || (i==blS)
- || crServerMuralCoverScreen(mural, i))
- {
- overlappingScreenCount++;
- primaryS = primaryS<0 ? i:primaryS;
- }
- }
-
- if (!overlappingScreenCount)
- {
- primaryS = 0;
- }
- }
-
- if (primaryS!=mural->screenId)
- {
- mural->screenId = primaryS;
-
- renderspuSetWindowId(cr_server.screen[primaryS].winID);
- renderspuReparentWindow(mural->spuWindow);
- renderspuSetWindowId(cr_server.screen[0].winID);
- }
-
- mural->hX = mural->gX-cr_server.screen[primaryS].x;
- mural->hY = mural->gY-cr_server.screen[primaryS].y;
-
- if (overlappingScreenCount<2 && !cr_server.bForceOffscreenRendering)
- {
- CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
-
- if (mural->bUseFBO)
- {
- crServerRedirMuralFBO(mural, GL_FALSE);
- crServerDeleteMuralFBO(mural);
- }
-
- cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
- }
- else
- {
- if (mural->spuWindow)
- {
- if (!mural->bUseFBO)
- {
- crServerRedirMuralFBO(mural, GL_TRUE);
- }
- else
- {
- if (mural->width!=mural->fboWidth
- || mural->height!=mural->height)
- {
- crServerRedirMuralFBO(mural, GL_FALSE);
- crServerDeleteMuralFBO(mural);
- crServerRedirMuralFBO(mural, GL_TRUE);
- }
- }
- }
-#ifdef DEBUG_misha
- else
- {
- Assert(!mural->bUseFBO);
- }
-#endif
-
- if (!mural->bUseFBO)
- {
- CRScreenViewportInfo *pVieport = &cr_server.screenVieport[mural->screenId];
-
- cr_server.head_spu->dispatch_table.WindowPosition(mural->spuWindow, mural->hX - pVieport->x, mural->hY - pVieport->y);
- }
- }
-
- if (mural->pvOutputRedirectInstance)
- {
- cr_server.outputRedirect.CRORGeometry(mural->pvOutputRedirectInstance,
- mural->hX, mural->hY,
- mural->width, mural->height);
- }
-}
-
-GLboolean crServerSupportRedirMuralFBO(void)
-{
- static GLboolean fInited = GL_FALSE;
- static GLboolean fSupported = GL_FALSE;
- if (!fInited)
- {
- const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
-
- fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
- || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
- && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
- fInited = GL_TRUE;
- }
- return fSupported;
-}
-
-void crServerRedirMuralFBO(CRMuralInfo *mural, GLboolean redir)
-{
- if (redir)
- {
- if (!crServerSupportRedirMuralFBO())
- {
- crWarning("FBO not supported, can't redirect window output");
- return;
- }
-
- cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, GL_FALSE);
-
- if (mural->idFBO==0)
- {
- crServerCreateMuralFBO(mural);
- }
-
- if (!crStateGetCurrent()->framebufferobject.drawFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, mural->idFBO);
- }
- if (!crStateGetCurrent()->framebufferobject.readFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, mural->idFBO);
- }
-
- if (cr_server.curClient && cr_server.curClient->currentMural == mural)
- {
- crStateGetCurrent()->buffer.width = 0;
- crStateGetCurrent()->buffer.height = 0;
- }
- }
- else
- {
- cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, mural->bVisible);
-
- if (mural->bUseFBO && crServerSupportRedirMuralFBO())
- {
- if (!crStateGetCurrent()->framebufferobject.drawFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
- }
- if (!crStateGetCurrent()->framebufferobject.readFB)
- {
- cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
- }
- }
-
- if (cr_server.curClient && cr_server.curClient->currentMural == mural)
- {
- crStateGetCurrent()->buffer.width = mural->width;
- crStateGetCurrent()->buffer.height = mural->height;
- }
- }
-
- mural->bUseFBO = redir;
-}
-
-void crServerCreateMuralFBO(CRMuralInfo *mural)
-{
- CRContext *ctx = crStateGetCurrent();
- GLuint uid;
- GLenum status;
- SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
-
- CRASSERT(mural->idFBO==0);
-
- /*Color texture*/
- gl->GenTextures(1, &mural->idColorTex);
- gl->BindTexture(GL_TEXTURE_2D, mural->idColorTex);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
- gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
- if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
- {
- gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
- }
- gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
- 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
-
- /*Depth&Stencil*/
- gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
- gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
- gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
- mural->width, mural->height);
-
- /*FBO*/
- gl->GenFramebuffersEXT(1, &mural->idFBO);
- gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->idFBO);
-
- gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- GL_TEXTURE_2D, mural->idColorTex, 0);
- gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
- gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
- GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
-
- status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
- if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
- {
- crWarning("FBO status(0x%x) isn't complete", status);
- }
-
- mural->fboWidth = mural->width;
- mural->fboHeight = mural->height;
-
- /*PBO*/
- if (cr_server.bUsePBOForReadback)
- {
- gl->GenBuffersARB(1, &mural->idPBO);
- gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
- gl->BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, mural->width*mural->height*4, 0, GL_STREAM_READ_ARB);
- gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
-
- if (!mural->idPBO)
- {
- crWarning("PBO create failed");
- }
- }
-
- /*Restore gl state*/
- uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
- gl->BindTexture(GL_TEXTURE_2D, uid);
-
- uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
- gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
-
- uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
- gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
-
- uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
- gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
-
- if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
- {
- gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
- }
-}
-
-void crServerDeleteMuralFBO(CRMuralInfo *mural)
-{
- CRASSERT(!mural->bUseFBO);
-
- if (mural->idFBO!=0)
- {
- cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->idColorTex);
- cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
- cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->idFBO);
-
- mural->idFBO = 0;
- mural->idColorTex = 0;
- mural->idDepthStencilRB = 0;
- }
-
- if (mural->idPBO!=0)
- {
- CRASSERT(cr_server.bUsePBOForReadback);
- cr_server.head_spu->dispatch_table.DeleteBuffersARB(1, &mural->idPBO);
- mural->idPBO = 0;
- }
-}
-
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#define MAX(a, b) ((a) > (b) ? (a) : (b))
-
-static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
-{
- CRASSERT(a && b && rect);
-
- rect->x1 = MAX(a->x1, b->x1);
- rect->x2 = MIN(a->x2, b->x2);
- rect->y1 = MAX(a->y1, b->y1);
- rect->y2 = MIN(a->y2, b->y2);
-
- return (rect->x2>rect->x1) && (rect->y2>rect->y1);
-}
-
-static GLboolean crServerIntersectScreen(CRMuralInfo *mural, int sId, CRrecti *rect)
-{
- rect->x1 = MAX(mural->gX, cr_server.screen[sId].x);
- rect->x2 = MIN(mural->gX+(int)mural->fboWidth, cr_server.screen[sId].x+(int)cr_server.screen[sId].w);
- rect->y1 = MAX(mural->gY, cr_server.screen[sId].y);
- rect->y2 = MIN(mural->gY+(int)mural->fboHeight, cr_server.screen[sId].y+(int)cr_server.screen[sId].h);
-
- return (rect->x2>rect->x1) && (rect->y2>rect->y1);
-}
-
-static void crServerCopySubImage(char *pDst, char* pSrc, CRrecti *pRect, int srcWidth, int srcHeight)
-{
- int i;
- int dstrowsize = 4*(pRect->x2-pRect->x1);
- int srcrowsize = 4*srcWidth;
- int height = pRect->y2-pRect->y1;
-
- pSrc += 4*pRect->x1 + srcrowsize*(srcHeight-1-pRect->y1);
-
- for (i=0; i<height; ++i)
- {
- crMemcpy(pDst, pSrc, dstrowsize);
-
- pSrc -= srcrowsize;
- pDst += dstrowsize;
- }
-}
-
-static void crServerTransformRect(CRrecti *pDst, CRrecti *pSrc, int dx, int dy)
-{
- pDst->x1 = pSrc->x1+dx;
- pDst->x2 = pSrc->x2+dx;
- pDst->y1 = pSrc->y1+dy;
- pDst->y2 = pSrc->y2+dy;
-}
-
-void crServerPresentFBO(CRMuralInfo *mural)
-{
- char *pixels=NULL, *tmppixels;
- GLuint uid;
- int i, j;
- CRrecti rect, rectwr, sectr;
- GLboolean bUsePBO;
- CRContext *ctx = crStateGetCurrent();
-
- CRASSERT(cr_server.pfnPresentFBO);
-
- if (!mural->bVisible)
- {
- return;
- }
-
- if (!mural->width || !mural->height)
- {
- return;
- }
-
- if (cr_server.bUsePBOForReadback && !mural->idPBO)
- {
- crWarning("Mural doesn't have PBO even though bUsePBOForReadback is set!");
- }
-
- bUsePBO = cr_server.bUsePBOForReadback && mural->idPBO;
-
- cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, mural->idColorTex);
-
- if (bUsePBO)
- {
- CRASSERT(mural->idPBO);
- cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, mural->idPBO);
- }
- else
- {
- if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
- {
- cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
- }
-
- pixels = crAlloc(4*mural->fboWidth*mural->fboHeight);
- if (!pixels)
- {
- crWarning("Out of memory in crServerPresentFBO");
- return;
- }
- }
-
- /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
- cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pixels);
-
- /*restore gl state*/
- uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
- cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
-
- if (bUsePBO)
- {
- pixels = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
- if (!pixels)
- {
- crWarning("Failed to MapBuffer in crServerPresentFBO");
- return;
- }
- }
-
- for (i=0; i<cr_server.screenCount; ++i)
- {
- if (crServerIntersectScreen(mural, i, &rect))
- {
- /* rect in window relative coords */
- crServerTransformRect(&rectwr, &rect, -mural->gX, -mural->gY);
-
- if (!mural->pVisibleRects)
- {
- /*we don't get any rects info for guest compiz windows, so we treat windows as visible unless explicitly received 0 visible rects*/
- if (!mural->bReceivedRects)
- {
- tmppixels = crAlloc(4*(rect.x2-rect.x1)*(rect.y2-rect.y1));
- if (!tmppixels)
- {
- crWarning("Out of memory in crServerPresentFBO");
- crFree(pixels);
- return;
- }
-
- crServerCopySubImage(tmppixels, pixels, &rectwr, mural->fboWidth, mural->fboHeight);
- /*Note: pfnPresentFBO would free tmppixels*/
- cr_server.pfnPresentFBO(tmppixels, i, rect.x1-cr_server.screen[i].x, rect.y1-cr_server.screen[i].y, rect.x2-rect.x1, rect.y2-rect.y1);
- }
- }
- else
- {
- for (j=0; j<mural->cVisibleRects; ++j)
- {
- if (crServerIntersectRect(&rectwr, (CRrecti*) &mural->pVisibleRects[4*j], &sectr))
- {
- tmppixels = crAlloc(4*(sectr.x2-sectr.x1)*(sectr.y2-sectr.y1));
- if (!tmppixels)
- {
- crWarning("Out of memory in crServerPresentFBO");
- crFree(pixels);
- return;
- }
-
- crServerCopySubImage(tmppixels, pixels, &sectr, mural->fboWidth, mural->fboHeight);
- /*Note: pfnPresentFBO would free tmppixels*/
- cr_server.pfnPresentFBO(tmppixels, i,
- sectr.x1+mural->gX-cr_server.screen[i].x,
- sectr.y1+mural->gY-cr_server.screen[i].y,
- sectr.x2-sectr.x1, sectr.y2-sectr.y1);
- }
- }
- }
- }
- }
-
- if (mural->pvOutputRedirectInstance)
- {
- /* @todo find out why presentfbo is not called but crorframe is called. */
- cr_server.outputRedirect.CRORFrame(mural->pvOutputRedirectInstance,
- pixels,
- 4 * mural->fboWidth * mural->fboHeight);
- }
-
- if (bUsePBO)
- {
- cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
- cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
- }
- else
- {
- crFree(pixels);
- if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
- {
- cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
- }
- }
-}
-
-GLboolean crServerIsRedirectedToFBO()
-{
- return cr_server.curClient
- && cr_server.curClient->currentMural
- && cr_server.curClient->currentMural->bUseFBO;
-}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp
new file mode 100644
index 00000000..10cdf5cf
--- /dev/null
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_muralfbo.cpp
@@ -0,0 +1,840 @@
+/* $Id: server_muralfbo.cpp $ */
+
+/** @file
+ * VBox crOpenGL: Window to FBO redirect support.
+ */
+
+/*
+ * Copyright (C) 2010-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include "server.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_vreg.h"
+#include "render/renderspu.h"
+
+static void crServerRedirMuralFbSync(CRMuralInfo *mural);
+
+void crServerCheckMuralGeometry(CRMuralInfo *mural)
+{
+ if (!mural->CreateInfo.externalID)
+ return;
+
+ CRASSERT(mural->spuWindow);
+ CRASSERT(mural->spuWindow != CR_RENDER_DEFAULT_WINDOW_ID);
+
+ if (!mural->width || !mural->height
+ || mural->fboWidth != mural->width
+ || mural->fboHeight != mural->height)
+ {
+ crServerRedirMuralFbClear(mural);
+ crServerRedirMuralFBO(mural, false);
+ crServerDeleteMuralFBO(mural);
+ }
+
+ if (!mural->width || !mural->height)
+ return;
+
+ crServerRedirMuralFBO(mural, true);
+ crServerRedirMuralFbSync(mural);
+}
+
+static void crServerCheckMuralGeometryCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo *pMI = (CRMuralInfo*) data1;
+
+ if (!pMI->fRedirected || pMI == data2)
+ return;
+
+ crServerCheckMuralGeometry(pMI);
+}
+
+
+void crServerCheckAllMuralGeometry(CRMuralInfo *pMI)
+{
+ CR_FBMAP Map;
+ int rc = CrPMgrHlpGlblUpdateBegin(&Map);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrPMgrHlpGlblUpdateBegin failed %d", rc));
+ return;
+ }
+
+ crHashtableWalk(cr_server.muralTable, crServerCheckMuralGeometryCB, pMI);
+
+ if (pMI)
+ crServerCheckMuralGeometry(pMI);
+
+ CrPMgrHlpGlblUpdateEnd(&Map);
+}
+
+GLboolean crServerSupportRedirMuralFBO(void)
+{
+ static GLboolean fInited = GL_FALSE;
+ static GLboolean fSupported = GL_FALSE;
+ if (!fInited)
+ {
+ const GLubyte* pExt = cr_server.head_spu->dispatch_table.GetString(GL_REAL_EXTENSIONS);
+
+ fSupported = ( NULL!=crStrstr((const char*)pExt, "GL_ARB_framebuffer_object")
+ || NULL!=crStrstr((const char*)pExt, "GL_EXT_framebuffer_object"))
+ && NULL!=crStrstr((const char*)pExt, "GL_ARB_texture_non_power_of_two");
+ fInited = GL_TRUE;
+ }
+ return fSupported;
+}
+
+static void crServerCreateMuralFBO(CRMuralInfo *mural);
+
+void crServerRedirMuralFbClear(CRMuralInfo *mural)
+{
+ uint32_t i;
+ for (i = 0; i < mural->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = mural->apUsedFBDatas[i];
+ int rc = CrFbUpdateBegin(pData->hFb);
+ if (RT_SUCCESS(rc))
+ {
+ CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+ CrFbUpdateEnd(pData->hFb);
+ }
+ else
+ WARN(("CrFbUpdateBegin failed rc %d", rc));
+ }
+ mural->cUsedFBDatas = 0;
+
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ GLuint j;
+ CR_FBDATA *pData = &mural->aFBDatas[i];
+ if (!pData->hFb)
+ continue;
+
+ CrFbEntryRelease(pData->hFb, pData->hFbEntry);
+ pData->hFbEntry = NULL;
+
+ for (j = 0; j < mural->cBuffers; ++j)
+ {
+ CrTdRelease(pData->apTexDatas[j]);
+ pData->apTexDatas[j] = NULL;
+ }
+
+ pData->hFb = NULL;
+ }
+}
+
+static int crServerRedirMuralDbSyncFb(CRMuralInfo *mural, HCR_FRAMEBUFFER hFb, CR_FBDATA **ppData)
+{
+ CR_FBDATA *pData;
+ const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(hFb);
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
+ RTRECT FbRect = *CrVrScrCompositorRectGet(pCompositor);
+ RTRECT DefaultRegionsRect;
+ const RTRECT * pRegions;
+ uint32_t cRegions;
+ RTPOINT Pos;
+ RTRECT MuralRect;
+ int rc;
+
+ CRASSERT(mural->fRedirected);
+
+ *ppData = NULL;
+
+ if (!mural->bVisible)
+ return VINF_SUCCESS;
+
+ MuralRect.xLeft = mural->gX;
+ MuralRect.yTop = mural->gY;
+ MuralRect.xRight = MuralRect.xLeft + mural->width;
+ MuralRect.yBottom = MuralRect.yTop + mural->height;
+
+ Pos.x = mural->gX - pScreenInfo->i32OriginX;
+ Pos.y = mural->gY - pScreenInfo->i32OriginY;
+
+ VBoxRectTranslate(&FbRect, pScreenInfo->i32OriginX, pScreenInfo->i32OriginY);
+
+ VBoxRectIntersect(&FbRect, &MuralRect);
+
+ if (VBoxRectIsZero(&FbRect))
+ return VINF_SUCCESS;
+
+ if (mural->bReceivedRects)
+ {
+ pRegions = (const RTRECT*)mural->pVisibleRects;
+ cRegions = mural->cVisibleRects;
+ }
+ else
+ {
+ DefaultRegionsRect.xLeft = 0;
+ DefaultRegionsRect.yTop = 0;
+ DefaultRegionsRect.xRight = mural->width;
+ DefaultRegionsRect.yBottom = mural->height;
+ pRegions = &DefaultRegionsRect;
+ cRegions = 1;
+ }
+
+ if (!cRegions)
+ return VINF_SUCCESS;
+
+ pData = &mural->aFBDatas[pScreenInfo->u32ViewIndex];
+
+ if (!pData->hFb)
+ {
+ pData->hFb = hFb;
+
+ for (uint32_t i = 0; i < mural->cBuffers; ++i)
+ {
+ VBOXVR_TEXTURE Tex;
+ Tex.width = mural->width;
+ Tex.height = mural->height;
+ Tex.hwid = mural->aidColorTexs[i];
+ Tex.target = GL_TEXTURE_2D;
+
+ pData->apTexDatas[i] = CrFbTexDataCreate(&Tex);
+ }
+
+ rc = CrFbEntryCreateForTexData(hFb, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)], 0, &pData->hFbEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
+ }
+ }
+ else
+ {
+ CRASSERT(pData->hFb == hFb);
+ }
+
+ rc = CrFbUpdateBegin(hFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbUpdateBegin failed rc %d", rc));
+ return rc;
+ }
+
+ rc = CrFbEntryRegionsSet(hFb, pData->hFbEntry, &Pos, cRegions, pRegions, true);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbEntryRegionsSet failed rc %d", rc));
+ }
+
+ CrFbUpdateEnd(hFb);
+
+ const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry = CrFbEntryGetCompositorEntry(pData->hFbEntry);
+ if (CrVrScrCompositorEntryIsUsed(pCEntry))
+ *ppData = pData;
+
+ return rc;
+}
+
+static void crServerRedirMuralFbSync(CRMuralInfo *mural)
+{
+ uint32_t i;
+ uint32_t cUsedFBs = 0;
+ HCR_FRAMEBUFFER ahUsedFbs[CR_MAX_GUEST_MONITORS];
+ HCR_FRAMEBUFFER hFb;
+
+ for (i = 0; i < mural->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = mural->apUsedFBDatas[i];
+ int rc = CrFbUpdateBegin(pData->hFb);
+ if (RT_SUCCESS(rc))
+ {
+ ahUsedFbs[cUsedFBs] = pData->hFb;
+ CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+ ++cUsedFBs;
+ }
+ else
+ WARN(("CrFbUpdateBegin failed rc %d", rc));
+ }
+ mural->cUsedFBDatas = 0;
+
+ if (!mural->width
+ || !mural->height
+ || !mural->bVisible
+ )
+ goto end;
+
+ CRASSERT(mural->fRedirected);
+
+ for (hFb = CrPMgrFbGetFirstEnabled();
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ CR_FBDATA *pData = NULL;
+ int rc = crServerRedirMuralDbSyncFb(mural, hFb, &pData);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
+ continue;
+ }
+
+ if (!pData)
+ continue;
+
+ mural->apUsedFBDatas[mural->cUsedFBDatas] = pData;
+ ++mural->cUsedFBDatas;
+ }
+
+end:
+
+ for (i = 0; i < cUsedFBs; ++i)
+ {
+ CrFbUpdateEnd(ahUsedFbs[i]);
+ }
+}
+
+static void crVBoxServerMuralFbCleanCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo *pMI = (CRMuralInfo*) data1;
+ HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
+ uint32_t i;
+ for (i = 0; i < pMI->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+ if (hFb != pData->hFb)
+ continue;
+
+ CrFbEntryRegionsSet(pData->hFb, pData->hFbEntry, NULL, 0, NULL, false);
+ break;
+ }
+}
+
+static void crVBoxServerMuralFbSetCB(unsigned long key, void *data1, void *data2)
+{
+ CRMuralInfo *pMI = (CRMuralInfo*) data1;
+ HCR_FRAMEBUFFER hFb = (HCR_FRAMEBUFFER)data2;
+ uint32_t i;
+ CR_FBDATA *pData = NULL;
+ bool fFbWasUsed = false;
+
+ Assert(hFb);
+
+ if (!pMI->fRedirected)
+ {
+ Assert(!pMI->cUsedFBDatas);
+ return;
+ }
+
+ for (i = 0; i < pMI->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+ if (hFb != pData->hFb)
+ continue;
+
+ fFbWasUsed = true;
+ break;
+ }
+
+ if (CrFbIsEnabled(hFb))
+ {
+ int rc = crServerRedirMuralDbSyncFb(pMI, hFb, &pData);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("crServerRedirMuralDbSyncFb failed %d", rc));
+ pData = NULL;
+ }
+ }
+
+ if (pData)
+ {
+ if (!fFbWasUsed)
+ {
+ uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+ for (i = 0; i < pMI->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = pMI->apUsedFBDatas[i];
+ uint32_t idCurScreen = CrFbGetScreenInfo(pData->hFb)->u32ViewIndex;
+ if (idCurScreen > idScreen)
+ break;
+
+ Assert(idCurScreen != idScreen);
+ }
+
+ for (int j = pMI->cUsedFBDatas; j > i; --j)
+ {
+ pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j-1];
+ }
+
+ pMI->apUsedFBDatas[i] = pData;
+ ++pMI->cUsedFBDatas;
+ }
+ /* else - nothing to do */
+ }
+ else
+ {
+ if (fFbWasUsed)
+ {
+ for (int j = i; j < pMI->cUsedFBDatas - 1; ++j)
+ {
+ pMI->apUsedFBDatas[j] = pMI->apUsedFBDatas[j+1];
+ }
+ --pMI->cUsedFBDatas;
+ }
+ /* else - nothing to do */
+ }
+}
+
+void crVBoxServerMuralFbResizeEnd(HCR_FRAMEBUFFER hFb)
+{
+ crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbSetCB, hFb);
+}
+
+void crVBoxServerMuralFbResizeBegin(HCR_FRAMEBUFFER hFb)
+{
+ crHashtableWalk(cr_server.muralTable, crVBoxServerMuralFbCleanCB, hFb);
+}
+
+
+static int crVBoxServerResizeScreen(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
+{
+ int rc;
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGet(pScreen->u32ViewIndex);
+ if (!hFb)
+ {
+ WARN(("CrPMgrFbGet failed"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ rc = CrFbUpdateBegin(hFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbUpdateBegin failed %d", rc));
+ return rc;
+ }
+
+ crVBoxServerMuralFbResizeBegin(hFb);
+
+ rc = CrFbResize(hFb, pScreen, pvVRAM);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbResize failed %d", rc));
+ }
+
+ crVBoxServerMuralFbResizeEnd(hFb);
+
+ CrFbUpdateEnd(hFb);
+
+ CrPMgrNotifyResize(hFb);
+
+ return rc;
+}
+
+DECLEXPORT(int) crVBoxServerNotifyResize(const struct VBVAINFOSCREEN *pScreen, void *pvVRAM)
+{
+ int rc = crVBoxServerResizeScreen(pScreen, pvVRAM);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+}
+
+void crServerRedirMuralFBO(CRMuralInfo *mural, bool fEnabled)
+{
+ if (!mural->fRedirected == !fEnabled)
+ {
+ return;
+ }
+
+ if (!mural->CreateInfo.externalID)
+ {
+ WARN(("trying to change redir setting for internal mural %d", mural->spuWindow));
+ return;
+ }
+
+ if (fEnabled)
+ {
+ if (!crServerSupportRedirMuralFBO())
+ {
+ WARN(("FBO not supported, can't redirect window output"));
+ return;
+ }
+
+ if (mural->aidFBOs[0]==0)
+ {
+ crServerCreateMuralFBO(mural);
+ }
+
+ if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+ {
+ if (!crStateGetCurrent()->framebufferobject.drawFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
+ }
+ if (!crStateGetCurrent()->framebufferobject.readFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+ }
+
+ crStateGetCurrent()->buffer.width = 0;
+ crStateGetCurrent()->buffer.height = 0;
+ }
+ }
+ else
+ {
+ if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+ {
+ if (!crStateGetCurrent()->framebufferobject.drawFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, 0);
+ }
+ if (!crStateGetCurrent()->framebufferobject.readFB)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, 0);
+ }
+
+ crStateGetCurrent()->buffer.width = mural->width;
+ crStateGetCurrent()->buffer.height = mural->height;
+ }
+ }
+
+ mural->fRedirected = !!fEnabled;
+}
+
+static void crServerCreateMuralFBO(CRMuralInfo *mural)
+{
+ CRContext *ctx = crStateGetCurrent();
+ GLuint uid, i;
+ GLenum status;
+ SPUDispatchTable *gl = &cr_server.head_spu->dispatch_table;
+ CRContextInfo *pMuralContextInfo;
+
+ CRASSERT(mural->aidFBOs[0]==0);
+ CRASSERT(mural->aidFBOs[1]==0);
+
+ pMuralContextInfo = cr_server.currentCtxInfo;
+ if (!pMuralContextInfo)
+ {
+ /* happens on saved state load */
+ CRASSERT(cr_server.MainContextInfo.SpuContext);
+ pMuralContextInfo = &cr_server.MainContextInfo;
+ cr_server.head_spu->dispatch_table.MakeCurrent(mural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
+ }
+
+ if (pMuralContextInfo->CreateInfo.realVisualBits != mural->CreateInfo.realVisualBits)
+ {
+ WARN(("mural visual bits do not match with current context visual bits!"));
+ }
+
+ mural->cBuffers = 2;
+ mural->iBbBuffer = 0;
+ /*Color texture*/
+
+ if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ }
+
+ for (i = 0; i < mural->cBuffers; ++i)
+ {
+ gl->GenTextures(1, &mural->aidColorTexs[i]);
+ gl->BindTexture(GL_TEXTURE_2D, mural->aidColorTexs[i]);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ gl->TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, mural->width, mural->height,
+ 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ /*Depth&Stencil*/
+ gl->GenRenderbuffersEXT(1, &mural->idDepthStencilRB);
+ gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+ gl->RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT,
+ mural->width, mural->height);
+
+ /*FBO*/
+ for (i = 0; i < mural->cBuffers; ++i)
+ {
+ gl->GenFramebuffersEXT(1, &mural->aidFBOs[i]);
+ gl->BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mural->aidFBOs[i]);
+
+ gl->FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, mural->aidColorTexs[i], 0);
+ gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+ gl->FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+ GL_RENDERBUFFER_EXT, mural->idDepthStencilRB);
+
+ status = gl->CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ if (status!=GL_FRAMEBUFFER_COMPLETE_EXT)
+ {
+ WARN(("FBO status(0x%x) isn't complete", status));
+ }
+ }
+
+ mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
+ mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
+
+ mural->fboWidth = mural->width;
+ mural->fboHeight = mural->height;
+
+ mural->iCurDrawBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.drawBuffer);
+ mural->iCurReadBuffer = crServerMuralFBOIdxFromBufferName(mural, ctx->buffer.readBuffer);
+
+ /*Restore gl state*/
+ uid = ctx->texture.unit[ctx->texture.curTextureUnit].currentTexture2D->hwid;
+ gl->BindTexture(GL_TEXTURE_2D, uid);
+
+ uid = ctx->framebufferobject.renderbuffer ? ctx->framebufferobject.renderbuffer->hwid:0;
+ gl->BindRenderbufferEXT(GL_RENDERBUFFER_EXT, uid);
+
+ uid = ctx->framebufferobject.drawFB ? ctx->framebufferobject.drawFB->hwid:0;
+ gl->BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, uid);
+
+ uid = ctx->framebufferobject.readFB ? ctx->framebufferobject.readFB->hwid:0;
+ gl->BindFramebufferEXT(GL_READ_FRAMEBUFFER, uid);
+
+ if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ gl->BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, ctx->bufferobject.unpackBuffer->hwid);
+ }
+
+ if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
+ {
+ gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, ctx->bufferobject.packBuffer->hwid);
+ }
+ else
+ {
+ gl->BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+
+ CRASSERT(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
+}
+
+void crServerDeleteMuralFBO(CRMuralInfo *mural)
+{
+ if (mural->aidFBOs[0]!=0)
+ {
+ GLuint i;
+ for (i = 0; i < mural->cBuffers; ++i)
+ {
+ cr_server.head_spu->dispatch_table.DeleteTextures(1, &mural->aidColorTexs[i]);
+ mural->aidColorTexs[i] = 0;
+ }
+
+ cr_server.head_spu->dispatch_table.DeleteRenderbuffersEXT(1, &mural->idDepthStencilRB);
+ mural->idDepthStencilRB = 0;
+
+ for (i = 0; i < mural->cBuffers; ++i)
+ {
+ cr_server.head_spu->dispatch_table.DeleteFramebuffersEXT(1, &mural->aidFBOs[i]);
+ mural->aidFBOs[i] = 0;
+ }
+ }
+
+ mural->cBuffers = 0;
+}
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+static GLboolean crServerIntersectRect(CRrecti *a, CRrecti *b, CRrecti *rect)
+{
+ CRASSERT(a && b && rect);
+
+ rect->x1 = MAX(a->x1, b->x1);
+ rect->x2 = MIN(a->x2, b->x2);
+ rect->y1 = MAX(a->y1, b->y1);
+ rect->y2 = MIN(a->y2, b->y2);
+
+ return (rect->x2>rect->x1) && (rect->y2>rect->y1);
+}
+
+DECLEXPORT(void) crServerVBoxCompositionSetEnableStateGlobal(GLboolean fEnable)
+{
+}
+
+DECLEXPORT(void) crServerVBoxScreenshotRelease(CR_SCREENSHOT *pScreenshot)
+{
+ if (pScreenshot->fDataAllocated)
+ {
+ RTMemFree(pScreenshot->Img.pvData);
+ pScreenshot->fDataAllocated = 0;
+ }
+}
+
+DECLEXPORT(int) crServerVBoxScreenshotGet(uint32_t u32Screen, uint32_t width, uint32_t height, uint32_t pitch, void *pvBuffer, CR_SCREENSHOT *pScreenshot)
+{
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u32Screen);
+ if (!hFb)
+ return VERR_INVALID_STATE;
+
+ const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+
+ if (!width)
+ width = pScreen->u32Width;
+ if (!height)
+ height = pScreen->u32Height;
+ if (!pitch)
+ pitch = pScreen->u32LineSize;
+
+ if (CrFbHas3DData(hFb)
+ || pScreen->u32Width != width
+ || pScreen->u32Height != height
+ || pScreen->u32LineSize != pitch
+ || pScreen->u16BitsPerPixel != 32)
+ {
+ RTRECT SrcRect;
+ RTRECT DstRect;
+
+ pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
+ if (!pvBuffer)
+ {
+ pScreenshot->Img.pvData = RTMemAlloc(pScreenshot->Img.cbData);
+ if (!pScreenshot->Img.pvData)
+ {
+ WARN(("RTMemAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+ pScreenshot->fDataAllocated = 1;
+ }
+ else
+ {
+ pScreenshot->Img.pvData = pvBuffer;
+ pScreenshot->fDataAllocated = 0;
+ }
+
+ pScreenshot->Img.enmFormat = GL_BGRA;
+ pScreenshot->Img.width = width;
+ pScreenshot->Img.height = height;
+ pScreenshot->Img.bpp = 32;
+ pScreenshot->Img.pitch = pitch;
+ SrcRect.xLeft = 0;
+ SrcRect.yTop = 0;
+ SrcRect.xRight = pScreen->u32Width;
+ SrcRect.yBottom = pScreen->u32Height;
+ DstRect.xLeft = 0;
+ DstRect.yTop = 0;
+ DstRect.xRight = width;
+ DstRect.yBottom = height;
+ int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, 1, &DstRect, &pScreenshot->Img);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbBltGetContents failed %d", rc));
+ crServerVBoxScreenshotRelease(pScreenshot);
+ return rc;
+ }
+ }
+ else
+ {
+ pScreenshot->Img.cbData = pScreen->u32LineSize * pScreen->u32Height;
+ if (!pvBuffer)
+ pScreenshot->Img.pvData = CrFbGetVRAM(hFb);
+ else
+ {
+ pScreenshot->Img.pvData = pvBuffer;
+ memcpy(pvBuffer, CrFbGetVRAM(hFb), pScreenshot->Img.cbData);
+ }
+ pScreenshot->Img.enmFormat = GL_BGRA;
+ pScreenshot->Img.width = pScreen->u32Width;
+ pScreenshot->Img.height = pScreen->u32Height;
+ pScreenshot->Img.bpp = pScreen->u16BitsPerPixel;
+ pScreenshot->Img.pitch = pScreen->u32LineSize;
+
+ pScreenshot->fDataAllocated = 0;
+ }
+
+ pScreenshot->u32Screen = u32Screen;
+
+ return VINF_SUCCESS;
+}
+
+extern DECLEXPORT(int) crServerVBoxWindowsShow(bool fShow)
+{
+ return CrPMgrModeWinVisible(fShow);
+}
+
+void crServerPresentFBO(CRMuralInfo *mural)
+{
+ uint32_t i;
+ for (i = 0; i < mural->cUsedFBDatas; ++i)
+ {
+ CR_FBDATA *pData = mural->apUsedFBDatas[i];
+ int rc = CrFbUpdateBegin(pData->hFb);
+ if (RT_SUCCESS(rc))
+ {
+ CrFbEntryTexDataUpdate(pData->hFb, pData->hFbEntry, pData->apTexDatas[CR_SERVER_FBO_FB_IDX(mural)]);
+ CrFbUpdateEnd(pData->hFb);
+ }
+ else
+ WARN(("CrFbUpdateBegin failed rc %d", rc));
+ }
+}
+
+GLboolean crServerIsRedirectedToFBO()
+{
+#ifdef DEBUG_misha
+ Assert(cr_server.curClient);
+ if (cr_server.curClient)
+ {
+ Assert(cr_server.curClient->currentMural == cr_server.currentMural);
+ Assert(cr_server.curClient->currentCtxInfo == cr_server.currentCtxInfo);
+ }
+#endif
+ return cr_server.curClient
+ && cr_server.curClient->currentMural
+ && cr_server.curClient->currentMural->fRedirected;
+}
+
+GLint crServerMuralFBOIdxFromBufferName(CRMuralInfo *mural, GLenum buffer)
+{
+ switch (buffer)
+ {
+ case GL_FRONT:
+ case GL_FRONT_LEFT:
+ case GL_FRONT_RIGHT:
+ return CR_SERVER_FBO_FB_IDX(mural);
+ case GL_BACK:
+ case GL_BACK_LEFT:
+ case GL_BACK_RIGHT:
+ return CR_SERVER_FBO_BB_IDX(mural);
+ case GL_NONE:
+ case GL_AUX0:
+ case GL_AUX1:
+ case GL_AUX2:
+ case GL_AUX3:
+ case GL_LEFT:
+ case GL_RIGHT:
+ case GL_FRONT_AND_BACK:
+ return -1;
+ default:
+ WARN(("crServerMuralFBOIdxFromBufferName: invalid buffer passed 0x%x", buffer));
+ return -2;
+ }
+}
+
+void crServerMuralFBOSwapBuffers(CRMuralInfo *mural)
+{
+ CRContext *ctx = crStateGetCurrent();
+ GLuint iOldCurDrawBuffer = mural->iCurDrawBuffer;
+ GLuint iOldCurReadBuffer = mural->iCurReadBuffer;
+ mural->iBbBuffer = ((mural->iBbBuffer + 1) % (mural->cBuffers));
+ if (mural->iCurDrawBuffer >= 0)
+ mural->iCurDrawBuffer = ((mural->iCurDrawBuffer + 1) % (mural->cBuffers));
+ if (mural->iCurReadBuffer >= 0)
+ mural->iCurReadBuffer = ((mural->iCurReadBuffer + 1) % (mural->cBuffers));
+ Assert(iOldCurDrawBuffer != mural->iCurDrawBuffer || mural->cBuffers == 1 || mural->iCurDrawBuffer < 0);
+ Assert(iOldCurReadBuffer != mural->iCurReadBuffer || mural->cBuffers == 1 || mural->iCurReadBuffer < 0);
+ if (!ctx->framebufferobject.drawFB && iOldCurDrawBuffer != mural->iCurDrawBuffer)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_DRAW_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurDrawBuffer));
+ }
+ if (!ctx->framebufferobject.readFB && iOldCurReadBuffer != mural->iCurReadBuffer)
+ {
+ cr_server.head_spu->dispatch_table.BindFramebufferEXT(GL_READ_FRAMEBUFFER, CR_SERVER_FBO_FOR_IDX(mural, mural->iCurReadBuffer));
+ }
+ Assert(mural->aidColorTexs[CR_SERVER_FBO_FB_IDX(mural)]);
+}
+
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
new file mode 100644
index 00000000..e1dca828
--- /dev/null
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_presenter.cpp
@@ -0,0 +1,4787 @@
+/* $Id: server_presenter.cpp $ */
+
+/** @file
+ * Presenter API
+ */
+
+/*
+ * Copyright (C) 2012-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "cr_spu.h"
+#include "chromium.h"
+#include "cr_error.h"
+#include "cr_net.h"
+#include "cr_rand.h"
+#include "server_dispatch.h"
+#include "server.h"
+#include "cr_mem.h"
+#include "cr_string.h"
+#include <cr_vreg.h>
+#include <cr_htable.h>
+#include <cr_bmpscale.h>
+
+#include <iprt/cdefs.h>
+#include <iprt/types.h>
+#include <iprt/asm.h>
+#include <iprt/mem.h>
+#include <iprt/list.h>
+
+
+#ifdef DEBUG_misha
+# define VBOXVDBG_MEMCACHE_DISABLE
+#endif
+
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+# include <iprt/memcache.h>
+#endif
+
+#include "render/renderspu.h"
+
+class ICrFbDisplay
+{
+public:
+ virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb) = 0;
+ virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb) = 0;
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+ virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry) = 0;
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+ virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+ virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry) = 0;
+
+ virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb) = 0;
+
+ virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb) = 0;
+
+ virtual ~ICrFbDisplay() {}
+};
+
+class CrFbDisplayComposite;
+class CrFbDisplayBase;
+class CrFbDisplayWindow;
+class CrFbDisplayWindowRootVr;
+class CrFbDisplayVrdp;
+
+typedef struct CR_FRAMEBUFFER
+{
+ VBOXVR_SCR_COMPOSITOR Compositor;
+ struct VBVAINFOSCREEN ScreenInfo;
+ void *pvVram;
+ ICrFbDisplay *pDisplay;
+ RTLISTNODE EntriesList;
+ uint32_t cEntries; /* <- just for debugging */
+ uint32_t cUpdating;
+ CRHTABLE SlotTable;
+} CR_FRAMEBUFFER;
+
+typedef union CR_FBENTRY_FLAGS
+{
+ struct {
+ uint32_t fCreateNotified : 1;
+ uint32_t fInList : 1;
+ uint32_t Reserved : 30;
+ };
+ uint32_t Value;
+} CR_FBENTRY_FLAGS;
+
+typedef struct CR_FRAMEBUFFER_ENTRY
+{
+ VBOXVR_SCR_COMPOSITOR_ENTRY Entry;
+ RTLISTNODE Node;
+ uint32_t cRefs;
+ CR_FBENTRY_FLAGS Flags;
+ CRHTABLE HTable;
+} CR_FRAMEBUFFER_ENTRY;
+
+typedef struct CR_FBTEX
+{
+ CR_TEXDATA Tex;
+ CRTextureObj *pTobj;
+} CR_FBTEX;
+
+#define PCR_FBTEX_FROM_TEX(_pTex) ((CR_FBTEX*)((uint8_t*)(_pTex) - RT_OFFSETOF(CR_FBTEX, Tex)))
+#define PCR_FRAMEBUFFER_FROM_COMPOSITOR(_pCompositor) ((CR_FRAMEBUFFER*)((uint8_t*)(_pCompositor) - RT_OFFSETOF(CR_FRAMEBUFFER, Compositor)))
+#define PCR_FBENTRY_FROM_ENTRY(_pEntry) ((CR_FRAMEBUFFER_ENTRY*)((uint8_t*)(_pEntry) - RT_OFFSETOF(CR_FRAMEBUFFER_ENTRY, Entry)))
+
+
+typedef struct CR_FBDISPLAY_INFO
+{
+ uint32_t u32Mode;
+ CrFbDisplayWindow *pDpWin;
+ CrFbDisplayWindowRootVr *pDpWinRootVr;
+ CrFbDisplayVrdp *pDpVrdp;
+ CrFbDisplayComposite *pDpComposite;
+} CR_FBDISPLAY_INFO;
+
+typedef struct CR_PRESENTER_GLOBALS
+{
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMEMCACHE FbEntryLookasideList;
+ RTMEMCACHE FbTexLookasideList;
+ RTMEMCACHE CEntryLookasideList;
+#endif
+ uint32_t u32DisplayMode;
+ CRHashTable *pFbTexMap;
+ CR_FBDISPLAY_INFO aDisplayInfos[CR_MAX_GUEST_MONITORS];
+ CR_FBMAP FramebufferInitMap;
+ CR_FRAMEBUFFER aFramebuffers[CR_MAX_GUEST_MONITORS];
+ bool fWindowsForceHidden;
+ uint32_t cbTmpBuf;
+ void *pvTmpBuf;
+ uint32_t cbTmpBuf2;
+ void *pvTmpBuf2;
+} CR_PRESENTER_GLOBALS;
+
+static CR_PRESENTER_GLOBALS g_CrPresenter;
+
+/* FRAMEBUFFER */
+
+void CrFbInit(CR_FRAMEBUFFER *pFb, uint32_t idScreen)
+{
+ RTRECT Rect;
+ Rect.xLeft = 0;
+ Rect.yTop = 0;
+ Rect.xRight = 1;
+ Rect.yBottom = 1;
+ memset(pFb, 0, sizeof (*pFb));
+ pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
+ pFb->ScreenInfo.u32ViewIndex = idScreen;
+ CrVrScrCompositorInit(&pFb->Compositor, &Rect);
+ RTListInit(&pFb->EntriesList);
+ CrHTableCreate(&pFb->SlotTable, 0);
+}
+
+bool CrFbIsEnabled(CR_FRAMEBUFFER *pFb)
+{
+ return !(pFb->ScreenInfo.u16Flags & VBVA_SCREEN_F_DISABLED);
+}
+
+HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry);
+
+const struct VBOXVR_SCR_COMPOSITOR* CrFbGetCompositor(CR_FRAMEBUFFER *pFb)
+{
+ return &pFb->Compositor;
+}
+
+DECLINLINE(CR_FRAMEBUFFER*) CrFbFromCompositor(const struct VBOXVR_SCR_COMPOSITOR* pCompositor)
+{
+ return RT_FROM_MEMBER(pCompositor, CR_FRAMEBUFFER, Compositor);
+}
+
+const struct VBVAINFOSCREEN* CrFbGetScreenInfo(HCR_FRAMEBUFFER hFb)
+{
+ return &hFb->ScreenInfo;
+}
+
+void* CrFbGetVRAM(HCR_FRAMEBUFFER hFb)
+{
+ return hFb->pvVram;
+}
+
+int CrFbUpdateBegin(CR_FRAMEBUFFER *pFb)
+{
+ ++pFb->cUpdating;
+
+ if (pFb->cUpdating == 1)
+ {
+ if (pFb->pDisplay)
+ pFb->pDisplay->UpdateBegin(pFb);
+ }
+
+ return VINF_SUCCESS;
+}
+
+void CrFbUpdateEnd(CR_FRAMEBUFFER *pFb)
+{
+ if (!pFb->cUpdating)
+ {
+ WARN(("invalid UpdateEnd call!"));
+ return;
+ }
+
+ --pFb->cUpdating;
+
+ if (!pFb->cUpdating)
+ {
+ if (pFb->pDisplay)
+ pFb->pDisplay->UpdateEnd(pFb);
+ }
+}
+
+bool CrFbIsUpdating(const CR_FRAMEBUFFER *pFb)
+{
+ return !!pFb->cUpdating;
+}
+
+bool CrFbHas3DData(HCR_FRAMEBUFFER hFb)
+{
+ return !CrVrScrCompositorIsEmpty(&hFb->Compositor);
+}
+
+static void crFbBltMem(uint8_t *pu8Src, int32_t cbSrcPitch, uint8_t *pu8Dst, int32_t cbDstPitch, uint32_t width, uint32_t height)
+{
+ uint32_t cbCopyRow = width * 4;
+
+ for (uint32_t i = 0; i < height; ++i)
+ {
+ memcpy(pu8Dst, pu8Src, cbCopyRow);
+
+ pu8Src += cbSrcPitch;
+ pu8Dst += cbDstPitch;
+ }
+}
+
+static void crFbBltImg(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, CR_BLITTER_IMG *pDst)
+{
+ int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
+ int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
+ Assert(srcX >= 0);
+ Assert(srcY >= 0);
+ Assert(srcX < (int32_t)pSrc->width);
+ Assert(srcY < (int32_t)pSrc->height);
+
+ int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
+ int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
+ Assert(dstX >= 0);
+ Assert(dstY >= 0);
+
+ uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
+ uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
+
+ crFbBltMem(pu8Src, fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch, pu8Dst, pDst->pitch, pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
+}
+
+static void crFbBltImgScaled(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
+{
+ int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
+ int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
+ Assert(srcX >= 0);
+ Assert(srcY >= 0);
+ Assert(srcX < (int32_t)pSrc->width);
+ Assert(srcY < (int32_t)pSrc->height);
+
+ RTPOINT ScaledDtsDataPoint;
+ RTRECT ScaledCopyRect;
+
+ VBoxRectScaled(pCopyRect, strX, strY, &ScaledCopyRect);
+ ScaledDtsDataPoint.x = CR_FLOAT_RCAST(int32_t, strX * pDstDataPoint->x);
+ ScaledDtsDataPoint.y = CR_FLOAT_RCAST(int32_t, strY * pDstDataPoint->y);
+
+ int32_t dstX = ScaledCopyRect.xLeft - ScaledDtsDataPoint.x;
+ int32_t dstY = ScaledCopyRect.yTop - ScaledDtsDataPoint.y;
+ Assert(dstX >= 0);
+ Assert(dstY >= 0);
+
+ int32_t ScaledDstWidth = ScaledCopyRect.xRight - ScaledCopyRect.xLeft;
+ int32_t delta = (int32_t)pDst->width - dstX - ScaledDstWidth;
+ if (delta < 0)
+ ScaledDstWidth += delta;
+
+ if (ScaledDstWidth <= 0)
+ {
+ LOG(("ScaledDstWidth <= 0"));
+ if (ScaledDstWidth < 0)
+ WARN(("dst width (%d) < 0", ScaledDstWidth));
+ return;
+ }
+
+ int32_t ScaledDstHeight = ScaledCopyRect.yBottom - ScaledCopyRect.yTop;
+ delta = (int32_t)pDst->height - dstY - ScaledDstHeight;
+ if (delta < 0)
+ ScaledDstHeight += delta;
+
+ if (ScaledDstHeight <= 0)
+ {
+ LOG(("ScaledDstHeight <= 0"));
+ if (ScaledDstHeight < 0)
+ WARN(("dst height (%d) < 0", ScaledDstHeight));
+ return;
+ }
+
+ uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
+ uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
+
+ CrBmpScale32(pu8Dst, pDst->pitch,
+ ScaledDstWidth,
+ ScaledDstHeight,
+ pu8Src,
+ fSrcInvert ? -((int32_t)pSrc->pitch) : (int32_t)pSrc->pitch,
+ pCopyRect->xRight - pCopyRect->xLeft, pCopyRect->yBottom - pCopyRect->yTop);
+}
+
+static void crFbBltImgScaledRects(const CR_BLITTER_IMG *pSrc, const RTPOINT *pSrcDataPoint, bool fSrcInvert, const RTRECT *pCopyRect, const RTPOINT *pDstDataPoint, float strX, float strY, CR_BLITTER_IMG *pDst)
+{
+ int32_t srcX = pCopyRect->xLeft - pSrcDataPoint->x;
+ int32_t srcY = pCopyRect->yTop - pSrcDataPoint->y;
+ Assert(srcX >= 0);
+ Assert(srcY >= 0);
+
+ RTRECT UnscaledCopyRect;
+ VBoxRectUnscaled(pCopyRect, strX, strY, &UnscaledCopyRect);
+
+ srcX = CR_FLOAT_RCAST(int32_t, srcX / strX);
+ srcY = CR_FLOAT_RCAST(int32_t, srcY / strY);
+
+ int32_t UnscaledSrcWidth = UnscaledCopyRect.xRight - UnscaledCopyRect.xLeft;
+ int32_t delta = (int32_t)pSrc->width - srcX - UnscaledSrcWidth;
+ if (delta < 0)
+ UnscaledSrcWidth += delta;
+
+ if (UnscaledSrcWidth <= 0)
+ {
+ LOG(("UnscaledSrcWidth <= 0"));
+ if (UnscaledSrcWidth < 0)
+ WARN(("src width (%d) < 0", UnscaledSrcWidth));
+ return;
+ }
+
+ int32_t UnscaledSrcHeight = UnscaledCopyRect.yBottom - UnscaledCopyRect.yTop;
+ delta = (int32_t)pSrc->height - srcY - UnscaledSrcHeight;
+ if (delta < 0)
+ UnscaledSrcHeight += delta;
+
+ if (UnscaledSrcHeight <= 0)
+ {
+ LOG(("UnscaledSrcHeight <= 0"));
+ if (UnscaledSrcHeight < 0)
+ WARN(("src height (%d) < 0", UnscaledSrcHeight));
+ return;
+ }
+
+ int32_t dstX = pCopyRect->xLeft - pDstDataPoint->x;
+ int32_t dstY = pCopyRect->yTop - pDstDataPoint->y;
+ Assert(dstX >= 0);
+ Assert(dstY >= 0);
+
+
+ uint8_t *pu8Src = ((uint8_t*)pSrc->pvData) + pSrc->pitch * (!fSrcInvert ? srcY : pSrc->height - srcY - 1) + srcX * 4;
+ uint8_t *pu8Dst = ((uint8_t*)pDst->pvData) + pDst->pitch * dstY + dstX * 4;
+
+ CrBmpScale32(pu8Dst, pDst->pitch,
+ pCopyRect->xRight - pCopyRect->xLeft,
+ pCopyRect->yBottom - pCopyRect->yTop,
+ pu8Src,
+ fSrcInvert ? -pSrc->pitch : pSrc->pitch,
+ UnscaledSrcWidth,
+ UnscaledSrcHeight
+ );
+}
+
+static void crFbImgFromScreenVram(const VBVAINFOSCREEN *pScreen, void *pvVram, CR_BLITTER_IMG *pImg)
+{
+ pImg->pvData = pvVram;
+ pImg->cbData = pScreen->u32LineSize * pScreen->u32Height;
+ pImg->enmFormat = GL_BGRA;
+ pImg->width = pScreen->u32Width;
+ pImg->height = pScreen->u32Height;
+ pImg->bpp = pScreen->u16BitsPerPixel;
+ pImg->pitch = pScreen->u32LineSize;
+}
+
+static void crFbImgFromFb(HCR_FRAMEBUFFER hFb, CR_BLITTER_IMG *pImg)
+{
+ const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+ void *pvVram = CrFbGetVRAM(hFb);
+ crFbImgFromScreenVram(pScreen, pvVram, pImg);
+}
+
+static int crFbBltGetContentsDirect(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
+{
+ VBOXVR_LIST List;
+ uint32_t c2DRects = 0;
+ CR_TEXDATA *pEnteredTex = NULL;
+ PCR_BLITTER pEnteredBlitter = NULL;
+ uint32_t width = 0, height = 0;
+ RTPOINT ScaledEntryPoint = {0};
+
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
+ int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
+ int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
+ int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
+
+ RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
+ float strX = ((float)dstWidth) / srcWidth;
+ float strY = ((float)dstHeight) / srcHeight;
+ bool fScale = (dstWidth != srcWidth || dstHeight != srcHeight);
+
+ const RTPOINT ZeroPoint = {0, 0};
+
+ VBoxVrListInit(&List);
+ int rc = VBoxVrListRectsAdd(&List, 1, CrVrScrCompositorRectGet(&hFb->Compositor), NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsAdd failed rc %d", rc));
+ goto end;
+ }
+
+ CrVrScrCompositorConstIterInit(&hFb->Compositor, &Iter);
+
+ for(const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrVrScrCompositorConstIterNext(&Iter);
+ pEntry;
+ pEntry = CrVrScrCompositorConstIterNext(&Iter))
+ {
+ uint32_t cRegions;
+ const RTRECT *pRegions;
+ rc = CrVrScrCompositorEntryRegionsGet(&hFb->Compositor, pEntry, &cRegions, NULL, NULL, &pRegions);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsGet failed rc %d", rc));
+ goto end;
+ }
+
+ rc = VBoxVrListRectsSubst(&List, cRegions, pRegions, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsSubst failed rc %d", rc));
+ goto end;
+ }
+
+ for (uint32_t j = 0; j < cRegions; ++j)
+ {
+ /* rects are in dst coordinates,
+ * while the pReg is in source coords
+ * convert */
+ const RTRECT * pReg = &pRegions[j];
+ RTRECT ScaledReg;
+ /* scale */
+ VBoxRectScaled(pReg, strX, strY, &ScaledReg);
+ /* translate */
+ VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ const RTRECT * pRect = &pRects[i];
+
+ RTRECT Intersection;
+ VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
+ if (VBoxRectIsZero(&Intersection))
+ continue;
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+ const CR_BLITTER_IMG *pSrcImg;
+
+ if (pEnteredTex != pTex)
+ {
+ if (!pEnteredBlitter)
+ {
+ pEnteredBlitter = CrTdBlitterGet(pTex);
+ rc = CrBltEnter(pEnteredBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrBltEnter failed %d", rc));
+ pEnteredBlitter = NULL;
+ goto end;
+ }
+ }
+
+ if (pEnteredTex)
+ {
+ CrTdBltLeave(pEnteredTex);
+
+ pEnteredTex = NULL;
+
+ if (pEnteredBlitter != CrTdBlitterGet(pTex))
+ {
+ WARN(("blitters not equal!"));
+ CrBltLeave(pEnteredBlitter);
+
+ pEnteredBlitter = CrTdBlitterGet(pTex);
+ rc = CrBltEnter(pEnteredBlitter);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrBltEnter failed %d", rc));
+ pEnteredBlitter = NULL;
+ goto end;
+ }
+ }
+ }
+
+ rc = CrTdBltEnter(pTex);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltEnter failed %d", rc));
+ goto end;
+ }
+
+ pEnteredTex = pTex;
+
+ const VBOXVR_TEXTURE *pVrTex = CrTdTexGet(pTex);
+
+ width = CR_FLOAT_RCAST(uint32_t, strX * pVrTex->width);
+ height = CR_FLOAT_RCAST(uint32_t, strY * pVrTex->height);
+ ScaledEntryPoint.x = CR_FLOAT_RCAST(int32_t, strX * CrVrScrCompositorEntryRectGet(pEntry)->xLeft) + pDstRect->xLeft;
+ ScaledEntryPoint.y = CR_FLOAT_RCAST(int32_t, strY * CrVrScrCompositorEntryRectGet(pEntry)->yTop) + pDstRect->yTop;
+ }
+
+ rc = CrTdBltDataAcquireScaled(pTex, GL_BGRA, false, width, height, &pSrcImg);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltDataAcquire failed rc %d", rc));
+ goto end;
+ }
+
+ bool fInvert = !(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS);
+
+ crFbBltImg(pSrcImg, &ScaledEntryPoint, fInvert, &Intersection, &ZeroPoint, pImg);
+
+ CrTdBltDataReleaseScaled(pTex, pSrcImg);
+ }
+ }
+ }
+
+ c2DRects = VBoxVrListRectsCount(&List);
+ if (c2DRects)
+ {
+ if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
+ {
+ if (g_CrPresenter.pvTmpBuf2)
+ RTMemFree(g_CrPresenter.pvTmpBuf2);
+
+ g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
+ g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
+ if (!g_CrPresenter.pvTmpBuf2)
+ {
+ WARN(("RTMemAlloc failed!"));
+ g_CrPresenter.cbTmpBuf2 = 0;
+ rc = VERR_NO_MEMORY;
+ goto end;
+ }
+ }
+
+ RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
+
+ rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsGet failed, rc %d", rc));
+ goto end;
+ }
+
+ const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
+
+ CR_BLITTER_IMG FbImg;
+
+ crFbImgFromFb(hFb, &FbImg);
+
+ for (uint32_t j = 0; j < c2DRects; ++j)
+ {
+ const RTRECT * p2DRect = &p2DRects[j];
+ RTRECT ScaledReg;
+ /* scale */
+ VBoxRectScaled(p2DRect, strX, strY, &ScaledReg);
+ /* translate */
+ VBoxRectTranslate(&ScaledReg, pDstRect->xLeft, pDstRect->yTop);
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ const RTRECT * pRect = &pRects[i];
+ RTRECT Intersection;
+
+ VBoxRectIntersected(pRect, &ScaledReg, &Intersection);
+ if (VBoxRectIsZero(&Intersection))
+ continue;
+
+ if (!fScale)
+ crFbBltImg(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, pImg);
+ else
+ crFbBltImgScaledRects(&FbImg, &DstPoint, false, &Intersection, &ZeroPoint, strX, strY, pImg);
+ }
+ }
+ }
+
+end:
+
+ if (pEnteredTex)
+ CrTdBltLeave(pEnteredTex);
+
+ if (pEnteredBlitter)
+ CrBltLeave(pEnteredBlitter);
+
+ VBoxVrListClear(&List);
+
+ return rc;
+}
+
+static int crFbBltGetContentsScaleCPU(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
+{
+ int32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
+ int32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
+ int32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
+ int32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
+
+ RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
+ float strX = ((float)dstWidth) / srcWidth;
+ float strY = ((float)dstHeight) / srcHeight;
+
+ RTRECT DstRect;
+ VBoxRectUnscaled(pDstRect, strX, strY, &DstRect);
+ DstRect.xRight = DstRect.xLeft + srcWidth;
+ DstRect.yBottom = DstRect.yTop + srcHeight;
+
+ /* destination is bigger than the source, do 3D data stretching with CPU */
+ CR_BLITTER_IMG Img;
+ Img.cbData = srcWidth * srcHeight * 4;
+ Img.pvData = RTMemAlloc(Img.cbData);
+ if (!Img.pvData)
+ {
+ WARN(("RTMemAlloc Failed"));
+ return VERR_NO_MEMORY;
+ }
+ Img.enmFormat = pImg->enmFormat;
+ Img.width = srcWidth;
+ Img.height = srcHeight;
+ Img.bpp = pImg->bpp;
+ Img.pitch = Img.width * 4;
+
+ int rc = CrFbBltGetContents(hFb, pSrcRect, &DstRect, cRects, pRects, &Img);
+ if (RT_SUCCESS(rc))
+ {
+ CrBmpScale32((uint8_t *)pImg->pvData,
+ pImg->pitch,
+ pImg->width, pImg->height,
+ (const uint8_t *)Img.pvData,
+ Img.pitch,
+ Img.width, Img.height);
+ }
+ else
+ WARN(("CrFbBltGetContents failed %d", rc));
+
+ RTMemFree(Img.pvData);
+
+ return rc;
+
+}
+
+int CrFbBltGetContents(HCR_FRAMEBUFFER hFb, const RTRECT *pSrcRect, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
+{
+ uint32_t srcWidth = pSrcRect->xRight - pSrcRect->xLeft;
+ uint32_t srcHeight = pSrcRect->yBottom - pSrcRect->yTop;
+ uint32_t dstWidth = pDstRect->xRight - pDstRect->xLeft;
+ uint32_t dstHeight = pDstRect->yBottom - pDstRect->yTop;
+ if ((srcWidth == dstWidth
+ && srcHeight == dstHeight)
+ || !CrFbHas3DData(hFb)
+ || (srcWidth * srcHeight > dstWidth * dstHeight))
+ {
+ return crFbBltGetContentsDirect(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
+ }
+
+ return crFbBltGetContentsScaleCPU(hFb, pSrcRect, pDstRect, cRects, pRects, pImg);
+}
+
+#if 0
+static int crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY)
+{
+ const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
+ const RTPOINT ZeroPoint = {0};
+
+ uint32_t fbWidth = (pCompRect->xRight - pCompRect->xLeft);
+ uint32_t fbHeight = pCompRect->yBottom - pCompRect->yTop;
+
+ uint32_t stretchedWidth = CR_FLOAT_RCAST(uint32_t, strX * fbWidth);
+ uint32_t stretchedHeight = CR_FLOAT_RCAST(uint32_t, strY * fbHeight);
+
+ CR_BLITTER_IMG FbImg;
+
+ bool fScale = fbWidth != stretchedWidth || fbHeight != stretchedHeight;
+
+ crFbImgFromFb(hFb, &FbImg);
+
+ RTRECT Intersection;
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ const RTRECT * pRect = &pRects[i];
+ VBoxRectIntersected(pRect, pCompRect, &Intersection);
+
+ if (VBoxRectIsZero(&Intersection))
+ continue;
+
+ if (!fScale)
+ crFbBltImg(pImg, pDstPoint, false, &Intersection, &ZeroPoint, &FbImg);
+ else
+ crFbBltImgScaled(pImg, pDstPoint, false, &Intersection, &ZeroPoint, strX, strY, &FbImg);
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrFbBltPutContents(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
+{
+ RTPOINT DstPoint = {pDstRect->xLeft, pDstRect->yTop};
+ float strX = ((float)pImg->width) / (pDstRect->xRight - pDstRect->xLeft);
+ float strY = ((float)pImg->height) / (pDstRect->yBottom - pDstRect->yTop);
+
+ int rc = CrFbEntryRegionsAdd(hFb, NULL, const RTPOINT *pPos, cRects, pRects, true)
+ if (!hFb->cUpdating)
+ {
+ WARN(("not updating\n"));
+ return VERR_INVALID_STATE;
+ }
+}
+
+int CrFbBltPutContentsNe(HCR_FRAMEBUFFER hFb, const RTRECT *pDstRect, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg)
+{
+ uint32_t cCompRects;
+ const RTRECT *pCompRects;
+ int rc = CrVrScrCompositorRegionsGet(&hFb->Compositor, &cCompRects, NULL, NULL, &pCompRects);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
+ return rc;
+ }
+
+ bool fRegChanged = false;
+ for (uint32_t i = 0; i < cCompRects; ++i)
+ {
+ const RTRECT *pCompRect = pCompRects[i];
+ for (uint32_t j = 0; j < cRects; ++j)
+ {
+ const RTRECT *pRect = pRects[j];
+ if (VBoxRectIsIntersect(pCompRect, pRect))
+ {
+ fRegChanged = true;
+ break;
+ }
+ }
+ }
+
+ if (fRegChanged)
+ {
+ rc = CrFbUpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrFbBltPutContents(hFb, pDstRect, cRects, pRects, pImg);
+ if (!RT_SUCCESS(rc))
+ WARN(("CrFbBltPutContents failed rc %d", rc));
+ CrFbUpdateEnd(hFb);
+ }
+ else
+ WARN(("CrFbUpdateBegin failed rc %d", rc));
+
+ return rc;
+ }
+
+ return crFbBltPutContentsVram(HCR_FRAMEBUFFER hFb, const RTPOINT *pDstPoint, uint32_t cRects, const RTRECT *pRects, CR_BLITTER_IMG *pImg, float strX, float strY);
+
+ const RTPOINT ZeroPoint = {0, 0};
+
+ c2DRects = VBoxVrListRectsCount(&List);
+ if (c2DRects)
+ {
+ if (g_CrPresenter.cbTmpBuf2 < c2DRects * sizeof (RTRECT))
+ {
+ if (g_CrPresenter.pvTmpBuf2)
+ RTMemFree(g_CrPresenter.pvTmpBuf2);
+
+ g_CrPresenter.cbTmpBuf2 = (c2DRects + 10) * sizeof (RTRECT);
+ g_CrPresenter.pvTmpBuf2 = RTMemAlloc(g_CrPresenter.cbTmpBuf2);
+ if (!g_CrPresenter.pvTmpBuf2)
+ {
+ WARN(("RTMemAlloc failed!"));
+ g_CrPresenter.cbTmpBuf2 = 0;
+ rc = VERR_NO_MEMORY;
+ goto end;
+ }
+ }
+
+ RTRECT *p2DRects = (RTRECT *)g_CrPresenter.pvTmpBuf2;
+
+ rc = VBoxVrListRectsGet(&List, c2DRects, p2DRects);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("VBoxVrListRectsGet failed, rc %d", rc));
+ goto end;
+ }
+
+ RTPOINT Pos = {0};
+ const RTRECT *pCompRect = CrVrScrCompositorRectGet(&hFb->Compositor);
+
+ CR_BLITTER_IMG FbImg;
+
+ crFbImgFromFb(hFb, &FbImg);
+
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ const RTRECT * pRect = &pRects[i];
+ for (uint32_t j = 0; j < c2DRects; ++j)
+ {
+ const RTRECT * p2DRect = &p2DRects[j];
+ RTRECT Intersection;
+ VBoxRectIntersected(pRect, p2DRect, &Intersection);
+ if (VBoxRectIsZero(&Intersection))
+ continue;
+
+ if (!fScale)
+ crFbBltImg(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, pImg);
+ else
+ crFbBltImgScaled(&FbImg, &ZeroPoint, false, &Intersection, &SrcPoint, strX, strY, pImg);
+ }
+ }
+ }
+
+end:
+
+ if (pEnteredTex)
+ CrTdBltLeave(pEnteredTex);
+
+ if (pEnteredBlitter)
+ CrBltLeave(pEnteredBlitter);
+
+ VBoxVrListClear(&List);
+
+ return rc;
+}
+#endif
+
+int CrFbResize(CR_FRAMEBUFFER *pFb, const struct VBVAINFOSCREEN * pScreen, void *pvVRAM)
+{
+ if (!pFb->cUpdating)
+ {
+ WARN(("no update in progress"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)
+ {
+ CrVrScrCompositorClear(&pFb->Compositor);
+ }
+
+ RTRECT Rect;
+ Rect.xLeft = 0;
+ Rect.yTop = 0;
+ Rect.xRight = pScreen->u32Width;
+ Rect.yBottom = pScreen->u32Height;
+ int rc = CrVrScrCompositorRectSet(&pFb->Compositor, &Rect, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorRectSet failed rc %d", rc));
+ return rc;
+ }
+
+ pFb->ScreenInfo = *pScreen;
+ pFb->pvVram = pvVRAM;
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->FramebufferChanged(pFb);
+
+ return VINF_SUCCESS;
+}
+
+void CrFbTerm(CR_FRAMEBUFFER *pFb)
+{
+ if (pFb->cUpdating)
+ {
+ WARN(("update in progress"));
+ return;
+ }
+ uint32_t idScreen = pFb->ScreenInfo.u32ViewIndex;
+
+ CrVrScrCompositorClear(&pFb->Compositor);
+ CrHTableDestroy(&pFb->SlotTable);
+
+ Assert(RTListIsEmpty(&pFb->EntriesList));
+ Assert(!pFb->cEntries);
+
+ memset(pFb, 0, sizeof (*pFb));
+
+ pFb->ScreenInfo.u16Flags = VBVA_SCREEN_F_DISABLED;
+ pFb->ScreenInfo.u32ViewIndex = idScreen;
+}
+
+ICrFbDisplay* CrFbDisplayGet(CR_FRAMEBUFFER *pFb)
+{
+ return pFb->pDisplay;
+}
+
+int CrFbDisplaySet(CR_FRAMEBUFFER *pFb, ICrFbDisplay *pDisplay)
+{
+ if (pFb->cUpdating)
+ {
+ WARN(("update in progress"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pFb->pDisplay == pDisplay)
+ return VINF_SUCCESS;
+
+ pFb->pDisplay = pDisplay;
+
+ return VINF_SUCCESS;
+}
+
+#define CR_PMGR_MODE_WINDOW 0x1
+/* mutually exclusive with CR_PMGR_MODE_WINDOW */
+#define CR_PMGR_MODE_ROOTVR 0x2
+#define CR_PMGR_MODE_VRDP 0x4
+#define CR_PMGR_MODE_ALL 0x7
+
+static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove);
+
+static CR_FBTEX* crFbTexAlloc()
+{
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ return (CR_FBTEX*)RTMemCacheAlloc(g_CrPresenter.FbTexLookasideList);
+#else
+ return (CR_FBTEX*)RTMemAlloc(sizeof (CR_FBTEX));
+#endif
+}
+
+static void crFbTexFree(CR_FBTEX *pTex)
+{
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMemCacheFree(g_CrPresenter.FbTexLookasideList, pTex);
+#else
+ RTMemFree(pTex);
+#endif
+}
+
+static CR_FRAMEBUFFER_ENTRY* crFbEntryAlloc()
+{
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ return (CR_FRAMEBUFFER_ENTRY*)RTMemCacheAlloc(g_CrPresenter.FbEntryLookasideList);
+#else
+ return (CR_FRAMEBUFFER_ENTRY*)RTMemAlloc(sizeof (CR_FRAMEBUFFER_ENTRY));
+#endif
+}
+
+static void crFbEntryFree(CR_FRAMEBUFFER_ENTRY *pEntry)
+{
+ Assert(!CrVrScrCompositorEntryIsUsed(&pEntry->Entry));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMemCacheFree(g_CrPresenter.FbEntryLookasideList, pEntry);
+#else
+ RTMemFree(pEntry);
+#endif
+}
+
+DECLCALLBACK(void) crFbTexRelease(CR_TEXDATA *pTex)
+{
+ CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTex);
+ CRTextureObj *pTobj = pFbTex->pTobj;
+
+ CrTdBltDataCleanupNe(pTex);
+
+ if (pTobj)
+ {
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pTobj, cr_server.MainContextInfo.pContext);
+
+ crHashtableDelete(g_CrPresenter.pFbTexMap, pTobj->id, NULL);
+
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pTobj))
+ {
+ CRSharedState *pShared = crStateGlobalSharedAcquire();
+
+ CRASSERT(pShared);
+ /* on the host side, we need to delete an ogl texture object here as well, which crStateDeleteTextureCallback will do
+ * in addition to calling crStateDeleteTextureObject to delete a state object */
+ crHashtableDelete(pShared->textureTable, pTobj->id, crStateDeleteTextureCallback);
+
+ crStateGlobalSharedRelease();
+ }
+
+ crStateGlobalSharedRelease();
+ }
+
+ crFbTexFree(pFbTex);
+}
+
+void CrFbTexDataInit(CR_TEXDATA* pFbTex, const VBOXVR_TEXTURE *pTex, PFNCRTEXDATA_RELEASED pfnTextureReleased)
+{
+ PCR_BLITTER pBlitter = crServerVBoxBlitterGet();
+
+ CrTdInit(pFbTex, pTex, pBlitter, pfnTextureReleased);
+}
+
+static CR_FBTEX* crFbTexCreate(const VBOXVR_TEXTURE *pTex)
+{
+ CR_FBTEX *pFbTex = crFbTexAlloc();
+ if (!pFbTex)
+ {
+ WARN(("crFbTexAlloc failed!"));
+ return NULL;
+ }
+
+ CrFbTexDataInit(&pFbTex->Tex, pTex, crFbTexRelease);
+ pFbTex->pTobj = NULL;
+
+ return pFbTex;
+}
+
+
+CR_TEXDATA* CrFbTexDataCreate(const VBOXVR_TEXTURE *pTex)
+{
+ CR_FBTEX *pFbTex = crFbTexCreate(pTex);
+ if (!pFbTex)
+ {
+ WARN(("crFbTexCreate failed!"));
+ return NULL;
+ }
+
+ return &pFbTex->Tex;
+}
+
+static CR_FBTEX* crFbTexAcquire(GLuint idTexture)
+{
+ CR_FBTEX *pFbTex = (CR_FBTEX *)crHashtableSearch(g_CrPresenter.pFbTexMap, idTexture);
+ if (pFbTex)
+ {
+ CrTdAddRef(&pFbTex->Tex);
+ return pFbTex;
+ }
+
+ CRSharedState *pShared = crStateGlobalSharedAcquire();
+ if (!pShared)
+ {
+ WARN(("pShared is null!"));
+ return NULL;
+ }
+
+ CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pShared->textureTable, idTexture);
+ if (!pTobj)
+ {
+ LOG(("pTobj is null!"));
+ crStateGlobalSharedRelease();
+ return NULL;
+ }
+
+ Assert(pTobj->id == idTexture);
+
+ GLuint hwid = crStateGetTextureObjHWID(pTobj);
+ if (!hwid)
+ {
+ WARN(("hwId is null!"));
+ crStateGlobalSharedRelease();
+ return NULL;
+ }
+
+ VBOXVR_TEXTURE Tex;
+ Tex.width = pTobj->level[0]->width;
+ Tex.height = pTobj->level[0]->height;
+ Tex.hwid = hwid;
+ Tex.target = pTobj->target;
+
+ pFbTex = crFbTexCreate(&Tex);
+ if (!pFbTex)
+ {
+ WARN(("crFbTexCreate failed!"));
+ crStateGlobalSharedRelease();
+ return NULL;
+ }
+
+ CR_STATE_SHAREDOBJ_USAGE_SET(pTobj, cr_server.MainContextInfo.pContext);
+
+ pFbTex->pTobj = pTobj;
+
+ crHashtableAdd(g_CrPresenter.pFbTexMap, idTexture, pFbTex);
+
+ return pFbTex;
+}
+
+static void crFbEntryMarkDestroyed(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+ if (pEntry->Flags.fCreateNotified)
+ {
+ pEntry->Flags.fCreateNotified = 0;
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryDestroyed(pFb, pEntry);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
+ if (pTex)
+ CrTdBltDataInvalidateNe(pTex);
+ }
+}
+
+static void crFbEntryDestroy(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+ crFbEntryMarkDestroyed(pFb, pEntry);
+ CrVrScrCompositorEntryCleanup(&pEntry->Entry);
+ CrHTableDestroy(&pEntry->HTable);
+ Assert(pFb->cEntries);
+ RTListNodeRemove(&pEntry->Node);
+ --pFb->cEntries;
+ crFbEntryFree(pEntry);
+}
+
+DECLINLINE(uint32_t) crFbEntryAddRef(CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+ return ++pEntry->cRefs;
+}
+
+DECLINLINE(uint32_t) crFbEntryRelease(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY* pEntry)
+{
+ uint32_t cRefs = --pEntry->cRefs;
+ if (!cRefs)
+ crFbEntryDestroy(pFb, pEntry);
+ return cRefs;
+}
+
+static DECLCALLBACK(void) crFbEntryReleased(const struct VBOXVR_SCR_COMPOSITOR *pCompositor, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry, struct VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacingEntry)
+{
+ CR_FRAMEBUFFER *pFb = PCR_FRAMEBUFFER_FROM_COMPOSITOR(pCompositor);
+ CR_FRAMEBUFFER_ENTRY *pFbEntry = PCR_FBENTRY_FROM_ENTRY(pEntry);
+ CR_FRAMEBUFFER_ENTRY *pFbReplacingEntry = pReplacingEntry ? PCR_FBENTRY_FROM_ENTRY(pReplacingEntry) : NULL;
+ if (pFbReplacingEntry)
+ {
+ /*replace operation implies the replaced entry gets auto-destroyed,
+ * while all its data gets moved to the *clean* replacing entry
+ * 1. ensure the replacing entry is cleaned up */
+ crFbEntryMarkDestroyed(pFb, pFbReplacingEntry);
+
+ CrHTableMoveTo(&pFbEntry->HTable, &pFbReplacingEntry->HTable);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
+ CR_TEXDATA *pReplacingTex = CrVrScrCompositorEntryTexGet(&pFbReplacingEntry->Entry);
+
+ CrTdBltScaleCacheMoveTo(pTex, pReplacingTex);
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryReplaced(pFb, pFbReplacingEntry, pFbEntry);
+
+ CrTdBltDataInvalidateNe(pTex);
+
+ /* 2. mark the replaced entry is destroyed */
+ Assert(pFbEntry->Flags.fCreateNotified);
+ Assert(pFbEntry->Flags.fInList);
+ pFbEntry->Flags.fCreateNotified = 0;
+ pFbEntry->Flags.fInList = 0;
+ pFbReplacingEntry->Flags.fCreateNotified = 1;
+ pFbReplacingEntry->Flags.fInList = 1;
+ }
+ else
+ {
+ if (pFbEntry->Flags.fInList)
+ {
+ pFbEntry->Flags.fInList = 0;
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryRemoved(pFb, pFbEntry);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pFbEntry->Entry);
+ if (pTex)
+ CrTdBltDataInvalidateNe(pTex);
+ }
+ }
+
+ crFbEntryRelease(pFb, pFbEntry);
+}
+
+static CR_FRAMEBUFFER_ENTRY* crFbEntryCreate(CR_FRAMEBUFFER *pFb, CR_TEXDATA* pTex, const RTRECT *pRect, uint32_t fFlags)
+{
+ CR_FRAMEBUFFER_ENTRY *pEntry = crFbEntryAlloc();
+ if (!pEntry)
+ {
+ WARN(("crFbEntryAlloc failed!"));
+ return NULL;
+ }
+
+ CrVrScrCompositorEntryInit(&pEntry->Entry, pRect, pTex, crFbEntryReleased);
+ CrVrScrCompositorEntryFlagsSet(&pEntry->Entry, fFlags);
+ pEntry->cRefs = 1;
+ pEntry->Flags.Value = 0;
+ CrHTableCreate(&pEntry->HTable, 0);
+
+ RTListAppend(&pFb->EntriesList, &pEntry->Node);
+ ++pFb->cEntries;
+
+ return pEntry;
+}
+
+int CrFbEntryCreateForTexData(CR_FRAMEBUFFER *pFb, struct CR_TEXDATA *pTex, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
+{
+ RTRECT Rect;
+ Rect.xLeft = 0;
+ Rect.yTop = 0;
+ Rect.xRight = pTex->Tex.width;
+ Rect.yBottom = pTex->Tex.height;
+ CR_FRAMEBUFFER_ENTRY* pEntry = crFbEntryCreate(pFb, pTex, &Rect, fFlags);
+ if (!pEntry)
+ {
+ WARN(("crFbEntryCreate failed"));
+ return VERR_NO_MEMORY;
+ }
+
+ *phEntry = pEntry;
+ return VINF_SUCCESS;
+}
+
+int CrFbEntryTexDataUpdate(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY pEntry, struct CR_TEXDATA *pTex)
+{
+ if (!pFb->cUpdating)
+ {
+ WARN(("framebuffer not updating"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (pTex)
+ CrVrScrCompositorEntryTexSet(&pEntry->Entry, pTex);
+
+ if (CrVrScrCompositorEntryIsUsed(&pEntry->Entry))
+ {
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryTexChanged(pFb, pEntry);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&pEntry->Entry);
+ if (pTex)
+ CrTdBltDataInvalidateNe(pTex);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+int CrFbEntryCreateForTexId(CR_FRAMEBUFFER *pFb, GLuint idTexture, uint32_t fFlags, HCR_FRAMEBUFFER_ENTRY *phEntry)
+{
+ CR_FBTEX* pFbTex = crFbTexAcquire(idTexture);
+ if (!pFbTex)
+ {
+ LOG(("crFbTexAcquire failed"));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ CR_TEXDATA* pTex = &pFbTex->Tex;
+ int rc = CrFbEntryCreateForTexData(pFb, pTex, fFlags, phEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbEntryCreateForTexData failed rc %d", rc));
+ }
+
+ /*always release the tex, the CrFbEntryCreateForTexData will do incref as necessary */
+ CrTdRelease(pTex);
+ return rc;
+}
+
+void CrFbEntryAddRef(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+ ++hEntry->cRefs;
+}
+
+void CrFbEntryRelease(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+ crFbEntryRelease(pFb, hEntry);
+}
+
+int CrFbRegionsClear(HCR_FRAMEBUFFER hFb)
+{
+ if (!hFb->cUpdating)
+ {
+ WARN(("framebuffer not updating"));
+ return VERR_INVALID_STATE;
+ }
+
+ bool fChanged = false;
+ CrVrScrCompositorRegionsClear(&hFb->Compositor, &fChanged);
+ if (fChanged)
+ {
+ if (hFb->pDisplay)
+ hFb->pDisplay->RegionsChanged(hFb);
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrFbEntryRegionsAdd(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
+{
+ if (!pFb->cUpdating)
+ {
+ WARN(("framebuffer not updating"));
+ return VERR_INVALID_STATE;
+ }
+
+ uint32_t fChangeFlags = 0;
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
+ bool fEntryWasInList;
+
+ if (hEntry)
+ {
+ crFbEntryAddRef(hEntry);
+ pNewEntry = &hEntry->Entry;
+ fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
+
+ Assert(!hEntry->Flags.fInList == !fEntryWasInList);
+ }
+ else
+ {
+ pNewEntry = NULL;
+ fEntryWasInList = false;
+ }
+
+ int rc = CrVrScrCompositorEntryRegionsAdd(&pFb->Compositor, hEntry ? &hEntry->Entry : NULL, pPos, cRegions, paRegions, fPosRelated, &pReplacedScrEntry, &fChangeFlags);
+ if (RT_SUCCESS(rc))
+ {
+ if (fChangeFlags & VBOXVR_COMPOSITOR_CF_REGIONS_CHANGED)
+ {
+ if (!fEntryWasInList && pNewEntry)
+ {
+ Assert(CrVrScrCompositorEntryIsUsed(pNewEntry));
+ if (!hEntry->Flags.fCreateNotified)
+ {
+ hEntry->Flags.fCreateNotified = 1;
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryCreated(pFb, hEntry);
+ }
+
+#ifdef DEBUG_misha
+ /* in theory hEntry->Flags.fInList can be set if entry is replaced,
+ * but then modified to fit the compositor rects,
+ * and so we get the regions changed notification as a result
+ * this should not generally happen though, so put an assertion to debug that situation */
+ Assert(!hEntry->Flags.fInList);
+#endif
+ if (!hEntry->Flags.fInList)
+ {
+ hEntry->Flags.fInList = 1;
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryAdded(pFb, hEntry);
+ }
+ }
+ if (pFb->pDisplay)
+ pFb->pDisplay->RegionsChanged(pFb);
+
+ Assert(!pReplacedScrEntry);
+ }
+ else if (fChangeFlags & VBOXVR_COMPOSITOR_CF_ENTRY_REPLACED)
+ {
+ Assert(pReplacedScrEntry);
+ /* we have already processed that in a "release" callback */
+ Assert(hEntry);
+ }
+ else
+ {
+ Assert(!fChangeFlags);
+ Assert(!pReplacedScrEntry);
+ }
+
+ if (hEntry)
+ {
+ if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
+ {
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryTexChanged(pFb, hEntry);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
+ if (pTex)
+ CrTdBltDataInvalidateNe(pTex);
+ }
+ }
+ }
+ else
+ WARN(("CrVrScrCompositorEntryRegionsAdd failed, rc %d", rc));
+
+ return rc;
+}
+
+int CrFbEntryRegionsSet(CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry, const RTPOINT *pPos, uint32_t cRegions, const RTRECT *paRegions, bool fPosRelated)
+{
+ if (!pFb->cUpdating)
+ {
+ WARN(("framebuffer not updating"));
+ return VERR_INVALID_STATE;
+ }
+
+ bool fChanged = 0;
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pReplacedScrEntry = NULL;
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pNewEntry;
+ bool fEntryWasInList;
+
+ if (hEntry)
+ {
+ crFbEntryAddRef(hEntry);
+ pNewEntry = &hEntry->Entry;
+ fEntryWasInList = CrVrScrCompositorEntryIsUsed(pNewEntry);
+ Assert(!hEntry->Flags.fInList == !fEntryWasInList);
+ }
+ else
+ {
+ pNewEntry = NULL;
+ fEntryWasInList = false;
+ }
+
+ int rc = CrVrScrCompositorEntryRegionsSet(&pFb->Compositor, pNewEntry, pPos, cRegions, paRegions, fPosRelated, &fChanged);
+ if (RT_SUCCESS(rc))
+ {
+ if (fChanged)
+ {
+ if (!fEntryWasInList && pNewEntry)
+ {
+ if (CrVrScrCompositorEntryIsUsed(pNewEntry))
+ {
+ if (!hEntry->Flags.fCreateNotified)
+ {
+ hEntry->Flags.fCreateNotified = 1;
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryCreated(pFb, hEntry);
+ }
+
+ Assert(!hEntry->Flags.fInList);
+ hEntry->Flags.fInList = 1;
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryAdded(pFb, hEntry);
+ }
+ }
+
+ if (pFb->pDisplay)
+ pFb->pDisplay->RegionsChanged(pFb);
+ }
+
+ if (hEntry)
+ {
+ if (CrVrScrCompositorEntryIsUsed(&hEntry->Entry))
+ {
+ if (pFb->pDisplay)
+ pFb->pDisplay->EntryTexChanged(pFb, hEntry);
+
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(&hEntry->Entry);
+ if (pTex)
+ CrTdBltDataInvalidateNe(pTex);
+ }
+ }
+ }
+ else
+ WARN(("CrVrScrCompositorEntryRegionsSet failed, rc %d", rc));
+
+ return rc;
+}
+
+const struct VBOXVR_SCR_COMPOSITOR_ENTRY* CrFbEntryGetCompositorEntry(HCR_FRAMEBUFFER_ENTRY hEntry)
+{
+ return &hEntry->Entry;
+}
+
+HCR_FRAMEBUFFER_ENTRY CrFbEntryFromCompositorEntry(const struct VBOXVR_SCR_COMPOSITOR_ENTRY* pCEntry)
+{
+ return RT_FROM_MEMBER(pCEntry, CR_FRAMEBUFFER_ENTRY, Entry);
+}
+
+void CrFbVisitCreatedEntries(HCR_FRAMEBUFFER hFb, PFNCR_FRAMEBUFFER_ENTRIES_VISITOR_CB pfnVisitorCb, void *pvContext)
+{
+ HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
+ RTListForEachSafe(&hFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
+ {
+ if (hEntry->Flags.fCreateNotified)
+ {
+ if (!pfnVisitorCb(hFb, hEntry, pvContext))
+ return;
+ }
+ }
+}
+
+
+CRHTABLE_HANDLE CrFbDDataAllocSlot(CR_FRAMEBUFFER *pFb)
+{
+ return CrHTablePut(&pFb->SlotTable, (void*)1);
+}
+
+void CrFbDDataReleaseSlot(CR_FRAMEBUFFER *pFb, CRHTABLE_HANDLE hSlot, PFNCR_FRAMEBUFFER_SLOT_RELEASE_CB pfnReleaseCb, void *pvContext)
+{
+ HCR_FRAMEBUFFER_ENTRY hEntry, hNext;
+ RTListForEachSafe(&pFb->EntriesList, hEntry, hNext, CR_FRAMEBUFFER_ENTRY, Node)
+ {
+ if (CrFbDDataEntryGet(hEntry, hSlot))
+ {
+ if (pfnReleaseCb)
+ pfnReleaseCb(pFb, hEntry, pvContext);
+
+ CrFbDDataEntryClear(hEntry, hSlot);
+ }
+ }
+
+ CrHTableRemove(&pFb->SlotTable, hSlot);
+}
+
+int CrFbDDataEntryPut(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot, void *pvData)
+{
+ return CrHTablePutToSlot(&hEntry->HTable, hSlot, pvData);
+}
+
+void* CrFbDDataEntryClear(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
+{
+ return CrHTableRemove(&hEntry->HTable, hSlot);
+}
+
+void* CrFbDDataEntryGet(HCR_FRAMEBUFFER_ENTRY hEntry, CRHTABLE_HANDLE hSlot)
+{
+ return CrHTableGet(&hEntry->HTable, hSlot);
+}
+
+typedef union CR_FBDISPBASE_FLAGS
+{
+ struct {
+ uint32_t fRegionsShanged : 1;
+ uint32_t Reserved : 31;
+ };
+ uint32_t u32Value;
+} CR_FBDISPBASE_FLAGS;
+
+class CrFbDisplayBase : public ICrFbDisplay
+{
+public:
+ CrFbDisplayBase() :
+ mpContainer(NULL),
+ mpFb(NULL),
+ mcUpdates(0),
+ mhSlot(CRHTABLE_HANDLE_INVALID)
+ {
+ mFlags.u32Value = 0;
+ }
+
+ virtual bool isComposite()
+ {
+ return false;
+ }
+
+ class CrFbDisplayComposite* getContainer()
+ {
+ return mpContainer;
+ }
+
+ bool isInList()
+ {
+ return !!mpContainer;
+ }
+
+ bool isUpdating()
+ {
+ return !!mcUpdates;
+ }
+
+ int setRegionsChanged()
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ mFlags.fRegionsShanged = 1;
+ return VINF_SUCCESS;
+ }
+
+ int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
+ {
+ if (mcUpdates)
+ {
+ WARN(("trying to set framebuffer while update is in progress"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (mpFb == pFb)
+ return VINF_SUCCESS;
+
+ int rc = setFramebufferBegin(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpFb)
+ {
+ rc = fbCleanup();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ setFramebufferEnd(pFb);
+ return rc;
+ }
+ }
+
+ mpFb = pFb;
+
+ if (mpFb)
+ {
+ rc = fbSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ setFramebufferEnd(pFb);
+ return rc;
+ }
+ }
+
+ setFramebufferEnd(pFb);
+ return VINF_SUCCESS;
+ }
+
+ struct CR_FRAMEBUFFER* getFramebuffer()
+ {
+ return mpFb;
+ }
+
+ virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+ {
+ ++mcUpdates;
+ Assert(!mFlags.fRegionsShanged || mcUpdates > 1);
+ return VINF_SUCCESS;
+ }
+
+ virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+ {
+ --mcUpdates;
+ Assert(mcUpdates < UINT32_MAX/2);
+ if (!mcUpdates)
+ onUpdateEnd();
+ }
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ mFlags.fRegionsShanged = 1;
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ mFlags.fRegionsShanged = 1;
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ mFlags.fRegionsShanged = 1;
+ return VINF_SUCCESS;
+ }
+
+ virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ mFlags.fRegionsShanged = 1;
+ return VINF_SUCCESS;
+ }
+
+ virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ if (!mcUpdates)
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual ~CrFbDisplayBase();
+
+ /*@todo: move to protected and switch from RTLISTNODE*/
+ RTLISTNODE mNode;
+ class CrFbDisplayComposite* mpContainer;
+protected:
+ virtual void onUpdateEnd()
+ {
+ if (mFlags.fRegionsShanged)
+ {
+ mFlags.fRegionsShanged = 0;
+ if (getFramebuffer()) /*<-dont't do anything on cleanup*/
+ ueRegions();
+ }
+ }
+
+ virtual void ueRegions()
+ {
+ }
+
+ static DECLCALLBACK(bool) entriesCreateCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+ {
+ int rc = ((ICrFbDisplay*)(pvContext))->EntryCreated(hFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ }
+ return true;
+ }
+
+ static DECLCALLBACK(bool) entriesDestroyCb(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+ {
+ int rc = ((ICrFbDisplay*)(pvContext))->EntryDestroyed(hFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ }
+ return true;
+ }
+
+ int fbSynchAddAllEntries()
+ {
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
+ CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
+
+ int rc = VINF_SUCCESS;
+
+ CrFbVisitCreatedEntries(mpFb, entriesCreateCb, this);
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+
+ rc = EntryAdded(mpFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ EntryDestroyed(mpFb, hEntry);
+ break;
+ }
+ }
+
+ return rc;
+ }
+
+ int fbCleanupRemoveAllEntries()
+ {
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+
+ CrVrScrCompositorConstIterInit(CrFbGetCompositor(mpFb), &Iter);
+
+ int rc = VINF_SUCCESS;
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+ rc = EntryRemoved(mpFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ break;
+ }
+
+ CrFbVisitCreatedEntries(mpFb, entriesDestroyCb, this);
+ }
+
+ return rc;
+ }
+
+ virtual int setFramebufferBegin(struct CR_FRAMEBUFFER *pFb)
+ {
+ return UpdateBegin(pFb);
+ }
+ virtual void setFramebufferEnd(struct CR_FRAMEBUFFER *pFb)
+ {
+ UpdateEnd(pFb);
+ }
+
+ static DECLCALLBACK(void) slotEntryReleaseCB(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry, void *pvContext)
+ {
+ }
+
+ virtual void slotRelease()
+ {
+ Assert(mhSlot);
+ CrFbDDataReleaseSlot(mpFb, mhSlot, slotEntryReleaseCB, this);
+ }
+
+ virtual int fbCleanup()
+ {
+ if (mhSlot)
+ {
+ slotRelease();
+ mhSlot = 0;
+ }
+ mpFb = NULL;
+ return VINF_SUCCESS;
+ }
+
+ virtual int fbSync()
+ {
+ return VINF_SUCCESS;
+ }
+
+ CRHTABLE_HANDLE slotGet()
+ {
+ if (!mhSlot)
+ {
+ if (mpFb)
+ mhSlot = CrFbDDataAllocSlot(mpFb);
+ }
+
+ return mhSlot;
+ }
+
+private:
+ struct CR_FRAMEBUFFER *mpFb;
+ uint32_t mcUpdates;
+ CRHTABLE_HANDLE mhSlot;
+ CR_FBDISPBASE_FLAGS mFlags;
+};
+
+class CrFbDisplayComposite : public CrFbDisplayBase
+{
+public:
+ CrFbDisplayComposite() :
+ mcDisplays(0)
+ {
+ RTListInit(&mDisplays);
+ }
+
+ virtual bool isComposite()
+ {
+ return true;
+ }
+
+ uint32_t getDisplayCount()
+ {
+ return mcDisplays;
+ }
+
+ bool add(CrFbDisplayBase *pDisplay)
+ {
+ if (pDisplay->isInList())
+ {
+ WARN(("entry in list already"));
+ return false;
+ }
+
+ RTListAppend(&mDisplays, &pDisplay->mNode);
+ pDisplay->mpContainer = this;
+ pDisplay->setFramebuffer(getFramebuffer());
+ ++mcDisplays;
+ return true;
+ }
+
+ bool remove(CrFbDisplayBase *pDisplay, bool fCleanupDisplay = true)
+ {
+ if (pDisplay->getContainer() != this)
+ {
+ WARN(("invalid entry container"));
+ return false;
+ }
+
+ RTListNodeRemove(&pDisplay->mNode);
+ pDisplay->mpContainer = NULL;
+ if (fCleanupDisplay)
+ pDisplay->setFramebuffer(NULL);
+ --mcDisplays;
+ return true;
+ }
+
+ CrFbDisplayBase* first()
+ {
+ return RTListGetFirstCpp(&mDisplays, CrFbDisplayBase, mNode);
+ }
+
+ CrFbDisplayBase* next(CrFbDisplayBase* pDisplay)
+ {
+ if (pDisplay->getContainer() != this)
+ {
+ WARN(("invalid entry container"));
+ return NULL;
+ }
+
+ return RTListGetNextCpp(&mDisplays, pDisplay, CrFbDisplayBase, mNode);
+ }
+
+ virtual int setFramebuffer(struct CR_FRAMEBUFFER *pFb)
+ {
+ CrFbDisplayBase::setFramebuffer(pFb);
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ pIter->setFramebuffer(pFb);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::UpdateBegin(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ rc = pIter->UpdateBegin(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+ {
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ pIter->UpdateEnd(pFb);
+ }
+
+ CrFbDisplayBase::UpdateEnd(pFb);
+ }
+
+ virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryAdded(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryAdded(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryCreated(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryRemoved(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->EntryDestroyed(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::RegionsChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->RegionsChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ CrFbDisplayBase *pIter;
+ RTListForEachCpp(&mDisplays, pIter, CrFbDisplayBase, mNode)
+ {
+ int rc = pIter->FramebufferChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+ return VINF_SUCCESS;
+ }
+
+ virtual ~CrFbDisplayComposite()
+ {
+ cleanup();
+ }
+
+ void cleanup(bool fCleanupDisplays = true)
+ {
+ CrFbDisplayBase *pIter, *pIterNext;
+ RTListForEachSafeCpp(&mDisplays, pIter, pIterNext, CrFbDisplayBase, mNode)
+ {
+ remove(pIter, fCleanupDisplays);
+ }
+ }
+private:
+ RTLISTNODE mDisplays;
+ uint32_t mcDisplays;
+};
+
+typedef union CR_FBWIN_FLAGS
+{
+ struct {
+ uint32_t fVisible : 1;
+ uint32_t fDataPresented : 1;
+ uint32_t fForcePresentOnReenable : 1;
+ uint32_t fCompositoEntriesModified : 1;
+ uint32_t Reserved : 28;
+ };
+ uint32_t Value;
+} CR_FBWIN_FLAGS;
+
+class CrFbWindow
+{
+public:
+ CrFbWindow(uint64_t parentId) :
+ mSpuWindow(0),
+ mpCompositor(NULL),
+ mcUpdates(0),
+ mxPos(0),
+ myPos(0),
+ mWidth(0),
+ mHeight(0),
+ mParentId(parentId)
+ {
+ mFlags.Value = 0;
+ }
+
+ bool IsCreated()
+ {
+ return !!mSpuWindow;
+ }
+
+ void Destroy()
+ {
+ CRASSERT(!mcUpdates);
+
+ if (!mSpuWindow)
+ return;
+
+ cr_server.head_spu->dispatch_table.WindowDestroy(mSpuWindow);
+
+ mSpuWindow = 0;
+ mFlags.fDataPresented = 0;
+ }
+
+ int Reparent(uint64_t parentId)
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ uint64_t oldParentId = mParentId;
+
+ mParentId = parentId;
+
+ if (mSpuWindow)
+ {
+ if (oldParentId && !parentId && mFlags.fVisible)
+ cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, false);
+
+ renderspuSetWindowId(mParentId);
+ renderspuReparentWindow(mSpuWindow);
+ renderspuSetWindowId(cr_server.screen[0].winID);
+
+ if (parentId)
+ cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
+
+ if (!oldParentId && parentId && mFlags.fVisible)
+ cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int SetVisible(bool fVisible)
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ LOG(("CrWIN: Vidible [%d]", fVisible));
+
+ if (!fVisible != !mFlags.fVisible)
+ {
+ mFlags.fVisible = fVisible;
+ if (mSpuWindow && mParentId)
+ cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, fVisible);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int SetSize(uint32_t width, uint32_t height)
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ LOG(("CrWIN: Size [%d ; %d]", width, height));
+
+ if (mWidth != width || mHeight != height)
+ {
+ mFlags.fCompositoEntriesModified = 1;
+ mWidth = width;
+ mHeight = height;
+ if (mSpuWindow)
+ cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, width, height);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int SetPosition(int32_t x, int32_t y)
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ LOG(("CrWIN: Pos [%d ; %d]", x, y));
+// always do WindowPosition to ensure window is adjusted properly
+// if (x != mxPos || y != myPos)
+ {
+ mxPos = x;
+ myPos = y;
+ if (mSpuWindow)
+ cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, x, y);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int SetVisibleRegionsChanged()
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ mFlags.fCompositoEntriesModified = 1;
+ return VINF_SUCCESS;
+ }
+
+ int SetCompositor(const struct VBOXVR_SCR_COMPOSITOR * pCompositor)
+ {
+ if (!checkInitedUpdating())
+ {
+ WARN(("err"));
+ return VERR_INVALID_STATE;
+ }
+
+ mpCompositor = pCompositor;
+ mFlags.fCompositoEntriesModified = 1;
+ return VINF_SUCCESS;
+ }
+
+ int UpdateBegin()
+ {
+ ++mcUpdates;
+ if (mcUpdates > 1)
+ return VINF_SUCCESS;
+
+ Assert(!mFlags.fForcePresentOnReenable);
+// Assert(!mFlags.fCompositoEntriesModified);
+
+ if (mFlags.fDataPresented)
+ {
+ Assert(mSpuWindow);
+ cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, NULL, NULL);
+ mFlags.fForcePresentOnReenable = isPresentNeeded();
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ void UpdateEnd()
+ {
+ --mcUpdates;
+ Assert(mcUpdates < UINT32_MAX/2);
+ if (mcUpdates)
+ return;
+
+ checkRegions();
+
+ if (mSpuWindow)
+ {
+ bool fPresentNeeded = isPresentNeeded();
+ if (fPresentNeeded || mFlags.fForcePresentOnReenable)
+ {
+ mFlags.fForcePresentOnReenable = false;
+ cr_server.head_spu->dispatch_table.VBoxPresentComposition(mSpuWindow, mpCompositor, NULL);
+ }
+
+ /* even if the above branch is entered due to mFlags.fForcePresentOnReenable,
+ * the backend should clean up the compositor as soon as presentation is performed */
+ mFlags.fDataPresented = fPresentNeeded;
+ }
+ else
+ {
+ Assert(!mFlags.fDataPresented);
+ Assert(!mFlags.fForcePresentOnReenable);
+ }
+ }
+
+ uint64_t GetParentId()
+ {
+ return mParentId;
+ }
+
+ int Create()
+ {
+ if (mSpuWindow)
+ {
+ //WARN(("window already created"));
+ return VINF_ALREADY_INITIALIZED;
+ }
+
+ CRASSERT(cr_server.fVisualBitsDefault);
+ renderspuSetWindowId(mParentId);
+ mSpuWindow = cr_server.head_spu->dispatch_table.WindowCreate("", cr_server.fVisualBitsDefault);
+ renderspuSetWindowId(cr_server.screen[0].winID);
+ if (mSpuWindow < 0) {
+ WARN(("WindowCreate failed"));
+ return VERR_GENERAL_FAILURE;
+ }
+
+ cr_server.head_spu->dispatch_table.WindowSize(mSpuWindow, mWidth, mHeight);
+ cr_server.head_spu->dispatch_table.WindowPosition(mSpuWindow, mxPos, myPos);
+
+ checkRegions();
+
+ if (mParentId && mFlags.fVisible)
+ cr_server.head_spu->dispatch_table.WindowShow(mSpuWindow, true);
+
+ return VINF_SUCCESS;
+ }
+
+ ~CrFbWindow()
+ {
+ Destroy();
+ }
+protected:
+ void checkRegions()
+ {
+ if (!mSpuWindow)
+ return;
+
+ if (!mFlags.fCompositoEntriesModified)
+ return;
+
+ uint32_t cRects;
+ const RTRECT *pRects;
+ if (mpCompositor)
+ {
+ int rc = CrVrScrCompositorRegionsGet(mpCompositor, &cRects, NULL, &pRects, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorRegionsGet failed rc %d", rc));
+ cRects = 0;
+ pRects = NULL;
+ }
+ }
+ else
+ {
+ cRects = 0;
+ pRects = NULL;
+ }
+
+ cr_server.head_spu->dispatch_table.WindowVisibleRegion(mSpuWindow, cRects, (const GLint*)pRects);
+
+ mFlags.fCompositoEntriesModified = 0;
+ }
+
+ bool isPresentNeeded()
+ {
+ return mFlags.fVisible && mWidth && mHeight && mpCompositor && !CrVrScrCompositorIsEmpty(mpCompositor);
+ }
+
+ bool checkInitedUpdating()
+ {
+ if (!mcUpdates)
+ {
+ WARN(("not updating"));
+ return false;
+ }
+
+ return true;
+ }
+private:
+ GLint mSpuWindow;
+ const struct VBOXVR_SCR_COMPOSITOR * mpCompositor;
+ uint32_t mcUpdates;
+ int32_t mxPos;
+ int32_t myPos;
+ uint32_t mWidth;
+ uint32_t mHeight;
+ CR_FBWIN_FLAGS mFlags;
+ uint64_t mParentId;
+};
+
+typedef union CR_FBDISPWINDOW_FLAGS
+{
+ struct {
+ uint32_t fNeVisible : 1;
+ uint32_t fNeForce : 1;
+ uint32_t Reserved : 30;
+ };
+ uint32_t u32Value;
+} CR_FBDISPWINDOW_FLAGS;
+class CrFbDisplayWindow : public CrFbDisplayBase
+{
+public:
+ CrFbDisplayWindow(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
+ mpWindow(pWindow),
+ mViewportRect(*pViewportRect),
+ mu32Screen(~0)
+ {
+ mFlags.u32Value = 0;
+ CRASSERT(pWindow);
+ }
+
+ virtual ~CrFbDisplayWindow()
+ {
+ if (mpWindow)
+ delete mpWindow;
+ }
+
+ virtual int UpdateBegin(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = mpWindow->UpdateBegin();
+ if (RT_SUCCESS(rc))
+ {
+ rc = CrFbDisplayBase::UpdateBegin(pFb);
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ else
+ WARN(("err"));
+ }
+ else
+ WARN(("err"));
+
+ return rc;
+ }
+
+ virtual void UpdateEnd(struct CR_FRAMEBUFFER *pFb)
+ {
+ CrFbDisplayBase::UpdateEnd(pFb);
+
+ mpWindow->UpdateEnd();
+ }
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ if (mpWindow->GetParentId())
+ {
+ rc = mpWindow->Create();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return screenChanged();
+ }
+
+ const RTRECT* getViewportRect()
+ {
+ return &mViewportRect;
+ }
+
+ virtual int setViewportRect(const RTRECT *pViewportRect)
+ {
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+// always call SetPosition to ensure window is adjustep properly
+// if (pViewportRect->xLeft != mViewportRect.xLeft || pViewportRect->yTop != mViewportRect.yTop)
+ {
+ const RTRECT* pRect = getRect();
+ int rc = mpWindow->SetPosition(pRect->xLeft - pViewportRect->xLeft, pRect->yTop - pViewportRect->yTop);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("SetPosition failed"));
+ return rc;
+ }
+ }
+
+ mViewportRect = *pViewportRect;
+
+ return VINF_SUCCESS;
+ }
+
+ virtual CrFbWindow * windowDetach()
+ {
+ if (isUpdating())
+ {
+ WARN(("updating!"));
+ return NULL;
+ }
+
+ CrFbWindow * pWindow = mpWindow;
+ if (mpWindow)
+ {
+ windowCleanup();
+ mpWindow = NULL;
+ }
+ return pWindow;
+ }
+
+ virtual CrFbWindow * windowAttach(CrFbWindow * pNewWindow)
+ {
+ if (isUpdating())
+ {
+ WARN(("updating!"));
+ return NULL;
+ }
+
+ CrFbWindow * pOld = mpWindow;
+ if (mpWindow)
+ windowDetach();
+
+ mpWindow = pNewWindow;
+ if (pNewWindow)
+ windowSync();
+
+ return mpWindow;
+ }
+
+ virtual int reparent(uint64_t parentId)
+ {
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+ int rc = mpWindow->Reparent(parentId);
+ if (!RT_SUCCESS(rc))
+ WARN(("window reparent failed"));
+
+ mFlags.fNeForce = 1;
+
+ return rc;
+ }
+
+ virtual bool isVisible()
+ {
+ HCR_FRAMEBUFFER hFb = getFramebuffer();
+ if (!hFb)
+ return false;
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(hFb);
+ return !CrVrScrCompositorIsEmpty(pCompositor);
+ }
+
+ int winVisibilityChanged()
+ {
+ int rc = mpWindow->UpdateBegin();
+ if (RT_SUCCESS(rc))
+ {
+ rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+ if (!RT_SUCCESS(rc))
+ WARN(("SetVisible failed, rc %d", rc));
+
+ mpWindow->UpdateEnd();
+ }
+ else
+ WARN(("UpdateBegin failed, rc %d", rc));
+
+ return rc;
+ }
+
+protected:
+ virtual void onUpdateEnd()
+ {
+ CrFbDisplayBase::onUpdateEnd();
+ bool fVisible = isVisible();
+ if (mFlags.fNeVisible != fVisible || mFlags.fNeForce)
+ {
+ crVBoxServerNotifyEvent(mu32Screen, VBOX3D_NOTIFY_EVENT_TYPE_VISIBLE_3DDATA, fVisible ? (void*)1 : NULL);
+ mFlags.fNeVisible = fVisible;
+ mFlags.fNeForce = 0;
+ }
+ }
+
+ virtual void ueRegions()
+ {
+ mpWindow->SetVisibleRegionsChanged();
+ }
+
+ virtual int screenChanged()
+ {
+ if (!isUpdating())
+ {
+ WARN(("not updating!"));
+ return VERR_INVALID_STATE;
+ }
+
+ if (CrFbIsEnabled(getFramebuffer()))
+ {
+ const RTRECT* pRect = getRect();
+ int rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("SetComposition failed rc %d", rc));
+ return rc;
+ }
+
+ setRegionsChanged();
+
+ return mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
+ }
+
+ return mpWindow->SetVisible(false);
+ }
+
+ virtual int windowSetCompositor(bool fSet)
+ {
+ if (fSet)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+ return mpWindow->SetCompositor(pCompositor);
+ }
+ return mpWindow->SetCompositor(NULL);
+ }
+
+ virtual int windowCleanup()
+ {
+ int rc = mpWindow->UpdateBegin();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = mpWindow->SetVisible(false);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = windowSetCompositor(false);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ mpWindow->UpdateEnd();
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int fbCleanup()
+ {
+ int rc = windowCleanup();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("windowCleanup failed"));
+ return rc;
+ }
+ return CrFbDisplayBase::fbCleanup();
+ }
+
+ virtual int windowSync()
+ {
+ const RTRECT* pRect = getRect();
+
+ int rc = mpWindow->UpdateBegin();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = windowSetCompositor(true);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = mpWindow->SetPosition(pRect->xLeft - mViewportRect.xLeft, pRect->yTop - mViewportRect.yTop);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = mpWindow->SetSize((uint32_t)(pRect->xRight - pRect->xLeft), (uint32_t)(pRect->yBottom - pRect->yTop));
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ rc = mpWindow->SetVisible(!g_CrPresenter.fWindowsForceHidden);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ mpWindow->UpdateEnd();
+ return rc;
+ }
+
+ mpWindow->UpdateEnd();
+
+ return rc;
+ }
+
+ virtual int fbSync()
+ {
+ int rc = CrFbDisplayBase::fbSync();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ mu32Screen = CrFbGetScreenInfo(getFramebuffer())->u32ViewIndex;
+
+ return windowSync();
+ }
+
+ virtual const struct RTRECT* getRect()
+ {
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(getFramebuffer());
+ return CrVrScrCompositorRectGet(pCompositor);
+ }
+
+ CrFbWindow* getWindow() {return mpWindow;}
+private:
+ CrFbWindow *mpWindow;
+ RTRECT mViewportRect;
+ CR_FBDISPWINDOW_FLAGS mFlags;
+ uint32_t mu32Screen;
+};
+
+class CrFbDisplayWindowRootVr : public CrFbDisplayWindow
+{
+public:
+ CrFbDisplayWindowRootVr(CrFbWindow *pWindow, const RTRECT *pViewportRect) :
+ CrFbDisplayWindow(pWindow, pViewportRect)
+ {
+ CrVrScrCompositorInit(&mCompositor, NULL);
+ }
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryCreated(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = entryAlloc();
+ CrVrScrCompositorEntryInit(pMyEntry, CrVrScrCompositorEntryRectGet(pSrcEntry), CrVrScrCompositorEntryTexGet(pSrcEntry), NULL);
+ CrVrScrCompositorEntryFlagsSet(pMyEntry, CrVrScrCompositorEntryFlagsGet(pSrcEntry));
+ rc = CrFbDDataEntryPut(hEntry, slotGet(), pMyEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbDDataEntryPut failed rc %d", rc));
+ entryFree(pMyEntry);
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryAdded(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryAdded(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+ Assert(pMyEntry);
+ CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hNewEntry, slotGet());
+ CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcNewEntry));
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+ CrVrScrCompositorEntryTexSet(pMyEntry, CrVrScrCompositorEntryTexGet(pSrcEntry));
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryRemoved(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+ rc = CrVrScrCompositorEntryRegionsSet(&mCompositor, pMyEntry, NULL, 0, NULL, false, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayWindow::EntryDestroyed(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pSrcEntry = CrFbEntryGetCompositorEntry(hEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, slotGet());
+ CrVrScrCompositorEntryCleanup(pMyEntry);
+ entryFree(pMyEntry);
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int setViewportRect(const RTRECT *pViewportRect)
+ {
+ int rc = CrFbDisplayWindow::setViewportRect(pViewportRect);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = setRegionsChanged();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+protected:
+ virtual int windowSetCompositor(bool fSet)
+ {
+ if (fSet)
+ return getWindow()->SetCompositor(&mCompositor);
+ return getWindow()->SetCompositor(NULL);
+ }
+
+ virtual void ueRegions()
+ {
+ synchCompositorRegions();
+ }
+
+ int compositorMarkUpdated()
+ {
+ CrVrScrCompositorClear(&mCompositor);
+
+ int rc = CrVrScrCompositorRectSet(&mCompositor, CrVrScrCompositorRectGet(CrFbGetCompositor(getFramebuffer())), NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = setRegionsChanged();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("screenChanged failed %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int screenChanged()
+ {
+ int rc = compositorMarkUpdated();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ rc = CrFbDisplayWindow::screenChanged();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("screenChanged failed %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual const struct RTRECT* getRect()
+ {
+ return CrVrScrCompositorRectGet(&mCompositor);
+ }
+
+ virtual int fbCleanup()
+ {
+ int rc = clearCompositor();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return CrFbDisplayWindow::fbCleanup();
+ }
+
+ virtual int fbSync()
+ {
+ int rc = synchCompositor();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return CrFbDisplayWindow::fbSync();
+ }
+
+ VBOXVR_SCR_COMPOSITOR_ENTRY* entryAlloc()
+ {
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemCacheAlloc(g_CrPresenter.CEntryLookasideList);
+#else
+ return (VBOXVR_SCR_COMPOSITOR_ENTRY*)RTMemAlloc(sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY));
+#endif
+ }
+
+ void entryFree(VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry)
+ {
+ Assert(!CrVrScrCompositorEntryIsUsed(pEntry));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMemCacheFree(g_CrPresenter.CEntryLookasideList, pEntry);
+#else
+ RTMemFree(pEntry);
+#endif
+ }
+
+ int synchCompositorRegions()
+ {
+ int rc;
+
+ rootVrTranslateForPos();
+
+ /* ensure the rootvr compositor does not hold any data,
+ * i.e. cleanup all rootvr entries data */
+ CrVrScrCompositorClear(&mCompositor);
+
+ rc = CrVrScrCompositorIntersectedList(CrFbGetCompositor(getFramebuffer()), &cr_server.RootVr, &mCompositor, rootVrGetCEntry, this, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorIntersectedList failed, rc %d", rc));
+ return rc;
+ }
+
+ return getWindow()->SetVisibleRegionsChanged();
+ }
+
+ virtual int synchCompositor()
+ {
+ int rc = compositorMarkUpdated();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("compositorMarkUpdated failed, rc %d", rc));
+ return rc;
+ }
+
+ rc = fbSynchAddAllEntries();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("fbSynchAddAllEntries failed, rc %d", rc));
+ return rc;
+ }
+
+ return rc;
+ }
+
+ virtual int clearCompositor()
+ {
+ return fbCleanupRemoveAllEntries();
+ }
+
+ void rootVrTranslateForPos()
+ {
+ const RTRECT *pRect = getViewportRect();
+ const struct VBVAINFOSCREEN* pScreen = CrFbGetScreenInfo(getFramebuffer());
+ int32_t x = pScreen->i32OriginX;
+ int32_t y = pScreen->i32OriginY;
+ int32_t dx = cr_server.RootVrCurPoint.x - x;
+ int32_t dy = cr_server.RootVrCurPoint.y - y;
+
+ cr_server.RootVrCurPoint.x = x;
+ cr_server.RootVrCurPoint.y = y;
+
+ VBoxVrListTranslate(&cr_server.RootVr, dx, dy);
+ }
+
+ static DECLCALLBACK(VBOXVR_SCR_COMPOSITOR_ENTRY*) rootVrGetCEntry(const VBOXVR_SCR_COMPOSITOR_ENTRY*pEntry, void *pvContext)
+ {
+ CrFbDisplayWindowRootVr *pThis = (CrFbDisplayWindowRootVr*)pvContext;
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+ VBOXVR_SCR_COMPOSITOR_ENTRY *pMyEntry = (VBOXVR_SCR_COMPOSITOR_ENTRY*)CrFbDDataEntryGet(hEntry, pThis->slotGet());
+ Assert(!CrVrScrCompositorEntryIsUsed(pMyEntry));
+ CrVrScrCompositorEntryRectSet(&pThis->mCompositor, pMyEntry, CrVrScrCompositorEntryRectGet(pEntry));
+ return pMyEntry;
+ }
+private:
+ VBOXVR_SCR_COMPOSITOR mCompositor;
+};
+
+class CrFbDisplayVrdp : public CrFbDisplayBase
+{
+public:
+ CrFbDisplayVrdp()
+ {
+ memset(&mPos, 0, sizeof (mPos));
+ }
+
+ virtual int EntryCreated(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryCreated(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("EntryAdded failed rc %d", rc));
+ return rc;
+ }
+
+ Assert(!CrFbDDataEntryGet(hEntry, slotGet()));
+ rc = vrdpCreate(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vrdpCreate failed rc %d", rc));
+ return rc;
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ int rc = CrFbDisplayBase::EntryReplaced(pFb, hNewEntry, hReplacedEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pReplacedEntry = CrFbEntryGetCompositorEntry(hReplacedEntry);
+ CR_TEXDATA *pReplacedTex = CrVrScrCompositorEntryTexGet(pReplacedEntry);
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pNewEntry = CrFbEntryGetCompositorEntry(hNewEntry);
+ CR_TEXDATA *pNewTex = CrVrScrCompositorEntryTexGet(pNewEntry);
+
+ CrTdBltDataInvalidateNe(pReplacedTex);
+
+ rc = CrTdBltEnter(pNewTex);
+ if (RT_SUCCESS(rc))
+ {
+ rc = vrdpFrame(hNewEntry);
+ CrTdBltLeave(pNewTex);
+ }
+ else
+ WARN(("CrTdBltEnter failed %d", rc));
+
+ return rc;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryTexChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+
+ rc = CrTdBltEnter(pTex);
+ if (RT_SUCCESS(rc))
+ {
+ rc = vrdpFrame(hEntry);
+ CrTdBltLeave(pTex);
+ }
+ else
+ WARN(("CrTdBltEnter failed %d", rc));
+
+ return rc;
+ }
+
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryRemoved(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+ CrTdBltDataInvalidateNe(pTex);
+
+ return vrdpRegions(pFb, hEntry);
+ }
+
+ virtual int EntryDestroyed(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryDestroyed(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ vrdpDestroy(hEntry);
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryPosChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ int rc = CrFbDisplayBase::EntryPosChanged(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ vrdpGeometry(hEntry);
+
+ return VINF_SUCCESS;
+ }
+
+ virtual int RegionsChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::RegionsChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return vrdpRegionsAll(pFb);
+ }
+
+ virtual int FramebufferChanged(struct CR_FRAMEBUFFER *pFb)
+ {
+ int rc = CrFbDisplayBase::FramebufferChanged(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ syncPos();
+
+ rc = vrdpSyncEntryAll(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return vrdpRegionsAll(pFb);
+ }
+
+protected:
+ void syncPos()
+ {
+ const struct VBVAINFOSCREEN* pScreenInfo = CrFbGetScreenInfo(getFramebuffer());
+ mPos.x = pScreenInfo->i32OriginX;
+ mPos.y = pScreenInfo->i32OriginY;
+ }
+
+ virtual int fbCleanup()
+ {
+ int rc = fbCleanupRemoveAllEntries();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return CrFbDisplayBase::fbCleanup();
+ }
+
+ virtual int fbSync()
+ {
+ syncPos();
+
+ int rc = fbSynchAddAllEntries();
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("err"));
+ return rc;
+ }
+
+ return CrFbDisplayBase::fbSync();
+ }
+protected:
+ void vrdpDestroy(HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+ cr_server.outputRedirect.CROREnd(pVrdp);
+ }
+
+ void vrdpGeometry(HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+
+ cr_server.outputRedirect.CRORGeometry(pVrdp,
+ mPos.x + CrVrScrCompositorEntryRectGet(pEntry)->xLeft,
+ mPos.y + CrVrScrCompositorEntryRectGet(pEntry)->yTop,
+ CrVrScrCompositorEntryTexGet(pEntry)->Tex.width,
+ CrVrScrCompositorEntryTexGet(pEntry)->Tex.height);
+ }
+
+ int vrdpRegions(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ uint32_t cRects;
+ const RTRECT *pRects;
+
+ int rc = CrVrScrCompositorEntryRegionsGet(pCompositor, pEntry, &cRects, NULL, &pRects, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrVrScrCompositorEntryRegionsGet failed, rc %d", rc));
+ return rc;
+ }
+
+ cr_server.outputRedirect.CRORVisibleRegion(pVrdp, cRects, pRects);
+ return VINF_SUCCESS;
+ }
+
+ int vrdpFrame(HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ void *pVrdp = CrFbDDataEntryGet(hEntry, slotGet());
+ const VBOXVR_SCR_COMPOSITOR_ENTRY* pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ CR_TEXDATA *pTex = CrVrScrCompositorEntryTexGet(pEntry);
+ const CR_BLITTER_IMG *pImg;
+ CrTdBltDataInvalidateNe(pTex);
+ int rc = CrTdBltDataAcquire(pTex, GL_BGRA, !!(CrVrScrCompositorEntryFlagsGet(pEntry) & CRBLT_F_INVERT_SRC_YCOORDS), &pImg);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrTdBltDataAcquire failed rc %d", rc));
+ return rc;
+ }
+
+ cr_server.outputRedirect.CRORFrame(pVrdp, pImg->pvData, pImg->cbData);
+ CrTdBltDataRelease(pTex);
+ return VINF_SUCCESS;
+ }
+
+ int vrdpRegionsAll(struct CR_FRAMEBUFFER *pFb)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ CrVrScrCompositorConstIterInit(pCompositor, &Iter);
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+ vrdpRegions(pFb, hEntry);
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int vrdpSynchEntry(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ vrdpGeometry(hEntry);
+
+ return vrdpRegions(pFb, hEntry);;
+ }
+
+ int vrdpSyncEntryAll(struct CR_FRAMEBUFFER *pFb)
+ {
+ const struct VBOXVR_SCR_COMPOSITOR* pCompositor = CrFbGetCompositor(pFb);
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ CrVrScrCompositorConstIterInit(pCompositor, &Iter);
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+ int rc = vrdpSynchEntry(pFb, hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("vrdpSynchEntry failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+ }
+
+ int vrdpCreate(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ void *pVrdp;
+
+ /* Query supported formats. */
+ uint32_t cbFormats = 4096;
+ char *pachFormats = (char *)crAlloc(cbFormats);
+
+ if (!pachFormats)
+ {
+ WARN(("crAlloc failed"));
+ return VERR_NO_MEMORY;
+ }
+
+ int rc = cr_server.outputRedirect.CRORContextProperty(cr_server.outputRedirect.pvContext,
+ 0 /* H3DOR_PROP_FORMATS */, // @todo from a header
+ pachFormats, cbFormats, &cbFormats);
+ if (RT_SUCCESS(rc))
+ {
+ if (RTStrStr(pachFormats, "H3DOR_FMT_RGBA_TOPDOWN"))
+ {
+ cr_server.outputRedirect.CRORBegin(cr_server.outputRedirect.pvContext,
+ &pVrdp,
+ "H3DOR_FMT_RGBA_TOPDOWN"); // @todo from a header
+
+ if (pVrdp)
+ {
+ rc = CrFbDDataEntryPut(hEntry, slotGet(), pVrdp);
+ if (RT_SUCCESS(rc))
+ {
+ vrdpGeometry(hEntry);
+ vrdpRegions(hFb, hEntry);
+ //vrdpFrame(hEntry);
+ return VINF_SUCCESS;
+ }
+ else
+ WARN(("CrFbDDataEntryPut failed rc %d", rc));
+
+ cr_server.outputRedirect.CROREnd(pVrdp);
+ }
+ else
+ {
+ WARN(("CRORBegin failed"));
+ rc = VERR_GENERAL_FAILURE;
+ }
+ }
+ }
+ else
+ WARN(("CRORContextProperty failed rc %d", rc));
+
+ crFree(pachFormats);
+
+ return rc;
+ }
+private:
+ RTPOINT mPos;
+};
+
+CrFbDisplayBase::~CrFbDisplayBase()
+{
+ Assert(!mcUpdates);
+
+ if (mpContainer)
+ mpContainer->remove(this);
+}
+
+
+#if 0
+
+
+
+
+
+void crDbgDumpRect(uint32_t i, const RTRECT *pRect)
+{
+ crDebug("%d: (%d;%d) X (%d;%d)", i, pRect->xLeft, pRect->yTop, pRect->xRight, pRect->yBottom);
+}
+
+void crDbgDumpRects(uint32_t cRects, const RTRECT *paRects)
+{
+ crDebug("Dumping rects (%d)", cRects);
+ for (uint32_t i = 0; i < cRects; ++i)
+ {
+ crDbgDumpRect(i, &paRects[i]);
+ }
+ crDebug("End Dumping rects (%d)", cRects);
+}
+
+int crServerDisplaySaveState(PSSMHANDLE pSSM)
+{
+ int rc;
+ int cDisplays = 0, i;
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
+ ++cDisplays;
+ }
+
+ rc = SSMR3PutS32(pSSM, cDisplays);
+ AssertRCReturn(rc, rc);
+
+ if (!cDisplays)
+ return VINF_SUCCESS;
+
+ rc = SSMR3PutS32(pSSM, cr_server.screenCount);
+ AssertRCReturn(rc, rc);
+
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ rc = SSMR3PutS32(pSSM, cr_server.screen[i].x);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutS32(pSSM, cr_server.screen[i].y);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, cr_server.screen[i].w);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, cr_server.screen[i].h);
+ AssertRCReturn(rc, rc);
+ }
+
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ if (ASMBitTest(cr_server.DisplaysInitMap, i) && !CrDpIsEmpty(&cr_server.aDispplays[i]))
+ {
+ rc = SSMR3PutS32(pSSM, i);
+ AssertRCReturn(rc, rc);
+
+ rc = CrDpSaveState(&cr_server.aDispplays[i], pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+int crServerDisplayLoadState(PSSMHANDLE pSSM, uint32_t u32Version)
+{
+
+}
+#endif
+
+class CrFbDisplayEntryDataMonitor : public CrFbDisplayBase
+{
+public:
+ virtual int EntryReplaced(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hNewEntry, HCR_FRAMEBUFFER_ENTRY hReplacedEntry)
+ {
+ entryDataChanged(pFb, hReplacedEntry);
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryTexChanged(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ entryDataChanged(pFb, hEntry);
+ return VINF_SUCCESS;
+ }
+
+ virtual int EntryRemoved(struct CR_FRAMEBUFFER *pFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+ entryDataChanged(pFb, hEntry);
+ return VINF_SUCCESS;
+ }
+protected:
+ virtual void entryDataChanged(HCR_FRAMEBUFFER hFb, HCR_FRAMEBUFFER_ENTRY hEntry)
+ {
+
+ }
+};
+
+int CrPMgrInit()
+{
+ int rc = VINF_SUCCESS;
+ memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
+ g_CrPresenter.pFbTexMap = crAllocHashtable();
+ if (g_CrPresenter.pFbTexMap)
+ {
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ rc = RTMemCacheCreate(&g_CrPresenter.FbEntryLookasideList, sizeof (CR_FRAMEBUFFER_ENTRY),
+ 0, /* size_t cbAlignment */
+ UINT32_MAX, /* uint32_t cMaxObjects */
+ NULL, /* PFNMEMCACHECTOR pfnCtor*/
+ NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+ NULL, /* void *pvUser*/
+ 0 /* uint32_t fFlags*/
+ );
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTMemCacheCreate(&g_CrPresenter.FbTexLookasideList, sizeof (CR_FBTEX),
+ 0, /* size_t cbAlignment */
+ UINT32_MAX, /* uint32_t cMaxObjects */
+ NULL, /* PFNMEMCACHECTOR pfnCtor*/
+ NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+ NULL, /* void *pvUser*/
+ 0 /* uint32_t fFlags*/
+ );
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTMemCacheCreate(&g_CrPresenter.CEntryLookasideList, sizeof (VBOXVR_SCR_COMPOSITOR_ENTRY),
+ 0, /* size_t cbAlignment */
+ UINT32_MAX, /* uint32_t cMaxObjects */
+ NULL, /* PFNMEMCACHECTOR pfnCtor*/
+ NULL, /* PFNMEMCACHEDTOR pfnDtor*/
+ NULL, /* void *pvUser*/
+ 0 /* uint32_t fFlags*/
+ );
+ if (RT_SUCCESS(rc))
+ {
+#endif
+ rc = crPMgrModeModifyGlobal(CR_PMGR_MODE_WINDOW, 0);
+ if (RT_SUCCESS(rc))
+ return VINF_SUCCESS;
+ else
+ WARN(("crPMgrModeModifyGlobal failed rc %d", rc));
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
+ }
+ else
+ WARN(("RTMemCacheCreate failed rc %d", rc));
+
+ RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
+ }
+ else
+ WARN(("RTMemCacheCreate failed rc %d", rc));
+
+ RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
+ }
+ else
+ WARN(("RTMemCacheCreate failed rc %d", rc));
+#endif
+ }
+ else
+ {
+ WARN(("crAllocHashtable failed"));
+ rc = VERR_NO_MEMORY;
+ }
+ return rc;
+}
+
+void CrPMgrTerm()
+{
+ crPMgrModeModifyGlobal(0, CR_PMGR_MODE_ALL);
+
+ HCR_FRAMEBUFFER hFb;
+
+ for (hFb = CrPMgrFbGetFirstInitialized();
+ hFb;
+ hFb = CrPMgrFbGetNextInitialized(hFb))
+ {
+ uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+ CrFbDisplaySet(hFb, NULL);
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+
+ if (pInfo->pDpComposite)
+ delete pInfo->pDpComposite;
+
+ Assert(!pInfo->pDpWin);
+ Assert(!pInfo->pDpWinRootVr);
+ Assert(!pInfo->pDpVrdp);
+
+ CrFbTerm(hFb);
+ }
+
+#ifndef VBOXVDBG_MEMCACHE_DISABLE
+ RTMemCacheDestroy(g_CrPresenter.FbEntryLookasideList);
+ RTMemCacheDestroy(g_CrPresenter.FbTexLookasideList);
+ RTMemCacheDestroy(g_CrPresenter.CEntryLookasideList);
+#endif
+ crFreeHashtable(g_CrPresenter.pFbTexMap, NULL);
+
+ if (g_CrPresenter.pvTmpBuf)
+ RTMemFree(g_CrPresenter.pvTmpBuf);
+
+ if (g_CrPresenter.pvTmpBuf2)
+ RTMemFree(g_CrPresenter.pvTmpBuf2);
+
+ memset(&g_CrPresenter, 0, sizeof (g_CrPresenter));
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGet(uint32_t idScreen)
+{
+ if (idScreen >= CR_MAX_GUEST_MONITORS)
+ {
+ WARN(("invalid idScreen %d", idScreen));
+ return NULL;
+ }
+
+ if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
+ {
+ CrFbInit(&g_CrPresenter.aFramebuffers[idScreen], idScreen);
+ CrFBmSetAtomic(&g_CrPresenter.FramebufferInitMap, idScreen);
+ }
+ else
+ Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
+
+ return &g_CrPresenter.aFramebuffers[idScreen];
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetInitialized(uint32_t idScreen)
+{
+ if (idScreen >= CR_MAX_GUEST_MONITORS)
+ {
+ WARN(("invalid idScreen %d", idScreen));
+ return NULL;
+ }
+
+ if (!CrFBmIsSet(&g_CrPresenter.FramebufferInitMap, idScreen))
+ {
+ return NULL;
+ }
+ else
+ Assert(g_CrPresenter.aFramebuffers[idScreen].ScreenInfo.u32ViewIndex == idScreen);
+
+ return &g_CrPresenter.aFramebuffers[idScreen];
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetEnabled(uint32_t idScreen)
+{
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(idScreen);
+
+ if(hFb && CrFbIsEnabled(hFb))
+ return hFb;
+
+ return NULL;
+}
+
+static HCR_FRAMEBUFFER crPMgrFbGetNextEnabled(uint32_t i)
+{
+ for (;i < (uint32_t)cr_server.screenCount; ++i)
+ {
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(i);
+ if (hFb)
+ return hFb;
+ }
+
+ return NULL;
+}
+
+static HCR_FRAMEBUFFER crPMgrFbGetNextInitialized(uint32_t i)
+{
+ for (;i < (uint32_t)cr_server.screenCount; ++i)
+ {
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
+ if (hFb)
+ return hFb;
+ }
+
+ return NULL;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetFirstEnabled()
+{
+ HCR_FRAMEBUFFER hFb = crPMgrFbGetNextEnabled(0);
+// if (!hFb)
+// WARN(("no enabled framebuffer found"));
+ return hFb;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetNextEnabled(HCR_FRAMEBUFFER hFb)
+{
+ return crPMgrFbGetNextEnabled(hFb->ScreenInfo.u32ViewIndex+1);
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetFirstInitialized()
+{
+ HCR_FRAMEBUFFER hFb = crPMgrFbGetNextInitialized(0);
+// if (!hFb)
+// WARN(("no initialized framebuffer found"));
+ return hFb;
+}
+
+HCR_FRAMEBUFFER CrPMgrFbGetNextInitialized(HCR_FRAMEBUFFER hFb)
+{
+ return crPMgrFbGetNextInitialized(hFb->ScreenInfo.u32ViewIndex+1);
+}
+
+static uint32_t crPMgrModeAdjustVal(uint32_t u32Mode)
+{
+ u32Mode = CR_PMGR_MODE_ALL & u32Mode;
+ if (CR_PMGR_MODE_ROOTVR & u32Mode)
+ u32Mode &= ~CR_PMGR_MODE_WINDOW;
+ return u32Mode;
+}
+
+int CrPMgrScreenChanged(uint32_t idScreen)
+{
+ if (idScreen >= CR_MAX_GUEST_MONITORS)
+ {
+ WARN(("invalid idScreen %d", idScreen));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+ if (pInfo->pDpWin)
+ {
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
+ if (CrFbIsUpdating(hFb))
+ {
+ WARN(("trying to update viewport while framebuffer is being updated"));
+ return VERR_INVALID_STATE;
+ }
+
+ int rc = pInfo->pDpWin->UpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ pInfo->pDpWin->reparent(cr_server.screen[idScreen].winID);
+
+ pInfo->pDpWin->UpdateEnd(hFb);
+ }
+ else
+ WARN(("UpdateBegin failed %d", rc));
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrViewportUpdate(uint32_t idScreen)
+{
+ if (idScreen >= CR_MAX_GUEST_MONITORS)
+ {
+ WARN(("invalid idScreen %d", idScreen));
+ return VERR_INVALID_PARAMETER;
+ }
+
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+ if (pInfo->pDpWin)
+ {
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGet(idScreen);
+ if (CrFbIsUpdating(hFb))
+ {
+ WARN(("trying to update viewport while framebuffer is being updated"));
+ return VERR_INVALID_STATE;
+ }
+
+ int rc = pInfo->pDpWin->UpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ pInfo->pDpWin->setViewportRect(&cr_server.screenVieport[idScreen].Rect);
+ pInfo->pDpWin->UpdateEnd(hFb);
+ }
+ else
+ WARN(("UpdateBegin failed %d", rc));
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrModeModify(HCR_FRAMEBUFFER hFb, uint32_t u32ModeAdd, uint32_t u32ModeRemove)
+{
+ uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+ u32ModeRemove = ((u32ModeRemove | crPMgrModeAdjustVal(u32ModeRemove)) & CR_PMGR_MODE_ALL);
+ u32ModeAdd = crPMgrModeAdjustVal(u32ModeAdd);
+ u32ModeRemove &= pInfo->u32Mode;
+ u32ModeAdd &= ~(u32ModeRemove | pInfo->u32Mode);
+ uint32_t u32ModeResulting = ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove);
+ uint32_t u32Tmp = crPMgrModeAdjustVal(u32ModeResulting);
+ if (u32Tmp != u32ModeResulting)
+ {
+ u32ModeAdd |= (u32Tmp & ~u32ModeResulting);
+ u32ModeRemove |= (~u32Tmp & u32ModeResulting);
+ u32ModeResulting = u32Tmp;
+ Assert(u32ModeResulting == ((pInfo->u32Mode | u32ModeAdd) & ~u32ModeRemove));
+ }
+ if (!u32ModeRemove && !u32ModeAdd)
+ return VINF_SUCCESS;
+
+ if (!pInfo->pDpComposite)
+ {
+ pInfo->pDpComposite = new CrFbDisplayComposite();
+ pInfo->pDpComposite->setFramebuffer(hFb);
+ }
+
+ CrFbWindow * pOldWin = NULL;
+
+ if (u32ModeRemove & CR_PMGR_MODE_ROOTVR)
+ {
+ CRASSERT(pInfo->pDpWinRootVr);
+ CRASSERT(pInfo->pDpWin == pInfo->pDpWinRootVr);
+ pInfo->pDpComposite->remove(pInfo->pDpWinRootVr);
+ pOldWin = pInfo->pDpWinRootVr->windowDetach();
+ CRASSERT(pOldWin);
+ delete pInfo->pDpWinRootVr;
+ pInfo->pDpWinRootVr = NULL;
+ pInfo->pDpWin = NULL;
+ }
+ else if (u32ModeRemove & CR_PMGR_MODE_WINDOW)
+ {
+ CRASSERT(!pInfo->pDpWinRootVr);
+ CRASSERT(pInfo->pDpWin);
+ pInfo->pDpComposite->remove(pInfo->pDpWin);
+ pOldWin = pInfo->pDpWin->windowDetach();
+ CRASSERT(pOldWin);
+ delete pInfo->pDpWin;
+ pInfo->pDpWin = NULL;
+ }
+
+ if (u32ModeRemove & CR_PMGR_MODE_VRDP)
+ {
+ CRASSERT(pInfo->pDpVrdp);
+ if (pInfo->pDpComposite)
+ pInfo->pDpComposite->remove(pInfo->pDpVrdp);
+ else
+ CrFbDisplaySet(hFb, NULL);
+
+ delete pInfo->pDpVrdp;
+ pInfo->pDpVrdp = NULL;
+ }
+
+ CrFbDisplayBase *pDpToSet = NULL;
+
+ if (u32ModeAdd & CR_PMGR_MODE_ROOTVR)
+ {
+ CRASSERT(!pInfo->pDpWin);
+ CRASSERT(!pInfo->pDpWinRootVr);
+
+ if (!pOldWin)
+ pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
+
+ pInfo->pDpWinRootVr = new CrFbDisplayWindowRootVr(pOldWin, &cr_server.screenVieport[idScreen].Rect);
+ pOldWin = NULL;
+ pInfo->pDpWin = pInfo->pDpWinRootVr;
+ pInfo->pDpComposite->add(pInfo->pDpWinRootVr);
+ }
+ else if (u32ModeAdd & CR_PMGR_MODE_WINDOW)
+ {
+ CRASSERT(!pInfo->pDpWin);
+ CRASSERT(!pInfo->pDpWinRootVr);
+
+ if (!pOldWin)
+ pOldWin = new CrFbWindow(cr_server.screen[idScreen].winID);
+
+ pInfo->pDpWin = new CrFbDisplayWindow(pOldWin, &cr_server.screenVieport[idScreen].Rect);
+ pOldWin = NULL;
+ pInfo->pDpComposite->add(pInfo->pDpWin);
+ }
+
+ if (u32ModeAdd & CR_PMGR_MODE_VRDP)
+ {
+ CRASSERT(!pInfo->pDpVrdp);
+ pInfo->pDpVrdp = new CrFbDisplayVrdp();
+ pInfo->pDpComposite->add(pInfo->pDpVrdp);
+ }
+
+ if (pInfo->pDpComposite->getDisplayCount() > 1)
+ {
+ ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
+ if (pCur != (ICrFbDisplay*)pInfo->pDpComposite)
+ CrFbDisplaySet(hFb, pInfo->pDpComposite);
+ }
+ else
+ {
+ ICrFbDisplay* pCur = CrFbDisplayGet(hFb);
+ ICrFbDisplay* pFirst = pInfo->pDpComposite->first();
+ if (pCur != pFirst)
+ CrFbDisplaySet(hFb, pFirst);
+ }
+
+ if (pOldWin)
+ delete pOldWin;
+
+ pInfo->u32Mode = u32ModeResulting;
+
+ return VINF_SUCCESS;
+}
+
+static int crPMgrModeModifyGlobal(uint32_t u32ModeAdd, uint32_t u32ModeRemove)
+{
+ g_CrPresenter.u32DisplayMode = (g_CrPresenter.u32DisplayMode | u32ModeAdd) & ~u32ModeRemove;
+
+ for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ CrPMgrModeModify(hFb, u32ModeAdd, u32ModeRemove);
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrModeVrdp(bool fEnable)
+{
+ uint32_t u32ModeAdd, u32ModeRemove;
+ if (fEnable)
+ {
+ u32ModeAdd = CR_PMGR_MODE_VRDP;
+ u32ModeRemove = 0;
+ }
+ else
+ {
+ u32ModeAdd = 0;
+ u32ModeRemove = CR_PMGR_MODE_VRDP;
+ }
+ return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
+}
+
+int CrPMgrModeRootVr(bool fEnable)
+{
+ uint32_t u32ModeAdd, u32ModeRemove;
+ if (fEnable)
+ {
+ u32ModeAdd = CR_PMGR_MODE_ROOTVR;
+ u32ModeRemove = CR_PMGR_MODE_WINDOW;
+ }
+ else
+ {
+ u32ModeAdd = CR_PMGR_MODE_WINDOW;
+ u32ModeRemove = CR_PMGR_MODE_ROOTVR;
+ }
+
+ return crPMgrModeModifyGlobal(u32ModeAdd, u32ModeRemove);
+}
+
+int CrPMgrModeWinVisible(bool fEnable)
+{
+ if (!g_CrPresenter.fWindowsForceHidden == !!fEnable)
+ return VINF_SUCCESS;
+
+ g_CrPresenter.fWindowsForceHidden = !fEnable;
+
+ for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+
+ if (pInfo->pDpWin)
+ pInfo->pDpWin->winVisibilityChanged();
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrRootVrUpdate()
+{
+ for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ uint32_t idScreen = CrFbGetScreenInfo(hFb)->u32ViewIndex;
+ CR_FBDISPLAY_INFO *pInfo = &g_CrPresenter.aDisplayInfos[idScreen];
+ int rc = CrFbUpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ pInfo->pDpWinRootVr->RegionsChanged(hFb);
+ CrFbUpdateEnd(hFb);
+ }
+ else
+ WARN(("CrFbUpdateBegin failed %d", rc));
+ }
+
+ return VINF_SUCCESS;
+}
+
+/*helper function that calls CrFbUpdateBegin for all enabled framebuffers */
+int CrPMgrHlpGlblUpdateBegin(CR_FBMAP *pMap)
+{
+ CrFBmInit(pMap);
+ for (HCR_FRAMEBUFFER hFb = CrPMgrFbGetFirstEnabled();
+ hFb;
+ hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ int rc = CrFbUpdateBegin(hFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("UpdateBegin failed, rc %d", rc));
+ for (HCR_FRAMEBUFFER hTmpFb = CrPMgrFbGetFirstEnabled();
+ hFb != hTmpFb;
+ hTmpFb = CrPMgrFbGetNextEnabled(hTmpFb))
+ {
+ CrFbUpdateEnd(hTmpFb);
+ CrFBmClear(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
+ }
+ return rc;
+ }
+
+ CrFBmSet(pMap, CrFbGetScreenInfo(hFb)->u32ViewIndex);
+ }
+
+ return VINF_SUCCESS;
+}
+
+/*helper function that calls CrFbUpdateEnd for all framebuffers being updated */
+void CrPMgrHlpGlblUpdateEnd(CR_FBMAP *pMap)
+{
+ for (uint32_t i = 0; i < (uint32_t)cr_server.screenCount; ++i)
+ {
+ if (!CrFBmIsSet(pMap, i))
+ continue;
+
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetInitialized(i);
+ CRASSERT(hFb);
+ CrFbUpdateEnd(hFb);
+ }
+}
+
+/*client should notify the manager about the framebuffer resize via this function */
+int CrPMgrNotifyResize(HCR_FRAMEBUFFER hFb)
+{
+ int rc = VINF_SUCCESS;
+ if (CrFbIsEnabled(hFb))
+ {
+ rc = CrPMgrModeModify(hFb, g_CrPresenter.u32DisplayMode, 0);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrPMgrModeModify failed rc %d", rc));
+ return rc;
+ }
+ }
+ else
+ {
+ rc = CrPMgrModeModify(hFb, 0, CR_PMGR_MODE_ALL);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrPMgrModeModify failed rc %d", rc));
+ return rc;
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrFbEntrySaveState(CR_FRAMEBUFFER *pFb, CR_FRAMEBUFFER_ENTRY *hEntry, PSSMHANDLE pSSM)
+{
+ const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+ int rc = SSMR3PutU32(pSSM, pFbTex->pTobj->id);
+ AssertRCReturn(rc, rc);
+ uint32_t u32 = 0;
+
+ u32 = CrVrScrCompositorEntryFlagsGet(pEntry);
+ rc = SSMR3PutU32(pSSM, u32);
+ AssertRCReturn(rc, rc);
+
+ const RTRECT *pRect = CrVrScrCompositorEntryRectGet(pEntry);
+
+ rc = SSMR3PutS32(pSSM, pRect->xLeft);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutS32(pSSM, pRect->yTop);
+ AssertRCReturn(rc, rc);
+#if 0
+ rc = SSMR3PutS32(pSSM, pRect->xRight);
+ AssertRCReturn(rc, rc);
+ rc = SSMR3PutS32(pSSM, pRect->yBottom);
+ AssertRCReturn(rc, rc);
+#endif
+
+ rc = CrVrScrCompositorEntryRegionsGet(&pFb->Compositor, pEntry, &u32, NULL, NULL, &pRect);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, u32);
+ AssertRCReturn(rc, rc);
+
+ if (u32)
+ {
+ rc = SSMR3PutMem(pSSM, pRect, u32 * sizeof (*pRect));
+ AssertRCReturn(rc, rc);
+ }
+ return rc;
+}
+
+int CrFbSaveState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM)
+{
+ VBOXVR_SCR_COMPOSITOR_CONST_ITERATOR Iter;
+ CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
+ const VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry;
+ uint32_t u32 = 0;
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ CRASSERT(pTexData);
+ CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+ if (pFbTex->pTobj)
+ ++u32;
+ }
+
+ int rc = SSMR3PutU32(pSSM, u32);
+ AssertRCReturn(rc, rc);
+
+ CrVrScrCompositorConstIterInit(&pFb->Compositor, &Iter);
+
+ while ((pEntry = CrVrScrCompositorConstIterNext(&Iter)) != NULL)
+ {
+ CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+ if (pFbTex->pTobj)
+ {
+ HCR_FRAMEBUFFER_ENTRY hEntry = CrFbEntryFromCompositorEntry(pEntry);
+ rc = CrFbEntrySaveState(pFb, hEntry, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrSaveState(PSSMHANDLE pSSM)
+{
+ int rc;
+ int cDisplays = 0, i;
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ if (CrPMgrFbGetEnabled(i))
+ ++cDisplays;
+ }
+
+ rc = SSMR3PutS32(pSSM, cDisplays);
+ AssertRCReturn(rc, rc);
+
+ if (!cDisplays)
+ return VINF_SUCCESS;
+
+ rc = SSMR3PutS32(pSSM, cr_server.screenCount);
+ AssertRCReturn(rc, rc);
+
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ CR_FRAMEBUFFER *hFb = CrPMgrFbGetEnabled(i);
+ if (hFb)
+ {
+ Assert(hFb->ScreenInfo.u32ViewIndex == i);
+ rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32ViewIndex);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginX);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutS32(pSSM, hFb->ScreenInfo.i32OriginY);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32StartOffset);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32LineSize);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Width);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, hFb->ScreenInfo.u32Height);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16BitsPerPixel);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU16(pSSM, hFb->ScreenInfo.u16Flags);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3PutU32(pSSM, (uint32_t)(((uintptr_t)hFb->pvVram) - ((uintptr_t)g_pvVRamBase)));
+ AssertRCReturn(rc, rc);
+
+ rc = CrFbSaveState(hFb, pSSM);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ return VINF_SUCCESS;
+}
+
+int CrFbEntryLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
+{
+ uint32_t texture;
+ int rc = SSMR3GetU32(pSSM, &texture);
+ AssertRCReturn(rc, rc);
+
+ uint32_t fFlags;
+ rc = SSMR3GetU32(pSSM, &fFlags);
+ AssertRCReturn(rc, rc);
+
+
+ HCR_FRAMEBUFFER_ENTRY hEntry;
+
+ rc = CrFbEntryCreateForTexId(pFb, texture, fFlags, &hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbEntryCreateForTexId Failed"));
+ return rc;
+ }
+
+ Assert(hEntry);
+
+ const struct VBOXVR_SCR_COMPOSITOR_ENTRY *pEntry = CrFbEntryGetCompositorEntry(hEntry);
+ CR_TEXDATA *pTexData = CrVrScrCompositorEntryTexGet(pEntry);
+ CR_FBTEX *pFbTex = PCR_FBTEX_FROM_TEX(pTexData);
+
+ RTPOINT Point;
+ rc = SSMR3GetS32(pSSM, &Point.x);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetS32(pSSM, &Point.y);
+ AssertRCReturn(rc, rc);
+
+ uint32_t cRects;
+ rc = SSMR3GetU32(pSSM, &cRects);
+ AssertRCReturn(rc, rc);
+
+ RTRECT * pRects = NULL;
+ if (cRects)
+ {
+ pRects = (RTRECT *)crAlloc(cRects * sizeof (*pRects));
+ AssertReturn(pRects, VERR_NO_MEMORY);
+
+ rc = SSMR3GetMem(pSSM, pRects, cRects * sizeof (*pRects));
+ AssertRCReturn(rc, rc);
+ }
+
+ rc = CrFbEntryRegionsSet(pFb, hEntry, &Point, cRects, pRects, false);
+ AssertRCReturn(rc, rc);
+
+ if (pRects)
+ crFree(pRects);
+
+ CrFbEntryRelease(pFb, hEntry);
+
+ return VINF_SUCCESS;
+}
+
+int CrFbLoadState(CR_FRAMEBUFFER *pFb, PSSMHANDLE pSSM, uint32_t version)
+{
+ uint32_t u32 = 0;
+ int rc = SSMR3GetU32(pSSM, &u32);
+ AssertRCReturn(rc, rc);
+
+ if (!u32)
+ return VINF_SUCCESS;
+
+ rc = CrFbUpdateBegin(pFb);
+ AssertRCReturn(rc, rc);
+
+ for (uint32_t i = 0; i < u32; ++i)
+ {
+ rc = CrFbEntryLoadState(pFb, pSSM, version);
+ AssertRCReturn(rc, rc);
+
+ }
+
+ CrFbUpdateEnd(pFb);
+
+ return VINF_SUCCESS;
+}
+
+int CrPMgrLoadState(PSSMHANDLE pSSM, uint32_t version)
+{
+ int rc;
+ int cDisplays, screenCount, i;
+
+ rc = SSMR3GetS32(pSSM, &cDisplays);
+ AssertRCReturn(rc, rc);
+
+ if (!cDisplays)
+ return VINF_SUCCESS;
+
+ rc = SSMR3GetS32(pSSM, &screenCount);
+ AssertRCReturn(rc, rc);
+
+ CRASSERT(screenCount == cr_server.screenCount);
+
+ CRScreenInfo screen[CR_MAX_GUEST_MONITORS];
+
+ if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
+ {
+ for (i = 0; i < cr_server.screenCount; ++i)
+ {
+ rc = SSMR3GetS32(pSSM, &screen[i].x);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetS32(pSSM, &screen[i].y);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &screen[i].w);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &screen[i].h);
+ AssertRCReturn(rc, rc);
+ }
+ }
+
+ for (i = 0; i < cDisplays; ++i)
+ {
+ int iScreen;
+
+ rc = SSMR3GetS32(pSSM, &iScreen);
+ AssertRCReturn(rc, rc);
+
+ CR_FRAMEBUFFER *pFb = CrPMgrFbGet(iScreen);
+ Assert(pFb);
+
+ rc = CrFbUpdateBegin(pFb);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbUpdateBegin failed %d", rc));
+ return rc;
+ }
+
+ VBVAINFOSCREEN Screen;
+ void *pvVRAM;
+
+ Screen.u32ViewIndex = iScreen;
+
+ if (version < SHCROGL_SSM_VERSION_WITH_FB_INFO)
+ {
+ memset(&Screen, 0, sizeof (Screen));
+ Screen.u32LineSize = 4 * screen[iScreen].w;
+ Screen.u32Width = screen[iScreen].w;
+ Screen.u32Height = screen[iScreen].h;
+ Screen.u16BitsPerPixel = 4;
+ Screen.u16Flags = VBVA_SCREEN_F_ACTIVE;
+
+ pvVRAM = g_pvVRamBase;
+ }
+ else
+ {
+ rc = SSMR3GetS32(pSSM, &Screen.i32OriginX);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetS32(pSSM, &Screen.i32OriginY);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &Screen.u32StartOffset);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &Screen.u32LineSize);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &Screen.u32Width);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU32(pSSM, &Screen.u32Height);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU16(pSSM, &Screen.u16BitsPerPixel);
+ AssertRCReturn(rc, rc);
+
+ rc = SSMR3GetU16(pSSM, &Screen.u16Flags);
+ AssertRCReturn(rc, rc);
+
+ uint32_t offVram = 0;
+ rc = SSMR3GetU32(pSSM, &offVram);
+ AssertRCReturn(rc, rc);
+
+ pvVRAM = (void*)(((uintptr_t)g_pvVRamBase) + offVram);
+ }
+
+ crVBoxServerMuralFbResizeBegin(pFb);
+
+ rc = CrFbResize(pFb, &Screen, pvVRAM);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbResize failed %d", rc));
+ return rc;
+ }
+
+ rc = CrFbLoadState(pFb, pSSM, version);
+ AssertRCReturn(rc, rc);
+
+ crVBoxServerMuralFbResizeEnd(pFb);
+
+ CrFbUpdateEnd(pFb);
+
+ CrPMgrNotifyResize(pFb);
+ }
+
+ return VINF_SUCCESS;
+}
+
+
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchVBoxTexPresent(GLuint texture, GLuint cfg, GLint xPos, GLint yPos, GLint cRects, const GLint *pRects)
+{
+ uint32_t idScreen = CR_PRESENT_GET_SCREEN(cfg);
+ if (idScreen >= CR_MAX_GUEST_MONITORS)
+ {
+ WARN(("Invalid guest screen"));
+ return;
+ }
+
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(idScreen);
+ if (!hFb)
+ {
+ WARN(("request to present on disabled framebuffer, ignore"));
+ return;
+ }
+
+ HCR_FRAMEBUFFER_ENTRY hEntry;
+ int rc;
+ if (texture)
+ {
+ rc = CrFbEntryCreateForTexId(hFb, texture, (cfg & CR_PRESENT_FLAG_TEX_NONINVERT_YCOORD) ? 0 : CRBLT_F_INVERT_SRC_YCOORDS, &hEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ LOG(("CrFbEntryCreateForTexId Failed"));
+ return;
+ }
+
+ Assert(hEntry);
+
+#if 0
+ if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
+ {
+ CR_SERVER_DUMP_TEXPRESENT(&pEntry->CEntry.Tex);
+ }
+#endif
+ }
+ else
+ hEntry = NULL;
+
+ rc = CrFbUpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ if (!(cfg & CR_PRESENT_FLAG_CLEAR_RECTS))
+ {
+ RTPOINT Point = {xPos, yPos};
+ rc = CrFbEntryRegionsAdd(hFb, hEntry, &Point, (uint32_t)cRects, (const RTRECT*)pRects, false);
+ }
+ else
+ {
+ CrFbRegionsClear(hFb);
+ }
+
+ CrFbUpdateEnd(hFb);
+ }
+ else
+ {
+ WARN(("CrFbUpdateBegin Failed"));
+ }
+
+ if (hEntry)
+ CrFbEntryRelease(hFb, hEntry);
+}
+
+DECLINLINE(void) crVBoxPRectUnpack(const VBOXCMDVBVA_RECT *pVbvaRect, RTRECT *pRect)
+{
+ pRect->xLeft = pVbvaRect->xLeft;
+ pRect->yTop = pVbvaRect->yTop;
+ pRect->xRight = pVbvaRect->xRight;
+ pRect->yBottom = pVbvaRect->yBottom;
+}
+
+DECLINLINE(void) crVBoxPRectUnpacks(const VBOXCMDVBVA_RECT *paVbvaRects, RTRECT *paRects, uint32_t cRects)
+{
+ uint32_t i = 0;
+ for (; i < cRects; ++i)
+ {
+ crVBoxPRectUnpack(&paVbvaRects[i], &paRects[i]);
+ }
+}
+
+int32_t crVBoxServerCrCmdBltProcess(PVBOXCMDVBVA_HDR pCmd, uint32_t cbCmd)
+{
+ uint8_t u8Flags = pCmd->u8Flags;
+ if (u8Flags & (VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY | VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
+ {
+ VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pCmd;
+ uint8_t u8PrimaryID = pBlt->Hdr.u.u8PrimaryID;
+ HCR_FRAMEBUFFER hFb = CrPMgrFbGetEnabled(u8PrimaryID);
+ if (!hFb)
+ {
+ WARN(("request to present on disabled framebuffer, ignore"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+
+ const VBOXCMDVBVA_RECT *pPRects = pBlt->aRects;
+ uint32_t cRects = (cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) / sizeof (VBOXCMDVBVA_RECT);
+ RTRECT *pRects;
+ if (g_CrPresenter.cbTmpBuf < cRects * sizeof (RTRECT))
+ {
+ if (g_CrPresenter.pvTmpBuf)
+ RTMemFree(g_CrPresenter.pvTmpBuf);
+
+ g_CrPresenter.cbTmpBuf = (cRects + 10) * sizeof (RTRECT);
+ g_CrPresenter.pvTmpBuf = RTMemAlloc(g_CrPresenter.cbTmpBuf);
+ if (!g_CrPresenter.pvTmpBuf)
+ {
+ WARN(("RTMemAlloc failed!"));
+ g_CrPresenter.cbTmpBuf = 0;
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+ }
+
+ pRects = (RTRECT *)g_CrPresenter.pvTmpBuf;
+
+ crVBoxPRectUnpacks(pPRects, pRects, cRects);
+
+ Assert(!((cbCmd - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects)) % sizeof (VBOXCMDVBVA_RECT)));
+
+ if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY)
+ {
+ if (!(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY))
+ {
+ /* blit to primary from non-primary */
+ uint32_t texId;
+ if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
+ {
+ /* TexPresent */
+ texId = pBlt->alloc.u.id;
+ }
+ else
+ {
+ VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.u.offVRAM;
+ const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+ uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height;
+ if (offVRAM >= g_cbVRam
+ || offVRAM + cbScreen >= g_cbVRam)
+ {
+ WARN(("invalid param"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+
+ uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
+ texId = 0;
+// cr_server.CrCmdClientInfo.pfnCltScrUpdateBegin(cr_server.CrCmdClientInfo.hCltScr);
+ /*todo: notify VGA device to perform updates */
+ }
+
+ crServerDispatchVBoxTexPresent(texId, u8PrimaryID, pBlt->Pos.x, pBlt->Pos.y, cRects, (const GLint*)pRects);
+ }
+ else
+ {
+ /* blit from one primary to another primary, wow */
+ WARN(("not implemented"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ {
+ Assert(u8Flags & VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY);
+ /* blit from primary to non-primary */
+ if (u8Flags & VBOXCMDVBVA_OPF_ALLOC_DSTID)
+ {
+ uint32_t texId = pBlt->alloc.u.id;
+ WARN(("not implemented"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ VBOXCMDVBVAOFFSET offVRAM = pBlt->alloc.u.offVRAM;
+ const VBVAINFOSCREEN *pScreen = CrFbGetScreenInfo(hFb);
+ uint32_t cbScreen = pScreen->u32LineSize * pScreen->u32Height;
+ if (offVRAM >= g_cbVRam
+ || offVRAM + cbScreen >= g_cbVRam)
+ {
+ WARN(("invalid param"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+
+ uint8_t *pu8Buf = g_pvVRamBase + offVRAM;
+
+ RTRECT SrcRect;
+ SrcRect.xLeft = 0;
+ SrcRect.yTop = 0;
+ SrcRect.xRight = pScreen->u32Width;
+ SrcRect.yBottom = pScreen->u32Height;
+ RTRECT DstRect;
+ DstRect.xLeft = pBlt->Pos.x;
+ DstRect.yTop = pBlt->Pos.y;
+ DstRect.xRight = DstRect.xLeft + pScreen->u32Width;
+ DstRect.yBottom = DstRect.yTop + pScreen->u32Height;
+ CR_BLITTER_IMG Img;
+ crFbImgFromScreenVram(pScreen, pu8Buf, &Img);
+ int rc = CrFbBltGetContents(hFb, &SrcRect, &DstRect, cRects, pRects, &Img);
+ if (!RT_SUCCESS(rc))
+ {
+ WARN(("CrFbBltGetContents failed %d", rc));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+ }
+ }
+ }
+ else
+ {
+ WARN(("not implemented"));
+ pCmd->u.i8Result = -1;
+ return VINF_SUCCESS;
+ }
+
+ pCmd->u.i8Result = 0;
+ return VINF_SUCCESS;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py
index 69d09b60..11f2e77f 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_retval.py
@@ -35,7 +35,7 @@ void crServerReturnValue( const void *payload, unsigned int payload_len )
rb = (CRMessageReadback *) crAlloc( msg_len );
rb->header.type = CR_MESSAGE_READBACK;
- CRDBGPTR_PRINTWB(cr_server.curClient->conn->u32ClientID, &cr_server.writeback_ptr);
+ CRDBGPTR_PRINTRB(cr_server.curClient->conn->u32ClientID, &cr_server.writeback_ptr);
CRDBGPTR_CHECKNZ(&cr_server.writeback_ptr);
CRDBGPTR_CHECKNZ(&cr_server.return_ptr);
crMemcpy( &(rb->writeback_ptr), &(cr_server.writeback_ptr), sizeof( rb->writeback_ptr ) );
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp
new file mode 100644
index 00000000..51c5d46f
--- /dev/null
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_rpw.cpp
@@ -0,0 +1,755 @@
+/* $Id: server_rpw.cpp $ */
+
+/** @file
+ * VBox crOpenGL: Read Pixels worker
+ */
+
+/*
+ * Copyright (C) 2010-2013 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+#include "server.h"
+#include "cr_string.h"
+#include "cr_mem.h"
+#include "cr_vreg.h"
+#include "render/renderspu.h"
+
+static void crServerRpwWorkerGpuSubmit(PRTLISTNODE pWorkList)
+{
+ CR_SERVER_RPW_ENTRY *pCurEntry;
+ RTListForEach(pWorkList, pCurEntry, CR_SERVER_RPW_ENTRY, WorkerWorkEntry)
+ {
+ cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, CR_SERVER_RPW_ENTRY_TEX(pCurEntry, Worker));
+
+ if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry))
+ {
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, CR_SERVER_RPW_ENTRY_PBO_CUR(pCurEntry));
+ /*read the texture, note pixels are NULL for PBO case as it's offset in the buffer*/
+ cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ CR_SERVER_RPW_ENTRY_PBO_FLIP(pCurEntry);
+ }
+ else
+ {
+ void *pvData = crAlloc(4*pCurEntry->Size.cx*pCurEntry->Size.cy);
+ if (pvData)
+ {
+ cr_server.head_spu->dispatch_table.GetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_BYTE, pvData);
+
+ pCurEntry->pfnData(pCurEntry, pvData);
+
+ crFree(pvData);
+ }
+ else
+ {
+ crWarning("crAlloc failed");
+ }
+ }
+
+ cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, 0);
+ }
+}
+
+static void crServerRpwWorkerGpuComplete(PRTLISTNODE pGpuSubmitedList)
+{
+ CR_SERVER_RPW_ENTRY *pCurEntry;
+ RTListForEach(pGpuSubmitedList, pCurEntry, CR_SERVER_RPW_ENTRY, GpuSubmittedEntry)
+ {
+ Assert(CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry));
+
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, CR_SERVER_RPW_ENTRY_PBO_COMPLETED(pCurEntry));
+
+ void *pvData = cr_server.head_spu->dispatch_table.MapBufferARB(GL_PIXEL_PACK_BUFFER_ARB, GL_READ_ONLY);
+
+ pCurEntry->pfnData(pCurEntry, pvData);
+
+ cr_server.head_spu->dispatch_table.UnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
+
+ cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, pCurEntry->Size.cx*pCurEntry->Size.cy*4, 0, GL_STREAM_READ_ARB);
+
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+}
+
+static void crServerRpwWorkerGpuMarkGpuCompletedSubmitedLocked(PRTLISTNODE pGpuSubmitedList, PRTLISTNODE pWorkList)
+{
+ CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
+ RTListForEachSafe(pGpuSubmitedList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, GpuSubmittedEntry)
+ {
+ CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pCurEntry, Gpu);
+ RTListNodeRemove(&pCurEntry->GpuSubmittedEntry);
+ }
+
+ Assert(RTListIsEmpty(pGpuSubmitedList));
+
+ RTListForEachSafe(pWorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkerWorkEntry)
+ {
+ Assert(CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Worker));
+ RTListNodeRemove(&pCurEntry->WorkerWorkEntry);
+ if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pCurEntry))
+ {
+ /* PBO mode, put to the GPU submitted queue*/
+ RTListAppend(pGpuSubmitedList, &pCurEntry->GpuSubmittedEntry);
+ CR_SERVER_RPW_ENTRY_TEX_PROMOTE(pCurEntry, Worker, Gpu);
+ }
+ else
+ {
+ /* no PBO, we are already done entry data processing, free it right away */
+ Assert(!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Gpu));
+ CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pCurEntry, Worker);
+ }
+ }
+}
+
+static void crServerRpwWorkerGetWorkLocked(CR_SERVER_RPW *pWorker, PRTLISTNODE pWorkList)
+{
+ CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
+ RTListForEachSafe(&pWorker->WorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkEntry)
+ {
+ RTListNodeRemove(&pCurEntry->WorkEntry);
+ RTListAppend(pWorkList, &pCurEntry->WorkerWorkEntry);
+ CR_SERVER_RPW_ENTRY_TEX_PROMOTE(pCurEntry, Submitted, Worker);
+ }
+}
+
+static DECLCALLBACK(int) crServerRpwWorkerThread(RTTHREAD ThreadSelf, void *pvUser)
+{
+ CR_SERVER_RPW *pWorker = (CR_SERVER_RPW *)pvUser;
+ RTMSINTERVAL cWaitMillis = RT_INDEFINITE_WAIT;
+ RTLISTNODE WorkList, GpuSubmittedList;
+ CR_SERVER_RPW_CTL_TYPE enmCtlType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
+ CR_SERVER_RPW_ENTRY *pCtlEntry = NULL;
+ CRMuralInfo *pDummyMural = crServerGetDummyMural(pWorker->ctxVisBits);
+ bool fExit = false;
+ bool fForceComplete = false;
+ bool fNotifyCmdCompleted = false;
+
+ CRASSERT(pDummyMural);
+
+ int rc = RTSemEventSignal(pWorker->Ctl.hCompleteEvent);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTSemEventSignal failed rc %d", rc);
+ return rc;
+ }
+
+ RTListInit(&WorkList);
+ RTListInit(&GpuSubmittedList);
+
+ cr_server.head_spu->dispatch_table.MakeCurrent(pDummyMural->spuWindow, 0, pWorker->ctxId);
+
+ rc = RTCritSectEnter(&pWorker->CritSect);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTCritSectEnter failed, rc %d", rc);
+ goto end;
+ }
+
+ for (;;)
+ {
+ /* the crit sect is locked here */
+
+ if (pWorker->Ctl.enmType != CR_SERVER_RPW_CTL_TYPE_UNDEFINED)
+ {
+ enmCtlType = pWorker->Ctl.enmType;
+ pCtlEntry = pWorker->Ctl.pEntry;
+ pWorker->Ctl.enmType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
+ pWorker->Ctl.pEntry = NULL;
+ }
+
+ crServerRpwWorkerGetWorkLocked(pWorker, &WorkList);
+
+ RTCritSectLeave(&pWorker->CritSect);
+
+ if (enmCtlType != CR_SERVER_RPW_CTL_TYPE_UNDEFINED)
+ {
+ switch (enmCtlType)
+ {
+ case CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE:
+ break;
+ case CR_SERVER_RPW_CTL_TYPE_TERM:
+ fExit = true;
+ break;
+ default:
+ crWarning("unexpected CtlType %d", enmCtlType);
+ break;
+ }
+ enmCtlType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
+ pCtlEntry = NULL;
+ fNotifyCmdCompleted = true;
+ }
+
+ bool fNewItems = !RTListIsEmpty(&WorkList);
+ bool fCompleted = false;
+
+ if (fNewItems)
+ {
+ crServerRpwWorkerGpuSubmit(&WorkList);
+ }
+
+ if (!RTListIsEmpty(&GpuSubmittedList))
+ {
+ if (fForceComplete || fNewItems)
+ {
+ crServerRpwWorkerGpuComplete(&GpuSubmittedList);
+ fForceComplete = false;
+ fCompleted = true;
+ }
+ }
+
+ rc = RTCritSectEnter(&pWorker->CritSect);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTCritSectEnter failed, rc %d", rc);
+ break;
+ }
+
+ /* fNewGpuItems means new entries arrived. WorkList contains new GPU submitted data
+ * fCompleted means completion was performed, GpuSubmittedList contains old GPU submitted data,
+ * which is now completed and should be released */
+ if (fNewItems || fCompleted)
+ {
+ crServerRpwWorkerGpuMarkGpuCompletedSubmitedLocked(&GpuSubmittedList, &WorkList);
+ }
+
+ if (fExit || !fNewItems)
+ {
+ RTCritSectLeave(&pWorker->CritSect);
+
+ if (fNotifyCmdCompleted)
+ {
+ rc = RTSemEventSignal(pWorker->Ctl.hCompleteEvent);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTSemEventSignal failed rc %d", rc);
+ break;
+ }
+ fNotifyCmdCompleted = false;
+ }
+
+ if (fExit)
+ break;
+
+ if (!RTListIsEmpty(&GpuSubmittedList))
+ cWaitMillis = 17; /* ~60Hz */
+ else
+ cWaitMillis = RT_INDEFINITE_WAIT;
+
+ rc = RTSemEventWait(pWorker->hSubmitEvent, cWaitMillis);
+ if (!RT_SUCCESS(rc) && rc != VERR_TIMEOUT)
+ {
+ crWarning("RTSemEventWait failed, rc %d", rc);
+ break;
+ }
+
+ if (rc == VERR_TIMEOUT)
+ {
+ Assert(!RTListIsEmpty(&GpuSubmittedList));
+ fForceComplete = true;
+ }
+
+ rc = RTCritSectEnter(&pWorker->CritSect);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTCritSectEnter failed, rc %d", rc);
+ break;
+ }
+ }
+ }
+
+end:
+ cr_server.head_spu->dispatch_table.MakeCurrent(0, 0, 0);
+
+ return rc;
+}
+
+static int crServerRpwCtlNotify(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ int rc = RTSemEventSignal(pWorker->hSubmitEvent);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventWait(pWorker->Ctl.hCompleteEvent, RT_INDEFINITE_WAIT);
+ if (RT_SUCCESS(rc))
+ {
+ rc = pWorker->Ctl.rc;
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("WdCtl command failed rc %d", rc);
+ }
+ }
+ else
+ {
+ crWarning("RTSemEventWait failed rc %d", rc);
+ }
+ }
+ else
+ {
+ int tmpRc;
+ crWarning("RTSemEventSignal failed rc %d", rc);
+ tmpRc = RTCritSectEnter(&pWorker->CritSect);
+ if (RT_SUCCESS(tmpRc))
+ {
+ pWorker->Ctl.enmType = CR_SERVER_RPW_CTL_TYPE_UNDEFINED;
+ pWorker->Ctl.pEntry = NULL;
+ RTCritSectLeave(&pWorker->CritSect);
+ }
+ else
+ {
+ crWarning("RTSemEventSignal failed tmpRc %d", tmpRc);
+ }
+ }
+
+ return rc;
+}
+
+static int crServerRpwCtl(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_CTL_TYPE enmType, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ int rc = RTCritSectEnter(&pWorker->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ pWorker->Ctl.enmType = enmType;
+ pWorker->Ctl.pEntry = pEntry;
+ RTCritSectLeave(&pWorker->CritSect);
+ }
+ else
+ {
+ crWarning("RTCritSectEnter failed rc %d", rc);
+ return rc;
+ }
+
+ rc = crServerRpwCtlNotify(pWorker, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwCtlNotify failed rc %d", rc);
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+
+int crServerRpwInit(CR_SERVER_RPW *pWorker)
+{
+ int rc;
+
+ memset(pWorker, 0, sizeof (*pWorker));
+
+ RTListInit(&pWorker->WorkList);
+
+ rc = RTCritSectInit(&pWorker->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventCreate(&pWorker->hSubmitEvent);
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventCreate(&pWorker->Ctl.hCompleteEvent);
+ if (RT_SUCCESS(rc))
+ {
+ CRASSERT(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ CRASSERT(cr_server.MainContextInfo.SpuContext);
+
+ pWorker->ctxId = cr_server.head_spu->dispatch_table.CreateContext("", cr_server.MainContextInfo.CreateInfo.realVisualBits, cr_server.MainContextInfo.SpuContext);
+ if (pWorker->ctxId)
+ {
+ CRMuralInfo *pDummyMural;
+ pWorker->ctxVisBits = cr_server.MainContextInfo.CreateInfo.realVisualBits;
+ pDummyMural = crServerGetDummyMural(pWorker->ctxVisBits);
+ if (pDummyMural)
+ {
+ /* since CreateContext does not actually create it on some platforms, e.g. on win,
+ * we need to do MakeCurrent to ensure it is created.
+ * There is some black magic in doing that to work around ogl driver bugs
+ * (i.e. we need to switch offscreen rendering off before doing make current) */
+ CR_SERVER_CTX_SWITCH CtxSwitch;
+
+ crServerCtxSwitchPrepare(&CtxSwitch, NULL);
+
+ cr_server.head_spu->dispatch_table.Flush();
+
+ cr_server.head_spu->dispatch_table.MakeCurrent(pDummyMural->spuWindow, 0, pWorker->ctxId);
+
+ if (cr_server.currentCtxInfo)
+ {
+ CRASSERT(cr_server.currentMural);
+ cr_server.head_spu->dispatch_table.MakeCurrent(cr_server.currentMural->spuWindow, 0,
+ cr_server.currentCtxInfo->SpuContext > 0 ? cr_server.currentCtxInfo->SpuContext : cr_server.MainContextInfo.SpuContext);
+ }
+ else
+ cr_server.head_spu->dispatch_table.MakeCurrent(CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID);
+
+ crServerCtxSwitchPostprocess(&CtxSwitch);
+
+ rc = RTThreadCreate(&pWorker->hThread, crServerRpwWorkerThread, pWorker, 0, RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "CrServerDw");
+ if (RT_SUCCESS(rc))
+ {
+ rc = RTSemEventWait(pWorker->Ctl.hCompleteEvent, RT_INDEFINITE_WAIT);
+ if (RT_SUCCESS(rc))
+ {
+ return VINF_SUCCESS;
+ }
+ else
+ {
+ crWarning("RTSemEventWait failed rc %d", rc);
+ }
+ }
+ else
+ {
+ crWarning("RTThreadCreate failed rc %d", rc);
+ }
+ }
+ else
+ {
+ crWarning("Failed to get dummy mural");
+ rc = VERR_GENERAL_FAILURE;
+ }
+ cr_server.head_spu->dispatch_table.DestroyContext(pWorker->ctxId);
+ }
+ else
+ {
+ crWarning("CreateContext failed rc %d", rc);
+ }
+
+ RTSemEventDestroy(pWorker->Ctl.hCompleteEvent);
+ }
+ else
+ {
+ crWarning("RTSemEventCreate failed rc %d", rc);
+ }
+ RTSemEventDestroy(pWorker->hSubmitEvent);
+ }
+ else
+ {
+ crWarning("RTSemEventCreate failed rc %d", rc);
+ }
+
+ RTCritSectDelete(&pWorker->CritSect);
+ }
+ else
+ {
+ crWarning("RTCritSectInit failed rc %d", rc);
+ }
+
+ return rc;
+}
+
+int crServerRpwEntryResizeCleaned(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height)
+{
+ CRContext *pContext;
+ if (!width || !height)
+ {
+ return VINF_SUCCESS;
+ }
+
+ if (!cr_server.currentCtxInfo)
+ {
+ CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ if (!pDummy)
+ {
+ crWarning("crServerGetDummyMural failed");
+ return VERR_GENERAL_FAILURE;
+ }
+
+
+ crServerPerformMakeCurrent(pDummy, &cr_server.MainContextInfo);
+ }
+
+ Assert(width);
+ Assert(height);
+
+ pContext = cr_server.currentCtxInfo->pContext;
+
+ if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ }
+
+ for (int i = 0; i < 4; ++i)
+ {
+ cr_server.head_spu->dispatch_table.GenTextures(1, &pEntry->aidWorkerTexs[i]);
+
+ cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, pEntry->aidWorkerTexs[i]);
+ cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ cr_server.head_spu->dispatch_table.TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ cr_server.head_spu->dispatch_table.TexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height,
+ 0, GL_BGRA, GL_UNSIGNED_BYTE, NULL);
+ }
+
+ pEntry->iTexDraw = -pEntry->iTexDraw;
+
+ if (crStateIsBufferBound(GL_PIXEL_UNPACK_BUFFER_ARB))
+ {
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pContext->bufferobject.unpackBuffer->hwid);
+ }
+
+ if (cr_server.bUsePBOForReadback)
+ {
+ for (int i = 0; i < 2; ++i)
+ {
+ cr_server.head_spu->dispatch_table.GenBuffersARB(1, &pEntry->aidPBOs[i]);
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pEntry->aidPBOs[i]);
+ cr_server.head_spu->dispatch_table.BufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, width*height*4, 0, GL_STREAM_READ_ARB);
+ }
+
+ if (crStateIsBufferBound(GL_PIXEL_PACK_BUFFER_ARB))
+ {
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, pContext->bufferobject.packBuffer->hwid);
+ }
+ else
+ {
+ cr_server.head_spu->dispatch_table.BindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
+ }
+ pEntry->iCurPBO = 0;
+ }
+
+
+ GLuint uid = pContext->texture.unit[pContext->texture.curTextureUnit].currentTexture2D->hwid;
+ cr_server.head_spu->dispatch_table.BindTexture(GL_TEXTURE_2D, uid);
+
+
+ pEntry->Size.cx = width;
+ pEntry->Size.cy = height;
+
+ crServerRpwEntryDbgVerify(pEntry);
+
+ return VINF_SUCCESS;
+}
+
+int crServerRpwEntryCleanup(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ if (!pEntry->Size.cx)
+ return VINF_SUCCESS;
+
+ int rc = crServerRpwEntryCancel(pWorker, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwEntryCancel failed rc %d", rc);
+ return rc;
+ }
+
+ if (!cr_server.currentCtxInfo)
+ {
+ CRMuralInfo *pDummy = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ if (!pDummy)
+ {
+ crWarning("crServerGetDummyMural failed");
+ return VERR_GENERAL_FAILURE;
+ }
+
+
+ crServerPerformMakeCurrent(pDummy, &cr_server.MainContextInfo);
+ }
+
+ cr_server.head_spu->dispatch_table.DeleteTextures(4, pEntry->aidWorkerTexs);
+
+ if (CR_SERVER_RPW_ENTRY_PBO_IS_ACTIVE(pEntry))
+ {
+ cr_server.head_spu->dispatch_table.DeleteBuffersARB(2, pEntry->aidPBOs);
+ memset(pEntry->aidPBOs, 0, sizeof (pEntry->aidPBOs));
+ pEntry->iCurPBO = -1;
+ }
+
+ memset(pEntry->aidWorkerTexs, 0, sizeof (pEntry->aidWorkerTexs));
+ CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted);
+ CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Worker);
+ CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Gpu);
+ pEntry->iTexDraw = -1;
+ pEntry->iTexSubmitted = -2;
+ pEntry->iTexWorker = -3;
+ pEntry->iTexGpu = -4;
+ pEntry->Size.cx = 0;
+ pEntry->Size.cy = 0;
+ return VINF_SUCCESS;
+}
+
+int crServerRpwEntryResize(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height)
+{
+ if (!width || !height)
+ {
+ width = 0;
+ height = 0;
+ }
+
+ if (width == pEntry->Size.cx && width == pEntry->Size.cy)
+ return VINF_SUCCESS;
+
+ int rc = crServerRpwEntryCleanup(pWorker, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwEntryCleanup failed rc %d", rc);
+ return rc;
+ }
+
+ rc = crServerRpwEntryResizeCleaned(pWorker, pEntry, width, height);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwEntryResizeCleaned failed rc %d", rc);
+ }
+ return rc;
+}
+
+int crServerRpwEntryInit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, uint32_t width, uint32_t height, PFNCR_SERVER_RPW_DATA pfnData)
+{
+ memset(pEntry, 0, sizeof (*pEntry));
+
+ pEntry->iTexDraw = -1;
+ pEntry->iTexSubmitted = -2;
+ pEntry->iTexWorker = -3;
+ pEntry->iTexGpu = -4;
+ pEntry->iCurPBO = -1;
+ pEntry->pfnData = pfnData;
+ int rc = crServerRpwEntryResizeCleaned(pWorker, pEntry, width, height);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwEntryResizeCleaned failed rc %d", rc);
+ return rc;
+ }
+ return VINF_SUCCESS;
+}
+
+int crServerRpwEntrySubmit(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Draw))
+ {
+ crWarning("submitting empty entry, ignoting");
+ Assert(!pEntry->Size.cx);
+ Assert(!pEntry->Size.cy);
+ return VERR_INVALID_PARAMETER;
+ }
+
+ Assert(pEntry->Size.cx);
+ Assert(pEntry->Size.cy);
+
+ int rc = RTCritSectEnter(&pWorker->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ Assert(pWorker->Ctl.enmType == CR_SERVER_RPW_CTL_TYPE_UNDEFINED);
+ if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted))
+ {
+ CR_SERVER_RPW_ENTRY_TEX_PROMOTE_KEEPVALID(pEntry, Draw, Submitted);
+ RTListAppend(&pWorker->WorkList, &pEntry->WorkEntry);
+ }
+ else
+ {
+ CR_SERVER_RPW_ENTRY_TEX_XCHG_VALID(pEntry, Draw, Submitted);
+ }
+ RTCritSectLeave(&pWorker->CritSect);
+
+ RTSemEventSignal(pWorker->hSubmitEvent);
+ }
+ else
+ {
+ crWarning("RTCritSectEnter failed rc %d", rc);
+ return rc;
+ }
+
+ return rc;
+}
+
+static int crServerRpwEntryCancelCtl(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry, CR_SERVER_RPW_CTL_TYPE enmType)
+{
+ if (CR_SERVER_RPW_CTL_TYPE_TERM == enmType && pEntry)
+ {
+ crWarning("Entry should be null for term request");
+ pEntry = NULL;
+ }
+
+ int rc = RTCritSectEnter(&pWorker->CritSect);
+ if (RT_SUCCESS(rc))
+ {
+ if (pEntry)
+ {
+ if (CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Submitted))
+ {
+ CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pEntry, Submitted);
+ RTListNodeRemove(&pEntry->WorkEntry);
+ }
+
+ if (!CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Worker) && !CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pEntry, Gpu))
+ {
+ /* can cancel it wight away */
+ RTCritSectLeave(&pWorker->CritSect);
+ return VINF_SUCCESS;
+ }
+ }
+ else
+ {
+ CR_SERVER_RPW_ENTRY *pCurEntry, *pNextEntry;
+ RTListForEachSafe(&pWorker->WorkList, pCurEntry, pNextEntry, CR_SERVER_RPW_ENTRY, WorkEntry)
+ {
+ CR_SERVER_RPW_ENTRY_TEX_IS_VALID(pCurEntry, Submitted);
+ CR_SERVER_RPW_ENTRY_TEX_INVALIDATE(pEntry, Submitted);
+ RTListNodeRemove(&pCurEntry->WorkEntry);
+ }
+ }
+ pWorker->Ctl.enmType = enmType;
+ pWorker->Ctl.pEntry = pEntry;
+ RTCritSectLeave(&pWorker->CritSect);
+ }
+ else
+ {
+ crWarning("RTCritSectEnter failed rc %d", rc);
+ return rc;
+ }
+
+ rc = crServerRpwCtlNotify(pWorker, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwCtlNotify failed rc %d", rc);
+ }
+ return VINF_SUCCESS;
+}
+
+int crServerRpwEntryWaitComplete(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ int rc = crServerRpwCtl(pWorker, CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE, pEntry);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwCtl failed rc %d", rc);
+ }
+ return rc;
+}
+
+int crServerRpwEntryCancel(CR_SERVER_RPW *pWorker, CR_SERVER_RPW_ENTRY *pEntry)
+{
+ return crServerRpwEntryCancelCtl(pWorker, pEntry, CR_SERVER_RPW_CTL_TYPE_WAIT_COMPLETE);
+}
+
+static int crServerRpwCtlTerm(CR_SERVER_RPW *pWorker)
+{
+ int rc = crServerRpwEntryCancelCtl(pWorker, NULL, CR_SERVER_RPW_CTL_TYPE_TERM);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwCtl failed rc %d", rc);
+ }
+ return rc;
+}
+
+int crServerRpwTerm(CR_SERVER_RPW *pWorker)
+{
+ int rc = crServerRpwCtlTerm(pWorker);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("crServerRpwCtlTerm failed rc %d", rc);
+ return rc;
+ }
+
+ rc = RTThreadWait(pWorker->hThread, RT_INDEFINITE_WAIT, NULL);
+ if (!RT_SUCCESS(rc))
+ {
+ crWarning("RTThreadWait failed rc %d", rc);
+ return rc;
+ }
+
+ RTSemEventDestroy(pWorker->Ctl.hCompleteEvent);
+ RTSemEventDestroy(pWorker->hSubmitEvent);
+ RTCritSectDelete(&pWorker->CritSect);
+
+ return VINF_SUCCESS;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
index 363ccb43..1698841f 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_simpleget.py
@@ -74,31 +74,37 @@ for index in range(len(funcs)):
{
GLuint fboid;
CRASSERT(tablesize/sizeof(%s)==1);
- fboid = crStateFBOHWIDtoID((GLuint) *get_values);
- if (cr_server.curClient->currentMural->bUseFBO
- && crServerIsRedirectedToFBO()
- && fboid==cr_server.curClient->currentMural->idFBO)
+ fboid = (GLuint) *get_values;
+ if (crServerIsRedirectedToFBO()
+ && (fboid==cr_server.curClient->currentMural->aidFBOs[0]
+ || fboid==cr_server.curClient->currentMural->aidFBOs[1]))
{
fboid = 0;
}
+ else
+ {
+ fboid = crStateFBOHWIDtoID(fboid);
+ }
*get_values = (%s) fboid;
}
else if (GL_READ_BUFFER==pname)
{
- if (cr_server.curClient->currentMural->bUseFBO && crServerIsRedirectedToFBO()
- && cr_server.curClient->currentMural->idFBO
+ if (crServerIsRedirectedToFBO()
+ && CR_SERVER_FBO_FOR_IDX(cr_server.curClient->currentMural, cr_server.curClient->currentMural->iCurReadBuffer)
&& !crStateGetCurrent()->framebufferobject.readFB)
{
*get_values = (%s) crStateGetCurrent()->buffer.readBuffer;
+ Assert(crStateGetCurrent()->buffer.readBuffer == GL_BACK || crStateGetCurrent()->buffer.readBuffer == GL_FRONT);
}
}
else if (GL_DRAW_BUFFER==pname)
{
- if (cr_server.curClient->currentMural->bUseFBO && crServerIsRedirectedToFBO()
- && cr_server.curClient->currentMural->idFBO
+ if (crServerIsRedirectedToFBO()
+ && CR_SERVER_FBO_FOR_IDX(cr_server.curClient->currentMural, cr_server.curClient->currentMural->iCurDrawBuffer)
&& !crStateGetCurrent()->framebufferobject.drawFB)
{
*get_values = (%s) crStateGetCurrent()->buffer.drawBuffer;
+ Assert(crStateGetCurrent()->buffer.drawBuffer == GL_BACK || crStateGetCurrent()->buffer.drawBuffer == GL_FRONT);
}
}
else if (GL_RENDERBUFFER_BINDING_EXT==pname)
@@ -132,7 +138,14 @@ for index in range(len(funcs)):
*get_values = (%s)CR_MAX_TEXTURE_UNITS;
}
}
- """ % (types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index])
+ else if (GL_MAX_VERTEX_ATTRIBS_ARB==pname)
+ {
+ if (CR_MAX_VERTEX_ATTRIBS < (GLuint)*get_values)
+ {
+ *get_values = (%s)CR_MAX_VERTEX_ATTRIBS;
+ }
+ }
+ """ % (types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index], types[index])
print '\tcrServerReturnValue( get_values, tablesize );'
print '\tcrFree(get_values);'
print '}\n'
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
index 7292626a..e2df4e91 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_special
@@ -160,6 +160,7 @@ ProgramParameter4fNV
ProgramParameter4dNV
GetCompressedTexImageARB
GenBuffersARB
+DeleteBuffersARB
GetBufferSubDataARB
GetBufferPointervARB
MapBufferARB
@@ -248,3 +249,17 @@ BlitFramebufferEXT
EndList
DrawBuffer
ReadBuffer
+VBoxTexPresent
+GetError
+GetProgramiv
+GetShaderiv
+Begin
+DrawArrays
+DrawElements
+End
+TexEnvf
+TexEnvfv
+TexEnvi
+TexEnviv
+GetTexEnvfv
+GetTexEnviv \ No newline at end of file
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
index b5c8a5bf..29670790 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_stream.c
@@ -84,7 +84,7 @@ void crServerAddToRunQueue( CRClient *client )
/* give this client a unique number if needed */
if (!client->number) {
- client->number = crServerGenerateID(&cr_server.idsPool.freeClientID);
+ client->number = client->conn->u32ClientID;
}
crDebug("Adding client %p to the run queue", client);
@@ -281,6 +281,28 @@ crServerDeleteClient( CRClient *client )
pNode->next = cr_server.pCleanupClient;
cr_server.pCleanupClient = pNode;
}
+
+ if (!cr_server.numClients)
+ {
+ /* if no clients, the guest driver may be unloaded,
+ * and thus the visible regions situation might not be under control anymore,
+ * so cleanup the 3D framebuffer data here
+ * @todo: what really should happen is that guest driver on unload
+ * posts some request to host that would copy the current framebuffer 3D data to the 2D buffer
+ * (i.e. to the memory used by the standard IFramebuffer API) */
+ HCR_FRAMEBUFFER hFb;
+ for (hFb = CrPMgrFbGetFirstEnabled(); hFb; hFb = CrPMgrFbGetNextEnabled(hFb))
+ {
+ int rc = CrFbUpdateBegin(hFb);
+ if (RT_SUCCESS(rc))
+ {
+ CrFbRegionsClear(hFb);
+ CrFbUpdateEnd(hFb);
+ }
+ else
+ WARN(("CrFbUpdateBegin failed %d", rc));
+ }
+ }
}
/**
@@ -441,7 +463,7 @@ crServerDispatchMessage(CRConnection *conn, CRMessage *msg)
{
uint32_t cbWriteback = pCmdData->cbWriteback;
rc = crVBoxServerInternalClientRead(conn->pClient, (uint8_t*)pCmdData->pWriteback, &cbWriteback);
- CRASSERT(rc == VINF_SUCCESS || rc == VERR_BUFFER_OVERFLOW);
+ Assert(rc == VINF_SUCCESS || rc == VERR_BUFFER_OVERFLOW);
*pCmdData->pcbWriteback = cbWriteback;
}
VBOXCRHGSMI_CMD_CHECK_COMPLETE(pCmdData, rc);
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
index 392bcd20..8037ac66 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_texture.c
@@ -136,3 +136,56 @@ CR_FUNC_IMAGE(TexImage2D,
CR_FUNC_IMAGE(TexImage3D,
(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid * pixels),
(target, level, internalFormat, width, height, depth, border, format, type, realptr), pixels)
+
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvf( GLenum target, GLenum pname, GLfloat param )
+{
+ crStateTexEnvf( target, pname, param );
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvf( target, pname, param ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvfv( GLenum target, GLenum pname, const GLfloat * params )
+{
+ crStateTexEnvfv( target, pname, params );
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvfv( target, pname, params ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnvi( GLenum target, GLenum pname, GLint param )
+{
+ crStateTexEnvi( target, pname, param );
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnvi( target, pname, param ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchTexEnviv( GLenum target, GLenum pname, const GLint * params )
+{
+ crStateTexEnviv( target, pname, params );
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ CR_GLERR_CHECK(cr_server.head_spu->dispatch_table.TexEnviv( target, pname, params ););
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetTexEnvfv( GLenum target, GLenum pname, GLfloat * params )
+{
+ GLfloat local_params[4];
+ (void) params;
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ cr_server.head_spu->dispatch_table.GetTexEnvfv( target, pname, local_params );
+ else
+ crStateGetTexEnvfv( target, pname, local_params );
+
+ crServerReturnValue( &(local_params[0]), crStateHlpComponentsCount(pname)*sizeof (GLfloat) );
+}
+
+void SERVER_DISPATCH_APIENTRY crServerDispatchGetTexEnviv( GLenum target, GLenum pname, GLint * params )
+{
+ GLint local_params[4];
+ (void) params;
+ if (GL_POINT_SPRITE != target && pname != GL_COORD_REPLACE)
+ cr_server.head_spu->dispatch_table.GetTexEnviv( target, pname, local_params );
+ else
+ crStateGetTexEnviv( target, pname, local_params );
+
+ crServerReturnValue( &(local_params[0]), crStateHlpComponentsCount(pname)*sizeof (GLint) );
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
index ce380be6..69351255 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
@@ -10,21 +10,94 @@
#include "cr_rand.h"
#include "cr_string.h"
+#include "render/renderspu.h"
+
GLint SERVER_DISPATCH_APIENTRY
crServerDispatchWindowCreate(const char *dpyName, GLint visBits)
{
return crServerDispatchWindowCreateEx(dpyName, visBits, -1);
}
+GLint crServerMuralInit(CRMuralInfo *mural, GLboolean fGuestWindow, GLint visBits, GLint preloadWinID)
+{
+ CRMuralInfo *defaultMural;
+ GLint dims[2];
+ GLint windowID = -1;
+ GLint spuWindow = 0;
+ GLint realVisBits = visBits;
+ const char *dpyName = "";
-GLint
-crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
+ crMemset(mural, 0, sizeof (*mural));
+
+ if (cr_server.fVisualBitsDefault)
+ realVisBits = cr_server.fVisualBitsDefault;
+
+#ifdef RT_OS_DARWIN
+ if (fGuestWindow)
+ {
+ CRMuralInfo *dummy = crServerGetDummyMural(visBits);
+ if (!dummy)
+ {
+ WARN(("crServerGetDummyMural failed"));
+ return -1;
+ }
+ spuWindow = dummy->spuWindow;
+ mural->fIsDummyRefference = GL_TRUE;
+ }
+ else
+#endif
+ {
+ /*
+ * Have first SPU make a new window.
+ */
+ spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, realVisBits );
+ if (spuWindow < 0) {
+ return spuWindow;
+ }
+ mural->fIsDummyRefference = GL_FALSE;
+ }
+
+ /* get initial window size */
+ cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
+
+ defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
+ CRASSERT(defaultMural);
+ mural->gX = 0;
+ mural->gY = 0;
+ mural->width = dims[0];
+ mural->height = dims[1];
+
+ mural->spuWindow = spuWindow;
+ mural->screenId = 0;
+ mural->fHasParentWindow = !!cr_server.screen[0].winID;
+ mural->bVisible = !cr_server.bWindowsInitiallyHidden;
+
+ mural->cVisibleRects = 0;
+ mural->pVisibleRects = NULL;
+ mural->bReceivedRects = GL_FALSE;
+
+ /* generate ID for this new window/mural (special-case for file conns) */
+ if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
+ windowID = spuWindow;
+ else
+ windowID = preloadWinID<0 ? (GLint)crHashtableAllocKeys( cr_server.muralTable, 1 ) : preloadWinID;
+
+ mural->CreateInfo.realVisualBits = realVisBits;
+ mural->CreateInfo.requestedVisualBits = visBits;
+ mural->CreateInfo.externalID = windowID;
+ mural->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
+
+ CR_STATE_SHAREDOBJ_USAGE_INIT(mural);
+
+ return windowID;
+}
+
+GLint crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preloadWinID)
{
CRMuralInfo *mural;
GLint windowID = -1;
- GLint spuWindow;
- GLint dims[2];
- CRCreateInfo_t *pCreateInfo;
+
+ dpyName = "";
if (cr_server.sharedWindows) {
int pos, j;
@@ -54,58 +127,30 @@ crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preload
}
}
- /*
- * Have first SPU make a new window.
- */
- spuWindow = cr_server.head_spu->dispatch_table.WindowCreate( dpyName, visBits );
- if (spuWindow < 0) {
- crServerReturnValue( &spuWindow, sizeof(spuWindow) );
- return spuWindow;
- }
-
- /* get initial window size */
- cr_server.head_spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, spuWindow, GL_INT, 2, dims);
/*
* Create a new mural for the new window.
*/
mural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
- if (mural) {
- CRMuralInfo *defaultMural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, 0);
- CRASSERT(defaultMural);
- mural->gX = 0;
- mural->gY = 0;
- mural->width = dims[0];
- mural->height = dims[1];
-
- mural->spuWindow = spuWindow;
- mural->screenId = 0;
- mural->bVisible = GL_FALSE;
- mural->bUseFBO = GL_FALSE;
-
- mural->cVisibleRects = 0;
- mural->pVisibleRects = NULL;
- mural->bReceivedRects = GL_FALSE;
-
- mural->pvOutputRedirectInstance = NULL;
-
- /* generate ID for this new window/mural (special-case for file conns) */
- if (cr_server.curClient && cr_server.curClient->conn->type == CR_FILE)
- windowID = spuWindow;
- else
- windowID = preloadWinID<0 ? crServerGenerateID(&cr_server.idsPool.freeWindowID) : preloadWinID;
- crHashtableAdd(cr_server.muralTable, windowID, mural);
-
- pCreateInfo = (CRCreateInfo_t *) crAlloc(sizeof(CRCreateInfo_t));
- pCreateInfo->pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
- pCreateInfo->visualBits = visBits;
- crHashtableAdd(cr_server.pWindowCreateInfoTable, windowID, pCreateInfo);
+ if (!mural)
+ {
+ crWarning("crCalloc failed!");
+ return -1;
+ }
- crServerSetupOutputRedirect(mural);
+ windowID = crServerMuralInit(mural, GL_TRUE, visBits, preloadWinID);
+ if (windowID < 0)
+ {
+ crWarning("crServerMuralInit failed!");
+ crServerReturnValue( &windowID, sizeof(windowID) );
+ crFree(mural);
+ return windowID;
}
+ crHashtableAdd(cr_server.muralTable, windowID, mural);
+
crDebug("CRServer: client %p created new window %d (SPU window %d)",
- cr_server.curClient, windowID, spuWindow);
+ cr_server.curClient, windowID, mural->spuWindow);
if (windowID != -1 && !cr_server.bIsInLoadingState) {
int pos;
@@ -117,6 +162,9 @@ crServerDispatchWindowCreateEx(const char *dpyName, GLint visBits, GLint preload
}
}
+ /* ensure we have a dummy mural created right away to avoid potential deadlocks on VM shutdown */
+ crServerGetDummyMural(mural->CreateInfo.realVisualBits);
+
crServerReturnValue( &windowID, sizeof(windowID) );
return windowID;
}
@@ -137,6 +185,65 @@ static int crServerRemoveClientWindow(CRClient *pClient, GLint window)
return false;
}
+void crServerMuralTerm(CRMuralInfo *mural)
+{
+ PCR_BLITTER pBlitter;
+ crServerRedirMuralFBO(mural, false);
+ crServerDeleteMuralFBO(mural);
+
+ if (cr_server.currentMural == mural)
+ {
+ CRMuralInfo *dummyMural = crServerGetDummyMural(cr_server.MainContextInfo.CreateInfo.realVisualBits);
+ /* reset the current context to some dummy values to ensure render spu does not switch to a default "0" context,
+ * which might lead to muralFBO (offscreen rendering) gl entities being created in a scope of that context */
+ cr_server.head_spu->dispatch_table.MakeCurrent(dummyMural->spuWindow, 0, cr_server.MainContextInfo.SpuContext);
+ cr_server.currentWindow = -1;
+ cr_server.currentMural = dummyMural;
+ }
+ else
+ {
+ CRASSERT(cr_server.currentWindow != mural->CreateInfo.externalID);
+ }
+
+ pBlitter = crServerVBoxBlitterGetInitialized();
+ if (pBlitter)
+ {
+ const CR_BLITTER_WINDOW * pWindow = CrBltMuralGetCurrentInfo(pBlitter);
+ if (pWindow && pWindow->Base.id == mural->spuWindow)
+ {
+ CRMuralInfo *dummy = crServerGetDummyMural(mural->CreateInfo.realVisualBits);
+ CR_BLITTER_WINDOW DummyInfo;
+ CRASSERT(dummy);
+ crServerVBoxBlitterWinInit(&DummyInfo, dummy);
+ CrBltMuralSetCurrentInfo(pBlitter, &DummyInfo);
+ }
+ }
+
+ if (!mural->fIsDummyRefference)
+ cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow );
+
+ mural->spuWindow = 0;
+
+ if (mural->pVisibleRects)
+ {
+ crFree(mural->pVisibleRects);
+ }
+
+ if (mural->CreateInfo.pszDpyName)
+ crFree(mural->CreateInfo.pszDpyName);
+
+ crServerRedirMuralFbClear(mural);
+}
+
+static void crServerCleanupCtxMuralRefsCB(unsigned long key, void *data1, void *data2)
+{
+ CRContextInfo *ctxInfo = (CRContextInfo *) data1;
+ CRMuralInfo *mural = (CRMuralInfo *) data2;
+
+ if (ctxInfo->currentMural == mural)
+ ctxInfo->currentMural = NULL;
+}
+
void SERVER_DISPATCH_APIENTRY
crServerDispatchWindowDestroy( GLint window )
{
@@ -157,22 +264,13 @@ crServerDispatchWindowDestroy( GLint window )
return;
}
- if (mural->pvOutputRedirectInstance)
- {
- cr_server.outputRedirect.CROREnd(mural->pvOutputRedirectInstance);
- mural->pvOutputRedirectInstance = NULL;
- }
+ crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
- if (cr_server.currentWindow == window)
- {
- cr_server.currentWindow = -1;
- }
+ crHashtableWalk(cr_server.contextTable, crServerCleanupCtxMuralRefsCB, mural);
- crServerRedirMuralFBO(mural, GL_FALSE);
- crServerDeleteMuralFBO(mural);
+ crServerMuralTerm(mural);
- crDebug("CRServer: Destroying window %d (spu window %d)", window, mural->spuWindow);
- cr_server.head_spu->dispatch_table.WindowDestroy( mural->spuWindow );
+ CRASSERT(cr_server.currentWindow != window);
if (cr_server.curClient)
{
@@ -233,13 +331,29 @@ crServerDispatchWindowDestroy( GLint window )
pNode = pNode->next;
}
- crHashtableDelete(cr_server.pWindowCreateInfoTable, window, crServerCreateInfoDeleteCB);
+ crHashtableDelete(cr_server.muralTable, window, crFree);
- if (mural->pVisibleRects)
+ crServerCheckAllMuralGeometry(NULL);
+}
+
+GLboolean crServerMuralSize(CRMuralInfo *mural, GLint width, GLint height)
+{
+ if (mural->width == width && mural->height == height)
+ return GL_FALSE;
+
+ mural->width = width;
+ mural->height = height;
+
+ if (cr_server.curClient && cr_server.curClient->currentMural == mural
+ && !mural->fRedirected)
{
- crFree(mural->pVisibleRects);
+ crStateGetCurrent()->buffer.width = mural->width;
+ crStateGetCurrent()->buffer.height = mural->height;
}
- crHashtableDelete(cr_server.muralTable, window, crFree);
+
+ crServerCheckAllMuralGeometry(mural);
+
+ return GL_TRUE;
}
void SERVER_DISPATCH_APIENTRY
@@ -256,60 +370,40 @@ crServerDispatchWindowSize( GLint window, GLint width, GLint height )
return;
}
- mural->width = width;
- mural->height = height;
+ crServerMuralSize(mural, width, height);
- if (cr_server.curClient && cr_server.curClient->currentMural == mural)
+ if (cr_server.currentMural == mural)
{
- crStateGetCurrent()->buffer.width = mural->width;
- crStateGetCurrent()->buffer.height = mural->height;
+ crServerPerformMakeCurrent( mural, cr_server.currentCtxInfo );
}
+}
- crServerCheckMuralGeometry(mural);
+void crServerMuralPosition(CRMuralInfo *mural, GLint x, GLint y)
+{
+ if (mural->gX == x && mural->gY == y)
+ return;
- cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
+ mural->gX = x;
+ mural->gY = y;
- /* Work-around Intel driver bug */
- CRASSERT(!cr_server.curClient
- || !cr_server.curClient->currentMural
- || cr_server.curClient->currentMural == mural);
- if (cr_server.curClient && cr_server.curClient->currentMural == mural)
- {
- CRContextInfo * ctxInfo = cr_server.currentCtxInfo;
- CRASSERT(ctxInfo);
- crServerDispatchMakeCurrent(mural->spuWindow, 0, ctxInfo->CreateInfo.externalID);
- }
+ crServerCheckAllMuralGeometry(mural);
}
-
void SERVER_DISPATCH_APIENTRY
crServerDispatchWindowPosition( GLint window, GLint x, GLint y )
{
CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
- /* crDebug("CRServer: Window %d pos %d, %d", window, x, y);*/
if (!mural) {
#if EXTRA_WARN
crWarning("CRServer: invalid window %d passed to WindowPosition()", window);
#endif
return;
}
- mural->gX = x;
- mural->gY = y;
-
- crServerCheckMuralGeometry(mural);
+ crServerMuralPosition(mural, x, y);
}
-void SERVER_DISPATCH_APIENTRY
-crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, GLint *pRects )
+void crServerMuralVisibleRegion( CRMuralInfo *mural, GLint cRects, const GLint *pRects )
{
- CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
- if (!mural) {
-#if EXTRA_WARN
- crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
-#endif
- return;
- }
-
if (mural->pVisibleRects)
{
crFree(mural->pVisibleRects);
@@ -328,17 +422,35 @@ crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, GLint *pRects )
crMemcpy(mural->pVisibleRects, pRects, 4*sizeof(GLint)*cRects);
}
- cr_server.head_spu->dispatch_table.WindowVisibleRegion(mural->spuWindow, cRects, pRects);
+ crServerCheckAllMuralGeometry(mural);
+}
- if (mural->pvOutputRedirectInstance)
- {
- /* @todo the code assumes that RTRECT == four GLInts. */
- cr_server.outputRedirect.CRORVisibleRegion(mural->pvOutputRedirectInstance,
- cRects, (RTRECT *)pRects);
+void SERVER_DISPATCH_APIENTRY
+crServerDispatchWindowVisibleRegion( GLint window, GLint cRects, const GLint *pRects )
+{
+ CRMuralInfo *mural = (CRMuralInfo *) crHashtableSearch(cr_server.muralTable, window);
+ if (!mural) {
+#if EXTRA_WARN
+ crWarning("CRServer: invalid window %d passed to WindowVisibleRegion()", window);
+#endif
+ return;
}
+
+ crServerMuralVisibleRegion( mural, cRects, pRects );
}
+void crServerMuralShow( CRMuralInfo *mural, GLint state )
+{
+ if (!mural->bVisible == !state)
+ return;
+ mural->bVisible = !!state;
+
+ if (mural->bVisible)
+ crServerCheckMuralGeometry(mural);
+ else
+ crServerCheckAllMuralGeometry(mural);
+}
void SERVER_DISPATCH_APIENTRY
crServerDispatchWindowShow( GLint window, GLint state )
@@ -351,15 +463,9 @@ crServerDispatchWindowShow( GLint window, GLint state )
return;
}
- if (!mural->bUseFBO)
- {
- cr_server.head_spu->dispatch_table.WindowShow(mural->spuWindow, state);
- }
-
- mural->bVisible = state;
+ crServerMuralShow( mural, state );
}
-
GLint
crServerSPUWindowID(GLint serverWindow)
{
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;
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_framebuffer.c b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_framebuffer.c
index ca4d82b3..cdf0591b 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_framebuffer.c
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_framebuffer.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_misc.c b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_misc.c
index 5c79f909..daf2b839 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_misc.c
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_misc.c
@@ -74,3 +74,14 @@ void crUnpackExtendGetPixelMapusv(void)
cr_unpackDispatch.GetPixelMapusv( map, values );
}
+
+void crUnpackExtendVBoxTexPresent(void)
+{
+ GLuint texture = READ_DATA( 8, GLuint );
+ GLuint cfg = READ_DATA( 12, GLuint );
+ GLint xPos = READ_DATA( 16, GLint );
+ GLint yPos = READ_DATA( 20, GLint );
+ GLint cRects = READ_DATA( 24, GLint );
+ GLint *pRects = (GLint *)DATA_POINTER( 28, GLvoid );
+ cr_unpackDispatch.VBoxTexPresent( texture, cfg, xPos, yPos, cRects, pRects );
+}
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
index 6b3204ce..2e90b3d5 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_shaders.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2009 Oracle Corporation
+ * Copyright (C) 2009-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
@@ -39,8 +39,8 @@ void crUnpackExtendShaderSource(void)
GLsizei count = READ_DATA(12, GLsizei);
GLint hasNonLocalLen = READ_DATA(16, GLsizei);
GLint *pLocalLength = DATA_POINTER(20, GLint);
- const char **ppStrings = NULL;
- GLsizei i;
+ char **ppStrings = NULL;
+ GLsizei i, j, jUpTo;
int pos=20+count*sizeof(*pLocalLength);
if (hasNonLocalLen>0)
@@ -60,9 +60,24 @@ void crUnpackExtendShaderSource(void)
{
pLocalLength[i] -= 1;
}
+
+ Assert(pLocalLength[i] > 0);
+ jUpTo = i == count -1 ? pLocalLength[i] - 1 : pLocalLength[i];
+ for (j = 0; j < jUpTo; ++j)
+ {
+ char *pString = ppStrings[i];
+
+ if (pString[j] == '\0')
+ {
+ Assert(j == jUpTo - 1);
+ pString[j] = '\n';
+ }
+ }
}
- cr_unpackDispatch.ShaderSource(shader, count, ppStrings, length ? length : pLocalLength);
+// cr_unpackDispatch.ShaderSource(shader, count, ppStrings, length ? length : pLocalLength);
+ cr_unpackDispatch.ShaderSource(shader, 1, ppStrings, 0);
+
crFree(ppStrings);
}
@@ -249,7 +264,7 @@ void crUnpackExtendGetAttachedShaders(void)
void crUnpackExtendGetAttachedObjectsARB(void)
{
- GLhandleARB containerObj = READ_DATA(8, GLhandleARB);
+ VBoxGLhandleARB containerObj = READ_DATA(8, VBoxGLhandleARB);
GLsizei maxCount = READ_DATA(12, GLsizei);
SET_RETURN_PTR(16);
SET_WRITEBACK_PTR(24);
@@ -258,7 +273,7 @@ void crUnpackExtendGetAttachedObjectsARB(void)
void crUnpackExtendGetInfoLogARB(void)
{
- GLhandleARB obj = READ_DATA(8, GLhandleARB);
+ VBoxGLhandleARB obj = READ_DATA(8, VBoxGLhandleARB);
GLsizei maxLength = READ_DATA(12, GLsizei);
SET_RETURN_PTR(16);
SET_WRITEBACK_PTR(24);
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_visibleregion.c b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_visibleregion.c
index 4bae17d1..961f7ac0 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_visibleregion.c
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpack_visibleregion.c
@@ -5,7 +5,7 @@
*/
/*
- * Copyright (C) 2008 Oracle Corporation
+ * Copyright (C) 2008-2010 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
diff --git a/src/VBox/HostServices/SharedOpenGL/unpacker/unpacker_special b/src/VBox/HostServices/SharedOpenGL/unpacker/unpacker_special
index e0f9a743..cd1fc415 100644
--- a/src/VBox/HostServices/SharedOpenGL/unpacker/unpacker_special
+++ b/src/VBox/HostServices/SharedOpenGL/unpacker/unpacker_special
@@ -180,3 +180,4 @@ UniformMatrix2x4fv
UniformMatrix4x2fv
UniformMatrix3x4fv
UniformMatrix4x3fv
+VBoxTexPresent \ No newline at end of file