xserver-multidpi/hw/kdrive/ephyr/ephyrvideo.c
Keith Packard 9838b7032e Introduce a consistent coding style
This is strictly the application of the script 'x-indent-all.sh'
from util/modular. Compared to the patch that Daniel posted in
January, I've added a few indent flags:

	-bap
	-psl
	-T PrivatePtr
	-T pmWait
	-T _XFUNCPROTOBEGIN
	-T _XFUNCPROTOEND
	-T _X_EXPORT

The typedefs were needed to make the output of sdksyms.sh match the
previous output, otherwise, the code is formatted badly enough that
sdksyms.sh generates incorrect output.

The generated code was compared with the previous version and found to
be essentially identical -- "assert" line numbers and BUILD_TIME were
the only differences found.

The comparison was done with this script:

dir1=$1
dir2=$2

for dir in $dir1 $dir2; do
	(cd $dir && find . -name '*.o' | while read file; do
		dir=`dirname $file`
		base=`basename $file .o`
		dump=$dir/$base.dump
		objdump -d $file > $dump
	done)
done

find $dir1 -name '*.dump' | while read dump; do
	otherdump=`echo $dump | sed "s;$dir1;$dir2;"`
	diff -u $dump $otherdump
done

Signed-off-by: Keith Packard <keithp@keithp.com>
Acked-by: Daniel Stone <daniel@fooishbar.org>
Acked-by: Alan Coopersmith <alan.coopersmith@oracle.com>
2012-03-21 13:54:42 -07:00

1219 lines
38 KiB
C

/*
* Xephyr - A kdrive X server thats runs in a host X window.
* Authored by Matthew Allum <mallum@openedhand.com>
*
* Copyright © 2007 OpenedHand Ltd
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of OpenedHand Ltd not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. OpenedHand Ltd makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*
* Authors:
* Dodji Seketeli <dodji@openedhand.com>
*/
#ifdef HAVE_CONFIG_H
#include <kdrive-config.h>
#endif
#include <string.h>
#include <X11/extensions/Xv.h>
#include "ephyrlog.h"
#include "kdrive.h"
#include "kxv.h"
#include "ephyr.h"
#include "hostx.h"
#include "ephyrhostvideo.h"
struct _EphyrXVPriv {
EphyrHostXVAdaptorArray *host_adaptors;
KdVideoAdaptorPtr adaptors;
int num_adaptors;
};
typedef struct _EphyrXVPriv EphyrXVPriv;
struct _EphyrPortPriv {
int port_number;
KdVideoAdaptorPtr current_adaptor;
EphyrXVPriv *xv_priv;
unsigned char *image_buf;
int image_buf_size;
int image_id;
int drw_x, drw_y, drw_w, drw_h;
int src_x, src_y, src_w, src_h;
int image_width, image_height;
};
typedef struct _EphyrPortPriv EphyrPortPriv;
static Bool DoSimpleClip(BoxPtr a_dst_drw, BoxPtr a_clipper, BoxPtr a_result);
static Bool ephyrLocalAtomToHost(int a_local_atom, int *a_host_atom);
/*
static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ;
*/
static EphyrXVPriv *ephyrXVPrivNew(void);
static void ephyrXVPrivDelete(EphyrXVPriv * a_this);
static Bool ephyrXVPrivQueryHostAdaptors(EphyrXVPriv * a_this);
static Bool ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this);
static Bool ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this,
ScreenPtr a_screen);
static Bool ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
int a_attrs_len,
const char *a_attr_name,
int a_attr_value, Bool *a_is_valid);
static Bool ephyrXVPrivGetImageBufSize(int a_port_id,
int a_image_id,
unsigned short a_width,
unsigned short a_height, int *a_size);
static Bool ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv * a_port_priv,
const unsigned char *a_image,
int a_image_len);
static void ephyrStopVideo(KdScreenInfo * a_info,
pointer a_xv_priv, Bool a_exit);
static int ephyrSetPortAttribute(KdScreenInfo * a_info,
Atom a_attr_name,
int a_attr_value, pointer a_port_priv);
static int ephyrGetPortAttribute(KdScreenInfo * a_screen_info,
Atom a_attr_name,
int *a_attr_value, pointer a_port_priv);
static void ephyrQueryBestSize(KdScreenInfo * a_info,
Bool a_motion,
short a_src_w,
short a_src_h,
short a_drw_w,
short a_drw_h,
unsigned int *a_prefered_w,
unsigned int *a_prefered_h, pointer a_port_priv);
static int ephyrPutImage(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_src_x,
short a_src_y,
short a_drw_x,
short a_drw_y,
short a_src_w,
short a_src_h,
short a_drw_w,
short a_drw_h,
int a_id,
unsigned char *a_buf,
short a_width,
short a_height,
Bool a_sync,
RegionPtr a_clipping_region, pointer a_port_priv);
static int ephyrReputImage(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_drw_x,
short a_drw_y,
RegionPtr a_clipping_region, pointer a_port_priv);
static int ephyrPutVideo(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clip_region, pointer a_port_priv);
static int ephyrGetVideo(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clip_region, pointer a_port_priv);
static int ephyrPutStill(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clip_region, pointer a_port_priv);
static int ephyrGetStill(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clip_region, pointer a_port_priv);
static int ephyrQueryImageAttributes(KdScreenInfo * a_info,
int a_id,
unsigned short *a_w,
unsigned short *a_h,
int *a_pitches, int *a_offsets);
static int s_base_port_id;
/**************
* <helpers>
* ************/
static Bool
DoSimpleClip(BoxPtr a_dst_box, BoxPtr a_clipper, BoxPtr a_result)
{
BoxRec dstClippedBox;
EPHYR_RETURN_VAL_IF_FAIL(a_dst_box && a_clipper && a_result, FALSE);
/*
* setup the clipbox inside the destination.
*/
dstClippedBox.x1 = a_dst_box->x1;
dstClippedBox.x2 = a_dst_box->x2;
dstClippedBox.y1 = a_dst_box->y1;
dstClippedBox.y2 = a_dst_box->y2;
/*
* if the cliper leftmost edge is inside
* the destination area then the leftmost edge of the resulting
* clipped box is the leftmost edge of the cliper.
*/
if (a_clipper->x1 > dstClippedBox.x1)
dstClippedBox.x1 = a_clipper->x1;
/*
* if the cliper top edge is inside the destination area
* then the bottom horizontal edge of the resulting clipped box
* is the bottom edge of the cliper
*/
if (a_clipper->y1 > dstClippedBox.y1)
dstClippedBox.y1 = a_clipper->y1;
/*ditto for right edge */
if (a_clipper->x2 < dstClippedBox.x2)
dstClippedBox.x2 = a_clipper->x2;
/*ditto for bottom edge */
if (a_clipper->y2 < dstClippedBox.y2)
dstClippedBox.y2 = a_clipper->y2;
memcpy(a_result, &dstClippedBox, sizeof(dstClippedBox));
return TRUE;
}
static Bool
ephyrLocalAtomToHost(int a_local_atom, int *a_host_atom)
{
const char *atom_name = NULL;
int host_atom = None;
EPHYR_RETURN_VAL_IF_FAIL(a_host_atom, FALSE);
if (!ValidAtom(a_local_atom))
return FALSE;
atom_name = NameForAtom(a_local_atom);
if (!atom_name)
return FALSE;
if (!ephyrHostGetAtom(atom_name, FALSE, &host_atom) || host_atom == None) {
EPHYR_LOG_ERROR("no atom for string %s defined in host X\n", atom_name);
return FALSE;
}
*a_host_atom = host_atom;
return TRUE;
}
/*
Not used yed.
static Bool
ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom)
{
Bool is_ok=FALSE ;
char *atom_name=NULL ;
int atom=None ;
EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ;
atom_name = ephyrHostGetAtomName (a_host_atom) ;
if (!atom_name)
goto out ;
atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ;
if (atom == None)
goto out ;
*a_local_atom = atom ;
is_ok = TRUE ;
out:
if (atom_name) {
ephyrHostFree (atom_name) ;
}
return is_ok ;
}
*/
/**************
*</helpers>
* ************/
Bool
ephyrInitVideo(ScreenPtr pScreen)
{
Bool is_ok = FALSE;
KdScreenPriv(pScreen);
KdScreenInfo *screen = pScreenPriv->screen;
static EphyrXVPriv *xv_priv;
EPHYR_LOG("enter\n");
if (screen->fb.bitsPerPixel == 8) {
EPHYR_LOG_ERROR("8 bits depth not supported\n");
return FALSE;
}
if (!xv_priv) {
xv_priv = ephyrXVPrivNew();
}
if (!xv_priv) {
EPHYR_LOG_ERROR("failed to create xv_priv\n");
goto out;
}
if (!ephyrXVPrivRegisterAdaptors(xv_priv, pScreen)) {
EPHYR_LOG_ERROR("failed to register adaptors\n");
goto out;
}
is_ok = TRUE;
out:
return is_ok;
}
static EphyrXVPriv *
ephyrXVPrivNew(void)
{
EphyrXVPriv *xv_priv = NULL;
EPHYR_LOG("enter\n");
xv_priv = calloc(1, sizeof(EphyrXVPriv));
if (!xv_priv) {
EPHYR_LOG_ERROR("failed to create EphyrXVPriv\n");
goto error;
}
ephyrHostXVInit();
if (!ephyrXVPrivQueryHostAdaptors(xv_priv)) {
EPHYR_LOG_ERROR("failed to query the host x for xv properties\n");
goto error;
}
if (!ephyrXVPrivSetAdaptorsHooks(xv_priv)) {
EPHYR_LOG_ERROR("failed to set xv_priv hooks\n");
goto error;
}
EPHYR_LOG("leave\n");
return xv_priv;
error:
if (xv_priv) {
ephyrXVPrivDelete(xv_priv);
xv_priv = NULL;
}
return NULL;
}
static void
ephyrXVPrivDelete(EphyrXVPriv * a_this)
{
EPHYR_LOG("enter\n");
if (!a_this)
return;
if (a_this->host_adaptors) {
ephyrHostXVAdaptorArrayDelete(a_this->host_adaptors);
a_this->host_adaptors = NULL;
}
free(a_this->adaptors);
a_this->adaptors = NULL;
free(a_this);
EPHYR_LOG("leave\n");
}
static KdVideoEncodingPtr
videoEncodingDup(EphyrHostEncoding * a_encodings, int a_num_encodings)
{
KdVideoEncodingPtr result = NULL;
int i = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_encodings && a_num_encodings, NULL);
result = calloc(a_num_encodings, sizeof(KdVideoEncodingRec));
for (i = 0; i < a_num_encodings; i++) {
result[i].id = a_encodings[i].id;
result[i].name = strdup(a_encodings[i].name);
result[i].width = a_encodings[i].width;
result[i].height = a_encodings[i].height;
result[i].rate.numerator = a_encodings[i].rate.numerator;
result[i].rate.denominator = a_encodings[i].rate.denominator;
}
return result;
}
static KdAttributePtr
portAttributesDup(EphyrHostAttribute * a_encodings, int a_num_encodings)
{
int i = 0;
KdAttributePtr result = NULL;
EPHYR_RETURN_VAL_IF_FAIL(a_encodings && a_num_encodings, NULL);
result = calloc(a_num_encodings, sizeof(KdAttributeRec));
if (!result) {
EPHYR_LOG_ERROR("failed to allocate attributes\n");
return NULL;
}
for (i = 0; i < a_num_encodings; i++) {
result[i].flags = a_encodings[i].flags;
result[i].min_value = a_encodings[i].min_value;
result[i].max_value = a_encodings[i].max_value;
result[i].name = strdup(a_encodings[i].name);
}
return result;
}
static Bool
ephyrXVPrivQueryHostAdaptors(EphyrXVPriv * a_this)
{
EphyrHostXVAdaptor *cur_host_adaptor = NULL;
EphyrHostVideoFormat *video_formats = NULL;
EphyrHostEncoding *encodings = NULL;
EphyrHostAttribute *attributes = NULL;
EphyrHostImageFormat *image_formats = NULL;
int num_video_formats = 0, base_port_id = 0,
num_attributes = 0, num_formats = 0, i = 0, port_priv_offset = 0;
unsigned num_encodings = 0;
Bool is_ok = FALSE;
EPHYR_RETURN_VAL_IF_FAIL(a_this, FALSE);
EPHYR_LOG("enter\n");
if (!ephyrHostXVQueryAdaptors(&a_this->host_adaptors)) {
EPHYR_LOG_ERROR("failed to query host adaptors\n");
goto out;
}
if (a_this->host_adaptors)
a_this->num_adaptors =
ephyrHostXVAdaptorArrayGetSize(a_this->host_adaptors);
if (a_this->num_adaptors < 0) {
EPHYR_LOG_ERROR("failed to get number of host adaptors\n");
goto out;
}
EPHYR_LOG("host has %d adaptors\n", a_this->num_adaptors);
/*
* copy what we can from adaptors into a_this->adaptors
*/
if (a_this->num_adaptors) {
a_this->adaptors = calloc(a_this->num_adaptors,
sizeof(KdVideoAdaptorRec));
if (!a_this->adaptors) {
EPHYR_LOG_ERROR("failed to create internal adaptors\n");
goto out;
}
}
for (i = 0; i < a_this->num_adaptors; i++) {
int j = 0;
cur_host_adaptor = ephyrHostXVAdaptorArrayAt(a_this->host_adaptors, i);
if (!cur_host_adaptor)
continue;
a_this->adaptors[i].nPorts =
ephyrHostXVAdaptorGetNbPorts(cur_host_adaptor);
if (a_this->adaptors[i].nPorts <= 0) {
EPHYR_LOG_ERROR("Could not find any port of adaptor %d\n", i);
continue;
}
a_this->adaptors[i].type = ephyrHostXVAdaptorGetType(cur_host_adaptor);
a_this->adaptors[i].type |= XvWindowMask;
a_this->adaptors[i].flags =
VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
if (ephyrHostXVAdaptorGetName(cur_host_adaptor))
a_this->adaptors[i].name =
strdup(ephyrHostXVAdaptorGetName(cur_host_adaptor));
else
a_this->adaptors[i].name = strdup("Xephyr Video Overlay");
base_port_id = ephyrHostXVAdaptorGetFirstPortID(cur_host_adaptor);
if (base_port_id < 0) {
EPHYR_LOG_ERROR("failed to get port id for adaptor %d\n", i);
continue;
}
if (!s_base_port_id)
s_base_port_id = base_port_id;
if (!ephyrHostXVQueryEncodings(base_port_id,
&encodings, &num_encodings)) {
EPHYR_LOG_ERROR("failed to get encodings for port port id %d,"
" adaptors %d\n", base_port_id, i);
continue;
}
a_this->adaptors[i].nEncodings = num_encodings;
a_this->adaptors[i].pEncodings =
videoEncodingDup(encodings, num_encodings);
video_formats = (EphyrHostVideoFormat *)
ephyrHostXVAdaptorGetVideoFormats(cur_host_adaptor,
&num_video_formats);
a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats;
a_this->adaptors[i].nFormats = num_video_formats;
/* got a_this->adaptors[i].nPorts already
a_this->adaptors[i].nPorts =
ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ;
*/
a_this->adaptors[i].pPortPrivates =
calloc(a_this->adaptors[i].nPorts,
sizeof(DevUnion) + sizeof(EphyrPortPriv));
port_priv_offset = a_this->adaptors[i].nPorts;
for (j = 0; j < a_this->adaptors[i].nPorts; j++) {
EphyrPortPriv *port_privs_base =
(EphyrPortPriv *) & a_this->adaptors[i].
pPortPrivates[port_priv_offset];
EphyrPortPriv *port_priv = &port_privs_base[j];
port_priv->port_number = base_port_id + j;
port_priv->current_adaptor = &a_this->adaptors[i];
port_priv->xv_priv = a_this;
a_this->adaptors[i].pPortPrivates[j].ptr = port_priv;
}
if (!ephyrHostXVQueryPortAttributes(base_port_id,
&attributes, &num_attributes)) {
EPHYR_LOG_ERROR("failed to get port attribute "
"for adaptor %d\n", i);
continue;
}
a_this->adaptors[i].pAttributes =
portAttributesDup(attributes, num_attributes);
a_this->adaptors[i].nAttributes = num_attributes;
/*make sure atoms of attrs names are created in xephyr */
for (j = 0; j < a_this->adaptors[i].nAttributes; j++) {
if (a_this->adaptors[i].pAttributes[j].name)
MakeAtom(a_this->adaptors[i].pAttributes[j].name,
strlen(a_this->adaptors[i].pAttributes[j].name), TRUE);
}
if (!ephyrHostXVQueryImageFormats(base_port_id,
&image_formats, &num_formats)) {
EPHYR_LOG_ERROR("failed to get image formats "
"for adaptor %d\n", i);
continue;
}
a_this->adaptors[i].pImages = (KdImagePtr) image_formats;
a_this->adaptors[i].nImages = num_formats;
}
is_ok = TRUE;
out:
if (encodings) {
ephyrHostEncodingsDelete(encodings, num_encodings);
encodings = NULL;
}
if (attributes) {
ephyrHostAttributesDelete(attributes);
attributes = NULL;
}
EPHYR_LOG("leave\n");
return is_ok;
}
static Bool
ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this)
{
int i = 0;
Bool has_it = FALSE;
EphyrHostXVAdaptor *cur_host_adaptor = NULL;
EPHYR_RETURN_VAL_IF_FAIL(a_this, FALSE);
EPHYR_LOG("enter\n");
for (i = 0; i < a_this->num_adaptors; i++) {
a_this->adaptors[i].ReputImage = ephyrReputImage;
a_this->adaptors[i].StopVideo = ephyrStopVideo;
a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute;
a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute;
a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize;
a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes;
cur_host_adaptor = ephyrHostXVAdaptorArrayAt(a_this->host_adaptors, i);
if (!cur_host_adaptor) {
EPHYR_LOG_ERROR("failed to get host adaptor at index %d\n", i);
continue;
}
has_it = FALSE;
if (!ephyrHostXVAdaptorHasPutImage(cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR("error\n");
}
if (has_it) {
a_this->adaptors[i].PutImage = ephyrPutImage;
}
has_it = FALSE;
if (!ephyrHostXVAdaptorHasPutVideo(cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR("error\n");
}
if (has_it) {
a_this->adaptors[i].PutVideo = ephyrPutVideo;
}
has_it = FALSE;
if (!ephyrHostXVAdaptorHasGetVideo(cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR("error\n");
}
if (has_it) {
a_this->adaptors[i].GetVideo = ephyrGetVideo;
}
has_it = FALSE;
if (!ephyrHostXVAdaptorHasPutStill(cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR("error\n");
}
if (has_it) {
a_this->adaptors[i].PutStill = ephyrPutStill;
}
has_it = FALSE;
if (!ephyrHostXVAdaptorHasGetStill(cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR("error\n");
}
if (has_it) {
a_this->adaptors[i].GetStill = ephyrGetStill;
}
}
EPHYR_LOG("leave\n");
return TRUE;
}
static Bool
ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
{
KdScreenPriv(a_screen);
KdScreenInfo *screen = pScreenPriv->screen;
Bool is_ok = FALSE;
KdVideoAdaptorPtr *adaptors = NULL, *registered_adaptors = NULL;
int num_registered_adaptors = 0, i = 0, num_adaptors = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_this && a_screen, FALSE);
EPHYR_LOG("enter\n");
if (!a_this->num_adaptors)
goto out;
num_registered_adaptors =
KdXVListGenericAdaptors(screen, &registered_adaptors);
num_adaptors = num_registered_adaptors + a_this->num_adaptors;
adaptors = calloc(num_adaptors, sizeof(KdVideoAdaptorPtr));
if (!adaptors) {
EPHYR_LOG_ERROR("failed to allocate adaptors tab\n");
goto out;
}
memmove(adaptors, registered_adaptors, num_registered_adaptors);
for (i = 0; i < a_this->num_adaptors; i++) {
*(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i];
}
if (!KdXVScreenInit(a_screen, adaptors, num_adaptors)) {
EPHYR_LOG_ERROR("failed to register adaptors\n");
goto out;
}
EPHYR_LOG("there are %d registered adaptors\n", num_adaptors);
is_ok = TRUE;
out:
free(registered_adaptors);
registered_adaptors = NULL;
free(adaptors);
adaptors = NULL;
EPHYR_LOG("leave\n");
return is_ok;
}
static Bool
ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs,
int a_attrs_len,
const char *a_attr_name,
int a_attr_value, Bool *a_is_valid)
{
int i = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_attrs && a_attr_name && a_is_valid, FALSE);
for (i = 0; i < a_attrs_len; i++) {
if (a_attrs[i].name && strcmp(a_attrs[i].name, a_attr_name))
continue;
if (a_attrs[i].min_value > a_attr_value ||
a_attrs[i].max_value < a_attr_value) {
*a_is_valid = FALSE;
EPHYR_LOG_ERROR("attribute was not valid\n"
"value:%d. min:%d. max:%d\n",
a_attr_value,
a_attrs[i].min_value, a_attrs[i].max_value);
}
else {
*a_is_valid = TRUE;
}
return TRUE;
}
return FALSE;
}
static Bool
ephyrXVPrivGetImageBufSize(int a_port_id,
int a_image_id,
unsigned short a_width,
unsigned short a_height, int *a_size)
{
Bool is_ok = FALSE;
unsigned short width = a_width, height = a_height;
EPHYR_RETURN_VAL_IF_FAIL(a_size, FALSE);
EPHYR_LOG("enter\n");
if (!ephyrHostXVQueryImageAttributes(a_port_id, a_image_id,
&width, &height, a_size, NULL, NULL)) {
EPHYR_LOG_ERROR("failed to get image attributes\n");
goto out;
}
is_ok = TRUE;
out:
EPHYR_LOG("leave\n");
return is_ok;
}
static Bool
ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv * a_port_priv,
const unsigned char *a_image_buf,
int a_image_len)
{
Bool is_ok = FALSE;
EPHYR_LOG("enter\n");
if (a_port_priv->image_buf_size < a_image_len) {
unsigned char *buf = NULL;
buf = realloc(a_port_priv->image_buf, a_image_len);
if (!buf) {
EPHYR_LOG_ERROR("failed to realloc image buffer\n");
goto out;
}
a_port_priv->image_buf = buf;
a_port_priv->image_buf_size = a_image_len;
}
memmove(a_port_priv->image_buf, a_image_buf, a_image_len);
is_ok = TRUE;
out:
return is_ok;
EPHYR_LOG("leave\n");
}
static void
ephyrStopVideo(KdScreenInfo * a_info, pointer a_port_priv, Bool a_exit)
{
EphyrPortPriv *port_priv = a_port_priv;
EPHYR_RETURN_IF_FAIL(a_info && a_info->pScreen);
EPHYR_RETURN_IF_FAIL(port_priv);
EPHYR_LOG("enter\n");
if (!ephyrHostXVStopVideo(a_info->pScreen->myNum, port_priv->port_number)) {
EPHYR_LOG_ERROR("XvStopVideo() failed\n");
}
EPHYR_LOG("leave\n");
}
static int
ephyrSetPortAttribute(KdScreenInfo * a_info,
Atom a_attr_name, int a_attr_value, pointer a_port_priv)
{
int res = Success, host_atom = 0;
EphyrPortPriv *port_priv = a_port_priv;
Bool is_attr_valid = FALSE;
EPHYR_RETURN_VAL_IF_FAIL(port_priv, BadMatch);
EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor, BadMatch);
EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor->pAttributes, BadMatch);
EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor->nAttributes, BadMatch);
EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name), BadMatch);
EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n",
port_priv->port_number,
(int) a_attr_name, NameForAtom(a_attr_name), a_attr_value);
if (!ephyrLocalAtomToHost(a_attr_name, &host_atom)) {
EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
res = BadMatch;
goto out;
}
if (!ephyrXVPrivIsAttrValueValid(port_priv->current_adaptor->pAttributes,
port_priv->current_adaptor->nAttributes,
NameForAtom(a_attr_name),
a_attr_value, &is_attr_valid)) {
EPHYR_LOG_ERROR("failed to validate attribute %s\n",
NameForAtom(a_attr_name));
/*
res = BadMatch ;
goto out ;
*/
}
if (!is_attr_valid) {
EPHYR_LOG_ERROR("attribute %s is not valid\n",
NameForAtom(a_attr_name));
/*
res = BadMatch ;
goto out ;
*/
}
if (!ephyrHostXVSetPortAttribute(port_priv->port_number,
host_atom, a_attr_value)) {
EPHYR_LOG_ERROR("failed to set port attribute\n");
res = BadMatch;
goto out;
}
res = Success;
out:
EPHYR_LOG("leave\n");
return res;
}
static int
ephyrGetPortAttribute(KdScreenInfo * a_screen_info,
Atom a_attr_name, int *a_attr_value, pointer a_port_priv)
{
int res = Success, host_atom = 0;
EphyrPortPriv *port_priv = a_port_priv;
EPHYR_RETURN_VAL_IF_FAIL(port_priv, BadMatch);
EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name), BadMatch);
EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s\n",
port_priv->port_number,
(int) a_attr_name, NameForAtom(a_attr_name));
if (!ephyrLocalAtomToHost(a_attr_name, &host_atom)) {
EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
res = BadMatch;
goto out;
}
if (!ephyrHostXVGetPortAttribute(port_priv->port_number,
host_atom, a_attr_value)) {
EPHYR_LOG_ERROR("failed to get port attribute\n");
res = BadMatch;
goto out;
}
res = Success;
out:
EPHYR_LOG("leave\n");
return res;
}
static void
ephyrQueryBestSize(KdScreenInfo * a_info,
Bool a_motion,
short a_src_w,
short a_src_h,
short a_drw_w,
short a_drw_h,
unsigned int *a_prefered_w,
unsigned int *a_prefered_h, pointer a_port_priv)
{
int res = 0;
EphyrPortPriv *port_priv = a_port_priv;
EPHYR_RETURN_IF_FAIL(port_priv);
EPHYR_LOG("enter\n");
res = ephyrHostXVQueryBestSize(port_priv->port_number,
a_motion,
a_src_w, a_src_h,
a_drw_w, a_drw_h,
a_prefered_w, a_prefered_h);
if (!res) {
EPHYR_LOG_ERROR("Failed to query best size\n");
}
EPHYR_LOG("leave\n");
}
static int
ephyrPutImage(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_src_x,
short a_src_y,
short a_drw_x,
short a_drw_y,
short a_src_w,
short a_src_h,
short a_drw_w,
short a_drw_h,
int a_id,
unsigned char *a_buf,
short a_width,
short a_height,
Bool a_sync, RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
Bool is_ok = FALSE;
int result = BadImplementation, image_size = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable, BadValue);
EPHYR_LOG("enter\n");
if (!ephyrHostXVPutImage(a_info->pScreen->myNum,
port_priv->port_number,
a_id,
a_drw_x, a_drw_y, a_drw_w, a_drw_h,
a_src_x, a_src_y, a_src_w, a_src_h,
a_width, a_height, a_buf,
(EphyrHostBox *) RegionRects(a_clipping_region),
RegionNumRects(a_clipping_region))) {
EPHYR_LOG_ERROR("EphyrHostXVPutImage() failed\n");
goto out;
}
/*
* Now save the image so that we can resend it to host it
* later, in ReputImage.
*/
if (!ephyrXVPrivGetImageBufSize(port_priv->port_number,
a_id, a_width, a_height, &image_size)) {
EPHYR_LOG_ERROR("failed to get image size\n");
/*this is a minor error so we won't get bail out abruptly */
is_ok = FALSE;
}
else {
is_ok = TRUE;
}
if (is_ok) {
if (!ephyrXVPrivSaveImageToPortPriv(port_priv, a_buf, image_size)) {
is_ok = FALSE;
}
else {
port_priv->image_id = a_id;
port_priv->drw_x = a_drw_x;
port_priv->drw_y = a_drw_y;
port_priv->drw_w = a_drw_w;
port_priv->drw_h = a_drw_h;
port_priv->src_x = a_src_x;
port_priv->src_y = a_src_y;
port_priv->src_w = a_src_w;
port_priv->src_h = a_src_h;
port_priv->image_width = a_width;
port_priv->image_height = a_height;
}
}
if (!is_ok) {
if (port_priv->image_buf) {
free(port_priv->image_buf);
port_priv->image_buf = NULL;
port_priv->image_buf_size = 0;
}
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrReputImage(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_drw_x,
short a_drw_y, RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
int result = BadImplementation;
EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, FALSE);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
EPHYR_LOG("enter\n");
if (!port_priv->image_buf_size || !port_priv->image_buf) {
EPHYR_LOG_ERROR("has null image buf in cache\n");
goto out;
}
if (!ephyrHostXVPutImage(a_info->pScreen->myNum,
port_priv->port_number,
port_priv->image_id,
a_drw_x, a_drw_y,
port_priv->drw_w, port_priv->drw_h,
port_priv->src_x, port_priv->src_y,
port_priv->src_w, port_priv->src_h,
port_priv->image_width, port_priv->image_height,
port_priv->image_buf,
(EphyrHostBox *) RegionRects(a_clipping_region),
RegionNumRects(a_clipping_region))) {
EPHYR_LOG_ERROR("ephyrHostXVPutImage() failed\n");
goto out;
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrPutVideo(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
BoxRec clipped_area, dst_box;
int result = BadImplementation;
int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
EPHYR_LOG("enter\n");
dst_box.x1 = a_drw_x;
dst_box.x2 = a_drw_x + a_drw_w;
dst_box.y1 = a_drw_y;
dst_box.y2 = a_drw_y + a_drw_h;
if (!DoSimpleClip(&dst_box,
RegionExtents(a_clipping_region), &clipped_area)) {
EPHYR_LOG_ERROR("failed to simple clip\n");
goto out;
}
drw_x = clipped_area.x1;
drw_y = clipped_area.y1;
drw_w = clipped_area.x2 - clipped_area.x1;
drw_h = clipped_area.y2 - clipped_area.y1;
if (!ephyrHostXVPutVideo(a_info->pScreen->myNum,
port_priv->port_number,
a_vid_x, a_vid_y, a_vid_w, a_vid_h,
a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
EPHYR_LOG_ERROR("ephyrHostXVPutVideo() failed\n");
goto out;
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrGetVideo(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
BoxRec clipped_area, dst_box;
int result = BadImplementation;
int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
EPHYR_LOG("enter\n");
dst_box.x1 = a_drw_x;
dst_box.x2 = a_drw_x + a_drw_w;
dst_box.y1 = a_drw_y;
dst_box.y2 = a_drw_y + a_drw_h;
if (!DoSimpleClip(&dst_box,
RegionExtents(a_clipping_region), &clipped_area)) {
EPHYR_LOG_ERROR("failed to simple clip\n");
goto out;
}
drw_x = clipped_area.x1;
drw_y = clipped_area.y1;
drw_w = clipped_area.x2 - clipped_area.x1;
drw_h = clipped_area.y2 - clipped_area.y1;
if (!ephyrHostXVGetVideo(a_info->pScreen->myNum,
port_priv->port_number,
a_vid_x, a_vid_y, a_vid_w, a_vid_h,
a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
EPHYR_LOG_ERROR("ephyrHostXVGetVideo() failed\n");
goto out;
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrPutStill(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
BoxRec clipped_area, dst_box;
int result = BadImplementation;
int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
EPHYR_LOG("enter\n");
dst_box.x1 = a_drw_x;
dst_box.x2 = a_drw_x + a_drw_w;
dst_box.y1 = a_drw_y;
dst_box.y2 = a_drw_y + a_drw_h;
if (!DoSimpleClip(&dst_box,
RegionExtents(a_clipping_region), &clipped_area)) {
EPHYR_LOG_ERROR("failed to simple clip\n");
goto out;
}
drw_x = clipped_area.x1;
drw_y = clipped_area.y1;
drw_w = clipped_area.x2 - clipped_area.x1;
drw_h = clipped_area.y2 - clipped_area.y1;
if (!ephyrHostXVPutStill(a_info->pScreen->myNum,
port_priv->port_number,
a_vid_x, a_vid_y, a_vid_w, a_vid_h,
a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
EPHYR_LOG_ERROR("ephyrHostXVPutStill() failed\n");
goto out;
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrGetStill(KdScreenInfo * a_info,
DrawablePtr a_drawable,
short a_vid_x, short a_vid_y,
short a_drw_x, short a_drw_y,
short a_vid_w, short a_vid_h,
short a_drw_w, short a_drw_h,
RegionPtr a_clipping_region, pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv;
BoxRec clipped_area, dst_box;
int result = BadImplementation;
int drw_x = 0, drw_y = 0, drw_w = 0, drw_h = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
EPHYR_LOG("enter\n");
dst_box.x1 = a_drw_x;
dst_box.x2 = a_drw_x + a_drw_w;
dst_box.y1 = a_drw_y;
dst_box.y2 = a_drw_y + a_drw_h;
if (!DoSimpleClip(&dst_box,
RegionExtents(a_clipping_region), &clipped_area)) {
EPHYR_LOG_ERROR("failed to simple clip\n");
goto out;
}
drw_x = clipped_area.x1;
drw_y = clipped_area.y1;
drw_w = clipped_area.x2 - clipped_area.x1;
drw_h = clipped_area.y2 - clipped_area.y1;
if (!ephyrHostXVGetStill(a_info->pScreen->myNum,
port_priv->port_number,
a_vid_x, a_vid_y, a_vid_w, a_vid_h,
a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
EPHYR_LOG_ERROR("ephyrHostXVGetStill() failed\n");
goto out;
}
result = Success;
out:
EPHYR_LOG("leave\n");
return result;
}
static int
ephyrQueryImageAttributes(KdScreenInfo * a_info,
int a_id,
unsigned short *a_w,
unsigned short *a_h, int *a_pitches, int *a_offsets)
{
int image_size = 0;
EPHYR_RETURN_VAL_IF_FAIL(a_w && a_h, FALSE);
EPHYR_LOG("enter: dim (%dx%d), pitches: %p, offsets: %p\n",
*a_w, *a_h, a_pitches, a_offsets);
if (!ephyrHostXVQueryImageAttributes(s_base_port_id,
a_id,
a_w, a_h,
&image_size, a_pitches, a_offsets)) {
EPHYR_LOG_ERROR("EphyrHostXVQueryImageAttributes() failed\n");
goto out;
}
EPHYR_LOG("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h);
out:
EPHYR_LOG("leave\n");
return image_size;
}