[PATCH libdri2] dri2video support

Rob Clark robdclark at gmail.com
Wed Nov 16 12:29:11 PST 2011


On Wed, Nov 16, 2011 at 7:36 AM, walter harms <wharms at bfs.de> wrote:
>
>
> Am 15.11.2011 23:49, schrieb Rob Clark:
>> ---
>>  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;
>> +      }
>>     }
>
>
>
> you check for OOM here what is good but i do  not see any action that is
> done when OOM occurs. Atleast you should send an errormsg.
> And the check is inside the loop ?

The reason for this is that we need to consume the data all the same,
or client and server will be out of sync.  I guess I could change this
back to the way it was before (handling buffers==NULL case outside of
the loop).  At one point I was trying to use the same common function
for DRI2GetBuffersVid, in which case you really need to handle the
!buffers case like this, because there is some extra data following
repBuffer.


>
>>     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;
>> +             }
>>
>
>
> are you sure you want to check buffers inside the loop ?
> It seems more logical to do this immediately after calloc()
> or to ignore the check .
>

yeah.. it is done this way because of the part following... the ' for
(j = 0; j < n; j++)' loop that follows.  This way we ensure we consume
the correct amount of data even if client is OOM..

>
>> -   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;
>
> i do not understand the 4 here. do you mean:
>  (rep.length / sizeof(*formats))*sizeof(*formats)


the rep.length is in units of 4-byte words..  although as pointed out
the multiply by four should be before the divide..


>> +    formats = malloc(nformats * sizeof(*formats));
>
>  calloc() ?
>

could be... seemed unnecessary since the _XReadPad() overwrites the
entire allocated area.  I could go either way on this, and usually
tend to use calloc() in cases where struct might not be fully
initialized/overwritten.


>> +    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
>
> i know it is a test ... but could you replace that with RED,GREEN,BLUE, (or what ever ...)
> single char defines tend to have unwanted consequences ....

will be fixed in next version

>
>> +
>> +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;
>> +     }
>> +
>
> This seems the only the only place where ATOM() is used.
> Perhaps you can drop that define ?

probably I should test a few more Get/SetAttribute's..  I guess I
should put that in the TODO

Thanks

BR,
-R

> re,
>  wh
>
>
>> +     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;
>> +}
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: http://lists.x.org/mailman/listinfo/xorg-devel


More information about the xorg-devel mailing list