Bug Summary

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