2 * Xephyr - A kdrive X server thats runs in a host X window.
3 * Authored by Matthew Allum <mallum@openedhand.com>
5 * Copyright © 2007 OpenedHand Ltd
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.
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.
26 * Dodji Seketeli <dodji@openedhand.com>
30 #include <kdrive-config.h>
33 #include <X11/extensions/Xv.h>
35 #include <xcb/xcb_aux.h>
44 xcb_xv_query_adaptors_reply_t
*host_adaptors
;
45 KdVideoAdaptorPtr adaptors
;
48 typedef struct _EphyrXVPriv EphyrXVPriv
;
50 struct _EphyrPortPriv
{
52 KdVideoAdaptorPtr current_adaptor
;
54 unsigned char *image_buf
;
57 int drw_x
, drw_y
, drw_w
, drw_h
;
58 int src_x
, src_y
, src_w
, src_h
;
59 int image_width
, image_height
;
61 typedef struct _EphyrPortPriv EphyrPortPriv
;
63 static Bool
ephyrLocalAtomToHost(int a_local_atom
, int *a_host_atom
);
65 static EphyrXVPriv
*ephyrXVPrivNew(void);
66 static void ephyrXVPrivDelete(EphyrXVPriv
* a_this
);
67 static Bool
ephyrXVPrivQueryHostAdaptors(EphyrXVPriv
* a_this
);
68 static Bool
ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv
* a_this
);
69 static Bool
ephyrXVPrivRegisterAdaptors(EphyrXVPriv
* a_this
,
72 static Bool
ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs
,
74 const char *a_attr_name
,
75 int a_attr_value
, Bool
*a_is_valid
);
77 static Bool
ephyrXVPrivGetImageBufSize(int a_port_id
,
79 unsigned short a_width
,
80 unsigned short a_height
, int *a_size
);
82 static Bool
ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv
* a_port_priv
,
83 const unsigned char *a_image
,
86 static void ephyrStopVideo(KdScreenInfo
* a_info
,
87 pointer a_xv_priv
, Bool a_exit
);
89 static int ephyrSetPortAttribute(KdScreenInfo
* a_info
,
91 int a_attr_value
, pointer a_port_priv
);
93 static int ephyrGetPortAttribute(KdScreenInfo
* a_screen_info
,
95 int *a_attr_value
, pointer a_port_priv
);
97 static void ephyrQueryBestSize(KdScreenInfo
* a_info
,
103 unsigned int *a_prefered_w
,
104 unsigned int *a_prefered_h
, pointer a_port_priv
);
106 static int ephyrPutImage(KdScreenInfo
* a_info
,
107 DrawablePtr a_drawable
,
117 unsigned char *a_buf
,
121 RegionPtr a_clipping_region
, pointer a_port_priv
);
123 static int ephyrReputImage(KdScreenInfo
* a_info
,
124 DrawablePtr a_drawable
,
127 RegionPtr a_clipping_region
, pointer a_port_priv
);
129 static int ephyrPutVideo(KdScreenInfo
* a_info
,
130 DrawablePtr a_drawable
,
131 short a_vid_x
, short a_vid_y
,
132 short a_drw_x
, short a_drw_y
,
133 short a_vid_w
, short a_vid_h
,
134 short a_drw_w
, short a_drw_h
,
135 RegionPtr a_clip_region
, pointer a_port_priv
);
137 static int ephyrGetVideo(KdScreenInfo
* a_info
,
138 DrawablePtr a_drawable
,
139 short a_vid_x
, short a_vid_y
,
140 short a_drw_x
, short a_drw_y
,
141 short a_vid_w
, short a_vid_h
,
142 short a_drw_w
, short a_drw_h
,
143 RegionPtr a_clip_region
, pointer a_port_priv
);
145 static int ephyrPutStill(KdScreenInfo
* a_info
,
146 DrawablePtr a_drawable
,
147 short a_vid_x
, short a_vid_y
,
148 short a_drw_x
, short a_drw_y
,
149 short a_vid_w
, short a_vid_h
,
150 short a_drw_w
, short a_drw_h
,
151 RegionPtr a_clip_region
, pointer a_port_priv
);
153 static int ephyrGetStill(KdScreenInfo
* a_info
,
154 DrawablePtr a_drawable
,
155 short a_vid_x
, short a_vid_y
,
156 short a_drw_x
, short a_drw_y
,
157 short a_vid_w
, short a_vid_h
,
158 short a_drw_w
, short a_drw_h
,
159 RegionPtr a_clip_region
, pointer a_port_priv
);
161 static int ephyrQueryImageAttributes(KdScreenInfo
* a_info
,
165 int *a_pitches
, int *a_offsets
);
166 static int s_base_port_id
;
173 adaptor_has_flags(const xcb_xv_adaptor_info_t
*adaptor
, uint32_t flags
)
175 return (adaptor
->type
& flags
) == flags
;
179 ephyrLocalAtomToHost(int a_local_atom
, int *a_host_atom
)
181 xcb_connection_t
*conn
= hostx_get_xcbconn();
182 xcb_intern_atom_cookie_t cookie
;
183 xcb_intern_atom_reply_t
*reply
;
184 const char *atom_name
= NULL
;
186 EPHYR_RETURN_VAL_IF_FAIL(a_host_atom
, FALSE
);
188 if (!ValidAtom(a_local_atom
))
191 atom_name
= NameForAtom(a_local_atom
);
196 cookie
= xcb_intern_atom(conn
, FALSE
, strlen(atom_name
), atom_name
);
197 reply
= xcb_intern_atom_reply(conn
, cookie
, NULL
);
198 if (!reply
|| reply
->atom
== None
) {
199 EPHYR_LOG_ERROR("no atom for string %s defined in host X\n", atom_name
);
203 *a_host_atom
= reply
->atom
;
214 ephyrInitVideo(ScreenPtr pScreen
)
218 KdScreenPriv(pScreen
);
219 KdScreenInfo
*screen
= pScreenPriv
->screen
;
220 static EphyrXVPriv
*xv_priv
;
222 EPHYR_LOG("enter\n");
224 if (screen
->fb
.bitsPerPixel
== 8) {
225 EPHYR_LOG_ERROR("8 bits depth not supported\n");
230 xv_priv
= ephyrXVPrivNew();
233 EPHYR_LOG_ERROR("failed to create xv_priv\n");
237 if (!ephyrXVPrivRegisterAdaptors(xv_priv
, pScreen
)) {
238 EPHYR_LOG_ERROR("failed to register adaptors\n");
250 EphyrXVPriv
*xv_priv
= NULL
;
252 EPHYR_LOG("enter\n");
254 xv_priv
= calloc(1, sizeof(EphyrXVPriv
));
256 EPHYR_LOG_ERROR("failed to create EphyrXVPriv\n");
260 if (!ephyrXVPrivQueryHostAdaptors(xv_priv
)) {
261 EPHYR_LOG_ERROR("failed to query the host x for xv properties\n");
264 if (!ephyrXVPrivSetAdaptorsHooks(xv_priv
)) {
265 EPHYR_LOG_ERROR("failed to set xv_priv hooks\n");
269 EPHYR_LOG("leave\n");
274 ephyrXVPrivDelete(xv_priv
);
281 ephyrXVPrivDelete(EphyrXVPriv
* a_this
)
283 EPHYR_LOG("enter\n");
287 if (a_this
->host_adaptors
) {
288 free(a_this
->host_adaptors
);
289 a_this
->host_adaptors
= NULL
;
291 free(a_this
->adaptors
);
292 a_this
->adaptors
= NULL
;
294 EPHYR_LOG("leave\n");
298 translate_video_encodings(KdVideoAdaptorPtr adaptor
,
299 xcb_xv_adaptor_info_t
*host_adaptor
)
301 xcb_connection_t
*conn
= hostx_get_xcbconn();
303 xcb_xv_query_encodings_cookie_t cookie
;
304 xcb_xv_query_encodings_reply_t
*reply
;
305 xcb_xv_encoding_info_iterator_t encoding_it
;
307 cookie
= xcb_xv_query_encodings(conn
, host_adaptor
->base_id
);
308 reply
= xcb_xv_query_encodings_reply(conn
, cookie
, NULL
);
312 adaptor
->nEncodings
= reply
->num_encodings
;
313 adaptor
->pEncodings
= calloc(adaptor
->nEncodings
,
314 sizeof(*adaptor
->pEncodings
));
315 if (!adaptor
->pEncodings
) {
320 encoding_it
= xcb_xv_query_encodings_info_iterator(reply
);
321 for (i
= 0; i
< adaptor
->nEncodings
; i
++) {
322 xcb_xv_encoding_info_t
*encoding_info
= encoding_it
.data
;
323 KdVideoEncodingPtr encoding
= &adaptor
->pEncodings
[i
];
325 encoding
->id
= encoding_info
->encoding
;
326 encoding
->name
= strndup(xcb_xv_encoding_info_name(encoding_info
),
327 encoding_info
->name_size
);
328 encoding
->width
= encoding_info
->width
;
329 encoding
->height
= encoding_info
->height
;
330 encoding
->rate
.numerator
= encoding_info
->rate
.numerator
;
331 encoding
->rate
.denominator
= encoding_info
->rate
.denominator
;
333 xcb_xv_encoding_info_next(&encoding_it
);
341 translate_xv_attributes(KdVideoAdaptorPtr adaptor
,
342 xcb_xv_adaptor_info_t
*host_adaptor
)
344 xcb_connection_t
*conn
= hostx_get_xcbconn();
346 xcb_xv_attribute_info_iterator_t it
;
347 xcb_xv_query_port_attributes_cookie_t cookie
=
348 xcb_xv_query_port_attributes(conn
, host_adaptor
->base_id
);
349 xcb_xv_query_port_attributes_reply_t
*reply
=
350 xcb_xv_query_port_attributes_reply(conn
, cookie
, NULL
);
355 adaptor
->nAttributes
= reply
->num_attributes
;
356 adaptor
->pAttributes
= calloc(reply
->num_attributes
,
357 sizeof(*adaptor
->pAttributes
));
358 if (!adaptor
->pAttributes
) {
359 EPHYR_LOG_ERROR("failed to allocate attributes\n");
364 it
= xcb_xv_query_port_attributes_attributes_iterator(reply
);
365 for (i
= 0; i
< reply
->num_attributes
; i
++) {
366 KdAttributePtr attribute
= &adaptor
->pAttributes
[i
];
368 attribute
->flags
= it
.data
->flags
;
369 attribute
->min_value
= it
.data
->min
;
370 attribute
->max_value
= it
.data
->max
;
371 attribute
->name
= strndup(xcb_xv_attribute_info_name(it
.data
),
374 /* make sure atoms of attrs names are created in xephyr */
375 MakeAtom(xcb_xv_attribute_info_name(it
.data
), it
.data
->size
, TRUE
);
377 xcb_xv_attribute_info_next(&it
);
385 translate_xv_image_formats(KdVideoAdaptorPtr adaptor
,
386 xcb_xv_adaptor_info_t
*host_adaptor
)
388 xcb_connection_t
*conn
= hostx_get_xcbconn();
390 xcb_xv_list_image_formats_cookie_t cookie
=
391 xcb_xv_list_image_formats(conn
, host_adaptor
->base_id
);
392 xcb_xv_list_image_formats_reply_t
*reply
=
393 xcb_xv_list_image_formats_reply(conn
, cookie
, NULL
);
394 xcb_xv_image_format_info_t
*formats
;
399 adaptor
->nImages
= reply
->num_formats
;
400 adaptor
->pImages
= calloc(reply
->num_formats
, sizeof(KdImageRec
));
401 if (!adaptor
->pImages
) {
406 formats
= xcb_xv_list_image_formats_format(reply
);
407 for (i
= 0; i
< reply
->num_formats
; i
++) {
408 KdImagePtr image
= &adaptor
->pImages
[i
];
410 image
->id
= formats
[i
].id
;
411 image
->type
= formats
[i
].type
;
412 image
->byte_order
= formats
[i
].byte_order
;
413 memcpy(image
->guid
, formats
[i
].guid
, 16);
414 image
->bits_per_pixel
= formats
[i
].bpp
;
415 image
->format
= formats
[i
].format
;
416 image
->num_planes
= formats
[i
].num_planes
;
417 image
->depth
= formats
[i
].depth
;
418 image
->red_mask
= formats
[i
].red_mask
;
419 image
->green_mask
= formats
[i
].green_mask
;
420 image
->blue_mask
= formats
[i
].blue_mask
;
421 image
->y_sample_bits
= formats
[i
].y_sample_bits
;
422 image
->u_sample_bits
= formats
[i
].u_sample_bits
;
423 image
->v_sample_bits
= formats
[i
].v_sample_bits
;
424 image
->horz_y_period
= formats
[i
].vhorz_y_period
;
425 image
->horz_u_period
= formats
[i
].vhorz_u_period
;
426 image
->horz_v_period
= formats
[i
].vhorz_v_period
;
427 image
->vert_y_period
= formats
[i
].vvert_y_period
;
428 image
->vert_u_period
= formats
[i
].vvert_u_period
;
429 image
->vert_v_period
= formats
[i
].vvert_v_period
;
430 memcpy(image
->component_order
, formats
[i
].vcomp_order
, 32);
431 image
->scanline_order
= formats
[i
].vscanline_order
;
439 ephyrXVPrivQueryHostAdaptors(EphyrXVPriv
* a_this
)
441 xcb_connection_t
*conn
= hostx_get_xcbconn();
442 xcb_screen_t
*xscreen
= xcb_aux_get_screen(conn
, hostx_get_screen());
443 int base_port_id
= 0, i
= 0, port_priv_offset
= 0;
445 xcb_generic_error_t
*e
= NULL
;
446 xcb_xv_adaptor_info_iterator_t it
;
448 EPHYR_RETURN_VAL_IF_FAIL(a_this
, FALSE
);
450 EPHYR_LOG("enter\n");
453 xcb_xv_query_adaptors_cookie_t cookie
=
454 xcb_xv_query_adaptors(conn
, xscreen
->root
);
455 a_this
->host_adaptors
= xcb_xv_query_adaptors_reply(conn
, cookie
, &e
);
458 EPHYR_LOG_ERROR("failed to query host adaptors\n");
463 if (a_this
->host_adaptors
)
464 a_this
->num_adaptors
= a_this
->host_adaptors
->num_adaptors
;
465 if (a_this
->num_adaptors
< 0) {
466 EPHYR_LOG_ERROR("failed to get number of host adaptors\n");
469 EPHYR_LOG("host has %d adaptors\n", a_this
->num_adaptors
);
471 * copy what we can from adaptors into a_this->adaptors
473 if (a_this
->num_adaptors
) {
474 a_this
->adaptors
= calloc(a_this
->num_adaptors
,
475 sizeof(KdVideoAdaptorRec
));
476 if (!a_this
->adaptors
) {
477 EPHYR_LOG_ERROR("failed to create internal adaptors\n");
482 it
= xcb_xv_query_adaptors_info_iterator(a_this
->host_adaptors
);
483 for (i
= 0; i
< a_this
->num_adaptors
; i
++) {
484 xcb_xv_adaptor_info_t
*cur_host_adaptor
= it
.data
;
485 xcb_xv_format_t
*format
= xcb_xv_adaptor_info_formats(cur_host_adaptor
);
488 a_this
->adaptors
[i
].nPorts
= cur_host_adaptor
->num_ports
;
489 if (a_this
->adaptors
[i
].nPorts
<= 0) {
490 EPHYR_LOG_ERROR("Could not find any port of adaptor %d\n", i
);
493 a_this
->adaptors
[i
].type
= cur_host_adaptor
->type
;
494 a_this
->adaptors
[i
].type
|= XvWindowMask
;
495 a_this
->adaptors
[i
].flags
=
496 VIDEO_OVERLAID_IMAGES
| VIDEO_CLIP_TO_VIEWPORT
;
497 a_this
->adaptors
[i
].name
=
498 strndup(xcb_xv_adaptor_info_name(cur_host_adaptor
),
499 cur_host_adaptor
->name_size
);
500 if (!a_this
->adaptors
[i
].name
)
501 a_this
->adaptors
[i
].name
= strdup("Xephyr Video Overlay");
502 base_port_id
= cur_host_adaptor
->base_id
;
503 if (base_port_id
< 0) {
504 EPHYR_LOG_ERROR("failed to get port id for adaptor %d\n", i
);
508 s_base_port_id
= base_port_id
;
510 if (!translate_video_encodings(&a_this
->adaptors
[i
],
512 EPHYR_LOG_ERROR("failed to get encodings for port port id %d,"
513 " adaptors %d\n", base_port_id
, i
);
517 a_this
->adaptors
[i
].nFormats
= cur_host_adaptor
->num_formats
;
518 a_this
->adaptors
[i
].pFormats
=
519 calloc(cur_host_adaptor
->num_formats
,
520 sizeof(*a_this
->adaptors
[i
].pFormats
));
521 for (j
= 0; j
< cur_host_adaptor
->num_formats
; j
++) {
522 xcb_visualtype_t
*visual
=
523 xcb_aux_find_visual_by_id(xscreen
, format
[j
].visual
);
524 a_this
->adaptors
[i
].pFormats
[j
].depth
= format
[j
].depth
;
525 a_this
->adaptors
[i
].pFormats
[j
].class = visual
->_class
;
528 a_this
->adaptors
[i
].pPortPrivates
=
529 calloc(a_this
->adaptors
[i
].nPorts
,
530 sizeof(DevUnion
) + sizeof(EphyrPortPriv
));
531 port_priv_offset
= a_this
->adaptors
[i
].nPorts
;
532 for (j
= 0; j
< a_this
->adaptors
[i
].nPorts
; j
++) {
533 EphyrPortPriv
*port_privs_base
=
534 (EphyrPortPriv
*) &a_this
->adaptors
[i
].
535 pPortPrivates
[port_priv_offset
];
536 EphyrPortPriv
*port_priv
= &port_privs_base
[j
];
538 port_priv
->port_number
= base_port_id
+ j
;
539 port_priv
->current_adaptor
= &a_this
->adaptors
[i
];
540 port_priv
->xv_priv
= a_this
;
541 a_this
->adaptors
[i
].pPortPrivates
[j
].ptr
= port_priv
;
544 if (!translate_xv_attributes(&a_this
->adaptors
[i
], cur_host_adaptor
)) {
546 EPHYR_LOG_ERROR("failed to get port attribute "
547 "for adaptor %d\n", i
);
552 if (!translate_xv_image_formats(&a_this
->adaptors
[i
], cur_host_adaptor
)) {
553 EPHYR_LOG_ERROR("failed to get image formats "
554 "for adaptor %d\n", i
);
558 xcb_xv_adaptor_info_next(&it
);
563 EPHYR_LOG("leave\n");
568 ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv
* a_this
)
571 xcb_xv_adaptor_info_iterator_t it
;
573 EPHYR_RETURN_VAL_IF_FAIL(a_this
, FALSE
);
575 EPHYR_LOG("enter\n");
577 it
= xcb_xv_query_adaptors_info_iterator(a_this
->host_adaptors
);
578 for (i
= 0; i
< a_this
->num_adaptors
; i
++) {
579 xcb_xv_adaptor_info_t
*cur_host_adaptor
= it
.data
;
581 a_this
->adaptors
[i
].ReputImage
= ephyrReputImage
;
582 a_this
->adaptors
[i
].StopVideo
= ephyrStopVideo
;
583 a_this
->adaptors
[i
].SetPortAttribute
= ephyrSetPortAttribute
;
584 a_this
->adaptors
[i
].GetPortAttribute
= ephyrGetPortAttribute
;
585 a_this
->adaptors
[i
].QueryBestSize
= ephyrQueryBestSize
;
586 a_this
->adaptors
[i
].QueryImageAttributes
= ephyrQueryImageAttributes
;
588 if (adaptor_has_flags(cur_host_adaptor
,
589 XCB_XV_TYPE_IMAGE_MASK
| XCB_XV_TYPE_INPUT_MASK
))
590 a_this
->adaptors
[i
].PutImage
= ephyrPutImage
;
592 if (adaptor_has_flags(cur_host_adaptor
,
593 XCB_XV_TYPE_VIDEO_MASK
| XCB_XV_TYPE_INPUT_MASK
))
594 a_this
->adaptors
[i
].PutVideo
= ephyrPutVideo
;
596 if (adaptor_has_flags(cur_host_adaptor
,
597 XCB_XV_TYPE_VIDEO_MASK
| XCB_XV_TYPE_OUTPUT_MASK
))
598 a_this
->adaptors
[i
].GetVideo
= ephyrGetVideo
;
600 if (adaptor_has_flags(cur_host_adaptor
,
601 XCB_XV_TYPE_STILL_MASK
| XCB_XV_TYPE_INPUT_MASK
))
602 a_this
->adaptors
[i
].PutStill
= ephyrPutStill
;
604 if (adaptor_has_flags(cur_host_adaptor
,
605 XCB_XV_TYPE_STILL_MASK
| XCB_XV_TYPE_OUTPUT_MASK
))
606 a_this
->adaptors
[i
].GetStill
= ephyrGetStill
;
608 EPHYR_LOG("leave\n");
613 ephyrXVPrivRegisterAdaptors(EphyrXVPriv
* a_this
, ScreenPtr a_screen
)
615 KdScreenPriv(a_screen
);
616 KdScreenInfo
*screen
= pScreenPriv
->screen
;
618 KdVideoAdaptorPtr
*adaptors
= NULL
, *registered_adaptors
= NULL
;
619 int num_registered_adaptors
= 0, i
= 0, num_adaptors
= 0;
621 EPHYR_RETURN_VAL_IF_FAIL(a_this
&& a_screen
, FALSE
);
623 EPHYR_LOG("enter\n");
625 if (!a_this
->num_adaptors
)
627 num_registered_adaptors
=
628 KdXVListGenericAdaptors(screen
, ®istered_adaptors
);
630 num_adaptors
= num_registered_adaptors
+ a_this
->num_adaptors
;
631 adaptors
= calloc(num_adaptors
, sizeof(KdVideoAdaptorPtr
));
633 EPHYR_LOG_ERROR("failed to allocate adaptors tab\n");
636 memmove(adaptors
, registered_adaptors
, num_registered_adaptors
);
637 for (i
= 0; i
< a_this
->num_adaptors
; i
++) {
638 *(adaptors
+ num_registered_adaptors
+ i
) = &a_this
->adaptors
[i
];
640 if (!KdXVScreenInit(a_screen
, adaptors
, num_adaptors
)) {
641 EPHYR_LOG_ERROR("failed to register adaptors\n");
644 EPHYR_LOG("there are %d registered adaptors\n", num_adaptors
);
648 free(registered_adaptors
);
649 registered_adaptors
= NULL
;
653 EPHYR_LOG("leave\n");
658 ephyrXVPrivIsAttrValueValid(KdAttributePtr a_attrs
,
660 const char *a_attr_name
,
661 int a_attr_value
, Bool
*a_is_valid
)
665 EPHYR_RETURN_VAL_IF_FAIL(a_attrs
&& a_attr_name
&& a_is_valid
, FALSE
);
667 for (i
= 0; i
< a_attrs_len
; i
++) {
668 if (a_attrs
[i
].name
&& strcmp(a_attrs
[i
].name
, a_attr_name
))
670 if (a_attrs
[i
].min_value
> a_attr_value
||
671 a_attrs
[i
].max_value
< a_attr_value
) {
673 EPHYR_LOG_ERROR("attribute was not valid\n"
674 "value:%d. min:%d. max:%d\n",
676 a_attrs
[i
].min_value
, a_attrs
[i
].max_value
);
687 ephyrXVPrivGetImageBufSize(int a_port_id
,
689 unsigned short a_width
,
690 unsigned short a_height
, int *a_size
)
692 xcb_connection_t
*conn
= hostx_get_xcbconn();
693 xcb_xv_query_image_attributes_cookie_t cookie
;
694 xcb_xv_query_image_attributes_reply_t
*reply
;
697 EPHYR_RETURN_VAL_IF_FAIL(a_size
, FALSE
);
699 EPHYR_LOG("enter\n");
701 cookie
= xcb_xv_query_image_attributes(conn
,
702 a_port_id
, a_image_id
,
704 reply
= xcb_xv_query_image_attributes_reply(conn
, cookie
, NULL
);
708 *a_size
= reply
->data_size
;
714 EPHYR_LOG("leave\n");
719 ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv
* a_port_priv
,
720 const unsigned char *a_image_buf
,
725 EPHYR_LOG("enter\n");
727 if (a_port_priv
->image_buf_size
< a_image_len
) {
728 unsigned char *buf
= NULL
;
730 buf
= realloc(a_port_priv
->image_buf
, a_image_len
);
732 EPHYR_LOG_ERROR("failed to realloc image buffer\n");
735 a_port_priv
->image_buf
= buf
;
736 a_port_priv
->image_buf_size
= a_image_len
;
738 memmove(a_port_priv
->image_buf
, a_image_buf
, a_image_len
);
743 EPHYR_LOG("leave\n");
747 ephyrStopVideo(KdScreenInfo
* a_info
, pointer a_port_priv
, Bool a_exit
)
749 xcb_connection_t
*conn
= hostx_get_xcbconn();
750 EphyrPortPriv
*port_priv
= a_port_priv
;
751 EphyrScrPriv
*scrpriv
= a_info
->driver
;
753 EPHYR_RETURN_IF_FAIL(port_priv
);
755 EPHYR_LOG("enter\n");
756 xcb_xv_stop_video(conn
, port_priv
->port_number
, scrpriv
->win
);
757 EPHYR_LOG("leave\n");
761 ephyrSetPortAttribute(KdScreenInfo
* a_info
,
762 Atom a_attr_name
, int a_attr_value
, pointer a_port_priv
)
764 xcb_connection_t
*conn
= hostx_get_xcbconn();
765 int res
= Success
, host_atom
= 0;
766 EphyrPortPriv
*port_priv
= a_port_priv
;
767 Bool is_attr_valid
= FALSE
;
769 EPHYR_RETURN_VAL_IF_FAIL(port_priv
, BadMatch
);
770 EPHYR_RETURN_VAL_IF_FAIL(port_priv
->current_adaptor
, BadMatch
);
771 EPHYR_RETURN_VAL_IF_FAIL(port_priv
->current_adaptor
->pAttributes
, BadMatch
);
772 EPHYR_RETURN_VAL_IF_FAIL(port_priv
->current_adaptor
->nAttributes
, BadMatch
);
773 EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name
), BadMatch
);
775 EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n",
776 port_priv
->port_number
,
777 (int) a_attr_name
, NameForAtom(a_attr_name
), a_attr_value
);
779 if (!ephyrLocalAtomToHost(a_attr_name
, &host_atom
)) {
780 EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
785 if (!ephyrXVPrivIsAttrValueValid(port_priv
->current_adaptor
->pAttributes
,
786 port_priv
->current_adaptor
->nAttributes
,
787 NameForAtom(a_attr_name
),
788 a_attr_value
, &is_attr_valid
)) {
789 EPHYR_LOG_ERROR("failed to validate attribute %s\n",
790 NameForAtom(a_attr_name
));
796 if (!is_attr_valid
) {
797 EPHYR_LOG_ERROR("attribute %s is not valid\n",
798 NameForAtom(a_attr_name
));
805 xcb_xv_set_port_attribute(conn
, port_priv
->port_number
,
806 host_atom
, a_attr_value
);
811 EPHYR_LOG("leave\n");
816 ephyrGetPortAttribute(KdScreenInfo
* a_screen_info
,
817 Atom a_attr_name
, int *a_attr_value
, pointer a_port_priv
)
819 xcb_connection_t
*conn
= hostx_get_xcbconn();
820 int res
= Success
, host_atom
= 0;
821 EphyrPortPriv
*port_priv
= a_port_priv
;
822 xcb_generic_error_t
*e
;
823 xcb_xv_get_port_attribute_cookie_t cookie
;
824 xcb_xv_get_port_attribute_reply_t
*reply
;
826 EPHYR_RETURN_VAL_IF_FAIL(port_priv
, BadMatch
);
827 EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name
), BadMatch
);
829 EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s\n",
830 port_priv
->port_number
,
831 (int) a_attr_name
, NameForAtom(a_attr_name
));
833 if (!ephyrLocalAtomToHost(a_attr_name
, &host_atom
)) {
834 EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
839 cookie
= xcb_xv_get_port_attribute(conn
, port_priv
->port_number
, host_atom
);
840 reply
= xcb_xv_get_port_attribute_reply(conn
, cookie
, &e
);
842 EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", e
->error_code
);
847 *a_attr_value
= reply
->value
;
853 EPHYR_LOG("leave\n");
858 ephyrQueryBestSize(KdScreenInfo
* a_info
,
864 unsigned int *a_prefered_w
,
865 unsigned int *a_prefered_h
, pointer a_port_priv
)
867 xcb_connection_t
*conn
= hostx_get_xcbconn();
868 EphyrPortPriv
*port_priv
= a_port_priv
;
869 xcb_xv_query_best_size_cookie_t cookie
=
870 xcb_xv_query_best_size(conn
,
871 port_priv
->port_number
,
875 xcb_xv_query_best_size_reply_t
*reply
=
876 xcb_xv_query_best_size_reply(conn
, cookie
, NULL
);
878 EPHYR_LOG("enter: frame (%dx%d), drw (%dx%d)\n",
879 a_src_w
, a_src_h
, a_drw_w
, a_drw_h
);
882 EPHYR_LOG_ERROR ("XvQueryBestSize() failed\n");
885 *a_prefered_w
= reply
->actual_width
;
886 *a_prefered_h
= reply
->actual_height
;
887 EPHYR_LOG("actual (%dx%d)\n", *a_prefered_w
, *a_prefered_h
);
890 EPHYR_LOG("leave\n");
895 ephyrHostXVPutImage(KdScreenInfo
* a_info
,
896 EphyrPortPriv
*port_priv
,
908 unsigned char *a_buf
,
909 BoxPtr a_clip_rects
, int a_clip_rect_nums
)
911 EphyrScrPriv
*scrpriv
= a_info
->driver
;
912 xcb_connection_t
*conn
= hostx_get_xcbconn();
915 xcb_rectangle_t
*rects
= NULL
;
916 int data_len
, width
, height
;
917 xcb_xv_query_image_attributes_cookie_t image_attr_cookie
;
918 xcb_xv_query_image_attributes_reply_t
*image_attr_reply
;
920 EPHYR_RETURN_VAL_IF_FAIL(a_buf
, FALSE
);
922 EPHYR_LOG("enter, num_clip_rects: %d\n", a_clip_rect_nums
);
924 image_attr_cookie
= xcb_xv_query_image_attributes(conn
,
925 port_priv
->port_number
,
929 image_attr_reply
= xcb_xv_query_image_attributes_reply(conn
,
932 if (!image_attr_reply
)
934 data_len
= image_attr_reply
->data_size
;
935 width
= image_attr_reply
->width
;
936 height
= image_attr_reply
->height
;
937 free(image_attr_reply
);
939 gc
= xcb_generate_id(conn
);
940 xcb_create_gc(conn
, gc
, scrpriv
->win
, 0, NULL
);
942 if (a_clip_rect_nums
) {
944 rects
= calloc(a_clip_rect_nums
, sizeof(xcb_rectangle_t
));
945 for (i
=0; i
< a_clip_rect_nums
; i
++) {
946 rects
[i
].x
= a_clip_rects
[i
].x1
;
947 rects
[i
].y
= a_clip_rects
[i
].y1
;
948 rects
[i
].width
= a_clip_rects
[i
].x2
- a_clip_rects
[i
].x1
;
949 rects
[i
].height
= a_clip_rects
[i
].y2
- a_clip_rects
[i
].y1
;
950 EPHYR_LOG("(x,y,w,h): (%d,%d,%d,%d)\n",
951 rects
[i
].x
, rects
[i
].y
, rects
[i
].width
, rects
[i
].height
);
953 xcb_set_clip_rectangles(conn
,
954 XCB_CLIP_ORDERING_YX_BANDED
,
962 xcb_xv_put_image(conn
,
963 port_priv
->port_number
,
967 a_src_x
, a_src_y
, a_src_w
, a_src_h
,
968 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
,
971 xcb_free_gc(conn
, gc
);
976 EPHYR_LOG("leave\n");
981 ephyrPutImage(KdScreenInfo
* a_info
,
982 DrawablePtr a_drawable
,
992 unsigned char *a_buf
,
995 Bool a_sync
, RegionPtr a_clipping_region
, pointer a_port_priv
)
997 EphyrPortPriv
*port_priv
= a_port_priv
;
999 int result
= BadImplementation
, image_size
= 0;
1001 EPHYR_RETURN_VAL_IF_FAIL(a_info
&& a_info
->pScreen
, BadValue
);
1002 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
, BadValue
);
1004 EPHYR_LOG("enter\n");
1006 if (!ephyrHostXVPutImage(a_info
, port_priv
,
1008 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
,
1009 a_src_x
, a_src_y
, a_src_w
, a_src_h
,
1010 a_width
, a_height
, a_buf
,
1011 RegionRects(a_clipping_region
),
1012 RegionNumRects(a_clipping_region
))) {
1013 EPHYR_LOG_ERROR("EphyrHostXVPutImage() failed\n");
1018 * Now save the image so that we can resend it to host it
1019 * later, in ReputImage.
1021 if (!ephyrXVPrivGetImageBufSize(port_priv
->port_number
,
1022 a_id
, a_width
, a_height
, &image_size
)) {
1023 EPHYR_LOG_ERROR("failed to get image size\n");
1024 /*this is a minor error so we won't get bail out abruptly */
1031 if (!ephyrXVPrivSaveImageToPortPriv(port_priv
, a_buf
, image_size
)) {
1035 port_priv
->image_id
= a_id
;
1036 port_priv
->drw_x
= a_drw_x
;
1037 port_priv
->drw_y
= a_drw_y
;
1038 port_priv
->drw_w
= a_drw_w
;
1039 port_priv
->drw_h
= a_drw_h
;
1040 port_priv
->src_x
= a_src_x
;
1041 port_priv
->src_y
= a_src_y
;
1042 port_priv
->src_w
= a_src_w
;
1043 port_priv
->src_h
= a_src_h
;
1044 port_priv
->image_width
= a_width
;
1045 port_priv
->image_height
= a_height
;
1049 if (port_priv
->image_buf
) {
1050 free(port_priv
->image_buf
);
1051 port_priv
->image_buf
= NULL
;
1052 port_priv
->image_buf_size
= 0;
1059 EPHYR_LOG("leave\n");
1064 ephyrReputImage(KdScreenInfo
* a_info
,
1065 DrawablePtr a_drawable
,
1067 short a_drw_y
, RegionPtr a_clipping_region
, pointer a_port_priv
)
1069 EphyrPortPriv
*port_priv
= a_port_priv
;
1070 int result
= BadImplementation
;
1072 EPHYR_RETURN_VAL_IF_FAIL(a_info
->pScreen
, FALSE
);
1073 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
&& port_priv
, BadValue
);
1075 EPHYR_LOG("enter\n");
1077 if (!port_priv
->image_buf_size
|| !port_priv
->image_buf
) {
1078 EPHYR_LOG_ERROR("has null image buf in cache\n");
1081 if (!ephyrHostXVPutImage(a_info
,
1083 port_priv
->image_id
,
1085 port_priv
->drw_w
, port_priv
->drw_h
,
1086 port_priv
->src_x
, port_priv
->src_y
,
1087 port_priv
->src_w
, port_priv
->src_h
,
1088 port_priv
->image_width
, port_priv
->image_height
,
1089 port_priv
->image_buf
,
1090 RegionRects(a_clipping_region
),
1091 RegionNumRects(a_clipping_region
))) {
1092 EPHYR_LOG_ERROR("ephyrHostXVPutImage() failed\n");
1099 EPHYR_LOG("leave\n");
1104 ephyrPutVideo(KdScreenInfo
* a_info
,
1105 DrawablePtr a_drawable
,
1106 short a_vid_x
, short a_vid_y
,
1107 short a_drw_x
, short a_drw_y
,
1108 short a_vid_w
, short a_vid_h
,
1109 short a_drw_w
, short a_drw_h
,
1110 RegionPtr a_clipping_region
, pointer a_port_priv
)
1112 EphyrScrPriv
*scrpriv
= a_info
->driver
;
1113 xcb_connection_t
*conn
= hostx_get_xcbconn();
1115 EphyrPortPriv
*port_priv
= a_port_priv
;
1117 EPHYR_RETURN_VAL_IF_FAIL(a_info
->pScreen
, BadValue
);
1118 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
&& port_priv
, BadValue
);
1120 EPHYR_LOG("enter\n");
1122 gc
= xcb_generate_id(conn
);
1123 xcb_create_gc(conn
, gc
, scrpriv
->win
, 0, NULL
);
1124 xcb_xv_put_video(conn
, port_priv
->port_number
,
1126 a_vid_x
, a_vid_y
, a_vid_w
, a_vid_h
,
1127 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
);
1128 xcb_free_gc(conn
, gc
);
1130 EPHYR_LOG("leave\n");
1135 ephyrGetVideo(KdScreenInfo
* a_info
,
1136 DrawablePtr a_drawable
,
1137 short a_vid_x
, short a_vid_y
,
1138 short a_drw_x
, short a_drw_y
,
1139 short a_vid_w
, short a_vid_h
,
1140 short a_drw_w
, short a_drw_h
,
1141 RegionPtr a_clipping_region
, pointer a_port_priv
)
1143 EphyrScrPriv
*scrpriv
= a_info
->driver
;
1144 xcb_connection_t
*conn
= hostx_get_xcbconn();
1146 EphyrPortPriv
*port_priv
= a_port_priv
;
1148 EPHYR_RETURN_VAL_IF_FAIL(a_info
&& a_info
->pScreen
, BadValue
);
1149 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
&& port_priv
, BadValue
);
1151 EPHYR_LOG("enter\n");
1153 gc
= xcb_generate_id(conn
);
1154 xcb_create_gc(conn
, gc
, scrpriv
->win
, 0, NULL
);
1155 xcb_xv_get_video(conn
, port_priv
->port_number
,
1157 a_vid_x
, a_vid_y
, a_vid_w
, a_vid_h
,
1158 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
);
1160 xcb_free_gc(conn
, gc
);
1162 EPHYR_LOG("leave\n");
1167 ephyrPutStill(KdScreenInfo
* a_info
,
1168 DrawablePtr a_drawable
,
1169 short a_vid_x
, short a_vid_y
,
1170 short a_drw_x
, short a_drw_y
,
1171 short a_vid_w
, short a_vid_h
,
1172 short a_drw_w
, short a_drw_h
,
1173 RegionPtr a_clipping_region
, pointer a_port_priv
)
1175 EphyrScrPriv
*scrpriv
= a_info
->driver
;
1176 xcb_connection_t
*conn
= hostx_get_xcbconn();
1178 EphyrPortPriv
*port_priv
= a_port_priv
;
1180 EPHYR_RETURN_VAL_IF_FAIL(a_info
&& a_info
->pScreen
, BadValue
);
1181 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
&& port_priv
, BadValue
);
1183 EPHYR_LOG("enter\n");
1185 gc
= xcb_generate_id(conn
);
1186 xcb_create_gc(conn
, gc
, scrpriv
->win
, 0, NULL
);
1187 xcb_xv_put_still(conn
, port_priv
->port_number
,
1189 a_vid_x
, a_vid_y
, a_vid_w
, a_vid_h
,
1190 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
);
1191 xcb_free_gc(conn
, gc
);
1193 EPHYR_LOG("leave\n");
1198 ephyrGetStill(KdScreenInfo
* a_info
,
1199 DrawablePtr a_drawable
,
1200 short a_vid_x
, short a_vid_y
,
1201 short a_drw_x
, short a_drw_y
,
1202 short a_vid_w
, short a_vid_h
,
1203 short a_drw_w
, short a_drw_h
,
1204 RegionPtr a_clipping_region
, pointer a_port_priv
)
1206 EphyrScrPriv
*scrpriv
= a_info
->driver
;
1207 xcb_connection_t
*conn
= hostx_get_xcbconn();
1209 EphyrPortPriv
*port_priv
= a_port_priv
;
1211 EPHYR_RETURN_VAL_IF_FAIL(a_info
&& a_info
->pScreen
, BadValue
);
1212 EPHYR_RETURN_VAL_IF_FAIL(a_drawable
&& port_priv
, BadValue
);
1214 EPHYR_LOG("enter\n");
1216 gc
= xcb_generate_id(conn
);
1217 xcb_create_gc(conn
, gc
, scrpriv
->win
, 0, NULL
);
1218 xcb_xv_get_still(conn
, port_priv
->port_number
,
1220 a_vid_x
, a_vid_y
, a_vid_w
, a_vid_h
,
1221 a_drw_x
, a_drw_y
, a_drw_w
, a_drw_h
);
1222 xcb_free_gc(conn
, gc
);
1224 EPHYR_LOG("leave\n");
1229 ephyrQueryImageAttributes(KdScreenInfo
* a_info
,
1231 unsigned short *a_w
,
1232 unsigned short *a_h
, int *a_pitches
, int *a_offsets
)
1234 xcb_connection_t
*conn
= hostx_get_xcbconn();
1235 xcb_xv_query_image_attributes_cookie_t cookie
;
1236 xcb_xv_query_image_attributes_reply_t
*reply
;
1239 EPHYR_RETURN_VAL_IF_FAIL(a_w
&& a_h
, FALSE
);
1241 EPHYR_LOG("enter: dim (%dx%d), pitches: %p, offsets: %p\n",
1242 *a_w
, *a_h
, a_pitches
, a_offsets
);
1244 cookie
= xcb_xv_query_image_attributes(conn
,
1245 s_base_port_id
, a_id
,
1247 reply
= xcb_xv_query_image_attributes_reply(conn
, cookie
, NULL
);
1251 *a_w
= reply
->width
;
1252 *a_h
= reply
->height
;
1253 if (a_pitches
&& a_offsets
) {
1254 memcpy(a_pitches
, xcb_xv_query_image_attributes_pitches(reply
),
1255 reply
->num_planes
<< 2);
1256 memcpy(a_offsets
, xcb_xv_query_image_attributes_offsets(reply
),
1257 reply
->num_planes
<< 2);
1259 image_size
= reply
->data_size
;
1263 EPHYR_LOG("image size: %d, dim (%dx%d)\n", image_size
, *a_w
, *a_h
);
1266 EPHYR_LOG("leave\n");