Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / kdrive / ephyr / ephyrdriext.c
CommitLineData
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
62typedef struct {
63 int foo;
64} EphyrDRIWindowPrivRec;
65typedef EphyrDRIWindowPrivRec *EphyrDRIWindowPrivPtr;
66
67typedef struct {
68 CreateWindowProcPtr CreateWindow;
69 DestroyWindowProcPtr DestroyWindow;
70 MoveWindowProcPtr MoveWindow;
71 PositionWindowProcPtr PositionWindow;
72 ClipNotifyProcPtr ClipNotify;
73} EphyrDRIScreenPrivRec;
74typedef EphyrDRIScreenPrivRec *EphyrDRIScreenPrivPtr;
75
76static int DRIErrorBase;
77
78static Bool ephyrDRIScreenInit(ScreenPtr a_screen);
79static Bool ephyrDRICreateWindow(WindowPtr a_win);
80static Bool ephyrDRIDestroyWindow(WindowPtr a_win);
81static void ephyrDRIMoveWindow(WindowPtr a_win,
82 int a_x, int a_y,
83 WindowPtr a_siblings, VTKind a_kind);
84static Bool ephyrDRIPositionWindow(WindowPtr a_win, int x, int y);
85static void ephyrDRIClipNotify(WindowPtr a_win, int a_x, int a_y);
86
87static Bool EphyrMirrorHostVisuals(ScreenPtr a_screen);
88static Bool destroyHostPeerWindow(const WindowPtr a_win);
89static Bool findWindowPairFromLocal(WindowPtr a_local,
90 EphyrWindowPair ** a_pair);
91
92static unsigned char DRIReqCode = 0;
93
94static DevPrivateKeyRec ephyrDRIWindowKeyRec;
95
96#define ephyrDRIWindowKey (&ephyrDRIWindowKeyRec)
97static 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
106static Bool
107ephyrDRIScreenInit(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
134static Bool
135ephyrDRICreateWindow(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
159static Bool
160ephyrDRIDestroyWindow(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
191static void
192ephyrDRIMoveWindow(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
242static Bool
243ephyrDRIPositionWindow(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
292static void
293ephyrDRIClipNotify(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 */
359static Bool
360EphyrDuplicateVisual(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 */
477static Bool
478EphyrMirrorHostVisuals(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
509static int
510ProcXF86DRIQueryVersion(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
537static int
538ProcXF86DRIQueryDirectRenderingCapable(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
578static int
579ProcXF86DRIOpenConnection(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
625static int
626ProcXF86DRIAuthConnection(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
655static int
656ProcXF86DRICloseConnection(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
674static int
675ProcXF86DRIGetClientDriverName(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
711static int
712ProcXF86DRICreateContext(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
756static int
757ProcXF86DRIDestroyContext(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
776static Bool
777getWindowVisual(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
796static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS];
797
798static Bool
799appendWindowPairToList(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
817static Bool
818findWindowPairFromLocal(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
834Bool
835findWindowPairFromRemote(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
851static Bool
852createHostPeerWindow(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
890static Bool
891destroyHostPeerWindow(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
912static int
913ProcXF86DRICreateDrawable(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
978static int
979ProcXF86DRIDestroyDrawable(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
1020static int
1021ProcXF86DRIGetDrawableInfo(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
1155static int
1156ProcXF86DRIGetDeviceInfo(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
1205static int
1206ProcXF86DRIDispatch(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
1274static int
1275SProcXF86DRIQueryVersion(register ClientPtr client)
1276{
1277 REQUEST(xXF86DRIQueryVersionReq);
1278 swaps(&stuff->length);
1279 return ProcXF86DRIQueryVersion(client);
1280}
1281
1282static int
1283SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client)
1284{
1285 REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
1286 swaps(&stuff->length);
1287 swapl(&stuff->screen);
1288 return ProcXF86DRIQueryDirectRenderingCapable(client);
1289}
1290
1291static int
1292SProcXF86DRIDispatch(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
1317Bool
1318ephyrDRIExtensionInit(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}