[PATCH libdri2] dri2video support

Rob Clark rob.clark at linaro.org
Tue Nov 15 14:49:50 PST 2011


---
 Makefile.am                   |   16 ++-
 include/X11/extensions/dri2.h |   52 +++++++-
 src/Makefile.am               |    2 +-
 src/dri2.c                    |  324 ++++++++++++++++++++++++++++++++---------
 test/Makefile.am              |    6 +-
 test/dri2-nouveau.c           |    2 +-
 test/dri2-omap.c              |    2 +-
 test/dri2test.c               |    4 +-
 test/dri2videotest.c          |  264 +++++++++++++++++++++++++++++++++
 9 files changed, 593 insertions(+), 79 deletions(-)
 create mode 100644 test/dri2videotest.c

diff --git a/Makefile.am b/Makefile.am
index 4a7b6a1..d4ce946 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -43,8 +43,16 @@ endif
 
 if ENABLE_TEST
 SUBDIRS            += test
-bin_PROGRAMS        = dri2test
-dri2test_SOURCES    = 
-dri2test_LDFLAGS    = -no-undefined
-dri2test_LDADD      = test/libdri2test.la src/libdri2.la @DRI2_LIBS@
+bin_PROGRAMS        = dri2test dri2videotest
+
+COMMON_LDFLAGS      = -no-undefined
+COMMON_LDADD        = src/libdri2.la @DRI2_LIBS@
+
+dri2test_SOURCES    =
+dri2test_LDFLAGS    = $(COMMON_LDFLAGS)
+dri2test_LDADD      = test/libdri2test.la $(COMMON_LDADD)
+
+dri2videotest_SOURCES =
+dri2videotest_LDFLAGS = $(COMMON_LDFLAGS)
+dri2videotest_LDADD   = test/libdri2videotest.la $(COMMON_LDADD)
 endif
diff --git a/include/X11/extensions/dri2.h b/include/X11/extensions/dri2.h
index e42cdb6..b15620c 100644
--- a/include/X11/extensions/dri2.h
+++ b/include/X11/extensions/dri2.h
@@ -38,13 +38,14 @@
 #include <X11/extensions/Xfixes.h>
 #include <X11/extensions/extutil.h>
 #include <X11/extensions/dri2tokens.h>
+#include <X11/Xregion.h>
 #include <drm.h>
 
 typedef struct
 {
    unsigned int attachment;
-   unsigned int name;
-   unsigned int pitch;
+   unsigned int names[3];    /* unused entries set to zero.. non-planar formats only use names[0] */
+   unsigned int pitch[3];    /* unused entries set to zero.. non-planar formats only use pitch[0] */
    unsigned int cpp;
    unsigned int flags;
 } DRI2Buffer;
@@ -95,6 +96,16 @@ DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
                          unsigned int *attachments,
                          int count, int *outCount);
 
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.4 or later.
+ * The 'attachments' array is same as with DRI2GetBuffersWithFormat()
+ */
+DRI2Buffer *
+DRI2GetBuffersVid(Display * dpy, XID drawable,
+               int width, int height,
+               unsigned int *attachments, int count, int *outCount);
+
 extern void
 DRI2CopyRegion(Display * dpy, XID drawable,
                XserverRegion region,
@@ -104,6 +115,15 @@ extern void
 DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc, CARD64 divisor,
 		CARD64 remainder, CARD64 *count);
 
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.4 or later.
+ */
+extern void
+DRI2SwapBuffersVid(Display *dpy, XID drawable, CARD64 target_msc,
+		CARD64 divisor, CARD64 remainder, CARD64 *count,
+		unsigned int source, BoxPtr b);
+
 extern Bool
 DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc, CARD64 *sbc);
 
