/* * Updates geometry info for given spu window. * Returns GL_TRUE if it changed since last call, GL_FALSE otherwise. * bForceUpdate - forces dispatching of geometry info even if it's unchanged */ GLboolean stubUpdateWindowGeometry(WindowInfo *pWindow, GLboolean bForceUpdate) { int winX, winY; unsigned int winW, winH; GLboolean res = GL_FALSE; CRASSERT(pWindow); stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH); /* @todo remove "if (winW && winH)"?*/ if (winW && winH) { if (stub.trackWindowSize) { if (bForceUpdate || winW != pWindow->width || winH != pWindow->height) { crDebug("Dispatched WindowSize (%i)", pWindow->spuWindow); stub.spuDispatch.WindowSize(pWindow->spuWindow, winW, winH); pWindow->width = winW; pWindow->height = winH; res = GL_TRUE; } } if (stub.trackWindowPos) { if (bForceUpdate || winX != pWindow->x || winY != pWindow->y) { crDebug("Dispatched WindowPosition (%i)", pWindow->spuWindow); stub.spuDispatch.WindowPosition(pWindow->spuWindow, winX, winY); pWindow->x = winX; pWindow->y = winY; res = GL_TRUE; } } } return res; }
static void GetCursorPosition( const WindowInfo *window, int pos[2] ) { RECT rect; POINT point; GLint size[2], x, y; unsigned int NativeHeight, NativeWidth, ChromiumHeight, ChromiumWidth; float WidthRatio, HeightRatio; static int DebugFlag = 0; // apparently the "window" parameter passed to this // function contains the native window information HWND NATIVEhwnd = WindowFromDC( window->drawable ); // get the native window's height and width stubGetWindowGeometry(window, &x, &y, &NativeWidth, &NativeHeight); // get the spu window's height and width stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, window->spuWindow, GL_INT, 2, size); ChromiumWidth = size[0]; ChromiumHeight = size[1]; // get the ratio of the size of the native window to the cr window WidthRatio = (float)ChromiumWidth / (float)NativeWidth; HeightRatio = (float)ChromiumHeight / (float)NativeHeight; // output some debug information at the beginning if(DebugFlag) { DebugFlag = 0; crDebug("Native Window Handle = %d", NATIVEhwnd); crDebug("Native Width = %i", NativeWidth); crDebug("Native Height = %i", NativeHeight); crDebug("Chromium Width = %i", ChromiumWidth); crDebug("Chromium Height = %i", ChromiumHeight); } if (NATIVEhwnd) { GetClientRect( NATIVEhwnd, &rect ); GetCursorPos (&point); // make sure these coordinates are relative to the native window, // not the whole desktop ScreenToClient(NATIVEhwnd, &point); // calculate the new position of the virtual cursor pos[0] = (int)(point.x * WidthRatio); pos[1] = (int)((NativeHeight - point.y) * HeightRatio); } else { pos[0] = 0; pos[1] = 0; } }
static void SPU_APIENTRY trapScissor(GLint x, GLint y, GLsizei w, GLsizei h) { int winX, winY; unsigned int winW, winH; WindowInfo *pWindow; ContextInfo *context = stubGetCurrentContext(); pWindow = context->currentDrawable; stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH); origScissor(0, 0, winW, winH); }
/** * As above, but for glViewport. Most apps call glViewport before * glClear when a window is resized. */ static void SPU_APIENTRY trapViewport(GLint x, GLint y, GLsizei w, GLsizei h) { stubCheckWindowsState(); /* call the original SPU glViewport function */ if (!stub.viewportHack) { origViewport(x, y, w, h); } else { ContextInfo *context = stubGetCurrentContext(); int winX, winY; unsigned int winW, winH; WindowInfo *pWindow; pWindow = context->currentDrawable; stubGetWindowGeometry(pWindow, &winX, &winY, &winW, &winH); origViewport(0, 0, winW, winH); } }
/** *Return current cursor position in local window coords. */ static void GetCursorPosition( const WindowInfo *window, int pos[2] ) { int rootX, rootY; Window root, child; unsigned int mask; int x, y; Bool q = XQueryPointer(window->dpy, window->drawable, &root, &child, &rootX, &rootY, &pos[0], &pos[1], &mask); if (q) { unsigned int w, h; stubGetWindowGeometry( window, &x, &y, &w, &h ); /* invert Y */ pos[1] = (int) h - pos[1] - 1; } else { pos[0] = pos[1] = 0; } }
GLboolean stubMakeCurrent( WindowInfo *window, ContextInfo *context ) { GLboolean retVal; /* * Get WindowInfo and ContextInfo pointers. */ if (!context || !window) { if (stub.currentContext) stub.currentContext->currentDrawable = NULL; if (context) context->currentDrawable = NULL; stub.currentContext = 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)) { /* * Create a Chromium context. */ #if defined(GLX) || defined(DARWIN) GLint spuShareCtx = context->share ? context->share->spuContext : 0; #else GLint spuShareCtx = 0; #endif CRASSERT(stub.spu); CRASSERT(stub.spu->dispatch_table.CreateContext); context->type = CHROMIUM; context->spuContext = stub.spu->dispatch_table.CreateContext( context->dpyName, context->visBits, spuShareCtx ); if (window->spuWindow == -1) window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits ); } 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) crWarning("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) window->spuWindow = stub.spu->dispatch_table.WindowCreate( window->dpyName, context->visBits ); 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; context->currentDrawable = window; stub.currentContext = 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 (stub.trackWindowSize) stub.spuDispatch.WindowSize( window->spuWindow, winW, winH ); if (winW > 0 && winH > 0) stub.spu->dispatch_table.Viewport( 0, 0, winW, winH ); } /* Update window mapping state. * Basically, this lets us hide render SPU windows which correspond * to unmapped application windows. Without this, perfly (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) { stub.spu->dispatch_table.WindowShow(window->spuWindow, mapped); window->mapped = mapped; } } return retVal; }
/** * This function is called by MakeCurrent() and determines whether or * not a new rendering context should be bound to Chromium or the native * OpenGL. * \return GL_FALSE if native OpenGL should be used, or GL_TRUE if Chromium * should be used. */ static GLboolean stubCheckUseChromium( WindowInfo *window ) { int x, y; unsigned int w, h; /* If the provided window is CHROMIUM, we're clearly intended * to create a CHROMIUM context. */ if (window->type == CHROMIUM) return GL_TRUE; if (stub.ignoreFreeglutMenus) { const char *glutMenuTitle = "freeglut menu"; char title[1000]; GetWindowTitle(window, title); if (crStrcmp(title, glutMenuTitle) == 0) { crDebug("GL faker: Ignoring freeglut menu window"); return GL_FALSE; } } /* If the user's specified a window count for Chromium, see if * this window satisfies that criterium. */ stub.matchChromiumWindowCounter++; if (stub.matchChromiumWindowCount > 0) { if (stub.matchChromiumWindowCounter != stub.matchChromiumWindowCount) { crDebug("Using native GL, app window doesn't meet match_window_count"); return GL_FALSE; } } /* If the user's specified a window list to ignore, see if this * window satisfies that criterium. */ if (stub.matchChromiumWindowID) { GLuint i; for (i = 0; i <= stub.numIgnoreWindowID; i++) { if (stub.matchChromiumWindowID[i] == stub.matchChromiumWindowCounter) { crDebug("Ignore window ID %d, using native GL", stub.matchChromiumWindowID[i]); return GL_FALSE; } } } /* If the user's specified a minimum window size for Chromium, see if * this window satisfies that criterium. */ if (stub.minChromiumWindowWidth > 0 && stub.minChromiumWindowHeight > 0) { stubGetWindowGeometry( window, &x, &y, &w, &h ); if (w >= stub.minChromiumWindowWidth && h >= stub.minChromiumWindowHeight) { /* Check for maximum sized window now too */ if (stub.maxChromiumWindowWidth && stub.maxChromiumWindowHeight) { if (w < stub.maxChromiumWindowWidth && h < stub.maxChromiumWindowHeight) return GL_TRUE; else return GL_FALSE; } return GL_TRUE; } crDebug("Using native GL, app window doesn't meet minimum_window_size"); return GL_FALSE; } else if (stub.matchWindowTitle) { /* If the user's specified a window title for Chromium, see if this * window satisfies that criterium. */ GLboolean wildcard = GL_FALSE; char title[1000]; char *titlePattern; int len; /* check for leading '*' wildcard */ if (stub.matchWindowTitle[0] == '*') { titlePattern = crStrdup( stub.matchWindowTitle + 1 ); wildcard = GL_TRUE; } else { titlePattern = crStrdup( stub.matchWindowTitle ); } /* check for trailing '*' wildcard */ len = crStrlen(titlePattern); if (len > 0 && titlePattern[len - 1] == '*') { titlePattern[len - 1] = '\0'; /* terminate here */ wildcard = GL_TRUE; } GetWindowTitle( window, title ); if (title[0]) { if (wildcard) { if (crStrstr(title, titlePattern)) { crFree(titlePattern); return GL_TRUE; } } else if (crStrcmp(title, titlePattern) == 0) { crFree(titlePattern); return GL_TRUE; } } crFree(titlePattern); crDebug("Using native GL, app window title doesn't match match_window_title string (\"%s\" != \"%s\")", title, stub.matchWindowTitle); return GL_FALSE; } /* Window title and size don't matter */ CRASSERT(stub.minChromiumWindowWidth == 0); CRASSERT(stub.minChromiumWindowHeight == 0); CRASSERT(stub.matchWindowTitle == NULL); /* User hasn't specified a width/height or window title. * We'll use chromium for this window (and context) if no other is. */ return GL_TRUE; /* use Chromium! */ }
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; }