Beispiel #1
0
static SPUFunctions *
packSPUInit( int id, SPU *child, SPU *self,
                         unsigned int context_id,
                         unsigned int num_contexts )
{
    ThreadInfo *thread;

    (void) context_id;
    (void) num_contexts;
    (void) child;
    (void) self;

#if defined(CHROMIUM_THREADSAFE) && !defined(WINDOWS)
    crInitMutex(&_PackMutex);
#endif

    pack_spu.id = id;

    packspuSetVBoxConfiguration( child );

    /* This connects to the server, sets up the packer, etc. */
    thread = packspuNewThread( crThreadID() );

    if (!thread) {
        return NULL;
    }
    CRASSERT( thread == &(pack_spu.thread[0]) );
    pack_spu.idxThreadInUse = 0;

    packspuCreateFunctions();
    crStateInit();

    return &pack_functions;
}
Beispiel #2
0
    static void
stubCheckMultithread( void )
{
    static unsigned long knownID;
    static GLboolean firstCall = GL_TRUE;

    if (stub.threadSafe)
	return;  /* nothing new, nothing to do */

    if (firstCall) {
	knownID = crThreadID();
	firstCall = GL_FALSE;
    }
    else if (knownID != crThreadID()) {
	/* going thread-safe now! */
	stub.threadSafe = GL_TRUE;
	crSPUCopyDispatchTable(&glim, &stubThreadsafeDispatch);
    }
}
Beispiel #3
0
void PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(void)
{
    crLockMutex(&_PackMutex);
    {
        int i;
        GET_THREAD(thread);
        CRASSERT(!thread);
        CRASSERT((pack_spu.numThreads>0) && (pack_spu.numThreads<MAX_THREADS));

        for (i=0; i<MAX_THREADS; ++i)
        {
            if (!pack_spu.thread[i].inUse)
            {
                thread = &pack_spu.thread[i];
                break;
            }
        }
        CRASSERT(thread);

        thread->inUse = GL_TRUE;
        thread->id = crThreadID();
        thread->currentContext = NULL;
        thread->bInjectThread = GL_TRUE;

        thread->netServer.name = crStrdup(pack_spu.name);
        thread->netServer.buffer_size = 64 * 1024;

        crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer));
        CRASSERT(thread->netServer.conn);

        CRASSERT(thread->packer == NULL);
        thread->packer = crPackNewContext( pack_spu.swap );
        CRASSERT(thread->packer);
        crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
                         thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
        thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;

        crPackSetBuffer( thread->packer, &thread->buffer );
        crPackFlushFunc( thread->packer, packspuFlush );
        crPackFlushArg( thread->packer, (void *) thread );
        crPackSendHugeFunc( thread->packer, packspuHuge );
        crPackSetContext( thread->packer );

        crSetTSD(&_PackTSD, thread);

        pack_spu.numThreads++;
    }
    crUnlockMutex(&_PackMutex);
}
Beispiel #4
0
void PACKSPU_APIENTRY packspu_VBoxPackAttachThread()
{
#if 0
    int i;
    GET_THREAD(thread);

    for (i=0; i<MAX_THREADS; ++i)
    {
        if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i] && thread->id==crThreadID())
        {
            crError("2nd attach to same thread");
        }
    }
