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_DIX_CONFIG_H
30 #include <dix-config.h>
31 #endif
32 #include <string.h>
33 #include <X11/extensions/Xv.h>
34 #include <xcb/xcb.h>
35 #include <xcb/xcb_aux.h>
36 #include <xcb/xv.h>
37 #include "ephyrlog.h"
38 #include "kdrive.h"
39 #include "kxv.h"
40 #include "ephyr.h"
41 #include "hostx.h"
42
43 struct _EphyrXVPriv {
44 xcb_xv_query_adaptors_reply_t *host_adaptors;
45 KdVideoAdaptorPtr adaptors;
46 int num_adaptors;
47 };
48 typedef struct _EphyrXVPriv EphyrXVPriv;
49
50 struct _EphyrPortPriv {
51 int port_number;
52 KdVideoAdaptorPtr current_adaptor;
53 EphyrXVPriv *xv_priv;
54 unsigned char *image_buf;
55 int image_buf_size;
56 int image_id;
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;
60 };
61 typedef struct _EphyrPortPriv EphyrPortPriv;
62
63 static Bool ephyrLocalAtomToHost(int a_local_atom, int *a_host_atom);
64
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,
70 ScreenPtr a_screen);
71
72 static Bool ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
73 int a_attrs_len,
74 const char *a_attr_name,
75 int a_attr_value, Bool *a_is_valid);
76
77 static Bool ephyrXVPrivGetImageBufSize(int a_port_id,
78 int a_image_id,
79 unsigned short a_width,
80 unsigned short a_height, int *a_size);
81
82 static Bool ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv * a_port_priv,
83 const unsigned char *a_image,
84 int a_image_len);
85
86 static void ephyrStopVideo(KdScreenInfo * a_info,
87 void *a_xv_priv, Bool a_exit);
88
89 static int ephyrSetPortAttribute(KdScreenInfo * a_info,
90 Atom a_attr_name,
91 int a_attr_value, void *a_port_priv);
92
93 static int ephyrGetPortAttribute(KdScreenInfo * a_screen_info,
94 Atom a_attr_name,
95 int *a_attr_value, void *a_port_priv);
96
97 static void ephyrQueryBestSize(KdScreenInfo * a_info,
98 Bool a_motion,
99 short a_src_w,
100 short a_src_h,
101 short a_drw_w,
102 short a_drw_h,
103 unsigned int *a_prefered_w,
104 unsigned int *a_prefered_h, void *a_port_priv);
105
106 static int ephyrPutImage(KdScreenInfo * a_info,
107 DrawablePtr a_drawable,
108 short a_src_x,
109 short a_src_y,
110 short a_drw_x,
111 short a_drw_y,
112 short a_src_w,
113 short a_src_h,
114 short a_drw_w,
115 short a_drw_h,
116 int a_id,
117 unsigned char *a_buf,
118 short a_width,
119 short a_height,
120 Bool a_sync,
121 RegionPtr a_clipping_region, void *a_port_priv);
122
123 static int ephyrReputImage(KdScreenInfo * a_info,
124 DrawablePtr a_drawable,
125 short a_drw_x,
126 short a_drw_y,
127 RegionPtr a_clipping_region, void *a_port_priv);
128
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, void *a_port_priv);
136
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, void *a_port_priv);
144
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, void *a_port_priv);
152
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, void *a_port_priv);
160
161 static int ephyrQueryImageAttributes(KdScreenInfo * a_info,
162 int a_id,
163 unsigned short *a_w,
164 unsigned short *a_h,
165 int *a_pitches, int *a_offsets);
166 static int s_base_port_id;
167
168 /**************
169 * <helpers>
170 * ************/
171
172 static Bool
adaptor_has_flags(const xcb_xv_adaptor_info_t * adaptor,uint32_t flags)173 adaptor_has_flags(const xcb_xv_adaptor_info_t *adaptor, uint32_t flags)
174 {
175 return (adaptor->type & flags) == flags;
176 }
177
178 static Bool
ephyrLocalAtomToHost(int a_local_atom,int * a_host_atom)179 ephyrLocalAtomToHost(int a_local_atom, int *a_host_atom)
180 {
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;
185
186 EPHYR_RETURN_VAL_IF_FAIL(a_host_atom, FALSE);
187
188 if (!ValidAtom(a_local_atom))
189 return FALSE;
190
191 atom_name = NameForAtom(a_local_atom);
192
193 if (!atom_name)
194 return FALSE;
195
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);
200 return FALSE;
201 }
202
203 *a_host_atom = reply->atom;
204 free(reply);
205
206 return TRUE;
207 }
208
209 /**************
210 *</helpers>
211 * ************/
212
213 Bool
ephyrInitVideo(ScreenPtr pScreen)214 ephyrInitVideo(ScreenPtr pScreen)
215 {
216 Bool is_ok = FALSE;
217
218 KdScreenPriv(pScreen);
219 KdScreenInfo *screen = pScreenPriv->screen;
220 static EphyrXVPriv *xv_priv;
221
222 EPHYR_LOG("enter\n");
223
224 if (screen->fb.bitsPerPixel == 8) {
225 EPHYR_LOG_ERROR("8 bits depth not supported\n");
226 return FALSE;
227 }
228
229 if (!hostx_has_extension(&xcb_xv_id)) {
230 EPHYR_LOG_ERROR("Host has no XVideo extension\n");
231 return FALSE;
232 }
233
234 if (!xv_priv) {
235 xv_priv = ephyrXVPrivNew();
236 }
237 if (!xv_priv) {
238 EPHYR_LOG_ERROR("failed to create xv_priv\n");
239 goto out;
240 }
241
242 if (!ephyrXVPrivRegisterAdaptors(xv_priv, pScreen)) {
243 EPHYR_LOG_ERROR("failed to register adaptors\n");
244 goto out;
245 }
246 is_ok = TRUE;
247
248 out:
249 return is_ok;
250 }
251
252 static EphyrXVPriv *
ephyrXVPrivNew(void)253 ephyrXVPrivNew(void)
254 {
255 EphyrXVPriv *xv_priv = NULL;
256
257 EPHYR_LOG("enter\n");
258
259 xv_priv = calloc(1, sizeof(EphyrXVPriv));
260 if (!xv_priv) {
261 EPHYR_LOG_ERROR("failed to create EphyrXVPriv\n");
262 goto error;
263 }
264
265 if (!ephyrXVPrivQueryHostAdaptors(xv_priv)) {
266 EPHYR_LOG_ERROR("failed to query the host x for xv properties\n");
267 goto error;
268 }
269 if (!ephyrXVPrivSetAdaptorsHooks(xv_priv)) {
270 EPHYR_LOG_ERROR("failed to set xv_priv hooks\n");
271 goto error;
272 }
273
274 EPHYR_LOG("leave\n");
275 return xv_priv;
276
277 error:
278 if (xv_priv) {
279 ephyrXVPrivDelete(xv_priv);
280 xv_priv = NULL;
281 }
282 return NULL;
283 }
284
285 static void
ephyrXVPrivDelete(EphyrXVPriv * a_this)286 ephyrXVPrivDelete(EphyrXVPriv * a_this)
287 {
288 EPHYR_LOG("enter\n");
289
290 if (!a_this)
291 return;
292 if (a_this->host_adaptors) {
293 free(a_this->host_adaptors);
294 a_this->host_adaptors = NULL;
295 }
296 free(a_this->adaptors);
297 a_this->adaptors = NULL;
298 free(a_this);
299 EPHYR_LOG("leave\n");
300 }
301
302 static Bool
translate_video_encodings(KdVideoAdaptorPtr adaptor,xcb_xv_adaptor_info_t * host_adaptor)303 translate_video_encodings(KdVideoAdaptorPtr adaptor,
304 xcb_xv_adaptor_info_t *host_adaptor)
305 {
306 xcb_connection_t *conn = hostx_get_xcbconn();
307 int i;
308 xcb_xv_query_encodings_cookie_t cookie;
309 xcb_xv_query_encodings_reply_t *reply;
310 xcb_xv_encoding_info_iterator_t encoding_it;
311
312 cookie = xcb_xv_query_encodings(conn, host_adaptor->base_id);
313 reply = xcb_xv_query_encodings_reply(conn, cookie, NULL);
314 if (!reply)
315 return FALSE;
316
317 adaptor->nEncodings = reply->num_encodings;
318 adaptor->pEncodings = calloc(adaptor->nEncodings,
319 sizeof(*adaptor->pEncodings));
320 if (!adaptor->pEncodings) {
321 free(reply);
322 return FALSE;
323 }
324
325 encoding_it = xcb_xv_query_encodings_info_iterator(reply);
326 for (i = 0; i < adaptor->nEncodings; i++) {
327 xcb_xv_encoding_info_t *encoding_info = encoding_it.data;
328 KdVideoEncodingPtr encoding = &adaptor->pEncodings[i];
329
330 encoding->id = encoding_info->encoding;
331 encoding->name = strndup(xcb_xv_encoding_info_name(encoding_info),
332 encoding_info->name_size);
333 encoding->width = encoding_info->width;
334 encoding->height = encoding_info->height;
335 encoding->rate.numerator = encoding_info->rate.numerator;
336 encoding->rate.denominator = encoding_info->rate.denominator;
337
338 xcb_xv_encoding_info_next(&encoding_it);
339 }
340
341 free(reply);
342 return TRUE;
343 }
344
345 static Bool
translate_xv_attributes(KdVideoAdaptorPtr adaptor,xcb_xv_adaptor_info_t * host_adaptor)346 translate_xv_attributes(KdVideoAdaptorPtr adaptor,
347 xcb_xv_adaptor_info_t *host_adaptor)
348 {
349 xcb_connection_t *conn = hostx_get_xcbconn();
350 int i = 0;
351 xcb_xv_attribute_info_iterator_t it;
352 xcb_xv_query_port_attributes_cookie_t cookie =
353 xcb_xv_query_port_attributes(conn, host_adaptor->base_id);
354 xcb_xv_query_port_attributes_reply_t *reply =
355 xcb_xv_query_port_attributes_reply(conn, cookie, NULL);
356
357 if (!reply)
358 return FALSE;
359
360 adaptor->nAttributes = reply->num_attributes;
361 adaptor->pAttributes = calloc(reply->num_attributes,
362 sizeof(*adaptor->pAttributes));
363 if (!adaptor->pAttributes) {
364 EPHYR_LOG_ERROR("failed to allocate attributes\n");
365 free(reply);
366 return FALSE;
367 }
368
369 it = xcb_xv_query_port_attributes_attributes_iterator(reply);
370 for (i = 0; i < reply->num_attributes; i++) {
371 XvAttributePtr attribute = &adaptor->pAttributes[i];
372
373 attribute->flags = it.data->flags;
374 attribute->min_value = it.data->min;
375 attribute->max_value = it.data->max;
376 attribute->name = strndup(xcb_xv_attribute_info_name(it.data),
377 it.data->size);
378
379 /* make sure atoms of attrs names are created in xephyr */
380 MakeAtom(xcb_xv_attribute_info_name(it.data), it.data->size, TRUE);
381
382 xcb_xv_attribute_info_next(&it);
383 }
384
385 free(reply);
386 return TRUE;
387 }
388
389 static Bool
translate_xv_image_formats(KdVideoAdaptorPtr adaptor,xcb_xv_adaptor_info_t * host_adaptor)390 translate_xv_image_formats(KdVideoAdaptorPtr adaptor,
391 xcb_xv_adaptor_info_t *host_adaptor)
392 {
393 xcb_connection_t *conn = hostx_get_xcbconn();
394 int i = 0;
395 xcb_xv_list_image_formats_cookie_t cookie =
396 xcb_xv_list_image_formats(conn, host_adaptor->base_id);
397 xcb_xv_list_image_formats_reply_t *reply =
398 xcb_xv_list_image_formats_reply(conn, cookie, NULL);
399 xcb_xv_image_format_info_t *formats;
400
401 if (!reply)
402 return FALSE;
403
404 adaptor->nImages = reply->num_formats;
405 adaptor->pImages = calloc(reply->num_formats, sizeof(XvImageRec));
406 if (!adaptor->pImages) {
407 free(reply);
408 return FALSE;
409 }
410
411 formats = xcb_xv_list_image_formats_format(reply);
412 for (i = 0; i < reply->num_formats; i++) {
413 XvImagePtr image = &adaptor->pImages[i];
414
415 image->id = formats[i].id;
416 image->type = formats[i].type;
417 image->byte_order = formats[i].byte_order;
418 memcpy(image->guid, formats[i].guid, 16);
419 image->bits_per_pixel = formats[i].bpp;
420 image->format = formats[i].format;
421 image->num_planes = formats[i].num_planes;
422 image->depth = formats[i].depth;
423 image->red_mask = formats[i].red_mask;
424 image->green_mask = formats[i].green_mask;
425 image->blue_mask = formats[i].blue_mask;
426 image->y_sample_bits = formats[i].y_sample_bits;
427 image->u_sample_bits = formats[i].u_sample_bits;
428 image->v_sample_bits = formats[i].v_sample_bits;
429 image->horz_y_period = formats[i].vhorz_y_period;
430 image->horz_u_period = formats[i].vhorz_u_period;
431 image->horz_v_period = formats[i].vhorz_v_period;
432 image->vert_y_period = formats[i].vvert_y_period;
433 image->vert_u_period = formats[i].vvert_u_period;
434 image->vert_v_period = formats[i].vvert_v_period;
435 memcpy(image->component_order, formats[i].vcomp_order, 32);
436 image->scanline_order = formats[i].vscanline_order;
437 }
438
439 free(reply);
440 return TRUE;
441 }
442
443 static Bool
ephyrXVPrivQueryHostAdaptors(EphyrXVPriv * a_this)444 ephyrXVPrivQueryHostAdaptors(EphyrXVPriv * a_this)
445 {
446 xcb_connection_t *conn = hostx_get_xcbconn();
447 xcb_screen_t *xscreen = xcb_aux_get_screen(conn, hostx_get_screen());
448 int base_port_id = 0, i = 0, port_priv_offset = 0;
449 Bool is_ok = FALSE;
450 xcb_generic_error_t *e = NULL;
451 xcb_xv_adaptor_info_iterator_t it;
452
453 EPHYR_RETURN_VAL_IF_FAIL(a_this, FALSE);
454
455 EPHYR_LOG("enter\n");
456
457 {
458 xcb_xv_query_adaptors_cookie_t cookie =
459 xcb_xv_query_adaptors(conn, xscreen->root);
460 a_this->host_adaptors = xcb_xv_query_adaptors_reply(conn, cookie, &e);
461 if (e) {
462 free(e);
463 EPHYR_LOG_ERROR("failed to query host adaptors\n");
464 goto out;
465 }
466 }
467
468 if (a_this->host_adaptors)
469 a_this->num_adaptors = a_this->host_adaptors->num_adaptors;
470 if (a_this->num_adaptors <= 0) {
471 EPHYR_LOG_ERROR("failed to get number of host adaptors\n");
472 goto out;
473 }
474 EPHYR_LOG("host has %d adaptors\n", a_this->num_adaptors);
475 /*
476 * copy what we can from adaptors into a_this->adaptors
477 */
478 if (a_this->num_adaptors) {
479 a_this->adaptors = calloc(a_this->num_adaptors,
480 sizeof(KdVideoAdaptorRec));
481 if (!a_this->adaptors) {
482 EPHYR_LOG_ERROR("failed to create internal adaptors\n");
483 goto out;
484 }
485 }
486
487 it = xcb_xv_query_adaptors_info_iterator(a_this->host_adaptors);
488 for (i = 0; i < a_this->num_adaptors; i++) {
489 xcb_xv_adaptor_info_t *cur_host_adaptor = it.data;
490 xcb_xv_format_t *format = xcb_xv_adaptor_info_formats(cur_host_adaptor);
491 int j = 0;
492
493 a_this->adaptors[i].nPorts = cur_host_adaptor->num_ports;
494 if (a_this->adaptors[i].nPorts <= 0) {
495 EPHYR_LOG_ERROR("Could not find any port of adaptor %d\n", i);
496 continue;
497 }
498 a_this->adaptors[i].type = cur_host_adaptor->type;
499 a_this->adaptors[i].type |= XvWindowMask;
500 a_this->adaptors[i].flags =
501 VIDEO_OVERLAID_IMAGES | VIDEO_CLIP_TO_VIEWPORT;
502 a_this->adaptors[i].name =
503 strndup(xcb_xv_adaptor_info_name(cur_host_adaptor),
504 cur_host_adaptor->name_size);
505 if (!a_this->adaptors[i].name)
506 a_this->adaptors[i].name = strdup("Xephyr Video Overlay");
507 base_port_id = cur_host_adaptor->base_id;
508 if (base_port_id < 0) {
509 EPHYR_LOG_ERROR("failed to get port id for adaptor %d\n", i);
510 continue;
511 }
512 if (!s_base_port_id)
513 s_base_port_id = base_port_id;
514
515 if (!translate_video_encodings(&a_this->adaptors[i],
516 cur_host_adaptor)) {
517 EPHYR_LOG_ERROR("failed to get encodings for port port id %d,"
518 " adaptors %d\n", base_port_id, i);
519 continue;
520 }
521
522 a_this->adaptors[i].nFormats = cur_host_adaptor->num_formats;
523 a_this->adaptors[i].pFormats =
524 calloc(cur_host_adaptor->num_formats,
525 sizeof(*a_this->adaptors[i].pFormats));
526 for (j = 0; j < cur_host_adaptor->num_formats; j++) {
527 xcb_visualtype_t *visual =
528 xcb_aux_find_visual_by_id(xscreen, format[j].visual);
529 a_this->adaptors[i].pFormats[j].depth = format[j].depth;
530 a_this->adaptors[i].pFormats[j].class = visual->_class;
531 }
532
533 a_this->adaptors[i].pPortPrivates =
534 calloc(a_this->adaptors[i].nPorts,
535 sizeof(DevUnion) + sizeof(EphyrPortPriv));
536 port_priv_offset = a_this->adaptors[i].nPorts;
537 for (j = 0; j < a_this->adaptors[i].nPorts; j++) {
538 EphyrPortPriv *port_privs_base =
539 (EphyrPortPriv *) &a_this->adaptors[i].
540 pPortPrivates[port_priv_offset];
541 EphyrPortPriv *port_priv = &port_privs_base[j];
542
543 port_priv->port_number = base_port_id + j;
544 port_priv->current_adaptor = &a_this->adaptors[i];
545 port_priv->xv_priv = a_this;
546 a_this->adaptors[i].pPortPrivates[j].ptr = port_priv;
547 }
548
549 if (!translate_xv_attributes(&a_this->adaptors[i], cur_host_adaptor)) {
550 {
551 EPHYR_LOG_ERROR("failed to get port attribute "
552 "for adaptor %d\n", i);
553 continue;
554 }
555 }
556
557 if (!translate_xv_image_formats(&a_this->adaptors[i], cur_host_adaptor)) {
558 EPHYR_LOG_ERROR("failed to get image formats "
559 "for adaptor %d\n", i);
560 continue;
561 }
562
563 xcb_xv_adaptor_info_next(&it);
564 }
565 is_ok = TRUE;
566
567 out:
568 EPHYR_LOG("leave\n");
569 return is_ok;
570 }
571
572 static Bool
ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this)573 ephyrXVPrivSetAdaptorsHooks(EphyrXVPriv * a_this)
574 {
575 int i = 0;
576 xcb_xv_adaptor_info_iterator_t it;
577
578 EPHYR_RETURN_VAL_IF_FAIL(a_this, FALSE);
579
580 EPHYR_LOG("enter\n");
581
582 it = xcb_xv_query_adaptors_info_iterator(a_this->host_adaptors);
583 for (i = 0; i < a_this->num_adaptors; i++) {
584 xcb_xv_adaptor_info_t *cur_host_adaptor = it.data;
585
586 a_this->adaptors[i].ReputImage = ephyrReputImage;
587 a_this->adaptors[i].StopVideo = ephyrStopVideo;
588 a_this->adaptors[i].SetPortAttribute = ephyrSetPortAttribute;
589 a_this->adaptors[i].GetPortAttribute = ephyrGetPortAttribute;
590 a_this->adaptors[i].QueryBestSize = ephyrQueryBestSize;
591 a_this->adaptors[i].QueryImageAttributes = ephyrQueryImageAttributes;
592
593 if (adaptor_has_flags(cur_host_adaptor,
594 XCB_XV_TYPE_IMAGE_MASK | XCB_XV_TYPE_INPUT_MASK))
595 a_this->adaptors[i].PutImage = ephyrPutImage;
596
597 if (adaptor_has_flags(cur_host_adaptor,
598 XCB_XV_TYPE_VIDEO_MASK | XCB_XV_TYPE_INPUT_MASK))
599 a_this->adaptors[i].PutVideo = ephyrPutVideo;
600
601 if (adaptor_has_flags(cur_host_adaptor,
602 XCB_XV_TYPE_VIDEO_MASK | XCB_XV_TYPE_OUTPUT_MASK))
603 a_this->adaptors[i].GetVideo = ephyrGetVideo;
604
605 if (adaptor_has_flags(cur_host_adaptor,
606 XCB_XV_TYPE_STILL_MASK | XCB_XV_TYPE_INPUT_MASK))
607 a_this->adaptors[i].PutStill = ephyrPutStill;
608
609 if (adaptor_has_flags(cur_host_adaptor,
610 XCB_XV_TYPE_STILL_MASK | XCB_XV_TYPE_OUTPUT_MASK))
611 a_this->adaptors[i].GetStill = ephyrGetStill;
612 }
613 EPHYR_LOG("leave\n");
614 return TRUE;
615 }
616
617 static Bool
ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this,ScreenPtr a_screen)618 ephyrXVPrivRegisterAdaptors(EphyrXVPriv * a_this, ScreenPtr a_screen)
619 {
620 Bool is_ok = FALSE;
621
622 EPHYR_RETURN_VAL_IF_FAIL(a_this && a_screen, FALSE);
623
624 EPHYR_LOG("enter\n");
625
626 if (!a_this->num_adaptors)
627 goto out;
628
629 if (!KdXVScreenInit(a_screen, a_this->adaptors, a_this->num_adaptors)) {
630 EPHYR_LOG_ERROR("failed to register adaptors\n");
631 goto out;
632 }
633 EPHYR_LOG("there are %d registered adaptors\n", a_this->num_adaptors);
634 is_ok = TRUE;
635
636 out:
637
638 EPHYR_LOG("leave\n");
639 return is_ok;
640 }
641
642 static Bool
ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,int a_attrs_len,const char * a_attr_name,int a_attr_value,Bool * a_is_valid)643 ephyrXVPrivIsAttrValueValid(XvAttributePtr a_attrs,
644 int a_attrs_len,
645 const char *a_attr_name,
646 int a_attr_value, Bool *a_is_valid)
647 {
648 int i = 0;
649
650 EPHYR_RETURN_VAL_IF_FAIL(a_attrs && a_attr_name && a_is_valid, FALSE);
651
652 for (i = 0; i < a_attrs_len; i++) {
653 if (a_attrs[i].name && strcmp(a_attrs[i].name, a_attr_name))
654 continue;
655 if (a_attrs[i].min_value > a_attr_value ||
656 a_attrs[i].max_value < a_attr_value) {
657 *a_is_valid = FALSE;
658 EPHYR_LOG_ERROR("attribute was not valid\n"
659 "value:%d. min:%d. max:%d\n",
660 a_attr_value,
661 a_attrs[i].min_value, a_attrs[i].max_value);
662 }
663 else {
664 *a_is_valid = TRUE;
665 }
666 return TRUE;
667 }
668 return FALSE;
669 }
670
671 static Bool
ephyrXVPrivGetImageBufSize(int a_port_id,int a_image_id,unsigned short a_width,unsigned short a_height,int * a_size)672 ephyrXVPrivGetImageBufSize(int a_port_id,
673 int a_image_id,
674 unsigned short a_width,
675 unsigned short a_height, int *a_size)
676 {
677 xcb_connection_t *conn = hostx_get_xcbconn();
678 xcb_xv_query_image_attributes_cookie_t cookie;
679 xcb_xv_query_image_attributes_reply_t *reply;
680 Bool is_ok = FALSE;
681
682 EPHYR_RETURN_VAL_IF_FAIL(a_size, FALSE);
683
684 EPHYR_LOG("enter\n");
685
686 cookie = xcb_xv_query_image_attributes(conn,
687 a_port_id, a_image_id,
688 a_width, a_height);
689 reply = xcb_xv_query_image_attributes_reply(conn, cookie, NULL);
690 if (!reply)
691 goto out;
692
693 *a_size = reply->data_size;
694 is_ok = TRUE;
695
696 free(reply);
697
698 out:
699 EPHYR_LOG("leave\n");
700 return is_ok;
701 }
702
703 static Bool
ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv * a_port_priv,const unsigned char * a_image_buf,int a_image_len)704 ephyrXVPrivSaveImageToPortPriv(EphyrPortPriv * a_port_priv,
705 const unsigned char *a_image_buf,
706 int a_image_len)
707 {
708 Bool is_ok = FALSE;
709
710 EPHYR_LOG("enter\n");
711
712 if (a_port_priv->image_buf_size < a_image_len) {
713 unsigned char *buf = NULL;
714
715 buf = realloc(a_port_priv->image_buf, a_image_len);
716 if (!buf) {
717 EPHYR_LOG_ERROR("failed to realloc image buffer\n");
718 goto out;
719 }
720 a_port_priv->image_buf = buf;
721 a_port_priv->image_buf_size = a_image_len;
722 }
723 memmove(a_port_priv->image_buf, a_image_buf, a_image_len);
724 is_ok = TRUE;
725
726 out:
727 return is_ok;
728 EPHYR_LOG("leave\n");
729 }
730
731 static void
ephyrStopVideo(KdScreenInfo * a_info,void * a_port_priv,Bool a_exit)732 ephyrStopVideo(KdScreenInfo * a_info, void *a_port_priv, Bool a_exit)
733 {
734 xcb_connection_t *conn = hostx_get_xcbconn();
735 EphyrPortPriv *port_priv = a_port_priv;
736 EphyrScrPriv *scrpriv = a_info->driver;
737
738 EPHYR_RETURN_IF_FAIL(port_priv);
739
740 EPHYR_LOG("enter\n");
741 xcb_xv_stop_video(conn, port_priv->port_number, scrpriv->win);
742 EPHYR_LOG("leave\n");
743 }
744
745 static int
ephyrSetPortAttribute(KdScreenInfo * a_info,Atom a_attr_name,int a_attr_value,void * a_port_priv)746 ephyrSetPortAttribute(KdScreenInfo * a_info,
747 Atom a_attr_name, int a_attr_value, void *a_port_priv)
748 {
749 xcb_connection_t *conn = hostx_get_xcbconn();
750 int res = Success, host_atom = 0;
751 EphyrPortPriv *port_priv = a_port_priv;
752 Bool is_attr_valid = FALSE;
753
754 EPHYR_RETURN_VAL_IF_FAIL(port_priv, BadMatch);
755 EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor, BadMatch);
756 EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor->pAttributes, BadMatch);
757 EPHYR_RETURN_VAL_IF_FAIL(port_priv->current_adaptor->nAttributes, BadMatch);
758 EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name), BadMatch);
759
760 EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s, attr_val:%d\n",
761 port_priv->port_number,
762 (int) a_attr_name, NameForAtom(a_attr_name), a_attr_value);
763
764 if (!ephyrLocalAtomToHost(a_attr_name, &host_atom)) {
765 EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
766 res = BadMatch;
767 goto out;
768 }
769
770 if (!ephyrXVPrivIsAttrValueValid(port_priv->current_adaptor->pAttributes,
771 port_priv->current_adaptor->nAttributes,
772 NameForAtom(a_attr_name),
773 a_attr_value, &is_attr_valid)) {
774 EPHYR_LOG_ERROR("failed to validate attribute %s\n",
775 NameForAtom(a_attr_name));
776 /*
777 res = BadMatch ;
778 goto out ;
779 */
780 }
781 if (!is_attr_valid) {
782 EPHYR_LOG_ERROR("attribute %s is not valid\n",
783 NameForAtom(a_attr_name));
784 /*
785 res = BadMatch ;
786 goto out ;
787 */
788 }
789
790 xcb_xv_set_port_attribute(conn, port_priv->port_number,
791 host_atom, a_attr_value);
792 xcb_flush(conn);
793
794 res = Success;
795 out:
796 EPHYR_LOG("leave\n");
797 return res;
798 }
799
800 static int
ephyrGetPortAttribute(KdScreenInfo * a_screen_info,Atom a_attr_name,int * a_attr_value,void * a_port_priv)801 ephyrGetPortAttribute(KdScreenInfo * a_screen_info,
802 Atom a_attr_name, int *a_attr_value, void *a_port_priv)
803 {
804 xcb_connection_t *conn = hostx_get_xcbconn();
805 int res = Success, host_atom = 0;
806 EphyrPortPriv *port_priv = a_port_priv;
807 xcb_generic_error_t *e;
808 xcb_xv_get_port_attribute_cookie_t cookie;
809 xcb_xv_get_port_attribute_reply_t *reply;
810
811 EPHYR_RETURN_VAL_IF_FAIL(port_priv, BadMatch);
812 EPHYR_RETURN_VAL_IF_FAIL(ValidAtom(a_attr_name), BadMatch);
813
814 EPHYR_LOG("enter, portnum:%d, atomid:%d, attr_name:%s\n",
815 port_priv->port_number,
816 (int) a_attr_name, NameForAtom(a_attr_name));
817
818 if (!ephyrLocalAtomToHost(a_attr_name, &host_atom)) {
819 EPHYR_LOG_ERROR("failed to convert local atom to host atom\n");
820 res = BadMatch;
821 goto out;
822 }
823
824 cookie = xcb_xv_get_port_attribute(conn, port_priv->port_number, host_atom);
825 reply = xcb_xv_get_port_attribute_reply(conn, cookie, &e);
826 if (e) {
827 EPHYR_LOG_ERROR ("XvGetPortAttribute() failed: %d \n", e->error_code);
828 free(e);
829 res = BadMatch;
830 goto out;
831 }
832 *a_attr_value = reply->value;
833
834 free(reply);
835
836 res = Success;
837 out:
838 EPHYR_LOG("leave\n");
839 return res;
840 }
841
842 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,void * a_port_priv)843 ephyrQueryBestSize(KdScreenInfo * a_info,
844 Bool a_motion,
845 short a_src_w,
846 short a_src_h,
847 short a_drw_w,
848 short a_drw_h,
849 unsigned int *a_prefered_w,
850 unsigned int *a_prefered_h, void *a_port_priv)
851 {
852 xcb_connection_t *conn = hostx_get_xcbconn();
853 EphyrPortPriv *port_priv = a_port_priv;
854 xcb_xv_query_best_size_cookie_t cookie =
855 xcb_xv_query_best_size(conn,
856 port_priv->port_number,
857 a_src_w, a_src_h,
858 a_drw_w, a_drw_h,
859 a_motion);
860 xcb_xv_query_best_size_reply_t *reply =
861 xcb_xv_query_best_size_reply(conn, cookie, NULL);
862
863 EPHYR_LOG("enter: frame (%dx%d), drw (%dx%d)\n",
864 a_src_w, a_src_h, a_drw_w, a_drw_h);
865
866 if (!reply) {
867 EPHYR_LOG_ERROR ("XvQueryBestSize() failed\n");
868 return;
869 }
870 *a_prefered_w = reply->actual_width;
871 *a_prefered_h = reply->actual_height;
872 EPHYR_LOG("actual (%dx%d)\n", *a_prefered_w, *a_prefered_h);
873 free(reply);
874
875 EPHYR_LOG("leave\n");
876 }
877
878
879 static Bool
ephyrHostXVPutImage(KdScreenInfo * a_info,EphyrPortPriv * port_priv,int a_image_id,int a_drw_x,int a_drw_y,int a_drw_w,int a_drw_h,int a_src_x,int a_src_y,int a_src_w,int a_src_h,int a_image_width,int a_image_height,unsigned char * a_buf,BoxPtr a_clip_rects,int a_clip_rect_nums)880 ephyrHostXVPutImage(KdScreenInfo * a_info,
881 EphyrPortPriv *port_priv,
882 int a_image_id,
883 int a_drw_x,
884 int a_drw_y,
885 int a_drw_w,
886 int a_drw_h,
887 int a_src_x,
888 int a_src_y,
889 int a_src_w,
890 int a_src_h,
891 int a_image_width,
892 int a_image_height,
893 unsigned char *a_buf,
894 BoxPtr a_clip_rects, int a_clip_rect_nums)
895 {
896 EphyrScrPriv *scrpriv = a_info->driver;
897 xcb_connection_t *conn = hostx_get_xcbconn();
898 xcb_gcontext_t gc;
899 Bool is_ok = TRUE;
900 xcb_rectangle_t *rects = NULL;
901 int data_len, width, height;
902 xcb_xv_query_image_attributes_cookie_t image_attr_cookie;
903 xcb_xv_query_image_attributes_reply_t *image_attr_reply;
904
905 EPHYR_RETURN_VAL_IF_FAIL(a_buf, FALSE);
906
907 EPHYR_LOG("enter, num_clip_rects: %d\n", a_clip_rect_nums);
908
909 image_attr_cookie = xcb_xv_query_image_attributes(conn,
910 port_priv->port_number,
911 a_image_id,
912 a_image_width,
913 a_image_height);
914 image_attr_reply = xcb_xv_query_image_attributes_reply(conn,
915 image_attr_cookie,
916 NULL);
917 if (!image_attr_reply)
918 goto out;
919 data_len = image_attr_reply->data_size;
920 width = image_attr_reply->width;
921 height = image_attr_reply->height;
922 free(image_attr_reply);
923
924 gc = xcb_generate_id(conn);
925 xcb_create_gc(conn, gc, scrpriv->win, 0, NULL);
926
927 if (a_clip_rect_nums) {
928 int i = 0;
929 rects = calloc(a_clip_rect_nums, sizeof(xcb_rectangle_t));
930 for (i=0; i < a_clip_rect_nums; i++) {
931 rects[i].x = a_clip_rects[i].x1;
932 rects[i].y = a_clip_rects[i].y1;
933 rects[i].width = a_clip_rects[i].x2 - a_clip_rects[i].x1;
934 rects[i].height = a_clip_rects[i].y2 - a_clip_rects[i].y1;
935 EPHYR_LOG("(x,y,w,h): (%d,%d,%d,%d)\n",
936 rects[i].x, rects[i].y, rects[i].width, rects[i].height);
937 }
938 xcb_set_clip_rectangles(conn,
939 XCB_CLIP_ORDERING_YX_BANDED,
940 gc,
941 0,
942 0,
943 a_clip_rect_nums,
944 rects);
945 free(rects);
946 }
947 xcb_xv_put_image(conn,
948 port_priv->port_number,
949 scrpriv->win,
950 gc,
951 a_image_id,
952 a_src_x, a_src_y, a_src_w, a_src_h,
953 a_drw_x, a_drw_y, a_drw_w, a_drw_h,
954 width, height,
955 data_len, a_buf);
956 xcb_free_gc(conn, gc);
957
958 is_ok = TRUE;
959
960 out:
961 EPHYR_LOG("leave\n");
962 return is_ok;
963 }
964
965 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,void * a_port_priv)966 ephyrPutImage(KdScreenInfo * a_info,
967 DrawablePtr a_drawable,
968 short a_src_x,
969 short a_src_y,
970 short a_drw_x,
971 short a_drw_y,
972 short a_src_w,
973 short a_src_h,
974 short a_drw_w,
975 short a_drw_h,
976 int a_id,
977 unsigned char *a_buf,
978 short a_width,
979 short a_height,
980 Bool a_sync, RegionPtr a_clipping_region, void *a_port_priv)
981 {
982 EphyrPortPriv *port_priv = a_port_priv;
983 Bool is_ok = FALSE;
984 int result = BadImplementation, image_size = 0;
985
986 EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
987 EPHYR_RETURN_VAL_IF_FAIL(a_drawable, BadValue);
988
989 EPHYR_LOG("enter\n");
990
991 if (!ephyrHostXVPutImage(a_info, port_priv,
992 a_id,
993 a_drw_x, a_drw_y, a_drw_w, a_drw_h,
994 a_src_x, a_src_y, a_src_w, a_src_h,
995 a_width, a_height, a_buf,
996 RegionRects(a_clipping_region),
997 RegionNumRects(a_clipping_region))) {
998 EPHYR_LOG_ERROR("EphyrHostXVPutImage() failed\n");
999 goto out;
1000 }
1001
1002 /*
1003 * Now save the image so that we can resend it to host it
1004 * later, in ReputImage.
1005 */
1006 if (!ephyrXVPrivGetImageBufSize(port_priv->port_number,
1007 a_id, a_width, a_height, &image_size)) {
1008 EPHYR_LOG_ERROR("failed to get image size\n");
1009 /*this is a minor error so we won't get bail out abruptly */
1010 is_ok = FALSE;
1011 }
1012 else {
1013 is_ok = TRUE;
1014 }
1015 if (is_ok) {
1016 if (!ephyrXVPrivSaveImageToPortPriv(port_priv, a_buf, image_size)) {
1017 is_ok = FALSE;
1018 }
1019 else {
1020 port_priv->image_id = a_id;
1021 port_priv->drw_x = a_drw_x;
1022 port_priv->drw_y = a_drw_y;
1023 port_priv->drw_w = a_drw_w;
1024 port_priv->drw_h = a_drw_h;
1025 port_priv->src_x = a_src_x;
1026 port_priv->src_y = a_src_y;
1027 port_priv->src_w = a_src_w;
1028 port_priv->src_h = a_src_h;
1029 port_priv->image_width = a_width;
1030 port_priv->image_height = a_height;
1031 }
1032 }
1033 if (!is_ok) {
1034 if (port_priv->image_buf) {
1035 free(port_priv->image_buf);
1036 port_priv->image_buf = NULL;
1037 port_priv->image_buf_size = 0;
1038 }
1039 }
1040
1041 result = Success;
1042
1043 out:
1044 EPHYR_LOG("leave\n");
1045 return result;
1046 }
1047
1048 static int
ephyrReputImage(KdScreenInfo * a_info,DrawablePtr a_drawable,short a_drw_x,short a_drw_y,RegionPtr a_clipping_region,void * a_port_priv)1049 ephyrReputImage(KdScreenInfo * a_info,
1050 DrawablePtr a_drawable,
1051 short a_drw_x,
1052 short a_drw_y, RegionPtr a_clipping_region, void *a_port_priv)
1053 {
1054 EphyrPortPriv *port_priv = a_port_priv;
1055 int result = BadImplementation;
1056
1057 EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, FALSE);
1058 EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
1059
1060 EPHYR_LOG("enter\n");
1061
1062 if (!port_priv->image_buf_size || !port_priv->image_buf) {
1063 EPHYR_LOG_ERROR("has null image buf in cache\n");
1064 goto out;
1065 }
1066 if (!ephyrHostXVPutImage(a_info,
1067 port_priv,
1068 port_priv->image_id,
1069 a_drw_x, a_drw_y,
1070 port_priv->drw_w, port_priv->drw_h,
1071 port_priv->src_x, port_priv->src_y,
1072 port_priv->src_w, port_priv->src_h,
1073 port_priv->image_width, port_priv->image_height,
1074 port_priv->image_buf,
1075 RegionRects(a_clipping_region),
1076 RegionNumRects(a_clipping_region))) {
1077 EPHYR_LOG_ERROR("ephyrHostXVPutImage() failed\n");
1078 goto out;
1079 }
1080
1081 result = Success;
1082
1083 out:
1084 EPHYR_LOG("leave\n");
1085 return result;
1086 }
1087
1088 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,void * a_port_priv)1089 ephyrPutVideo(KdScreenInfo * a_info,
1090 DrawablePtr a_drawable,
1091 short a_vid_x, short a_vid_y,
1092 short a_drw_x, short a_drw_y,
1093 short a_vid_w, short a_vid_h,
1094 short a_drw_w, short a_drw_h,
1095 RegionPtr a_clipping_region, void *a_port_priv)
1096 {
1097 EphyrScrPriv *scrpriv = a_info->driver;
1098 xcb_connection_t *conn = hostx_get_xcbconn();
1099 xcb_gcontext_t gc;
1100 EphyrPortPriv *port_priv = a_port_priv;
1101
1102 EPHYR_RETURN_VAL_IF_FAIL(a_info->pScreen, BadValue);
1103 EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
1104
1105 EPHYR_LOG("enter\n");
1106
1107 gc = xcb_generate_id(conn);
1108 xcb_create_gc(conn, gc, scrpriv->win, 0, NULL);
1109 xcb_xv_put_video(conn, port_priv->port_number,
1110 scrpriv->win, gc,
1111 a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1112 a_drw_x, a_drw_y, a_drw_w, a_drw_h);
1113 xcb_free_gc(conn, gc);
1114
1115 EPHYR_LOG("leave\n");
1116 return Success;
1117 }
1118
1119 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,void * a_port_priv)1120 ephyrGetVideo(KdScreenInfo * a_info,
1121 DrawablePtr a_drawable,
1122 short a_vid_x, short a_vid_y,
1123 short a_drw_x, short a_drw_y,
1124 short a_vid_w, short a_vid_h,
1125 short a_drw_w, short a_drw_h,
1126 RegionPtr a_clipping_region, void *a_port_priv)
1127 {
1128 EphyrScrPriv *scrpriv = a_info->driver;
1129 xcb_connection_t *conn = hostx_get_xcbconn();
1130 xcb_gcontext_t gc;
1131 EphyrPortPriv *port_priv = a_port_priv;
1132
1133 EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
1134 EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
1135
1136 EPHYR_LOG("enter\n");
1137
1138 gc = xcb_generate_id(conn);
1139 xcb_create_gc(conn, gc, scrpriv->win, 0, NULL);
1140 xcb_xv_get_video(conn, port_priv->port_number,
1141 scrpriv->win, gc,
1142 a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1143 a_drw_x, a_drw_y, a_drw_w, a_drw_h);
1144
1145 xcb_free_gc(conn, gc);
1146
1147 EPHYR_LOG("leave\n");
1148 return Success;
1149 }
1150
1151 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,void * a_port_priv)1152 ephyrPutStill(KdScreenInfo * a_info,
1153 DrawablePtr a_drawable,
1154 short a_vid_x, short a_vid_y,
1155 short a_drw_x, short a_drw_y,
1156 short a_vid_w, short a_vid_h,
1157 short a_drw_w, short a_drw_h,
1158 RegionPtr a_clipping_region, void *a_port_priv)
1159 {
1160 EphyrScrPriv *scrpriv = a_info->driver;
1161 xcb_connection_t *conn = hostx_get_xcbconn();
1162 xcb_gcontext_t gc;
1163 EphyrPortPriv *port_priv = a_port_priv;
1164
1165 EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
1166 EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
1167
1168 EPHYR_LOG("enter\n");
1169
1170 gc = xcb_generate_id(conn);
1171 xcb_create_gc(conn, gc, scrpriv->win, 0, NULL);
1172 xcb_xv_put_still(conn, port_priv->port_number,
1173 scrpriv->win, gc,
1174 a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1175 a_drw_x, a_drw_y, a_drw_w, a_drw_h);
1176 xcb_free_gc(conn, gc);
1177
1178 EPHYR_LOG("leave\n");
1179 return Success;
1180 }
1181
1182 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,void * a_port_priv)1183 ephyrGetStill(KdScreenInfo * a_info,
1184 DrawablePtr a_drawable,
1185 short a_vid_x, short a_vid_y,
1186 short a_drw_x, short a_drw_y,
1187 short a_vid_w, short a_vid_h,
1188 short a_drw_w, short a_drw_h,
1189 RegionPtr a_clipping_region, void *a_port_priv)
1190 {
1191 EphyrScrPriv *scrpriv = a_info->driver;
1192 xcb_connection_t *conn = hostx_get_xcbconn();
1193 xcb_gcontext_t gc;
1194 EphyrPortPriv *port_priv = a_port_priv;
1195
1196 EPHYR_RETURN_VAL_IF_FAIL(a_info && a_info->pScreen, BadValue);
1197 EPHYR_RETURN_VAL_IF_FAIL(a_drawable && port_priv, BadValue);
1198
1199 EPHYR_LOG("enter\n");
1200
1201 gc = xcb_generate_id(conn);
1202 xcb_create_gc(conn, gc, scrpriv->win, 0, NULL);
1203 xcb_xv_get_still(conn, port_priv->port_number,
1204 scrpriv->win, gc,
1205 a_vid_x, a_vid_y, a_vid_w, a_vid_h,
1206 a_drw_x, a_drw_y, a_drw_w, a_drw_h);
1207 xcb_free_gc(conn, gc);
1208
1209 EPHYR_LOG("leave\n");
1210 return Success;
1211 }
1212
1213 static int
ephyrQueryImageAttributes(KdScreenInfo * a_info,int a_id,unsigned short * a_w,unsigned short * a_h,int * a_pitches,int * a_offsets)1214 ephyrQueryImageAttributes(KdScreenInfo * a_info,
1215 int a_id,
1216 unsigned short *a_w,
1217 unsigned short *a_h, int *a_pitches, int *a_offsets)
1218 {
1219 xcb_connection_t *conn = hostx_get_xcbconn();
1220 xcb_xv_query_image_attributes_cookie_t cookie;
1221 xcb_xv_query_image_attributes_reply_t *reply;
1222 int image_size = 0;
1223
1224 EPHYR_RETURN_VAL_IF_FAIL(a_w && a_h, FALSE);
1225
1226 EPHYR_LOG("enter: dim (%dx%d), pitches: %p, offsets: %p\n",
1227 *a_w, *a_h, a_pitches, a_offsets);
1228
1229 cookie = xcb_xv_query_image_attributes(conn,
1230 s_base_port_id, a_id,
1231 *a_w, *a_h);
1232 reply = xcb_xv_query_image_attributes_reply(conn, cookie, NULL);
1233 if (!reply)
1234 goto out;
1235
1236 *a_w = reply->width;
1237 *a_h = reply->height;
1238 if (a_pitches && a_offsets) {
1239 memcpy(a_pitches, xcb_xv_query_image_attributes_pitches(reply),
1240 reply->num_planes << 2);
1241 memcpy(a_offsets, xcb_xv_query_image_attributes_offsets(reply),
1242 reply->num_planes << 2);
1243 }
1244 image_size = reply->data_size;
1245
1246 free(reply);
1247
1248 EPHYR_LOG("image size: %d, dim (%dx%d)\n", image_size, *a_w, *a_h);
1249
1250 out:
1251 EPHYR_LOG("leave\n");
1252 return image_size;
1253 }
1254