diff options
author | Olivier Fourdan <ofourdan@redhat.com> | 2016-03-09 16:21:18 +0100 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2016-03-09 14:03:03 -0500 |
commit | da7724d3d277c6c8a814881785b716896802629a (patch) | |
tree | 9df884ccb41763d8d8b3ed7ffa447b5dbb24586a | |
parent | d11fdff50c91575e977a63617806a61bca98cd35 (diff) |
xwayland: add glamor Xv adaptor
This adds an Xv adaptor using glamor.
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
-rw-r--r-- | hw/xwayland/Makefile.am | 7 | ||||
-rw-r--r-- | hw/xwayland/xwayland-glamor-xv.c | 412 | ||||
-rw-r--r-- | hw/xwayland/xwayland-glamor.c | 5 | ||||
-rw-r--r-- | hw/xwayland/xwayland.h | 5 |
4 files changed, 428 insertions, 1 deletions
diff --git a/hw/xwayland/Makefile.am b/hw/xwayland/Makefile.am index 090508204..0e6a1eaa2 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 000000000..c99418d43 --- /dev/null +++ b/hw/xwayland/xwayland-glamor-xv.c @@ -0,0 +1,412 @@ +/* + * 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@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 8e77a84e2..ad66cf643 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 4b150edbf..67b30cb94 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 |