summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLionel Landwerlin <lionel.g.landwerlin@intel.com>2014-11-27 10:39:50 +0000
committerXiang, Haihao <haihao.xiang@intel.com>2014-12-14 21:53:40 +0800
commit0804ff786ae178502d6b73d46aa7d56d763e4788 (patch)
tree3b9a6955cee8613291d87bd786809c0bb90b971b
parent5a9e81bde66819bb472c87fcdd82e27bd8917c56 (diff)
x11: check x pixmap is still alive before DRI2DestroyDrawable
Calling vaTerminate() after the pixmaps, given to vaPutSurface(), have been destroyed results in errors coming from the X server. These errors happens because LibVA tries to destroy the DRI2Drawables related to the XPixmaps passed to vaPutSurface(). VA_DRI2Error() has some code to catch these errors and ignore them. The problem is that LibX11 doesn't trigger the extension error handlers unless you're waiting for a response using _XReply(), and there is no defined answer to a DRI2DestroyDrawable message in the DRI2 protocol. The attached patch tries to work around that issue by checking whether the XPixmap is still alive before proceeding with DRI2DestroyDrawable. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
-rw-r--r--va/x11/va_dri2.c100
1 files changed, 80 insertions, 20 deletions
diff --git a/va/x11/va_dri2.c b/va/x11/va_dri2.c
index 1c91bca..b4a4398 100644
--- a/va/x11/va_dri2.c
+++ b/va/x11/va_dri2.c
@@ -47,6 +47,14 @@
static int
VA_DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code);
+static VA_DRI2Buffer *
+VA_DRI2GetBuffers_internal(XExtDisplayInfo *info,
+ Display *dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments,
+ int count,
+ int *outCount);
+
static char va_dri2ExtensionName[] = DRI2_NAME;
static XExtensionInfo _va_dri2_info_data;
static XExtensionInfo *va_dri2Info = &_va_dri2_info_data;
@@ -70,18 +78,30 @@ static XEXT_GENERATE_FIND_DISPLAY (DRI2FindDisplay, va_dri2Info,
&va_dri2ExtensionHooks,
0, NULL)
+static CARD32 _va_resource_x_error_drawable = 0;
+static Bool _va_resource_x_error_matched = False;
+
+#define VA_EnterResourceError(drawable) \
+ do { \
+ _va_resource_x_error_drawable = (drawable); \
+ _va_resource_x_error_matched = False; \
+ } while (0)
+
+#define VA_LeaveResourceError() \
+ do { \
+ _va_resource_x_error_drawable = 0; \
+ } while (0)
+
+#define VA_ResourceErrorMatched() \
+ (_va_resource_x_error_matched)
+
static int
VA_DRI2Error(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
{
- /*
- * If the X drawable was destroyed before the VA drawable, the DRI2 drawable
- * will be gone by the time we call VA_DRI2DestroyDrawable(). So, simply
- * ignore BadDrawable errors in that case.
- */
- if (err->majorCode == codes->major_opcode &&
- err->errorCode == BadDrawable &&
- err->minorCode == X_DRI2DestroyDrawable)
- return True;
+ if (_va_resource_x_error_drawable == err->resourceID) {
+ _va_resource_x_error_matched = True;
+ return True;
+ }
return False;
}
@@ -229,12 +249,34 @@ void VA_DRI2DestroyDrawable(Display *dpy, XID drawable)
{
XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2DestroyDrawableReq *req;
+ unsigned int attachement = 0; // FRONT_LEFT
+ VA_DRI2Buffer *buffers;
XextSimpleCheckExtension (dpy, info, va_dri2ExtensionName);
XSync(dpy, False);
LockDisplay(dpy);
+ /*
+ * We have no way of catching DRI2DestroyDrawable errors because
+ * this message doesn't have a defined answer. So we test whether
+ * the drawable is still alive by sending DRIGetBuffers first and
+ * checking whether we get an error.
+ */
+ VA_EnterResourceError(drawable);
+
+ buffers = VA_DRI2GetBuffers_internal(info, dpy, drawable,
+ NULL, NULL,
+ &attachement, 1, NULL);
+ VA_LeaveResourceError();
+ if (buffers)
+ XFree(buffers);
+ if (VA_ResourceErrorMatched()) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return;
+ }
+
GetReq(DRI2DestroyDrawable, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2DestroyDrawable;
@@ -243,12 +285,12 @@ void VA_DRI2DestroyDrawable(Display *dpy, XID drawable)
SyncHandle();
}
-VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
- int *width, int *height,
- unsigned int *attachments, int count,
- int *outCount)
+VA_DRI2Buffer *VA_DRI2GetBuffers_internal(XExtDisplayInfo *info,
+ Display *dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *outCount)
{
- XExtDisplayInfo *info = DRI2FindDisplay(dpy);
xDRI2GetBuffersReply rep;
xDRI2GetBuffersReq *req;
VA_DRI2Buffer *buffers;
@@ -256,9 +298,6 @@ VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
CARD32 *p;
int i;
- XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
-
- LockDisplay(dpy);
GetReqExtra(DRI2GetBuffers, count * 4, req);
req->reqType = info->codes->major_opcode;
req->dri2ReqType = X_DRI2GetBuffers;
@@ -274,9 +313,12 @@ VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
return NULL;
}
- *width = rep.width;
- *height = rep.height;
- *outCount = rep.count;
+ if (width)
+ *width = rep.width;
+ if (height)
+ *height = rep.height;
+ if (outCount)
+ *outCount = rep.count;
buffers = Xmalloc(rep.count * sizeof buffers[0]);
if (buffers == NULL) {
@@ -295,6 +337,24 @@ VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
buffers[i].flags = repBuffer.flags;
}
+ return buffers;
+}
+
+VA_DRI2Buffer *VA_DRI2GetBuffers(Display *dpy, XID drawable,
+ int *width, int *height,
+ unsigned int *attachments, int count,
+ int *outCount)
+{
+ XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+ VA_DRI2Buffer *buffers;
+
+ XextCheckExtension (dpy, info, va_dri2ExtensionName, False);
+
+ LockDisplay(dpy);
+
+ buffers = VA_DRI2GetBuffers_internal(info, dpy, drawable, width, height,
+ attachments, count, outCount);
+
UnlockDisplay(dpy);
SyncHandle();