--- 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 (r...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel