[PATCH xserver v3] xwayland: add glamor Xv adaptor

Olivier Fourdan ofourdan at redhat.com
Tue Mar 8 15:15:56 UTC 2016


Hi Adam,

I had posted a revisited version using GL_MAX_TEXTURE_SIZE to determine the encoder size as per your review last week, is there anything else that needs rework?

Cheers,
Olivier

----- Original Message -----
> This adds an Xv adaptor using glamor.
> 
> Signed-off-by: Olivier Fourdan <ofourdan at redhat.com>
> ---
>  v2: Plug leak of Xv adaptor and glamor private ports array on closure
>  v3: Get the adaptor size from the GL_MAX_TEXTURE_SIZE
> 
>  hw/xwayland/Makefile.am          |   4 +-
>  hw/xwayland/xwayland-glamor-xv.c | 413
>  +++++++++++++++++++++++++++++++++++++++
>  hw/xwayland/xwayland-glamor.c    |   3 +
>  hw/xwayland/xwayland.h           |   2 +
>  4 files changed, 421 insertions(+), 1 deletion(-)
>  create mode 100644 hw/xwayland/xwayland-glamor-xv.c
> 
> diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am
> index 0905082..26fdba7 100644
> --- a/hw/xwayland/Makefile.am
> +++ b/hw/xwayland/Makefile.am
> @@ -32,7 +32,9 @@ Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
>  
>  
>  if GLAMOR_EGL
> -Xwayland_SOURCES += xwayland-glamor.c
> +Xwayland_SOURCES += 				\
> +	xwayland-glamor.c			\
> +	xwayland-glamor-xv.c
>  
>  nodist_Xwayland_SOURCES =			\
>  	drm-client-protocol.h			\
> diff --git a/hw/xwayland/xwayland-glamor-xv.c
> b/hw/xwayland/xwayland-glamor-xv.c
> new file mode 100644
> index 0000000..5fa1c69
> --- /dev/null
> +++ b/hw/xwayland/xwayland-glamor-xv.c
> @@ -0,0 +1,413 @@
> +/*
> + * Copyright (c) 1998-2003 by The XFree86 Project, Inc.
> + * Copyright © 2013 Red Hat
> + * Copyright © 2014 Intel Corporation
> + * Copyright © 2016 Red Hat
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + *
> + * Authors:
> + *      Olivier Fourdan <ofourdan at redhat.com>
> + *
> + * Derived from the glamor_xf86_xv, ephyr_glamor_xv and xf86xv
> + * implementations
> + */
> +
> +#include "xwayland.h"
> +#include "glamor_priv.h"
> +
> +#include <X11/extensions/Xv.h>
> +
> +#define NUM_FORMATS    3
> +#define NUM_PORTS      16
> +#define ADAPTOR_NAME   "glamor textured video"
> +#define ENCODER_NAME   "XV_IMAGE"
> +
> +static DevPrivateKeyRec xwlXvScreenPrivateKeyRec;
> +#define xwlXvScreenPrivateKey (&xwlXvScreenPrivateKeyRec)
> +
> +typedef struct {
> +    XvAdaptorPtr glxv_adaptor; /* We have only one adaptor, glamor Xv */
> +    glamor_port_private *port_privates;
> +
> +    CloseScreenProcPtr CloseScreen;
> +} xwlXvScreenRec, *xwlXvScreenPtr;
> +
> +typedef struct {
> +    char depth;
> +    short class;
> +} xwlVideoFormatRec, *xwlVideoFormatPtr;
> +
> +static xwlVideoFormatRec Formats[NUM_FORMATS] = {
> +    {15, TrueColor},
> +    {16, TrueColor},
> +    {24, TrueColor}
> +};
> +
> +static int
> +xwl_glamor_xv_stop_video(XvPortPtr   pPort,
> +                         DrawablePtr pDraw)
> +{
> +    glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
> +
> +    if (pDraw->type != DRAWABLE_WINDOW)
> +        return BadAlloc;
> +
> +    glamor_xv_stop_video(gpp);
> +
> +    return Success;
> +}
> +
> +static int
> +xwl_glamor_xv_set_port_attribute(XvPortPtr pPort,
> +                                 Atom      attribute,
> +                                 INT32     value)
> +{
> +    glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
> +
> +    return glamor_xv_set_port_attribute(gpp, attribute, value);
> +}
> +
> +static int
> +xwl_glamor_xv_get_port_attribute(XvPortPtr pPort,
> +                                 Atom      attribute,
> +                                 INT32    *pValue)
> +{
> +    glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
> +
> +    return glamor_xv_get_port_attribute(gpp, attribute, pValue);
> +}
> +
> +static int
> +xwl_glamor_xv_query_best_size(XvPortPtr     pPort,
> +                              CARD8         motion,
> +                              CARD16        vid_w,
> +                              CARD16        vid_h,
> +                              CARD16        drw_w,
> +                              CARD16        drw_h,
> +                              unsigned int *p_w,
> +                              unsigned int *p_h)
> +{
> +    *p_w = drw_w;
> +    *p_h = drw_h;
> +
> +    return Success;
> +}
> +
> +static int
> +xwl_glamor_xv_query_image_attributes(XvPortPtr  pPort,
> +                                     XvImagePtr format,
> +                                     CARD16    *width,
> +                                     CARD16    *height,
> +                                     int       *pitches,
> +                                     int       *offsets)
> +{
> +    return glamor_xv_query_image_attributes(format->id,
> +                                            width,
> +                                            height,
> +                                            pitches,
> +                                            offsets);
> +}
> +
> +static int
> +xwl_glamor_xv_put_image(DrawablePtr    pDrawable,
> +                        XvPortPtr      pPort,
> +                        GCPtr          pGC,
> +                        INT16          src_x,
> +                        INT16          src_y,
> +                        CARD16         src_w,
> +                        CARD16         src_h,
> +                        INT16          drw_x,
> +                        INT16          drw_y,
> +                        CARD16         drw_w,
> +                        CARD16         drw_h,
> +                        XvImagePtr     format,
> +                        unsigned char *data,
> +                        Bool           sync,
> +                        CARD16         width,
> +                        CARD16         height)
> +{
> +    glamor_port_private *gpp = (glamor_port_private *) (pPort->devPriv.ptr);
> +
> +    RegionRec WinRegion;
> +    RegionRec ClipRegion;
> +    BoxRec WinBox;
> +    int ret = Success;
> +
> +    if (pDrawable->type != DRAWABLE_WINDOW)
> +        return BadWindow;
> +
> +    WinBox.x1 = pDrawable->x + drw_x;
> +    WinBox.y1 = pDrawable->y + drw_y;
> +    WinBox.x2 = WinBox.x1 + drw_w;
> +    WinBox.y2 = WinBox.y1 + drw_h;
> +
> +    RegionInit(&WinRegion, &WinBox, 1);
> +    RegionInit(&ClipRegion, NullBox, 1);
> +    RegionIntersect(&ClipRegion, &WinRegion, pGC->pCompositeClip);
> +
> +    if (RegionNotEmpty(&ClipRegion))
> +        ret = glamor_xv_put_image(gpp,
> +                                  pDrawable,
> +                                  src_x,
> +                                  src_y,
> +                                  pDrawable->x + drw_x,
> +                                  pDrawable->y + drw_y,
> +                                  src_w,
> +                                  src_h,
> +                                  drw_w,
> +                                  drw_h,
> +                                  format->id,
> +                                  data,
> +                                  width,
> +                                  height,
> +                                  sync,
> +                                  &ClipRegion);
> +
> +     RegionUninit(&WinRegion);
> +     RegionUninit(&ClipRegion);
> +
> +     return ret;
> +
> +}
> +
> +static Bool
> +xwl_glamor_xv_add_formats(XvAdaptorPtr pa)
> +{
> +    ScreenPtr pScreen;
> +    XvFormatPtr pFormat, pf;
> +    VisualPtr pVisual;
> +    int numFormat;
> +    int totFormat;
> +    int numVisuals;
> +    int i;
> +
> +    totFormat = NUM_FORMATS;
> +    pFormat = xnfcalloc(totFormat, sizeof(XvFormatRec));
> +    pScreen = pa->pScreen;
> +    for (pf = pFormat, i = 0, numFormat = 0; i < NUM_FORMATS; i++) {
> +        numVisuals = pScreen->numVisuals;
> +        pVisual = pScreen->visuals;
> +
> +        while (numVisuals--) {
> +           if ((pVisual->class == Formats[i].class) &&
> +               (pVisual->nplanes == Formats[i].depth)) {
> +                    if (numFormat >= totFormat) {
> +                        void *moreSpace;
> +
> +                        totFormat *= 2;
> +                        moreSpace = XNFreallocarray(pFormat, totFormat,
> +                                                    sizeof(XvFormatRec));
> +                        pFormat = moreSpace;
> +                        pf = pFormat + numFormat;
> +                    }
> +
> +                    pf->visual = pVisual->vid;
> +                    pf->depth = Formats[i].depth;
> +
> +                    pf++;
> +                    numFormat++;
> +                }
> +            pVisual++;
> +        }
> +    }
> +    pa->nFormats = numFormat;
> +    pa->pFormats = pFormat;
> +
> +    return numFormat != 0;
> +}
> +
> +static Bool
> +xwl_glamor_xv_add_ports(XvAdaptorPtr pa)
> +{
> +    XvPortPtr pPorts, pp;
> +    xwlXvScreenPtr xwlXvScreen;
> +    unsigned long PortResource = 0;
> +    int nPorts;
> +    int i;
> +
> +    pPorts = xnfcalloc(NUM_PORTS, sizeof(XvPortRec));
> +    xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates,
> +                                   xwlXvScreenPrivateKey);
> +    xwlXvScreen->port_privates = xnfcalloc(NUM_PORTS,
> +                                           sizeof(glamor_port_private));
> +
> +    PortResource = XvGetRTPort();
> +    for (pp = pPorts, i = 0, nPorts = 0; i < NUM_PORTS; i++) {
> +        if (!(pp->id = FakeClientID(0)))
> +            continue;
> +
> +        pp->pAdaptor = pa;
> +
> +        glamor_xv_init_port(&xwlXvScreen->port_privates[i]);
> +        pp->devPriv.ptr = &xwlXvScreen->port_privates[i];
> +
> +        if (AddResource(pp->id, PortResource, pp)) {
> +            pp++;
> +            nPorts++;
> +        }
> +    }
> +
> +    pa->base_id = pPorts->id;
> +    pa->nPorts = nPorts;
> +    pa->pPorts = pPorts;
> +
> +    return nPorts != 0;
> +}
> +
> +static void
> +xwl_glamor_xv_add_attributes(XvAdaptorPtr pa)
> +{
> +    int i;
> +
> +    pa->pAttributes = xnfcalloc(glamor_xv_num_attributes,
> sizeof(XvAttributeRec));
> +    memcpy(pa->pAttributes, glamor_xv_attributes,
> +           glamor_xv_num_attributes * sizeof(XvAttributeRec));
> +
> +    for (i = 0; i < glamor_xv_num_attributes; i++)
> +        pa->pAttributes[i].name = strdup(glamor_xv_attributes[i].name);
> +
> +    pa->nAttributes = glamor_xv_num_attributes;
> +}
> +
> +static void
> +xwl_glamor_xv_add_images(XvAdaptorPtr pa)
> +{
> +    pa->pImages = xnfcalloc(glamor_xv_num_images, sizeof(XvImageRec));
> +    memcpy(pa->pImages, glamor_xv_images, glamor_xv_num_images *
> sizeof(XvImageRec));
> +
> +    pa->nImages = glamor_xv_num_images;
> +}
> +
> +static void
> +xwl_glamor_xv_add_encodings(XvAdaptorPtr pa)
> +{
> +    XvEncodingPtr pe;
> +    GLint texsize;
> +
> +    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texsize);
> +
> +    pe = xnfcalloc(1, sizeof(XvEncodingRec));
> +    pe->id = 0;
> +    pe->pScreen = pa->pScreen;
> +    pe->name = strdup(ENCODER_NAME);
> +    pe->width = texsize;
> +    pe->height = texsize;
> +    pe->rate.numerator = 1;
> +    pe->rate.denominator = 1;
> +
> +    pa->pEncodings = pe;
> +    pa->nEncodings = 1;
> +}
> +
> +static Bool
> +xwl_glamor_xv_add_adaptors(ScreenPtr pScreen)
> +{
> +    DevPrivateKey XvScreenKey;
> +    XvScreenPtr XvScreen;
> +    xwlXvScreenPtr xwlXvScreen;
> +    XvAdaptorPtr pa;
> +
> +    if (XvScreenInit(pScreen) != Success)
> +        return FALSE;
> +
> +    XvScreenKey = XvGetScreenKey();
> +    XvScreen = dixLookupPrivate(&(pScreen)->devPrivates, XvScreenKey);
> +
> +    XvScreen->nAdaptors = 0;
> +    XvScreen->pAdaptors = NULL;
> +
> +    pa = xnfcalloc(1, sizeof(XvAdaptorRec));
> +    pa->pScreen = pScreen;
> +    pa->type = XvWindowMask | XvInputMask | XvImageMask;;
> +    pa->ddStopVideo = xwl_glamor_xv_stop_video;
> +    pa->ddPutImage = xwl_glamor_xv_put_image;
> +    pa->ddSetPortAttribute = xwl_glamor_xv_set_port_attribute;
> +    pa->ddGetPortAttribute = xwl_glamor_xv_get_port_attribute;
> +    pa->ddQueryBestSize = xwl_glamor_xv_query_best_size;
> +    pa->ddQueryImageAttributes = xwl_glamor_xv_query_image_attributes;
> +    pa->name = strdup(ADAPTOR_NAME);
> +
> +    xwl_glamor_xv_add_encodings(pa);
> +    xwl_glamor_xv_add_images(pa);
> +    xwl_glamor_xv_add_attributes(pa);
> +    if (!xwl_glamor_xv_add_formats(pa))
> +        goto failed;
> +    if (!xwl_glamor_xv_add_ports(pa))
> +        goto failed;
> +
> +    /* We're good now with out Xv adaptor */
> +    XvScreen->nAdaptors = 1;
> +    XvScreen->pAdaptors = pa;
> +
> +    xwlXvScreen = dixLookupPrivate(&(pa->pScreen)->devPrivates,
> +                                   xwlXvScreenPrivateKey);
> +    xwlXvScreen->glxv_adaptor = pa;
> +
> +    return TRUE;
> +
> +failed:
> +    XvFreeAdaptor(pa);
> +    free(pa);
> +
> +    return FALSE;
> +}
> +
> +static Bool
> +xwl_glamor_xv_close_screen(ScreenPtr pScreen)
> +{
> +    xwlXvScreenPtr xwlXvScreen;
> +
> +    xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates,
> +                                   xwlXvScreenPrivateKey);
> +
> +    if (xwlXvScreen->glxv_adaptor) {
> +        XvFreeAdaptor(xwlXvScreen->glxv_adaptor);
> +        free(xwlXvScreen->glxv_adaptor);
> +    }
> +    free(xwlXvScreen->port_privates);
> +
> +    pScreen->CloseScreen = xwlXvScreen->CloseScreen;
> +
> +    return pScreen->CloseScreen(pScreen);
> +}
> +
> +Bool
> +xwl_glamor_xv_init(ScreenPtr pScreen)
> +{
> +    xwlXvScreenPtr xwlXvScreen;
> +
> +    if (!dixRegisterPrivateKey(xwlXvScreenPrivateKey, PRIVATE_SCREEN,
> +                               sizeof(xwlXvScreenRec)))
> +        return FALSE;
> +
> +    xwlXvScreen = dixLookupPrivate(&(pScreen)->devPrivates,
> +                                    xwlXvScreenPrivateKey);
> +
> +    xwlXvScreen->port_privates = NULL;
> +    xwlXvScreen->glxv_adaptor = NULL;
> +    xwlXvScreen->CloseScreen = pScreen->CloseScreen;
> +    pScreen->CloseScreen = xwl_glamor_xv_close_screen;
> +
> +    glamor_xv_core_init(pScreen);
> +
> +    return xwl_glamor_xv_add_adaptors(pScreen);
> +}
> +
> diff --git a/hw/xwayland/xwayland-glamor.c b/hw/xwayland/xwayland-glamor.c
> index 8e77a84..9acbf3a 100644
> --- a/hw/xwayland/xwayland-glamor.c
> +++ b/hw/xwayland/xwayland-glamor.c
> @@ -569,5 +569,8 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
>      screen->CreatePixmap = xwl_glamor_create_pixmap;
>      screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
>  
> +    if (!xwl_glamor_xv_init(screen))
> +        ErrorF("Failed to initialize glamor Xv extension\n");
> +
>      return TRUE;
>  }
> diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
> index 4b150ed..2a54183 100644
> --- a/hw/xwayland/xwayland.h
> +++ b/hw/xwayland/xwayland.h
> @@ -189,6 +189,8 @@ Bool xwl_glamor_init(struct xwl_screen *xwl_screen);
>  Bool xwl_screen_init_glamor(struct xwl_screen *xwl_screen,
>                           uint32_t id, uint32_t version);
>  struct wl_buffer *xwl_glamor_pixmap_get_wl_buffer(PixmapPtr pixmap);
> +/* glamor Xv Adaptor */
> +Bool xwl_glamor_xv_init(ScreenPtr pScreen);
>  
>  #ifdef XF86VIDMODE
>  void xwlVidModeExtensionInit(void);
> --
> 2.5.0
> 
> _______________________________________________
> xorg-devel at lists.x.org: X.Org development
> Archives: http://lists.x.org/archives/xorg-devel
> Info: https://lists.x.org/mailman/listinfo/xorg-devel


More information about the xorg-devel mailing list