static bool stubSystemWindowExist(WindowInfo *pWindow) { #ifdef WINDOWS if (pWindow->hWnd!=WindowFromDC(pWindow->drawable)) { return false; } #else Window root; int x, y; unsigned int border, depth, w, h; Display *dpy; dpy = stubGetWindowDisplay(pWindow); XLOCK(dpy); if (!XGetGeometry(dpy, pWindow->drawable, &root, &x, &y, &w, &h, &border, &depth)) { XUNLOCK(dpy); return false; } XUNLOCK(dpy); #endif return true; }
void stubGetWindowGeometry(WindowInfo *window, int *x, int *y, unsigned int *w, unsigned int *h) { Window root, child; unsigned int border, depth; Display *dpy; dpy = stubGetWindowDisplay(window); //@todo: Performing those checks is expensive operation, especially for simple apps with high FPS. // Disabling those triples glxgears fps, thus using xevents instead of per frame polling is much more preferred. //@todo: Check similar on windows guests, though doubtful as there're no XSync like calls on windows. if (window && dpy) { XLOCK(dpy); } if (!window || !dpy || !window->drawable || !XGetGeometry(dpy, window->drawable, &root, x, y, w, h, &border, &depth) || !XTranslateCoordinates(dpy, window->drawable, root, 0, 0, x, y, &child)) { crWarning("Failed to get windows geometry for %p, try xwininfo", window); *x = *y = 0; *w = *h = 0; } if (window && dpy) { XUNLOCK(dpy); } }
void stubCheckXExtensions(WindowInfo *pWindow) { int evb, erb, vmi=0, vma=0; Display *dpy = stubGetWindowDisplay(pWindow); stub.bXExtensionsChecked = GL_TRUE; stub.trackWindowVisibleRgn = 0; XLOCK(dpy); if (XCompositeQueryExtension(dpy, &evb, &erb) && XCompositeQueryVersion(dpy, &vma, &vmi) && (vma>0 || vmi>=4)) { stub.bHaveXComposite = GL_TRUE; crDebug("XComposite %i.%i", vma, vmi); vma=0; vmi=0; if (XFixesQueryExtension(dpy, &evb, &erb) && XFixesQueryVersion(dpy, &vma, &vmi) && vma>=2) { crDebug("XFixes %i.%i", vma, vmi); stub.bHaveXFixes = GL_TRUE; stub.trackWindowVisibleRgn = 1; XUNLOCK(dpy); return; } else { crWarning("XFixes not found or old version (%i.%i), no VisibilityTracking", vma, vmi); } } else { crWarning("XComposite not found or old version (%i.%i), no VisibilityTracking", vma, vmi); } XUNLOCK(dpy); return; }
GLboolean stubIsWindowVisible(WindowInfo *win) { #if defined(WINDOWS) # ifdef VBOX_WITH_WDDM if (stub.bRunningUnderWDDM) return win->mapped; # endif return GL_TRUE; #elif defined(Darwin) return GL_TRUE; #elif defined(GLX) Display *dpy = stubGetWindowDisplay(win); if (dpy) { XWindowAttributes attr; XLOCK(dpy); XGetWindowAttributes(dpy, win->drawable, &attr); XUNLOCK(dpy); if (attr.map_state == IsUnmapped) { return GL_FALSE; } # if 1 return GL_TRUE; # else if (attr.override_redirect) { return GL_TRUE; } if (!stub.bXExtensionsChecked) { stubCheckXExtensions(win); } if (!stub.bHaveXComposite) { return GL_TRUE; } else { Pixmap p; crLockMutex(&stub.mutex); XLOCK(dpy); XSync(dpy, false); oldErrorHandler = XSetErrorHandler(errorHandler); /*@todo this will create new pixmap for window every call*/ p = XCompositeNameWindowPixmap(dpy, win->drawable); XSync(dpy, false); XSetErrorHandler(oldErrorHandler); XUNLOCK(dpy); switch (lastXError) { case Success: XFreePixmap(dpy, p); crUnlockMutex(&stub.mutex); return GL_FALSE; break; case BadMatch: /*Window isn't redirected*/ lastXError = Success; break; default: crWarning("Unexpected XError %i", (int)lastXError); lastXError = Success; } crUnlockMutex(&stub.mutex); return GL_TRUE; } # endif } else { /* probably created by crWindowCreate() */ return win->mapped; } #endif }
/* * Updates visible regions for given spu window. * Returns GL_TRUE if regions changed since last call, GL_FALSE otherwise. */ GLboolean stubUpdateWindowVisibileRegions(WindowInfo *pWindow) { XserverRegion xreg; int cRects, i; XRectangle *pXRects; GLint* pGLRects; Display *dpy; bool bNoUpdate = false; if (!stub.bXExtensionsChecked) { stubCheckXExtensions(pWindow); if (!stub.trackWindowVisibleRgn) { return GL_FALSE; } } dpy = stubGetWindowDisplay(pWindow); /*@todo see comment regarding size/position updates and XSync, same applies to those functions but * it seems there's no way to get even based updates for this. Or I've failed to find the appropriate extension. */ XLOCK(dpy); xreg = XCompositeCreateRegionFromBorderClip(dpy, pWindow->drawable); pXRects = XFixesFetchRegion(dpy, xreg, &cRects); XFixesDestroyRegion(dpy, xreg); XUNLOCK(dpy); /* Check for compiz main window */ if (!pWindow->pVisibleRegions && !cRects) { #ifdef VBOX_TEST_MEGOO XWindowAttributes attr; XLOCK(dpy); XSync(dpy, false); XGetWindowAttributes(dpy, pWindow->drawable, &attr); XUNLOCK(dpy); bNoUpdate = attr.override_redirect; #else bNoUpdate = true; #endif } if (!bNoUpdate && (!pWindow->pVisibleRegions || pWindow->cVisibleRegions!=cRects || (pWindow->pVisibleRegions && crMemcmp(pWindow->pVisibleRegions, pXRects, cRects * sizeof(XRectangle))))) { if (pWindow->pVisibleRegions) { XFree(pWindow->pVisibleRegions); } pWindow->pVisibleRegions = pXRects; pWindow->cVisibleRegions = cRects; pGLRects = crAlloc(4*cRects*sizeof(GLint)); if (!pGLRects) { crWarning("stubUpdateWindowVisibileRegions: failed to allocate %lu bytes", (unsigned long)(4*cRects*sizeof(GLint))); return GL_FALSE; } //crDebug("Got %i rects.", cRects); for (i=0; i<cRects; ++i) { pGLRects[4*i+0] = pXRects[i].x; pGLRects[4*i+1] = pXRects[i].y; pGLRects[4*i+2] = pXRects[i].x+pXRects[i].width; pGLRects[4*i+3] = pXRects[i].y+pXRects[i].height; //crDebug("Rect[%i]=(%i,%i,%i,%i)", i, pGLRects[4*i+0], pGLRects[4*i+1], pGLRects[4*i+2], pGLRects[4*i+3]); } crDebug("Dispatched WindowVisibleRegion (%i, cRects=%i)", pWindow->spuWindow, cRects); stub.spuDispatch.WindowVisibleRegion(pWindow->spuWindow, cRects, pGLRects); crFree(pGLRects); return GL_TRUE; } else { XFree(pXRects); } return GL_FALSE; }