#endif

    crSetTSD(&_PackTSD, NULL);
}
Beispiel #5
0
int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer)
{
    CRClient *pClient=NULL;
    int32_t i;

    //crDebug("crServer: [%x] ClientRead u32ClientID=%d", crThreadID(), 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)
        {
            pClient = cr_server.clients[i];
            break;
        }
    }
    if (!pClient) return VERR_INVALID_PARAMETER;    

    if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED;

    if (pClient->conn->cbHostBuffer > *pcbBuffer)
    {
        crDebug("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d",
                  crThreadID(), u32ClientID, *pcbBuffer, pClient->conn->cbHostBuffer);

        /* Return the size of needed buffer */
        *pcbBuffer = pClient->conn->cbHostBuffer;

        return VERR_BUFFER_OVERFLOW;
    }

    *pcbBuffer = pClient->conn->cbHostBuffer;

    if (*pcbBuffer)
    {
        CRASSERT(pClient->conn->pHostBuffer);

        crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
        pClient->conn->cbHostBuffer = 0;
    }

    return VINF_SUCCESS;
}
Beispiel #6
0
GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits )
{
    GET_THREAD(thread);
    static int num_calls = 0;
    int writeback = pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
    GLint return_val = (GLint) 0;

    if (!thread) {
        thread = packspuNewThread( crThreadID() );
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    crPackSetContext(thread->packer);

    if (pack_spu.swap)
    {
        crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
    }
    else
    {
        crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
    }
    packspuFlush(thread);
    if (!(thread->netServer.conn->actual_network))
    {
        return num_calls++;
    }
    else
    {
        while (writeback)
            crNetRecv();
        if (pack_spu.swap)
        {
            return_val = (GLint) SWAP32(return_val);
        }
        return return_val;
    }
}
Beispiel #7
0
void PACKSPU_APIENTRY packspu_VBoxDetachThread()
{
    int i;
    GET_THREAD(thread);

    if (thread)
    {
        crLockMutex(&_PackMutex);

        for (i=0; i<MAX_THREADS; ++i)
        {
            if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i]
                && thread->id==crThreadID() && thread->netServer.conn)
            {
                CRASSERT(pack_spu.numThreads>0);

                packspuFlush((void *) thread);

                if (pack_spu.thread[i].packer)
                {
                    CR_LOCK_PACKER_CONTEXT(thread->packer);
                    crPackSetContext(NULL);
                    CR_UNLOCK_PACKER_CONTEXT(thread->packer);
                    crPackDeleteContext(pack_spu.thread[i].packer);
                }
                crNetFreeConnection(pack_spu.thread[i].netServer.conn);

                pack_spu.numThreads--;
                /*note can't shift the array here, because other threads have TLS references to array elements*/
                crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo));

                crSetTSD(&_PackTSD, NULL);

                if (i==pack_spu.idxThreadInUse)
                {
                    for (i=0; i<MAX_THREADS; ++i)
                    {
                        if (pack_spu.thread[i].inUse)
                        {
                            pack_spu.idxThreadInUse=i;
                            break;
                        }
                    }
                }

                break;
            }
        }

        for (i=0; i<CR_MAX_CONTEXTS; ++i)
        {
            ContextInfo *ctx = &pack_spu.context[i];
            if (ctx->currentThread == thread)
            {
                CRASSERT(ctx->fAutoFlush);
                ctx->currentThread = NULL;
            }
        }

        crUnlockMutex(&_PackMutex);
    }

    crStateVBoxDetachThread();
}
static DWORD WINAPI renderSPUWindowThreadProc(void* unused)
{
    MSG msg;
    bool bRet;

    (void) unused;

    /* Force system to create the message queue.
     * Else, there's a chance that render spu will issue PostThreadMessage
     * before this thread calls GetMessage for first time.
     */
    PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);

    crDebug("RenderSPU: Window thread started (%x)", crThreadID());
    SetEvent(render_spu.hWinThreadReadyEvent);

    while( (bRet = GetMessage( &msg, 0, 0, 0 )) != 0)
    {
        if (bRet == -1)
        {
            crError("RenderSPU: Window thread GetMessage failed (%x)", GetLastError());
            break;
        }
        else
        {
            if (msg.message == WM_VBOX_RENDERSPU_CREATE_WINDOW)
            {
                LPCREATESTRUCT pCS = (LPCREATESTRUCT) msg.lParam;
                HWND hWnd;
                WindowInfo *pWindow = (WindowInfo *)pCS->lpCreateParams;

                CRASSERT(msg.lParam && !msg.wParam && pCS->lpCreateParams);

                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)
            {
                CRASSERT(msg.lParam && !msg.wParam);

                DestroyWindow(((VBOX_RENDERSPU_DESTROY_WINDOW*) msg.lParam)->hWnd);

                SetEvent(render_spu.hWinThreadReadyEvent);
            }
            else
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }
    }

    render_spu.dwWinThreadId = 0;

    crDebug("RenderSPU: Window thread stopped (%x)", crThreadID());
    SetEvent(render_spu.hWinThreadReadyEvent);

    return 0;
}
Beispiel #9
0
GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi)
{
    GLint con = 0;
    int i;
    GET_THREAD(thread);
    CRASSERT(!thread);
    crLockMutex(&_PackMutex);
    {
        CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI() || (pack_spu.numThreads>0));
        CRASSERT(pack_spu.numThreads<MAX_THREADS);
        for (i=0; i<MAX_THREADS; ++i)
        {
            if (!pack_spu.thread[i].inUse)
            {
                thread = &pack_spu.thread[i];
                break;
            }
        }
        CRASSERT(thread);

        thread->inUse = GL_TRUE;
        if (!CRPACKSPU_IS_WDDM_CRHGSMI())
            thread->id = crThreadID();
        else
            thread->id = THREAD_OFFSET_MAGIC + i;
        thread->currentContext = NULL;
        thread->bInjectThread = GL_TRUE;

        thread->netServer.name = crStrdup(pack_spu.name);
        thread->netServer.buffer_size = 64 * 1024;

        packspuConnectToServer(&(thread->netServer)
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
                , pHgsmi
#endif
        );
        CRASSERT(thread->netServer.conn);

        CRASSERT(thread->packer == NULL);
        thread->packer = crPackNewContext( pack_spu.swap );
        CRASSERT(thread->packer);
        crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
                         thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
        thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;

        crPackSetBuffer( thread->packer, &thread->buffer );
        crPackFlushFunc( thread->packer, packspuFlush );
        crPackFlushArg( thread->packer, (void *) thread );
        crPackSendHugeFunc( thread->packer, packspuHuge );
        crPackSetContext( thread->packer );

        crSetTSD(&_PackTSD, thread);

        pack_spu.numThreads++;
    }
    crUnlockMutex(&_PackMutex);

    if (CRPACKSPU_IS_WDDM_CRHGSMI())
    {
        CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread)
                && GET_THREAD_VAL_ID(thread->id) == thread);
        con = thread->id;
    }
    return con;
}
Beispiel #10
0
void stubInstallWindowMessageHook()
{
    stub.hMessageHook = SetWindowsHookEx(WH_CALLWNDPROCRET, stubCBWindowMessageHookProc, 0, crThreadID());

    if (!stub.hMessageHook)
        crWarning("Window message hook install failed! (not fatal)");
}
Beispiel #11
0
void REPLICATESPU_APIENTRY
replicatespu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx )
{
	unsigned int i;
	unsigned int show_window = 0;
	WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, window );
	ContextInfo *newCtx = (ContextInfo *) crHashtableSearch( replicate_spu.contextTable, ctx );
	GET_THREAD(thread);

	if (!winInfo) {
		crWarning("Replicate SPU: Invalid window ID %d passed to MakeCurrent", window);
		return;
	}

	if (thread)
		replicatespuFlushAll( (void *)thread );

	if (!thread) {
		thread = replicatespuNewThread( crThreadID() );
	}
	CRASSERT(thread);
	CRASSERT(thread->packer);

	if (newCtx && winInfo) {
		newCtx->currentWindow = winInfo;

#if 000
		/* This appears to be obsolete code */
		if (replicate_spu.render_to_crut_window && !nativeWindow) {
			char response[8096];
			CRConnection *conn = crMothershipConnect();
			if (!conn) {
				crError("Replicate SPU: Couldn't connect to the mothership to get CRUT drawable-- "
								"I have no idea what to do!");
			}
			crMothershipGetParam( conn, "crut_drawable", response );
			nativeWindow = crStrToInt(response);
			crDebug("Replicate SPU: using CRUT drawable: 0x%x", nativeWindow);
			crMothershipDisconnect(conn);
		}
#endif

		if (replicate_spu.glx_display
				&& winInfo
				&& winInfo->nativeWindow != nativeWindow)
		{
			winInfo->nativeWindow = nativeWindow;
			replicatespuMonitorWindow(winInfo);
			replicatespuRePositionWindow(winInfo);
			show_window = 1;
		}

		CRASSERT(newCtx->State);  /* verify valid */

		crPackSetContext( thread->packer );
	}

	/*
	 * Send the MakeCurrent to all crservers (vnc viewers)
	 */
	for (i = 0; i < CR_MAX_REPLICANTS; i++) {
		const GLint serverWin = winInfo ? winInfo->id[i] : -1;
		const GLint serverCtx = newCtx ? newCtx->rserverCtx[i] : -1;

		if (!IS_CONNECTED(replicate_spu.rserver[i].conn))
				continue;

		/* Note: app's native window ID not needed on server side; pass zero */
		if (replicate_spu.swap)
			crPackMakeCurrentSWAP(serverWin, 0, serverCtx);
		else
			crPackMakeCurrent(serverWin, 0, serverCtx);

		if (show_window) {
			/* We may find that the window was mapped before we
			 * called MakeCurrent, if that's the case then ensure
			 * the remote end gets the WindowShow event */
			if (winInfo->viewable) {
				if (replicate_spu.swap)
					crPackWindowShowSWAP(serverWin, GL_TRUE);
				else
					crPackWindowShow(serverWin, GL_TRUE);
			}
		}

		replicatespuFlushOne(thread, i);
	}

	if (newCtx) {
		crStateMakeCurrent( newCtx->State );
		crDLMSetCurrentState(newCtx->dlmState);
	}
	else {
		crStateMakeCurrent( NULL );
		crDLMSetCurrentState(NULL);
	}

	thread->currentContext = newCtx;
}
Beispiel #12
0
GLint REPLICATESPU_APIENTRY
replicatespu_WindowCreate( const char *dpyName, GLint visBits )
{
	unsigned int i;
	static GLint freeWinID = 400;
	WindowInfo *winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
	GET_THREAD(thread);

	if (!winInfo)
		return -1;

	if (thread)
		replicatespuFlushAll( (void *) thread );
	else
		thread = replicatespuNewThread( crThreadID() );

	replicatespuFlushAll( (void *) thread );
	crPackSetContext( thread->packer );

#ifdef CHROMIUM_THREADSAFE_notyet
	crLockMutex(&_ReplicateMutex);
#endif

	for (i = 1; i < CR_MAX_REPLICANTS; i++) {
		if (IS_CONNECTED(replicate_spu.rserver[i].conn)) {
			int writeback = 1;
			int return_val = -1;

			if (replicate_spu.swap)
				crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
			else
				crPackWindowCreate( dpyName, visBits, &return_val, &writeback );

			replicatespuFlushOne(thread, i);

			while (writeback)
				crNetRecv();

			if (replicate_spu.swap)
				return_val = (GLint) SWAP32(return_val);

			if (return_val < 0)
				crWarning("Replicate SPU: server %d returned window id -1", i);

			/* XXX temp */
			crDebug("Replicate SPU: Window create, server %d returned %d", i, return_val);
			winInfo->id[i] = return_val;
		}
		else {
			winInfo->id[i] = -1;
		}
	}

	winInfo->visBits = visBits;
	winInfo->width = 0;
	winInfo->height = 0;
	winInfo->nativeWindow = 0;
	winInfo->viewable = GL_FALSE; 

	crHashtableAdd(replicate_spu.windowTable, freeWinID, winInfo);

#ifdef CHROMIUM_THREADSAFE_notyet
	crUnlockMutex(&_ReplicateMutex);
#endif

	return freeWinID++;
}
Beispiel #13
0
GLint PACKSPU_APIENTRY
packspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx )
{
    GET_THREAD(thread);
    int writeback = 1;
    GLint serverCtx = (GLint) -1;
    int slot;

#ifdef CHROMIUM_THREADSAFE
    crLockMutex(&_PackMutex);
#endif

    if (!thread) {
        thread = packspuNewThread(crThreadID());
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    if (shareCtx > 0) {
        /* translate to server ctx id */
        shareCtx -= MAGIC_OFFSET;
        if (shareCtx >= 0 && shareCtx < pack_spu.numContexts) {
            shareCtx = pack_spu.context[shareCtx].serverCtx;
        }
    }

    crPackSetContext( thread->packer );

    /* Pack the command */
    if (pack_spu.swap)
        crPackCreateContextSWAP( dpyName, visual, shareCtx, &serverCtx, &writeback );
    else
        crPackCreateContext( dpyName, visual, shareCtx, &serverCtx, &writeback );

    /* Flush buffer and get return value */
    packspuFlush(thread);
    if (!(thread->netServer.conn->actual_network))
    {
        /* HUMUNGOUS HACK TO MATCH SERVER NUMBERING
         *
         * The hack exists solely to make file networking work for now.  This
         * is totally gross, but since the server expects the numbers to start
         * from 5000, we need to write them out this way.  This would be
         * marginally less gross if the numbers (500 and 5000) were maybe
         * some sort of #define'd constants somewhere so the client and the
         * server could be aware of how each other were numbering things in
         * cases like file networking where they actually
         * care. 
         *
         *  -Humper 
         *
         */
        serverCtx = 5000;
    }
    else {
        while (writeback)
            crNetRecv();

        if (pack_spu.swap) {
            serverCtx = (GLint) SWAP32(serverCtx);
        }
        if (serverCtx < 0) {
#ifdef CHROMIUM_THREADSAFE
            crUnlockMutex(&_PackMutex);
#endif
            crWarning("Failure in packspu_CreateContext");
            return -1;  /* failed */
        }
    }

    /* find an empty context slot */
    for (slot = 0; slot < pack_spu.numContexts; slot++) {
        if (!pack_spu.context[slot].clientState) {
            /* found empty slot */
            break;
        }
    }
    if (slot == pack_spu.numContexts) {
        pack_spu.numContexts++;
    }

    /* Fill in the new context info */
    /* XXX fix-up sharedCtx param here */
    pack_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL);
    pack_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE;
    pack_spu.context[slot].serverCtx = serverCtx;

#ifdef CHROMIUM_THREADSAFE
    crUnlockMutex(&_PackMutex);
#endif

    return MAGIC_OFFSET + slot;
}
Beispiel #14
0
void PACKSPU_APIENTRY packspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx )
{
    GET_THREAD(thread);
    GLint serverCtx;
    ContextInfo *newCtx;

    if (!thread) {
        thread = packspuNewThread( crThreadID() );
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    if (ctx) {
        const int slot = ctx - MAGIC_OFFSET;

        CRASSERT(slot >= 0);
        CRASSERT(slot < pack_spu.numContexts);

        newCtx = &pack_spu.context[slot];
        CRASSERT(newCtx->clientState);  /* verify valid */

        if (newCtx->fAutoFlush)
        {
            if (newCtx->currentThread && newCtx->currentThread != thread)
            {
                crLockMutex(&_PackMutex);
                /* do a flush for the previusly assigned thread
                 * to ensure all commands issued there are submitted */
                if (newCtx->currentThread
                    && newCtx->currentThread->inUse
                    && newCtx->currentThread->netServer.conn
                    && newCtx->currentThread->packer && newCtx->currentThread->packer->currentBuffer)
                {
                    packspuFlush((void *) newCtx->currentThread);
                }
                crUnlockMutex(&_PackMutex);
            }
            newCtx->currentThread = thread;
        }

        thread->currentContext = newCtx;

        crPackSetContext( thread->packer );
        crStateMakeCurrent( newCtx->clientState );
        //crStateSetCurrentPointers(newCtx->clientState, &thread->packer->current);
        serverCtx = pack_spu.context[slot].serverCtx;
    }
    else {
        thread->currentContext = NULL;
        crStateMakeCurrent( NULL );
        newCtx = NULL;
        serverCtx = 0;
    }

    if (pack_spu.swap)
        crPackMakeCurrentSWAP( window, nativeWindow, serverCtx );
    else
        crPackMakeCurrent( window, nativeWindow, serverCtx );

    {
        GET_THREAD(t);
        (void) t;
        CRASSERT(t);
    }
}