forked from pool/xorg-x11-server
Stefan Dirsch
5c795d39de
Copy from home:vuntz:branches:X11:XOrg/xorg-x11-server via accept of submit request 45191 revision 2. Request was accepted with message: reviewed ok. OBS-URL: https://build.opensuse.org/request/show/45191 OBS-URL: https://build.opensuse.org/package/show/X11:XOrg/xorg-x11-server?expand=0&rev=272
2843 lines
90 KiB
Diff
2843 lines
90 KiB
Diff
commit 86ca6baee221fc691c7828b078008314ac989864
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Fri Apr 16 05:55:32 2010 -0400
|
|
|
|
glx: Track GLX 1.3 style GLX drawables under their X drawable ID as well
|
|
|
|
This ensures that the DrawableGone callback gets called as necessary
|
|
when the X drawable goes away. Otherwise, using a GLX drawable
|
|
(say, glXSwapBuffers) in indirect mode after the X drawable has been
|
|
destroyed will crash the server.
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Reviewed-by: Michel Dänzer <michel@daenzer.net>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
(cherry picked from commit f0006aa58f6cf7552a239e169ff6e7e4fda532f4)
|
|
|
|
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
|
|
index 77afbf4..04c6d40 100644
|
|
--- a/glx/glxcmds.c
|
|
+++ b/glx/glxcmds.c
|
|
@@ -161,7 +161,11 @@ validGlxDrawable(ClientPtr client, XID id, int type, int access_mode,
|
|
return FALSE;
|
|
}
|
|
|
|
+ /* If the ID of the glx drawable we looked up doesn't match the id
|
|
+ * we looked for, it's because we looked it up under the X
|
|
+ * drawable ID (see DoCreateGLXDrawable). */
|
|
if (rc == BadValue ||
|
|
+ (*drawable)->drawId != id ||
|
|
(type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) {
|
|
client->errorValue = id;
|
|
switch (type) {
|
|
@@ -1128,6 +1132,14 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
|
|
return BadAlloc;
|
|
}
|
|
|
|
+ /* Add the glx drawable under the XID of the underlying X drawable
|
|
+ * too. That way we'll get a callback in DrawableGone and can
|
|
+ * clean up properly when the drawable is destroyed. */
|
|
+ if (!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
|
|
+ pGlxDraw->destroy (pGlxDraw);
|
|
+ return BadAlloc;
|
|
+ }
|
|
+
|
|
return Success;
|
|
}
|
|
|
|
diff --git a/glx/glxext.c b/glx/glxext.c
|
|
index 59bcfbe..89e58b0 100644
|
|
--- a/glx/glxext.c
|
|
+++ b/glx/glxext.c
|
|
@@ -126,6 +126,17 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
|
|
{
|
|
__GLXcontext *c;
|
|
|
|
+ /* If this drawable was created using glx 1.3 drawable
|
|
+ * constructors, we added it as a glx drawable resource under both
|
|
+ * its glx drawable ID and it X drawable ID. Remove the other
|
|
+ * resource now so we don't a callback for freed memory. */
|
|
+ if (glxPriv->drawId != glxPriv->pDraw->id) {
|
|
+ if (xid == glxPriv->drawId)
|
|
+ FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE);
|
|
+ else
|
|
+ FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE);
|
|
+ }
|
|
+
|
|
for (c = glxAllContexts; c; c = c->next) {
|
|
if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) {
|
|
int i;
|
|
commit 0460a76b9ae25fe26f683f0cbff1e4157287cf56
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Fri Apr 16 05:55:33 2010 -0400
|
|
|
|
glx: Let the resource system destroy pixmaps
|
|
|
|
GLX pbuffers are implemented using a pixmap allocated by the server.
|
|
With the change to DRI2 to track DRI2 drawables as resources, we need to make
|
|
sure that every drawable we create a DRI2 drawable for has an XID. By
|
|
using the XID of the pbuffer, the resource system will automatically
|
|
reclaim the hidden pixmap and the DRI2 drawable when the pbuffer is
|
|
destroyed or the client exits.
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
(cherry picked from commit 22da7aa9d743deee198aaf6df5d370a446db9763)
|
|
|
|
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
|
|
index 04c6d40..087d52e 100644
|
|
--- a/glx/glxcmds.c
|
|
+++ b/glx/glxcmds.c
|
|
@@ -1101,14 +1101,6 @@ __glXDrawableInit(__GLXdrawable *drawable,
|
|
void
|
|
__glXDrawableRelease(__GLXdrawable *drawable)
|
|
{
|
|
- ScreenPtr pScreen = drawable->pDraw->pScreen;
|
|
-
|
|
- switch (drawable->type) {
|
|
- case GLX_DRAWABLE_PIXMAP:
|
|
- case GLX_DRAWABLE_PBUFFER:
|
|
- (*pScreen->DestroyPixmap)((PixmapPtr) drawable->pDraw);
|
|
- break;
|
|
- }
|
|
}
|
|
|
|
static int
|
|
@@ -1117,8 +1109,6 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
|
|
{
|
|
__GLXdrawable *pGlxDraw;
|
|
|
|
- LEGAL_NEW_RESOURCE(glxDrawableId, client);
|
|
-
|
|
if (pGlxScreen->pScreen != pDraw->pScreen)
|
|
return BadMatch;
|
|
|
|
@@ -1135,7 +1125,8 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
|
|
/* Add the glx drawable under the XID of the underlying X drawable
|
|
* too. That way we'll get a callback in DrawableGone and can
|
|
* clean up properly when the drawable is destroyed. */
|
|
- if (!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
|
|
+ if (pDraw->id != glxDrawableId &&
|
|
+ !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
|
|
pGlxDraw->destroy (pGlxDraw);
|
|
return BadAlloc;
|
|
}
|
|
@@ -1150,6 +1141,8 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
|
|
DrawablePtr pDraw;
|
|
int err;
|
|
|
|
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
|
|
+
|
|
err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess);
|
|
if (err != Success) {
|
|
client->errorValue = drawableId;
|
|
@@ -1163,9 +1156,6 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
|
|
err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw,
|
|
glxDrawableId, GLX_DRAWABLE_PIXMAP);
|
|
|
|
- if (err == Success)
|
|
- ((PixmapPtr) pDraw)->refcnt++;
|
|
-
|
|
return err;
|
|
}
|
|
|
|
@@ -1306,6 +1296,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
|
|
PixmapPtr pPixmap;
|
|
int err;
|
|
|
|
+ LEGAL_NEW_RESOURCE(glxDrawableId, client);
|
|
+
|
|
if (!validGlxScreen(client, screenNum, &pGlxScreen, &err))
|
|
return err;
|
|
if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err))
|
|
@@ -1316,6 +1308,13 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
|
|
width, height, config->rgbBits, 0);
|
|
__glXleaveServer(GL_FALSE);
|
|
|
|
+ /* Assign the pixmap the same id as the pbuffer and add it as a
|
|
+ * resource so it and the DRI2 drawable will be reclaimed when the
|
|
+ * pbuffer is destroyed. */
|
|
+ pPixmap->drawable.id = glxDrawableId;
|
|
+ if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap))
|
|
+ return BadAlloc;
|
|
+
|
|
return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
|
|
glxDrawableId, GLX_DRAWABLE_PBUFFER);
|
|
}
|
|
@@ -1423,6 +1422,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
|
|
DrawablePtr pDraw;
|
|
int err;
|
|
|
|
+ LEGAL_NEW_RESOURCE(req->glxwindow, client);
|
|
+
|
|
if (!validGlxScreen(client, req->screen, &pGlxScreen, &err))
|
|
return err;
|
|
if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err))
|
|
commit 0c499f2ee4ae2b7dc424009abb336fc81a8a2853
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Fri Apr 16 05:55:34 2010 -0400
|
|
|
|
DRI2: Track DRI2 drawables as resources, not privates
|
|
|
|
The main motivation here is to have the resource system clean up the
|
|
DRI2 drawable automatically so glx doesn't have to. Right now, the
|
|
glx drawable resource must be destroyed before the X drawable, so that
|
|
calling DRI2DestroyDrawable doesn't crash. By making the DRI2
|
|
drawable a resource, GLX doesn't have to worry about that and the
|
|
resource destruction order becomes irrelevant.
|
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=26394
|
|
|
|
[Ported to 1.8 branch by ajax@redhat.com]
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index edd29b0..bde519a 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -105,11 +105,6 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
|
|
|
(*core->destroyDrawable)(private->driDrawable);
|
|
|
|
- /* If the X window was destroyed, the dri DestroyWindow hook will
|
|
- * aready have taken care of this, so only call if pDraw isn't NULL. */
|
|
- if (drawable->pDraw != NULL)
|
|
- DRI2DestroyDrawable(drawable->pDraw);
|
|
-
|
|
__glXDrawableRelease(drawable);
|
|
|
|
xfree(private);
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 48618e1..63bef28 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -45,15 +45,14 @@
|
|
|
|
#include "xf86.h"
|
|
|
|
-static int dri2ScreenPrivateKeyIndex;
|
|
+static int dri2ScreenPrivateKeyIndex;
|
|
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
|
-static int dri2WindowPrivateKeyIndex;
|
|
-static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
|
|
-static int dri2PixmapPrivateKeyIndex;
|
|
-static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
|
|
+static RESTYPE dri2DrawableRes;
|
|
+
|
|
+typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
|
|
typedef struct _DRI2Drawable {
|
|
- unsigned int refCount;
|
|
+ DRI2ScreenPtr dri2_screen;
|
|
int width;
|
|
int height;
|
|
DRI2BufferPtr *buffers;
|
|
@@ -67,9 +66,8 @@ typedef struct _DRI2Drawable {
|
|
int swap_limit; /* for N-buffering */
|
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
|
|
|
-typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
-
|
|
typedef struct _DRI2Screen {
|
|
+ ScreenPtr screen;
|
|
unsigned int numDrivers;
|
|
const char **driverNames;
|
|
const char *deviceName;
|
|
@@ -95,43 +93,33 @@ DRI2GetScreen(ScreenPtr pScreen)
|
|
static DRI2DrawablePtr
|
|
DRI2GetDrawable(DrawablePtr pDraw)
|
|
{
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
-
|
|
- if (!pDraw)
|
|
+ DRI2DrawablePtr pPriv;
|
|
+ int rc;
|
|
+
|
|
+ rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
+ dri2DrawableRes, NULL, DixReadAccess);
|
|
+ if (rc != Success)
|
|
return NULL;
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
|
|
- }
|
|
+ return pPriv;
|
|
}
|
|
|
|
int
|
|
DRI2CreateDrawable(DrawablePtr pDraw)
|
|
{
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
DRI2DrawablePtr pPriv;
|
|
+ int rc;
|
|
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv != NULL)
|
|
- {
|
|
- pPriv->refCount++;
|
|
- return Success;
|
|
- }
|
|
+ rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
+ dri2DrawableRes, NULL, DixReadAccess);
|
|
+ if (rc == Success || rc != BadValue)
|
|
+ return rc;
|
|
|
|
pPriv = xalloc(sizeof *pPriv);
|
|
if (pPriv == NULL)
|
|
return BadAlloc;
|
|
|
|
- pPriv->refCount = 1;
|
|
+ pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
|
|
pPriv->width = pDraw->width;
|
|
pPriv->height = pDraw->height;
|
|
pPriv->buffers = NULL;
|
|
@@ -144,43 +132,30 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->last_swap_target = -1;
|
|
pPriv->swap_limit = 1; /* default to double buffering */
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
|
|
- }
|
|
+ if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
|
|
+ return BadAlloc;
|
|
|
|
return Success;
|
|
}
|
|
|
|
-static void
|
|
-DRI2FreeDrawable(DrawablePtr pDraw)
|
|
+static int DRI2DrawableGone(pointer p, XID id)
|
|
{
|
|
- DRI2DrawablePtr pPriv;
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
+ DRI2DrawablePtr pPriv = p;
|
|
+ DRI2ScreenPtr ds = pPriv->dri2_screen;
|
|
+ DrawablePtr root;
|
|
+ int i;
|
|
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
- return;
|
|
+ root = &WindowTable[ds->screen->myNum]->drawable;
|
|
+ if (pPriv->buffers != NULL) {
|
|
+ for (i = 0; i < pPriv->bufferCount; i++)
|
|
+ (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
|
|
+
|
|
+ xfree(pPriv->buffers);
|
|
+ }
|
|
|
|
xfree(pPriv);
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
|
|
- }
|
|
+ return Success;
|
|
}
|
|
|
|
static int
|
|
@@ -534,13 +509,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
return;
|
|
}
|
|
|
|
- if (pPriv->refCount == 0) {
|
|
- xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
- "[DRI2] %s: bad drawable refcount\n", __func__);
|
|
- DRI2FreeDrawable(pDraw);
|
|
- return;
|
|
- }
|
|
-
|
|
ust = ((CARD64)tv_sec * 1000000) + tv_usec;
|
|
if (swap_complete)
|
|
swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
|
|
@@ -753,36 +721,6 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
return Success;
|
|
}
|
|
|
|
-void
|
|
-DRI2DestroyDrawable(DrawablePtr pDraw)
|
|
-{
|
|
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
- DRI2DrawablePtr pPriv;
|
|
-
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
- return;
|
|
-
|
|
- pPriv->refCount--;
|
|
- if (pPriv->refCount > 0)
|
|
- return;
|
|
-
|
|
- if (pPriv->buffers != NULL) {
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < pPriv->bufferCount; i++)
|
|
- (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
|
|
-
|
|
- xfree(pPriv->buffers);
|
|
- }
|
|
-
|
|
- /* If the window is destroyed while we have a swap pending, don't
|
|
- * actually free the priv yet. We'll need it in the DRI2SwapComplete()
|
|
- * callback and we'll free it there once we're done. */
|
|
- if (!pPriv->swapsPending)
|
|
- DRI2FreeDrawable(pDraw);
|
|
-}
|
|
-
|
|
Bool
|
|
DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
|
|
const char **driverName, const char **deviceName)
|
|
@@ -834,6 +772,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
if (!ds)
|
|
return FALSE;
|
|
|
|
+ ds->screen = pScreen;
|
|
ds->fd = info->fd;
|
|
ds->deviceName = info->deviceName;
|
|
|
|
@@ -897,6 +836,8 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = FALSE;
|
|
|
|
+ dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
+
|
|
if (!setupDone)
|
|
{
|
|
setupDone = TRUE;
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index bd92fd3..1ac4a5f 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -51,7 +51,6 @@
|
|
#include "xf86Module.h"
|
|
|
|
static ExtensionEntry *dri2Extension;
|
|
-static RESTYPE dri2DrawableRes;
|
|
|
|
static Bool
|
|
validDrawable(ClientPtr client, XID drawable, Mask access_mode,
|
|
@@ -172,11 +171,6 @@ ProcDRI2CreateDrawable(ClientPtr client)
|
|
if (status != Success)
|
|
return status;
|
|
|
|
- if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
|
|
- DRI2DestroyDrawable(pDrawable);
|
|
- return BadAlloc;
|
|
- }
|
|
-
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -192,8 +186,6 @@ ProcDRI2DestroyDrawable(ClientPtr client)
|
|
&pDrawable, &status))
|
|
return status;
|
|
|
|
- FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
|
|
-
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -620,25 +612,11 @@ SProcDRI2Dispatch (ClientPtr client)
|
|
}
|
|
}
|
|
|
|
-static int DRI2DrawableGone(pointer p, XID id)
|
|
-{
|
|
- DrawablePtr pDrawable = p;
|
|
-
|
|
- DRI2DestroyDrawable(pDrawable);
|
|
-
|
|
- return Success;
|
|
-}
|
|
-
|
|
int DRI2EventBase;
|
|
|
|
static void
|
|
DRI2ExtensionInit(void)
|
|
{
|
|
- dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
-
|
|
- if (!dri2DrawableRes)
|
|
- return;
|
|
-
|
|
dri2Extension = AddExtension(DRI2_NAME,
|
|
DRI2NumberEvents,
|
|
DRI2NumberErrors,
|
|
commit 6ab87eb04cf24619c17c1fa05daaeebb481a6a50
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Fri Apr 16 05:55:35 2010 -0400
|
|
|
|
glx: Drop DestroyWindow hook
|
|
|
|
Now that glx doesn't call DRI2DestroyDrawable anymore, we don't need to
|
|
force a specific resource destruction order in the DestroyWindow hook.
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Reviewed-by: Michel Dänzer <michel@daenzer.net>
|
|
|
|
https://bugs.freedesktop.org/show_bug.cgi?id=26394
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
|
|
diff --git a/glx/glxscreens.c b/glx/glxscreens.c
|
|
index 58d8ee0..b75aea6 100644
|
|
--- a/glx/glxscreens.c
|
|
+++ b/glx/glxscreens.c
|
|
@@ -215,7 +215,6 @@ glxCloseScreen (int index, ScreenPtr pScreen)
|
|
__GLXscreen *pGlxScreen = glxGetScreen(pScreen);
|
|
|
|
pScreen->CloseScreen = pGlxScreen->CloseScreen;
|
|
- pScreen->DestroyWindow = pGlxScreen->DestroyWindow;
|
|
|
|
pGlxScreen->destroy(pGlxScreen);
|
|
|
|
@@ -347,31 +346,6 @@ pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
|
|
return best;
|
|
}
|
|
|
|
-static Bool
|
|
-glxDestroyWindow(WindowPtr pWin)
|
|
-{
|
|
- ScreenPtr pScreen = pWin->drawable.pScreen;
|
|
- __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
|
|
- Bool retval = TRUE;
|
|
-
|
|
- FreeResource(pWin->drawable.id, FALSE);
|
|
-
|
|
- /* call lower wrapped functions */
|
|
- if (pGlxScreen->DestroyWindow) {
|
|
- /* unwrap */
|
|
- pScreen->DestroyWindow = pGlxScreen->DestroyWindow;
|
|
-
|
|
- /* call lower layers */
|
|
- retval = (*pScreen->DestroyWindow)(pWin);
|
|
-
|
|
- /* rewrap */
|
|
- pGlxScreen->DestroyWindow = pScreen->DestroyWindow;
|
|
- pScreen->DestroyWindow = glxDestroyWindow;
|
|
- }
|
|
-
|
|
- return retval;
|
|
-}
|
|
-
|
|
void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
|
|
{
|
|
__GLXconfig *m;
|
|
@@ -394,8 +368,6 @@ void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
|
|
|
|
pGlxScreen->CloseScreen = pScreen->CloseScreen;
|
|
pScreen->CloseScreen = glxCloseScreen;
|
|
- pGlxScreen->DestroyWindow = pScreen->DestroyWindow;
|
|
- pScreen->DestroyWindow = glxDestroyWindow;
|
|
|
|
i = 0;
|
|
for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
|
|
diff --git a/glx/glxscreens.h b/glx/glxscreens.h
|
|
index bff4363..d52099f 100644
|
|
--- a/glx/glxscreens.h
|
|
+++ b/glx/glxscreens.h
|
|
@@ -173,7 +173,6 @@ struct __GLXscreen {
|
|
/*@}*/
|
|
|
|
Bool (*CloseScreen)(int index, ScreenPtr pScreen);
|
|
- Bool (*DestroyWindow)(WindowPtr pWindow);
|
|
};
|
|
|
|
|
|
commit c394b17266301d363a9e234f58f8015f74e01307
|
|
Author: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Tue Apr 27 17:53:22 2010 +1000
|
|
|
|
Revert "DRI2: Track DRI2 drawables as resources, not privates"
|
|
|
|
This change breaks GLX compositing managers.
|
|
See Bug 27767 <https://bugs.freedesktop.org/show_bug.cgi?id=27767>
|
|
|
|
This reverts commit 0c499f2ee4ae2b7dc424009abb336fc81a8a2853.
|
|
|
|
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
|
|
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index bde519a..edd29b0 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -105,6 +105,11 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
|
|
|
(*core->destroyDrawable)(private->driDrawable);
|
|
|
|
+ /* If the X window was destroyed, the dri DestroyWindow hook will
|
|
+ * aready have taken care of this, so only call if pDraw isn't NULL. */
|
|
+ if (drawable->pDraw != NULL)
|
|
+ DRI2DestroyDrawable(drawable->pDraw);
|
|
+
|
|
__glXDrawableRelease(drawable);
|
|
|
|
xfree(private);
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 63bef28..48618e1 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -45,14 +45,15 @@
|
|
|
|
#include "xf86.h"
|
|
|
|
-static int dri2ScreenPrivateKeyIndex;
|
|
+static int dri2ScreenPrivateKeyIndex;
|
|
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
|
-static RESTYPE dri2DrawableRes;
|
|
-
|
|
-typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
+static int dri2WindowPrivateKeyIndex;
|
|
+static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
|
|
+static int dri2PixmapPrivateKeyIndex;
|
|
+static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
|
|
|
|
typedef struct _DRI2Drawable {
|
|
- DRI2ScreenPtr dri2_screen;
|
|
+ unsigned int refCount;
|
|
int width;
|
|
int height;
|
|
DRI2BufferPtr *buffers;
|
|
@@ -66,8 +67,9 @@ typedef struct _DRI2Drawable {
|
|
int swap_limit; /* for N-buffering */
|
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
|
|
|
+typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
+
|
|
typedef struct _DRI2Screen {
|
|
- ScreenPtr screen;
|
|
unsigned int numDrivers;
|
|
const char **driverNames;
|
|
const char *deviceName;
|
|
@@ -93,33 +95,43 @@ DRI2GetScreen(ScreenPtr pScreen)
|
|
static DRI2DrawablePtr
|
|
DRI2GetDrawable(DrawablePtr pDraw)
|
|
{
|
|
- DRI2DrawablePtr pPriv;
|
|
- int rc;
|
|
-
|
|
- rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
- dri2DrawableRes, NULL, DixReadAccess);
|
|
- if (rc != Success)
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
+
|
|
+ if (!pDraw)
|
|
return NULL;
|
|
|
|
- return pPriv;
|
|
+ if (pDraw->type == DRAWABLE_WINDOW)
|
|
+ {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
|
|
+ }
|
|
}
|
|
|
|
int
|
|
DRI2CreateDrawable(DrawablePtr pDraw)
|
|
{
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
DRI2DrawablePtr pPriv;
|
|
- int rc;
|
|
|
|
- rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
- dri2DrawableRes, NULL, DixReadAccess);
|
|
- if (rc == Success || rc != BadValue)
|
|
- return rc;
|
|
+ pPriv = DRI2GetDrawable(pDraw);
|
|
+ if (pPriv != NULL)
|
|
+ {
|
|
+ pPriv->refCount++;
|
|
+ return Success;
|
|
+ }
|
|
|
|
pPriv = xalloc(sizeof *pPriv);
|
|
if (pPriv == NULL)
|
|
return BadAlloc;
|
|
|
|
- pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
|
|
+ pPriv->refCount = 1;
|
|
pPriv->width = pDraw->width;
|
|
pPriv->height = pDraw->height;
|
|
pPriv->buffers = NULL;
|
|
@@ -132,30 +144,43 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->last_swap_target = -1;
|
|
pPriv->swap_limit = 1; /* default to double buffering */
|
|
|
|
- if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
|
|
- return BadAlloc;
|
|
+ if (pDraw->type == DRAWABLE_WINDOW)
|
|
+ {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
|
|
+ }
|
|
|
|
return Success;
|
|
}
|
|
|
|
-static int DRI2DrawableGone(pointer p, XID id)
|
|
+static void
|
|
+DRI2FreeDrawable(DrawablePtr pDraw)
|
|
{
|
|
- DRI2DrawablePtr pPriv = p;
|
|
- DRI2ScreenPtr ds = pPriv->dri2_screen;
|
|
- DrawablePtr root;
|
|
- int i;
|
|
-
|
|
- root = &WindowTable[ds->screen->myNum]->drawable;
|
|
- if (pPriv->buffers != NULL) {
|
|
- for (i = 0; i < pPriv->bufferCount; i++)
|
|
- (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
|
|
+ DRI2DrawablePtr pPriv;
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
|
|
- xfree(pPriv->buffers);
|
|
- }
|
|
+ pPriv = DRI2GetDrawable(pDraw);
|
|
+ if (pPriv == NULL)
|
|
+ return;
|
|
|
|
xfree(pPriv);
|
|
|
|
- return Success;
|
|
+ if (pDraw->type == DRAWABLE_WINDOW)
|
|
+ {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
|
|
+ }
|
|
}
|
|
|
|
static int
|
|
@@ -509,6 +534,13 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
return;
|
|
}
|
|
|
|
+ if (pPriv->refCount == 0) {
|
|
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
+ "[DRI2] %s: bad drawable refcount\n", __func__);
|
|
+ DRI2FreeDrawable(pDraw);
|
|
+ return;
|
|
+ }
|
|
+
|
|
ust = ((CARD64)tv_sec * 1000000) + tv_usec;
|
|
if (swap_complete)
|
|
swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
|
|
@@ -721,6 +753,36 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
return Success;
|
|
}
|
|
|
|
+void
|
|
+DRI2DestroyDrawable(DrawablePtr pDraw)
|
|
+{
|
|
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
+ DRI2DrawablePtr pPriv;
|
|
+
|
|
+ pPriv = DRI2GetDrawable(pDraw);
|
|
+ if (pPriv == NULL)
|
|
+ return;
|
|
+
|
|
+ pPriv->refCount--;
|
|
+ if (pPriv->refCount > 0)
|
|
+ return;
|
|
+
|
|
+ if (pPriv->buffers != NULL) {
|
|
+ int i;
|
|
+
|
|
+ for (i = 0; i < pPriv->bufferCount; i++)
|
|
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
|
|
+
|
|
+ xfree(pPriv->buffers);
|
|
+ }
|
|
+
|
|
+ /* If the window is destroyed while we have a swap pending, don't
|
|
+ * actually free the priv yet. We'll need it in the DRI2SwapComplete()
|
|
+ * callback and we'll free it there once we're done. */
|
|
+ if (!pPriv->swapsPending)
|
|
+ DRI2FreeDrawable(pDraw);
|
|
+}
|
|
+
|
|
Bool
|
|
DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
|
|
const char **driverName, const char **deviceName)
|
|
@@ -772,7 +834,6 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
if (!ds)
|
|
return FALSE;
|
|
|
|
- ds->screen = pScreen;
|
|
ds->fd = info->fd;
|
|
ds->deviceName = info->deviceName;
|
|
|
|
@@ -836,8 +897,6 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = FALSE;
|
|
|
|
- dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
-
|
|
if (!setupDone)
|
|
{
|
|
setupDone = TRUE;
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index 1ac4a5f..bd92fd3 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -51,6 +51,7 @@
|
|
#include "xf86Module.h"
|
|
|
|
static ExtensionEntry *dri2Extension;
|
|
+static RESTYPE dri2DrawableRes;
|
|
|
|
static Bool
|
|
validDrawable(ClientPtr client, XID drawable, Mask access_mode,
|
|
@@ -171,6 +172,11 @@ ProcDRI2CreateDrawable(ClientPtr client)
|
|
if (status != Success)
|
|
return status;
|
|
|
|
+ if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
|
|
+ DRI2DestroyDrawable(pDrawable);
|
|
+ return BadAlloc;
|
|
+ }
|
|
+
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -186,6 +192,8 @@ ProcDRI2DestroyDrawable(ClientPtr client)
|
|
&pDrawable, &status))
|
|
return status;
|
|
|
|
+ FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
|
|
+
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -612,11 +620,25 @@ SProcDRI2Dispatch (ClientPtr client)
|
|
}
|
|
}
|
|
|
|
+static int DRI2DrawableGone(pointer p, XID id)
|
|
+{
|
|
+ DrawablePtr pDrawable = p;
|
|
+
|
|
+ DRI2DestroyDrawable(pDrawable);
|
|
+
|
|
+ return Success;
|
|
+}
|
|
+
|
|
int DRI2EventBase;
|
|
|
|
static void
|
|
DRI2ExtensionInit(void)
|
|
{
|
|
+ dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
+
|
|
+ if (!dri2DrawableRes)
|
|
+ return;
|
|
+
|
|
dri2Extension = AddExtension(DRI2_NAME,
|
|
DRI2NumberEvents,
|
|
DRI2NumberErrors,
|
|
commit 18dc5d1f15fe0df7e836b057d34c4ca596e31e8f
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Thu Mar 4 09:19:13 2010 -0800
|
|
|
|
DRI2: fixup handling of last_swap_target
|
|
|
|
We need to initialize the swap target, which is passed to the driver to
|
|
schedule events. Rather than using -1 to indicate that the field is
|
|
uninitialized, just make sure we initialize it at drawable creation
|
|
time.
|
|
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit c4d54816f2ee4883d8f9bcf4595474fb58c95146)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 48618e1..d60bd5e 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -116,9 +116,11 @@ DRI2GetDrawable(DrawablePtr pDraw)
|
|
int
|
|
DRI2CreateDrawable(DrawablePtr pDraw)
|
|
{
|
|
+ DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
WindowPtr pWin;
|
|
PixmapPtr pPixmap;
|
|
DRI2DrawablePtr pPriv;
|
|
+ CARD64 ust;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
if (pPriv != NULL)
|
|
@@ -141,7 +143,10 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->swap_count = 0;
|
|
pPriv->target_sbc = -1;
|
|
pPriv->swap_interval = 1;
|
|
- pPriv->last_swap_target = -1;
|
|
+ /* Initialize last swap target from DDX if possible */
|
|
+ if (!ds->GetMSC || !(*ds->GetMSC)(pDraw, &ust, &pPriv->last_swap_target))
|
|
+ pPriv->last_swap_target = 0;
|
|
+
|
|
pPriv->swap_limit = 1; /* default to double buffering */
|
|
|
|
if (pDraw->type == DRAWABLE_WINDOW)
|
|
@@ -579,7 +584,6 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
DRI2DrawablePtr pPriv;
|
|
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
|
- CARD64 ust;
|
|
int ret, i;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
@@ -621,27 +625,6 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
}
|
|
|
|
/*
|
|
- * In the simple glXSwapBuffers case, all params will be 0, and we just
|
|
- * need to schedule a swap for the last swap target + the swap interval.
|
|
- * If the last swap target hasn't been set yet, call into the driver
|
|
- * to get the current count.
|
|
- */
|
|
- if (target_msc == 0 && divisor == 0 && remainder == 0 &&
|
|
- pPriv->last_swap_target < 0) {
|
|
- ret = (*ds->GetMSC)(pDraw, &ust, &target_msc);
|
|
- if (!ret) {
|
|
- xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
- "[DRI2] %s: driver failed to return current MSC\n",
|
|
- __func__);
|
|
- return BadDrawable;
|
|
- }
|
|
- }
|
|
-
|
|
- /* First swap needs to initialize last_swap_target */
|
|
- if (pPriv->last_swap_target < 0)
|
|
- pPriv->last_swap_target = target_msc;
|
|
-
|
|
- /*
|
|
* Swap target for this swap is last swap target + swap interval since
|
|
* we have to account for the current swap count, interval, and the
|
|
* number of pending swaps.
|
|
commit 96a12314ae41a2edec67d388c1c4770bd099d9ec
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Thu Mar 4 09:54:15 2010 -0800
|
|
|
|
DRI2: make target_sbc signed
|
|
|
|
We need to track invalid targets as well as 0 targets, so just make it
|
|
signed so our comparisons work like they should.
|
|
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reported-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 4c8ec49826a46eb3b36c69d2ad3f82320c179c38)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index d60bd5e..ec4f982 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -62,7 +62,7 @@ typedef struct _DRI2Drawable {
|
|
ClientPtr blockedClient;
|
|
int swap_interval;
|
|
CARD64 swap_count;
|
|
- CARD64 target_sbc; /* -1 means no SBC wait outstanding */
|
|
+ int64_t target_sbc; /* -1 means no SBC wait outstanding */
|
|
CARD64 last_swap_target; /* most recently queued swap target */
|
|
int swap_limit; /* for N-buffering */
|
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
|
commit a9b70da1afe7361955a19d34bb5e9b94dc156889
|
|
Author: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Date: Sun Feb 21 05:25:59 2010 +0100
|
|
|
|
DRI2: Fix glitches in DRI2SwapComplete() and DRI2WakeupClient()
|
|
|
|
DRI2SwapComplete(): Increment pPriv->swap_count++; before calling
|
|
into callback for INTEL_swap_events extension, so the swap event
|
|
contains the current SBC after swap completion instead of the
|
|
previous one.
|
|
|
|
DRI2WakeupClient: Check for pPriv->target_sbc <= pPriv->swap_count,
|
|
had wrong comparison pPriv->target_sbc >= pPriv->swap_count for
|
|
unblocking of clients of DRI2WaitSBC().
|
|
|
|
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
(cherry picked from commit 0de4974b90b10fa6a447cdf980b4a114c6c9e5a8)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index ec4f982..cb227be 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -509,7 +509,7 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
* blocked due to GLX activity during a swap.
|
|
*/
|
|
if (pPriv->target_sbc != -1 &&
|
|
- pPriv->target_sbc >= pPriv->swap_count) {
|
|
+ pPriv->target_sbc <= pPriv->swap_count) {
|
|
ProcDRI2WaitMSCReply(client, ((CARD64)tv_sec * 1000000) + tv_usec,
|
|
frame, pPriv->swap_count);
|
|
pPriv->target_sbc = -1;
|
|
@@ -546,13 +546,13 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
return;
|
|
}
|
|
|
|
+ pPriv->swapsPending--;
|
|
+ pPriv->swap_count++;
|
|
+
|
|
ust = ((CARD64)tv_sec * 1000000) + tv_usec;
|
|
if (swap_complete)
|
|
swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
|
|
|
|
- pPriv->swapsPending--;
|
|
- pPriv->swap_count++;
|
|
-
|
|
DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
|
|
}
|
|
|
|
commit a56178402ede82ed3ffd81439b2efc4a39f2779e
|
|
Author: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Date: Sun Feb 21 05:26:00 2010 +0100
|
|
|
|
DRI2WaitSbc(): Fixes for correct semantic of glXWaitForSbcOML()
|
|
|
|
Added implementation for case target_sbc == 0. In that case, the
|
|
function shall schedule a wait until all pending swaps for the drawable
|
|
have completed.
|
|
|
|
Fix for non-blocking case. Old implementation returned random,
|
|
uninitialized values for (ust,msc,sbc) if it returned immediately
|
|
without scheduling a wait due to sbc >= target_sbc.
|
|
|
|
Now if function doesn't schedule a wait, but returns immediately,
|
|
it returns the (ust,msc,sbc) of the most recently completed swap,
|
|
i.e., the UST and MSC corresponding to the time when the returned
|
|
current SBC was reached.
|
|
|
|
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
(cherry picked from commit 751e8c09d34df4b41e8d8384a3ec1bf5cb8ca028)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index cb227be..ef838ff 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -64,6 +64,8 @@ typedef struct _DRI2Drawable {
|
|
CARD64 swap_count;
|
|
int64_t target_sbc; /* -1 means no SBC wait outstanding */
|
|
CARD64 last_swap_target; /* most recently queued swap target */
|
|
+ CARD64 last_swap_msc; /* msc at completion of most recent swap */
|
|
+ CARD64 last_swap_ust; /* ust at completion of most recent swap */
|
|
int swap_limit; /* for N-buffering */
|
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
|
|
|
@@ -148,6 +150,8 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->last_swap_target = 0;
|
|
|
|
pPriv->swap_limit = 1; /* default to double buffering */
|
|
+ pPriv->last_swap_msc = 0;
|
|
+ pPriv->last_swap_ust = 0;
|
|
|
|
if (pDraw->type == DRAWABLE_WINDOW)
|
|
{
|
|
@@ -553,6 +557,9 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
if (swap_complete)
|
|
swap_complete(client, swap_data, type, ust, frame, pPriv->swap_count);
|
|
|
|
+ pPriv->last_swap_msc = frame;
|
|
+ pPriv->last_swap_ust = ust;
|
|
+
|
|
DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
|
|
}
|
|
|
|
@@ -727,8 +734,22 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
if (pPriv == NULL)
|
|
return BadDrawable;
|
|
|
|
- if (pPriv->swap_count >= target_sbc)
|
|
- return Success;
|
|
+ /* target_sbc == 0 means to block until all pending swaps are
|
|
+ * finished. Recalculate target_sbc to get that behaviour.
|
|
+ */
|
|
+ if (target_sbc == 0)
|
|
+ target_sbc = pPriv->swap_count + pPriv->swapsPending;
|
|
+
|
|
+ /* If current swap count already >= target_sbc,
|
|
+ * return immediately with (ust, msc, sbc) triplet of
|
|
+ * most recent completed swap.
|
|
+ */
|
|
+ if (pPriv->swap_count >= target_sbc) {
|
|
+ *sbc = pPriv->swap_count;
|
|
+ *msc = pPriv->last_swap_msc;
|
|
+ *ust = pPriv->last_swap_ust;
|
|
+ return Success;
|
|
+ }
|
|
|
|
pPriv->target_sbc = target_sbc;
|
|
DRI2BlockClient(client, pDraw);
|
|
commit 23d78005b06b15f7b68fc4eed7e325ad29d0880a
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Thu Mar 4 10:31:59 2010 -0800
|
|
|
|
DRI2: fix swapbuffers handling of SBC and target MSC
|
|
|
|
Returns expected SBC after completion of swap to caller, as required by
|
|
OML_sync_control spec, instead of the last_swap_target value.
|
|
|
|
Passes target_msc, divisor, remainder, correctly for
|
|
glXSwapBuffersMscOML() call, while retaining old behaviour for simple
|
|
glXSwapBuffers() call.
|
|
|
|
An OML swap can have a 0 target_msc, which just means it needs to
|
|
satisfy the divisor/remainder equation. Pass this down to the driver as
|
|
needed so we can support it.
|
|
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
(cherry picked from commit b180e43977710b56ccfd6780f204ddcc952987a1)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index ef838ff..354b724 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -632,11 +632,20 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
}
|
|
|
|
/*
|
|
- * Swap target for this swap is last swap target + swap interval since
|
|
- * we have to account for the current swap count, interval, and the
|
|
- * number of pending swaps.
|
|
+ * In the simple glXSwapBuffers case, all params will be 0, and we just
|
|
+ * need to schedule a swap for the last swap target + the swap interval.
|
|
*/
|
|
- *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
|
+ if (target_msc == 0 && divisor == 0 && remainder == 0) {
|
|
+ /*
|
|
+ * Swap target for this swap is last swap target + swap interval since
|
|
+ * we have to account for the current swap count, interval, and the
|
|
+ * number of pending swaps.
|
|
+ */
|
|
+ *swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
|
+ } else {
|
|
+ /* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
|
+ *swap_target = target_msc;
|
|
+ }
|
|
|
|
ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
|
|
swap_target, divisor, remainder, func, data);
|
|
@@ -649,6 +658,11 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
pPriv->swapsPending++;
|
|
pPriv->last_swap_target = *swap_target;
|
|
|
|
+ /* According to spec, return expected swapbuffers count SBC after this swap
|
|
+ * will complete.
|
|
+ */
|
|
+ *swap_target = pPriv->swap_count + pPriv->swapsPending;
|
|
+
|
|
return Success;
|
|
}
|
|
|
|
commit 73fe4a0952b5c8aea90bce6f758546c13d0754b5
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Fri Mar 5 09:15:24 2010 -0800
|
|
|
|
DRI2: drawable lifetime fixes
|
|
|
|
Handle drawable destruction and lifetime correctly.
|
|
|
|
Check whether the drawable priv is valid in DRI2SwapInterval(),
|
|
DRI2WaitSBC() and DRI2WaitMSC(); it may have gone away, so be sure to
|
|
check it before using it.
|
|
|
|
If more than 1 outstanding swap is queued, we may complete several after
|
|
an app has exited. If we free it after the first one completes and the
|
|
refcount reaches 0, we'll crash the server on subsequent completions.
|
|
So delay freeing until all swaps complete and remove the error message
|
|
as this is a normal occurence. To do this properly, we must also avoid
|
|
destroying drawables in DRI2DestroyDrawable() if a swap or wait event is
|
|
pending.
|
|
|
|
And finally, make sure we free drawables in DRI2WaitMSCComplete() if
|
|
necessary (i.e. if the refcount has reached 0 and this MSC was the last
|
|
pending event on the object).
|
|
|
|
Reported-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 8476d99231cb725c090305d60f1c1c889d25c8dc)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 354b724..58f478f 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -492,6 +492,10 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
AttendClient(pPriv->blockedClient);
|
|
|
|
pPriv->blockedClient = NULL;
|
|
+
|
|
+ /* If there's still a swap pending, let DRI2SwapComplete free it */
|
|
+ if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
|
|
+ DRI2FreeDrawable(pDraw);
|
|
}
|
|
|
|
static void
|
|
@@ -543,13 +547,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
return;
|
|
}
|
|
|
|
- if (pPriv->refCount == 0) {
|
|
- xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
- "[DRI2] %s: bad drawable refcount\n", __func__);
|
|
- DRI2FreeDrawable(pDraw);
|
|
- return;
|
|
- }
|
|
-
|
|
pPriv->swapsPending--;
|
|
pPriv->swap_count++;
|
|
|
|
@@ -561,6 +558,13 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
pPriv->last_swap_ust = ust;
|
|
|
|
DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
|
|
+
|
|
+ /*
|
|
+ * It's normal for the app to have exited with a swap outstanding, but
|
|
+ * don't free the drawable until they're all complete.
|
|
+ */
|
|
+ if (pPriv->swapsPending == 0 && pPriv->refCount == 0)
|
|
+ DRI2FreeDrawable(pDraw);
|
|
}
|
|
|
|
Bool
|
|
@@ -669,10 +673,16 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
void
|
|
DRI2SwapInterval(DrawablePtr pDrawable, int interval)
|
|
{
|
|
+ ScreenPtr pScreen = pDrawable->pScreen;
|
|
DRI2DrawablePtr pPriv = DRI2GetDrawable(pDrawable);
|
|
|
|
- /* fixme: check against arbitrary max? */
|
|
+ if (pPriv == NULL) {
|
|
+ xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
+ "[DRI2] %s: bad drawable\n", __func__);
|
|
+ return;
|
|
+ }
|
|
|
|
+ /* fixme: check against arbitrary max? */
|
|
pPriv->swap_interval = interval;
|
|
}
|
|
|
|
@@ -721,7 +731,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
Bool ret;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
+ if (pPriv == NULL || pPriv->refCount == 0)
|
|
return BadDrawable;
|
|
|
|
/* Old DDX just completes immediately */
|
|
@@ -745,7 +755,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
DRI2DrawablePtr pPriv;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
+ if (pPriv == NULL || pPriv->refCount == 0)
|
|
return BadDrawable;
|
|
|
|
/* target_sbc == 0 means to block until all pending swaps are
|
|
@@ -794,10 +804,10 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
|
|
xfree(pPriv->buffers);
|
|
}
|
|
|
|
- /* If the window is destroyed while we have a swap pending, don't
|
|
+ /* If the window is destroyed while we have a swap or wait pending, don't
|
|
* actually free the priv yet. We'll need it in the DRI2SwapComplete()
|
|
* callback and we'll free it there once we're done. */
|
|
- if (!pPriv->swapsPending)
|
|
+ if (!pPriv->swapsPending && !pPriv->blockedClient)
|
|
DRI2FreeDrawable(pDraw);
|
|
}
|
|
|
|
commit 20708781d43501f116b4161c1cc96b0eb39e96b1
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Fri Mar 5 09:49:03 2010 -0800
|
|
|
|
DRI2: handle swap_interval of 0 correctly
|
|
|
|
A 0 swap interval means that swaps shouldn't be sync'd to vblank, so
|
|
just complete the swap immediately in that case.
|
|
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 87ca6320f26eb3129e3c19056e1d8fa5c1784723)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 58f478f..9825a55 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -616,8 +616,8 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
return BadDrawable;
|
|
}
|
|
|
|
- /* Old DDX, just blit */
|
|
- if (!ds->ScheduleSwap) {
|
|
+ /* Old DDX or no swap interval, just blit */
|
|
+ if (!ds->ScheduleSwap || !pPriv->swap_interval) {
|
|
BoxRec box;
|
|
RegionRec region;
|
|
|
|
commit c7e9e36fd3cdb889704d3b0e1333653d06ef9069
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Mon Mar 8 12:38:37 2010 -0800
|
|
|
|
DRI2: advertise lowest supported DRI2 protocol version
|
|
|
|
Update our supported DRI2 protocol version as each driver does
|
|
DRI2ScreenInit, since depending on available kernel features, each DDX
|
|
may support different callbacks and therefore protocol.
|
|
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit db1c7cb604167baf49e61be4c09ccf7b592c4af3)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 9825a55..3fc7f4e 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -45,6 +45,9 @@
|
|
|
|
#include "xf86.h"
|
|
|
|
+CARD8 dri2_major; /* version of DRI2 supported by DDX */
|
|
+CARD8 dri2_minor;
|
|
+
|
|
static int dri2ScreenPrivateKeyIndex;
|
|
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
|
static int dri2WindowPrivateKeyIndex;
|
|
@@ -848,6 +851,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
"VDPAU", /* DRI2DriverVDPAU */
|
|
};
|
|
unsigned int i;
|
|
+ CARD8 cur_minor;
|
|
|
|
if (info->version < 3)
|
|
return FALSE;
|
|
@@ -864,6 +868,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
|
|
ds->fd = info->fd;
|
|
ds->deviceName = info->deviceName;
|
|
+ dri2_major = 1;
|
|
|
|
ds->CreateBuffer = info->CreateBuffer;
|
|
ds->DestroyBuffer = info->DestroyBuffer;
|
|
@@ -873,8 +878,15 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
ds->ScheduleSwap = info->ScheduleSwap;
|
|
ds->ScheduleWaitMSC = info->ScheduleWaitMSC;
|
|
ds->GetMSC = info->GetMSC;
|
|
+ cur_minor = 2;
|
|
+ } else {
|
|
+ cur_minor = 1;
|
|
}
|
|
|
|
+ /* Initialize minor if needed and set to minimum provied by DDX */
|
|
+ if (!dri2_minor || dri2_minor > cur_minor)
|
|
+ dri2_minor = cur_minor;
|
|
+
|
|
if (info->version == 3 || info->numDrivers == 0) {
|
|
/* Driver too old: use the old-style driverName field */
|
|
ds->numDrivers = 1;
|
|
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
|
|
index 1c8626b..066cc39 100644
|
|
--- a/hw/xfree86/dri2/dri2.h
|
|
+++ b/hw/xfree86/dri2/dri2.h
|
|
@@ -46,6 +46,9 @@ typedef struct {
|
|
void *driverPrivate;
|
|
} DRI2BufferRec, *DRI2BufferPtr;
|
|
|
|
+extern CARD8 dri2_major; /* version of DRI2 supported by DDX */
|
|
+extern CARD8 dri2_minor;
|
|
+
|
|
typedef DRI2BufferRec DRI2Buffer2Rec, *DRI2Buffer2Ptr;
|
|
typedef void (*DRI2SwapEventPtr)(ClientPtr client, void *data, int type,
|
|
CARD64 ust, CARD64 msc, CARD64 sbc);
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index bd92fd3..7a9f8ca 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -80,8 +80,8 @@ ProcDRI2QueryVersion(ClientPtr client)
|
|
rep.type = X_Reply;
|
|
rep.length = 0;
|
|
rep.sequenceNumber = client->sequence;
|
|
- rep.majorVersion = SERVER_DRI2_MAJOR_VERSION;
|
|
- rep.minorVersion = SERVER_DRI2_MINOR_VERSION;
|
|
+ rep.majorVersion = dri2_major;
|
|
+ rep.minorVersion = dri2_minor;
|
|
|
|
if (client->swapped) {
|
|
swaps(&rep.sequenceNumber, n);
|
|
diff --git a/include/protocol-versions.h b/include/protocol-versions.h
|
|
index c74b7fa..97ef5da 100644
|
|
--- a/include/protocol-versions.h
|
|
+++ b/include/protocol-versions.h
|
|
@@ -51,10 +51,6 @@
|
|
#define SERVER_DMX_MINOR_VERSION 2
|
|
#define SERVER_DMX_PATCH_VERSION 20040604
|
|
|
|
-/* DRI2 */
|
|
-#define SERVER_DRI2_MAJOR_VERSION 1
|
|
-#define SERVER_DRI2_MINOR_VERSION 2
|
|
-
|
|
/* Generic event extension */
|
|
#define SERVER_GE_MAJOR_VERSION 1
|
|
#define SERVER_GE_MINOR_VERSION 0
|
|
commit fcd76ddfc59de6a1d37ca2aa6e6e91cb8d814744
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Mon Mar 8 12:39:54 2010 -0800
|
|
|
|
DRI2: throttle swaps at submission time too
|
|
|
|
We need to throttle swaps here in addition to when the context is made
|
|
current to avoid causing problems with clients that just swap.
|
|
Throttling here also ensures our swaps get ordered as long as we block
|
|
the client occasionally.
|
|
|
|
Reported-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 0294ff2a5cadddc8fcc77ba9a851f979f0b91fc3)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index 7a9f8ca..094d54d 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -384,6 +384,13 @@ ProcDRI2SwapBuffers(ClientPtr client)
|
|
DixReadAccess | DixWriteAccess, &pDrawable, &status))
|
|
return status;
|
|
|
|
+ /*
|
|
+ * Ensures an out of control client can't exhaust our swap queue, and
|
|
+ * also orders swaps.
|
|
+ */
|
|
+ if (DRI2ThrottleClient(client, pDrawable))
|
|
+ return client->noClientException;
|
|
+
|
|
target_msc = vals_to_card64(stuff->target_msc_lo, stuff->target_msc_hi);
|
|
divisor = vals_to_card64(stuff->divisor_lo, stuff->divisor_hi);
|
|
remainder = vals_to_card64(stuff->remainder_lo, stuff->remainder_hi);
|
|
commit 5c54e7fa004532d595160a815177dda467b3cc9c
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Mon Mar 8 12:41:25 2010 -0800
|
|
|
|
DRI2: handle swapsPending better
|
|
|
|
Avoid a potential swapsPending underflow by incrementing it before
|
|
ScheduleSwap, which may complete it immediately. And be sure to
|
|
decrement it again in case the schedule failed.
|
|
|
|
Reported-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit b00d435ddf2e9817e33bfd5f7e9b905442dc23c7)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 3fc7f4e..8a67122 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -654,15 +654,16 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
*swap_target = target_msc;
|
|
}
|
|
|
|
+ pPriv->swapsPending++;
|
|
ret = (*ds->ScheduleSwap)(client, pDraw, pDestBuffer, pSrcBuffer,
|
|
swap_target, divisor, remainder, func, data);
|
|
if (!ret) {
|
|
+ pPriv->swapsPending--; /* didn't schedule */
|
|
xf86DrvMsg(pScreen->myNum, X_ERROR,
|
|
"[DRI2] %s: driver failed to schedule swap\n", __func__);
|
|
return BadDrawable;
|
|
}
|
|
|
|
- pPriv->swapsPending++;
|
|
pPriv->last_swap_target = *swap_target;
|
|
|
|
/* According to spec, return expected swapbuffers count SBC after this swap
|
|
commit b24856626e1836657ebf35ad4c61984e0a407c5b
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Mon Mar 8 15:10:47 2010 -0800
|
|
|
|
DRI2: prevent swap wakes from waking MSC waiters
|
|
|
|
If a few swaps were queued leading to a throttle related block on the
|
|
client, and then the client submitted an MSC wait, one of the previous
|
|
swap wakeups could have caused the MSC wait to complete early. Add a
|
|
flag for this to prevent a swap wake from prematurely waking an MSC
|
|
waiter.
|
|
|
|
Reported-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 5933b0abc6a76aaea84aa534df89900cd795c888)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 8a67122..8b4c36f 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -63,6 +63,7 @@ typedef struct _DRI2Drawable {
|
|
int bufferCount;
|
|
unsigned int swapsPending;
|
|
ClientPtr blockedClient;
|
|
+ Bool blockedOnMsc;
|
|
int swap_interval;
|
|
CARD64 swap_count;
|
|
int64_t target_sbc; /* -1 means no SBC wait outstanding */
|
|
@@ -145,6 +146,7 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->bufferCount = 0;
|
|
pPriv->swapsPending = 0;
|
|
pPriv->blockedClient = NULL;
|
|
+ pPriv->blockedOnMsc = FALSE;
|
|
pPriv->swap_count = 0;
|
|
pPriv->target_sbc = -1;
|
|
pPriv->swap_interval = 1;
|
|
@@ -402,6 +404,15 @@ DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw)
|
|
return FALSE;
|
|
}
|
|
|
|
+static void
|
|
+__DRI2BlockClient(ClientPtr client, DRI2DrawablePtr pPriv)
|
|
+{
|
|
+ if (pPriv->blockedClient == NULL) {
|
|
+ IgnoreClient(client);
|
|
+ pPriv->blockedClient = client;
|
|
+ }
|
|
+}
|
|
+
|
|
void
|
|
DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
|
|
{
|
|
@@ -411,10 +422,8 @@ DRI2BlockClient(ClientPtr client, DrawablePtr pDraw)
|
|
if (pPriv == NULL)
|
|
return;
|
|
|
|
- if (pPriv->blockedClient == NULL) {
|
|
- IgnoreClient(client);
|
|
- pPriv->blockedClient = client;
|
|
- }
|
|
+ __DRI2BlockClient(client, pPriv);
|
|
+ pPriv->blockedOnMsc = TRUE;
|
|
}
|
|
|
|
int
|
|
@@ -495,6 +504,7 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
AttendClient(pPriv->blockedClient);
|
|
|
|
pPriv->blockedClient = NULL;
|
|
+ pPriv->blockedOnMsc = FALSE;
|
|
|
|
/* If there's still a swap pending, let DRI2SwapComplete free it */
|
|
if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
|
|
@@ -516,8 +526,12 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
}
|
|
|
|
/*
|
|
- * Swap completed. Either wake up an SBC waiter or a client that was
|
|
- * blocked due to GLX activity during a swap.
|
|
+ * Swap completed.
|
|
+ * Wake the client iff:
|
|
+ * - it was waiting on SBC
|
|
+ * - was blocked due to GLX make current
|
|
+ * - was blocked due to swap throttling
|
|
+ * - is not blocked due to an MSC wait
|
|
*/
|
|
if (pPriv->target_sbc != -1 &&
|
|
pPriv->target_sbc <= pPriv->swap_count) {
|
|
@@ -527,10 +541,11 @@ DRI2WakeClient(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
|
|
AttendClient(pPriv->blockedClient);
|
|
pPriv->blockedClient = NULL;
|
|
- } else if (pPriv->target_sbc == -1) {
|
|
- if (pPriv->blockedClient)
|
|
+ } else if (pPriv->target_sbc == -1 && !pPriv->blockedOnMsc) {
|
|
+ if (pPriv->blockedClient) {
|
|
AttendClient(pPriv->blockedClient);
|
|
- pPriv->blockedClient = NULL;
|
|
+ pPriv->blockedClient = NULL;
|
|
+ }
|
|
}
|
|
}
|
|
|
|
@@ -582,7 +597,7 @@ DRI2WaitSwap(ClientPtr client, DrawablePtr pDrawable)
|
|
pPriv->blockedClient == NULL) {
|
|
ResetCurrentRequest(client);
|
|
client->sequence--;
|
|
- DRI2BlockClient(client, pDrawable);
|
|
+ __DRI2BlockClient(client, pPriv);
|
|
return TRUE;
|
|
}
|
|
|
|
@@ -780,7 +795,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
}
|
|
|
|
pPriv->target_sbc = target_sbc;
|
|
- DRI2BlockClient(client, pDraw);
|
|
+ __DRI2BlockClient(client, pPriv);
|
|
|
|
return Success;
|
|
}
|
|
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
|
|
index 066cc39..e1881ba 100644
|
|
--- a/hw/xfree86/dri2/dri2.h
|
|
+++ b/hw/xfree86/dri2/dri2.h
|
|
@@ -257,6 +257,7 @@ extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
|
|
|
|
extern _X_EXPORT Bool DRI2CanExchange(DrawablePtr pDraw);
|
|
|
|
+/* Note: use *only* for MSC related waits */
|
|
extern _X_EXPORT void DRI2BlockClient(ClientPtr client, DrawablePtr pDraw);
|
|
|
|
extern _X_EXPORT void DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw,
|
|
commit a8de0866130df62c2b1e4653e028a0fe365e0e3a
|
|
Author: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Date: Tue Mar 23 09:47:08 2010 -0700
|
|
|
|
GLX/DRI2: expose swap control extensions if DDX support is present
|
|
|
|
Export DDX swap control status from the DRI2 module and check for it in
|
|
GLX when initializing extensions.
|
|
|
|
Reviewed-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
(cherry picked from commit 165a4a9c7de0fcc6ef6a6421736b412ccb35965e)
|
|
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index edd29b0..e791bf6 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -616,6 +616,7 @@ glxDRILeaveVT (int index, int flags)
|
|
static void
|
|
initializeExtensions(__GLXDRIscreen *screen)
|
|
{
|
|
+ ScreenPtr pScreen = screen->base.pScreen;
|
|
const __DRIextension **extensions;
|
|
int i;
|
|
|
|
@@ -625,10 +626,17 @@ initializeExtensions(__GLXDRIscreen *screen)
|
|
"GLX_MESA_copy_sub_buffer");
|
|
LogMessage(X_INFO, "AIGLX: enabled GLX_MESA_copy_sub_buffer\n");
|
|
|
|
- /* FIXME: only if DDX supports it */
|
|
__glXEnableExtension(screen->glx_enable_bits, "GLX_INTEL_swap_event");
|
|
LogMessage(X_INFO, "AIGLX: enabled GLX_INTEL_swap_event\n");
|
|
|
|
+ if (DRI2HasSwapControl(pScreen)) {
|
|
+ __glXEnableExtension(screen->glx_enable_bits,
|
|
+ "GLX_SGI_swap_control");
|
|
+ __glXEnableExtension(screen->glx_enable_bits,
|
|
+ "GLX_MESA_swap_control");
|
|
+ LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
|
|
+ }
|
|
+
|
|
for (i = 0; extensions[i]; i++) {
|
|
#ifdef __DRI_READ_DRAWABLE
|
|
if (strcmp(extensions[i]->name, __DRI_READ_DRAWABLE) == 0) {
|
|
@@ -639,19 +647,6 @@ initializeExtensions(__GLXDRIscreen *screen)
|
|
}
|
|
#endif
|
|
|
|
-#ifdef __DRI_SWAP_CONTROL
|
|
- if (strcmp(extensions[i]->name, __DRI_SWAP_CONTROL) == 0) {
|
|
- screen->swapControl =
|
|
- (const __DRIswapControlExtension *) extensions[i];
|
|
- __glXEnableExtension(screen->glx_enable_bits,
|
|
- "GLX_SGI_swap_control");
|
|
- __glXEnableExtension(screen->glx_enable_bits,
|
|
- "GLX_MESA_swap_control");
|
|
-
|
|
- LogMessage(X_INFO, "AIGLX: enabled GLX_SGI_swap_control and GLX_MESA_swap_control\n");
|
|
- }
|
|
-#endif
|
|
-
|
|
#ifdef __DRI_TEX_BUFFER
|
|
if (strcmp(extensions[i]->name, __DRI_TEX_BUFFER) == 0) {
|
|
screen->texBuffer =
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 8b4c36f..2bdb733 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -831,6 +831,14 @@ DRI2DestroyDrawable(DrawablePtr pDraw)
|
|
}
|
|
|
|
Bool
|
|
+DRI2HasSwapControl(ScreenPtr pScreen)
|
|
+{
|
|
+ DRI2ScreenPtr ds = DRI2GetScreen(pScreen);
|
|
+
|
|
+ return (ds->ScheduleSwap && ds->GetMSC);
|
|
+}
|
|
+
|
|
+Bool
|
|
DRI2Connect(ScreenPtr pScreen, unsigned int driverType, int *fd,
|
|
const char **driverName, const char **deviceName)
|
|
{
|
|
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
|
|
index e1881ba..ce8a5df 100644
|
|
--- a/hw/xfree86/dri2/dri2.h
|
|
+++ b/hw/xfree86/dri2/dri2.h
|
|
@@ -188,6 +188,8 @@ extern _X_EXPORT Bool DRI2ScreenInit(ScreenPtr pScreen,
|
|
|
|
extern _X_EXPORT void DRI2CloseScreen(ScreenPtr pScreen);
|
|
|
|
+extern _X_EXPORT Bool DRI2HasSwapControl(ScreenPtr pScreen);
|
|
+
|
|
extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
|
|
unsigned int driverType,
|
|
int *fd,
|
|
commit a847cc9bce744cab72637d62bc6bd45237bd3de5
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Sat May 1 13:07:46 2010 -0400
|
|
|
|
dix: Update element count in FreeResource*()
|
|
|
|
FreeResource() keeps clientTable[cid].elements up to date with the
|
|
number of resources allocated to the client. The other free
|
|
resource functions (FreeResourceByType(),
|
|
FreeClientNeverRetainResources() and FreeClientResources()) don't
|
|
maintain this invariant.
|
|
|
|
Typically, the only consequence is that the element count is too high
|
|
and we end up allocating the hash table bigger than necessary. However,
|
|
FreeResource() also relies on the element count to restart the search if
|
|
the list of resources has been changed during a resource destruction
|
|
callback. Since FreeResourceByType() doesn't update the count, if we call
|
|
that from a resource destruction callback from FreeResource(), the
|
|
loop isn't restarted and we end up following an invalid next pointer.
|
|
|
|
Furthermore, LookupClientResourceComplex() and
|
|
FreeClientNeverRetainResources() don't use the element count to detect
|
|
if a callback deleted a resource and may end up following an invalid
|
|
next pointer if the resource system is called into recursively.
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Reviewed-by: Keith Packard <keithp@keithp.com>
|
|
(cherry picked from commit 6d7ba5e0fcb5d1bce6bb213dec009f3a0f802d26)
|
|
|
|
diff --git a/dix/resource.c b/dix/resource.c
|
|
index 91d0cfb..ab3762e 100644
|
|
--- a/dix/resource.c
|
|
+++ b/dix/resource.c
|
|
@@ -589,6 +589,7 @@ FreeResourceByType(XID id, RESTYPE type, Bool skipFree)
|
|
res->value, TypeNameString(res->type));
|
|
#endif
|
|
*prev = res->next;
|
|
+ clientTable[cid].elements--;
|
|
|
|
CallResourceStateCallback(ResourceStateFreeing, res);
|
|
|
|
@@ -734,12 +735,14 @@ FreeClientNeverRetainResources(ClientPtr client)
|
|
ResourcePtr *resources;
|
|
ResourcePtr this;
|
|
ResourcePtr *prev;
|
|
- int j;
|
|
+ int j, elements;
|
|
+ int *eltptr;
|
|
|
|
if (!client)
|
|
return;
|
|
|
|
resources = clientTable[client->index].resources;
|
|
+ eltptr = &clientTable[client->index].elements;
|
|
for (j=0; j < clientTable[client->index].buckets; j++)
|
|
{
|
|
prev = &resources[j];
|
|
@@ -753,11 +756,15 @@ FreeClientNeverRetainResources(ClientPtr client)
|
|
this->value, TypeNameString(this->type));
|
|
#endif
|
|
*prev = this->next;
|
|
+ clientTable[client->index].elements--;
|
|
|
|
CallResourceStateCallback(ResourceStateFreeing, this);
|
|
|
|
+ elements = *eltptr;
|
|
(*DeleteFuncs[rtype & TypeMask])(this->value, this->id);
|
|
xfree(this);
|
|
+ if (*eltptr != elements)
|
|
+ prev = &resources[j]; /* prev may no longer be valid */
|
|
}
|
|
else
|
|
prev = &this->next;
|
|
@@ -804,6 +811,7 @@ FreeClientResources(ClientPtr client)
|
|
this->value, TypeNameString(this->type));
|
|
#endif
|
|
*head = this->next;
|
|
+ clientTable[client->index].elements--;
|
|
|
|
CallResourceStateCallback(ResourceStateFreeing, this);
|
|
|
|
commit 44521bb9d03a0b7af10f89c98e51bd4109fec327
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Sat May 1 13:13:54 2010 -0400
|
|
|
|
glxdri2: Hard-code the extension version we need
|
|
|
|
If we use the #define'd version from dri_interface.h, the server will
|
|
require at least that version of the extension. If we're compiling against
|
|
a dri_interface.h with a newer version we don't really require, glxdri2
|
|
will require a too high version of the extension.
|
|
|
|
The right approach is to just hard-code the version we need instead of
|
|
using the #defines.
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
|
|
Reviewed-by: Adam Jackson <ajax@redhat.com>
|
|
(cherry picked from commit 4a8a615d01b9ed18c272414bd11dc2fc661727e5)
|
|
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index e791bf6..e84c28b 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -658,7 +658,7 @@ initializeExtensions(__GLXDRIscreen *screen)
|
|
|
|
#ifdef __DRI2_FLUSH
|
|
if (strcmp(extensions[i]->name, __DRI2_FLUSH) == 0 &&
|
|
- extensions[i]->version >= __DRI2_FLUSH_VERSION) {
|
|
+ extensions[i]->version >= 3) {
|
|
screen->flush = (__DRI2flushExtension *) extensions[i];
|
|
}
|
|
#endif
|
|
@@ -718,11 +718,11 @@ __glXDRIscreenProbe(ScreenPtr pScreen)
|
|
|
|
for (i = 0; extensions[i]; i++) {
|
|
if (strcmp(extensions[i]->name, __DRI_CORE) == 0 &&
|
|
- extensions[i]->version >= __DRI_CORE_VERSION) {
|
|
+ extensions[i]->version >= 1) {
|
|
screen->core = (const __DRIcoreExtension *) extensions[i];
|
|
}
|
|
if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 &&
|
|
- extensions[i]->version >= __DRI_DRI2_VERSION) {
|
|
+ extensions[i]->version >= 1) {
|
|
screen->dri2 = (const __DRIdri2Extension *) extensions[i];
|
|
}
|
|
}
|
|
commit 95f56176255d5b689b06793d9cbeed36c6a46227
|
|
Author: Kristian Høgsberg <krh@bitplanet.net>
|
|
Date: Sat May 1 13:15:00 2010 -0400
|
|
|
|
list.h: Add list_for_each_entry_safe()
|
|
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
Reviewed-by: Adam Jackson <ajax@redhat.com>
|
|
(cherry picked from commit 32381363cd8f43aeb741bad70bcf96a287dac0c9)
|
|
|
|
diff --git a/include/list.h b/include/list.h
|
|
index a126a65..89dc29d 100644
|
|
--- a/include/list.h
|
|
+++ b/include/list.h
|
|
@@ -94,4 +94,10 @@ list_is_empty(struct list *head)
|
|
&pos->member != (head); \
|
|
pos = __container_of(pos->member.next, pos, member))
|
|
|
|
+#define list_for_each_entry_safe(pos, next, head, member) \
|
|
+ for (pos = __container_of((head)->next, pos, member), \
|
|
+ next = __container_of(pos->member.next, pos, member); \
|
|
+ &pos->member != (head); \
|
|
+ pos = next, next = __container_of(next->member.next, next, member))
|
|
+
|
|
#endif
|
|
commit 7faff42deb4b5a71504377375eba95c3cac2e013
|
|
Author: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Wed Jun 2 11:11:21 2010 +1000
|
|
|
|
Revert "Revert "DRI2: Track DRI2 drawables as resources, not privates""
|
|
|
|
This reverts commit c394b17266301d363a9e234f58f8015f74e01307. Follow-up
|
|
patch should fix the reason this was reverted in the first place.
|
|
|
|
Conflicts:
|
|
|
|
hw/xfree86/dri2/dri2.c
|
|
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index e84c28b..2975bb3 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -105,11 +105,6 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
|
|
|
|
(*core->destroyDrawable)(private->driDrawable);
|
|
|
|
- /* If the X window was destroyed, the dri DestroyWindow hook will
|
|
- * aready have taken care of this, so only call if pDraw isn't NULL. */
|
|
- if (drawable->pDraw != NULL)
|
|
- DRI2DestroyDrawable(drawable->pDraw);
|
|
-
|
|
__glXDrawableRelease(drawable);
|
|
|
|
xfree(private);
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 2bdb733..e8985b0 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -48,15 +48,14 @@
|
|
CARD8 dri2_major; /* version of DRI2 supported by DDX */
|
|
CARD8 dri2_minor;
|
|
|
|
-static int dri2ScreenPrivateKeyIndex;
|
|
+static int dri2ScreenPrivateKeyIndex;
|
|
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
|
-static int dri2WindowPrivateKeyIndex;
|
|
-static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
|
|
-static int dri2PixmapPrivateKeyIndex;
|
|
-static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
|
|
+static RESTYPE dri2DrawableRes;
|
|
+
|
|
+typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
|
|
typedef struct _DRI2Drawable {
|
|
- unsigned int refCount;
|
|
+ DRI2ScreenPtr dri2_screen;
|
|
int width;
|
|
int height;
|
|
DRI2BufferPtr *buffers;
|
|
@@ -73,9 +72,8 @@ typedef struct _DRI2Drawable {
|
|
int swap_limit; /* for N-buffering */
|
|
} DRI2DrawableRec, *DRI2DrawablePtr;
|
|
|
|
-typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
-
|
|
typedef struct _DRI2Screen {
|
|
+ ScreenPtr screen;
|
|
unsigned int numDrivers;
|
|
const char **driverNames;
|
|
const char *deviceName;
|
|
@@ -101,45 +99,35 @@ DRI2GetScreen(ScreenPtr pScreen)
|
|
static DRI2DrawablePtr
|
|
DRI2GetDrawable(DrawablePtr pDraw)
|
|
{
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
+ DRI2DrawablePtr pPriv;
|
|
+ int rc;
|
|
|
|
- if (!pDraw)
|
|
+ rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
+ dri2DrawableRes, NULL, DixReadAccess);
|
|
+ if (rc != Success)
|
|
return NULL;
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
|
|
- }
|
|
+ return pPriv;
|
|
}
|
|
|
|
int
|
|
DRI2CreateDrawable(DrawablePtr pDraw)
|
|
{
|
|
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
DRI2DrawablePtr pPriv;
|
|
CARD64 ust;
|
|
+ int rc;
|
|
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv != NULL)
|
|
- {
|
|
- pPriv->refCount++;
|
|
- return Success;
|
|
- }
|
|
+ rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
+ dri2DrawableRes, NULL, DixReadAccess);
|
|
+ if (rc == Success || rc != BadValue)
|
|
+ return rc;
|
|
|
|
pPriv = xalloc(sizeof *pPriv);
|
|
if (pPriv == NULL)
|
|
return BadAlloc;
|
|
|
|
- pPriv->refCount = 1;
|
|
+ pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
|
|
pPriv->width = pDraw->width;
|
|
pPriv->height = pDraw->height;
|
|
pPriv->buffers = NULL;
|
|
@@ -158,43 +146,30 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->last_swap_msc = 0;
|
|
pPriv->last_swap_ust = 0;
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
|
|
- }
|
|
+ if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
|
|
+ return BadAlloc;
|
|
|
|
return Success;
|
|
}
|
|
|
|
-static void
|
|
-DRI2FreeDrawable(DrawablePtr pDraw)
|
|
+static int DRI2DrawableGone(pointer p, XID id)
|
|
{
|
|
- DRI2DrawablePtr pPriv;
|
|
- WindowPtr pWin;
|
|
- PixmapPtr pPixmap;
|
|
+ DRI2DrawablePtr pPriv = p;
|
|
+ DRI2ScreenPtr ds = pPriv->dri2_screen;
|
|
+ DrawablePtr root;
|
|
+ int i;
|
|
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
- return;
|
|
+ root = &WindowTable[ds->screen->myNum]->drawable;
|
|
+ if (pPriv->buffers != NULL) {
|
|
+ for (i = 0; i < pPriv->bufferCount; i++)
|
|
+ (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
|
|
+
|
|
+ xfree(pPriv->buffers);
|
|
+ }
|
|
|
|
xfree(pPriv);
|
|
|
|
- if (pDraw->type == DRAWABLE_WINDOW)
|
|
- {
|
|
- pWin = (WindowPtr) pDraw;
|
|
- dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
|
|
- }
|
|
- else
|
|
- {
|
|
- pPixmap = (PixmapPtr) pDraw;
|
|
- dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
|
|
- }
|
|
+ return Success;
|
|
}
|
|
|
|
static int
|
|
@@ -506,9 +481,6 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
pPriv->blockedClient = NULL;
|
|
pPriv->blockedOnMsc = FALSE;
|
|
|
|
- /* If there's still a swap pending, let DRI2SwapComplete free it */
|
|
- if (pPriv->refCount == 0 && pPriv->swapsPending == 0)
|
|
- DRI2FreeDrawable(pDraw);
|
|
}
|
|
|
|
static void
|
|
@@ -576,13 +548,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame,
|
|
pPriv->last_swap_ust = ust;
|
|
|
|
DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec);
|
|
-
|
|
- /*
|
|
- * It's normal for the app to have exited with a swap outstanding, but
|
|
- * don't free the drawable until they're all complete.
|
|
- */
|
|
- if (pPriv->swapsPending == 0 && pPriv->refCount == 0)
|
|
- DRI2FreeDrawable(pDraw);
|
|
}
|
|
|
|
Bool
|
|
@@ -750,7 +715,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
Bool ret;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL || pPriv->refCount == 0)
|
|
+ if (pPriv == NULL)
|
|
return BadDrawable;
|
|
|
|
/* Old DDX just completes immediately */
|
|
@@ -774,7 +739,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
DRI2DrawablePtr pPriv;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL || pPriv->refCount == 0)
|
|
+ if (pPriv == NULL)
|
|
return BadDrawable;
|
|
|
|
/* target_sbc == 0 means to block until all pending swaps are
|
|
@@ -800,36 +765,6 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
return Success;
|
|
}
|
|
|
|
-void
|
|
-DRI2DestroyDrawable(DrawablePtr pDraw)
|
|
-{
|
|
- DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
- DRI2DrawablePtr pPriv;
|
|
-
|
|
- pPriv = DRI2GetDrawable(pDraw);
|
|
- if (pPriv == NULL)
|
|
- return;
|
|
-
|
|
- pPriv->refCount--;
|
|
- if (pPriv->refCount > 0)
|
|
- return;
|
|
-
|
|
- if (pPriv->buffers != NULL) {
|
|
- int i;
|
|
-
|
|
- for (i = 0; i < pPriv->bufferCount; i++)
|
|
- (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
|
|
-
|
|
- xfree(pPriv->buffers);
|
|
- }
|
|
-
|
|
- /* If the window is destroyed while we have a swap or wait pending, don't
|
|
- * actually free the priv yet. We'll need it in the DRI2SwapComplete()
|
|
- * callback and we'll free it there once we're done. */
|
|
- if (!pPriv->swapsPending && !pPriv->blockedClient)
|
|
- DRI2FreeDrawable(pDraw);
|
|
-}
|
|
-
|
|
Bool
|
|
DRI2HasSwapControl(ScreenPtr pScreen)
|
|
{
|
|
@@ -890,6 +825,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info)
|
|
if (!ds)
|
|
return FALSE;
|
|
|
|
+ ds->screen = pScreen;
|
|
ds->fd = info->fd;
|
|
ds->deviceName = info->deviceName;
|
|
dri2_major = 1;
|
|
@@ -961,6 +897,8 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin)
|
|
{
|
|
static Bool setupDone = FALSE;
|
|
|
|
+ dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
+
|
|
if (!setupDone)
|
|
{
|
|
setupDone = TRUE;
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index 094d54d..17df130 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -51,7 +51,6 @@
|
|
#include "xf86Module.h"
|
|
|
|
static ExtensionEntry *dri2Extension;
|
|
-static RESTYPE dri2DrawableRes;
|
|
|
|
static Bool
|
|
validDrawable(ClientPtr client, XID drawable, Mask access_mode,
|
|
@@ -172,11 +171,6 @@ ProcDRI2CreateDrawable(ClientPtr client)
|
|
if (status != Success)
|
|
return status;
|
|
|
|
- if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) {
|
|
- DRI2DestroyDrawable(pDrawable);
|
|
- return BadAlloc;
|
|
- }
|
|
-
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -192,8 +186,6 @@ ProcDRI2DestroyDrawable(ClientPtr client)
|
|
&pDrawable, &status))
|
|
return status;
|
|
|
|
- FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE);
|
|
-
|
|
return client->noClientException;
|
|
}
|
|
|
|
@@ -627,25 +619,11 @@ SProcDRI2Dispatch (ClientPtr client)
|
|
}
|
|
}
|
|
|
|
-static int DRI2DrawableGone(pointer p, XID id)
|
|
-{
|
|
- DrawablePtr pDrawable = p;
|
|
-
|
|
- DRI2DestroyDrawable(pDrawable);
|
|
-
|
|
- return Success;
|
|
-}
|
|
-
|
|
int DRI2EventBase;
|
|
|
|
static void
|
|
DRI2ExtensionInit(void)
|
|
{
|
|
- dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable");
|
|
-
|
|
- if (!dri2DrawableRes)
|
|
- return;
|
|
-
|
|
dri2Extension = AddExtension(DRI2_NAME,
|
|
DRI2NumberEvents,
|
|
DRI2NumberErrors,
|
|
commit 598603021f6c4fa64161366177e93de67511bc2e
|
|
Author: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Wed Jun 2 11:13:17 2010 +1000
|
|
|
|
dri2: Take an XID for tracking the DRI2 drawable
|
|
|
|
Some pixmaps (window pixmaps and scratch pixmaps) don't have the
|
|
drawable->id set and thus DRI2 gets confused when using that field
|
|
for looking up the DRI2 drawable. Go back to using privates for getting
|
|
at the DRI2 drawable from a DrawablePtr. We need to keep the resource
|
|
tracking in place so we can remove the DRI2 drawable when the X resource
|
|
it was created for goes away. Additionally, we also now track the DRI2
|
|
drawable using a client XID so we can reclaim the DRI2 drawable even if
|
|
the client goes before the drawable and doesn't destroy the DRI2 drawable.
|
|
|
|
Tested-by: Owen W. Taylor <otaylor@fishsoup.net>
|
|
Signed-off-by: Kristian Høgsberg <krh@bitplanet.net>
|
|
(cherry picked from commit 9de0e31746d5f0d9d39d11c94ec3cbc04a9935fc)
|
|
|
|
Conflicts:
|
|
|
|
hw/xfree86/dri2/dri2.c
|
|
|
|
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
|
|
index 087d52e..ec3bbe6 100644
|
|
--- a/glx/glxcmds.c
|
|
+++ b/glx/glxcmds.c
|
|
@@ -512,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client,
|
|
if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error))
|
|
return NULL;
|
|
|
|
- pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen,
|
|
- pDraw, GLX_DRAWABLE_WINDOW,
|
|
+ pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen,
|
|
+ pDraw, drawId,
|
|
+ GLX_DRAWABLE_WINDOW,
|
|
drawId, glxc->config);
|
|
|
|
/* since we are creating the drawablePrivate, drawId should be new */
|
|
@@ -1104,15 +1105,17 @@ __glXDrawableRelease(__GLXdrawable *drawable)
|
|
}
|
|
|
|
static int
|
|
-DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config,
|
|
- DrawablePtr pDraw, XID glxDrawableId, int type)
|
|
+DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen,
|
|
+ __GLXconfig *config, DrawablePtr pDraw, XID drawableId,
|
|
+ XID glxDrawableId, int type)
|
|
{
|
|
__GLXdrawable *pGlxDraw;
|
|
|
|
if (pGlxScreen->pScreen != pDraw->pScreen)
|
|
return BadMatch;
|
|
|
|
- pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type,
|
|
+ pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw,
|
|
+ drawableId, type,
|
|
glxDrawableId, config);
|
|
if (pGlxDraw == NULL)
|
|
return BadAlloc;
|
|
@@ -1125,7 +1128,7 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf
|
|
/* Add the glx drawable under the XID of the underlying X drawable
|
|
* too. That way we'll get a callback in DrawableGone and can
|
|
* clean up properly when the drawable is destroyed. */
|
|
- if (pDraw->id != glxDrawableId &&
|
|
+ if (drawableId != glxDrawableId &&
|
|
!AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) {
|
|
pGlxDraw->destroy (pGlxDraw);
|
|
return BadAlloc;
|
|
@@ -1153,7 +1156,7 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config
|
|
return BadPixmap;
|
|
}
|
|
|
|
- err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw,
|
|
+ err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId,
|
|
glxDrawableId, GLX_DRAWABLE_PIXMAP);
|
|
|
|
return err;
|
|
@@ -1316,7 +1319,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId,
|
|
return BadAlloc;
|
|
|
|
return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable,
|
|
- glxDrawableId, GLX_DRAWABLE_PBUFFER);
|
|
+ glxDrawableId, glxDrawableId,
|
|
+ GLX_DRAWABLE_PBUFFER);
|
|
}
|
|
|
|
int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc)
|
|
@@ -1439,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc)
|
|
return err;
|
|
|
|
return DoCreateGLXDrawable(client, pGlxScreen, config,
|
|
- pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW);
|
|
+ pDraw, req->window,
|
|
+ req->glxwindow, GLX_DRAWABLE_WINDOW);
|
|
}
|
|
|
|
int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc)
|
|
diff --git a/glx/glxdri.c b/glx/glxdri.c
|
|
index 21e44d1..e4870c3 100644
|
|
--- a/glx/glxdri.c
|
|
+++ b/glx/glxdri.c
|
|
@@ -682,10 +682,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
|
|
}
|
|
|
|
static __GLXdrawable *
|
|
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
+__glXDRIscreenCreateDrawable(ClientPtr client,
|
|
+ __GLXscreen *screen,
|
|
DrawablePtr pDraw,
|
|
- int type,
|
|
XID drawId,
|
|
+ int type,
|
|
+ XID glxDrawId,
|
|
__GLXconfig *glxConfig)
|
|
{
|
|
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
|
|
@@ -699,7 +701,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
return NULL;
|
|
|
|
if (!__glXDrawableInit(&private->base, screen,
|
|
- pDraw, type, drawId, glxConfig)) {
|
|
+ pDraw, type, glxDrawId, glxConfig)) {
|
|
xfree(private);
|
|
return NULL;
|
|
}
|
|
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
|
|
index 2975bb3..a580df3 100644
|
|
--- a/glx/glxdri2.c
|
|
+++ b/glx/glxdri2.c
|
|
@@ -430,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen,
|
|
}
|
|
|
|
static __GLXdrawable *
|
|
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
+__glXDRIscreenCreateDrawable(ClientPtr client,
|
|
+ __GLXscreen *screen,
|
|
DrawablePtr pDraw,
|
|
- int type,
|
|
XID drawId,
|
|
+ int type,
|
|
+ XID glxDrawId,
|
|
__GLXconfig *glxConfig)
|
|
{
|
|
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
|
|
@@ -446,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
|
|
private->screen = driScreen;
|
|
if (!__glXDrawableInit(&private->base, screen,
|
|
- pDraw, type, drawId, glxConfig)) {
|
|
+ pDraw, type, glxDrawId, glxConfig)) {
|
|
xfree(private);
|
|
return NULL;
|
|
}
|
|
@@ -457,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
private->base.waitGL = __glXDRIdrawableWaitGL;
|
|
private->base.waitX = __glXDRIdrawableWaitX;
|
|
|
|
- if (DRI2CreateDrawable(pDraw)) {
|
|
+ if (DRI2CreateDrawable(client, pDraw, drawId)) {
|
|
xfree(private);
|
|
return NULL;
|
|
}
|
|
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
|
|
index c647d83..6a34393 100644
|
|
--- a/glx/glxdriswrast.c
|
|
+++ b/glx/glxdriswrast.c
|
|
@@ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val)
|
|
}
|
|
|
|
static __GLXdrawable *
|
|
-__glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
+__glXDRIscreenCreateDrawable(ClientPtr client,
|
|
+ __GLXscreen *screen,
|
|
DrawablePtr pDraw,
|
|
- int type,
|
|
XID drawId,
|
|
+ int type,
|
|
+ XID glxDrawId,
|
|
__GLXconfig *glxConfig)
|
|
{
|
|
__GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen;
|
|
@@ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen,
|
|
|
|
private->screen = driScreen;
|
|
if (!__glXDrawableInit(&private->base, screen,
|
|
- pDraw, type, drawId, glxConfig)) {
|
|
+ pDraw, type, glxDrawId, glxConfig)) {
|
|
xfree(private);
|
|
return NULL;
|
|
}
|
|
diff --git a/glx/glxscreens.h b/glx/glxscreens.h
|
|
index d52099f..861e03c 100644
|
|
--- a/glx/glxscreens.h
|
|
+++ b/glx/glxscreens.h
|
|
@@ -134,10 +134,12 @@ struct __GLXscreen {
|
|
__GLXconfig *modes,
|
|
__GLXcontext *shareContext);
|
|
|
|
- __GLXdrawable *(*createDrawable)(__GLXscreen *context,
|
|
+ __GLXdrawable *(*createDrawable)(ClientPtr client,
|
|
+ __GLXscreen *context,
|
|
DrawablePtr pDraw,
|
|
- int type,
|
|
XID drawId,
|
|
+ int type,
|
|
+ XID glxDrawId,
|
|
__GLXconfig *modes);
|
|
int (*swapInterval) (__GLXdrawable *drawable,
|
|
int interval);
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index e8985b0..dd9bb41 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -37,6 +37,7 @@
|
|
#include <errno.h>
|
|
#include <xf86drm.h>
|
|
#include "xf86Module.h"
|
|
+#include "list.h"
|
|
#include "scrnintstr.h"
|
|
#include "windowstr.h"
|
|
#include "dixstruct.h"
|
|
@@ -50,12 +51,18 @@ CARD8 dri2_minor;
|
|
|
|
static int dri2ScreenPrivateKeyIndex;
|
|
static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex;
|
|
+static int dri2WindowPrivateKeyIndex;
|
|
+static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex;
|
|
+static int dri2PixmapPrivateKeyIndex;
|
|
+static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex;
|
|
static RESTYPE dri2DrawableRes;
|
|
|
|
typedef struct _DRI2Screen *DRI2ScreenPtr;
|
|
|
|
typedef struct _DRI2Drawable {
|
|
DRI2ScreenPtr dri2_screen;
|
|
+ DrawablePtr drawable;
|
|
+ struct list reference_list;
|
|
int width;
|
|
int height;
|
|
DRI2BufferPtr *buffers;
|
|
@@ -74,6 +81,7 @@ typedef struct _DRI2Drawable {
|
|
|
|
typedef struct _DRI2Screen {
|
|
ScreenPtr screen;
|
|
+ int refcnt;
|
|
unsigned int numDrivers;
|
|
const char **driverNames;
|
|
const char *deviceName;
|
|
@@ -99,35 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen)
|
|
static DRI2DrawablePtr
|
|
DRI2GetDrawable(DrawablePtr pDraw)
|
|
{
|
|
- DRI2DrawablePtr pPriv;
|
|
- int rc;
|
|
-
|
|
- rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
- dri2DrawableRes, NULL, DixReadAccess);
|
|
- if (rc != Success)
|
|
- return NULL;
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
|
|
- return pPriv;
|
|
+ if (pDraw->type == DRAWABLE_WINDOW) {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey);
|
|
+ } else {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey);
|
|
+ }
|
|
}
|
|
|
|
-int
|
|
-DRI2CreateDrawable(DrawablePtr pDraw)
|
|
+static DRI2DrawablePtr
|
|
+DRI2AllocateDrawable(DrawablePtr pDraw)
|
|
{
|
|
DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen);
|
|
DRI2DrawablePtr pPriv;
|
|
CARD64 ust;
|
|
- int rc;
|
|
-
|
|
- rc = dixLookupResourceByType((pointer *) &pPriv, pDraw->id,
|
|
- dri2DrawableRes, NULL, DixReadAccess);
|
|
- if (rc == Success || rc != BadValue)
|
|
- return rc;
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
|
|
pPriv = xalloc(sizeof *pPriv);
|
|
if (pPriv == NULL)
|
|
- return BadAlloc;
|
|
+ return NULL;
|
|
|
|
- pPriv->dri2_screen = DRI2GetScreen(pDraw->pScreen);
|
|
+ pPriv->dri2_screen = ds;
|
|
+ pPriv->drawable = pDraw;
|
|
pPriv->width = pDraw->width;
|
|
pPriv->height = pDraw->height;
|
|
pPriv->buffers = NULL;
|
|
@@ -145,9 +151,77 @@ DRI2CreateDrawable(DrawablePtr pDraw)
|
|
pPriv->swap_limit = 1; /* default to double buffering */
|
|
pPriv->last_swap_msc = 0;
|
|
pPriv->last_swap_ust = 0;
|
|
+ list_init(&pPriv->reference_list);
|
|
|
|
- if (!AddResource(pDraw->id, dri2DrawableRes, pPriv))
|
|
+ if (pDraw->type == DRAWABLE_WINDOW) {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv);
|
|
+ } else {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv);
|
|
+ }
|
|
+
|
|
+ return pPriv;
|
|
+}
|
|
+
|
|
+typedef struct DRI2DrawableRefRec {
|
|
+ XID id;
|
|
+ XID dri2_id;
|
|
+ struct list link;
|
|
+} DRI2DrawableRefRec, *DRI2DrawableRefPtr;
|
|
+
|
|
+static DRI2DrawableRefPtr
|
|
+DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id)
|
|
+{
|
|
+ DRI2DrawableRefPtr ref;
|
|
+
|
|
+ list_for_each_entry(ref, &pPriv->reference_list, link) {
|
|
+ if (ref->id == id)
|
|
+ return ref;
|
|
+ }
|
|
+
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static int
|
|
+DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id)
|
|
+{
|
|
+ DRI2DrawableRefPtr ref;
|
|
+
|
|
+ ref = malloc(sizeof *ref);
|
|
+ if (ref == NULL)
|
|
+ return BadAlloc;
|
|
+
|
|
+ if (!AddResource(dri2_id, dri2DrawableRes, pPriv))
|
|
+ return BadAlloc;
|
|
+ if (!DRI2LookupDrawableRef(pPriv, id))
|
|
+ if (!AddResource(id, dri2DrawableRes, pPriv))
|
|
+ return BadAlloc;
|
|
+
|
|
+ ref->id = id;
|
|
+ ref->dri2_id = dri2_id;
|
|
+ list_add(&ref->link, &pPriv->reference_list);
|
|
+
|
|
+ return Success;
|
|
+}
|
|
+
|
|
+int
|
|
+DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id)
|
|
+{
|
|
+ DRI2DrawablePtr pPriv;
|
|
+ XID dri2_id;
|
|
+ int rc;
|
|
+
|
|
+ pPriv = DRI2GetDrawable(pDraw);
|
|
+ if (pPriv == NULL)
|
|
+ pPriv = DRI2AllocateDrawable(pDraw);
|
|
+ if (pPriv == NULL)
|
|
return BadAlloc;
|
|
+
|
|
+ dri2_id = FakeClientID(client->index);
|
|
+ rc = DRI2AddDrawableRef(pPriv, id, dri2_id);
|
|
+ if (rc != Success)
|
|
+ return rc;
|
|
|
|
return Success;
|
|
}
|
|
@@ -156,13 +230,45 @@ static int DRI2DrawableGone(pointer p, XID id)
|
|
{
|
|
DRI2DrawablePtr pPriv = p;
|
|
DRI2ScreenPtr ds = pPriv->dri2_screen;
|
|
- DrawablePtr root;
|
|
+ DRI2DrawableRefPtr ref, next;
|
|
+ WindowPtr pWin;
|
|
+ PixmapPtr pPixmap;
|
|
+ DrawablePtr pDraw;
|
|
int i;
|
|
|
|
- root = &WindowTable[ds->screen->myNum]->drawable;
|
|
+ list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) {
|
|
+ if (ref->dri2_id == id) {
|
|
+ list_del(&ref->link);
|
|
+ /* If this was the last ref under this X drawable XID,
|
|
+ * unregister the X drawable resource. */
|
|
+ if (!DRI2LookupDrawableRef(pPriv, ref->id))
|
|
+ FreeResourceByType(ref->id, dri2DrawableRes, TRUE);
|
|
+ free(ref);
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ if (ref->id == id) {
|
|
+ list_del(&ref->link);
|
|
+ FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE);
|
|
+ free(ref);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (!list_is_empty(&pPriv->reference_list))
|
|
+ return Success;
|
|
+
|
|
+ pDraw = pPriv->drawable;
|
|
+ if (pDraw->type == DRAWABLE_WINDOW) {
|
|
+ pWin = (WindowPtr) pDraw;
|
|
+ dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL);
|
|
+ } else {
|
|
+ pPixmap = (PixmapPtr) pDraw;
|
|
+ dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL);
|
|
+ }
|
|
+
|
|
if (pPriv->buffers != NULL) {
|
|
for (i = 0; i < pPriv->bufferCount; i++)
|
|
- (*ds->DestroyBuffer)(root, pPriv->buffers[i]);
|
|
+ (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]);
|
|
|
|
xfree(pPriv->buffers);
|
|
}
|
|
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
|
|
index ce8a5df..5415a0b 100644
|
|
--- a/hw/xfree86/dri2/dri2.h
|
|
+++ b/hw/xfree86/dri2/dri2.h
|
|
@@ -198,7 +198,8 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen,
|
|
|
|
extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic);
|
|
|
|
-extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw);
|
|
+extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client,
|
|
+ DrawablePtr pDraw, XID id);
|
|
|
|
extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw);
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index 17df130..58eaa10 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -167,7 +167,7 @@ ProcDRI2CreateDrawable(ClientPtr client)
|
|
&pDrawable, &status))
|
|
return status;
|
|
|
|
- status = DRI2CreateDrawable(pDrawable);
|
|
+ status = DRI2CreateDrawable(client, pDrawable, stuff->drawable);
|
|
if (status != Success)
|
|
return status;
|
|
|
|
commit 421f5dfdd8b566dc07b4606f0edec487b3ead3d9
|
|
Author: Peter Hutterer <peter.hutterer@who-t.net>
|
|
Date: Fri Jun 11 11:08:31 2010 +1000
|
|
|
|
DRI2: Don't return junk reply instead of blocking in glXWaitForSbcOML()
|
|
|
|
DRI2WaitSBC() didn't block if requested targetSBC wasn't yet reached.
|
|
|
|
Instead it returned a xreply with uninitialized junk return values, then
|
|
blocked the connection until targetSBC was reached.
|
|
|
|
Therefore the client didn't block, but continued with bogus return
|
|
values from glXWaitForSbcOML.
|
|
|
|
This patch fixes the problem by implementing DRI2WaitSBC similar
|
|
to the clean and proven DRI2WaitMSC implementation.
|
|
|
|
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
(cherry picked from commit b3548612c7943011f79a910f9a59bb975984d8a6)
|
|
|
|
Conflicts:
|
|
|
|
hw/xfree86/dri2/dri2ext.c
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 2bdb733..7d670ff 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -768,8 +768,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
}
|
|
|
|
int
|
|
-DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
- CARD64 *ust, CARD64 *msc, CARD64 *sbc)
|
|
+DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc)
|
|
{
|
|
DRI2DrawablePtr pPriv;
|
|
|
|
@@ -783,14 +782,13 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc,
|
|
if (target_sbc == 0)
|
|
target_sbc = pPriv->swap_count + pPriv->swapsPending;
|
|
|
|
- /* If current swap count already >= target_sbc,
|
|
+ /* If current swap count already >= target_sbc, reply and
|
|
* return immediately with (ust, msc, sbc) triplet of
|
|
* most recent completed swap.
|
|
*/
|
|
if (pPriv->swap_count >= target_sbc) {
|
|
- *sbc = pPriv->swap_count;
|
|
- *msc = pPriv->last_swap_msc;
|
|
- *ust = pPriv->last_swap_ust;
|
|
+ ProcDRI2WaitMSCReply(client, pPriv->last_swap_ust,
|
|
+ pPriv->last_swap_msc, pPriv->swap_count);
|
|
return Success;
|
|
}
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h
|
|
index ce8a5df..de94c0b 100644
|
|
--- a/hw/xfree86/dri2/dri2.h
|
|
+++ b/hw/xfree86/dri2/dri2.h
|
|
@@ -251,8 +251,7 @@ extern _X_EXPORT int DRI2WaitMSC(ClientPtr client, DrawablePtr pDrawable,
|
|
extern _X_EXPORT int ProcDRI2WaitMSCReply(ClientPtr client, CARD64 ust,
|
|
CARD64 msc, CARD64 sbc);
|
|
extern _X_EXPORT int DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw,
|
|
- CARD64 target_sbc, CARD64 *ust, CARD64 *msc,
|
|
- CARD64 *sbc);
|
|
+ CARD64 target_sbc);
|
|
extern _X_EXPORT Bool DRI2ThrottleClient(ClientPtr client, DrawablePtr pDraw);
|
|
|
|
extern _X_EXPORT Bool DRI2CanFlip(DrawablePtr pDraw);
|
|
diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c
|
|
index 094d54d..627dfc0 100644
|
|
--- a/hw/xfree86/dri2/dri2ext.c
|
|
+++ b/hw/xfree86/dri2/dri2ext.c
|
|
@@ -516,9 +516,8 @@ static int
|
|
ProcDRI2WaitSBC(ClientPtr client)
|
|
{
|
|
REQUEST(xDRI2WaitSBCReq);
|
|
- xDRI2MSCReply rep;
|
|
DrawablePtr pDrawable;
|
|
- CARD64 target, ust, msc, sbc;
|
|
+ CARD64 target;
|
|
int status;
|
|
|
|
REQUEST_SIZE_MATCH(xDRI2WaitSBCReq);
|
|
@@ -528,18 +527,9 @@ ProcDRI2WaitSBC(ClientPtr client)
|
|
return status;
|
|
|
|
target = vals_to_card64(stuff->target_sbc_lo, stuff->target_sbc_hi);
|
|
- status = DRI2WaitSBC(client, pDrawable, target, &ust, &msc, &sbc);
|
|
- if (status != Success)
|
|
- return status;
|
|
+ status = DRI2WaitSBC(client, pDrawable, target);
|
|
|
|
- rep.type = X_Reply;
|
|
- rep.length = 0;
|
|
- rep.sequenceNumber = client->sequence;
|
|
- load_msc_reply(&rep, ust, msc, sbc);
|
|
-
|
|
- WriteToClient(client, sizeof(xDRI2MSCReply), &rep);
|
|
-
|
|
- return client->noClientException;
|
|
+ return status;
|
|
}
|
|
|
|
static int
|
|
commit cc9f6806ac0d45e122c24c0e99c1db70a6d5ca12
|
|
Author: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Date: Sun Jun 13 18:05:26 2010 +0200
|
|
|
|
DRI2/xserver: Don't hang in glXSwapBuffers if drawable moves between crtc's (bug 28383)
|
|
|
|
Detect if a drawable has been moved from an original crtc to a new crtc
|
|
with a lower current vblank count than the original crtc inbetween
|
|
glXSwapBuffers() calls. Reinitialize drawable's last_swap_target
|
|
before scheduling next swap if such a move has taken place.
|
|
|
|
last_swap_target defines the baseline for scheduling the next swap.
|
|
If a movement between crtc's is not taken into account, the swap may
|
|
schedule for a vblank count on the new crtc far in the future, resulting
|
|
in a apparent "hang" of the drawable for a long time.
|
|
|
|
Fixes Bugzilla bug #28383.
|
|
|
|
Signed-off-by: Mario Kleiner <mario.kleiner@tuebingen.mpg.de>
|
|
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
|
|
Signed-off-by: Keith Packard <keithp@keithp.com>
|
|
(cherry picked from commit 75beadd766fed7b12a76e59e57c244e297c2d2cb)
|
|
|
|
diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c
|
|
index 7d670ff..62734d1 100644
|
|
--- a/hw/xfree86/dri2/dri2.c
|
|
+++ b/hw/xfree86/dri2/dri2.c
|
|
@@ -614,6 +614,7 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
DRI2DrawablePtr pPriv;
|
|
DRI2BufferPtr pDestBuffer = NULL, pSrcBuffer = NULL;
|
|
int ret, i;
|
|
+ CARD64 ust, current_msc;
|
|
|
|
pPriv = DRI2GetDrawable(pDraw);
|
|
if (pPriv == NULL) {
|
|
@@ -658,12 +659,26 @@ DRI2SwapBuffers(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc,
|
|
* need to schedule a swap for the last swap target + the swap interval.
|
|
*/
|
|
if (target_msc == 0 && divisor == 0 && remainder == 0) {
|
|
+ /* If the current vblank count of the drawable's crtc is lower
|
|
+ * than the count stored in last_swap_target from a previous swap
|
|
+ * then reinitialize last_swap_target to the current crtc's msc,
|
|
+ * otherwise the swap will hang. This will happen if the drawable
|
|
+ * is moved to a crtc with a lower refresh rate, or a crtc that just
|
|
+ * got enabled.
|
|
+ */
|
|
+ if (!(*ds->GetMSC)(pDraw, &ust, ¤t_msc))
|
|
+ pPriv->last_swap_target = 0;
|
|
+
|
|
+ if (current_msc < pPriv->last_swap_target)
|
|
+ pPriv->last_swap_target = current_msc;
|
|
+
|
|
/*
|
|
* Swap target for this swap is last swap target + swap interval since
|
|
* we have to account for the current swap count, interval, and the
|
|
* number of pending swaps.
|
|
*/
|
|
*swap_target = pPriv->last_swap_target + pPriv->swap_interval;
|
|
+
|
|
} else {
|
|
/* glXSwapBuffersMscOML could have a 0 target_msc, honor it */
|
|
*swap_target = target_msc;
|