@@ -118,4 +138,32 @@ DRI2WaitSBC(Display *dpy, XID drawable, CARD64 target_sbc, CARD64 *ust,
 extern void
 DRI2SwapInterval(Display *dpy, XID drawable, int interval);
 
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.4 or later.
+ * length in multiple of CARD32's
+ */
+extern void
+DRI2SetAttribute(Display * dpy, XID drawable, Atom attribute,
+		int len, const CARD32 *val);
+
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.4 or later.
+ * The returned attribute should be free'd by caller.. length in
+ * multiple of CARD32's
+ */
+extern Bool
+DRI2GetAttribute(Display * dpy, XID drawable, Atom attribute,
+		int *len, CARD32 **val);
+
+/**
+ * \note
+ * This function is only supported with DRI2 version 1.4 or later.
+ * returned formats should be freed by caller
+ */
+extern Bool
+DRI2GetFormats(Display * dpy, XID drawable, unsigned int *pnformats,
+		unsigned int **pformats);
+
 #endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 07f2492..ac3494a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,7 @@ libdri2_la_SOURCES = \
          dri2.c
 
 libdri2_la_LIBADD = @DRI2_LIBS@
-AM_CFLAGS = $(CWARNFLAGS) @DRI2_CFLAGS@ -I$(top_srcdir)/include @MALLOC_ZERO_CFLAGS@
+AM_CFLAGS =-I$(top_srcdir)/include $(CWARNFLAGS) @DRI2_CFLAGS@ @MALLOC_ZERO_CFLAGS@
 
 libdri2_la_LDFLAGS = -version-number 1:0:0 -no-undefined
 
diff --git a/src/dri2.c b/src/dri2.c
index 3e5ee21..c8c0726 100644
--- a/src/dri2.c
+++ b/src/dri2.c
@@ -69,6 +69,7 @@ typedef struct {
 	struct list list;
 	Display *dpy;
 	const DRI2EventOps *ops;
+	int major, minor;
 } DRI2Display;
 
 static DRI2Display * dpy2dri(Display *dpy)
@@ -201,6 +202,7 @@ Bool
 DRI2QueryVersion(Display * dpy, int *major, int *minor)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+   DRI2Display *dri2dpy = dpy2dri(dpy);
    xDRI2QueryVersionReply rep;
    xDRI2QueryVersionReq *req;
    int i, nevents;
@@ -218,8 +220,8 @@ DRI2QueryVersion(Display * dpy, int *major, int *minor)
       SyncHandle();
       return False;
    }
-   *major = rep.majorVersion;
-   *minor = rep.minorVersion;
+   dri2dpy->major = *major = rep.majorVersion;
+   dri2dpy->minor = *minor = rep.minorVersion;
    UnlockDisplay(dpy);
    SyncHandle();
 
@@ -365,10 +367,9 @@ DRI2DestroyDrawable(Display * dpy, XID drawable)
    SyncHandle();
 }
 
