329
374
crLockMutex(mutex);
331
376
crDebug("stubSPUSafeTearDown");
379
# ifndef CR_NEWWINTRACK
334
380
stubUninstallWindowMessageHook();
336
crMemset(&stub, 0, sizeof(stub));
384
#if defined(CR_NEWWINTRACK)
385
crUnlockMutex(mutex);
386
# if defined(WINDOWS)
387
if (RTThreadGetState(stub.hSyncThread)!=RTTHREADSTATE_TERMINATED)
392
hNative = OpenThread(SYNCHRONIZE|THREAD_QUERY_INFORMATION|THREAD_TERMINATE,
393
false, RTThreadGetNative(stub.hSyncThread));
396
crWarning("Failed to get handle for sync thread(%#x)", GetLastError());
400
crDebug("Got handle %p for thread %#x", hNative, RTThreadGetNative(stub.hSyncThread));
403
ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
405
if (PostThreadMessage(RTThreadGetNative(stub.hSyncThread), WM_QUIT, 0, 0))
407
RTThreadWait(stub.hSyncThread, 1000, NULL);
409
/*Same issue as on linux, RTThreadWait exits before system thread is terminated, which leads
410
* to issues as our dll goes to be unloaded.
412
*We usually call this function from DllMain which seems to be holding some lock and thus we have to
413
* kill thread via TerminateThread.
415
if (WaitForSingleObject(hNative, 100)==WAIT_TIMEOUT)
417
crDebug("Wait failed, terminating");
418
if (!TerminateThread(hNative, 1))
420
crDebug("TerminateThread failed");
423
if (GetExitCodeThread(hNative, &ec))
425
crDebug("Thread %p exited with ec=%i", hNative, ec);
429
crDebug("GetExitCodeThread failed(%#x)", GetLastError());
434
crDebug("Sync thread killed before DLL_PROCESS_DETACH");
439
CloseHandle(hNative);
443
if (stub.hSyncThread!=NIL_RTTHREAD)
445
ASMAtomicWriteBool(&stub.bShutdownSyncThread, true);
447
/*RTThreadWait might return too early, which cause our code being unloaded while RT thread wrapper is still running*/
448
int rc = pthread_join(RTThreadGetNative(stub.hSyncThread), NULL);
451
crDebug("pthread_join failed %i", rc);
337
463
#ifdef CHROMIUM_THREADSAFE
338
464
crUnlockMutex(mutex);
339
465
crFreeMutex(mutex);
467
crMemset(&stub, 0, sizeof(stub));
732
#ifdef CR_NEWWINTRACK
733
# ifdef VBOX_WITH_WDDM
734
static stubDispatchVisibleRegions(WindowInfo *pWindow)
739
dwCount = GetRegionData(pWindow->hVisibleRegion, 0, NULL);
740
lpRgnData = crAlloc(dwCount);
744
GetRegionData(pWindow->hVisibleRegion, dwCount, lpRgnData);
745
crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, lpRgnData->rdh.nCount);
746
stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, lpRgnData->rdh.nCount, (GLint*) lpRgnData->Buffer);
749
else crWarning("GetRegionData failed, VisibleRegions update failed");
752
static HRGN stubMakeRegionFromRects(PVBOXVIDEOCM_CMD_RECTS pRegions, uint32_t start)
757
if (pRegions->RectsInfo.cRects<=start)
759
return INVALID_HANDLE_VALUE;
762
hRgn = CreateRectRgn(0, 0, 0, 0);
763
for (i=start; i<pRegions->RectsInfo.cRects; ++i)
765
hTmpRgn = CreateRectRgnIndirect(&pRegions->RectsInfo.aRects[i]);
766
CombineRgn(hRgn, hRgn, hTmpRgn, RGN_OR);
767
DeleteObject(hTmpRgn);
772
static void stubSyncTrUpdateWindowCB(unsigned long key, void *data1, void *data2)
774
WindowInfo *pWindow = (WindowInfo *) data1;
775
VBOXDISPMP_REGIONS *pRegions = (VBOXDISPMP_REGIONS*) data2;
776
bool bChanged = false;
777
HRGN hNewRgn = INVALID_HANDLE_VALUE;
779
if (pRegions->hWnd != pWindow->hWnd)
784
stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
786
if (!stubSystemWindowExist(pWindow))
788
crWindowDestroy((GLint)pWindow->hWnd);
792
if (!pWindow->mapped)
794
pWindow->mapped = GL_TRUE;
796
crDebug("Dispatched: WindowShow(%i, %i)", pWindow->spuWindow, pWindow->mapped);
797
stub.spu->dispatch_table.WindowShow(pWindow->spuWindow, pWindow->mapped);
800
if (pRegions->pRegions->fFlags.bSetVisibleRects || pRegions->pRegions->fFlags.bSetViewRect)
802
/* ensure data integrity */
803
Assert(!pRegions->pRegions->fFlags.bAddHiddenRects);
805
if (pRegions->pRegions->fFlags.bSetViewRect)
808
unsigned int winW, winH;
811
winX = pRegions->pRegions->RectsInfo.aRects[0].left;
812
winY = pRegions->pRegions->RectsInfo.aRects[0].top;
813
winW = pRegions->pRegions->RectsInfo.aRects[0].right - winX;
814
winH = pRegions->pRegions->RectsInfo.aRects[0].bottom - winY;
816
if (stub.trackWindowPos && (winX!=pWindow->x || winY!=pWindow->y))
818
crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow);
819
stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY);
825
if (stub.trackWindowSize && (winW!=pWindow->width || winH!=pWindow->height))
827
crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow);
828
stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH);
829
pWindow->width = winW;
830
pWindow->height = winH;
834
bRc = MoveWindow(pRegions->hWnd, winX, winY, winW, winH, FALSE /*BOOL bRepaint*/);
837
DWORD winEr = GetLastError();
838
crWarning("stubSyncTrUpdateWindowCB: MoveWindow failed winEr(%d)", winEr);
842
if (pRegions->pRegions->fFlags.bSetVisibleRects)
844
hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, pRegions->pRegions->fFlags.bSetViewRect ? 1 : 0);
847
else if (!pRegions->pRegions->fFlags.bHide)
849
Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
850
hNewRgn = stubMakeRegionFromRects(pRegions->pRegions, 0);
854
Assert(pRegions->pRegions->fFlags.bAddHiddenRects);
855
hNewRgn = CreateRectRgn(pWindow->x, pWindow->y, pWindow->x + pWindow->width, pWindow->y + pWindow->height);
858
if (hNewRgn!=INVALID_HANDLE_VALUE)
860
OffsetRgn(hNewRgn, -pWindow->x, -pWindow->y);
862
if (pWindow->hVisibleRegion!=INVALID_HANDLE_VALUE)
864
CombineRgn(hNewRgn, pWindow->hVisibleRegion, hNewRgn,
865
pRegions->pRegions->fFlags.bAddHiddenRects ? RGN_DIFF:RGN_OR);
867
if (!EqualRgn(pWindow->hVisibleRegion, hNewRgn))
869
DeleteObject(pWindow->hVisibleRegion);
870
pWindow->hVisibleRegion = hNewRgn;
871
stubDispatchVisibleRegions(pWindow);
876
DeleteObject(hNewRgn);
881
if (pRegions->pRegions->fFlags.bSetVisibleRects)
883
pWindow->hVisibleRegion = hNewRgn;
884
stubDispatchVisibleRegions(pWindow);
892
stub.spu->dispatch_table.Flush();
897
static void stubSyncTrCheckWindowsCB(unsigned long key, void *data1, void *data2)
899
WindowInfo *pWindow = (WindowInfo *) data1;
902
if (pWindow->type!=CHROMIUM || pWindow->spuWindow==0)
907
stub.spu->dispatch_table.VBoxPackSetInjectID(pWindow->u32ClientID);
909
if (!stubSystemWindowExist(pWindow))
912
crWindowDestroy((GLint)pWindow->hWnd);
914
crWindowDestroy((GLint)pWindow->drawable);
916
/*No need to flush here as crWindowDestroy does it*/
920
#if defined(WINDOWS) && defined(VBOX_WITH_WDDM)
921
if (stub.bRunningUnderWDDM)
924
stubCheckWindowState(pWindow, GL_TRUE);
927
static DECLCALLBACK(int) stubSyncThreadProc(RTTHREAD ThreadSelf, void *pvUser)
931
# ifdef VBOX_WITH_WDDM
932
static VBOXDISPMP_CALLBACKS VBoxDispMpTstCallbacks = {NULL, NULL, NULL};
933
HMODULE hVBoxD3D = NULL;
934
VBOXDISPMP_REGIONS Regions;
941
crDebug("Sync thread started");
943
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
944
# ifdef VBOX_WITH_WDDM
945
hVBoxD3D = GetModuleHandle("VBoxDispD3D");
948
hVBoxD3D = LoadLibrary("VBoxDispD3D");
953
PFNVBOXDISPMP_GETCALLBACKS pfnVBoxDispMpGetCallbacks;
954
pfnVBoxDispMpGetCallbacks = (PFNVBOXDISPMP_GETCALLBACKS)GetProcAddress(hVBoxD3D, TEXT("VBoxDispMpGetCallbacks"));
955
if (pfnVBoxDispMpGetCallbacks)
957
hr = pfnVBoxDispMpGetCallbacks(VBOXDISPMP_VERSION, &VBoxDispMpTstCallbacks);
960
CRASSERT(VBoxDispMpTstCallbacks.pfnEnableEvents);
961
CRASSERT(VBoxDispMpTstCallbacks.pfnDisableEvents);
962
CRASSERT(VBoxDispMpTstCallbacks.pfnGetRegions);
964
hr = VBoxDispMpTstCallbacks.pfnEnableEvents();
967
crWarning("VBoxDispMpTstCallbacks.pfnEnableEvents failed");
971
crDebug("running with VBoxDispD3D");
972
stub.trackWindowVisibleRgn = 0;
973
stub.bRunningUnderWDDM = true;
978
crWarning("VBoxDispMpGetCallbacks failed");
985
crLockMutex(&stub.mutex);
986
stub.spu->dispatch_table.VBoxPackSetInjectThread();
987
crUnlockMutex(&stub.mutex);
989
RTThreadUserSignal(ThreadSelf);
991
while(!stub.bShutdownSyncThread)
994
if (!PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
996
# ifdef VBOX_WITH_WDDM
997
if (VBoxDispMpTstCallbacks.pfnGetRegions)
999
hr = VBoxDispMpTstCallbacks.pfnGetRegions(&Regions, 50);
1004
crDebug(">>>Regions for HWND(0x%x)>>>", Regions.hWnd);
1005
crDebug("Flags(0x%x)", Regions.pRegions->fFlags.Value);
1006
for (i = 0; i < Regions.pRegions->RectsInfo.cRects; ++i)
1008
RECT *pRect = &Regions.pRegions->RectsInfo.aRects[i];
1009
crDebug("Rect(%d): left(%d), top(%d), right(%d), bottom(%d)", i, pRect->left, pRect->top, pRect->right, pRect->bottom);
1013
/*hacky way to make sure window wouldn't be deleted in another thread as we hold hashtable lock here*/
1014
crHashtableWalk(stub.windowTable, stubSyncTrUpdateWindowCB, &Regions);
1018
if (WAIT_TIMEOUT!=hr)
1020
crWarning("VBoxDispMpTstCallbacks.pfnGetRegions failed with 0x%x", hr);
1022
crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1028
crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1034
if (WM_QUIT==msg.message)
1036
crDebug("Sync thread got WM_QUIT");
1041
TranslateMessage(&msg);
1042
DispatchMessage(&msg);
1046
crLockMutex(&stub.mutex);
1047
crHashtableWalk(stub.windowTable, stubSyncTrCheckWindowsCB, NULL);
1048
crUnlockMutex(&stub.mutex);
1053
#ifdef VBOX_WITH_WDDM
1054
if (VBoxDispMpTstCallbacks.pfnDisableEvents)
1056
VBoxDispMpTstCallbacks.pfnDisableEvents();
1060
FreeLibrary(hVBoxD3D);
1063
crDebug("Sync thread stopped");
598
1069
* Do one-time initializations for the faker.
599
1070
* Returns TRUE on success, FALSE otherwise.