[PATCH xserver v4] xwayland: add glamor Xv adaptor

Olivier Fourdan ofourdan at redhat.com
Wed Mar 9 15:21:18 UTC 2016


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
 v4: Fix double comma and unsigned int warning, fix build with --disable-xv

 hw/xwayland/Makefile.am          |   7 +-
 hw/xwayland/xwayland-glamor-xv.c | 413 +++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland-glamor.c    |   5 +
 hw/xwayland/xwayland.h           |   5 +
 4 files changed, 429 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..0e6a1ea 100644
--- a/hw/xwayland/Makefile.am
+++ b/hw/xwayland/Makefile.am
@@ -32,7 +32,12 @@ Xwayland_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
 
 if GLAMOR_EGL
-Xwayland_SOURCES += xwayland-glamor.c
+Xwayland_SOURCES += 				\
+	xwayland-glamor.c
+if XV
+Xwayland_SOURCES += 				\
+	xwayland-glamor-xv.c
+endif
 
 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..22c81a0
--- /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 = (unsigned int) (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..ad66cf6 100644
--- a/hw/xwayland/xwayland-glamor.c
+++ b/hw/xwayland/xwayland-glamor.c
@@ -569,5 +569,10 @@ xwl_glamor_init(struct xwl_screen *xwl_screen)
     screen->CreatePixmap = xwl_glamor_create_pixmap;
     screen->DestroyPixmap = xwl_glamor_destroy_pixmap;
 
+#ifdef XV
+    if (!xwl_glamor_xv_init(screen))
+        ErrorF("Failed to initialize glamor Xv extension\n");
+#endif
+
     return TRUE;
 }
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 4b150ed..67b30cb 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -190,6 +190,11 @@ 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);
 
+#ifdef XV
+/* glamor Xv Adaptor */
+Bool xwl_glamor_xv_init(ScreenPtr pScreen);
+#endif
+
 #ifdef XF86VIDMODE
 void xwlVidModeExtensionInit(void);
 #endif
-- 
2.5.0



More information about the xorg-devel mailing list