summaryrefslogtreecommitdiff
path: root/src/VBox/HostServices
diff options
context:
space:
mode:
authorFelix Geyer <debfx-pkg@fobos.de>2010-05-13 18:18:03 +0200
committerFelix Geyer <debfx-pkg@fobos.de>2010-05-13 18:18:03 +0200
commit0c7f2a3d122182fe8890ea1f8178d1955c5a04dc (patch)
tree8cba8ec40170496c6511fb9016d157df568258cb /src/VBox/HostServices
parent33961db1e2718be932cefe0b32aae173ae760cea (diff)
downloadvirtualbox-0c7f2a3d122182fe8890ea1f8178d1955c5a04dc.tar.gz
Imported Upstream version 3.1.53-dfsgupstream/3.1.53-dfsg
Diffstat (limited to 'src/VBox/HostServices')
-rw-r--r--src/VBox/HostServices/GuestControl/service.cpp80
-rw-r--r--src/VBox/HostServices/GuestProperties/service.cpp96
-rw-r--r--src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp14
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c79
-rw-r--r--src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c5
-rw-r--r--src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m102
6 files changed, 245 insertions, 131 deletions
diff --git a/src/VBox/HostServices/GuestControl/service.cpp b/src/VBox/HostServices/GuestControl/service.cpp
index 74b002523..d3cdb093a 100644
--- a/src/VBox/HostServices/GuestControl/service.cpp
+++ b/src/VBox/HostServices/GuestControl/service.cpp
@@ -1,4 +1,4 @@
-/* $Id: service.cpp 29003 2010-05-04 11:26:52Z vboxsync $ */
+/* $Id: service.cpp 29220 2010-05-07 15:09:53Z vboxsync $ */
/** @file
* Guest Control Service: Controlling the guest.
*/
@@ -27,7 +27,7 @@
#include <VBox/HostServices/GuestControlSvc.h>
#include <VBox/log.h>
-#include <iprt/asm.h>
+#include <iprt/asm.h> /* For ASMBreakpoint(). */
#include <iprt/assert.h>
#include <iprt/cpp/autores.h>
#include <iprt/cpp/utils.h>
@@ -64,6 +64,8 @@ typedef std::list< HostCmd >::const_iterator HostCmdListIterConst;
*/
struct GuestCall
{
+ /** Client ID; a client can have multiple handles! */
+ uint32_t mClientID;
/** The call handle */
VBOXHGCMCALLHANDLE mHandle;
/** The call parameters */
@@ -72,13 +74,16 @@ struct GuestCall
uint32_t mNumParms;
/** The standard constructor */
- GuestCall() : mHandle(0), mParms(NULL), mNumParms(0) {}
+ GuestCall() : mClientID(0), mHandle(0), mParms(NULL), mNumParms(0) {}
/** The normal contructor */
- GuestCall(VBOXHGCMCALLHANDLE aHandle, VBOXHGCMSVCPARM aParms[], int cParms)
- : mHandle(aHandle), mParms(aParms), mNumParms(cParms) {}
+ GuestCall(uint32_t aClientID, VBOXHGCMCALLHANDLE aHandle,
+ VBOXHGCMSVCPARM aParms[], uint32_t cParms)
+ : mClientID(aClientID), mHandle(aHandle), mParms(aParms), mNumParms(cParms) {}
};
/** The guest call list type */
-typedef std::list <GuestCall> CallList;
+typedef std::list< GuestCall > CallList;
+typedef std::list< GuestCall >::iterator CallListIter;
+typedef std::list< GuestCall >::const_iterator CallListIterConst;
/**
* Class containing the shared information service functionality.
@@ -90,15 +95,6 @@ private:
typedef Service SELF;
/** HGCM helper functions. */
PVBOXHGCMSVCHELPERS mpHelpers;
- /** @todo we should have classes for thread and request handler thread */
- /** Queue of outstanding property change notifications */
- RTREQQUEUE *mReqQueue;
- /** Request that we've left pending in a call to flushNotifications. */
- PRTREQ mPendingDummyReq;
- /** Thread for processing the request queue */
- RTTHREAD mReqThread;
- /** Tell the thread that it should exit */
- bool volatile mfExitThread;
/** Callback function supplied by the host for notification of updates
* to properties */
PFNHGCMSVCEXT mpfnHostCallback;
@@ -112,20 +108,9 @@ private:
public:
explicit Service(PVBOXHGCMSVCHELPERS pHelpers)
: mpHelpers(pHelpers)
- , mPendingDummyReq(NULL)
- , mfExitThread(false)
, mpfnHostCallback(NULL)
, mpvHostData(NULL)
{
- int rc = RTReqCreateQueue(&mReqQueue);
-#ifndef VBOX_GUEST_CTRL_TEST_NOTHREAD
- if (RT_SUCCESS(rc))
- rc = RTThreadCreate(&mReqThread, reqThreadFn, this, 0,
- RTTHREADTYPE_MSG_PUMP, RTTHREADFLAGS_WAITABLE,
- "GuestCtrlReq");
-#endif
- if (RT_FAILURE(rc))
- throw rc;
}
/**
@@ -230,11 +215,10 @@ private:
void paramBufferFree(PVBOXGUESTCTRPARAMBUFFER pBuf);
int paramBufferAssign(PVBOXGUESTCTRPARAMBUFFER pBuf, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
int prepareExecute(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
- static DECLCALLBACK(int) reqThreadFn(RTTHREAD ThreadSelf, void *pvUser);
int clientConnect(uint32_t u32ClientID, void *pvClient);
int clientDisconnect(uint32_t u32ClientID, void *pvClient);
int sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
- int retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
+ int retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
int notifyHost(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
int processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
void call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
@@ -245,19 +229,6 @@ private:
};
-/**
- * Thread function for processing the request queue
- * @copydoc FNRTTHREAD
- */
-/* static */
-DECLCALLBACK(int) Service::reqThreadFn(RTTHREAD ThreadSelf, void *pvUser)
-{
- SELF *pSelf = reinterpret_cast<SELF *>(pvUser);
- while (!pSelf->mfExitThread)
- RTReqProcess(pSelf->mReqQueue, RT_INDEFINITE_WAIT);
- return VINF_SUCCESS;
-}
-
/** @todo Write some nice doc headers! */
/* Stores a HGCM request in an internal buffer (pEx). Needs to be freed later using execBufferFree(). */
int Service::paramBufferAllocate(PVBOXGUESTCTRPARAMBUFFER pBuf, uint32_t uMsg, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
@@ -265,6 +236,10 @@ int Service::paramBufferAllocate(PVBOXGUESTCTRPARAMBUFFER pBuf, uint32_t uMsg, u
AssertPtr(pBuf);
int rc = VINF_SUCCESS;
+ /* Paranoia. */
+ if (cParms > 256)
+ cParms = 256;
+
/*
* Don't verify anything here (yet), because this function only buffers
* the HGCM data into an internal structure and reaches it back to the guest (client)
@@ -391,6 +366,17 @@ int Service::clientConnect(uint32_t u32ClientID, void *pvClient)
int Service::clientDisconnect(uint32_t u32ClientID, void *pvClient)
{
LogFlowFunc(("Client (%ld) disconnected\n", u32ClientID));
+ /*
+ * Throw out all stale clients.
+ */
+ CallListIter it = mClientList.begin();
+ while (it != mClientList.end())
+ {
+ if (it->mClientID == u32ClientID)
+ it = mClientList.erase(it);
+ else
+ it++;
+ }
return VINF_SUCCESS;
}
@@ -423,7 +409,8 @@ int Service::sendHostCmdToGuest(HostCmd *pCmd, VBOXHGCMCALLHANDLE callHandle, ui
* Either fills in parameters from a pending host command into our guest context or
* defer the guest call until we have something from the host.
*/
-int Service::retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
+int Service::retrieveNextHostCmd(uint32_t u32ClientID, VBOXHGCMCALLHANDLE callHandle,
+ uint32_t cParms, VBOXHGCMSVCPARM paParms[])
{
int rc = VINF_SUCCESS;
@@ -434,7 +421,7 @@ int Service::retrieveNextHostCmd(VBOXHGCMCALLHANDLE callHandle, uint32_t cParms,
*/
if (mHostCmds.empty()) /* If command list is empty, defer ... */
{
- mClientList.push_back(GuestCall(callHandle, paParms, cParms));
+ mClientList.push_back(GuestCall(u32ClientID, callHandle, paParms, cParms));
rc = VINF_HGCM_ASYNC_EXECUTE;
}
else
@@ -534,11 +521,12 @@ int Service::processHostCmd(uint32_t eFunction, uint32_t cParms, VBOXHGCMSVCPARM
/* If not processed, buffer it ... */
if (!fProcessed)
{
- mHostCmds.push_back(newCmd);
-
+ mHostCmds.push_back(newCmd);
+#if 0
/* Limit list size by deleting oldest element. */
if (mHostCmds.size() > 256) /** @todo Use a define! */
mHostCmds.pop_front();
+#endif
}
}
return rc;
@@ -567,7 +555,7 @@ void Service::call(VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID,
/* The guest asks the host for the next messsage to process. */
case GUEST_GET_HOST_MSG:
LogFlowFunc(("GUEST_GET_HOST_MSG\n"));
- rc = retrieveNextHostCmd(callHandle, cParms, paParms);
+ rc = retrieveNextHostCmd(u32ClientID, callHandle, cParms, paParms);
break;
/* The guest notifies the host that some output at stdout/stderr is available. */
diff --git a/src/VBox/HostServices/GuestProperties/service.cpp b/src/VBox/HostServices/GuestProperties/service.cpp
index bb443a1fb..7b97a96c3 100644
--- a/src/VBox/HostServices/GuestProperties/service.cpp
+++ b/src/VBox/HostServices/GuestProperties/service.cpp
@@ -1,4 +1,4 @@
-/* $Id: service.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: service.cpp 29394 2010-05-12 01:27:04Z vboxsync $ */
/** @file
* Guest Property Service: Host service entry points.
*/
@@ -96,13 +96,17 @@ struct Property
}
/** Are two properties equal? */
- bool operator== (const Property &prop)
+ bool operator==(const Property &prop)
{
- return ( mName == prop.mName
- && mValue == prop.mValue
- && mTimestamp == prop.mTimestamp
- && mFlags == prop.mFlags
- );
+ if (mTimestamp != prop.mTimestamp)
+ return false;
+ if (mFlags != prop.mFlags)
+ return false;
+ if (mName != prop.mName)
+ return false;
+ if (mValue != prop.mValue)
+ return false;
+ return true;
}
/* Is the property nil? */
@@ -163,6 +167,14 @@ private:
PFNHGCMSVCEXT mpfnHostCallback;
/** User data pointer to be supplied to the host callback function */
void *mpvHostData;
+ /** The previous timestamp.
+ * This is used by getCurrentTimestamp() to decrease the chance of
+ * generating duplicate timestamps. */
+ uint64_t mPrevTimestamp;
+ /** The number of consecutive timestamp adjustments that we've made.
+ * Together with mPrevTimestamp, this defines a set of obsolete timestamp
+ * values: {(mPrevTimestamp - mcTimestampAdjustments), ..., mPrevTimestamp} */
+ uint64_t mcTimestampAdjustments;
/**
* Get the next property change notification from the queue of saved
@@ -192,9 +204,12 @@ private:
* - Appears later than u64Timestamp
* - Matches the pszPatterns
*/
+ /** @todo r=bird: This incorrectly ASSUMES that mTimestamp is unique.
+ * The timestamp resolution can be very coarse on windows for instance. */
PropertyList::const_iterator it = mGuestNotifications.begin();
for (; it != mGuestNotifications.end()
- && it->mTimestamp != u64Timestamp; ++it) {}
+ && it->mTimestamp != u64Timestamp; ++it)
+ {}
if (it == mGuestNotifications.end()) /* Not found */
it = mGuestNotifications.begin();
else
@@ -238,6 +253,8 @@ public:
, meGlobalFlags(NILFLAG)
, mpfnHostCallback(NULL)
, mpvHostData(NULL)
+ , mPrevTimestamp(0)
+ , mcTimestampAdjustments(0)
{ }
/**
@@ -318,6 +335,7 @@ public:
}
private:
static DECLCALLBACK(int) reqThreadFn(RTTHREAD ThreadSelf, void *pvUser);
+ uint64_t getCurrentTimestamp(void);
int validateName(const char *pszName, uint32_t cbName);
int validateValue(const char *pszValue, uint32_t cbValue);
int setPropertyBlock(uint32_t cParms, VBOXHGCMSVCPARM paParms[]);
@@ -343,6 +361,31 @@ private:
/**
+ * Gets the current timestamp.
+ *
+ * Since the RTTimeNow resolution can be very coarse, this method takes some
+ * simple steps to try avoid returning the same timestamp for two consecutive
+ * calls. Code like getOldNotification() more or less assumes unique
+ * timestamps.
+ *
+ * @returns Nanosecond timestamp.
+ */
+uint64_t Service::getCurrentTimestamp(void)
+{
+ RTTIMESPEC time;
+ uint64_t u64NanoTS = RTTimeSpecGetNano(RTTimeNow(&time));
+ if (mPrevTimestamp - u64NanoTS > mcTimestampAdjustments)
+ mcTimestampAdjustments = 0;
+ else
+ {
+ mcTimestampAdjustments++;
+ u64NanoTS = mPrevTimestamp + 1;
+ }
+ this->mPrevTimestamp = u64NanoTS;
+ return u64NanoTS;
+}
+
+/**
* Check that a string fits our criteria for a property name.
*
* @returns IPRT status code
@@ -571,8 +614,7 @@ int Service::setProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGues
uint32_t cchValue = 0; /* ditto */
uint32_t cchFlags = 0;
uint32_t fFlags = NILFLAG;
- RTTIMESPEC time;
- uint64_t u64TimeNano = RTTimeSpecGetNano(RTTimeNow(&time));
+ uint64_t u64TimeNano = getCurrentTimestamp();
LogFlowThisFunc(("\n"));
/*
@@ -701,8 +743,7 @@ int Service::delProperty(uint32_t cParms, VBOXHGCMSVCPARM paParms[], bool isGues
*/
if (rc == VINF_SUCCESS && found)
{
- RTTIMESPEC time;
- uint64_t u64Timestamp = RTTimeSpecGetNano(RTTimeNow(&time));
+ uint64_t u64Timestamp = getCurrentTimestamp();
mProperties.erase(it);
// if (isGuest) /* Notify the host even for properties that the host
// * changed. Less efficient, but ensures consistency. */
@@ -807,28 +848,27 @@ int Service::getOldNotificationInternal(const char *pszPatterns,
uint64_t u64Timestamp,
Property *pProp)
{
- int rc = VINF_SUCCESS;
- bool warn = false;
-
/* We count backwards, as the guest should normally be querying the
* most recent events. */
+ int rc = VWRN_NOT_FOUND;
PropertyList::reverse_iterator it = mGuestNotifications.rbegin();
- for (; it->mTimestamp != u64Timestamp && it != mGuestNotifications.rend();
- ++it) {}
- /* Warn if the timestamp was not found. */
- if (it->mTimestamp != u64Timestamp)
- warn = true;
+ for (; it != mGuestNotifications.rend(); ++it)
+ if (it->mTimestamp == u64Timestamp)
+ {
+ rc = VINF_SUCCESS;
+ break;
+ }
+
/* Now look for an event matching the patterns supplied. The base()
* member conveniently points to the following element. */
PropertyList::iterator base = it.base();
- for (; !base->Matches(pszPatterns) && base != mGuestNotifications.end();
- ++base) {}
- if (RT_SUCCESS(rc) && base != mGuestNotifications.end())
- *pProp = *base;
- else if (RT_SUCCESS(rc))
- *pProp = Property();
- if (warn)
- rc = VWRN_NOT_FOUND;
+ for (; base != mGuestNotifications.end(); ++base)
+ if (base->Matches(pszPatterns))
+ {
+ *pProp = *base;
+ return rc;
+ }
+ *pProp = Property();
return rc;
}
diff --git a/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp b/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
index b76cf5821..6433ff5ea 100644
--- a/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
+++ b/src/VBox/HostServices/GuestProperties/testcase/tstGuestPropSvc.cpp
@@ -1,4 +1,4 @@
-/* $Id: tstGuestPropSvc.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
+/* $Id: tstGuestPropSvc.cpp 29394 2010-05-12 01:27:04Z vboxsync $ */
/** @file
*
* Testcase for the guest property service.
@@ -726,7 +726,7 @@ int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
{
int rc = VINF_SUCCESS;
VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS };
- char chBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
+ char achBuffer[MAX_NAME_LEN + MAX_VALUE_LEN + MAX_FLAGS_LEN];
static char szPattern[] = "";
RTPrintf("Testing the GET_NOTIFICATION call.\n");
@@ -738,7 +738,7 @@ int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
u64Timestamp = 1;
paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
paParms[1].setUInt64 (u64Timestamp);
- paParms[2].setPointer ((void *) chBuffer, getNotifications[0].cchBuffer - 1);
+ paParms[2].setPointer ((void *) achBuffer, getNotifications[0].cchBuffer - 1);
pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
GET_NOTIFICATION, 4, paParms);
if ( callHandle.rc != VERR_BUFFER_OVERFLOW
@@ -759,7 +759,7 @@ int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
{
paParms[0].setPointer ((void *) szPattern, sizeof(szPattern));
paParms[1].setUInt64 (u64Timestamp);
- paParms[2].setPointer ((void *) chBuffer, sizeof(chBuffer));
+ paParms[2].setPointer ((void *) achBuffer, sizeof(achBuffer));
pTable->pfnCall(pTable->pvService, &callHandle, 0, NULL,
GET_NOTIFICATION, 4, paParms);
if ( RT_FAILURE(callHandle.rc)
@@ -767,11 +767,11 @@ int testGetNotification(VBOXHGCMSVCFNTABLE *pTable)
|| RT_FAILURE(paParms[1].getUInt64 (&u64Timestamp))
|| RT_FAILURE(paParms[3].getUInt32 (&u32Size))
|| u32Size != getNotifications[i].cchBuffer
- || memcmp(chBuffer, getNotifications[i].pchBuffer, u32Size) != 0
+ || memcmp(achBuffer, getNotifications[i].pchBuffer, u32Size) != 0
)
{
- RTPrintf("Failed to get notification for property '%s'.\n",
- getNotifications[i].pchBuffer);
+ RTPrintf("Failed to get notification for property '%s' (rc=%Rrc).\n",
+ getNotifications[i].pchBuffer, rc);
rc = VERR_UNRESOLVED_ERROR;
}
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
index 695a6f7fc..41e4f74ae 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c
@@ -25,7 +25,7 @@
#include <iprt/assert.h>
/**
- * \mainpage CrServerLib
+ * \mainpage CrServerLib
*
* \section CrServerLibIntroduction Introduction
*
@@ -90,7 +90,7 @@ static void crServerTearDown( void )
/* Deallocate all semaphores */
crFreeHashtable(cr_server.semaphores, crFree);
cr_server.semaphores = NULL;
-
+
/* Deallocate all barriers */
crFreeHashtable(cr_server.barriers, DeleteBarrierCallback);
cr_server.barriers = NULL;
@@ -328,7 +328,7 @@ int32_t crVBoxServerAddClient(uint32_t u32ClientID)
return VERR_MAX_THRDS_REACHED;
}
- newClient = (CRClient *) crCalloc(sizeof(CRClient));
+ newClient = (CRClient *) crCalloc(sizeof(CRClient));
crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
newClient->spu_id = 0;
@@ -355,8 +355,8 @@ void crVBoxServerRemoveClient(uint32_t u32ClientID)
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn
- && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn
+ && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
{
break;
}
@@ -380,8 +380,8 @@ int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn
- && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn
+ && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
{
break;
}
@@ -403,11 +403,11 @@ int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t
crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID);
pClient->conn->allow_redir_ptr = 0;
}
- else
+ else
{
pClient->conn->allow_redir_ptr = 1;
}
-
+
pClient->conn->pBuffer = pBuffer;
pClient->conn->cbBuffer = cbBuffer;
@@ -459,8 +459,8 @@ int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn
- && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn
+ && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
{
break;
}
@@ -490,7 +490,7 @@ int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t
crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
pClient->conn->cbHostBuffer = 0;
}
-
+
return VINF_SUCCESS;
}
@@ -501,8 +501,8 @@ int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn
- && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn
+ && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
{
break;
}
@@ -602,7 +602,7 @@ static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void
*/
rc = SSMR3PutMem(pSSM, &key, sizeof(key));
CRASSERT(rc == VINF_SUCCESS);
-
+
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
if (cr_server.curClient)
{
@@ -676,9 +676,9 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
#endif
/* Save contexts state tracker data */
- /* @todo For now just some blind data dumps,
+ /* @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.
+ * 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);
@@ -699,7 +699,7 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
/* Save cr_server.muralTable
* @todo we don't need it all, just geometry info actually
- * @todo store visible regions as well
+ * @todo store visible regions as well
*/
ui32 = crHashtableNumElements(cr_server.muralTable);
/* There should be default mural always */
@@ -715,7 +715,7 @@ DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
/* Save clients info */
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn)
{
CRClient *pClient = cr_server.clients[i];
@@ -816,7 +816,7 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
rc = crStateLoadContext(pContext, pSSM);
AssertRCReturn(rc, rc);
- }
+ }
/* Load windows */
rc = SSMR3GetU32(pSSM, &uiNumElems);
@@ -891,7 +891,7 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
/* Load clients info */
for (i = 0; i < cr_server.numClients; i++)
{
- if (cr_server.clients[i] && cr_server.clients[i]->conn)
+ if (cr_server.clients[i] && cr_server.clients[i]->conn)
{
CRClient *pClient = cr_server.clients[i];
CRClient client;
@@ -982,7 +982,7 @@ DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
-
+
//crStateViewport( 0, 0, 600, 600 );
//pClient->currentMural->viewportValidated = GL_FALSE;
//cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
@@ -1102,9 +1102,6 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
if (sIndex<0 || sIndex>=cr_server.screenCount)
return VERR_INVALID_PARAMETER;
- if (winID==0)
- return VERR_INVALID_PARAMETER;
-
if (MAPPED(SCREEN(sIndex)) && SCREEN(sIndex).winID!=winID)
{
crWarning("Mapped screen[%i] is being remapped.", sIndex);
@@ -1122,7 +1119,37 @@ DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint
renderspuSetWindowId(SCREEN(0).winID);
crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
-
+
+#ifndef WINDOWS
+ /*Restore FB content for clients, which have current window on a screen being remapped*/
+ {
+ GLint i;
+
+ for (i = 0; i < cr_server.numClients; i++)
+ {
+ cr_server.curClient = cr_server.clients[i];
+ if (cr_server.curClient->currentCtx
+ && cr_server.curClient->currentCtx->pImage
+ && cr_server.curClient->currentMural
+ && cr_server.curClient->currentMural->screenId == sIndex
+ && cr_server.curClient->currentCtx->viewport.viewportH == h
+ && cr_server.curClient->currentCtx->viewport.viewportW == w)
+ {
+ int clientWindow = cr_server.curClient->currentWindow;
+ int clientContext = cr_server.curClient->currentContextNumber;
+
+ if (clientWindow && clientWindow != cr_server.currentWindow)
+ {
+ crServerDispatchMakeCurrent(clientWindow, 0, clientContext);
+ }
+
+ crStateApplyFBImage(cr_server.curClient->currentCtx);
+ }
+ }
+ cr_server.curClient = NULL;
+ }
+#endif
+
return VINF_SUCCESS;
}
diff --git a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
index 2d04295b5..bf9af42fd 100644
--- a/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
+++ b/src/VBox/HostServices/SharedOpenGL/crserverlib/server_window.c
@@ -212,10 +212,7 @@ crServerDispatchWindowSize( GLint window, GLint width, GLint height )
crServerCheckMuralGeometry(mural);
- if (!mural->bUseFBO)
- {
- cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
- }
+ cr_server.head_spu->dispatch_table.WindowSize(mural->spuWindow, width, height);
}
diff --git a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
index 32a5ac654..50ce881c1 100644
--- a/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
+++ b/src/VBox/HostServices/SharedOpenGL/render/renderspu_cocoa_helper.m
@@ -21,11 +21,14 @@
#include <iprt/thread.h>
#include <iprt/string.h>
+#include <iprt/mem.h>
+#include <iprt/time.h>
/* Debug macros */
#define FBO 1 /* Disable this to see how the output is without the FBO in the middle of the processing chain. */
//#define SHOW_WINDOW_BACKGROUND 1 /* Define this to see the window background even if the window is clipped */
//#define DEBUG_VERBOSE /* Define this could get some debug info about the messages flow. */
+//#define DEBUG_poetzsch 1
#ifdef DEBUG_poetzsch
#define DEBUG_MSG(text) \
@@ -53,7 +56,7 @@
static void checkGLError(char *file, int line)
{
GLenum g = glGetError();
- if (g != GL_NO_ERROR)
+ if (g != GL_NO_ERROR)
{
char *errStr;
switch (g)
@@ -506,12 +509,14 @@ while(0);
/* 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];
+ DEBUG_MSG(("parentWindowFrameChanged\n"));
[m_pOverlayView reshape];
}
- (void)parentWindowChanged:(NSWindow*)pWindow
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
+ DEBUG_MSG(("parentWindowChanged\n"));
if(pWindow != nil)
{
/* Ask to get notifications when our parent window frame changes. */
@@ -527,7 +532,6 @@ while(0);
// [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 reshape];
-
}
}
@@ -551,6 +555,8 @@ while(0);
m_FBOTexId = 0;
m_FBOTexSize = NSZeroSize;
m_FBODepthStencilPackedId = 0;
+ m_FBOThumbId = 0;
+ m_FBOThumbTexId = 0;
m_cClipRects = 0;
m_paClipRects = NULL;
m_Pos = NSZeroPoint;
@@ -647,8 +653,21 @@ while(0);
- (void)setSize:(NSSize)size
{
m_Size = size;
- [self reshape];
- [self updateFBO];
+
+ if (!m_FBOId)
+ {
+ DEBUG_MSG(("Set size (no fbo) %p\n", self));
+ [self reshape];
+ [self updateFBO];
+ }
+ else
+ {
+ DEBUG_MSG(("Set size FBO %p\n", self));
+ [self reshape];
+ [self updateFBO];
+ /* have to rebind GL_TEXTURE_RECTANGLE_ARB as m_FBOTexId could be changed in updateFBO call */
+ [self updateViewport];
+ }
}
- (NSSize)size
@@ -658,9 +677,11 @@ while(0);
- (void)updateViewport
{
+ DEBUG_MSG(("updateViewport %p\n", self));
if (m_pSharedGLCtx)
{
/* Update the viewport for our OpenGL view */
+ DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
[m_pSharedGLCtx makeCurrentContext];
[m_pSharedGLCtx update];
@@ -683,12 +704,14 @@ while(0);
glEnable(GL_TEXTURE_RECTANGLE_ARB);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
+ DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
[m_pGLCtx makeCurrentContext];
}
}
- (void)reshape
{
+ DEBUG_MSG(("(%p)reshape %p\n", RTThreadSelf(), self));
/* Getting the right screen coordinates of the parents frame is a little bit
* complicated. */
NSRect parentFrame = [m_pParentView frame];
@@ -742,9 +765,13 @@ while(0);
}
- (void)createFBO
-{
+{
+ GLuint fboid = m_FBOId;
+
+ DEBUG_MSG(("createFBO %p\n", self));
[self deleteFBO];
+if (0&&!fboid)
GL_SAVE_STATE;
/* If not previously setup generate IDs for FBO and its associated texture. */
@@ -766,7 +793,7 @@ while(0);
glGenFramebuffersEXT(1, &m_FBOId);
/* & the texture as well the depth/stencil render buffer */
glGenTextures(1, &m_FBOTexId);
- DEBUG_MSG_1(("Create FBO %d %d\n", m_FBOId, m_FBOTexId));
+ DEBUG_MSG(("Create FBO %d %d\n", m_FBOId, m_FBOTexId));
glGenRenderbuffersEXT(1, &m_FBODepthStencilPackedId);
}
@@ -787,7 +814,7 @@ while(0);
GLint filter = GL_NEAREST;
if (m_FBOTexSize.width > maxTexSize || m_FBOTexSize.height > maxTexSize)
{
- filter = GL_NICEST;
+ filter = GL_LINEAR;
if (imageAspectRatio > 1)
{
m_FBOTexSize.width = maxTexSize;
@@ -825,6 +852,7 @@ while(0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
/* Is there a dock tile preview enabled in the GUI? If so setup a
* additional thumbnail view for the dock tile. */
@@ -840,8 +868,8 @@ while(0);
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_NICEST);
- glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NICEST);
+ 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);
@@ -872,15 +900,28 @@ while(0);
m_paClipRects[1] = 0;
m_paClipRects[2] = m_FBOTexSize.width;
m_paClipRects[3] = m_FBOTexSize.height;
-
+
+if (0&&!fboid)
GL_RESTORE_STATE;
}
- (void)deleteFBO
{
- if ([NSOpenGLContext currentContext] != nil)
+ DEBUG_MSG(("deleteFBO %p\n", self));
+ if (m_pSharedGLCtx)
{
- GL_SAVE_STATE;
+ DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
+ [m_pSharedGLCtx makeCurrentContext];
+ [m_pSharedGLCtx update];
+
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ }
+
+ if (m_pGLCtx)
+ {
+ DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
+ [m_pGLCtx makeCurrentContext];
if (m_FBODepthStencilPackedId > 0)
{
@@ -896,14 +937,19 @@ while(0);
}
if (m_FBOId > 0)
{
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ GLint tmpFB;
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING_EXT, &tmpFB);
+ if (tmpFB == m_FBOId)
+ {
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ }
+
glDeleteFramebuffersEXT(1, &m_FBOId);
m_FBOId = 0;
}
-
- GL_RESTORE_STATE;
}
+
if (m_DockTileView != nil)
{
[m_DockTileView removeFromSuperview];
@@ -914,6 +960,7 @@ while(0);
- (void)updateFBO
{
+ DEBUG_MSG(("updateFBO %p\n", self));
[self makeCurrentFBO];
if (m_pGLCtx)
@@ -947,6 +994,7 @@ while(0);
}
// if ([NSOpenGLContext currentContext] != m_pGLCtx)
{
+ DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
[m_pGLCtx makeCurrentContext];
CHECK_GL_ERROR();
// [m_pGLCtx update];
@@ -969,7 +1017,7 @@ while(0);
// [m_pGLCtx flushBuffer];
glFlush();
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- if (tmpFB == m_FBOId)
+ if (tmpFB == m_FBOId)
{
if ([self lockFocusIfCanDraw])
{
@@ -990,7 +1038,7 @@ while(0);
glFlush();
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
DEBUG_MSG_1 (("Flush GetINT %d\n", tmpFB));
- if (tmpFB == m_FBOId)
+ if (tmpFB == m_FBOId)
{
if ([self lockFocusIfCanDraw])
{
@@ -1008,7 +1056,7 @@ while(0);
glFinish();
// glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
DEBUG_MSG_1 (("Finish GetINT %d\n", tmpFB));
- if (tmpFB == m_FBOId)
+ if (tmpFB == m_FBOId)
{
if ([self lockFocusIfCanDraw])
{
@@ -1048,8 +1096,16 @@ while(0);
if (m_FBOTexId > 0)
{
+ if ([m_pSharedGLCtx view] != self)
+ {
+ DEBUG_MSG(("renderFBOToView: not currect view of shared ctx!"));
+ [m_pSharedGLCtx setView: self];
+ [self updateViewport];
+ }
+
+ //DEBUG_MSG(("MakeCurrent (shared) %X\n", m_pSharedGLCtx));
[m_pSharedGLCtx makeCurrentContext];
-
+
if (m_FBOThumbTexId > 0 &&
[m_DockTileView thumbBitmap] != nil)
{
@@ -1143,6 +1199,9 @@ while(0);
/* Clear background to transparent */
glClear(GL_COLOR_BUFFER_BIT);
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, m_FBOTexId);
+
/* Blit the content of the FBO to the screen. todo: check for
* optimization with display lists. */
GLint i;
@@ -1163,6 +1222,7 @@ while(0);
}
glFinish();
[m_pSharedGLCtx flushBuffer];
+ //DEBUG_MSG(("MakeCurrent %X\n", m_pGLCtx));
[m_pGLCtx makeCurrentContext];
}
}
@@ -1454,6 +1514,8 @@ void cocoaViewMakeCurrentContext(NativeViewRef pView, NativeGLCtxRef pCtx)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
+ DEBUG_MSG(("cocoaViewMakeCurrentContext(%p, %p)\n", pView, pCtx));
+
[(OverlayView*)pView setGLCtx:pCtx];
[(OverlayView*)pView makeCurrentFBO];
@@ -1529,7 +1591,7 @@ void cocoaBindFramebufferEXT(GLenum target, GLuint framebuffer)
{
NSAutoreleasePool *pPool = [[NSAutoreleasePool alloc] init];
- DEBUG_MSG_1(("glRenderspuBindFramebufferEXT called %d\n", framebuffer));
+ DEBUG_MSG(("glRenderspuBindFramebufferEXT called %d\n", framebuffer));
#ifdef FBO
if (framebuffer != 0)