[PATCH xserver v3] xwayland: add glamor Xv adaptor
Olivier Fourdan
ofourdan at redhat.com
Tue Mar 1 08:14:08 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
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
More information about the xorg-devel
mailing list