1279 lines
		
	
	
		
			41 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1279 lines
		
	
	
		
			41 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)
 | |
| {
 | |
|     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[0].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 = xcalloc (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 ;
 | |
|     }
 | |
|     if (a_this->adaptors) {
 | |
|         xfree (a_this->adaptors) ;
 | |
|         a_this->adaptors = NULL ;
 | |
|     }
 | |
|     xfree (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 = xcalloc (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 = xcalloc (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 = xcalloc (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 =
 | |
|                 xcalloc (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, ®istered_adaptors);
 | |
| 
 | |
|     num_adaptors = num_registered_adaptors + a_this->num_adaptors ;
 | |
|     adaptors = xcalloc (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:
 | |
|     if (registered_adaptors) {
 | |
|         xfree (registered_adaptors) ;
 | |
|         registered_adaptors = NULL ;
 | |
|     }
 | |
|     if (adaptors) {
 | |
|         xfree (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*)REGION_RECTS (a_clipping_region),
 | |
|                               REGION_NUM_RECTS (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*)REGION_RECTS (a_clipping_region),
 | |
|                               REGION_NUM_RECTS (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,
 | |
|                        REGION_EXTENTS (pScreen->pScreen, 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,
 | |
|                        REGION_EXTENTS (pScreen->pScreen, 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,
 | |
|                        REGION_EXTENTS (pScreen->pScreen, 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,
 | |
|                        REGION_EXTENTS (pScreen->pScreen, 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: %#x, offsets: %#x\n",
 | |
|                *a_w, *a_h, (unsigned int)a_pitches, (unsigned int)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 ;
 | |
| }
 |