Implement ReputImage and StopVideo

* hw/kdrive/ephyr/ephyrhostvideo.c/h:
	  (ephyrHostXVStopVideo): add this entry point.
	* hw/kdrive/ephyr/ephyrvideo.c:
	  Basically add ReputImage and StopVideo implementations.
	  Now, when other windows obscur the video window, the reclipping
	  seems to be well handled using StopVideo and ReputImage.
	  To do this, I was obliged to save the frame in PutImage, so
	  that I could resend it un ReputImage.
This commit is contained in:
Dodji Seketeli 2007-08-16 17:30:13 +02:00 committed by Dodji Seketeli
parent 810dc55866
commit 0b85451449
3 changed files with 204 additions and 6 deletions

View File

@ -976,3 +976,26 @@ out:
return is_ok ;
}
Bool
ephyrHostXVStopVideo (int a_port_id)
{
int ret=0 ;
Bool is_ok=FALSE ;
Display *dpy = hostx_get_display () ;
EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
EPHYR_LOG ("enter\n") ;
ret = XvStopVideo (dpy, a_port_id, hostx_get_window ()) ;
if (ret != Success) {
EPHYR_LOG_ERROR ("XvStopVideo() failed: %d \n", ret) ;
goto out ;
}
is_ok = TRUE ;
out:
EPHYR_LOG ("leave\n") ;
return is_ok ;
}

View File

@ -223,5 +223,11 @@ Bool ephyrHostXVPutStill (int a_port_id,
Bool ephyrHostXVGetStill (int a_port_id,
int a_vid_x, int a_vid_y, int a_vid_w, int a_vid_h,
int a_drw_x, int a_drw_y, int a_drw_w, int a_drw_h) ;
/*
* StopVideo
*/
Bool ephyrHostXVStopVideo (int a_port_id) ;
#endif /*__EPHYRHOSTVIDEO_H__*/

View File

@ -49,6 +49,12 @@ 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 ;
@ -73,6 +79,16 @@ static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs,
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);
@ -115,6 +131,13 @@ static int ephyrPutImage (KdScreenInfo *a_info,
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,
@ -233,6 +256,8 @@ ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom)
return TRUE ;
}
/*
Not used yed.
static Bool
ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom)
{
@ -259,6 +284,7 @@ out:
}
return is_ok ;
}
*/
/**************
*</helpers>
@ -553,6 +579,7 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this)
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 ;
@ -569,36 +596,41 @@ ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this)
if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) {
EPHYR_LOG_ERROR ("error\n") ;
}
if (has_it)
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)
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)
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)
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)
if (has_it) {
a_this->adaptors[i].GetStill = ephyrGetStill;
}
}
EPHYR_LOG ("leave\n") ;
return TRUE ;
@ -679,10 +711,70 @@ ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs,
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 (port_priv) ;
EPHYR_LOG ("enter\n") ;
if (!ephyrHostXVStopVideo (port_priv->port_number)) {
EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ;
}
EPHYR_LOG ("leave\n") ;
}
@ -832,7 +924,8 @@ ephyrPutImage (KdScreenInfo *a_info,
pointer a_port_priv)
{
EphyrPortPriv *port_priv = a_port_priv ;
int result=BadImplementation ;
Bool is_ok=FALSE ;
int result=BadImplementation, image_size=0 ;
EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ;
@ -849,6 +942,82 @@ ephyrPutImage (KdScreenInfo *a_info,
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_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 (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*)REGION_RECTS (a_clipping_region),
REGION_NUM_RECTS (a_clipping_region))) {
EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ;
goto out ;
}
result = Success ;
out: