6e1bcfb3c6
tested by krw@ and dcoppa@ ok dcoppa@
413 lines
12 KiB
C
413 lines
12 KiB
C
/*
|
|
* 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);
|
|
}
|