From 7051aadf7e01ecdeebc8e9cf98eaaff758c31916 Mon Sep 17 00:00:00 2001
From: Sam Spilsbury <smspillaz@gmail.com>
Date: Mon, 18 Feb 2013 08:48:26 +0800
Subject: [PATCH] Remove the second damage display connection, and instead
query the server for damage directly. This has the same cost as the old
method and does not rely on event delivery or a second connection.
---
src/VBox/Additions/common/crOpenGL/context.c | 5 --
src/VBox/Additions/common/crOpenGL/glx.c | 101 +++++++++++++--------------
src/VBox/Additions/common/crOpenGL/stub.h | 1 -
3 files changed, 50 insertions(+), 57 deletions(-)
diff --git a/src/VBox/Additions/common/crOpenGL/context.c b/src/VBox/Additions/common/crOpenGL/context.c
index e4c5667..43b479f 100644
|
a
|
b
|
stubDestroyContextLocked( ContextInfo *context )
|
| 332 | 332 | |
| 333 | 333 | #ifdef GLX |
| 334 | 334 | crFreeHashtable(context->pGLXPixmapsHash, crFree); |
| 335 | | if (context->damageDpy) |
| 336 | | { |
| 337 | | XCloseDisplay(context->damageDpy); |
| 338 | | } |
| 339 | 335 | #endif |
| 340 | 336 | |
| 341 | 337 | crMemZero(context, sizeof(ContextInfo)); /* just to be safe */ |
| … |
… |
stubNewContext( const char *dpyName, GLint visBits, ContextType type,
|
| 409 | 405 | #ifdef GLX |
| 410 | 406 | context->pGLXPixmapsHash = crAllocHashtable(); |
| 411 | 407 | context->damageInitFailed = GL_FALSE; |
| 412 | | context->damageDpy = NULL; |
| 413 | 408 | context->damageEventsBase = 0; |
| 414 | 409 | #endif |
| 415 | 410 | |
diff --git a/src/VBox/Additions/common/crOpenGL/glx.c b/src/VBox/Additions/common/crOpenGL/glx.c
index 4e8900a..9bf0f0c 100644
|
a
|
b
|
DECLEXPORT(void) VBOXGLXTAG(glXDestroyPixmap)(Display *dpy, GLXPixmap pixmap)
|
| 1777 | 1777 | if (parms.pGlxPixmap->hDamage>0) |
| 1778 | 1778 | { |
| 1779 | 1779 | //crDebug("Destroy: Damage for drawable 0x%x, handle 0x%x", (unsigned int) pixmap, (unsigned int) parms.pGlxPixmap->damage); |
| 1780 | | XDamageDestroy(parms.pCtx->damageDpy, parms.pGlxPixmap->hDamage); |
| | 1780 | XDamageDestroy(dpy, parms.pGlxPixmap->hDamage); |
| 1781 | 1781 | } |
| 1782 | 1782 | |
| 1783 | 1783 | if (parms.pGlxPixmap->pDamageRegion) |
| … |
… |
static void stubInitXSharedMemory(Display *dpy)
|
| 2167 | 2167 | #endif |
| 2168 | 2168 | } |
| 2169 | 2169 | |
| 2170 | | static void stubInitXDamageExtension(ContextInfo *pContext) |
| | 2170 | static void stubInitXDamageExtension(Display *dpy, ContextInfo *pContext) |
| 2171 | 2171 | { |
| 2172 | 2172 | int erb, vma, vmi; |
| 2173 | 2173 | |
| 2174 | 2174 | CRASSERT(pContext); |
| 2175 | 2175 | |
| 2176 | | if (pContext->damageInitFailed || pContext->damageDpy) |
| | 2176 | if (pContext->damageInitFailed) |
| 2177 | 2177 | return; |
| 2178 | 2178 | |
| 2179 | 2179 | pContext->damageInitFailed = True; |
| 2180 | 2180 | |
| 2181 | | /* Open second xserver connection to make sure we'd receive all the xdamage messages |
| 2182 | | * and those wouldn't be eaten by application even queue */ |
| 2183 | | pContext->damageDpy = XOpenDisplay(DisplayString(pContext->dpy)); |
| 2184 | | |
| 2185 | | if (!pContext->damageDpy) |
| 2186 | | { |
| 2187 | | crWarning("XDamage: Can't connect to display %s", DisplayString(pContext->dpy)); |
| 2188 | | return; |
| 2189 | | } |
| 2190 | | |
| 2191 | | if (!XDamageQueryExtension(pContext->damageDpy, &pContext->damageEventsBase, &erb) |
| 2192 | | || !XDamageQueryVersion(pContext->damageDpy, &vma, &vmi)) |
| | 2181 | if (!XDamageQueryExtension(dpy, &pContext->damageEventsBase, &erb) |
| | 2182 | || !XDamageQueryVersion(dpy, &vma, &vmi)) |
| 2193 | 2183 | { |
| 2194 | 2184 | crWarning("XDamage not found or old version (%i.%i), going to run *very* slow", vma, vmi); |
| 2195 | | XCloseDisplay(pContext->damageDpy); |
| 2196 | | pContext->damageDpy = NULL; |
| 2197 | 2185 | return; |
| 2198 | 2186 | } |
| 2199 | 2187 | |
| … |
… |
static void stubInitXDamageExtension(ContextInfo *pContext)
|
| 2201 | 2189 | pContext->damageInitFailed = False; |
| 2202 | 2190 | } |
| 2203 | 2191 | |
| 2204 | | static void stubCheckXDamageCB(unsigned long key, void *data1, void *data2) |
| | 2192 | static void stubFetchDamageOnDrawable (Display *dpy, GLX_Pixmap_t *pGlxPixmap) |
| 2205 | 2193 | { |
| 2206 | | GLX_Pixmap_t *pGlxPixmap = (GLX_Pixmap_t *) data1; |
| 2207 | | XDamageNotifyEvent *e = (XDamageNotifyEvent *) data2; |
| | 2194 | Damage damage = pGlxPixmap->hDamage; |
| 2208 | 2195 | |
| 2209 | | if (pGlxPixmap->hDamage==e->damage) |
| | 2196 | if (damage) |
| 2210 | 2197 | { |
| | 2198 | XRectangle *returnRects; |
| | 2199 | int nReturnRects; |
| 2211 | 2200 | /*crDebug("Event: Damage for pixmap 0x%lx(drawable 0x%x), handle 0x%x (level=%i) [%i,%i,%i,%i]", |
| 2212 | 2201 | key, (unsigned int) e->drawable, (unsigned int) e->damage, (int) e->level, |
| 2213 | 2202 | e->area.x, e->area.y, e->area.width, e->area.height);*/ |
| 2214 | 2203 | |
| | 2204 | /* Get the damage region as a server region */ |
| | 2205 | XserverRegion serverDamageRegion = XFixesCreateRegion (dpy, NULL, 0); |
| | 2206 | |
| | 2207 | /* Unite damage region with server region and clear damage region */ |
| | 2208 | XDamageSubtract (dpy, |
| | 2209 | damage, |
| | 2210 | None, /* subtract all damage from this region */ |
| | 2211 | serverDamageRegion /* save in serverDamageRegion */); |
| | 2212 | |
| | 2213 | /* Fetch damage rectangles */ |
| | 2214 | returnRects = XFixesFetchRegion (dpy, serverDamageRegion, &nReturnRects); |
| | 2215 | |
| | 2216 | /* Delete region */ |
| | 2217 | XFixesDestroyRegion (dpy, serverDamageRegion); |
| | 2218 | |
| 2215 | 2219 | if (pGlxPixmap->pDamageRegion) |
| 2216 | 2220 | { |
| 2217 | 2221 | /* If it's dirty and regions are empty, it marked for full update, so do nothing.*/ |
| 2218 | 2222 | if (!pGlxPixmap->bPixmapImageDirty || !XEmptyRegion(pGlxPixmap->pDamageRegion)) |
| 2219 | 2223 | { |
| 2220 | | if (CR_MAX_DAMAGE_REGIONS_TRACKED <= pGlxPixmap->pDamageRegion->numRects) |
| | 2224 | int i = 0; |
| | 2225 | for (; i < nReturnRects; ++i) |
| 2221 | 2226 | { |
| 2222 | | /* Mark for full update */ |
| 2223 | | EMPTY_REGION(pGlxPixmap->pDamageRegion); |
| 2224 | | } |
| 2225 | | else |
| 2226 | | { |
| 2227 | | /* Add to damage regions */ |
| 2228 | | XUnionRectWithRegion(&e->area, pGlxPixmap->pDamageRegion, pGlxPixmap->pDamageRegion); |
| | 2227 | if (CR_MAX_DAMAGE_REGIONS_TRACKED <= pGlxPixmap->pDamageRegion->numRects) |
| | 2228 | { |
| | 2229 | /* Mark for full update */ |
| | 2230 | EMPTY_REGION(pGlxPixmap->pDamageRegion); |
| | 2231 | } |
| | 2232 | else |
| | 2233 | { |
| | 2234 | /* Add to damage regions */ |
| | 2235 | XUnionRectWithRegion(&returnRects[i], pGlxPixmap->pDamageRegion, pGlxPixmap->pDamageRegion); |
| | 2236 | } |
| 2229 | 2237 | } |
| 2230 | 2238 | } |
| 2231 | 2239 | } |
| 2232 | 2240 | |
| | 2241 | XFree (returnRects); |
| | 2242 | |
| 2233 | 2243 | pGlxPixmap->bPixmapImageDirty = True; |
| 2234 | 2244 | } |
| 2235 | 2245 | } |
| … |
… |
static GLX_Pixmap_t* stubInitGlxPixmap(GLX_Pixmap_t* pCreateInfoPixmap, Display
|
| 2332 | 2342 | } |
| 2333 | 2343 | XUNLOCK(dpy); |
| 2334 | 2344 | |
| 2335 | | stubInitXDamageExtension(pContext); |
| | 2345 | stubInitXDamageExtension(dpy, pContext); |
| 2336 | 2346 | |
| 2337 | 2347 | /* If there's damage extension, then get handle for damage events related to this pixmap */ |
| 2338 | | if (pContext->damageDpy) |
| | 2348 | if (!pContext->damageInitFailed) |
| 2339 | 2349 | { |
| 2340 | | pGlxPixmap->hDamage = XDamageCreate(pContext->damageDpy, (Pixmap)draw, XDamageReportRawRectangles); |
| | 2350 | pGlxPixmap->hDamage = XDamageCreate(dpy, (Pixmap)draw, XDamageReportNonEmpty); |
| 2341 | 2351 | /*crDebug("Create: Damage for drawable 0x%x, handle 0x%x (level=%i)", |
| 2342 | 2352 | (unsigned int) draw, (unsigned int) pGlxPixmap->damage, (int) XDamageReportRawRectangles);*/ |
| 2343 | 2353 | pGlxPixmap->pDamageRegion = XCreateRegion(); |
| … |
… |
DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw,
|
| 2529 | 2539 | } |
| 2530 | 2540 | |
| 2531 | 2541 | /* If there's damage extension, then process incoming events as we need the information right now */ |
| 2532 | | if (context->damageDpy) |
| 2533 | | { |
| 2534 | | /* Sync connections, note that order of syncs is important here. |
| 2535 | | * First make sure client commands are finished, then make sure we get all the damage events back*/ |
| 2536 | | XLOCK(dpy); |
| 2537 | | XSync(dpy, False); |
| 2538 | | XUNLOCK(dpy); |
| 2539 | | XSync(context->damageDpy, False); |
| 2540 | 2542 | |
| 2541 | | while (XPending(context->damageDpy)) |
| 2542 | | { |
| 2543 | | XEvent event; |
| 2544 | | XNextEvent(context->damageDpy, &event); |
| 2545 | | if (event.type==context->damageEventsBase+XDamageNotify) |
| 2546 | | { |
| 2547 | | crHashtableWalk(context->pGLXPixmapsHash, stubCheckXDamageCB, &event); |
| 2548 | | } |
| 2549 | | } |
| 2550 | | } |
| | 2543 | /* Sync connections, note that order of syncs is important here. |
| | 2544 | * First make sure client commands are finished, then make sure we get all the damage events back*/ |
| | 2545 | XLOCK(dpy); |
| | 2546 | XSync(dpy, False); |
| | 2547 | XUNLOCK(dpy); |
| | 2548 | |
| | 2549 | stubFetchDamageOnDrawable(dpy, pGlxPixmap); |
| 2551 | 2550 | |
| 2552 | 2551 | /* No shared memory? Rollback to use slow x protocol then */ |
| 2553 | 2552 | if (stub.xshmSI.shmid<0) |
| … |
… |
DECLEXPORT(void) VBOXGLXTAG(glXBindTexImageEXT)(Display *dpy, GLXDrawable draw,
|
| 2594 | 2593 | else /* Use shm to get pixmap data */ |
| 2595 | 2594 | { |
| 2596 | 2595 | /* Check if we have damage extension */ |
| 2597 | | if (context->damageDpy) |
| | 2596 | if (!context->damageInitFailed) |
| 2598 | 2597 | { |
| 2599 | 2598 | if (pGlxPixmap->bPixmapImageDirty) |
| 2600 | 2599 | { |
diff --git a/src/VBox/Additions/common/crOpenGL/stub.h b/src/VBox/Additions/common/crOpenGL/stub.h
index aff7bbb..acbe02d 100644
|
a
|
b
|
struct context_info_t
|
| 142 | 142 | GLXContext glxContext; |
| 143 | 143 | CRHashTable *pGLXPixmapsHash; |
| 144 | 144 | Bool damageInitFailed; |
| 145 | | Display *damageDpy; /* second display connection to read xdamage extension data */ |
| 146 | 145 | int damageEventsBase; |
| 147 | 146 | #endif |
| 148 | 147 | }; |