/* * 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 * * Derived from the glamor_xf86_xv, ephyr_glamor_xv and xf86xv * implementations */ #include #include "glamor_priv.h" #include #include "xwayland-glamor.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 char) (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); }