-DRI2Buffer *
-DRI2GetBuffers(Display * dpy, XID drawable,
-               int *width, int *height,
-               unsigned int *attachments, int count, int *outCount)
+static DRI2Buffer *
+getbuffers(Display *dpy, XID drawable, int *width, int *height,
+		unsigned int *attachments, int count, int *outCount, int dri2ReqType)
 {
    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
    xDRI2GetBuffersReply rep;
@@ -376,18 +377,27 @@ DRI2GetBuffers(Display * dpy, XID drawable,
    DRI2Buffer *buffers;
    xDRI2Buffer repBuffer;
    CARD32 *p;
-   int i;
+   int i, nattachments;
+
+   /* DRI2GetBuffersWithFormat has interleaved attachment+format in
+    * attachments[] array, so length of array is 2x as long..
+    */
+   if (dri2ReqType == X_DRI2GetBuffersWithFormat) {
+	   nattachments = 2 * count;
+   } else {
+	   nattachments = count;
+   }
 
    XextCheckExtension(dpy, info, dri2ExtensionName, False);
 
    LockDisplay(dpy);
-   GetReqExtra(DRI2GetBuffers, count * 4, req);
+   GetReqExtra(DRI2GetBuffers, nattachments * 4, req);
    req->reqType = info->codes->major_opcode;
-   req->dri2ReqType = X_DRI2GetBuffers;
+   req->dri2ReqType = dri2ReqType;
    req->drawable = drawable;
    req->count = count;
    p = (CARD32 *) & req[1];
-   for (i = 0; i < count; i++)
+   for (i = 0; i < nattachments; i++)
       p[i] = attachments[i];
 
    if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
@@ -400,21 +410,16 @@ DRI2GetBuffers(Display * dpy, XID drawable,
    *height = rep.height;
    *outCount = rep.count;
 
-   buffers = Xmalloc(rep.count * sizeof buffers[0]);
-   if (buffers == NULL) {
-      _XEatData(dpy, rep.count * sizeof repBuffer);
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
-
+   buffers = calloc(rep.count, sizeof buffers[0]);
    for (i = 0; i < rep.count; i++) {
       _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
-      buffers[i].attachment = repBuffer.attachment;
-      buffers[i].name = repBuffer.name;
-      buffers[i].pitch = repBuffer.pitch;
-      buffers[i].cpp = repBuffer.cpp;
-      buffers[i].flags = repBuffer.flags;
+      if (buffers) {
+         buffers[i].attachment = repBuffer.attachment;
+         buffers[i].names[0] = repBuffer.name;
+         buffers[i].pitch[0] = repBuffer.pitch;
+         buffers[i].cpp = repBuffer.cpp;
+         buffers[i].flags = repBuffer.flags;
+      }
    }
 
    UnlockDisplay(dpy);
@@ -423,65 +428,94 @@ DRI2GetBuffers(Display * dpy, XID drawable,
    return buffers;
 }
 
+DRI2Buffer *
+DRI2GetBuffers(Display * dpy, XID drawable,
+               int *width, int *height,
+               unsigned int *attachments, int count, int *outCount)
+{
+	return getbuffers(dpy, drawable, width, height, attachments,
+			count, outCount, X_DRI2GetBuffers);
+}
 
 DRI2Buffer *
 DRI2GetBuffersWithFormat(Display * dpy, XID drawable,
                          int *width, int *height,
                          unsigned int *attachments, int count, int *outCount)
 {
-   XExtDisplayInfo *info = DRI2FindDisplay(dpy);
-   xDRI2GetBuffersReply rep;
-   xDRI2GetBuffersReq *req;
-   DRI2Buffer *buffers;
-   xDRI2Buffer repBuffer;
-   CARD32 *p;
-   int i;
+	return getbuffers(dpy, drawable, width, height, attachments,
+			count, outCount, X_DRI2GetBuffersWithFormat);
+}
 
-   XextCheckExtension(dpy, info, dri2ExtensionName, False);
+#ifdef X_DRI2GetBuffersVid
+DRI2Buffer *
+DRI2GetBuffersVid(Display * dpy, XID drawable,
+               int width, int height,
+               unsigned int *attachments, int count, int *outCount)
+{
+	XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+	DRI2Display *dri2dpy = dpy2dri(dpy);
+	xDRI2GetBuffersReply rep;
+	xDRI2GetBuffersVidReq *req;
+	DRI2Buffer *buffers;
+	xDRI2Buffer repBuffer;
+	CARD32 *p;
+	int i, nattachments = 2 * count;
 
-   LockDisplay(dpy);
-   GetReqExtra(DRI2GetBuffers, count * (4 * 2), req);
-   req->reqType = info->codes->major_opcode;
-   req->dri2ReqType = X_DRI2GetBuffersWithFormat;
-   req->drawable = drawable;
-   req->count = count;
-   p = (CARD32 *) & req[1];
-   for (i = 0; i < (count * 2); i++)
-      p[i] = attachments[i];
+	XextCheckExtension(dpy, info, dri2ExtensionName, False);
 
-   if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
+    if (dri2dpy->minor < 4)
+	return False;
 
-   *width = rep.width;
-   *height = rep.height;
-   *outCount = rep.count;
+	LockDisplay(dpy);
+	GetReqExtra(DRI2GetBuffersVid, nattachments * 4, req);
+	req->reqType = info->codes->major_opcode;
+	req->dri2ReqType = X_DRI2GetBuffersVid;
+	req->drawable = drawable;
+	req->width = width;
+	req->height = height;
+	req->count = count;
+	p = (CARD32 *) & req[1];
+	for (i = 0; i < nattachments; i++)
+		p[i] = attachments[i];
+
+	if (!_XReply(dpy, (xReply *) & rep, 0, xFalse)) {
+		UnlockDisplay(dpy);
+		SyncHandle();
+		return NULL;
+	}
 
-   buffers = Xmalloc(rep.count * sizeof buffers[0]);
-   if (buffers == NULL) {
-      _XEatData(dpy, rep.count * sizeof repBuffer);
-      UnlockDisplay(dpy);
-      SyncHandle();
-      return NULL;
-   }
+	*outCount = rep.count;
+
+	buffers = calloc(rep.count, sizeof buffers[0]);
+	for (i = 0; i < rep.count; i++) {
+		CARD32 n, j;
+		_XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
+		if (buffers) {
+			buffers[i].attachment = repBuffer.attachment;
+			buffers[i].names[0] = repBuffer.name;
+			buffers[i].pitch[0] = repBuffer.pitch;
+			buffers[i].cpp = repBuffer.cpp;
+			buffers[i].flags = repBuffer.flags;
+		}
 
-   for (i = 0; i < rep.count; i++) {
-      _XReadPad(dpy, (char *) &repBuffer, sizeof repBuffer);
-      buffers[i].attachment = repBuffer.attachment;
-      buffers[i].name = repBuffer.name;
-      buffers[i].pitch = repBuffer.pitch;
-      buffers[i].cpp = repBuffer.cpp;
-      buffers[i].flags = repBuffer.flags;
-   }
+		_XReadPad(dpy, (char *) &n, sizeof n);
+		for (j = 0; j < n; j++) {
+			CARD32 name, pitch;
+			_XReadPad(dpy, (char *) &name, 4);
+			_XReadPad(dpy, (char *) &pitch, 4);
+			if (buffers) {
+				buffers[i].names[j+1] = name;
+				buffers[i].pitch[j+1] = pitch;
+			}
+		}
+	}
 
-   UnlockDisplay(dpy);
-   SyncHandle();
+	UnlockDisplay(dpy);
+	SyncHandle();
 
-   return buffers;
+	return buffers;
 }
-
+#endif
 
 void
 DRI2CopyRegion(Display * dpy, XID drawable, XserverRegion region,
@@ -552,6 +586,45 @@ void DRI2SwapBuffers(Display *dpy, XID drawable, CARD64 target_msc,
 }
 #endif
 
+#ifdef X_DRI2SwapBuffersVid
+void DRI2SwapBuffersVid(Display *dpy, XID drawable, CARD64 target_msc,
+		     CARD64 divisor, CARD64 remainder, CARD64 *count,
+		     unsigned int source, BoxPtr b)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    DRI2Display *dri2dpy = dpy2dri(dpy);
+    xDRI2SwapBuffersVidReq *req;
+    xDRI2SwapBuffersReply rep;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    if (dri2dpy->minor < 4)
+	return;
+
+    LockDisplay(dpy);
+    GetReq(DRI2SwapBuffersVid, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SwapBuffersVid;
+    req->drawable = drawable;
+
+    /* first part of message is same as original DRI2SwapBuffers.. */
+    load_swap_req((xDRI2SwapBuffersReq *)req, target_msc, divisor, remainder);
+
+    req->source = source;
+    req->x1 = b->x1;
+    req->y1 = b->y1;
+    req->x2 = b->x2;
+    req->y2 = b->y2;
+
+    _XReply(dpy, (xReply *)&rep, 0, xFalse);
+
+    *count = vals_to_card64(rep.swap_lo, rep.swap_hi);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
+
 #ifdef X_DRI2GetMSC
 Bool DRI2GetMSC(Display *dpy, XID drawable, CARD64 *ust, CARD64 *msc,
 		CARD64 *sbc)
@@ -690,3 +763,120 @@ void DRI2SwapInterval(Display *dpy, XID drawable, int interval)
     SyncHandle();
 }
 #endif
+
+#ifdef X_DRI2SetAttribute
+/* length in multiple of CARD32's */
+void
+DRI2SetAttribute(Display * dpy, XID drawable, Atom attribute,
+		int len, const CARD32 *val)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    DRI2Display *dri2dpy = dpy2dri(dpy);
+    xDRI2SetAttributeReq *req;
+
+    XextSimpleCheckExtension (dpy, info, dri2ExtensionName);
+
+    if (dri2dpy->minor < 4)
+	return;
+
+    LockDisplay(dpy);
+    GetReqExtra(DRI2SetAttribute, len * 4, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2SetAttribute;
+    req->drawable = drawable;
+    req->attribute = attribute;
+    memcpy(&req[1], val, len * 4);
+    UnlockDisplay(dpy);
+    SyncHandle();
+}
+#endif
+
+#ifdef X_DRI2GetAttribute
+/* returned attribute should be free'd by caller.. length in multiple of
+ * CARD32's
+ */
+Bool
+DRI2GetAttribute(Display * dpy, XID drawable, Atom attribute,
+		int *len, CARD32 **val)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    DRI2Display *dri2dpy = dpy2dri(dpy);
+    xDRI2GetAttributeReq *req;
+    xDRI2GetAttributeReply rep;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    if (dri2dpy->minor < 4)
+	return False;
+
+    LockDisplay(dpy);
+    GetReq(DRI2GetAttribute, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2GetAttribute;
+    req->drawable = drawable;
+    req->attribute = attribute;
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+	UnlockDisplay(dpy);
+	SyncHandle();
+	return False;
+    }
+
+    *len = rep.length;
+    *val = malloc(rep.length * 4);
+
+    _XReadPad(dpy, (char *) *val, rep.length * 4);
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    return True;
+}
+#endif
+
+#ifdef X_DRI2GetFormats
+/* returned formats should be freed by caller */
+Bool
+DRI2GetFormats(Display * dpy, XID drawable, unsigned int *pnformats,
+		unsigned int **pformats)
+{
+    XExtDisplayInfo *info = DRI2FindDisplay(dpy);
+    DRI2Display *dri2dpy = dpy2dri(dpy);
+    xDRI2GetFormatsReq *req;
+    xDRI2GetFormatsReply rep;
+    unsigned int nformats, *formats;
+    int i;
+
+    XextCheckExtension (dpy, info, dri2ExtensionName, False);
+
+    if (dri2dpy->minor < 4)
+	return False;
+
+    LockDisplay(dpy);
+    GetReq(DRI2GetFormats, req);
+    req->reqType = info->codes->major_opcode;
+    req->dri2ReqType = X_DRI2GetFormats;
+    req->drawable = drawable;
+
+    if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+	UnlockDisplay(dpy);
+	SyncHandle();
+	return False;
+    }
+
+    nformats = (rep.length / sizeof(*formats)) * 4;
+    formats = malloc(nformats * sizeof(*formats));
+
+    for (i = 0; i < nformats; i++) {
+	_XReadPad(dpy, (char *) &formats[i], sizeof(formats[i]));
+    }
+
+    UnlockDisplay(dpy);
+    SyncHandle();
+
+    *pnformats = nformats;
+    *pformats = formats;
+
+    return True;
+}
+#endif
diff --git a/test/Makefile.am b/test/Makefile.am
index 8515c6b..fa48499 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -1,4 +1,4 @@
-lib_LTLIBRARIES = libdri2test.la
+lib_LTLIBRARIES = libdri2test.la libdri2videotest.la
 
 COMMON_SOURCES = dri2util.c
 COMMON_LIBADD  = @DRI2_LIBS@ 
@@ -19,3 +19,7 @@ endif
 libdri2test_la_SOURCES = dri2test.c $(COMMON_SOURCES)
 libdri2test_la_LIBADD = $(COMMON_LIBADD)
 libdri2test_la_CFLAGS = $(COMMON_CFLAGS)
+
+libdri2videotest_la_SOURCES = dri2videotest.c $(COMMON_SOURCES)
+libdri2videotest_la_LIBADD = $(COMMON_LIBADD)
+libdri2videotest_la_CFLAGS = $(COMMON_CFLAGS)
diff --git a/test/dri2-nouveau.c b/test/dri2-nouveau.c
index f91cc48..52de35e 100644
--- a/test/dri2-nouveau.c
+++ b/test/dri2-nouveau.c
@@ -52,7 +52,7 @@ static void setup(int fd)
 static void * init(DRI2Buffer *dri2buf)
 {
 	struct nouveau_bo *bo = NULL;
-	int ret = nouveau_bo_handle_ref(dev, dri2buf->name, &bo);
+	int ret = nouveau_bo_handle_ref(dev, dri2buf->names[0], &bo);
 	if (ret) {
 		ERROR_MSG("nouveau_bo_handle_ref failed: %d", ret);
 		return NULL;
diff --git a/test/dri2-omap.c b/test/dri2-omap.c
index 181599d..2bcff28 100644
--- a/test/dri2-omap.c
+++ b/test/dri2-omap.c
@@ -48,7 +48,7 @@ static void setup(int fd)
 
 static void * init(DRI2Buffer *dri2buf)
 {
-	return omap_bo_from_name(dev, dri2buf->name);
+	return omap_bo_from_name(dev, dri2buf->names[0]);
 }
 
 static char * prep(void *hdl)
diff --git a/test/dri2test.c b/test/dri2test.c
index 1aa101d..ec74e81 100644
--- a/test/dri2test.c
+++ b/test/dri2test.c
@@ -48,7 +48,7 @@ static void fill(char *virtual, int n, int width, int height, int stride)
     for (j = 0; j < height; j++) {
             uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
             for (i = 0; i < width; i++) {
-                    div_t d = div(n+i, width);
+                    div_t d = div(n+i+j, width);
                     fb_ptr[i] =
                             0x00130502 * (d.quot >> 6) +
                             0x000a1120 * (d.rem >> 6);
@@ -109,7 +109,7 @@ int main(int argc, char **argv)
 		CARD64 count;
 
 		char *buf = backend->prep(bufs[i % nbufs].hdl);
-		fill(buf, i, w, h, bufs[i % nbufs].dri2buf->pitch);
+		fill(buf, i, w, h, bufs[i % nbufs].dri2buf->pitch[0]);
 		backend->fini(bufs[i % nbufs].hdl);
 		DRI2SwapBuffers(dpy, win, 0, 0, 0, &count);
 		MSG("DRI2SwapBuffers: count=%lu", count);
diff --git a/test/dri2videotest.c b/test/dri2videotest.c
new file mode 100644
index 0000000..c20141c
--- /dev/null
+++ b/test/dri2videotest.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright © 2011 Texas Instruments, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Rob Clark (rob at ti.com)
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include "config.h"
+#endif
+
+#include <ctype.h>
+
+#include "dri2util.h"
+
+#define NFRAMES 300
+#define WIN_WIDTH  500
+#define WIN_HEIGHT 500
+#define VID_WIDTH  1920
+#define VID_HEIGHT 1080
+
+#define FOURCC(a, b, c, d) ((uint32_t)(uint8_t)(a) | ((uint32_t)(uint8_t)(b) << 8) | ((uint32_t)(uint8_t)(c) << 16) | ((uint32_t)(uint8_t)(d) << 24 ))
+#define FOURCC_STR(str)    FOURCC(str[0], str[1], str[2], str[3])
+
+/* swap these for big endian.. */
+#define R 2
+#define G 1
+#define B 0
+
+static void fill420(unsigned char *y, unsigned char *u, unsigned char *v,
+		int cs /*chroma pixel stride */,
+		int n, int width, int height, int stride)
+{
+	int i, j;
+
+	/* paint the buffer with colored tiles, in blocks of 2x2 */
+	for (j = 0; j < height; j+=2) {
+		unsigned char *y1p = y + j * stride;
+		unsigned char *y2p = y1p + stride;
+		unsigned char *up = u + (j/2) * stride * cs / 2;
+		unsigned char *vp = v + (j/2) * stride * cs / 2;
+
+		for (i = 0; i < width; i+=2) {
+			div_t d = div(n+i+j, width);
+			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
+			unsigned char *rgbp = &rgb;
+			unsigned char y = (0.299 * rgbp[R]) + (0.587 * rgbp[G]) + (0.114 * rgbp[B]);
+
+			*(y2p++) = *(y1p++) = y;
+			*(y2p++) = *(y1p++) = y;
+
+			*up = (rgbp[B] - y) * 0.565 + 128;
+			*vp = (rgbp[R] - y) * 0.713 + 128;
+			up += cs;
+			vp += cs;
+		}
+	}
+}
+
+static void fill422(unsigned char *virtual, int n, int width, int height, int stride)
+{
+	int i, j;
+	/* paint the buffer with colored tiles */
+	for (j = 0; j < height; j++) {
+		uint8_t *ptr = (uint32_t*)((char*)virtual + j * stride);
+		for (i = 0; i < width; i++) {
+			div_t d = div(n+i+j, width);
+			uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
+			unsigned char *rgbp = &rgb;
+			unsigned char y = (0.299 * rgbp[R]) + (0.587 * rgbp[G]) + (0.114 * rgbp[B]);
+
+			*(ptr++) = y;
+			*(ptr++) = (rgbp[B] - y) * 0.565 + 128;
+			*(ptr++) = y;
+			*(ptr++) = (rgbp[R] - y) * 0.713 + 128;
+		}
+	}
+}
+
+/* stolen from modetest.c */
+static void fill(unsigned char *virtual, int n, int width, int height, int stride)
+{
+	int i, j;
+    /* paint the buffer with colored tiles */
+    for (j = 0; j < height; j++) {
+            uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
+            for (i = 0; i < width; i++) {
+                    div_t d = div(n+i+j, width);
+                    fb_ptr[i] =
+                            0x00130502 * (d.quot >> 6) +
+                            0x000a1120 * (d.rem >> 6);
+            }
+    }
+}
+
+
+/* move this somewhere common?  It does seem useful.. */
+static Bool is_fourcc(unsigned int val)
+{
+	char *str = (char *)&val;
+	return isalnum(str[0]) && isalnum(str[1]) && isalnum(str[2]) && isalnum(str[3]);
+}
+
+#define ATOM(name) XInternAtom(dpy, name, False)
+
+int main(int argc, char **argv)
+{
+	Display *dpy;
+	Window win;
+	Backend *backend = NULL;
+	DRI2Buffer *dri2bufs;
+	Buffer *bufs;
+	char *driver;
+	unsigned int nformats, *formats, format = 0;
+	int fd, nbufs, i;
+	CARD32 *pval;
+
+	dpy = XOpenDisplay(NULL);
+	win = XCreateSimpleWindow(dpy, RootWindow(dpy, 0), 1, 1,
+			WIN_WIDTH, WIN_HEIGHT, 0, BlackPixel (dpy, 0), BlackPixel(dpy, 0));
+	XMapWindow(dpy, win);
+	XFlush(dpy);
+
+	if ((fd = dri2_connect(dpy, DRI2DriverXV, &driver)) < 0) {
+		return -1;
+	}
+
+	if (!DRI2GetFormats(dpy, RootWindow(dpy, DefaultScreen(dpy)),
+			&nformats, &formats)) {
+		ERROR_MSG("DRI2GetFormats failed");
+		return -1;
+	}
+
+	if (nformats == 0) {
+		ERROR_MSG("no formats!");
+		return -1;
+	}
+
+	/* print out supported formats */
+	MSG("Found %d supported formats:", nformats);
+	for (i = 0; i < nformats; i++) {
+		if (is_fourcc(formats[i])) {
+			MSG("  %d: %08x (\"%.4s\")", i, formats[i], (char *)&formats[i]);
+		} else {
+			MSG("  %d: %08x (device dependent)", i, formats[i]);
+		}
+	}
+
+	// XXX pick something we understand!
+//	format = FOURCC_STR("I420");
+	format = FOURCC_STR("YUY2");
+//	format = FOURCC_STR("RGB4");
+
+	free(formats);
+
+	backend = get_backend(driver);
+	if (!backend) {
+		return -1;
+	}
+
+	backend->setup(fd);
+
+	DRI2CreateDrawable(dpy, win);
+
+	/* check some attribute.. just to exercise the code-path: */
+	if (!DRI2GetAttribute(dpy, win, ATOM("XV_CSC_MATRIX"), &i, &pval)) {
+		ERROR_MSG("DRI2GetAttribute failed");
+		return -1;
+	}
+
+	MSG("Got CSC matrix:");
+	print_hex(i*4, (const unsigned char *)pval);
+
+	free(pval);
+
+	unsigned attachments[] = {
+			DRI2BufferFrontLeft, 32, /* always requested, never returned */
+			1, format, 2, format, 3, format, 4, format,
+	};
+	dri2bufs = DRI2GetBuffersVid(dpy, win, VID_WIDTH, VID_HEIGHT, attachments, 4, &nbufs);
+	if (!dri2bufs) {
+		ERROR_MSG("DRI2GetBuffersVid failed");
+		return -1;
+	}
+
+	MSG("DRI2GetBuffers: nbufs=%d", nbufs);
+
+	bufs = calloc(nbufs, sizeof(Buffer));
+
+	for (i = 0; i < nbufs; i++) {
+		bufs[i].dri2buf = &dri2bufs[i];
+		bufs[i].hdl = backend->init(bufs[i].dri2buf);
+	}
+
+	for (i = 0; i < NFRAMES; i++) {
+		BoxRec b = {
+				// TODO change this dynamically..  fill appropriately so
+				// the cropped region has different color, or something,
+				// so we can see visually if cropping is incorrect..
+				.x1 = 0,
+				.y1 = 0,
+				.x2 = VID_WIDTH,
+				.y2 = VID_HEIGHT,
+		};
+		CARD64 count;
+
+		Buffer *buf = &bufs[i % nbufs];
+		int pitch = buf->dri2buf->pitch[0];
+		unsigned char *ptr = backend->prep(buf->hdl);
+		if (format == FOURCC_STR("I420")) {
+#if 0
+			unsigned char *y = ptr;
+			// XXX deal with multiple bo case
+			unsigned char *u = y + (VID_HEIGHT * pitch);
+			unsigned char *v = u + (VID_HEIGHT * pitch) / 4;
+			fill420(y, u, v, 1, i, VID_WIDTH, VID_HEIGHT, pitch);
+#else
+			/* I think the nouveau shader actually expects NV12... */
+			unsigned char *y = ptr;
+			// XXX deal with multiple bo case
+			unsigned char *u = y + (VID_HEIGHT * pitch);
+			unsigned char *v = u + 1;
+			fill420(y, u, v, 2, i, VID_WIDTH, VID_HEIGHT, pitch);
+#endif
+		} else if (format == FOURCC_STR("YUY2")) {
+			fill422(ptr, i, VID_WIDTH, VID_HEIGHT, pitch);
+		} else if (format == FOURCC_STR("RGB4")) {
+			fill(ptr, i, VID_WIDTH, VID_HEIGHT, pitch);
+		}
+		backend->fini(buf->hdl);
+		DRI2SwapBuffersVid(dpy, win, 0, 0, 0, &count, (i % nbufs) + 1, &b);
+		MSG("DRI2SwapBuffersVid: count=%lu", count);
+		if (i > 0) {
+			/* XXX wait.. */
+		}
+	}
+
+	return 0;
+}
-- 
1.7.5.4



More information about the xorg-devel mailing list