Commit | Line | Data |
---|---|---|
a09e091a JB |
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 | * This file is heavily copied from hw/xfree86/dri/xf86dri.c | |
26 | * | |
27 | * Authors: | |
28 | * Dodji Seketeli <dodji@openedhand.com> | |
29 | */ | |
30 | ||
31 | #ifdef HAVE_CONFIG_H | |
32 | #include <kdrive-config.h> | |
33 | #endif | |
34 | ||
35 | #include <string.h> | |
36 | ||
37 | #include <X11/X.h> | |
38 | #include <X11/Xproto.h> | |
39 | #define _XF86DRI_SERVER_ | |
40 | #include <X11/dri/xf86dri.h> | |
41 | #include <X11/dri/xf86driproto.h> | |
42 | #include <xcb/xcb.h> | |
43 | #include <xcb/shape.h> | |
44 | #include <xcb/xf86dri.h> | |
45 | #include "misc.h" | |
46 | #include "privates.h" | |
47 | #include "dixstruct.h" | |
48 | #include "extnsionst.h" | |
49 | #include "colormapst.h" | |
50 | #include "cursorstr.h" | |
51 | #include "scrnintstr.h" | |
52 | #include "windowstr.h" | |
53 | #include "servermd.h" | |
54 | #include "swaprep.h" | |
55 | #include "ephyrdri.h" | |
56 | #include "ephyrdriext.h" | |
57 | #include "hostx.h" | |
58 | #define _HAVE_XALLOC_DECLS | |
59 | #include "ephyrlog.h" | |
60 | #include "protocol-versions.h" | |
61 | ||
62 | typedef struct { | |
63 | int foo; | |
64 | } EphyrDRIWindowPrivRec; | |
65 | typedef EphyrDRIWindowPrivRec *EphyrDRIWindowPrivPtr; | |
66 | ||
67 | typedef struct { | |
68 | CreateWindowProcPtr CreateWindow; | |
69 | DestroyWindowProcPtr DestroyWindow; | |
70 | MoveWindowProcPtr MoveWindow; | |
71 | PositionWindowProcPtr PositionWindow; | |
72 | ClipNotifyProcPtr ClipNotify; | |
73 | } EphyrDRIScreenPrivRec; | |
74 | typedef EphyrDRIScreenPrivRec *EphyrDRIScreenPrivPtr; | |
75 | ||
76 | static int DRIErrorBase; | |
77 | ||
78 | static Bool ephyrDRIScreenInit(ScreenPtr a_screen); | |
79 | static Bool ephyrDRICreateWindow(WindowPtr a_win); | |
80 | static Bool ephyrDRIDestroyWindow(WindowPtr a_win); | |
81 | static void ephyrDRIMoveWindow(WindowPtr a_win, | |
82 | int a_x, int a_y, | |
83 | WindowPtr a_siblings, VTKind a_kind); | |
84 | static Bool ephyrDRIPositionWindow(WindowPtr a_win, int x, int y); | |
85 | static void ephyrDRIClipNotify(WindowPtr a_win, int a_x, int a_y); | |
86 | ||
87 | static Bool EphyrMirrorHostVisuals(ScreenPtr a_screen); | |
88 | static Bool destroyHostPeerWindow(const WindowPtr a_win); | |
89 | static Bool findWindowPairFromLocal(WindowPtr a_local, | |
90 | EphyrWindowPair ** a_pair); | |
91 | ||
92 | static unsigned char DRIReqCode = 0; | |
93 | ||
94 | static DevPrivateKeyRec ephyrDRIWindowKeyRec; | |
95 | ||
96 | #define ephyrDRIWindowKey (&ephyrDRIWindowKeyRec) | |
97 | static DevPrivateKeyRec ephyrDRIScreenKeyRec; | |
98 | ||
99 | #define ephyrDRIScreenKey (&ephyrDRIScreenKeyRec) | |
100 | ||
101 | #define GET_EPHYR_DRI_WINDOW_PRIV(win) ((EphyrDRIWindowPrivPtr) \ | |
102 | dixLookupPrivate(&(win)->devPrivates, ephyrDRIWindowKey)) | |
103 | #define GET_EPHYR_DRI_SCREEN_PRIV(screen) ((EphyrDRIScreenPrivPtr) \ | |
104 | dixLookupPrivate(&(screen)->devPrivates, ephyrDRIScreenKey)) | |
105 | ||
106 | static Bool | |
107 | ephyrDRIScreenInit(ScreenPtr a_screen) | |
108 | { | |
109 | Bool is_ok = FALSE; | |
110 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
111 | ||
112 | EPHYR_RETURN_VAL_IF_FAIL(a_screen, FALSE); | |
113 | ||
114 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(a_screen); | |
115 | EPHYR_RETURN_VAL_IF_FAIL(screen_priv, FALSE); | |
116 | ||
117 | screen_priv->CreateWindow = a_screen->CreateWindow; | |
118 | screen_priv->DestroyWindow = a_screen->DestroyWindow; | |
119 | screen_priv->MoveWindow = a_screen->MoveWindow; | |
120 | screen_priv->PositionWindow = a_screen->PositionWindow; | |
121 | screen_priv->ClipNotify = a_screen->ClipNotify; | |
122 | ||
123 | a_screen->CreateWindow = ephyrDRICreateWindow; | |
124 | a_screen->DestroyWindow = ephyrDRIDestroyWindow; | |
125 | a_screen->MoveWindow = ephyrDRIMoveWindow; | |
126 | a_screen->PositionWindow = ephyrDRIPositionWindow; | |
127 | a_screen->ClipNotify = ephyrDRIClipNotify; | |
128 | ||
129 | is_ok = TRUE; | |
130 | ||
131 | return is_ok; | |
132 | } | |
133 | ||
134 | static Bool | |
135 | ephyrDRICreateWindow(WindowPtr a_win) | |
136 | { | |
137 | Bool is_ok = FALSE; | |
138 | ScreenPtr screen = NULL; | |
139 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
140 | ||
141 | EPHYR_RETURN_VAL_IF_FAIL(a_win, FALSE); | |
142 | screen = a_win->drawable.pScreen; | |
143 | EPHYR_RETURN_VAL_IF_FAIL(screen, FALSE); | |
144 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(screen); | |
145 | EPHYR_RETURN_VAL_IF_FAIL(screen_priv && screen_priv->CreateWindow, FALSE); | |
146 | ||
147 | EPHYR_LOG("enter. win:%p\n", a_win); | |
148 | ||
149 | screen->CreateWindow = screen_priv->CreateWindow; | |
150 | is_ok = (*screen->CreateWindow) (a_win); | |
151 | screen->CreateWindow = ephyrDRICreateWindow; | |
152 | ||
153 | if (is_ok) { | |
154 | dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); | |
155 | } | |
156 | return is_ok; | |
157 | } | |
158 | ||
159 | static Bool | |
160 | ephyrDRIDestroyWindow(WindowPtr a_win) | |
161 | { | |
162 | Bool is_ok = FALSE; | |
163 | ScreenPtr screen = NULL; | |
164 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
165 | ||
166 | EPHYR_RETURN_VAL_IF_FAIL(a_win, FALSE); | |
167 | screen = a_win->drawable.pScreen; | |
168 | EPHYR_RETURN_VAL_IF_FAIL(screen, FALSE); | |
169 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(screen); | |
170 | EPHYR_RETURN_VAL_IF_FAIL(screen_priv && screen_priv->DestroyWindow, FALSE); | |
171 | ||
172 | screen->DestroyWindow = screen_priv->DestroyWindow; | |
173 | if (screen->DestroyWindow) { | |
174 | is_ok = (*screen->DestroyWindow) (a_win); | |
175 | } | |
176 | screen->DestroyWindow = ephyrDRIDestroyWindow; | |
177 | ||
178 | if (is_ok) { | |
179 | EphyrDRIWindowPrivPtr win_priv = GET_EPHYR_DRI_WINDOW_PRIV(a_win); | |
180 | ||
181 | if (win_priv) { | |
182 | destroyHostPeerWindow(a_win); | |
183 | free(win_priv); | |
184 | dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, NULL); | |
185 | EPHYR_LOG("destroyed the remote peer window\n"); | |
186 | } | |
187 | } | |
188 | return is_ok; | |
189 | } | |
190 | ||
191 | static void | |
192 | ephyrDRIMoveWindow(WindowPtr a_win, | |
193 | int a_x, int a_y, WindowPtr a_siblings, VTKind a_kind) | |
194 | { | |
195 | ScreenPtr screen = NULL; | |
196 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
197 | EphyrDRIWindowPrivPtr win_priv = NULL; | |
198 | EphyrWindowPair *pair = NULL; | |
199 | EphyrBox geo; | |
200 | int x = 0, y = 0; /*coords relative to parent window */ | |
201 | ||
202 | EPHYR_RETURN_IF_FAIL(a_win); | |
203 | ||
204 | EPHYR_LOG("enter\n"); | |
205 | screen = a_win->drawable.pScreen; | |
206 | EPHYR_RETURN_IF_FAIL(screen); | |
207 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(screen); | |
208 | EPHYR_RETURN_IF_FAIL(screen_priv && screen_priv->MoveWindow); | |
209 | ||
210 | screen->MoveWindow = screen_priv->MoveWindow; | |
211 | if (screen->MoveWindow) { | |
212 | (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind); | |
213 | } | |
214 | screen->MoveWindow = ephyrDRIMoveWindow; | |
215 | ||
216 | EPHYR_LOG("window: %p\n", a_win); | |
217 | if (!a_win->parent) { | |
218 | EPHYR_LOG("cannot move root window\n"); | |
219 | return; | |
220 | } | |
221 | win_priv = GET_EPHYR_DRI_WINDOW_PRIV(a_win); | |
222 | if (!win_priv) { | |
223 | EPHYR_LOG("not a DRI peered window\n"); | |
224 | return; | |
225 | } | |
226 | if (!findWindowPairFromLocal(a_win, &pair) || !pair) { | |
227 | EPHYR_LOG_ERROR("failed to get window pair\n"); | |
228 | return; | |
229 | } | |
230 | /*compute position relative to parent window */ | |
231 | x = a_win->drawable.x - a_win->parent->drawable.x; | |
232 | y = a_win->drawable.y - a_win->parent->drawable.y; | |
233 | /*set the geometry to pass to hostx_set_window_geometry */ | |
234 | memset(&geo, 0, sizeof(geo)); | |
235 | geo.x = x; | |
236 | geo.y = y; | |
237 | geo.width = a_win->drawable.width; | |
238 | geo.height = a_win->drawable.height; | |
239 | hostx_set_window_geometry(pair->remote, &geo); | |
240 | } | |
241 | ||
242 | static Bool | |
243 | ephyrDRIPositionWindow(WindowPtr a_win, int a_x, int a_y) | |
244 | { | |
245 | Bool is_ok = FALSE; | |
246 | ScreenPtr screen = NULL; | |
247 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
248 | EphyrDRIWindowPrivPtr win_priv = NULL; | |
249 | EphyrWindowPair *pair = NULL; | |
250 | EphyrBox geo; | |
251 | ||
252 | EPHYR_RETURN_VAL_IF_FAIL(a_win, FALSE); | |
253 | ||
254 | EPHYR_LOG("enter\n"); | |
255 | screen = a_win->drawable.pScreen; | |
256 | EPHYR_RETURN_VAL_IF_FAIL(screen, FALSE); | |
257 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(screen); | |
258 | EPHYR_RETURN_VAL_IF_FAIL(screen_priv && screen_priv->PositionWindow, FALSE); | |
259 | ||
260 | screen->PositionWindow = screen_priv->PositionWindow; | |
261 | if (screen->PositionWindow) { | |
262 | (*screen->PositionWindow) (a_win, a_x, a_y); | |
263 | } | |
264 | screen->PositionWindow = ephyrDRIPositionWindow; | |
265 | ||
266 | EPHYR_LOG("window: %p\n", a_win); | |
267 | win_priv = GET_EPHYR_DRI_WINDOW_PRIV(a_win); | |
268 | if (!win_priv) { | |
269 | EPHYR_LOG("not a DRI peered window\n"); | |
270 | is_ok = TRUE; | |
271 | goto out; | |
272 | } | |
273 | if (!findWindowPairFromLocal(a_win, &pair) || !pair) { | |
274 | EPHYR_LOG_ERROR("failed to get window pair\n"); | |
275 | goto out; | |
276 | } | |
277 | /*set the geometry to pass to hostx_set_window_geometry */ | |
278 | memset(&geo, 0, sizeof(geo)); | |
279 | geo.x = a_x; | |
280 | geo.y = a_y; | |
281 | geo.width = a_win->drawable.width; | |
282 | geo.height = a_win->drawable.height; | |
283 | hostx_set_window_geometry(pair->remote, &geo); | |
284 | is_ok = TRUE; | |
285 | ||
286 | out: | |
287 | EPHYR_LOG("leave. is_ok:%d\n", is_ok); | |
288 | /*do cleanup here */ | |
289 | return is_ok; | |
290 | } | |
291 | ||
292 | static void | |
293 | ephyrDRIClipNotify(WindowPtr a_win, int a_x, int a_y) | |
294 | { | |
295 | ScreenPtr screen = NULL; | |
296 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
297 | EphyrDRIWindowPrivPtr win_priv = NULL; | |
298 | EphyrWindowPair *pair = NULL; | |
299 | EphyrRect *rects = NULL; | |
300 | int i = 0; | |
301 | ||
302 | EPHYR_RETURN_IF_FAIL(a_win); | |
303 | ||
304 | EPHYR_LOG("enter\n"); | |
305 | screen = a_win->drawable.pScreen; | |
306 | EPHYR_RETURN_IF_FAIL(screen); | |
307 | screen_priv = GET_EPHYR_DRI_SCREEN_PRIV(screen); | |
308 | EPHYR_RETURN_IF_FAIL(screen_priv && screen_priv->ClipNotify); | |
309 | ||
310 | screen->ClipNotify = screen_priv->ClipNotify; | |
311 | if (screen->ClipNotify) { | |
312 | (*screen->ClipNotify) (a_win, a_x, a_y); | |
313 | } | |
314 | screen->ClipNotify = ephyrDRIClipNotify; | |
315 | ||
316 | EPHYR_LOG("window: %p\n", a_win); | |
317 | win_priv = GET_EPHYR_DRI_WINDOW_PRIV(a_win); | |
318 | if (!win_priv) { | |
319 | EPHYR_LOG("not a DRI peered window\n"); | |
320 | goto out; | |
321 | } | |
322 | if (!findWindowPairFromLocal(a_win, &pair) || !pair) { | |
323 | EPHYR_LOG_ERROR("failed to get window pair\n"); | |
324 | goto out; | |
325 | } | |
326 | rects = calloc(RegionNumRects(&a_win->clipList), sizeof(EphyrRect)); | |
327 | for (i = 0; i < RegionNumRects(&a_win->clipList); i++) { | |
328 | memmove(&rects[i], | |
329 | &RegionRects(&a_win->clipList)[i], sizeof(EphyrRect)); | |
330 | rects[i].x1 -= a_win->drawable.x; | |
331 | rects[i].x2 -= a_win->drawable.x; | |
332 | rects[i].y1 -= a_win->drawable.y; | |
333 | rects[i].y2 -= a_win->drawable.y; | |
334 | } | |
335 | /* | |
336 | * push the clipping region of this window | |
337 | * to the peer window in the host | |
338 | */ | |
339 | hostx_set_window_bounding_rectangles | |
340 | (pair->remote, rects, RegionNumRects(&a_win->clipList)); | |
341 | ||
342 | out: | |
343 | free(rects); | |
344 | rects = NULL; | |
345 | ||
346 | EPHYR_LOG("leave.\n"); | |
347 | /*do cleanup here */ | |
348 | } | |
349 | ||
350 | /** | |
351 | * Duplicates a visual of a_screen | |
352 | * In screen a_screen, for depth a_depth, find a visual which | |
353 | * bitsPerRGBValue and colormap size equal | |
354 | * a_bits_per_rgb_values and a_colormap_entries. | |
355 | * The ID of that duplicated visual is set to a_new_id. | |
356 | * That duplicated visual is then added to the list of visuals | |
357 | * of the screen. | |
358 | */ | |
359 | static Bool | |
360 | EphyrDuplicateVisual(unsigned int a_screen, | |
361 | short a_depth, | |
362 | short a_class, | |
363 | short a_bits_per_rgb_values, | |
364 | short a_colormap_entries, | |
365 | unsigned int a_red_mask, | |
366 | unsigned int a_green_mask, | |
367 | unsigned int a_blue_mask, unsigned int a_new_id) | |
368 | { | |
369 | Bool is_ok = FALSE, found_visual = FALSE, found_depth = FALSE; | |
370 | ScreenPtr screen = NULL; | |
371 | VisualRec new_visual, *new_visuals = NULL; | |
372 | int i = 0; | |
373 | ||
374 | EPHYR_LOG("enter\n"); | |
375 | if (a_screen >= screenInfo.numScreens) { | |
376 | EPHYR_LOG_ERROR("bad screen number\n"); | |
377 | goto out; | |
378 | } | |
379 | memset(&new_visual, 0, sizeof(VisualRec)); | |
380 | ||
381 | /*get the screen pointed to by a_screen */ | |
382 | screen = screenInfo.screens[a_screen]; | |
383 | EPHYR_RETURN_VAL_IF_FAIL(screen, FALSE); | |
384 | ||
385 | /* | |
386 | * In that screen, first look for an existing visual that has the | |
387 | * same characteristics as those passed in parameter | |
388 | * to this function and copy it. | |
389 | */ | |
390 | for (i = 0; i < screen->numVisuals; i++) { | |
391 | if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values && | |
392 | screen->visuals[i].ColormapEntries == a_colormap_entries) { | |
393 | /*copy the visual found */ | |
394 | memcpy(&new_visual, &screen->visuals[i], sizeof(new_visual)); | |
395 | new_visual.vid = a_new_id; | |
396 | new_visual.class = a_class; | |
397 | new_visual.redMask = a_red_mask; | |
398 | new_visual.greenMask = a_green_mask; | |
399 | new_visual.blueMask = a_blue_mask; | |
400 | found_visual = TRUE; | |
401 | EPHYR_LOG("found a visual that matches visual id: %d\n", a_new_id); | |
402 | break; | |
403 | } | |
404 | } | |
405 | if (!found_visual) { | |
406 | EPHYR_LOG("did not find any visual matching %d\n", a_new_id); | |
407 | goto out; | |
408 | } | |
409 | /* | |
410 | * be prepare to extend screen->visuals to add new_visual to it | |
411 | */ | |
412 | new_visuals = calloc(screen->numVisuals + 1, sizeof(VisualRec)); | |
413 | memmove(new_visuals, | |
414 | screen->visuals, screen->numVisuals * sizeof(VisualRec)); | |
415 | memmove(&new_visuals[screen->numVisuals], &new_visual, sizeof(VisualRec)); | |
416 | /* | |
417 | * Now, in that same screen, update the screen->allowedDepths member. | |
418 | * In that array, each element represents the visuals applicable to | |
419 | * a given depth. So we need to add an entry matching the new visual | |
420 | * that we are going to add to screen->visuals | |
421 | */ | |
422 | for (i = 0; i < screen->numDepths; i++) { | |
423 | VisualID *vids = NULL; | |
424 | DepthPtr cur_depth = NULL; | |
425 | ||
426 | /*find the entry matching a_depth */ | |
427 | if (screen->allowedDepths[i].depth != a_depth) | |
428 | continue; | |
429 | cur_depth = &screen->allowedDepths[i]; | |
430 | /* | |
431 | * extend the list of visual IDs in that entry, | |
432 | * so to add a_new_id in there. | |
433 | */ | |
434 | vids = realloc(cur_depth->vids, | |
435 | (cur_depth->numVids + 1) * sizeof(VisualID)); | |
436 | if (!vids) { | |
437 | EPHYR_LOG_ERROR("failed to realloc numids\n"); | |
438 | goto out; | |
439 | } | |
440 | vids[cur_depth->numVids] = a_new_id; | |
441 | /* | |
442 | * Okay now commit our change. | |
443 | * Do really update screen->allowedDepths[i] | |
444 | */ | |
445 | cur_depth->numVids++; | |
446 | cur_depth->vids = vids; | |
447 | found_depth = TRUE; | |
448 | } | |
449 | if (!found_depth) { | |
450 | EPHYR_LOG_ERROR("failed to update screen[%d]->allowedDepth\n", | |
451 | a_screen); | |
452 | goto out; | |
453 | } | |
454 | /* | |
455 | * Commit our change to screen->visuals | |
456 | */ | |
457 | free(screen->visuals); | |
458 | screen->visuals = new_visuals; | |
459 | screen->numVisuals++; | |
460 | new_visuals = NULL; | |
461 | ||
462 | is_ok = TRUE; | |
463 | out: | |
464 | free(new_visuals); | |
465 | new_visuals = NULL; | |
466 | ||
467 | EPHYR_LOG("leave\n"); | |
468 | return is_ok; | |
469 | } | |
470 | ||
471 | /** | |
472 | * Duplicates the visuals of the host X server. | |
473 | * This is necessary to have visuals that have the same | |
474 | * ID as those of the host X. It is important to have that for | |
475 | * GLX. | |
476 | */ | |
477 | static Bool | |
478 | EphyrMirrorHostVisuals(ScreenPtr a_screen) | |
479 | { | |
480 | Bool is_ok = FALSE; | |
481 | EphyrHostVisualInfo *visuals = NULL; | |
482 | int nb_visuals = 0, i = 0; | |
483 | ||
484 | EPHYR_LOG("enter\n"); | |
485 | if (!hostx_get_visuals_info(&visuals, &nb_visuals)) { | |
486 | EPHYR_LOG_ERROR("failed to get host visuals\n"); | |
487 | goto out; | |
488 | } | |
489 | for (i = 0; i < nb_visuals; i++) { | |
490 | if (!EphyrDuplicateVisual(a_screen->myNum, | |
491 | visuals[i].depth, | |
492 | visuals[i].class, | |
493 | visuals[i].bits_per_rgb, | |
494 | visuals[i].colormap_size, | |
495 | visuals[i].red_mask, | |
496 | visuals[i].green_mask, | |
497 | visuals[i].blue_mask, visuals[i].visualid)) { | |
498 | EPHYR_LOG_ERROR("failed to duplicate host visual %d\n", | |
499 | (int) visuals[i].visualid); | |
500 | } | |
501 | } | |
502 | ||
503 | is_ok = TRUE; | |
504 | out: | |
505 | EPHYR_LOG("leave\n"); | |
506 | return is_ok; | |
507 | } | |
508 | ||
509 | static int | |
510 | ProcXF86DRIQueryVersion(register ClientPtr client) | |
511 | { | |
512 | xXF86DRIQueryVersionReply rep = { | |
513 | .type = X_Reply, | |
514 | .sequenceNumber = client->sequence, | |
515 | .length = 0, | |
516 | .majorVersion = SERVER_XF86DRI_MAJOR_VERSION, | |
517 | .minorVersion = SERVER_XF86DRI_MINOR_VERSION, | |
518 | .patchVersion = SERVER_XF86DRI_PATCH_VERSION | |
519 | }; | |
520 | ||
521 | REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); | |
522 | ||
523 | EPHYR_LOG("enter\n"); | |
524 | ||
525 | if (client->swapped) { | |
526 | swaps(&rep.sequenceNumber); | |
527 | swapl(&rep.length); | |
528 | swaps(&rep.majorVersion); | |
529 | swaps(&rep.minorVersion); | |
530 | swapl(&rep.patchVersion); | |
531 | } | |
532 | WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), &rep); | |
533 | EPHYR_LOG("leave\n"); | |
534 | return Success; | |
535 | } | |
536 | ||
537 | static int | |
538 | ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client) | |
539 | { | |
540 | xXF86DRIQueryDirectRenderingCapableReply rep; | |
541 | Bool isCapable; | |
542 | ||
543 | REQUEST(xXF86DRIQueryDirectRenderingCapableReq); | |
544 | REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); | |
545 | ||
546 | EPHYR_LOG("enter\n"); | |
547 | if (stuff->screen >= screenInfo.numScreens) { | |
548 | client->errorValue = stuff->screen; | |
549 | return BadValue; | |
550 | } | |
551 | ||
552 | if (!ephyrDRIQueryDirectRenderingCapable(stuff->screen, &isCapable)) { | |
553 | return BadValue; | |
554 | } | |
555 | ||
556 | if (!client->local || client->swapped) | |
557 | isCapable = 0; | |
558 | ||
559 | rep = (xXF86DRIQueryDirectRenderingCapableReply) { | |
560 | .type = X_Reply, | |
561 | .sequenceNumber = client->sequence, | |
562 | .length = 0, | |
563 | .isCapable = isCapable | |
564 | }; | |
565 | ||
566 | if (client->swapped) { | |
567 | swaps(&rep.sequenceNumber); | |
568 | swapl(&rep.length); | |
569 | } | |
570 | ||
571 | WriteToClient(client, sizeof(xXF86DRIQueryDirectRenderingCapableReply), | |
572 | &rep); | |
573 | EPHYR_LOG("leave\n"); | |
574 | ||
575 | return Success; | |
576 | } | |
577 | ||
578 | static int | |
579 | ProcXF86DRIOpenConnection(register ClientPtr client) | |
580 | { | |
581 | xXF86DRIOpenConnectionReply rep; | |
582 | drm_handle_t hSAREA; | |
583 | char *busIdString = NULL; | |
584 | CARD32 busIdStringLength = 0; | |
585 | ||
586 | REQUEST(xXF86DRIOpenConnectionReq); | |
587 | REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); | |
588 | ||
589 | EPHYR_LOG("enter\n"); | |
590 | if (stuff->screen >= screenInfo.numScreens) { | |
591 | client->errorValue = stuff->screen; | |
592 | return BadValue; | |
593 | } | |
594 | ||
595 | if (!ephyrDRIOpenConnection(stuff->screen, &hSAREA, &busIdString)) { | |
596 | return BadValue; | |
597 | } | |
598 | ||
599 | if (busIdString) | |
600 | busIdStringLength = strlen(busIdString); | |
601 | ||
602 | rep = (xXF86DRIOpenConnectionReply) { | |
603 | .type = X_Reply, | |
604 | .sequenceNumber = client->sequence, | |
605 | .length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - | |
606 | SIZEOF(xGenericReply) + | |
607 | pad_to_int32(busIdStringLength)), | |
608 | .hSAREALow = (CARD32) (hSAREA & 0xffffffff), | |
609 | #if defined(LONG64) && !defined(__linux__) | |
610 | .hSAREAHigh = (CARD32) (hSAREA >> 32), | |
611 | #else | |
612 | .hSAREAHigh = 0, | |
613 | #endif | |
614 | .busIdStringLength = busIdStringLength | |
615 | }; | |
616 | ||
617 | WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), &rep); | |
618 | if (busIdStringLength) | |
619 | WriteToClient(client, busIdStringLength, busIdString); | |
620 | free(busIdString); | |
621 | EPHYR_LOG("leave\n"); | |
622 | return Success; | |
623 | } | |
624 | ||
625 | static int | |
626 | ProcXF86DRIAuthConnection(register ClientPtr client) | |
627 | { | |
628 | xXF86DRIAuthConnectionReply rep; | |
629 | ||
630 | REQUEST(xXF86DRIAuthConnectionReq); | |
631 | REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); | |
632 | ||
633 | EPHYR_LOG("enter\n"); | |
634 | if (stuff->screen >= screenInfo.numScreens) { | |
635 | client->errorValue = stuff->screen; | |
636 | return BadValue; | |
637 | } | |
638 | ||
639 | rep = (xXF86DRIAuthConnectionReply) { | |
640 | .type = X_Reply, | |
641 | .sequenceNumber = client->sequence, | |
642 | .length = 0, | |
643 | .authenticated = 1 | |
644 | }; | |
645 | ||
646 | if (!ephyrDRIAuthConnection(stuff->screen, stuff->magic)) { | |
647 | ErrorF("Failed to authenticate %lu\n", (unsigned long) stuff->magic); | |
648 | rep.authenticated = 0; | |
649 | } | |
650 | WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), &rep); | |
651 | EPHYR_LOG("leave\n"); | |
652 | return Success; | |
653 | } | |
654 | ||
655 | static int | |
656 | ProcXF86DRICloseConnection(register ClientPtr client) | |
657 | { | |
658 | REQUEST(xXF86DRICloseConnectionReq); | |
659 | REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); | |
660 | EPHYR_LOG("enter\n"); | |
661 | if (stuff->screen >= screenInfo.numScreens) { | |
662 | client->errorValue = stuff->screen; | |
663 | return BadValue; | |
664 | } | |
665 | ||
666 | /* | |
667 | DRICloseConnection( screenInfo.screens[stuff->screen]); | |
668 | */ | |
669 | ||
670 | EPHYR_LOG("leave\n"); | |
671 | return Success; | |
672 | } | |
673 | ||
674 | static int | |
675 | ProcXF86DRIGetClientDriverName(register ClientPtr client) | |
676 | { | |
677 | xXF86DRIGetClientDriverNameReply rep = { | |
678 | .type = X_Reply, | |
679 | .sequenceNumber = client->sequence, | |
680 | .clientDriverNameLength = 0 | |
681 | }; | |
682 | char *clientDriverName; | |
683 | ||
684 | REQUEST(xXF86DRIGetClientDriverNameReq); | |
685 | REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); | |
686 | ||
687 | EPHYR_LOG("enter\n"); | |
688 | if (stuff->screen >= screenInfo.numScreens) { | |
689 | client->errorValue = stuff->screen; | |
690 | return BadValue; | |
691 | } | |
692 | ||
693 | ephyrDRIGetClientDriverName(stuff->screen, | |
694 | (int *) &rep.ddxDriverMajorVersion, | |
695 | (int *) &rep.ddxDriverMinorVersion, | |
696 | (int *) &rep.ddxDriverPatchVersion, | |
697 | &clientDriverName); | |
698 | if (clientDriverName) | |
699 | rep.clientDriverNameLength = strlen(clientDriverName); | |
700 | rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - | |
701 | SIZEOF(xGenericReply) + | |
702 | pad_to_int32(rep.clientDriverNameLength)); | |
703 | ||
704 | WriteToClient(client, sizeof(xXF86DRIGetClientDriverNameReply), &rep); | |
705 | if (rep.clientDriverNameLength) | |
706 | WriteToClient(client, rep.clientDriverNameLength, clientDriverName); | |
707 | EPHYR_LOG("leave\n"); | |
708 | return Success; | |
709 | } | |
710 | ||
711 | static int | |
712 | ProcXF86DRICreateContext(register ClientPtr client) | |
713 | { | |
714 | xXF86DRICreateContextReply rep = { | |
715 | .type = X_Reply, | |
716 | .sequenceNumber = client->sequence, | |
717 | .length = 0 | |
718 | }; | |
719 | ScreenPtr pScreen; | |
720 | VisualPtr visual; | |
721 | int i = 0; | |
722 | ||
723 | REQUEST(xXF86DRICreateContextReq); | |
724 | REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); | |
725 | ||
726 | EPHYR_LOG("enter\n"); | |
727 | if (stuff->screen >= screenInfo.numScreens) { | |
728 | client->errorValue = stuff->screen; | |
729 | return BadValue; | |
730 | } | |
731 | ||
732 | pScreen = screenInfo.screens[stuff->screen]; | |
733 | visual = pScreen->visuals; | |
734 | ||
735 | /* Find the requested X visual */ | |
736 | for (i = 0; i < pScreen->numVisuals; i++, visual++) | |
737 | if (visual->vid == stuff->visual) | |
738 | break; | |
739 | if (i == pScreen->numVisuals) { | |
740 | /* No visual found */ | |
741 | return BadValue; | |
742 | } | |
743 | ||
744 | if (!ephyrDRICreateContext(stuff->screen, | |
745 | stuff->visual, | |
746 | stuff->context, | |
747 | (drm_context_t *) &rep.hHWContext)) { | |
748 | return BadValue; | |
749 | } | |
750 | ||
751 | WriteToClient(client, sizeof(xXF86DRICreateContextReply), &rep); | |
752 | EPHYR_LOG("leave\n"); | |
753 | return Success; | |
754 | } | |
755 | ||
756 | static int | |
757 | ProcXF86DRIDestroyContext(register ClientPtr client) | |
758 | { | |
759 | REQUEST(xXF86DRIDestroyContextReq); | |
760 | REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); | |
761 | EPHYR_LOG("enter\n"); | |
762 | ||
763 | if (stuff->screen >= screenInfo.numScreens) { | |
764 | client->errorValue = stuff->screen; | |
765 | return BadValue; | |
766 | } | |
767 | ||
768 | if (!ephyrDRIDestroyContext(stuff->screen, stuff->context)) { | |
769 | return BadValue; | |
770 | } | |
771 | ||
772 | EPHYR_LOG("leave\n"); | |
773 | return Success; | |
774 | } | |
775 | ||
776 | static Bool | |
777 | getWindowVisual(const WindowPtr a_win, VisualPtr * a_visual) | |
778 | { | |
779 | int i = 0, visual_id = 0; | |
780 | ||
781 | EPHYR_RETURN_VAL_IF_FAIL(a_win | |
782 | && a_win->drawable.pScreen | |
783 | && a_win->drawable.pScreen->visuals, FALSE); | |
784 | ||
785 | visual_id = wVisual(a_win); | |
786 | for (i = 0; i < a_win->drawable.pScreen->numVisuals; i++) { | |
787 | if (a_win->drawable.pScreen->visuals[i].vid == visual_id) { | |
788 | *a_visual = &a_win->drawable.pScreen->visuals[i]; | |
789 | return TRUE; | |
790 | } | |
791 | } | |
792 | return FALSE; | |
793 | } | |
794 | ||
795 | #define NUM_WINDOW_PAIRS 256 | |
796 | static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS]; | |
797 | ||
798 | static Bool | |
799 | appendWindowPairToList(WindowPtr a_local, int a_remote) | |
800 | { | |
801 | int i = 0; | |
802 | ||
803 | EPHYR_RETURN_VAL_IF_FAIL(a_local, FALSE); | |
804 | ||
805 | EPHYR_LOG("(local,remote):(%p, %d)\n", a_local, a_remote); | |
806 | ||
807 | for (i = 0; i < NUM_WINDOW_PAIRS; i++) { | |
808 | if (window_pairs[i].local == NULL) { | |
809 | window_pairs[i].local = a_local; | |
810 | window_pairs[i].remote = a_remote; | |
811 | return TRUE; | |
812 | } | |
813 | } | |
814 | return FALSE; | |
815 | } | |
816 | ||
817 | static Bool | |
818 | findWindowPairFromLocal(WindowPtr a_local, EphyrWindowPair ** a_pair) | |
819 | { | |
820 | int i = 0; | |
821 | ||
822 | EPHYR_RETURN_VAL_IF_FAIL(a_pair && a_local, FALSE); | |
823 | ||
824 | for (i = 0; i < NUM_WINDOW_PAIRS; i++) { | |
825 | if (window_pairs[i].local == a_local) { | |
826 | *a_pair = &window_pairs[i]; | |
827 | EPHYR_LOG("found (%p, %d)\n", (*a_pair)->local, (*a_pair)->remote); | |
828 | return TRUE; | |
829 | } | |
830 | } | |
831 | return FALSE; | |
832 | } | |
833 | ||
834 | Bool | |
835 | findWindowPairFromRemote(int a_remote, EphyrWindowPair ** a_pair) | |
836 | { | |
837 | int i = 0; | |
838 | ||
839 | EPHYR_RETURN_VAL_IF_FAIL(a_pair, FALSE); | |
840 | ||
841 | for (i = 0; i < NUM_WINDOW_PAIRS; i++) { | |
842 | if (window_pairs[i].remote == a_remote) { | |
843 | *a_pair = &window_pairs[i]; | |
844 | EPHYR_LOG("found (%p, %d)\n", (*a_pair)->local, (*a_pair)->remote); | |
845 | return TRUE; | |
846 | } | |
847 | } | |
848 | return FALSE; | |
849 | } | |
850 | ||
851 | static Bool | |
852 | createHostPeerWindow(const WindowPtr a_win, int *a_peer_win) | |
853 | { | |
854 | Bool is_ok = FALSE; | |
855 | VisualPtr visual = NULL; | |
856 | EphyrBox geo; | |
857 | ||
858 | EPHYR_RETURN_VAL_IF_FAIL(a_win && a_peer_win, FALSE); | |
859 | EPHYR_RETURN_VAL_IF_FAIL(a_win->drawable.pScreen, FALSE); | |
860 | ||
861 | EPHYR_LOG("enter. a_win '%p'\n", a_win); | |
862 | if (!getWindowVisual(a_win, &visual)) { | |
863 | EPHYR_LOG_ERROR("failed to get window visual\n"); | |
864 | goto out; | |
865 | } | |
866 | if (!visual) { | |
867 | EPHYR_LOG_ERROR("failed to create visual\n"); | |
868 | goto out; | |
869 | } | |
870 | memset(&geo, 0, sizeof(geo)); | |
871 | geo.x = a_win->drawable.x; | |
872 | geo.y = a_win->drawable.y; | |
873 | geo.width = a_win->drawable.width; | |
874 | geo.height = a_win->drawable.height; | |
875 | if (!hostx_create_window(a_win->drawable.pScreen->myNum, | |
876 | &geo, visual->vid, a_peer_win)) { | |
877 | EPHYR_LOG_ERROR("failed to create host peer window\n"); | |
878 | goto out; | |
879 | } | |
880 | if (!appendWindowPairToList(a_win, *a_peer_win)) { | |
881 | EPHYR_LOG_ERROR("failed to append window to pair list\n"); | |
882 | goto out; | |
883 | } | |
884 | is_ok = TRUE; | |
885 | out: | |
886 | EPHYR_LOG("leave:remote win%d\n", *a_peer_win); | |
887 | return is_ok; | |
888 | } | |
889 | ||
890 | static Bool | |
891 | destroyHostPeerWindow(const WindowPtr a_win) | |
892 | { | |
893 | Bool is_ok = FALSE; | |
894 | EphyrWindowPair *pair = NULL; | |
895 | ||
896 | EPHYR_RETURN_VAL_IF_FAIL(a_win, FALSE); | |
897 | ||
898 | EPHYR_LOG("enter\n"); | |
899 | ||
900 | if (!findWindowPairFromLocal(a_win, &pair) || !pair) { | |
901 | EPHYR_LOG_ERROR("failed to find peer to local window\n"); | |
902 | goto out; | |
903 | } | |
904 | hostx_destroy_window(pair->remote); | |
905 | is_ok = TRUE; | |
906 | ||
907 | out: | |
908 | EPHYR_LOG("leave\n"); | |
909 | return is_ok; | |
910 | } | |
911 | ||
912 | static int | |
913 | ProcXF86DRICreateDrawable(ClientPtr client) | |
914 | { | |
915 | xXF86DRICreateDrawableReply rep = { | |
916 | .type = X_Reply, | |
917 | .sequenceNumber = client->sequence, | |
918 | .length = 0 | |
919 | }; | |
920 | DrawablePtr drawable = NULL; | |
921 | WindowPtr window = NULL; | |
922 | EphyrWindowPair *pair = NULL; | |
923 | EphyrDRIWindowPrivPtr win_priv = NULL; | |
924 | int rc = 0, remote_win = 0; | |
925 | ||
926 | REQUEST(xXF86DRICreateDrawableReq); | |
927 | REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); | |
928 | ||
929 | EPHYR_LOG("enter\n"); | |
930 | if (stuff->screen >= screenInfo.numScreens) { | |
931 | client->errorValue = stuff->screen; | |
932 | return BadValue; | |
933 | } | |
934 | ||
935 | rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, | |
936 | DixReadAccess); | |
937 | if (rc != Success) | |
938 | return rc; | |
939 | if (drawable->type != DRAWABLE_WINDOW) { | |
940 | EPHYR_LOG_ERROR("non drawable windows are not yet supported\n"); | |
941 | return BadImplementation; | |
942 | } | |
943 | EPHYR_LOG("lookedup drawable %p\n", drawable); | |
944 | window = (WindowPtr) drawable; | |
945 | if (findWindowPairFromLocal(window, &pair) && pair) { | |
946 | remote_win = pair->remote; | |
947 | EPHYR_LOG("found window '%p' paire with remote '%d'\n", | |
948 | window, remote_win); | |
949 | } | |
950 | else if (!createHostPeerWindow(window, &remote_win)) { | |
951 | EPHYR_LOG_ERROR("failed to create host peer window\n"); | |
952 | return BadAlloc; | |
953 | } | |
954 | ||
955 | if (!ephyrDRICreateDrawable(stuff->screen, | |
956 | remote_win, | |
957 | (drm_drawable_t *) &rep.hHWDrawable)) { | |
958 | EPHYR_LOG_ERROR("failed to create dri drawable\n"); | |
959 | return BadValue; | |
960 | } | |
961 | ||
962 | win_priv = GET_EPHYR_DRI_WINDOW_PRIV(window); | |
963 | if (!win_priv) { | |
964 | win_priv = calloc(1, sizeof(EphyrDRIWindowPrivRec)); | |
965 | if (!win_priv) { | |
966 | EPHYR_LOG_ERROR("failed to allocate window private\n"); | |
967 | return BadAlloc; | |
968 | } | |
969 | dixSetPrivate(&window->devPrivates, ephyrDRIWindowKey, win_priv); | |
970 | EPHYR_LOG("paired window '%p' with remote '%d'\n", window, remote_win); | |
971 | } | |
972 | ||
973 | WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), &rep); | |
974 | EPHYR_LOG("leave\n"); | |
975 | return Success; | |
976 | } | |
977 | ||
978 | static int | |
979 | ProcXF86DRIDestroyDrawable(register ClientPtr client) | |
980 | { | |
981 | DrawablePtr drawable = NULL; | |
982 | WindowPtr window = NULL; | |
983 | EphyrWindowPair *pair = NULL; | |
984 | int rc = 0; | |
985 | ||
986 | REQUEST(xXF86DRIDestroyDrawableReq); | |
987 | REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); | |
988 | ||
989 | EPHYR_LOG("enter\n"); | |
990 | if (stuff->screen >= screenInfo.numScreens) { | |
991 | client->errorValue = stuff->screen; | |
992 | return BadValue; | |
993 | } | |
994 | ||
995 | rc = dixLookupDrawable(&drawable, | |
996 | stuff->drawable, client, 0, DixReadAccess); | |
997 | if (rc != Success) | |
998 | return rc; | |
999 | if (drawable->type != DRAWABLE_WINDOW) { | |
1000 | EPHYR_LOG_ERROR("non drawable windows are not yet supported\n"); | |
1001 | return BadImplementation; | |
1002 | } | |
1003 | window = (WindowPtr) drawable; | |
1004 | if (!findWindowPairFromLocal(window, &pair) && pair) { | |
1005 | EPHYR_LOG_ERROR("failed to find pair window\n"); | |
1006 | return BadImplementation; | |
1007 | } | |
1008 | if (!ephyrDRIDestroyDrawable(stuff->screen, | |
1009 | pair->remote /*drawable in host x */ )) { | |
1010 | EPHYR_LOG_ERROR("failed to destroy dri drawable\n"); | |
1011 | return BadImplementation; | |
1012 | } | |
1013 | pair->local = NULL; | |
1014 | pair->remote = 0; | |
1015 | ||
1016 | EPHYR_LOG("leave\n"); | |
1017 | return Success; | |
1018 | } | |
1019 | ||
1020 | static int | |
1021 | ProcXF86DRIGetDrawableInfo(register ClientPtr client) | |
1022 | { | |
1023 | xXF86DRIGetDrawableInfoReply rep = { | |
1024 | .type = X_Reply, | |
1025 | .sequenceNumber = client->sequence, | |
1026 | .length = 0 | |
1027 | }; | |
1028 | DrawablePtr drawable; | |
1029 | WindowPtr window = NULL; | |
1030 | EphyrWindowPair *pair = NULL; | |
1031 | int X = 0, Y = 0, W = 0, H = 0, backX = 0, backY = 0, rc = 0, i = 0; | |
1032 | drm_clip_rect_t *clipRects = NULL; | |
1033 | drm_clip_rect_t *backClipRects = NULL; | |
1034 | ||
1035 | REQUEST(xXF86DRIGetDrawableInfoReq); | |
1036 | REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); | |
1037 | ||
1038 | EPHYR_LOG("enter\n"); | |
1039 | if (stuff->screen >= screenInfo.numScreens) { | |
1040 | client->errorValue = stuff->screen; | |
1041 | return BadValue; | |
1042 | } | |
1043 | ||
1044 | rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0, | |
1045 | DixReadAccess); | |
1046 | if (rc != Success || !drawable) { | |
1047 | EPHYR_LOG_ERROR("could not get drawable\n"); | |
1048 | return rc; | |
1049 | } | |
1050 | ||
1051 | if (drawable->type != DRAWABLE_WINDOW) { | |
1052 | EPHYR_LOG_ERROR("non windows type drawables are not yes supported\n"); | |
1053 | return BadImplementation; | |
1054 | } | |
1055 | window = (WindowPtr) drawable; | |
1056 | memset(&pair, 0, sizeof(pair)); | |
1057 | if (!findWindowPairFromLocal(window, &pair) || !pair) { | |
1058 | EPHYR_LOG_ERROR("failed to find remote peer drawable\n"); | |
1059 | return BadMatch; | |
1060 | } | |
1061 | EPHYR_LOG("clip list of xephyr gl drawable:\n"); | |
1062 | for (i = 0; i < RegionNumRects(&window->clipList); i++) { | |
1063 | EPHYR_LOG("x1:%d, y1:%d, x2:%d, y2:%d\n", | |
1064 | RegionRects(&window->clipList)[i].x1, | |
1065 | RegionRects(&window->clipList)[i].y1, | |
1066 | RegionRects(&window->clipList)[i].x2, | |
1067 | RegionRects(&window->clipList)[i].y2); | |
1068 | } | |
1069 | ||
1070 | if (!ephyrDRIGetDrawableInfo(stuff->screen, | |
1071 | pair->remote /*the drawable in hostx */ , | |
1072 | (unsigned int *) &rep.drawableTableIndex, | |
1073 | (unsigned int *) &rep.drawableTableStamp, | |
1074 | (int *) &X, | |
1075 | (int *) &Y, | |
1076 | (int *) &W, | |
1077 | (int *) &H, | |
1078 | (int *) &rep.numClipRects, | |
1079 | &clipRects, | |
1080 | &backX, | |
1081 | &backY, | |
1082 | (int *) &rep.numBackClipRects, | |
1083 | &backClipRects)) { | |
1084 | return BadValue; | |
1085 | } | |
1086 | EPHYR_LOG("num clip rects:%d, num back clip rects:%d\n", | |
1087 | (int) rep.numClipRects, (int) rep.numBackClipRects); | |
1088 | ||
1089 | rep.drawableX = X; | |
1090 | rep.drawableY = Y; | |
1091 | rep.drawableWidth = W; | |
1092 | rep.drawableHeight = H; | |
1093 | rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - SIZEOF(xGenericReply)); | |
1094 | ||
1095 | rep.backX = backX; | |
1096 | rep.backY = backY; | |
1097 | ||
1098 | if (rep.numClipRects) { | |
1099 | if (clipRects) { | |
1100 | ScreenPtr pScreen = screenInfo.screens[stuff->screen]; | |
1101 | int i = 0; | |
1102 | ||
1103 | EPHYR_LOG("clip list of host gl drawable:\n"); | |
1104 | for (i = 0; i < rep.numClipRects; i++) { | |
1105 | clipRects[i].x1 = max(clipRects[i].x1, 0); | |
1106 | clipRects[i].y1 = max(clipRects[i].y1, 0); | |
1107 | clipRects[i].x2 = min(clipRects[i].x2, | |
1108 | pScreen->width + clipRects[i].x1); | |
1109 | clipRects[i].y2 = min(clipRects[i].y2, | |
1110 | pScreen->width + clipRects[i].y1); | |
1111 | ||
1112 | EPHYR_LOG("x1:%d, y1:%d, x2:%d, y2:%d\n", | |
1113 | clipRects[i].x1, clipRects[i].y1, | |
1114 | clipRects[i].x2, clipRects[i].y2); | |
1115 | } | |
1116 | } | |
1117 | else { | |
1118 | rep.numClipRects = 0; | |
1119 | } | |
1120 | } | |
1121 | else { | |
1122 | EPHYR_LOG("got zero host gl drawable clipping rects\n"); | |
1123 | } | |
1124 | rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; | |
1125 | backClipRects = clipRects; | |
1126 | rep.numBackClipRects = rep.numClipRects; | |
1127 | if (rep.numBackClipRects) | |
1128 | rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; | |
1129 | EPHYR_LOG("num host clip rects:%d\n", (int) rep.numClipRects); | |
1130 | EPHYR_LOG("num host back clip rects:%d\n", (int) rep.numBackClipRects); | |
1131 | ||
1132 | rep.length = bytes_to_int32(rep.length); | |
1133 | ||
1134 | WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), &rep); | |
1135 | ||
1136 | if (rep.numClipRects) { | |
1137 | WriteToClient(client, | |
1138 | sizeof(drm_clip_rect_t) * rep.numClipRects, | |
1139 | clipRects); | |
1140 | } | |
1141 | ||
1142 | if (rep.numBackClipRects) { | |
1143 | WriteToClient(client, | |
1144 | sizeof(drm_clip_rect_t) * rep.numBackClipRects, | |
1145 | backClipRects); | |
1146 | } | |
1147 | free(clipRects); | |
1148 | clipRects = NULL; | |
1149 | ||
1150 | EPHYR_LOG("leave\n"); | |
1151 | ||
1152 | return Success; | |
1153 | } | |
1154 | ||
1155 | static int | |
1156 | ProcXF86DRIGetDeviceInfo(register ClientPtr client) | |
1157 | { | |
1158 | xXF86DRIGetDeviceInfoReply rep = { | |
1159 | .type = X_Reply, | |
1160 | .sequenceNumber = client->sequence, | |
1161 | .length = 0 | |
1162 | }; | |
1163 | drm_handle_t hFrameBuffer; | |
1164 | void *pDevPrivate; | |
1165 | ||
1166 | REQUEST(xXF86DRIGetDeviceInfoReq); | |
1167 | REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); | |
1168 | ||
1169 | EPHYR_LOG("enter\n"); | |
1170 | if (stuff->screen >= screenInfo.numScreens) { | |
1171 | client->errorValue = stuff->screen; | |
1172 | return BadValue; | |
1173 | } | |
1174 | ||
1175 | if (!ephyrDRIGetDeviceInfo(stuff->screen, | |
1176 | &hFrameBuffer, | |
1177 | (int *) &rep.framebufferOrigin, | |
1178 | (int *) &rep.framebufferSize, | |
1179 | (int *) &rep.framebufferStride, | |
1180 | (int *) &rep.devPrivateSize, &pDevPrivate)) { | |
1181 | return BadValue; | |
1182 | } | |
1183 | ||
1184 | rep.hFrameBufferLow = (CARD32) (hFrameBuffer & 0xffffffff); | |
1185 | #if defined(LONG64) && !defined(__linux__) | |
1186 | rep.hFrameBufferHigh = (CARD32) (hFrameBuffer >> 32); | |
1187 | #else | |
1188 | rep.hFrameBufferHigh = 0; | |
1189 | #endif | |
1190 | ||
1191 | if (rep.devPrivateSize) { | |
1192 | rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - | |
1193 | SIZEOF(xGenericReply) + | |
1194 | pad_to_int32(rep.devPrivateSize)); | |
1195 | } | |
1196 | ||
1197 | WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), &rep); | |
1198 | if (rep.length) { | |
1199 | WriteToClient(client, rep.devPrivateSize, pDevPrivate); | |
1200 | } | |
1201 | EPHYR_LOG("leave\n"); | |
1202 | return Success; | |
1203 | } | |
1204 | ||
1205 | static int | |
1206 | ProcXF86DRIDispatch(register ClientPtr client) | |
1207 | { | |
1208 | REQUEST(xReq); | |
1209 | EPHYR_LOG("enter\n"); | |
1210 | ||
1211 | switch (stuff->data) { | |
1212 | case X_XF86DRIQueryVersion:{ | |
1213 | EPHYR_LOG("leave\n"); | |
1214 | return ProcXF86DRIQueryVersion(client); | |
1215 | } | |
1216 | case X_XF86DRIQueryDirectRenderingCapable:{ | |
1217 | EPHYR_LOG("leave\n"); | |
1218 | return ProcXF86DRIQueryDirectRenderingCapable(client); | |
1219 | } | |
1220 | } | |
1221 | ||
1222 | if (!client->local) | |
1223 | return DRIErrorBase + XF86DRIClientNotLocal; | |
1224 | ||
1225 | switch (stuff->data) { | |
1226 | case X_XF86DRIOpenConnection:{ | |
1227 | EPHYR_LOG("leave\n"); | |
1228 | return ProcXF86DRIOpenConnection(client); | |
1229 | } | |
1230 | case X_XF86DRICloseConnection:{ | |
1231 | EPHYR_LOG("leave\n"); | |
1232 | return ProcXF86DRICloseConnection(client); | |
1233 | } | |
1234 | case X_XF86DRIGetClientDriverName:{ | |
1235 | EPHYR_LOG("leave\n"); | |
1236 | return ProcXF86DRIGetClientDriverName(client); | |
1237 | } | |
1238 | case X_XF86DRICreateContext:{ | |
1239 | EPHYR_LOG("leave\n"); | |
1240 | return ProcXF86DRICreateContext(client); | |
1241 | } | |
1242 | case X_XF86DRIDestroyContext:{ | |
1243 | EPHYR_LOG("leave\n"); | |
1244 | return ProcXF86DRIDestroyContext(client); | |
1245 | } | |
1246 | case X_XF86DRICreateDrawable:{ | |
1247 | EPHYR_LOG("leave\n"); | |
1248 | return ProcXF86DRICreateDrawable(client); | |
1249 | } | |
1250 | case X_XF86DRIDestroyDrawable:{ | |
1251 | EPHYR_LOG("leave\n"); | |
1252 | return ProcXF86DRIDestroyDrawable(client); | |
1253 | } | |
1254 | case X_XF86DRIGetDrawableInfo:{ | |
1255 | EPHYR_LOG("leave\n"); | |
1256 | return ProcXF86DRIGetDrawableInfo(client); | |
1257 | } | |
1258 | case X_XF86DRIGetDeviceInfo:{ | |
1259 | EPHYR_LOG("leave\n"); | |
1260 | return ProcXF86DRIGetDeviceInfo(client); | |
1261 | } | |
1262 | case X_XF86DRIAuthConnection:{ | |
1263 | EPHYR_LOG("leave\n"); | |
1264 | return ProcXF86DRIAuthConnection(client); | |
1265 | } | |
1266 | /* {Open,Close}FullScreen are deprecated now */ | |
1267 | default:{ | |
1268 | EPHYR_LOG("leave\n"); | |
1269 | return BadRequest; | |
1270 | } | |
1271 | } | |
1272 | } | |
1273 | ||
1274 | static int | |
1275 | SProcXF86DRIQueryVersion(register ClientPtr client) | |
1276 | { | |
1277 | REQUEST(xXF86DRIQueryVersionReq); | |
1278 | swaps(&stuff->length); | |
1279 | return ProcXF86DRIQueryVersion(client); | |
1280 | } | |
1281 | ||
1282 | static int | |
1283 | SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client) | |
1284 | { | |
1285 | REQUEST(xXF86DRIQueryDirectRenderingCapableReq); | |
1286 | swaps(&stuff->length); | |
1287 | swapl(&stuff->screen); | |
1288 | return ProcXF86DRIQueryDirectRenderingCapable(client); | |
1289 | } | |
1290 | ||
1291 | static int | |
1292 | SProcXF86DRIDispatch(register ClientPtr client) | |
1293 | { | |
1294 | REQUEST(xReq); | |
1295 | ||
1296 | EPHYR_LOG("enter\n"); | |
1297 | /* | |
1298 | * Only local clients are allowed DRI access, but remote clients still need | |
1299 | * these requests to find out cleanly. | |
1300 | */ | |
1301 | switch (stuff->data) { | |
1302 | case X_XF86DRIQueryVersion:{ | |
1303 | EPHYR_LOG("leave\n"); | |
1304 | return SProcXF86DRIQueryVersion(client); | |
1305 | } | |
1306 | case X_XF86DRIQueryDirectRenderingCapable:{ | |
1307 | EPHYR_LOG("leave\n"); | |
1308 | return SProcXF86DRIQueryDirectRenderingCapable(client); | |
1309 | } | |
1310 | default:{ | |
1311 | EPHYR_LOG("leave\n"); | |
1312 | return DRIErrorBase + XF86DRIClientNotLocal; | |
1313 | } | |
1314 | } | |
1315 | } | |
1316 | ||
1317 | Bool | |
1318 | ephyrDRIExtensionInit(ScreenPtr a_screen) | |
1319 | { | |
1320 | Bool is_ok = FALSE; | |
1321 | ExtensionEntry *extEntry = NULL; | |
1322 | EphyrDRIScreenPrivPtr screen_priv = NULL; | |
1323 | ||
1324 | EPHYR_LOG("enter\n"); | |
1325 | if (!host_has_extension(&xcb_xf86dri_id)) { | |
1326 | EPHYR_LOG("host does not have DRI extension\n"); | |
1327 | goto out; | |
1328 | } | |
1329 | EPHYR_LOG("host X does have DRI extension\n"); | |
1330 | if (!host_has_extension(&xcb_shape_id)) { | |
1331 | EPHYR_LOG("host does not have XShape extension\n"); | |
1332 | goto out; | |
1333 | } | |
1334 | EPHYR_LOG("host X does have XShape extension\n"); | |
1335 | ||
1336 | #ifdef XF86DRI_EVENTS | |
1337 | EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvents"); | |
1338 | if (!EventType) { | |
1339 | EPHYR_LOG_ERROR("failed to register DRI event resource type\n"); | |
1340 | goto out; | |
1341 | } | |
1342 | #endif | |
1343 | ||
1344 | if ((extEntry = AddExtension(XF86DRINAME, | |
1345 | XF86DRINumberEvents, | |
1346 | XF86DRINumberErrors, | |
1347 | ProcXF86DRIDispatch, | |
1348 | SProcXF86DRIDispatch, | |
1349 | NULL, StandardMinorOpcode))) { | |
1350 | DRIReqCode = (unsigned char) extEntry->base; | |
1351 | DRIErrorBase = extEntry->errorBase; | |
1352 | } | |
1353 | else { | |
1354 | EPHYR_LOG_ERROR("failed to register DRI extension\n"); | |
1355 | goto out; | |
1356 | } | |
1357 | if (!dixRegisterPrivateKey(&ephyrDRIScreenKeyRec, PRIVATE_SCREEN, 0)) | |
1358 | goto out; | |
1359 | if (!dixRegisterPrivateKey(&ephyrDRIWindowKeyRec, PRIVATE_WINDOW, 0)) | |
1360 | goto out; | |
1361 | screen_priv = calloc(1, sizeof(EphyrDRIScreenPrivRec)); | |
1362 | if (!screen_priv) { | |
1363 | EPHYR_LOG_ERROR("failed to allocate screen_priv\n"); | |
1364 | goto out; | |
1365 | } | |
1366 | dixSetPrivate(&a_screen->devPrivates, ephyrDRIScreenKey, screen_priv); | |
1367 | ||
1368 | if (!ephyrDRIScreenInit(a_screen)) { | |
1369 | EPHYR_LOG_ERROR("ephyrDRIScreenInit() failed\n"); | |
1370 | goto out; | |
1371 | } | |
1372 | EphyrMirrorHostVisuals(a_screen); | |
1373 | is_ok = TRUE; | |
1374 | out: | |
1375 | EPHYR_LOG("leave\n"); | |
1376 | return is_ok; | |
1377 | } |