xenocara/xserver/hw/xwayland/xwayland-glamor-xv.c

413 lines
12 KiB
C
Raw Normal View History

/*
* 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 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);
}