1/*
2 * Xephyr - A kdrive X server thats runs in a host X window.
3 *          Authored by Matthew Allum <mallum@openedhand.com>
4 *
5 * Copyright © 2007 OpenedHand Ltd
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of OpenedHand Ltd not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. OpenedHand Ltd makes no
14 * representations about the suitability of this software for any purpose.  It
15 * is provided "as is" without express or implied warranty.
16 *
17 * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 * Authors:
26 *    Dodji Seketeli <dodji@openedhand.com>
27 */
28
29#ifdef HAVE_CONFIG_H
30#include <kdrive-config.h>
31#endif
32#include <string.h>
33#include <X11/extensions/Xv.h>
34#include "ephyrlog.h"
35#include "kdrive.h"
36#include "kxv.h"
37#include "ephyr.h"
38#include "hostx.h"
39#include "ephyrhostvideo.h"
40
41struct _EphyrXVPriv {
42    EphyrHostXVAdaptorArray *host_adaptors ;
43    KdVideoAdaptorPtr adaptors ;
44    int num_adaptors ;
45};
46typedef struct _EphyrXVPriv EphyrXVPriv ;
47
48struct _EphyrPortPriv {
49    int port_number ;
50    KdVideoAdaptorPtr current_adaptor ;
51    EphyrXVPriv *xv_priv;
52    unsigned char *image_buf ;
53    int image_buf_size ;
54    int image_id ;
55    int drw_x, drw_y, drw_w, drw_h ;
56    int src_x, src_y, src_w, src_h ;
57    int image_width, image_height ;
58};
59typedef struct _EphyrPortPriv EphyrPortPriv ;
60
61static Bool DoSimpleClip (BoxPtr a_dst_drw,
62                          BoxPtr a_clipper,
63                          BoxPtr a_result) ;
64
65static Bool ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom) ;
66
67/*
68static Bool ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom) ;
69*/
70
71static EphyrXVPriv* ephyrXVPrivNew (void) ;
72static void ephyrXVPrivDelete (EphyrXVPriv *a_this) ;
73static Bool ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this) ;
74static Bool ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this) ;
75static Bool ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this,
76                                         ScreenPtr a_screen) ;
77
78static Bool ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs,
79                                         int a_attrs_len,
80                                         const char *a_attr_name,
81                                         int a_attr_value,
82                                         Bool *a_is_valid) ;
83
84static Bool ephyrXVPrivGetImageBufSize (int a_port_id,
85                                        int a_image_id,
86                                        unsigned short a_width,
87                                        unsigned short a_height,
88                                        int *a_size) ;
89
90static Bool ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv,
91                                            const unsigned char *a_image,
92                                            int a_image_len) ;
93
94static void ephyrStopVideo (KdScreenInfo *a_info,
95                            pointer a_xv_priv,
96                            Bool a_exit);
97
98static int ephyrSetPortAttribute (KdScreenInfo *a_info,
99                                  Atom a_attr_name,
100                                  int a_attr_value,
101                                  pointer a_port_priv);
102
103static int ephyrGetPortAttribute (KdScreenInfo *a_screen_info,
104                                  Atom a_attr_name,
105                                  int *a_attr_value,
106                                  pointer a_port_priv);
107
108static void ephyrQueryBestSize (KdScreenInfo *a_info,
109                                Bool a_motion,
110                                short a_src_w,
111                                short a_src_h,
112                                short a_drw_w,
113                                short a_drw_h,
114                                unsigned int *a_prefered_w,
115                                unsigned int *a_prefered_h,
116                                pointer a_port_priv);
117
118static int ephyrPutImage (KdScreenInfo *a_info,
119                          DrawablePtr a_drawable,
120                          short a_src_x,
121                          short a_src_y,
122                          short a_drw_x,
123                          short a_drw_y,
124                          short a_src_w,
125                          short a_src_h,
126                          short a_drw_w,
127                          short a_drw_h,
128                          int a_id,
129                          unsigned char *a_buf,
130                          short a_width,
131                          short a_height,
132                          Bool a_sync,
133                          RegionPtr a_clipping_region,
134                          pointer a_port_priv);
135
136static int ephyrReputImage (KdScreenInfo *a_info,
137                            DrawablePtr a_drawable,
138                            short a_drw_x,
139                            short a_drw_y,
140                            RegionPtr a_clipping_region,
141                            pointer a_port_priv) ;
142
143static int ephyrPutVideo (KdScreenInfo *a_info,
144                          DrawablePtr a_drawable,
145                          short a_vid_x, short a_vid_y,
146                          short a_drw_x, short a_drw_y,
147                          short a_vid_w, short a_vid_h,
148                          short a_drw_w, short a_drw_h,
149                          RegionPtr a_clip_region,
150                          pointer a_port_priv) ;
151
152static int ephyrGetVideo (KdScreenInfo *a_info,
153                          DrawablePtr a_drawable,
154                          short a_vid_x, short a_vid_y,
155                          short a_drw_x, short a_drw_y,
156                          short a_vid_w, short a_vid_h,
157                          short a_drw_w, short a_drw_h,
158                          RegionPtr a_clip_region,
159                          pointer a_port_priv) ;
160
161static int ephyrPutStill (KdScreenInfo *a_info,
162                          DrawablePtr a_drawable,
163                          short a_vid_x, short a_vid_y,
164                          short a_drw_x, short a_drw_y,
165                          short a_vid_w, short a_vid_h,
166                          short a_drw_w, short a_drw_h,
167                          RegionPtr a_clip_region,
168                          pointer a_port_priv) ;
169
170static int ephyrGetStill (KdScreenInfo *a_info,
171                          DrawablePtr a_drawable,
172                          short a_vid_x, short a_vid_y,
173                          short a_drw_x, short a_drw_y,
174                          short a_vid_w, short a_vid_h,
175                          short a_drw_w, short a_drw_h,
176                          RegionPtr a_clip_region,
177                          pointer a_port_priv) ;
178
179static int ephyrQueryImageAttributes (KdScreenInfo *a_info,
180                                      int a_id,
181                                      unsigned short *a_w,
182                                      unsigned short *a_h,
183                                      int *a_pitches,
184                                      int *a_offsets);
185static int s_base_port_id ;
186
187/**************
188 * <helpers>
189 * ************/
190
191static Bool
192DoSimpleClip (BoxPtr a_dst_box,
193              BoxPtr a_clipper,
194              BoxPtr a_result)
195{
196    BoxRec dstClippedBox ;
197
198    EPHYR_RETURN_VAL_IF_FAIL (a_dst_box && a_clipper && a_result, FALSE) ;
199
200    /*
201     * setup the clipbox inside the destination.
202     */
203    dstClippedBox.x1 = a_dst_box->x1 ;
204    dstClippedBox.x2 = a_dst_box->x2 ;
205    dstClippedBox.y1 = a_dst_box->y1 ;
206    dstClippedBox.y2 = a_dst_box->y2 ;
207
208    /*
209     * if the cliper leftmost edge is inside
210     * the destination area then the leftmost edge of the resulting
211     * clipped box is the leftmost edge of the cliper.
212     */
213    if (a_clipper->x1 > dstClippedBox.x1)
214        dstClippedBox.x1 = a_clipper->x1 ;
215
216    /*
217     * if the cliper top edge is inside the destination area
218     * then the bottom horizontal edge of the resulting clipped box
219     * is the bottom edge of the cliper
220     */
221    if (a_clipper->y1 > dstClippedBox.y1)
222        dstClippedBox.y1 = a_clipper->y1 ;
223
224    /*ditto for right edge*/
225    if (a_clipper->x2 < dstClippedBox.x2)
226        dstClippedBox.x2 = a_clipper->x2 ;
227
228    /*ditto for bottom edge*/
229    if (a_clipper->y2 < dstClippedBox.y2)
230        dstClippedBox.y2 = a_clipper->y2 ;
231
232    memcpy (a_result, &dstClippedBox, sizeof (dstClippedBox)) ;
233    return TRUE ;
234}
235
236static Bool
237ephyrLocalAtomToHost (int a_local_atom, int *a_host_atom)
238{
239    const char *atom_name=NULL;
240    int host_atom=None ;
241
242    EPHYR_RETURN_VAL_IF_FAIL (a_host_atom, FALSE) ;
243
244    if (!ValidAtom (a_local_atom))
245        return FALSE ;
246
247    atom_name = NameForAtom (a_local_atom) ;
248
249    if (!atom_name)
250        return FALSE ;
251
252    if (!ephyrHostGetAtom (atom_name, FALSE, &host_atom) || host_atom == None) {
253        EPHYR_LOG_ERROR ("no atom for string %s defined in host X\n",
254                         atom_name) ;
255        return FALSE ;
256    }
257    *a_host_atom = host_atom ;
258    return TRUE ;
259}
260
261/*
262 Not used yed.
263static Bool
264ephyrHostAtomToLocal (int a_host_atom, int *a_local_atom)
265{
266    Bool is_ok=FALSE ;
267    char *atom_name=NULL ;
268    int atom=None ;
269
270    EPHYR_RETURN_VAL_IF_FAIL (a_local_atom, FALSE) ;
271
272    atom_name = ephyrHostGetAtomName (a_host_atom) ;
273    if (!atom_name)
274        goto out ;
275
276    atom = MakeAtom (atom_name, strlen (atom_name), TRUE) ;
277    if (atom == None)
278        goto out ;
279
280    *a_local_atom = atom ;
281    is_ok = TRUE ;
282
283out:
284    if (atom_name) {
285        ephyrHostFree (atom_name) ;
286    }
287    return is_ok ;
288}
289*/
290
291/**************
292 *</helpers>
293 * ************/
294
295Bool
296ephyrInitVideo (ScreenPtr pScreen)
297{
298    Bool is_ok = FALSE ;
299    KdScreenPriv(pScreen);
300    KdScreenInfo *screen = pScreenPriv->screen;
301    static EphyrXVPriv *xv_priv;
302
303    EPHYR_LOG ("enter\n") ;
304
305    if (screen->fb.bitsPerPixel == 8) {
306        EPHYR_LOG_ERROR ("8 bits depth not supported\n") ;
307        return FALSE ;
308    }
309
310    if (!xv_priv) {
311        xv_priv = ephyrXVPrivNew () ;
312    }
313    if (!xv_priv) {
314        EPHYR_LOG_ERROR ("failed to create xv_priv\n") ;
315        goto out ;
316    }
317
318    if (!ephyrXVPrivRegisterAdaptors (xv_priv, pScreen)) {
319        EPHYR_LOG_ERROR ("failed to register adaptors\n") ;
320        goto out ;
321    }
322    is_ok = TRUE ;
323
324out:
325    return is_ok ;
326}
327
328static EphyrXVPriv*
329ephyrXVPrivNew (void)
330{
331    EphyrXVPriv *xv_priv=NULL ;
332
333    EPHYR_LOG ("enter\n") ;
334
335    xv_priv = calloc(1, sizeof (EphyrXVPriv)) ;
336    if (!xv_priv) {
337        EPHYR_LOG_ERROR ("failed to create EphyrXVPriv\n") ;
338        goto error ;
339    }
340
341    ephyrHostXVInit () ;
342
343    if (!ephyrXVPrivQueryHostAdaptors (xv_priv)) {
344        EPHYR_LOG_ERROR ("failed to query the host x for xv properties\n") ;
345        goto error ;
346    }
347    if (!ephyrXVPrivSetAdaptorsHooks (xv_priv)) {
348        EPHYR_LOG_ERROR ("failed to set xv_priv hooks\n") ;
349        goto error ;
350    }
351
352    EPHYR_LOG ("leave\n") ;
353    return xv_priv ;
354
355error:
356    if (xv_priv) {
357        ephyrXVPrivDelete (xv_priv) ;
358        xv_priv = NULL ;
359    }
360    return NULL ;
361}
362
363static void
364ephyrXVPrivDelete (EphyrXVPriv *a_this)
365{
366    EPHYR_LOG ("enter\n") ;
367
368    if (!a_this)
369        return ;
370    if (a_this->host_adaptors) {
371        ephyrHostXVAdaptorArrayDelete (a_this->host_adaptors) ;
372        a_this->host_adaptors = NULL ;
373    }
374    free(a_this->adaptors) ;
375    a_this->adaptors = NULL ;
376    free(a_this) ;
377    EPHYR_LOG ("leave\n") ;
378}
379
380static KdVideoEncodingPtr
381videoEncodingDup (EphyrHostEncoding *a_encodings,
382                   int a_num_encodings)
383{
384    KdVideoEncodingPtr result = NULL ;
385    int i=0 ;
386
387    EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ;
388
389    result = calloc(a_num_encodings, sizeof (KdVideoEncodingRec)) ;
390    for (i=0 ; i < a_num_encodings; i++) {
391        result[i].id = a_encodings[i].id ;
392        result[i].name = strdup (a_encodings[i].name) ;
393        result[i].width = a_encodings[i].width ;
394        result[i].height = a_encodings[i].height ;
395        result[i].rate.numerator = a_encodings[i].rate.numerator ;
396        result[i].rate.denominator = a_encodings[i].rate.denominator ;
397    }
398    return result ;
399}
400
401static KdAttributePtr
402portAttributesDup (EphyrHostAttribute *a_encodings,
403                   int a_num_encodings)
404{
405    int i=0 ;
406    KdAttributePtr result=NULL ;
407
408    EPHYR_RETURN_VAL_IF_FAIL (a_encodings && a_num_encodings, NULL) ;
409
410    result = calloc(a_num_encodings, sizeof (KdAttributeRec)) ;
411    if (!result) {
412        EPHYR_LOG_ERROR ("failed to allocate attributes\n") ;
413        return NULL ;
414    }
415    for (i=0; i < a_num_encodings; i++) {
416        result[i].flags = a_encodings[i].flags ;
417        result[i].min_value = a_encodings[i].min_value ;
418        result[i].max_value = a_encodings[i].max_value ;
419        result[i].name = strdup (a_encodings[i].name) ;
420    }
421    return result ;
422}
423
424static Bool
425ephyrXVPrivQueryHostAdaptors (EphyrXVPriv *a_this)
426{
427    EphyrHostXVAdaptor *cur_host_adaptor=NULL ;
428    EphyrHostVideoFormat *video_formats=NULL ;
429    EphyrHostEncoding *encodings=NULL ;
430    EphyrHostAttribute *attributes=NULL ;
431    EphyrHostImageFormat *image_formats=NULL ;
432    int num_video_formats=0, base_port_id=0,
433        num_attributes=0, num_formats=0, i=0,
434        port_priv_offset=0;
435    unsigned num_encodings=0 ;
436    Bool is_ok = FALSE ;
437
438    EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ;
439
440    EPHYR_LOG ("enter\n") ;
441
442    if (!ephyrHostXVQueryAdaptors (&a_this->host_adaptors)) {
443        EPHYR_LOG_ERROR ("failed to query host adaptors\n") ;
444        goto out ;
445    }
446    if (a_this->host_adaptors)
447        a_this->num_adaptors =
448                    ephyrHostXVAdaptorArrayGetSize (a_this->host_adaptors) ;
449    if (a_this->num_adaptors < 0) {
450        EPHYR_LOG_ERROR ("failed to get number of host adaptors\n") ;
451        goto out ;
452    }
453    EPHYR_LOG ("host has %d adaptors\n", a_this->num_adaptors) ;
454    /*
455     * copy what we can from adaptors into a_this->adaptors
456     */
457    if (a_this->num_adaptors) {
458        a_this->adaptors = calloc(a_this->num_adaptors,
459                                    sizeof (KdVideoAdaptorRec)) ;
460        if (!a_this->adaptors) {
461            EPHYR_LOG_ERROR ("failed to create internal adaptors\n") ;
462            goto out ;
463        }
464    }
465    for (i=0; i < a_this->num_adaptors; i++) {
466        int j=0 ;
467        cur_host_adaptor =
468                   ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ;
469        if (!cur_host_adaptor)
470            continue ;
471        a_this->adaptors[i].nPorts =
472                            ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ;
473        if (a_this->adaptors[i].nPorts <=0) {
474            EPHYR_LOG_ERROR ("Could not find any port of adaptor %d\n", i) ;
475            continue ;
476        }
477        a_this->adaptors[i].type =
478                        ephyrHostXVAdaptorGetType (cur_host_adaptor) ;
479        a_this->adaptors[i].type |= XvWindowMask ;
480        a_this->adaptors[i].flags =
481                        VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
482        if (ephyrHostXVAdaptorGetName (cur_host_adaptor))
483            a_this->adaptors[i].name =
484                    strdup (ephyrHostXVAdaptorGetName (cur_host_adaptor)) ;
485        else
486            a_this->adaptors[i].name = strdup ("Xephyr Video Overlay");
487        base_port_id = ephyrHostXVAdaptorGetFirstPortID (cur_host_adaptor) ;
488        if (base_port_id < 0) {
489            EPHYR_LOG_ERROR ("failed to get port id for adaptor %d\n", i) ;
490            continue ;
491        }
492        if (!s_base_port_id)
493            s_base_port_id = base_port_id ;
494
495        if (!ephyrHostXVQueryEncodings (base_port_id,
496                                        &encodings,
497                                        &num_encodings)) {
498            EPHYR_LOG_ERROR ("failed to get encodings for port port id %d,"
499                             " adaptors %d\n",
500                             base_port_id, i) ;
501            continue ;
502        }
503        a_this->adaptors[i].nEncodings = num_encodings ;
504        a_this->adaptors[i].pEncodings =
505                            videoEncodingDup (encodings, num_encodings) ;
506        video_formats = (EphyrHostVideoFormat*)
507            ephyrHostXVAdaptorGetVideoFormats (cur_host_adaptor,
508                                               &num_video_formats);
509        a_this->adaptors[i].pFormats = (KdVideoFormatPtr) video_formats ;
510        a_this->adaptors[i].nFormats = num_video_formats ;
511        /* got a_this->adaptors[i].nPorts already
512        a_this->adaptors[i].nPorts =
513                            ephyrHostXVAdaptorGetNbPorts (cur_host_adaptor) ;
514        */
515        a_this->adaptors[i].pPortPrivates =
516                calloc(a_this->adaptors[i].nPorts,
517                         sizeof (DevUnion) + sizeof (EphyrPortPriv)) ;
518        port_priv_offset = a_this->adaptors[i].nPorts;
519        for (j=0; j < a_this->adaptors[i].nPorts; j++) {
520            EphyrPortPriv *port_privs_base =
521                    (EphyrPortPriv*)&a_this->adaptors[i].pPortPrivates[port_priv_offset];
522            EphyrPortPriv *port_priv = &port_privs_base[j] ;
523            port_priv->port_number = base_port_id + j;
524            port_priv->current_adaptor = &a_this->adaptors[i] ;
525            port_priv->xv_priv = a_this ;
526            a_this->adaptors[i].pPortPrivates[j].ptr = port_priv;
527        }
528        if (!ephyrHostXVQueryPortAttributes (base_port_id,
529                                             &attributes,
530                                             &num_attributes)) {
531            EPHYR_LOG_ERROR ("failed to get port attribute "
532                             "for adaptor %d\n", i) ;
533            continue ;
534        }
535        a_this->adaptors[i].pAttributes =
536                    portAttributesDup (attributes, num_attributes);
537        a_this->adaptors[i].nAttributes = num_attributes ;
538        /*make sure atoms of attrs names are created in xephyr*/
539        for (j=0; j < a_this->adaptors[i].nAttributes; j++) {
540            if (a_this->adaptors[i].pAttributes[j].name)
541                MakeAtom (a_this->adaptors[i].pAttributes[j].name,
542                          strlen (a_this->adaptors[i].pAttributes[j].name),
543                          TRUE) ;
544        }
545        if (!ephyrHostXVQueryImageFormats (base_port_id,
546                                           &image_formats,
547                                           &num_formats)) {
548            EPHYR_LOG_ERROR ("failed to get image formats "
549                             "for adaptor %d\n", i) ;
550            continue ;
551        }
552        a_this->adaptors[i].pImages = (KdImagePtr) image_formats ;
553        a_this->adaptors[i].nImages = num_formats ;
554    }
555    is_ok = TRUE ;
556
557out:
558    if (encodings) {
559        ephyrHostEncodingsDelete (encodings, num_encodings) ;
560        encodings = NULL ;
561    }
562    if (attributes) {
563        ephyrHostAttributesDelete (attributes) ;
564        attributes = NULL ;
565    }
566    EPHYR_LOG ("leave\n") ;
567    return is_ok ;
568}
569
570static Bool
571ephyrXVPrivSetAdaptorsHooks (EphyrXVPriv *a_this)
572{
573    int i=0 ;
574    Bool has_it=FALSE ;
575    EphyrHostXVAdaptor *cur_host_adaptor=NULL ;
576
577    EPHYR_RETURN_VAL_IF_FAIL (a_this, FALSE) ;
578
579    EPHYR_LOG ("enter\n") ;
580
581    for (i=0; i < a_this->num_adaptors; i++) {
582        a_this->adaptors[i].ReputImage = ephyrReputImage ;
583        a_this->adaptors[i].StopVideo = ephyrStopVideo ;
584        a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute ;
585        a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute ;
586        a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize ;
587        a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes ;
588
589        cur_host_adaptor =
590                   ephyrHostXVAdaptorArrayAt (a_this->host_adaptors, i) ;
591        if (!cur_host_adaptor) {
592            EPHYR_LOG_ERROR ("failed to get host adaptor at index %d\n", i) ;
593            continue ;
594        }
595        has_it = FALSE ;
596        if (!ephyrHostXVAdaptorHasPutImage (cur_host_adaptor, &has_it)) {
597            EPHYR_LOG_ERROR ("error\n") ;
598        }
599        if (has_it) {
600            a_this->adaptors[i].PutImage = ephyrPutImage;
601        }
602
603        has_it = FALSE ;
604        if (!ephyrHostXVAdaptorHasPutVideo (cur_host_adaptor, &has_it)) {
605            EPHYR_LOG_ERROR ("error\n") ;
606        }
607        if (has_it) {
608            a_this->adaptors[i].PutVideo = ephyrPutVideo;
609        }
610
611        has_it = FALSE ;
612        if (!ephyrHostXVAdaptorHasGetVideo (cur_host_adaptor, &has_it)) {
613            EPHYR_LOG_ERROR ("error\n") ;
614        }
615        if (has_it) {
616            a_this->adaptors[i].GetVideo = ephyrGetVideo;
617        }
618
619        has_it = FALSE ;
620        if (!ephyrHostXVAdaptorHasPutStill (cur_host_adaptor, &has_it)) {
621            EPHYR_LOG_ERROR ("error\n") ;
622        }
623        if (has_it) {
624            a_this->adaptors[i].PutStill = ephyrPutStill;
625        }
626
627        has_it = FALSE ;
628        if (!ephyrHostXVAdaptorHasGetStill (cur_host_adaptor, &has_it)) {
629            EPHYR_LOG_ERROR ("error\n") ;
630        }
631        if (has_it) {
632            a_this->adaptors[i].GetStill = ephyrGetStill;
633        }
634    }
635    EPHYR_LOG ("leave\n") ;
636    return TRUE ;
637}
638
639static Bool
640ephyrXVPrivRegisterAdaptors (EphyrXVPriv *a_this,
641                             ScreenPtr a_screen)
642{
643    KdScreenPriv(a_screen);
644    KdScreenInfo *screen = pScreenPriv->screen;
645    Bool is_ok = FALSE ;
646    KdVideoAdaptorPtr *adaptors=NULL, *registered_adaptors=NULL ;
647    int num_registered_adaptors=0, i=0, num_adaptors=0 ;
648
649    EPHYR_RETURN_VAL_IF_FAIL (a_this && a_screen, FALSE) ;
650
651    EPHYR_LOG ("enter\n") ;
652
653    if (!a_this->num_adaptors)
654        goto out ;
655    num_registered_adaptors =
656                KdXVListGenericAdaptors (screen, &registered_adaptors);
657
658    num_adaptors = num_registered_adaptors + a_this->num_adaptors ;
659    adaptors = calloc(num_adaptors, sizeof (KdVideoAdaptorPtr)) ;
660    if (!adaptors) {
661        EPHYR_LOG_ERROR ("failed to allocate adaptors tab\n") ;
662        goto out ;
663    }
664    memmove (adaptors, registered_adaptors, num_registered_adaptors) ;
665    for (i=0 ; i < a_this->num_adaptors; i++) {
666        *(adaptors + num_registered_adaptors + i) = &a_this->adaptors[i] ;
667    }
668    if (!KdXVScreenInit (a_screen, adaptors, num_adaptors)) {
669        EPHYR_LOG_ERROR ("failed to register adaptors\n");
670        goto out ;
671    }
672    EPHYR_LOG ("there are  %d registered adaptors\n", num_adaptors) ;
673    is_ok = TRUE ;
674
675out:
676    free(registered_adaptors) ;
677    registered_adaptors = NULL ;
678    free(adaptors) ;
679    adaptors = NULL ;
680
681    EPHYR_LOG ("leave\n") ;
682    return is_ok ;
683}
684
685static Bool
686ephyrXVPrivIsAttrValueValid (KdAttributePtr a_attrs,
687                             int a_attrs_len,
688                             const char *a_attr_name,
689                             int a_attr_value,
690                             Bool *a_is_valid)
691{
692    int i=0 ;
693
694    EPHYR_RETURN_VAL_IF_FAIL (a_attrs && a_attr_name && a_is_valid,
695                              FALSE) ;
696
697    for (i=0; i < a_attrs_len; i++) {
698        if (a_attrs[i].name && strcmp (a_attrs[i].name, a_attr_name))
699            continue ;
700        if (a_attrs[i].min_value > a_attr_value ||
701            a_attrs[i].max_value < a_attr_value) {
702            *a_is_valid = FALSE ;
703            EPHYR_LOG_ERROR ("attribute was not valid\n"
704                             "value:%d. min:%d. max:%d\n",
705                             a_attr_value,
706                             a_attrs[i].min_value,
707                             a_attrs[i].max_value) ;
708        } else {
709            *a_is_valid = TRUE ;
710        }
711        return TRUE ;
712    }
713    return FALSE ;
714}
715
716static Bool
717ephyrXVPrivGetImageBufSize (int a_port_id,
718                            int a_image_id,
719                            unsigned short a_width,
720                            unsigned short a_height,
721                            int *a_size)
722{
723    Bool is_ok=FALSE ;
724    unsigned short width=a_width, height=a_height ;
725
726    EPHYR_RETURN_VAL_IF_FAIL (a_size, FALSE) ;
727
728    EPHYR_LOG ("enter\n") ;
729
730    if (!ephyrHostXVQueryImageAttributes (a_port_id, a_image_id,
731                                          &width, &height, a_size, NULL, NULL)) {
732        EPHYR_LOG_ERROR ("failed to get image attributes\n") ;
733        goto out ;
734    }
735    is_ok = TRUE ;
736
737out:
738    EPHYR_LOG ("leave\n") ;
739    return is_ok ;
740}
741
742static Bool
743ephyrXVPrivSaveImageToPortPriv (EphyrPortPriv *a_port_priv,
744                                const unsigned char *a_image_buf,
745                                int a_image_len)
746{
747    Bool is_ok=FALSE ;
748
749    EPHYR_LOG ("enter\n") ;
750
751    if (a_port_priv->image_buf_size < a_image_len) {
752        unsigned char *buf=NULL ;
753        buf = realloc (a_port_priv->image_buf, a_image_len) ;
754        if (!buf) {
755            EPHYR_LOG_ERROR ("failed to realloc image buffer\n") ;
756            goto out ;
757        }
758        a_port_priv->image_buf = buf ;
759        a_port_priv->image_buf_size = a_image_len;
760    }
761    memmove (a_port_priv->image_buf, a_image_buf, a_image_len) ;
762    is_ok = TRUE ;
763
764out:
765    return is_ok ;
766    EPHYR_LOG ("leave\n") ;
767}
768
769static void
770ephyrStopVideo (KdScreenInfo *a_info, pointer a_port_priv, Bool a_exit)
771{
772    EphyrPortPriv *port_priv = a_port_priv ;
773
774    EPHYR_RETURN_IF_FAIL (a_info && a_info->pScreen) ;
775    EPHYR_RETURN_IF_FAIL (port_priv) ;
776
777    EPHYR_LOG ("enter\n") ;
778    if (!ephyrHostXVStopVideo (a_info->pScreen->myNum,
779                               port_priv->port_number)) {
780        EPHYR_LOG_ERROR ("XvStopVideo() failed\n") ;
781    }
782    EPHYR_LOG ("leave\n") ;
783}
784
785static int
786ephyrSetPortAttribute (KdScreenInfo *a_info,
787                       Atom a_attr_name,
788                       int a_attr_value,
789                       pointer a_port_priv)
790{
791    int res=Success, host_atom=0 ;
792    EphyrPortPriv *port_priv = a_port_priv ;
793    Bool is_attr_valid=FALSE ;
794
795    EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ;
796    EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor, BadMatch) ;
797    EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->pAttributes,
798                              BadMatch) ;
799    EPHYR_RETURN_VAL_IF_FAIL (port_priv->current_adaptor->nAttributes,
800                              BadMatch) ;
801    EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ;
802
803    EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n",
804               port_priv->port_number,
805               (int)a_attr_name,
806               NameForAtom (a_attr_name),
807               a_attr_value) ;
808
809    if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) {
810        EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ;
811        res = BadMatch ;
812        goto out ;
813    }
814
815    if (!ephyrXVPrivIsAttrValueValid (port_priv->current_adaptor->pAttributes,
816                                      port_priv->current_adaptor->nAttributes,
817                                      NameForAtom (a_attr_name),
818                                      a_attr_value,
819                                      &is_attr_valid)) {
820        EPHYR_LOG_ERROR ("failed to validate attribute %s\n",
821                         NameForAtom (a_attr_name)) ;
822        /*
823         res = BadMatch ;
824         goto out ;
825         */
826    }
827    if (!is_attr_valid) {
828        EPHYR_LOG_ERROR ("attribute %s is not valid\n",
829                         NameForAtom (a_attr_name)) ;
830        /*
831        res = BadMatch ;
832        goto out ;
833        */
834    }
835
836    if (!ephyrHostXVSetPortAttribute (port_priv->port_number,
837                                      host_atom,
838                                      a_attr_value)) {
839        EPHYR_LOG_ERROR ("failed to set port attribute\n") ;
840        res = BadMatch ;
841        goto out ;
842    }
843
844    res = Success ;
845out:
846    EPHYR_LOG ("leave\n") ;
847    return res ;
848}
849
850static int
851ephyrGetPortAttribute (KdScreenInfo *a_screen_info,
852                       Atom a_attr_name,
853                       int *a_attr_value,
854                       pointer a_port_priv)
855{
856    int res=Success, host_atom=0 ;
857    EphyrPortPriv *port_priv = a_port_priv ;
858
859    EPHYR_RETURN_VAL_IF_FAIL (port_priv, BadMatch) ;
860    EPHYR_RETURN_VAL_IF_FAIL (ValidAtom (a_attr_name), BadMatch) ;
861
862    EPHYR_LOG ("enter, portnum:%d, atomid:%d, attr_name:%s\n",
863               port_priv->port_number,
864               (int)a_attr_name,
865               NameForAtom (a_attr_name)) ;
866
867    if (!ephyrLocalAtomToHost (a_attr_name, &host_atom)) {
868        EPHYR_LOG_ERROR ("failed to convert local atom to host atom\n") ;
869        res = BadMatch ;
870        goto out ;
871    }
872
873    if (!ephyrHostXVGetPortAttribute (port_priv->port_number,
874                                      host_atom,
875                                      a_attr_value)) {
876        EPHYR_LOG_ERROR ("failed to get port attribute\n") ;
877        res = BadMatch ;
878        goto out ;
879    }
880
881    res = Success ;
882out:
883    EPHYR_LOG ("leave\n") ;
884    return res ;
885}
886
887static void
888ephyrQueryBestSize (KdScreenInfo *a_info,
889                    Bool a_motion,
890                    short a_src_w,
891                    short a_src_h,
892                    short a_drw_w,
893                    short a_drw_h,
894                    unsigned int *a_prefered_w,
895                    unsigned int *a_prefered_h,
896                    pointer a_port_priv)
897{
898    int res=0 ;
899    EphyrPortPriv *port_priv = a_port_priv ;
900
901    EPHYR_RETURN_IF_FAIL (port_priv) ;
902
903    EPHYR_LOG ("enter\n") ;
904    res = ephyrHostXVQueryBestSize (port_priv->port_number,
905                                    a_motion,
906                                    a_src_w, a_src_h,
907                                    a_drw_w, a_drw_h,
908                                    a_prefered_w, a_prefered_h) ;
909    if (!res) {
910        EPHYR_LOG_ERROR ("Failed to query best size\n") ;
911    }
912    EPHYR_LOG ("leave\n") ;
913}
914
915static int
916ephyrPutImage (KdScreenInfo *a_info,
917               DrawablePtr a_drawable,
918               short a_src_x,
919               short a_src_y,
920               short a_drw_x,
921               short a_drw_y,
922               short a_src_w,
923               short a_src_h,
924               short a_drw_w,
925               short a_drw_h,
926               int a_id,
927               unsigned char *a_buf,
928               short a_width,
929               short a_height,
930               Bool a_sync,
931               RegionPtr a_clipping_region,
932               pointer a_port_priv)
933{
934    EphyrPortPriv *port_priv = a_port_priv ;
935    Bool is_ok=FALSE ;
936    int result=BadImplementation, image_size=0 ;
937
938    EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ;
939    EPHYR_RETURN_VAL_IF_FAIL (a_drawable, BadValue) ;
940
941    EPHYR_LOG ("enter\n") ;
942
943    if (!ephyrHostXVPutImage (a_info->pScreen->myNum,
944                              port_priv->port_number,
945                              a_id,
946                              a_drw_x, a_drw_y, a_drw_w, a_drw_h,
947                              a_src_x, a_src_y, a_src_w, a_src_h,
948                              a_width, a_height, a_buf,
949                              (EphyrHostBox*)RegionRects (a_clipping_region),
950                              RegionNumRects (a_clipping_region))) {
951        EPHYR_LOG_ERROR ("EphyrHostXVPutImage() failed\n") ;
952        goto out ;
953    }
954
955    /*
956     * Now save the image so that we can resend it to host it
957     * later, in ReputImage.
958     */
959    if (!ephyrXVPrivGetImageBufSize (port_priv->port_number,
960                                     a_id, a_width, a_height, &image_size)) {
961        EPHYR_LOG_ERROR ("failed to get image size\n") ;
962        /*this is a minor error so we won't get bail out abruptly*/
963        is_ok = FALSE ;
964    } else {
965        is_ok = TRUE ;
966    }
967    if (is_ok) {
968        if (!ephyrXVPrivSaveImageToPortPriv (port_priv, a_buf, image_size)) {
969            is_ok=FALSE ;
970        } else {
971            port_priv->image_id = a_id;
972            port_priv->drw_x = a_drw_x;
973            port_priv->drw_y = a_drw_y;
974            port_priv->drw_w = a_drw_w ;
975            port_priv->drw_h = a_drw_h ;
976            port_priv->src_x = a_src_x;
977            port_priv->src_y = a_src_y ;
978            port_priv->src_w = a_src_w ;
979            port_priv->src_h = a_src_h ;
980            port_priv->image_width = a_width ;
981            port_priv->image_height = a_height ;
982        }
983    }
984    if (!is_ok) {
985        if (port_priv->image_buf) {
986            free (port_priv->image_buf) ;
987            port_priv->image_buf = NULL ;
988            port_priv->image_buf_size = 0 ;
989        }
990    }
991
992    result = Success ;
993
994out:
995    EPHYR_LOG ("leave\n") ;
996    return result ;
997}
998
999static int
1000ephyrReputImage (KdScreenInfo *a_info,
1001                 DrawablePtr a_drawable,
1002                 short a_drw_x,
1003                 short a_drw_y,
1004                 RegionPtr a_clipping_region,
1005                 pointer a_port_priv)
1006{
1007    EphyrPortPriv *port_priv = a_port_priv ;
1008    int result=BadImplementation ;
1009
1010    EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, FALSE) ;
1011    EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ;
1012
1013    EPHYR_LOG ("enter\n") ;
1014
1015    if (!port_priv->image_buf_size || !port_priv->image_buf) {
1016        EPHYR_LOG_ERROR ("has null image buf in cache\n") ;
1017        goto out ;
1018    }
1019    if (!ephyrHostXVPutImage (a_info->pScreen->myNum,
1020                              port_priv->port_number,
1021                              port_priv->image_id,
1022                              a_drw_x, a_drw_y,
1023                              port_priv->drw_w, port_priv->drw_h,
1024                              port_priv->src_x, port_priv->src_y,
1025                              port_priv->src_w, port_priv->src_h,
1026                              port_priv->image_width, port_priv->image_height,
1027                              port_priv->image_buf,
1028                              (EphyrHostBox*)RegionRects (a_clipping_region),
1029                              RegionNumRects (a_clipping_region))) {
1030        EPHYR_LOG_ERROR ("ephyrHostXVPutImage() failed\n") ;
1031        goto out ;
1032    }
1033
1034    result = Success ;
1035
1036out:
1037    EPHYR_LOG ("leave\n") ;
1038    return result ;
1039}
1040
1041static int
1042ephyrPutVideo (KdScreenInfo *a_info,
1043               DrawablePtr a_drawable,
1044               short a_vid_x, short a_vid_y,
1045               short a_drw_x, short a_drw_y,
1046               short a_vid_w, short a_vid_h,
1047               short a_drw_w, short a_drw_h,
1048               RegionPtr a_clipping_region,
1049               pointer a_port_priv)
1050{
1051    EphyrPortPriv *port_priv = a_port_priv ;
1052    BoxRec clipped_area, dst_box ;
1053    int result=BadImplementation ;
1054    int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ;
1055
1056    EPHYR_RETURN_VAL_IF_FAIL (a_info->pScreen, BadValue) ;
1057    EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ;
1058
1059    EPHYR_LOG ("enter\n") ;
1060
1061    dst_box.x1 = a_drw_x ;
1062    dst_box.x2 = a_drw_x + a_drw_w;
1063    dst_box.y1 = a_drw_y ;
1064    dst_box.y2 = a_drw_y + a_drw_h;
1065
1066    if (!DoSimpleClip (&dst_box,
1067                       RegionExtents(a_clipping_region),
1068                       &clipped_area)) {
1069        EPHYR_LOG_ERROR ("failed to simple clip\n") ;
1070        goto out ;
1071    }
1072
1073    drw_x = clipped_area.x1 ;
1074    drw_y = clipped_area.y1 ;
1075    drw_w = clipped_area.x2 - clipped_area.x1 ;
1076    drw_h = clipped_area.y2 - clipped_area.y1 ;
1077
1078    if (!ephyrHostXVPutVideo (a_info->pScreen->myNum,
1079                              port_priv->port_number,
1080                              a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1081                              a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
1082        EPHYR_LOG_ERROR ("ephyrHostXVPutVideo() failed\n") ;
1083        goto out ;
1084    }
1085    result = Success ;
1086
1087out:
1088    EPHYR_LOG ("leave\n") ;
1089    return result ;
1090}
1091
1092static int
1093ephyrGetVideo (KdScreenInfo *a_info,
1094               DrawablePtr a_drawable,
1095               short a_vid_x, short a_vid_y,
1096               short a_drw_x, short a_drw_y,
1097               short a_vid_w, short a_vid_h,
1098               short a_drw_w, short a_drw_h,
1099               RegionPtr a_clipping_region,
1100               pointer a_port_priv)
1101{
1102    EphyrPortPriv *port_priv = a_port_priv ;
1103    BoxRec clipped_area, dst_box ;
1104    int result=BadImplementation ;
1105    int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ;
1106
1107    EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ;
1108    EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ;
1109
1110    EPHYR_LOG ("enter\n") ;
1111
1112    dst_box.x1 = a_drw_x ;
1113    dst_box.x2 = a_drw_x + a_drw_w;
1114    dst_box.y1 = a_drw_y ;
1115    dst_box.y2 = a_drw_y + a_drw_h;
1116
1117    if (!DoSimpleClip (&dst_box,
1118                       RegionExtents(a_clipping_region),
1119                       &clipped_area)) {
1120        EPHYR_LOG_ERROR ("failed to simple clip\n") ;
1121        goto out ;
1122    }
1123
1124    drw_x = clipped_area.x1 ;
1125    drw_y = clipped_area.y1 ;
1126    drw_w = clipped_area.x2 - clipped_area.x1 ;
1127    drw_h = clipped_area.y2 - clipped_area.y1 ;
1128
1129    if (!ephyrHostXVGetVideo (a_info->pScreen->myNum,
1130                              port_priv->port_number,
1131                              a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1132                              a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
1133        EPHYR_LOG_ERROR ("ephyrHostXVGetVideo() failed\n") ;
1134        goto out ;
1135    }
1136    result = Success ;
1137
1138out:
1139    EPHYR_LOG ("leave\n") ;
1140    return result ;
1141}
1142
1143static int
1144ephyrPutStill (KdScreenInfo *a_info,
1145               DrawablePtr a_drawable,
1146               short a_vid_x, short a_vid_y,
1147               short a_drw_x, short a_drw_y,
1148               short a_vid_w, short a_vid_h,
1149               short a_drw_w, short a_drw_h,
1150               RegionPtr a_clipping_region,
1151               pointer a_port_priv)
1152{
1153    EphyrPortPriv *port_priv = a_port_priv ;
1154    BoxRec clipped_area, dst_box ;
1155    int result=BadImplementation ;
1156    int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ;
1157
1158    EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ;
1159    EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ;
1160
1161    EPHYR_LOG ("enter\n") ;
1162
1163    dst_box.x1 = a_drw_x ;
1164    dst_box.x2 = a_drw_x + a_drw_w;
1165    dst_box.y1 = a_drw_y ;
1166    dst_box.y2 = a_drw_y + a_drw_h;
1167
1168    if (!DoSimpleClip (&dst_box,
1169                       RegionExtents(a_clipping_region),
1170                       &clipped_area)) {
1171        EPHYR_LOG_ERROR ("failed to simple clip\n") ;
1172        goto out ;
1173    }
1174
1175    drw_x = clipped_area.x1 ;
1176    drw_y = clipped_area.y1 ;
1177    drw_w = clipped_area.x2 - clipped_area.x1 ;
1178    drw_h = clipped_area.y2 - clipped_area.y1 ;
1179
1180    if (!ephyrHostXVPutStill (a_info->pScreen->myNum,
1181                              port_priv->port_number,
1182                              a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1183                              a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
1184        EPHYR_LOG_ERROR ("ephyrHostXVPutStill() failed\n") ;
1185        goto out ;
1186    }
1187    result = Success ;
1188
1189out:
1190    EPHYR_LOG ("leave\n") ;
1191    return result ;
1192}
1193
1194static int
1195ephyrGetStill (KdScreenInfo *a_info,
1196               DrawablePtr a_drawable,
1197               short a_vid_x, short a_vid_y,
1198               short a_drw_x, short a_drw_y,
1199               short a_vid_w, short a_vid_h,
1200               short a_drw_w, short a_drw_h,
1201               RegionPtr a_clipping_region,
1202               pointer a_port_priv)
1203{
1204    EphyrPortPriv *port_priv = a_port_priv ;
1205    BoxRec clipped_area, dst_box ;
1206    int result=BadImplementation ;
1207    int drw_x=0, drw_y=0, drw_w=0, drw_h=0 ;
1208
1209    EPHYR_RETURN_VAL_IF_FAIL (a_info && a_info->pScreen, BadValue) ;
1210    EPHYR_RETURN_VAL_IF_FAIL (a_drawable && port_priv, BadValue) ;
1211
1212    EPHYR_LOG ("enter\n") ;
1213
1214    dst_box.x1 = a_drw_x ;
1215    dst_box.x2 = a_drw_x + a_drw_w;
1216    dst_box.y1 = a_drw_y ;
1217    dst_box.y2 = a_drw_y + a_drw_h;
1218
1219    if (!DoSimpleClip (&dst_box,
1220                       RegionExtents(a_clipping_region),
1221                       &clipped_area)) {
1222        EPHYR_LOG_ERROR ("failed to simple clip\n") ;
1223        goto out ;
1224    }
1225
1226    drw_x = clipped_area.x1 ;
1227    drw_y = clipped_area.y1 ;
1228    drw_w = clipped_area.x2 - clipped_area.x1 ;
1229    drw_h = clipped_area.y2 - clipped_area.y1 ;
1230
1231    if (!ephyrHostXVGetStill (a_info->pScreen->myNum,
1232                              port_priv->port_number,
1233                              a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1234                              a_drw_x, a_drw_y, a_drw_w, a_drw_h)) {
1235        EPHYR_LOG_ERROR ("ephyrHostXVGetStill() failed\n") ;
1236        goto out ;
1237    }
1238    result = Success ;
1239
1240out:
1241    EPHYR_LOG ("leave\n") ;
1242    return result ;
1243}
1244
1245static int
1246ephyrQueryImageAttributes (KdScreenInfo *a_info,
1247                           int a_id,
1248                           unsigned short *a_w,
1249                           unsigned short *a_h,
1250                           int *a_pitches,
1251                           int *a_offsets)
1252{
1253    int image_size=0 ;
1254
1255    EPHYR_RETURN_VAL_IF_FAIL (a_w && a_h, FALSE) ;
1256
1257    EPHYR_LOG ("enter: dim (%dx%d), pitches: %p, offsets: %p\n",
1258               *a_w, *a_h, a_pitches, a_offsets) ;
1259
1260   if (!ephyrHostXVQueryImageAttributes (s_base_port_id,
1261                                         a_id,
1262                                         a_w, a_h,
1263                                         &image_size,
1264                                         a_pitches, a_offsets)) {
1265       EPHYR_LOG_ERROR ("EphyrHostXVQueryImageAttributes() failed\n") ;
1266       goto out ;
1267   }
1268   EPHYR_LOG ("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h) ;
1269
1270out:
1271    EPHYR_LOG ("leave\n") ;
1272    return image_size ;
1273}
1274