Bug Summary

File:hw/kdrive/ephyr/hostx.c
Location:line 927, column 27
Description:Access to field 'stride' results in a dereference of a null pointer (loaded from field 'ximg')

Annotated Source Code

1/*
2 * Xephyr - A kdrive X server thats runs in a host X window.
3 * Authored by Matthew Allum <mallum@o-hand.com>
4 *
5 * Copyright © 2004 Nokia
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 Nokia not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. Nokia 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 * NOKIA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL NOKIA 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
26#ifdef HAVE_CONFIG_H1
27#include <kdrive-config.h>
28#endif
29
30#include "hostx.h"
31#include "input.h"
32
33#include <stdlib.h>
34#include <stdio.h>
35#include <unistd.h>
36#include <string.h> /* for memset */
37#include <errno(*__error()).h>
38#include <time.h>
39#include <err.h>
40
41#include <sys/ipc.h>
42#include <sys/shm.h>
43#include <sys/time.h>
44
45#include <X11/keysym.h>
46#include <xcb/xcb.h>
47#include <xcb/xproto.h>
48#include <xcb/xcb_icccm.h>
49#include <xcb/xcb_aux.h>
50#include <xcb/shm.h>
51#include <xcb/xcb_image.h>
52#include <xcb/shape.h>
53#include <xcb/xcb_keysyms.h>
54#include <xcb/randr.h>
55#ifdef XF86DRI
56#include <xcb/xf86dri.h>
57#include <xcb/glx.h>
58#endif /* XF86DRI */
59#ifdef GLAMOR
60#include <epoxy/gl.h>
61#include "glamor.h"
62#include "ephyr_glamor_glx.h"
63#endif
64#include "ephyrlog.h"
65#include "ephyr.h"
66
67struct EphyrHostXVars {
68 char *server_dpy_name;
69 xcb_connection_t *conn;
70 int screen;
71 xcb_visualtype_t *visual;
72 Window winroot;
73 xcb_gcontext_t gc;
74 xcb_render_pictformat_t argb_format;
75 xcb_cursor_t empty_cursor;
76 int depth;
77 Bool use_sw_cursor;
78 Bool use_fullscreen;
79 Bool have_shm;
80
81 int n_screens;
82 KdScreenInfo **screens;
83
84 long damage_debug_msec;
85};
86
87/* memset ( missing> ) instead of below */
88/*static EphyrHostXVars HostX = { "?", 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};*/
89static EphyrHostXVars HostX;
90
91static int HostXWantDamageDebug = 0;
92
93extern EphyrKeySyms ephyrKeySyms;
94
95extern Bool EphyrWantResize;
96
97char *ephyrResName = NULL((void*)0);
98int ephyrResNameFromCmd = 0;
99char *ephyrTitle = NULL((void*)0);
100Bool ephyr_glamor = FALSE0;
101
102static void
103 hostx_set_fullscreen_hint(void);
104
105#define host_depth_matches_server(_vars)(HostX.depth == (_vars)->server_depth) (HostX.depth == (_vars)->server_depth)
106
107int
108hostx_want_screen_geometry(KdScreenInfo *screen, int *width, int *height, int *x, int *y)
109{
110 EphyrScrPriv *scrpriv = screen->driver;
111
112 if (scrpriv && (scrpriv->win_pre_existing != None0L ||
113 scrpriv->output != NULL((void*)0) ||
114 HostX.use_fullscreen == TRUE1)) {
115 *x = scrpriv->win_x;
116 *y = scrpriv->win_y;
117 *width = scrpriv->win_width;
118 *height = scrpriv->win_height;
119 return 1;
120 }
121
122 return 0;
123}
124
125void
126hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry, const char *output)
127{
128 EphyrScrPriv *scrpriv = screen->driver;
129 int index = HostX.n_screens;
130
131 HostX.n_screens += 1;
132 HostX.screens = realloc(HostX.screens,
133 HostX.n_screens * sizeof(HostX.screens[0]));
134 HostX.screens[index] = screen;
135
136 scrpriv->screen = screen;
137 scrpriv->win_pre_existing = win_id;
138 scrpriv->win_explicit_position = use_geometry;
139 scrpriv->output = output;
140}
141
142void
143hostx_set_display_name(char *name)
144{
145 HostX.server_dpy_name = strdup(name);
146}
147
148void
149hostx_set_screen_number(KdScreenInfo *screen, int number)
150{
151 EphyrScrPriv *scrpriv = screen->driver;
152
153 if (scrpriv) {
154 scrpriv->mynum = number;
155 hostx_set_win_title(screen, "");
156 }
157}
158
159void
160hostx_set_win_title(KdScreenInfo *screen, const char *extra_text)
161{
162 EphyrScrPriv *scrpriv = screen->driver;
163
164 if (!scrpriv)
165 return;
166
167 if (ephyrTitle) {
168 xcb_icccm_set_wm_name(HostX.conn,
169 scrpriv->win,
170 XCB_ATOM_STRING,
171 8,
172 strlen(ephyrTitle),
173 ephyrTitle);
174 } else {
175#define BUF_LEN256 256
176 char buf[BUF_LEN256 + 1];
177
178 memset(buf, 0, BUF_LEN + 1)__builtin___memset_chk (buf, 0, 256 + 1, __builtin_object_size
(buf, 0))
;
179 snprintf(buf, BUF_LEN, "Xephyr on %s.%d %s",__builtin___snprintf_chk (buf, 256, 0, __builtin_object_size (
buf, 2 > 1 ? 1 : 0), "Xephyr on %s.%d %s", HostX.server_dpy_name
? HostX.server_dpy_name : ":0", scrpriv->mynum, (extra_text
!= ((void*)0)) ? extra_text : "")
180 HostX.server_dpy_name ? HostX.server_dpy_name : ":0",__builtin___snprintf_chk (buf, 256, 0, __builtin_object_size (
buf, 2 > 1 ? 1 : 0), "Xephyr on %s.%d %s", HostX.server_dpy_name
? HostX.server_dpy_name : ":0", scrpriv->mynum, (extra_text
!= ((void*)0)) ? extra_text : "")
181 scrpriv->mynum, (extra_text != NULL) ? extra_text : "")__builtin___snprintf_chk (buf, 256, 0, __builtin_object_size (
buf, 2 > 1 ? 1 : 0), "Xephyr on %s.%d %s", HostX.server_dpy_name
? HostX.server_dpy_name : ":0", scrpriv->mynum, (extra_text
!= ((void*)0)) ? extra_text : "")
;
182
183 xcb_icccm_set_wm_name(HostX.conn,
184 scrpriv->win,
185 XCB_ATOM_STRING,
186 8,
187 strlen(buf),
188 buf);
189 xcb_flush(HostX.conn);
190 }
191}
192
193int
194hostx_want_host_cursor(void)
195{
196 return !HostX.use_sw_cursor;
197}
198
199void
200hostx_use_sw_cursor(void)
201{
202 HostX.use_sw_cursor = TRUE1;
203}
204
205xcb_cursor_t
206hostx_get_empty_cursor(void)
207{
208 return HostX.empty_cursor;
209}
210
211int
212hostx_want_preexisting_window(KdScreenInfo *screen)
213{
214 EphyrScrPriv *scrpriv = screen->driver;
215
216 if (scrpriv && scrpriv->win_pre_existing) {
217 return 1;
218 }
219 else {
220 return 0;
221 }
222}
223
224void
225hostx_get_output_geometry(const char *output,
226 int *x, int *y,
227 int *width, int *height)
228{
229 int i, name_len = 0, output_found = FALSE0;
230 char *name = NULL((void*)0);
231 xcb_generic_error_t *error;
232 xcb_randr_query_version_cookie_t version_c;
233 xcb_randr_query_version_reply_t *version_r;
234 xcb_randr_get_screen_resources_cookie_t screen_resources_c;
235 xcb_randr_get_screen_resources_reply_t *screen_resources_r;
236 xcb_randr_output_t *randr_outputs;
237 xcb_randr_get_output_info_cookie_t output_info_c;
238 xcb_randr_get_output_info_reply_t *output_info_r;
239 xcb_randr_get_crtc_info_cookie_t crtc_info_c;
240 xcb_randr_get_crtc_info_reply_t *crtc_info_r;
241
242 /* First of all, check for extension */
243 if (!xcb_get_extension_data(HostX.conn, &xcb_randr_id)->present)
244 {
245 fprintf(stderr__stderrp, "\nHost X server does not support RANDR extension (or it's disabled).\n");
246 exit(1);
247 }
248
249 /* Check RandR version */
250 version_c = xcb_randr_query_version(HostX.conn, 1, 2);
251 version_r = xcb_randr_query_version_reply(HostX.conn,
252 version_c,
253 &error);
254
255 if (error != NULL((void*)0) || version_r == NULL((void*)0))
256 {
257 fprintf(stderr__stderrp, "\nFailed to get RandR version supported by host X server.\n");
258 exit(1);
259 }
260 else if (version_r->major_version < 1 || version_r->minor_version < 2)
261 {
262 free(version_r);
263 fprintf(stderr__stderrp, "\nHost X server doesn't support RandR 1.2, needed for -output usage.\n");
264 exit(1);
265 }
266
267 free(version_r);
268
269 /* Get list of outputs from screen resources */
270 screen_resources_c = xcb_randr_get_screen_resources(HostX.conn,
271 HostX.winroot);
272 screen_resources_r = xcb_randr_get_screen_resources_reply(HostX.conn,
273 screen_resources_c,
274 NULL((void*)0));
275 randr_outputs = xcb_randr_get_screen_resources_outputs(screen_resources_r);
276
277 for (i = 0; !output_found && i < screen_resources_r->num_outputs; i++)
278 {
279 /* Get info on the output */
280 output_info_c = xcb_randr_get_output_info(HostX.conn,
281 randr_outputs[i],
282 XCB_CURRENT_TIME0L);
283 output_info_r = xcb_randr_get_output_info_reply(HostX.conn,
284 output_info_c,
285 NULL((void*)0));
286
287 /* Get output name */
288 name_len = xcb_randr_get_output_info_name_length(output_info_r);
289 name = malloc(name_len + 1);
290 strncpy(name, (char*)xcb_randr_get_output_info_name(output_info_r), name_len)__builtin___strncpy_chk (name, (char*)xcb_randr_get_output_info_name
(output_info_r), name_len, __builtin_object_size (name, 2 >
1 ? 1 : 0))
;
291 name[name_len] = '\0';
292
293 if (!strcmp(name, output))
294 {
295 output_found = TRUE1;
296
297 /* Check if output is connected */
298 if (output_info_r->crtc == XCB_NONE0L)
299 {
300 free(name);
301 free(output_info_r);
302 free(screen_resources_r);
303 fprintf(stderr__stderrp, "\nOutput %s is currently disabled (or not connected).\n", output);
304 exit(1);
305 }
306
307 /* Get CRTC from output info */
308 crtc_info_c = xcb_randr_get_crtc_info(HostX.conn,
309 output_info_r->crtc,
310 XCB_CURRENT_TIME0L);
311 crtc_info_r = xcb_randr_get_crtc_info_reply(HostX.conn,
312 crtc_info_c,
313 NULL((void*)0));
314
315 /* Get CRTC geometry */
316 *x = crtc_info_r->x;
317 *y = crtc_info_r->y;
318 *width = crtc_info_r->width;
319 *height = crtc_info_r->height;
320
321 free(crtc_info_r);
322 }
323
324 free(name);
325 free(output_info_r);
326 }
327
328 free(screen_resources_r);
329
330 if (!output_found)
331 {
332 fprintf(stderr__stderrp, "\nOutput %s not available in host X server.\n", output);
333 exit(1);
334 }
335}
336
337void
338hostx_use_fullscreen(void)
339{
340 HostX.use_fullscreen = TRUE1;
341}
342
343int
344hostx_want_fullscreen(void)
345{
346 return HostX.use_fullscreen;
347}
348
349static xcb_intern_atom_cookie_t cookie_WINDOW_STATE,
350 cookie_WINDOW_STATE_FULLSCREEN;
351
352static void
353hostx_set_fullscreen_hint(void)
354{
355 xcb_atom_t atom_WINDOW_STATE, atom_WINDOW_STATE_FULLSCREEN;
356 int index;
357 xcb_intern_atom_reply_t *reply;
358
359 reply = xcb_intern_atom_reply(HostX.conn, cookie_WINDOW_STATE, NULL((void*)0));
360 atom_WINDOW_STATE = reply->atom;
361 free(reply);
362
363 reply = xcb_intern_atom_reply(HostX.conn, cookie_WINDOW_STATE_FULLSCREEN,
364 NULL((void*)0));
365 atom_WINDOW_STATE_FULLSCREEN = reply->atom;
366 free(reply);
367
368 for (index = 0; index < HostX.n_screens; index++) {
369 EphyrScrPriv *scrpriv = HostX.screens[index]->driver;
370 xcb_change_property(HostX.conn,
371 PropModeReplace0,
372 scrpriv->win,
373 atom_WINDOW_STATE,
374 XCB_ATOM_ATOM,
375 32,
376 1,
377 &atom_WINDOW_STATE_FULLSCREEN);
378 }
379}
380
381static void
382hostx_toggle_damage_debug(void)
383{
384 HostXWantDamageDebug ^= 1;
385}
386
387void
388hostx_handle_signal(int signum)
389{
390 hostx_toggle_damage_debug();
391 EPHYR_DBG("Signal caught. Damage Debug:%i\n", HostXWantDamageDebug)do {} while (0);
392}
393
394void
395hostx_use_resname(char *name, int fromcmd)
396{
397 ephyrResName = name;
398 ephyrResNameFromCmd = fromcmd;
399}
400
401void
402hostx_set_title(char *title)
403{
404 ephyrTitle = title;
405}
406
407#ifdef __SUNPRO_C
408/* prevent "Function has no return statement" error for x_io_error_handler */
409#pragma does_not_return(exit)
410#endif
411
412int
413hostx_init(void)
414{
415 uint32_t attrs[2];
416 uint32_t attr_mask = 0;
417 xcb_pixmap_t cursor_pxm;
418 xcb_gcontext_t cursor_gc;
419 uint16_t red, green, blue;
420 uint32_t pixel;
421 int index;
422 char *tmpstr;
423 char *class_hint;
424 size_t class_len;
425 const xcb_query_extension_reply_t *shm_rep;
426 xcb_screen_t *xscreen;
427 xcb_rectangle_t rect = { 0, 0, 1, 1 };
428
429 attrs[0] =
430 XCB_EVENT_MASK_BUTTON_PRESS
431 | XCB_EVENT_MASK_BUTTON_RELEASE
432 | XCB_EVENT_MASK_POINTER_MOTION
433 | XCB_EVENT_MASK_KEY_PRESS
434 | XCB_EVENT_MASK_KEY_RELEASE
435 | XCB_EVENT_MASK_EXPOSURE
436 | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
437 attr_mask |= XCB_CW_EVENT_MASK;
438
439 EPHYR_DBG("mark")do {} while (0);
440#ifdef GLAMOR
441 if (ephyr_glamor)
442 HostX.conn = ephyr_glamor_connect();
443 else
444#endif
445 HostX.conn = xcb_connect(NULL((void*)0), &HostX.screen);
446 if (!HostX.conn || xcb_connection_has_error(HostX.conn)) {
447 fprintf(stderr__stderrp, "\nXephyr cannot open host display. Is DISPLAY set?\n");
448 exit(1);
449 }
450
451 xscreen = xcb_aux_get_screen(HostX.conn, HostX.screen);
452 HostX.winroot = xscreen->root;
453 HostX.gc = xcb_generate_id(HostX.conn);
454 HostX.depth = xscreen->root_depth;
455#ifdef GLAMOR
456 if (ephyr_glamor) {
457 HostX.visual = ephyr_glamor_get_visual();
458 if (HostX.visual->visual_id != xscreen->root_visual) {
459 attrs[1] = xcb_generate_id(HostX.conn);
460 attr_mask |= XCB_CW_COLORMAP;
461 xcb_create_colormap(HostX.conn,
462 XCB_COLORMAP_ALLOC_NONE,
463 attrs[1],
464 HostX.winroot,
465 HostX.visual->visual_id);
466 }
467 } else
468#endif
469 HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
470
471 xcb_create_gc(HostX.conn, HostX.gc, HostX.winroot, 0, NULL((void*)0));
472 cookie_WINDOW_STATE = xcb_intern_atom(HostX.conn, FALSE0,
473 strlen("_NET_WM_STATE"),
474 "_NET_WM_STATE");
475 cookie_WINDOW_STATE_FULLSCREEN =
476 xcb_intern_atom(HostX.conn, FALSE0,
477 strlen("_NET_WM_STATE_FULLSCREEN"),
478 "_NET_WM_STATE_FULLSCREEN");
479
480 for (index = 0; index < HostX.n_screens; index++) {
481 KdScreenInfo *screen = HostX.screens[index];
482 EphyrScrPriv *scrpriv = screen->driver;
483
484 scrpriv->win = xcb_generate_id(HostX.conn);
485 scrpriv->server_depth = HostX.depth;
486 scrpriv->ximg = NULL((void*)0);
487 scrpriv->win_x = 0;
488 scrpriv->win_y = 0;
489
490 if (scrpriv->win_pre_existing != XCB_WINDOW_NONE) {
491 xcb_get_geometry_reply_t *prewin_geom;
492 xcb_get_geometry_cookie_t cookie;
493 xcb_generic_error_t *e = NULL((void*)0);
494
495 /* Get screen size from existing window */
496 cookie = xcb_get_geometry(HostX.conn,
497 scrpriv->win_pre_existing);
498 prewin_geom = xcb_get_geometry_reply(HostX.conn, cookie, &e);
499
500 if (e) {
501 free(e);
502 free(prewin_geom);
503 fprintf (stderr__stderrp, "\nXephyr -parent window' does not exist!\n");
504 exit (1);
505 }
506
507 scrpriv->win_width = prewin_geom->width;
508 scrpriv->win_height = prewin_geom->height;
509
510 free(prewin_geom);
511
512 xcb_create_window(HostX.conn,
513 XCB_COPY_FROM_PARENT0L,
514 scrpriv->win,
515 scrpriv->win_pre_existing,
516 0,0,
517 scrpriv->win_width,
518 scrpriv->win_height,
519 0,
520 XCB_WINDOW_CLASS_COPY_FROM_PARENT,
521 HostX.visual->visual_id,
522 attr_mask,
523 attrs);
524 }
525 else {
526 xcb_create_window(HostX.conn,
527 XCB_COPY_FROM_PARENT0L,
528 scrpriv->win,
529 HostX.winroot,
530 0,0,100,100, /* will resize */
531 0,
532 XCB_WINDOW_CLASS_COPY_FROM_PARENT,
533 HostX.visual->visual_id,
534 attr_mask,
535 attrs);
536
537 hostx_set_win_title(screen,
538 "(ctrl+shift grabs mouse and keyboard)");
539
540 if (HostX.use_fullscreen) {
541 scrpriv->win_width = xscreen->width_in_pixels;
542 scrpriv->win_height = xscreen->height_in_pixels;
543
544 hostx_set_fullscreen_hint();
545 }
546 else if (scrpriv->output) {
547 hostx_get_output_geometry(scrpriv->output,
548 &scrpriv->win_x,
549 &scrpriv->win_y,
550 &scrpriv->win_width,
551 &scrpriv->win_height);
552
553 HostX.use_fullscreen = TRUE1;
554 hostx_set_fullscreen_hint();
555 }
556
557
558 tmpstr = getenv("RESOURCE_NAME");
559 if (tmpstr && (!ephyrResNameFromCmd))
560 ephyrResName = tmpstr;
561 class_len = strlen(ephyrResName) + 1 + strlen("Xephyr") + 1;
562 class_hint = malloc(class_len);
563 if (class_hint) {
564 strcpy(class_hint, ephyrResName)__builtin___strcpy_chk (class_hint, ephyrResName, __builtin_object_size
(class_hint, 2 > 1 ? 1 : 0))
;
565 strcpy(class_hint + strlen(ephyrResName) + 1, "Xephyr")__builtin___strcpy_chk (class_hint + strlen(ephyrResName) + 1
, "Xephyr", __builtin_object_size (class_hint + strlen(ephyrResName
) + 1, 2 > 1 ? 1 : 0))
;
566 xcb_change_property(HostX.conn,
567 XCB_PROP_MODE_REPLACE,
568 scrpriv->win,
569 XCB_ATOM_WM_CLASS,
570 XCB_ATOM_STRING,
571 8,
572 class_len,
573 class_hint);
574 free(class_hint);
575 }
576 }
577 }
578
579 if (!xcb_aux_parse_color("red", &red, &green, &blue)) {
580 xcb_lookup_color_cookie_t c =
581 xcb_lookup_color(HostX.conn, xscreen->default_colormap, 3, "red");
582 xcb_lookup_color_reply_t *reply =
583 xcb_lookup_color_reply(HostX.conn, c, NULL((void*)0));
584 red = reply->exact_red;
585 green = reply->exact_green;
586 blue = reply->exact_blue;
587 free(reply);
588 }
589
590 {
591 xcb_alloc_color_cookie_t c = xcb_alloc_color(HostX.conn,
592 xscreen->default_colormap,
593 red, green, blue);
594 xcb_alloc_color_reply_t *r = xcb_alloc_color_reply(HostX.conn, c, NULL((void*)0));
595 red = r->red;
596 green = r->green;
597 blue = r->blue;
598 pixel = r->pixel;
599 free(r);
600 }
601
602 xcb_change_gc(HostX.conn, HostX.gc, XCB_GC_FOREGROUND, &pixel);
603
604 cursor_pxm = xcb_generate_id(HostX.conn);
605 xcb_create_pixmap(HostX.conn, 1, cursor_pxm, HostX.winroot, 1, 1);
606 cursor_gc = xcb_generate_id(HostX.conn);
607 pixel = 0;
608 xcb_create_gc(HostX.conn, cursor_gc, cursor_pxm,
609 XCB_GC_FOREGROUND, &pixel);
610 xcb_poly_fill_rectangle(HostX.conn, cursor_pxm, cursor_gc, 1, &rect);
611 xcb_free_gc(HostX.conn, cursor_gc);
612 HostX.empty_cursor = xcb_generate_id(HostX.conn);
613 xcb_create_cursor(HostX.conn,
614 HostX.empty_cursor,
615 cursor_pxm, cursor_pxm,
616 0,0,0,
617 0,0,0,
618 1,1);
619 xcb_free_pixmap(HostX.conn, cursor_pxm);
620 if (!hostx_want_host_cursor ()) {
621 CursorVisible = TRUE1;
622 /* Ditch the cursor, we provide our 'own' */
623 for (index = 0; index < HostX.n_screens; index++) {
624 KdScreenInfo *screen = HostX.screens[index];
625 EphyrScrPriv *scrpriv = screen->driver;
626
627 xcb_change_window_attributes(HostX.conn,
628 scrpriv->win,
629 XCB_CW_CURSOR,
630 &HostX.empty_cursor);
631 }
632 }
633
634 /* Try to get share memory ximages for a little bit more speed */
635 shm_rep = xcb_get_extension_data(HostX.conn, &xcb_shm_id);
636 if (!shm_rep || !shm_rep->present || getenv("XEPHYR_NO_SHM")) {
637 fprintf(stderr__stderrp, "\nXephyr unable to use SHM XImages\n");
638 HostX.have_shm = FALSE0;
639 }
640 else {
641 /* Really really check we have shm - better way ?*/
642 xcb_shm_segment_info_t shminfo;
643 xcb_generic_error_t *e;
644 xcb_void_cookie_t cookie;
645 xcb_shm_seg_t shmseg;
646
647 HostX.have_shm = TRUE1;
648
649 shminfo.shmid = shmget(IPC_PRIVATE((key_t)0), 1, IPC_CREAT001000|0777);
650 shminfo.shmaddr = shmat(shminfo.shmid,0,0);
651
652 shmseg = xcb_generate_id(HostX.conn);
653 cookie = xcb_shm_attach_checked(HostX.conn, shmseg, shminfo.shmid,
654 TRUE1);
655 e = xcb_request_check(HostX.conn, cookie);
656
657 if (e) {
658 fprintf(stderr__stderrp, "\nXephyr unable to use SHM XImages\n");
659 HostX.have_shm = FALSE0;
660 free(e);
661 }
662
663 shmdt(shminfo.shmaddr);
664 shmctl(shminfo.shmid, IPC_RMID0, 0);
665 }
666
667 xcb_flush(HostX.conn);
668
669 /* Setup the pause time between paints when debugging updates */
670
671 HostX.damage_debug_msec = 20000; /* 1/50 th of a second */
672
673 if (getenv("XEPHYR_PAUSE")) {
674 HostX.damage_debug_msec = strtol(getenv("XEPHYR_PAUSE"), NULL((void*)0), 0);
675 EPHYR_DBG("pause is %li\n", HostX.damage_debug_msec)do {} while (0);
676 }
677
678 return 1;
679}
680
681int
682hostx_get_depth(void)
683{
684 return HostX.depth;
685}
686
687int
688hostx_get_server_depth(KdScreenInfo *screen)
689{
690 EphyrScrPriv *scrpriv = screen->driver;
691
692 return scrpriv ? scrpriv->server_depth : 0;
693}
694
695int
696hostx_get_bpp(KdScreenInfo *screen)
697{
698 EphyrScrPriv *scrpriv = screen->driver;
699
700 if (!scrpriv)
701 return 0;
702
703 if (host_depth_matches_server(scrpriv)(HostX.depth == (scrpriv)->server_depth))
704 return HostX.visual->bits_per_rgb_value;
705 else
706 return scrpriv->server_depth; /*XXX correct ?*/
707}
708
709void
710hostx_get_visual_masks(KdScreenInfo *screen,
711 CARD32 *rmsk, CARD32 *gmsk, CARD32 *bmsk)
712{
713 EphyrScrPriv *scrpriv = screen->driver;
714
715 if (!scrpriv)
716 return;
717
718 if (host_depth_matches_server(scrpriv)(HostX.depth == (scrpriv)->server_depth)) {
719 *rmsk = HostX.visual->red_mask;
720 *gmsk = HostX.visual->green_mask;
721 *bmsk = HostX.visual->blue_mask;
722 }
723 else if (scrpriv->server_depth == 16) {
724 /* Assume 16bpp 565 */
725 *rmsk = 0xf800;
726 *gmsk = 0x07e0;
727 *bmsk = 0x001f;
728 }
729 else {
730 *rmsk = 0x0;
731 *gmsk = 0x0;
732 *bmsk = 0x0;
733 }
734}
735
736static int
737hostx_calculate_color_shift(unsigned long mask)
738{
739 int shift = 1;
740
741 /* count # of bits in mask */
742 while ((mask = (mask >> 1)))
743 shift++;
744 /* cmap entry is an unsigned char so adjust it by size of that */
745 shift = shift - sizeof(unsigned char) * 8;
746 if (shift < 0)
747 shift = 0;
748 return shift;
749}
750
751void
752hostx_set_cmap_entry(ScreenPtr pScreen, unsigned char idx,
753 unsigned char r, unsigned char g, unsigned char b)
754{
755 KdScreenPriv(pScreen)KdPrivScreenPtr pScreenPriv = ((KdPrivScreenPtr) dixLookupPrivate
(&(pScreen)->devPrivates, (&kdScreenPrivateKeyRec)
))
;
756 KdScreenInfo *screen = pScreenPriv->screen;
757 EphyrScrPriv *scrpriv = screen->driver;
758/* need to calculate the shifts for RGB because server could be BGR. */
759/* XXX Not sure if this is correct for 8 on 16, but this works for 8 on 24.*/
760 static int rshift, bshift, gshift = 0;
761 static int first_time = 1;
762
763 if (first_time) {
764 first_time = 0;
765 rshift = hostx_calculate_color_shift(HostX.visual->red_mask);
766 gshift = hostx_calculate_color_shift(HostX.visual->green_mask);
767 bshift = hostx_calculate_color_shift(HostX.visual->blue_mask);
768 }
769 scrpriv->cmap[idx] = ((r << rshift) & HostX.visual->red_mask) |
770 ((g << gshift) & HostX.visual->green_mask) |
771 ((b << bshift) & HostX.visual->blue_mask);
772}
773
774/**
775 * hostx_screen_init creates the XImage that will contain the front buffer of
776 * the ephyr screen, and possibly offscreen memory.
777 *
778 * @param width width of the screen
779 * @param height height of the screen
780 * @param buffer_height height of the rectangle to be allocated.
781 *
782 * hostx_screen_init() creates an XImage, using MIT-SHM if it's available.
783 * buffer_height can be used to create a larger offscreen buffer, which is used
784 * by fakexa for storing offscreen pixmap data.
785 */
786void *
787hostx_screen_init(KdScreenInfo *screen,
788 int x, int y,
789 int width, int height, int buffer_height,
790 int *bytes_per_line, int *bits_per_pixel)
791{
792 EphyrScrPriv *scrpriv = screen->driver;
793 Bool shm_success = FALSE0;
794
795 if (!scrpriv) {
1
Assuming 'scrpriv' is non-null
2
Taking false branch
796 fprintf(stderr__stderrp, "%s: Error in accessing hostx data\n", __func__);
797 exit(1);
798 }
799
800 EPHYR_DBG("host_screen=%p x=%d, y=%d, wxh=%dx%d, buffer_height=%d",do {} while (0)
801 screen, x, y, width, height, buffer_height)do {} while (0);
802
803 if (scrpriv->ximg != NULL((void*)0)) {
3
Assuming pointer value is null
4
Taking false branch
804 /* Free up the image data if previously used
805 * i.ie called by server reset
806 */
807
808 if (HostX.have_shm) {
809 xcb_shm_detach(HostX.conn, scrpriv->shminfo.shmseg);
810 xcb_image_destroy(scrpriv->ximg);
811 shmdt(scrpriv->shminfo.shmaddr);
812 shmctl(scrpriv->shminfo.shmid, IPC_RMID0, 0);
813 }
814 else {
815 free(scrpriv->ximg->data);
816 scrpriv->ximg->data = NULL((void*)0);
817
818 xcb_image_destroy(scrpriv->ximg);
819 }
820 }
821
822 if (!ephyr_glamor && HostX.have_shm) {
5
Assuming 'ephyr_glamor' is not equal to 0
823 scrpriv->ximg = xcb_image_create_native(HostX.conn,
824 width,
825 buffer_height,
826 XCB_IMAGE_FORMAT_Z_PIXMAP,
827 HostX.depth,
828 NULL((void*)0),
829 ~0,
830 NULL((void*)0));
831
832 scrpriv->shminfo.shmid =
833 shmget(IPC_PRIVATE((key_t)0),
834 scrpriv->ximg->stride * buffer_height,
835 IPC_CREAT001000 | 0777);
836 scrpriv->ximg->data = shmat(scrpriv->shminfo.shmid, 0, 0);
837 scrpriv->shminfo.shmaddr = scrpriv->ximg->data;
838
839 if (scrpriv->ximg->data == (uint8_t *) -1) {
840 EPHYR_DBGdo {} while (0)
841 ("Can't attach SHM Segment, falling back to plain XImages")do {} while (0);
842 HostX.have_shm = FALSE0;
843 xcb_image_destroy (scrpriv->ximg);
844 shmctl(scrpriv->shminfo.shmid, IPC_RMID0, 0);
845 }
846 else {
847 EPHYR_DBG("SHM segment attached %p", scrpriv->shminfo.shmaddr)do {} while (0);
848 scrpriv->shminfo.shmseg = xcb_generate_id(HostX.conn);
849 xcb_shm_attach(HostX.conn,
850 scrpriv->shminfo.shmseg,
851 scrpriv->shminfo.shmid,
852 FALSE0);
853 shm_success = TRUE1;
854 }
855 }
856
857 if (!ephyr_glamor && !shm_success) {
858 EPHYR_DBG("Creating image %dx%d for screen scrpriv=%p\n",do {} while (0)
859 width, buffer_height, scrpriv)do {} while (0);
860 scrpriv->ximg = xcb_image_create_native(HostX.conn,
861 width,
862 buffer_height,
863 XCB_IMAGE_FORMAT_Z_PIXMAP,
864 HostX.depth,
865 NULL((void*)0),
866 ~0,
867 NULL((void*)0));
868
869 /* Match server byte order so that the image can be converted to
870 * the native byte order by xcb_image_put() before drawing */
871 if (host_depth_matches_server(scrpriv)(HostX.depth == (scrpriv)->server_depth))
872 scrpriv->ximg->byte_order = IMAGE_BYTE_ORDER0;
873
874 scrpriv->ximg->data =
875 malloc(scrpriv->ximg->stride * buffer_height);
876 }
877
878 {
879 uint32_t mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
880 uint32_t values[2] = {width, height};
881 xcb_configure_window(HostX.conn, scrpriv->win, mask, values);
882 }
883
884 if (scrpriv->win_pre_existing == None0L && !EphyrWantResize) {
885 /* Ask the WM to keep our size static */
886 xcb_size_hints_t size_hints = {0};
887 size_hints.max_width = size_hints.min_width = width;
888 size_hints.max_height = size_hints.min_height = height;
889 size_hints.flags = (XCB_ICCCM_SIZE_HINT_P_MIN_SIZE |
890 XCB_ICCCM_SIZE_HINT_P_MAX_SIZE);
891 xcb_icccm_set_wm_normal_hints(HostX.conn, scrpriv->win,
892 &size_hints);
893 }
894
895 xcb_map_window(HostX.conn, scrpriv->win);
896
897 /* Set explicit window position if it was informed in
898 * -screen option (WxH+X or WxH+X+Y). Otherwise, accept the
899 * position set by WM.
900 * The trick here is putting this code after xcb_map_window() call,
901 * so these values won't be overriden by WM. */
902 if (scrpriv->win_explicit_position)
6
Taking false branch
903 {
904 uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
905 uint32_t values[2] = {x, y};
906 xcb_configure_window(HostX.conn, scrpriv->win, mask, values);
907 }
908
909
910 xcb_aux_sync(HostX.conn);
911
912 scrpriv->win_width = width;
913 scrpriv->win_height = height;
914 scrpriv->win_x = x;
915 scrpriv->win_y = y;
916
917#ifdef GLAMOR
918 if (ephyr_glamor) {
919 *bytes_per_line = 0;
920 *bits_per_pixel = 0;
921 ephyr_glamor_set_window_size(scrpriv->glamor,
922 scrpriv->win_width, scrpriv->win_height);
923 return NULL((void*)0);
924 } else
925#endif
926 if (host_depth_matches_server(scrpriv)(HostX.depth == (scrpriv)->server_depth)) {
7
Taking true branch
927 *bytes_per_line = scrpriv->ximg->stride;
8
Access to field 'stride' results in a dereference of a null pointer (loaded from field 'ximg')
928 *bits_per_pixel = scrpriv->ximg->bpp;
929
930 EPHYR_DBG("Host matches server")do {} while (0);
931 return scrpriv->ximg->data;
932 }
933 else {
934 int bytes_per_pixel = scrpriv->server_depth >> 3;
935 int stride = (width * bytes_per_pixel + 0x3) & ~0x3;
936
937 *bytes_per_line = stride;
938 *bits_per_pixel = scrpriv->server_depth;
939
940 EPHYR_DBG("server bpp %i", bytes_per_pixel)do {} while (0);
941 scrpriv->fb_data = malloc (stride * buffer_height);
942 return scrpriv->fb_data;
943 }
944}
945
946static void hostx_paint_debug_rect(KdScreenInfo *screen,
947 int x, int y, int width, int height);
948
949void
950hostx_paint_rect(KdScreenInfo *screen,
951 int sx, int sy, int dx, int dy, int width, int height)
952{
953 EphyrScrPriv *scrpriv = screen->driver;
954
955 EPHYR_DBG("painting in screen %d\n", scrpriv->mynum)do {} while (0);
956
957#ifdef GLAMOR
958 if (ephyr_glamor) {
959 BoxRec box;
960 RegionRec region;
961
962 box.x1 = dx;
963 box.y1 = dy;
964 box.x2 = dx + width;
965 box.y2 = dy + height;
966
967 RegionInit(&region, &box, 1);
968 ephyr_glamor_damage_redisplay(scrpriv->glamor, &region);
969 RegionUninit(&region);
970 return;
971 }
972#endif
973
974 /*
975 * Copy the image data updated by the shadow layer
976 * on to the window
977 */
978
979 if (HostXWantDamageDebug) {
980 hostx_paint_debug_rect(screen, dx, dy, width, height);
981 }
982
983 /*
984 * If the depth of the ephyr server is less than that of the host,
985 * the kdrive fb does not point to the ximage data but to a buffer
986 * ( fb_data ), we shift the various bits from this onto the XImage
987 * so they match the host.
988 *
989 * Note, This code is pretty new ( and simple ) so may break on
990 * endian issues, 32 bpp host etc.
991 * Not sure if 8bpp case is right either.
992 * ... and it will be slower than the matching depth case.
993 */
994
995 if (!host_depth_matches_server(scrpriv)(HostX.depth == (scrpriv)->server_depth)) {
996 int x, y, idx, bytes_per_pixel = (scrpriv->server_depth >> 3);
997 int stride = (scrpriv->win_width * bytes_per_pixel + 0x3) & ~0x3;
998 unsigned char r, g, b;
999 unsigned long host_pixel;
1000
1001 EPHYR_DBG("Unmatched host depth scrpriv=%p\n", scrpriv)do {} while (0);
1002 for (y = sy; y < sy + height; y++)
1003 for (x = sx; x < sx + width; x++) {
1004 idx = y * stride + x * bytes_per_pixel;
1005
1006 switch (scrpriv->server_depth) {
1007 case 16:
1008 {
1009 unsigned short pixel =
1010 *(unsigned short *) (scrpriv->fb_data + idx);
1011
1012 r = ((pixel & 0xf800) >> 8);
1013 g = ((pixel & 0x07e0) >> 3);
1014 b = ((pixel & 0x001f) << 3);
1015
1016 host_pixel = (r << 16) | (g << 8) | (b);
1017
1018 xcb_image_put_pixel(scrpriv->ximg, x, y, host_pixel);
1019 break;
1020 }
1021 case 8:
1022 {
1023 unsigned char pixel =
1024 *(unsigned char *) (scrpriv->fb_data + idx);
1025 xcb_image_put_pixel(scrpriv->ximg, x, y,
1026 scrpriv->cmap[pixel]);
1027 break;
1028 }
1029 default:
1030 break;
1031 }
1032 }
1033 }
1034
1035 if (HostX.have_shm) {
1036 xcb_image_shm_put(HostX.conn, scrpriv->win,
1037 HostX.gc, scrpriv->ximg,
1038 scrpriv->shminfo,
1039 sx, sy, dx, dy, width, height, FALSE0);
1040 }
1041 else {
1042 xcb_image_t *subimg = xcb_image_subimage(scrpriv->ximg, sx, sy,
1043 width, height, 0, 0, 0);
1044 xcb_image_t *img = xcb_image_native(HostX.conn, subimg, 1);
1045 xcb_image_put(HostX.conn, scrpriv->win, HostX.gc, img, dx, dy, 0);
1046 if (subimg != img)
1047 xcb_image_destroy(img);
1048 xcb_image_destroy(subimg);
1049 }
1050
1051 xcb_aux_sync(HostX.conn);
1052}
1053
1054static void
1055hostx_paint_debug_rect(KdScreenInfo *screen,
1056 int x, int y, int width, int height)
1057{
1058 EphyrScrPriv *scrpriv = screen->driver;
1059 struct timespec tspec;
1060 xcb_rectangle_t rect = { .x = x, .y = y, .width = width, .height = height };
1061 xcb_void_cookie_t cookie;
1062 xcb_generic_error_t *e;
1063
1064 tspec.tv_sec = HostX.damage_debug_msec / (1000000);
1065 tspec.tv_nsec = (HostX.damage_debug_msec % 1000000) * 1000;
1066
1067 EPHYR_DBG("msec: %li tv_sec %li, tv_msec %li",do {} while (0)
1068 HostX.damage_debug_msec, tspec.tv_sec, tspec.tv_nsec)do {} while (0);
1069
1070 /* fprintf(stderr, "Xephyr updating: %i+%i %ix%i\n", x, y, width, height); */
1071
1072 cookie = xcb_poly_fill_rectangle_checked(HostX.conn, scrpriv->win,
1073 HostX.gc, 1, &rect);
1074 e = xcb_request_check(HostX.conn, cookie);
1075 free(e);
1076
1077 /* nanosleep seems to work better than usleep for me... */
1078 nanosleep(&tspec, NULL((void*)0));
1079}
1080
1081void
1082hostx_load_keymap(void)
1083{
1084 int min_keycode, max_keycode;
1085
1086 min_keycode = xcb_get_setup(HostX.conn)->min_keycode;
1087 max_keycode = xcb_get_setup(HostX.conn)->max_keycode;
1088
1089 EPHYR_DBG("min: %d, max: %d", min_keycode, max_keycode)do {} while (0);
1090
1091 ephyrKeySyms.minKeyCode = min_keycode;
1092 ephyrKeySyms.maxKeyCode = max_keycode;
1093}
1094
1095xcb_connection_t *
1096hostx_get_xcbconn(void)
1097{
1098 return HostX.conn;
1099}
1100
1101int
1102hostx_get_screen(void)
1103{
1104 return HostX.screen;
1105}
1106
1107int
1108hostx_get_window(int a_screen_number)
1109{
1110 EphyrScrPriv *scrpriv;
1111 if (a_screen_number < 0 || a_screen_number >= HostX.n_screens) {
1112 EPHYR_LOG_ERROR("bad screen number:%d\n", a_screen_number);
1113 return 0;
1114 }
1115 scrpriv = HostX.screens[a_screen_number]->driver;
1116 return scrpriv->win;
1117}
1118
1119int
1120hostx_get_window_attributes(int a_window, EphyrHostWindowAttributes * a_attrs)
1121{
1122 xcb_get_geometry_cookie_t geom_cookie;
1123 xcb_get_window_attributes_cookie_t attr_cookie;
1124 xcb_get_geometry_reply_t *geom_reply;
1125 xcb_get_window_attributes_reply_t *attr_reply;
1126
1127 geom_cookie = xcb_get_geometry(HostX.conn, a_window);
1128 attr_cookie = xcb_get_window_attributes(HostX.conn, a_window);
1129 geom_reply = xcb_get_geometry_reply(HostX.conn, geom_cookie, NULL((void*)0));
1130 attr_reply = xcb_get_window_attributes_reply(HostX.conn, attr_cookie, NULL((void*)0));
1131
1132 a_attrs->x = geom_reply->x;
1133 a_attrs->y = geom_reply->y;
1134 a_attrs->width = geom_reply->width;
1135 a_attrs->height = geom_reply->height;
1136 a_attrs->visualid = attr_reply->visual;
1137
1138 free(geom_reply);
1139 free(attr_reply);
1140 return TRUE1;
1141}
1142
1143int
1144hostx_get_visuals_info(EphyrHostVisualInfo ** a_visuals, int *a_num_entries)
1145{
1146 Bool is_ok = FALSE0;
1147 EphyrHostVisualInfo *host_visuals = NULL((void*)0);
1148 int nb_items = 0, i = 0, screen_num;
1149 xcb_screen_iterator_t screens;
1150 xcb_depth_iterator_t depths;
1151
1152 EPHYR_RETURN_VAL_IF_FAIL(a_visuals && a_num_entries, FALSE)if (!(a_visuals && a_num_entries)) {;return 0;};
1153 EPHYR_LOG("enter\n");
1154
1155 screens = xcb_setup_roots_iterator(xcb_get_setup(HostX.conn));
1156 for (screen_num = 0; screens.rem; screen_num++, xcb_screen_next(&screens)) {
1157 depths = xcb_screen_allowed_depths_iterator(screens.data);
1158 for (; depths.rem; xcb_depth_next(&depths)) {
1159 xcb_visualtype_t *visuals = xcb_depth_visuals(depths.data);
1160 EphyrHostVisualInfo *tmp_visuals =
1161 realloc(host_visuals,
1162 (nb_items + depths.data->visuals_len)
1163 * sizeof(EphyrHostVisualInfo));
1164 if (!tmp_visuals) {
1165 goto out;
1166 }
1167 host_visuals = tmp_visuals;
1168 for (i = 0; i < depths.data->visuals_len; i++) {
1169 host_visuals[nb_items + i].visualid = visuals[i].visual_id;
1170 host_visuals[nb_items + i].screen = screen_num;
1171 host_visuals[nb_items + i].depth = depths.data->depth;
1172 host_visuals[nb_items + i].class = visuals[i]._class;
1173 host_visuals[nb_items + i].red_mask = visuals[i].red_mask;
1174 host_visuals[nb_items + i].green_mask = visuals[i].green_mask;
1175 host_visuals[nb_items + i].blue_mask = visuals[i].blue_mask;
1176 host_visuals[nb_items + i].colormap_size = visuals[i].colormap_entries;
1177 host_visuals[nb_items + i].bits_per_rgb = visuals[i].bits_per_rgb_value;
1178 }
1179 nb_items += depths.data->visuals_len;
1180 }
1181 }
1182
1183 EPHYR_LOG("host advertises %d visuals\n", nb_items);
1184 *a_visuals = host_visuals;
1185 *a_num_entries = nb_items;
1186 host_visuals = NULL((void*)0);
1187
1188 is_ok = TRUE1;
1189out:
1190 free(host_visuals);
1191 host_visuals = NULL((void*)0);
1192 EPHYR_LOG("leave\n");
1193 return is_ok;
1194
1195}
1196
1197int
1198hostx_create_window(int a_screen_number,
1199 EphyrBox * a_geometry,
1200 int a_visual_id, int *a_host_peer /*out parameter */ )
1201{
1202 Bool is_ok = FALSE0;
1203 xcb_window_t win;
1204 int winmask = 0;
1205 uint32_t attrs[2];
1206 xcb_screen_t *screen = xcb_aux_get_screen(HostX.conn, hostx_get_screen());
1207 xcb_visualtype_t *visual;
1208 int depth = 0;
1209 EphyrScrPriv *scrpriv = HostX.screens[a_screen_number]->driver;
1210
1211 EPHYR_RETURN_VAL_IF_FAIL(screen && a_geometry, FALSE)if (!(screen && a_geometry)) {;return 0;};
1212
1213 EPHYR_LOG("enter\n");
1214
1215 visual = xcb_aux_find_visual_by_id(screen, a_visual_id);
1216 if (!visual) {
1217 EPHYR_LOG_ERROR ("argh, could not find a remote visual with id:%d\n",
1218 a_visual_id);
1219 goto out;
1220 }
1221 depth = xcb_aux_get_depth_of_visual(screen, a_visual_id);
1222
1223 winmask = XCB_CW_EVENT_MASK | XCB_CW_COLORMAP;
1224 attrs[0] = XCB_EVENT_MASK_BUTTON_PRESS
1225 |XCB_EVENT_MASK_BUTTON_RELEASE
1226 |XCB_EVENT_MASK_POINTER_MOTION
1227 |XCB_EVENT_MASK_KEY_PRESS
1228 |XCB_EVENT_MASK_KEY_RELEASE
1229 |XCB_EVENT_MASK_EXPOSURE;
1230 attrs[1] = xcb_generate_id(HostX.conn);
1231 xcb_create_colormap(HostX.conn,
1232 XCB_COLORMAP_ALLOC_NONE,
1233 attrs[1],
1234 hostx_get_window(a_screen_number),
1235 a_visual_id);
1236
1237 win = xcb_generate_id(HostX.conn);
1238 xcb_create_window(HostX.conn,
1239 depth,
1240 win,
1241 hostx_get_window (a_screen_number),
1242 a_geometry->x, a_geometry->y,
1243 a_geometry->width, a_geometry->height, 0,
1244 XCB_WINDOW_CLASS_COPY_FROM_PARENT,
1245 a_visual_id, winmask, attrs);
1246
1247 if (scrpriv->peer_win == XCB_NONE0L) {
1248 scrpriv->peer_win = win;
1249 }
1250 else {
1251 EPHYR_LOG_ERROR("multiple peer windows created for same screen\n");
1252 }
1253 xcb_flush(HostX.conn);
1254 xcb_map_window(HostX.conn, win);
1255 *a_host_peer = win;
1256 is_ok = TRUE1;
1257 out:
1258 EPHYR_LOG("leave\n");
1259 return is_ok;
1260}
1261
1262int
1263hostx_destroy_window(int a_win)
1264{
1265 xcb_destroy_window(HostX.conn, a_win);
1266 xcb_flush(HostX.conn);
1267 return TRUE1;
1268}
1269
1270int
1271hostx_set_window_geometry(int a_win, EphyrBox * a_geo)
1272{
1273 uint32_t mask = XCB_CONFIG_WINDOW_X
1274 | XCB_CONFIG_WINDOW_Y
1275 | XCB_CONFIG_WINDOW_WIDTH
1276 | XCB_CONFIG_WINDOW_HEIGHT;
1277 uint32_t values[4];
1278
1279 EPHYR_RETURN_VAL_IF_FAIL(a_geo, FALSE)if (!(a_geo)) {;return 0;};
1280
1281 EPHYR_LOG("enter. x,y,w,h:(%d,%d,%d,%d)\n",
1282 a_geo->x, a_geo->y, a_geo->width, a_geo->height);
1283
1284 values[0] = a_geo->x;
1285 values[1] = a_geo->y;
1286 values[2] = a_geo->width;
1287 values[3] = a_geo->height;
1288 xcb_configure_window(HostX.conn, a_win, mask, values);
1289
1290 EPHYR_LOG("leave\n");
1291 return TRUE1;
1292}
1293
1294int
1295hostx_set_window_bounding_rectangles(int a_window,
1296 EphyrRect * a_rects, int a_num_rects)
1297{
1298 Bool is_ok = FALSE0;
1299 int i = 0;
1300 xcb_rectangle_t *rects = NULL((void*)0);
1301
1302 EPHYR_RETURN_VAL_IF_FAIL(a_rects, FALSE)if (!(a_rects)) {;return 0;};
1303
1304 EPHYR_LOG("enter. num rects:%d\n", a_num_rects);
1305
1306 rects = calloc(a_num_rects, sizeof (xcb_rectangle_t));
1307 if (!rects)
1308 goto out;
1309 for (i = 0; i < a_num_rects; i++) {
1310 rects[i].x = a_rects[i].x1;
1311 rects[i].y = a_rects[i].y1;
1312 rects[i].width = abs(a_rects[i].x2 - a_rects[i].x1);
1313 rects[i].height = abs(a_rects[i].y2 - a_rects[i].y1);
1314 EPHYR_LOG("borders clipped to rect[x:%d,y:%d,w:%d,h:%d]\n",
1315 rects[i].x, rects[i].y, rects[i].width, rects[i].height);
1316 }
1317 xcb_shape_rectangles(HostX.conn,
1318 XCB_SHAPE_SO_SET,
1319 XCB_SHAPE_SK_BOUNDING,
1320 XCB_CLIP_ORDERING_YX_BANDED,
1321 a_window,
1322 0, 0,
1323 a_num_rects,
1324 rects);
1325 is_ok = TRUE1;
1326
1327out:
1328 free(rects);
1329 rects = NULL((void*)0);
1330 EPHYR_LOG("leave\n");
1331 return is_ok;
1332}
1333
1334#ifdef XF86DRI
1335typedef struct {
1336 int is_valid;
1337 int local_id;
1338 int remote_id;
1339} ResourcePair;
1340
1341#define RESOURCE_PEERS_SIZE 1024*10
1342static ResourcePair resource_peers[RESOURCE_PEERS_SIZE];
1343
1344int
1345hostx_allocate_resource_id_peer(int a_local_resource_id,
1346 int *a_remote_resource_id)
1347{
1348 int i = 0;
1349 ResourcePair *peer = NULL((void*)0);
1350
1351 /*
1352 * first make sure a resource peer
1353 * does not exist already for
1354 * a_local_resource_id
1355 */
1356 for (i = 0; i < RESOURCE_PEERS_SIZE; i++) {
1357 if (resource_peers[i].is_valid
1358 && resource_peers[i].local_id == a_local_resource_id) {
1359 peer = &resource_peers[i];
1360 break;
1361 }
1362 }
1363 /*
1364 * find one free peer entry, an feed it with
1365 */
1366 if (!peer) {
1367 for (i = 0; i < RESOURCE_PEERS_SIZE; i++) {
1368 if (!resource_peers[i].is_valid) {
1369 peer = &resource_peers[i];
1370 break;
1371 }
1372 }
1373 if (peer) {
1374 peer->remote_id = xcb_generate_id(HostX.conn);
1375 peer->local_id = a_local_resource_id;
1376 peer->is_valid = TRUE1;
1377 }
1378 }
1379 if (peer) {
1380 *a_remote_resource_id = peer->remote_id;
1381 return TRUE1;
1382 }
1383 return FALSE0;
1384}
1385
1386int
1387hostx_get_resource_id_peer(int a_local_resource_id, int *a_remote_resource_id)
1388{
1389 int i = 0;
1390 ResourcePair *peer = NULL((void*)0);
1391
1392 for (i = 0; i < RESOURCE_PEERS_SIZE; i++) {
1393 if (resource_peers[i].is_valid
1394 && resource_peers[i].local_id == a_local_resource_id) {
1395 peer = &resource_peers[i];
1396 break;
1397 }
1398 }
1399 if (peer) {
1400 *a_remote_resource_id = peer->remote_id;
1401 return TRUE1;
1402 }
1403 return FALSE0;
1404}
1405
1406#endif /* XF86DRI */
1407
1408#ifdef GLAMOR
1409Bool
1410ephyr_glamor_init(ScreenPtr screen)
1411{
1412 KdScreenPriv(screen)KdPrivScreenPtr pScreenPriv = ((KdPrivScreenPtr) dixLookupPrivate
(&(screen)->devPrivates, (&kdScreenPrivateKeyRec))
)
;
1413 KdScreenInfo *kd_screen = pScreenPriv->screen;
1414 EphyrScrPriv *scrpriv = kd_screen->driver;
1415
1416 scrpriv->glamor = ephyr_glamor_glx_screen_init(scrpriv->win);
1417 ephyr_glamor_set_window_size(scrpriv->glamor,
1418 scrpriv->win_width, scrpriv->win_height);
1419
1420 if (!glamor_init(screen,
1421 GLAMOR_USE_SCREEN |
1422 GLAMOR_USE_PICTURE_SCREEN)) {
1423 FatalError("Failed to initialize glamor\n");
1424 return FALSE0;
1425 }
1426
1427 return TRUE1;
1428}
1429
1430Bool
1431ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
1432{
1433 KdScreenPriv(pScreen)KdPrivScreenPtr pScreenPriv = ((KdPrivScreenPtr) dixLookupPrivate
(&(pScreen)->devPrivates, (&kdScreenPrivateKeyRec)
))
;
1434 KdScreenInfo *kd_screen = pScreenPriv->screen;
1435 EphyrScrPriv *scrpriv = kd_screen->driver;
1436 PixmapPtr screen_pixmap;
1437 uint32_t tex;
1438
1439 if (!ephyr_glamor)
1440 return TRUE1;
1441
1442 /* kdrive's fbSetupScreen() told mi to have
1443 * miCreateScreenResources() (which is called before this) make a
1444 * scratch pixmap wrapping ephyr-glamor's NULL
1445 * KdScreenInfo->fb.framebuffer.
1446 *
1447 * We want a real (texture-based) screen pixmap at this point.
1448 * This is what glamor will render into, and we'll then texture
1449 * out of that into the host's window to present the results.
1450 *
1451 * Thus, delete the current screen pixmap, and put a fresh one in.
1452 */
1453 screen_pixmap = pScreen->GetScreenPixmap(pScreen);
1454 pScreen->DestroyPixmap(screen_pixmap);
1455
1456 screen_pixmap = pScreen->CreatePixmap(pScreen,
1457 pScreen->width,
1458 pScreen->height,
1459 pScreen->rootDepth,
1460 GLAMOR_CREATE_NO_LARGE);
1461
1462 pScreen->SetScreenPixmap(screen_pixmap);
1463
1464 /* Tell the GLX code what to GL texture to read from. */
1465 tex = glamor_get_pixmap_texture(screen_pixmap);
1466 ephyr_glamor_set_texture(scrpriv->glamor, tex);
1467
1468 return TRUE1;
1469}
1470
1471void
1472ephyr_glamor_enable(ScreenPtr screen)
1473{
1474}
1475
1476void
1477ephyr_glamor_disable(ScreenPtr screen)
1478{
1479}
1480
1481void
1482ephyr_glamor_fini(ScreenPtr screen)
1483{
1484 KdScreenPriv(screen)KdPrivScreenPtr pScreenPriv = ((KdPrivScreenPtr) dixLookupPrivate
(&(screen)->devPrivates, (&kdScreenPrivateKeyRec))
)
;
1485 KdScreenInfo *kd_screen = pScreenPriv->screen;
1486 EphyrScrPriv *scrpriv = kd_screen->driver;
1487
1488 glamor_fini(screen);
1489 ephyr_glamor_glx_screen_fini(scrpriv->glamor);
1490 scrpriv->glamor = NULL((void*)0);
1491}
1492#endif