void stubDestroyContext( unsigned long contextId ) { ContextInfo *context; if (!stub.contextTable) { return; } /* the lock order is windowTable->contextTable (see wglMakeCurrent_prox, glXMakeCurrent) * this is why we need to take a windowTable lock since we will later do stub.windowTable access & locking */ crHashtableLock(stub.windowTable); crHashtableLock(stub.contextTable); context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId); if (context) stubDestroyContextLocked(context); else crError("No context."); #ifdef CHROMIUM_THREADSAFE if (stubGetCurrentContext() == context) { stubSetCurrentContext(NULL); } VBoxTlsRefMarkDestroy(context); VBoxTlsRefRelease(context); #else if (stubGetCurrentContext() == context) { stubSetCurrentContext(NULL); } stubContextFree(context); #endif crHashtableUnlock(stub.contextTable); crHashtableUnlock(stub.windowTable); }
/** * Init variables in the stub structure, install signal handler. */ static void stubInitVars(void) { WindowInfo *defaultWin; #ifdef CHROMIUM_THREADSAFE crInitMutex(&stub.mutex); #endif /* At the very least we want CR_RGB_BIT. */ stub.haveNativeOpenGL = GL_FALSE; stub.spu = NULL; stub.appDrawCursor = 0; stub.minChromiumWindowWidth = 0; stub.minChromiumWindowHeight = 0; stub.maxChromiumWindowWidth = 0; stub.maxChromiumWindowHeight = 0; stub.matchChromiumWindowCount = 0; stub.matchChromiumWindowID = NULL; stub.matchWindowTitle = NULL; stub.ignoreFreeglutMenus = 0; stub.threadSafe = GL_FALSE; stub.trackWindowSize = 0; stub.trackWindowPos = 0; stub.trackWindowVisibility = 0; stub.trackWindowVisibleRgn = 0; stub.mothershipPID = 0; stub.spu_dir = NULL; stub.freeContextNumber = MAGIC_CONTEXT_BASE; stub.contextTable = crAllocHashtable(); #ifndef RT_OS_WINDOWS # ifdef CHROMIUM_THREADSAFE if (!g_stubIsCurrentContextTSDInited) { crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor); g_stubIsCurrentContextTSDInited = true; } # endif #endif stubSetCurrentContext(NULL); stub.windowTable = crAllocHashtable(); #ifdef CR_NEWWINTRACK stub.bShutdownSyncThread = false; stub.hSyncThread = NIL_RTTHREAD; #endif defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo)); defaultWin->type = CHROMIUM; defaultWin->spuWindow = 0; /* window 0 always exists */ #ifdef WINDOWS defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE; #elif defined(GLX) defaultWin->pVisibleRegions = NULL; defaultWin->cVisibleRegions = 0; #endif crHashtableAdd(stub.windowTable, 0, defaultWin); #if 1 atexit(stubExitHandler); signal(SIGTERM, stubSignalHandler); signal(SIGINT, stubSignalHandler); #ifndef WINDOWS signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */ #endif #else (void) stubExitHandler; (void) stubSignalHandler; #endif }
/* Windows crap */ BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { CRNetServer ns; #ifdef CHROMIUM_THREADSAFE crInitTSD(&g_stubCurrentContextTSD); #endif crInitMutex(&stub_init_mutex); #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerRegister(); #endif crNetInit(NULL, NULL); ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerUnregister(); #endif return FALSE; } else crNetFreeConnection(ns.conn); break; } case DLL_PROCESS_DETACH: { /* do exactly the same thing as for DLL_THREAD_DETACH since * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } stubSPUSafeTearDown(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&g_stubCurrentContextTSD); #endif #ifdef VDBG_VEHANDLER vboxVDbgVEHandlerUnregister(); #endif break; } case DLL_THREAD_ATTACH: { if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxAttachThread(); } break; } case DLL_THREAD_DETACH: { stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } break; } default: break; } return TRUE; }
GLboolean stubMakeCurrent( WindowInfo *window, ContextInfo *context ) { GLboolean retVal; /* * Get WindowInfo and ContextInfo pointers. */ if (!context || !window) { ContextInfo * currentContext = stubGetCurrentContext(); if (currentContext) currentContext->currentDrawable = NULL; if (context) context->currentDrawable = NULL; stubSetCurrentContext(NULL); return GL_TRUE; /* OK */ } #ifdef CHROMIUM_THREADSAFE stubCheckMultithread(); #endif if (context->type == UNDECIDED) { /* Here's where we really create contexts */ #ifdef CHROMIUM_THREADSAFE crLockMutex(&stub.mutex); #endif if (stubCheckUseChromium(window)) { GLint spuConnection = 0; if (!stubCtxCreate(context)) { crWarning("stubCtxCreate failed"); return GL_FALSE; } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) spuConnection = context->spuConnection; #endif if (window->spuWindow == -1) { /*crDebug("(1)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate(spuConnection, window->dpyName, context->visBits ); #ifdef CR_NEWWINTRACK window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID(spuConnection); #endif } } else { /* * Create a native OpenGL context. */ if (!InstantiateNativeContext(window, context)) { #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&stub.mutex); #endif return 0; /* false */ } context->type = NATIVE; } #ifdef CHROMIUM_THREADSAFE crUnlockMutex(&stub.mutex); #endif } if (context->type == NATIVE) { /* * Native OpenGL MakeCurrent(). */ #ifdef WINDOWS retVal = (GLboolean) stub.wsInterface.wglMakeCurrent( window->drawable, context->hglrc ); #elif defined(Darwin) // XXX \todo We need to differentiate between these two.. retVal = ( stub.wsInterface.CGLSetSurface(context->cglc, window->connection, window->drawable, window->surface) == noErr ); retVal = ( stub.wsInterface.CGLSetCurrentContext(context->cglc) == noErr ); #elif defined(GLX) retVal = (GLboolean) stub.wsInterface.glXMakeCurrent( window->dpy, window->drawable, context->glxContext ); #endif } else { /* * SPU chain MakeCurrent(). */ CRASSERT(context->type == CHROMIUM); CRASSERT(context->spuContext >= 0); /*if (context->currentDrawable && context->currentDrawable != window) crDebug("Rebinding context %p to a different window", context);*/ if (window->type == NATIVE) { crWarning("Can't rebind a chromium context to a native window\n"); retVal = 0; } else { if (window->spuWindow == -1) { /*crDebug("(2)stubMakeCurrent ctx=%p(%i) window=%p(%i)", context, context->spuContext, window, window->spuWindow);*/ window->spuWindow = stub.spu->dispatch_table.VBoxWindowCreate( #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) context->spuConnection, #else 0, #endif window->dpyName, context->visBits ); #ifdef CR_NEWWINTRACK window->u32ClientID = stub.spu->dispatch_table.VBoxPackGetInjectID( # if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) context->spuConnection # else 0 # endif ); #endif if (context->currentDrawable && context->currentDrawable->type==CHROMIUM && context->currentDrawable->pOwner==context) { #ifdef WINDOWS if (context->currentDrawable->hWnd!=WindowFromDC(context->currentDrawable->drawable)) { stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->hWnd); } #else Window root; int x, y; unsigned int border, depth, w, h; XLOCK(context->currentDrawable->dpy); if (!XGetGeometry(context->currentDrawable->dpy, context->currentDrawable->drawable, &root, &x, &y, &w, &h, &border, &depth)) { stubDestroyWindow(CR_CTX_CON(context), (GLint)context->currentDrawable->drawable); } XUNLOCK(context->currentDrawable->dpy); #endif } } if (window->spuWindow != (GLint)window->drawable) stub.spu->dispatch_table.MakeCurrent( window->spuWindow, (GLint) window->drawable, context->spuContext ); else stub.spu->dispatch_table.MakeCurrent( window->spuWindow, 0, /* native window handle */ context->spuContext ); retVal = 1; } } window->type = context->type; window->pOwner = context; context->currentDrawable = window; stubSetCurrentContext(context); if (retVal) { /* Now, if we've transitions from Chromium to native rendering, or * vice versa, we have to change all the OpenGL entrypoint pointers. */ if (context->type == NATIVE) { /* Switch to native API */ /*printf(" Switching to native API\n");*/ stubSetDispatch(&stub.nativeDispatch); } else if (context->type == CHROMIUM) { /* Switch to stub (SPU) API */ /*printf(" Switching to spu API\n");*/ stubSetDispatch(&stub.spuDispatch); } else { /* no API switch needed */ } } if (!window->width && window->type == CHROMIUM) { /* One time window setup */ int x, y; unsigned int winW, winH; stubGetWindowGeometry( window, &x, &y, &winW, &winH ); /* If we're not using GLX/WGL (no app window) we'll always get * a width and height of zero here. In that case, skip the viewport * call since we're probably using a tilesort SPU with fake_window_dims * which the tilesort SPU will use for the viewport. */ window->width = winW; window->height = winH; #if defined(WINDOWS) && defined(VBOX_WITH_WDDM) if (stubIsWindowVisible(window)) #endif { if (stub.trackWindowSize) stub.spuDispatch.WindowSize( window->spuWindow, winW, winH ); if (stub.trackWindowPos) stub.spuDispatch.WindowPosition(window->spuWindow, x, y); if (winW > 0 && winH > 0) stub.spu->dispatch_table.Viewport( 0, 0, winW, winH ); } #ifdef VBOX_WITH_WDDM if (stub.trackWindowVisibleRgn) stub.spu->dispatch_table.WindowVisibleRegion(window->spuWindow, 0, NULL); #endif } /* Update window mapping state. * Basically, this lets us hide render SPU windows which correspond * to unmapped application windows. Without this, "pertly" (for example) * opens *lots* of temporary windows which otherwise clutter the screen. */ if (stub.trackWindowVisibility && window->type == CHROMIUM && window->drawable) { const int mapped = stubIsWindowVisible(window); if (mapped != window->mapped) { crDebug("Dispatched: WindowShow(%i, %i)", window->spuWindow, mapped); stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped); window->mapped = mapped; } } return retVal; }
/* Windows crap */ BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved) { (void) lpvReserved; switch (fdwReason) { case DLL_PROCESS_ATTACH: { CRNetServer ns; const char * env; #if defined(DEBUG_misha) HMODULE hCrUtil; char aName[MAX_PATH]; GetModuleFileNameA(hDLLInst, aName, RT_ELEMENTS(aName)); crDbgCmdSymLoadPrint(aName, hDLLInst); hCrUtil = GetModuleHandleA("VBoxOGLcrutil.dll"); Assert(hCrUtil); crDbgCmdSymLoadPrint("VBoxOGLcrutil.dll", hCrUtil); #endif #ifdef CHROMIUM_THREADSAFE crInitTSD(&g_stubCurrentContextTSD); #endif crInitMutex(&stub_init_mutex); #ifdef VDBG_VEHANDLER env = crGetenv("CR_DBG_VEH_ENABLE"); g_VBoxVehEnable = crStrParseI32(env, # ifdef DEBUG_misha 1 # else 0 # endif ); if (g_VBoxVehEnable) { char procName[1024]; size_t cProcName; size_t cChars; env = crGetenv("CR_DBG_VEH_FLAGS"); g_VBoxVehFlags = crStrParseI32(env, 0 # ifdef DEBUG_misha | VBOXVEH_F_BREAK # else | VBOXVEH_F_DUMP # endif ); env = crGetenv("CR_DBG_VEH_DUMP_DIR"); if (!env) env = VBOXMD_DUMP_DIR_DEFAULT; g_cVBoxMdFilePrefixLen = strlen(env); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) <= g_cVBoxMdFilePrefixLen + 26 + (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR)) { g_cVBoxMdFilePrefixLen = 0; env = ""; } mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix, g_cVBoxMdFilePrefixLen + 1, env, _TRUNCATE); Assert(cChars == g_cVBoxMdFilePrefixLen + 1); g_cVBoxMdFilePrefixLen = cChars - 1; if (g_cVBoxMdFilePrefixLen && g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen - 1] != L'\\') g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'\\'; memcpy(g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, VBOXMD_DUMP_NAME_PREFIX_W, sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)); g_cVBoxMdFilePrefixLen += (sizeof (VBOXMD_DUMP_NAME_PREFIX_W) - sizeof (WCHAR)) / sizeof (WCHAR); crGetProcName(procName, RT_ELEMENTS(procName)); cProcName = strlen(procName); if (RT_ELEMENTS(g_aszwVBoxMdFilePrefix) > g_cVBoxMdFilePrefixLen + cProcName + 1 + 26) { mbstowcs_s(&cChars, g_aszwVBoxMdFilePrefix + g_cVBoxMdFilePrefixLen, cProcName + 1, procName, _TRUNCATE); Assert(cChars == cProcName + 1); g_cVBoxMdFilePrefixLen += cChars - 1; g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen++] = L'_'; } /* sanity */ g_aszwVBoxMdFilePrefix[g_cVBoxMdFilePrefixLen] = L'\0'; env = crGetenv("CR_DBG_VEH_DUMP_TYPE"); g_enmVBoxMdDumpType = crStrParseI32(env, MiniDumpNormal | MiniDumpWithDataSegs | MiniDumpWithFullMemory | MiniDumpWithHandleData //// | MiniDumpFilterMemory //// | MiniDumpScanMemory // | MiniDumpWithUnloadedModules //// | MiniDumpWithIndirectlyReferencedMemory //// | MiniDumpFilterModulePaths // | MiniDumpWithProcessThreadData // | MiniDumpWithPrivateReadWriteMemory //// | MiniDumpWithoutOptionalData // | MiniDumpWithFullMemoryInfo // | MiniDumpWithThreadInfo // | MiniDumpWithCodeSegs // | MiniDumpWithFullAuxiliaryState // | MiniDumpWithPrivateWriteCopyMemory // | MiniDumpIgnoreInaccessibleMemory // | MiniDumpWithTokenInformation //// | MiniDumpWithModuleHeaders //// | MiniDumpFilterTriage ); vboxVDbgVEHandlerRegister(); } #endif crNetInit(NULL, NULL); ns.name = "vboxhgcm://host:0"; ns.buffer_size = 1024; crNetServerConnect(&ns #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) , NULL #endif ); if (!ns.conn) { crDebug("Failed to connect to host (is guest 3d acceleration enabled?), aborting ICD load."); #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif return FALSE; } else { crNetFreeConnection(ns.conn); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiInit(); #endif break; } case DLL_PROCESS_DETACH: { /* do exactly the same thing as for DLL_THREAD_DETACH since * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */ stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } #if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST) VBoxCrHgsmiTerm(); #endif stubSPUSafeTearDown(); #ifdef CHROMIUM_THREADSAFE crFreeTSD(&g_stubCurrentContextTSD); #endif #ifdef VDBG_VEHANDLER if (g_VBoxVehEnable) vboxVDbgVEHandlerUnregister(); #endif break; } case DLL_THREAD_ATTACH: { if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxAttachThread(); } break; } case DLL_THREAD_DETACH: { stubSetCurrentContext(NULL); if (stub_initialized) { CRASSERT(stub.spu); stub.spu->dispatch_table.VBoxDetachThread(); } break; } default: break; } return TRUE; }