2 * Xephyr - A kdrive X server thats runs in a host X window.
3 * Authored by Matthew Allum <mallum@openedhand.com>
5 * Copyright © 2007 OpenedHand Ltd
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.
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.
25 * This file is heavily copied from hw/xfree86/dri/xf86dri.c
28 * Dodji Seketeli <dodji@openedhand.com>
32 #include <kdrive-config.h>
38 #include <X11/Xproto.h>
39 #define _XF86DRI_SERVER_
40 #include <X11/dri/xf86dri.h>
41 #include <X11/dri/xf86driproto.h>
43 #include <xcb/shape.h>
44 #include <xcb/xf86dri.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"
56 #include "ephyrdriext.h"
58 #define _HAVE_XALLOC_DECLS
60 #include "protocol-versions.h"
64 } EphyrDRIWindowPrivRec
;
65 typedef EphyrDRIWindowPrivRec
*EphyrDRIWindowPrivPtr
;
68 CreateWindowProcPtr CreateWindow
;
69 DestroyWindowProcPtr DestroyWindow
;
70 MoveWindowProcPtr MoveWindow
;
71 PositionWindowProcPtr PositionWindow
;
72 ClipNotifyProcPtr ClipNotify
;
73 } EphyrDRIScreenPrivRec
;
74 typedef EphyrDRIScreenPrivRec
*EphyrDRIScreenPrivPtr
;
76 static int DRIErrorBase
;
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
,
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
);
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
);
92 static unsigned char DRIReqCode
= 0;
94 static DevPrivateKeyRec ephyrDRIWindowKeyRec
;
96 #define ephyrDRIWindowKey (&ephyrDRIWindowKeyRec)
97 static DevPrivateKeyRec ephyrDRIScreenKeyRec
;
99 #define ephyrDRIScreenKey (&ephyrDRIScreenKeyRec)
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))
107 ephyrDRIScreenInit(ScreenPtr a_screen
)
110 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
112 EPHYR_RETURN_VAL_IF_FAIL(a_screen
, FALSE
);
114 screen_priv
= GET_EPHYR_DRI_SCREEN_PRIV(a_screen
);
115 EPHYR_RETURN_VAL_IF_FAIL(screen_priv
, FALSE
);
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
;
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
;
135 ephyrDRICreateWindow(WindowPtr a_win
)
138 ScreenPtr screen
= NULL
;
139 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
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
);
147 EPHYR_LOG("enter. win:%p\n", a_win
);
149 screen
->CreateWindow
= screen_priv
->CreateWindow
;
150 is_ok
= (*screen
->CreateWindow
) (a_win
);
151 screen
->CreateWindow
= ephyrDRICreateWindow
;
154 dixSetPrivate(&a_win
->devPrivates
, ephyrDRIWindowKey
, NULL
);
160 ephyrDRIDestroyWindow(WindowPtr a_win
)
163 ScreenPtr screen
= NULL
;
164 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
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
);
172 screen
->DestroyWindow
= screen_priv
->DestroyWindow
;
173 if (screen
->DestroyWindow
) {
174 is_ok
= (*screen
->DestroyWindow
) (a_win
);
176 screen
->DestroyWindow
= ephyrDRIDestroyWindow
;
179 EphyrDRIWindowPrivPtr win_priv
= GET_EPHYR_DRI_WINDOW_PRIV(a_win
);
182 destroyHostPeerWindow(a_win
);
184 dixSetPrivate(&a_win
->devPrivates
, ephyrDRIWindowKey
, NULL
);
185 EPHYR_LOG("destroyed the remote peer window\n");
192 ephyrDRIMoveWindow(WindowPtr a_win
,
193 int a_x
, int a_y
, WindowPtr a_siblings
, VTKind a_kind
)
195 ScreenPtr screen
= NULL
;
196 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
197 EphyrDRIWindowPrivPtr win_priv
= NULL
;
198 EphyrWindowPair
*pair
= NULL
;
200 int x
= 0, y
= 0; /*coords relative to parent window */
202 EPHYR_RETURN_IF_FAIL(a_win
);
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
);
210 screen
->MoveWindow
= screen_priv
->MoveWindow
;
211 if (screen
->MoveWindow
) {
212 (*screen
->MoveWindow
) (a_win
, a_x
, a_y
, a_siblings
, a_kind
);
214 screen
->MoveWindow
= ephyrDRIMoveWindow
;
216 EPHYR_LOG("window: %p\n", a_win
);
217 if (!a_win
->parent
) {
218 EPHYR_LOG("cannot move root window\n");
221 win_priv
= GET_EPHYR_DRI_WINDOW_PRIV(a_win
);
223 EPHYR_LOG("not a DRI peered window\n");
226 if (!findWindowPairFromLocal(a_win
, &pair
) || !pair
) {
227 EPHYR_LOG_ERROR("failed to get window pair\n");
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
));
237 geo
.width
= a_win
->drawable
.width
;
238 geo
.height
= a_win
->drawable
.height
;
239 hostx_set_window_geometry(pair
->remote
, &geo
);
243 ephyrDRIPositionWindow(WindowPtr a_win
, int a_x
, int a_y
)
246 ScreenPtr screen
= NULL
;
247 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
248 EphyrDRIWindowPrivPtr win_priv
= NULL
;
249 EphyrWindowPair
*pair
= NULL
;
252 EPHYR_RETURN_VAL_IF_FAIL(a_win
, FALSE
);
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
);
260 screen
->PositionWindow
= screen_priv
->PositionWindow
;
261 if (screen
->PositionWindow
) {
262 (*screen
->PositionWindow
) (a_win
, a_x
, a_y
);
264 screen
->PositionWindow
= ephyrDRIPositionWindow
;
266 EPHYR_LOG("window: %p\n", a_win
);
267 win_priv
= GET_EPHYR_DRI_WINDOW_PRIV(a_win
);
269 EPHYR_LOG("not a DRI peered window\n");
273 if (!findWindowPairFromLocal(a_win
, &pair
) || !pair
) {
274 EPHYR_LOG_ERROR("failed to get window pair\n");
277 /*set the geometry to pass to hostx_set_window_geometry */
278 memset(&geo
, 0, sizeof(geo
));
281 geo
.width
= a_win
->drawable
.width
;
282 geo
.height
= a_win
->drawable
.height
;
283 hostx_set_window_geometry(pair
->remote
, &geo
);
287 EPHYR_LOG("leave. is_ok:%d\n", is_ok
);
293 ephyrDRIClipNotify(WindowPtr a_win
, int a_x
, int a_y
)
295 ScreenPtr screen
= NULL
;
296 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
297 EphyrDRIWindowPrivPtr win_priv
= NULL
;
298 EphyrWindowPair
*pair
= NULL
;
299 EphyrRect
*rects
= NULL
;
302 EPHYR_RETURN_IF_FAIL(a_win
);
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
);
310 screen
->ClipNotify
= screen_priv
->ClipNotify
;
311 if (screen
->ClipNotify
) {
312 (*screen
->ClipNotify
) (a_win
, a_x
, a_y
);
314 screen
->ClipNotify
= ephyrDRIClipNotify
;
316 EPHYR_LOG("window: %p\n", a_win
);
317 win_priv
= GET_EPHYR_DRI_WINDOW_PRIV(a_win
);
319 EPHYR_LOG("not a DRI peered window\n");
322 if (!findWindowPairFromLocal(a_win
, &pair
) || !pair
) {
323 EPHYR_LOG_ERROR("failed to get window pair\n");
326 rects
= calloc(RegionNumRects(&a_win
->clipList
), sizeof(EphyrRect
));
327 for (i
= 0; i
< RegionNumRects(&a_win
->clipList
); 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
;
336 * push the clipping region of this window
337 * to the peer window in the host
339 hostx_set_window_bounding_rectangles
340 (pair
->remote
, rects
, RegionNumRects(&a_win
->clipList
));
346 EPHYR_LOG("leave.\n");
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
360 EphyrDuplicateVisual(unsigned int a_screen
,
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
)
369 Bool is_ok
= FALSE
, found_visual
= FALSE
, found_depth
= FALSE
;
370 ScreenPtr screen
= NULL
;
371 VisualRec new_visual
, *new_visuals
= NULL
;
374 EPHYR_LOG("enter\n");
375 if (a_screen
>= screenInfo
.numScreens
) {
376 EPHYR_LOG_ERROR("bad screen number\n");
379 memset(&new_visual
, 0, sizeof(VisualRec
));
381 /*get the screen pointed to by a_screen */
382 screen
= screenInfo
.screens
[a_screen
];
383 EPHYR_RETURN_VAL_IF_FAIL(screen
, FALSE
);
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.
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
;
401 EPHYR_LOG("found a visual that matches visual id: %d\n", a_new_id
);
406 EPHYR_LOG("did not find any visual matching %d\n", a_new_id
);
410 * be prepare to extend screen->visuals to add new_visual to it
412 new_visuals
= calloc(screen
->numVisuals
+ 1, sizeof(VisualRec
));
414 screen
->visuals
, screen
->numVisuals
* sizeof(VisualRec
));
415 memmove(&new_visuals
[screen
->numVisuals
], &new_visual
, sizeof(VisualRec
));
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
422 for (i
= 0; i
< screen
->numDepths
; i
++) {
423 VisualID
*vids
= NULL
;
424 DepthPtr cur_depth
= NULL
;
426 /*find the entry matching a_depth */
427 if (screen
->allowedDepths
[i
].depth
!= a_depth
)
429 cur_depth
= &screen
->allowedDepths
[i
];
431 * extend the list of visual IDs in that entry,
432 * so to add a_new_id in there.
434 vids
= realloc(cur_depth
->vids
,
435 (cur_depth
->numVids
+ 1) * sizeof(VisualID
));
437 EPHYR_LOG_ERROR("failed to realloc numids\n");
440 vids
[cur_depth
->numVids
] = a_new_id
;
442 * Okay now commit our change.
443 * Do really update screen->allowedDepths[i]
445 cur_depth
->numVids
++;
446 cur_depth
->vids
= vids
;
450 EPHYR_LOG_ERROR("failed to update screen[%d]->allowedDepth\n",
455 * Commit our change to screen->visuals
457 free(screen
->visuals
);
458 screen
->visuals
= new_visuals
;
459 screen
->numVisuals
++;
467 EPHYR_LOG("leave\n");
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
478 EphyrMirrorHostVisuals(ScreenPtr a_screen
)
481 EphyrHostVisualInfo
*visuals
= NULL
;
482 int nb_visuals
= 0, i
= 0;
484 EPHYR_LOG("enter\n");
485 if (!hostx_get_visuals_info(&visuals
, &nb_visuals
)) {
486 EPHYR_LOG_ERROR("failed to get host visuals\n");
489 for (i
= 0; i
< nb_visuals
; i
++) {
490 if (!EphyrDuplicateVisual(a_screen
->myNum
,
493 visuals
[i
].bits_per_rgb
,
494 visuals
[i
].colormap_size
,
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
);
505 EPHYR_LOG("leave\n");
510 ProcXF86DRIQueryVersion(register ClientPtr client
)
512 xXF86DRIQueryVersionReply rep
= {
514 .sequenceNumber
= client
->sequence
,
516 .majorVersion
= SERVER_XF86DRI_MAJOR_VERSION
,
517 .minorVersion
= SERVER_XF86DRI_MINOR_VERSION
,
518 .patchVersion
= SERVER_XF86DRI_PATCH_VERSION
521 REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq
);
523 EPHYR_LOG("enter\n");
525 if (client
->swapped
) {
526 swaps(&rep
.sequenceNumber
);
528 swaps(&rep
.majorVersion
);
529 swaps(&rep
.minorVersion
);
530 swapl(&rep
.patchVersion
);
532 WriteToClient(client
, sizeof(xXF86DRIQueryVersionReply
), &rep
);
533 EPHYR_LOG("leave\n");
538 ProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client
)
540 xXF86DRIQueryDirectRenderingCapableReply rep
;
543 REQUEST(xXF86DRIQueryDirectRenderingCapableReq
);
544 REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq
);
546 EPHYR_LOG("enter\n");
547 if (stuff
->screen
>= screenInfo
.numScreens
) {
548 client
->errorValue
= stuff
->screen
;
552 if (!ephyrDRIQueryDirectRenderingCapable(stuff
->screen
, &isCapable
)) {
556 if (!client
->local
|| client
->swapped
)
559 rep
= (xXF86DRIQueryDirectRenderingCapableReply
) {
561 .sequenceNumber
= client
->sequence
,
563 .isCapable
= isCapable
566 if (client
->swapped
) {
567 swaps(&rep
.sequenceNumber
);
571 WriteToClient(client
, sizeof(xXF86DRIQueryDirectRenderingCapableReply
),
573 EPHYR_LOG("leave\n");
579 ProcXF86DRIOpenConnection(register ClientPtr client
)
581 xXF86DRIOpenConnectionReply rep
;
583 char *busIdString
= NULL
;
584 CARD32 busIdStringLength
= 0;
586 REQUEST(xXF86DRIOpenConnectionReq
);
587 REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq
);
589 EPHYR_LOG("enter\n");
590 if (stuff
->screen
>= screenInfo
.numScreens
) {
591 client
->errorValue
= stuff
->screen
;
595 if (!ephyrDRIOpenConnection(stuff
->screen
, &hSAREA
, &busIdString
)) {
600 busIdStringLength
= strlen(busIdString
);
602 rep
= (xXF86DRIOpenConnectionReply
) {
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),
614 .busIdStringLength
= busIdStringLength
617 WriteToClient(client
, sizeof(xXF86DRIOpenConnectionReply
), &rep
);
618 if (busIdStringLength
)
619 WriteToClient(client
, busIdStringLength
, busIdString
);
621 EPHYR_LOG("leave\n");
626 ProcXF86DRIAuthConnection(register ClientPtr client
)
628 xXF86DRIAuthConnectionReply rep
;
630 REQUEST(xXF86DRIAuthConnectionReq
);
631 REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq
);
633 EPHYR_LOG("enter\n");
634 if (stuff
->screen
>= screenInfo
.numScreens
) {
635 client
->errorValue
= stuff
->screen
;
639 rep
= (xXF86DRIAuthConnectionReply
) {
641 .sequenceNumber
= client
->sequence
,
646 if (!ephyrDRIAuthConnection(stuff
->screen
, stuff
->magic
)) {
647 ErrorF("Failed to authenticate %lu\n", (unsigned long) stuff
->magic
);
648 rep
.authenticated
= 0;
650 WriteToClient(client
, sizeof(xXF86DRIAuthConnectionReply
), &rep
);
651 EPHYR_LOG("leave\n");
656 ProcXF86DRICloseConnection(register ClientPtr client
)
658 REQUEST(xXF86DRICloseConnectionReq
);
659 REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq
);
660 EPHYR_LOG("enter\n");
661 if (stuff
->screen
>= screenInfo
.numScreens
) {
662 client
->errorValue
= stuff
->screen
;
667 DRICloseConnection( screenInfo.screens[stuff->screen]);
670 EPHYR_LOG("leave\n");
675 ProcXF86DRIGetClientDriverName(register ClientPtr client
)
677 xXF86DRIGetClientDriverNameReply rep
= {
679 .sequenceNumber
= client
->sequence
,
680 .clientDriverNameLength
= 0
682 char *clientDriverName
;
684 REQUEST(xXF86DRIGetClientDriverNameReq
);
685 REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq
);
687 EPHYR_LOG("enter\n");
688 if (stuff
->screen
>= screenInfo
.numScreens
) {
689 client
->errorValue
= stuff
->screen
;
693 ephyrDRIGetClientDriverName(stuff
->screen
,
694 (int *) &rep
.ddxDriverMajorVersion
,
695 (int *) &rep
.ddxDriverMinorVersion
,
696 (int *) &rep
.ddxDriverPatchVersion
,
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
));
704 WriteToClient(client
, sizeof(xXF86DRIGetClientDriverNameReply
), &rep
);
705 if (rep
.clientDriverNameLength
)
706 WriteToClient(client
, rep
.clientDriverNameLength
, clientDriverName
);
707 EPHYR_LOG("leave\n");
712 ProcXF86DRICreateContext(register ClientPtr client
)
714 xXF86DRICreateContextReply rep
= {
716 .sequenceNumber
= client
->sequence
,
723 REQUEST(xXF86DRICreateContextReq
);
724 REQUEST_SIZE_MATCH(xXF86DRICreateContextReq
);
726 EPHYR_LOG("enter\n");
727 if (stuff
->screen
>= screenInfo
.numScreens
) {
728 client
->errorValue
= stuff
->screen
;
732 pScreen
= screenInfo
.screens
[stuff
->screen
];
733 visual
= pScreen
->visuals
;
735 /* Find the requested X visual */
736 for (i
= 0; i
< pScreen
->numVisuals
; i
++, visual
++)
737 if (visual
->vid
== stuff
->visual
)
739 if (i
== pScreen
->numVisuals
) {
740 /* No visual found */
744 if (!ephyrDRICreateContext(stuff
->screen
,
747 (drm_context_t
*) &rep
.hHWContext
)) {
751 WriteToClient(client
, sizeof(xXF86DRICreateContextReply
), &rep
);
752 EPHYR_LOG("leave\n");
757 ProcXF86DRIDestroyContext(register ClientPtr client
)
759 REQUEST(xXF86DRIDestroyContextReq
);
760 REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq
);
761 EPHYR_LOG("enter\n");
763 if (stuff
->screen
>= screenInfo
.numScreens
) {
764 client
->errorValue
= stuff
->screen
;
768 if (!ephyrDRIDestroyContext(stuff
->screen
, stuff
->context
)) {
772 EPHYR_LOG("leave\n");
777 getWindowVisual(const WindowPtr a_win
, VisualPtr
* a_visual
)
779 int i
= 0, visual_id
= 0;
781 EPHYR_RETURN_VAL_IF_FAIL(a_win
782 && a_win
->drawable
.pScreen
783 && a_win
->drawable
.pScreen
->visuals
, FALSE
);
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
];
795 #define NUM_WINDOW_PAIRS 256
796 static EphyrWindowPair window_pairs
[NUM_WINDOW_PAIRS
];
799 appendWindowPairToList(WindowPtr a_local
, int a_remote
)
803 EPHYR_RETURN_VAL_IF_FAIL(a_local
, FALSE
);
805 EPHYR_LOG("(local,remote):(%p, %d)\n", a_local
, a_remote
);
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
;
818 findWindowPairFromLocal(WindowPtr a_local
, EphyrWindowPair
** a_pair
)
822 EPHYR_RETURN_VAL_IF_FAIL(a_pair
&& a_local
, FALSE
);
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
);
835 findWindowPairFromRemote(int a_remote
, EphyrWindowPair
** a_pair
)
839 EPHYR_RETURN_VAL_IF_FAIL(a_pair
, FALSE
);
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
);
852 createHostPeerWindow(const WindowPtr a_win
, int *a_peer_win
)
855 VisualPtr visual
= NULL
;
858 EPHYR_RETURN_VAL_IF_FAIL(a_win
&& a_peer_win
, FALSE
);
859 EPHYR_RETURN_VAL_IF_FAIL(a_win
->drawable
.pScreen
, FALSE
);
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");
867 EPHYR_LOG_ERROR("failed to create visual\n");
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");
880 if (!appendWindowPairToList(a_win
, *a_peer_win
)) {
881 EPHYR_LOG_ERROR("failed to append window to pair list\n");
886 EPHYR_LOG("leave:remote win%d\n", *a_peer_win
);
891 destroyHostPeerWindow(const WindowPtr a_win
)
894 EphyrWindowPair
*pair
= NULL
;
896 EPHYR_RETURN_VAL_IF_FAIL(a_win
, FALSE
);
898 EPHYR_LOG("enter\n");
900 if (!findWindowPairFromLocal(a_win
, &pair
) || !pair
) {
901 EPHYR_LOG_ERROR("failed to find peer to local window\n");
904 hostx_destroy_window(pair
->remote
);
908 EPHYR_LOG("leave\n");
913 ProcXF86DRICreateDrawable(ClientPtr client
)
915 xXF86DRICreateDrawableReply rep
= {
917 .sequenceNumber
= client
->sequence
,
920 DrawablePtr drawable
= NULL
;
921 WindowPtr window
= NULL
;
922 EphyrWindowPair
*pair
= NULL
;
923 EphyrDRIWindowPrivPtr win_priv
= NULL
;
924 int rc
= 0, remote_win
= 0;
926 REQUEST(xXF86DRICreateDrawableReq
);
927 REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq
);
929 EPHYR_LOG("enter\n");
930 if (stuff
->screen
>= screenInfo
.numScreens
) {
931 client
->errorValue
= stuff
->screen
;
935 rc
= dixLookupDrawable(&drawable
, stuff
->drawable
, client
, 0,
939 if (drawable
->type
!= DRAWABLE_WINDOW
) {
940 EPHYR_LOG_ERROR("non drawable windows are not yet supported\n");
941 return BadImplementation
;
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",
950 else if (!createHostPeerWindow(window
, &remote_win
)) {
951 EPHYR_LOG_ERROR("failed to create host peer window\n");
955 if (!ephyrDRICreateDrawable(stuff
->screen
,
957 (drm_drawable_t
*) &rep
.hHWDrawable
)) {
958 EPHYR_LOG_ERROR("failed to create dri drawable\n");
962 win_priv
= GET_EPHYR_DRI_WINDOW_PRIV(window
);
964 win_priv
= calloc(1, sizeof(EphyrDRIWindowPrivRec
));
966 EPHYR_LOG_ERROR("failed to allocate window private\n");
969 dixSetPrivate(&window
->devPrivates
, ephyrDRIWindowKey
, win_priv
);
970 EPHYR_LOG("paired window '%p' with remote '%d'\n", window
, remote_win
);
973 WriteToClient(client
, sizeof(xXF86DRICreateDrawableReply
), &rep
);
974 EPHYR_LOG("leave\n");
979 ProcXF86DRIDestroyDrawable(register ClientPtr client
)
981 DrawablePtr drawable
= NULL
;
982 WindowPtr window
= NULL
;
983 EphyrWindowPair
*pair
= NULL
;
986 REQUEST(xXF86DRIDestroyDrawableReq
);
987 REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq
);
989 EPHYR_LOG("enter\n");
990 if (stuff
->screen
>= screenInfo
.numScreens
) {
991 client
->errorValue
= stuff
->screen
;
995 rc
= dixLookupDrawable(&drawable
,
996 stuff
->drawable
, client
, 0, DixReadAccess
);
999 if (drawable
->type
!= DRAWABLE_WINDOW
) {
1000 EPHYR_LOG_ERROR("non drawable windows are not yet supported\n");
1001 return BadImplementation
;
1003 window
= (WindowPtr
) drawable
;
1004 if (!findWindowPairFromLocal(window
, &pair
) && pair
) {
1005 EPHYR_LOG_ERROR("failed to find pair window\n");
1006 return BadImplementation
;
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
;
1016 EPHYR_LOG("leave\n");
1021 ProcXF86DRIGetDrawableInfo(register ClientPtr client
)
1023 xXF86DRIGetDrawableInfoReply rep
= {
1025 .sequenceNumber
= client
->sequence
,
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
;
1035 REQUEST(xXF86DRIGetDrawableInfoReq
);
1036 REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq
);
1038 EPHYR_LOG("enter\n");
1039 if (stuff
->screen
>= screenInfo
.numScreens
) {
1040 client
->errorValue
= stuff
->screen
;
1044 rc
= dixLookupDrawable(&drawable
, stuff
->drawable
, client
, 0,
1046 if (rc
!= Success
|| !drawable
) {
1047 EPHYR_LOG_ERROR("could not get drawable\n");
1051 if (drawable
->type
!= DRAWABLE_WINDOW
) {
1052 EPHYR_LOG_ERROR("non windows type drawables are not yes supported\n");
1053 return BadImplementation
;
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");
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
);
1070 if (!ephyrDRIGetDrawableInfo(stuff
->screen
,
1071 pair
->remote
/*the drawable in hostx */ ,
1072 (unsigned int *) &rep
.drawableTableIndex
,
1073 (unsigned int *) &rep
.drawableTableStamp
,
1078 (int *) &rep
.numClipRects
,
1082 (int *) &rep
.numBackClipRects
,
1086 EPHYR_LOG("num clip rects:%d, num back clip rects:%d\n",
1087 (int) rep
.numClipRects
, (int) rep
.numBackClipRects
);
1091 rep
.drawableWidth
= W
;
1092 rep
.drawableHeight
= H
;
1093 rep
.length
= (SIZEOF(xXF86DRIGetDrawableInfoReply
) - SIZEOF(xGenericReply
));
1098 if (rep
.numClipRects
) {
1100 ScreenPtr pScreen
= screenInfo
.screens
[stuff
->screen
];
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
);
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
);
1118 rep
.numClipRects
= 0;
1122 EPHYR_LOG("got zero host gl drawable clipping rects\n");
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
);
1132 rep
.length
= bytes_to_int32(rep
.length
);
1134 WriteToClient(client
, sizeof(xXF86DRIGetDrawableInfoReply
), &rep
);
1136 if (rep
.numClipRects
) {
1137 WriteToClient(client
,
1138 sizeof(drm_clip_rect_t
) * rep
.numClipRects
,
1142 if (rep
.numBackClipRects
) {
1143 WriteToClient(client
,
1144 sizeof(drm_clip_rect_t
) * rep
.numBackClipRects
,
1150 EPHYR_LOG("leave\n");
1156 ProcXF86DRIGetDeviceInfo(register ClientPtr client
)
1158 xXF86DRIGetDeviceInfoReply rep
= {
1160 .sequenceNumber
= client
->sequence
,
1163 drm_handle_t hFrameBuffer
;
1166 REQUEST(xXF86DRIGetDeviceInfoReq
);
1167 REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq
);
1169 EPHYR_LOG("enter\n");
1170 if (stuff
->screen
>= screenInfo
.numScreens
) {
1171 client
->errorValue
= stuff
->screen
;
1175 if (!ephyrDRIGetDeviceInfo(stuff
->screen
,
1177 (int *) &rep
.framebufferOrigin
,
1178 (int *) &rep
.framebufferSize
,
1179 (int *) &rep
.framebufferStride
,
1180 (int *) &rep
.devPrivateSize
, &pDevPrivate
)) {
1184 rep
.hFrameBufferLow
= (CARD32
) (hFrameBuffer
& 0xffffffff);
1185 #if defined(LONG64) && !defined(__linux__)
1186 rep
.hFrameBufferHigh
= (CARD32
) (hFrameBuffer
>> 32);
1188 rep
.hFrameBufferHigh
= 0;
1191 if (rep
.devPrivateSize
) {
1192 rep
.length
= bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply
) -
1193 SIZEOF(xGenericReply
) +
1194 pad_to_int32(rep
.devPrivateSize
));
1197 WriteToClient(client
, sizeof(xXF86DRIGetDeviceInfoReply
), &rep
);
1199 WriteToClient(client
, rep
.devPrivateSize
, pDevPrivate
);
1201 EPHYR_LOG("leave\n");
1206 ProcXF86DRIDispatch(register ClientPtr client
)
1209 EPHYR_LOG("enter\n");
1211 switch (stuff
->data
) {
1212 case X_XF86DRIQueryVersion
:{
1213 EPHYR_LOG("leave\n");
1214 return ProcXF86DRIQueryVersion(client
);
1216 case X_XF86DRIQueryDirectRenderingCapable
:{
1217 EPHYR_LOG("leave\n");
1218 return ProcXF86DRIQueryDirectRenderingCapable(client
);
1223 return DRIErrorBase
+ XF86DRIClientNotLocal
;
1225 switch (stuff
->data
) {
1226 case X_XF86DRIOpenConnection
:{
1227 EPHYR_LOG("leave\n");
1228 return ProcXF86DRIOpenConnection(client
);
1230 case X_XF86DRICloseConnection
:{
1231 EPHYR_LOG("leave\n");
1232 return ProcXF86DRICloseConnection(client
);
1234 case X_XF86DRIGetClientDriverName
:{
1235 EPHYR_LOG("leave\n");
1236 return ProcXF86DRIGetClientDriverName(client
);
1238 case X_XF86DRICreateContext
:{
1239 EPHYR_LOG("leave\n");
1240 return ProcXF86DRICreateContext(client
);
1242 case X_XF86DRIDestroyContext
:{
1243 EPHYR_LOG("leave\n");
1244 return ProcXF86DRIDestroyContext(client
);
1246 case X_XF86DRICreateDrawable
:{
1247 EPHYR_LOG("leave\n");
1248 return ProcXF86DRICreateDrawable(client
);
1250 case X_XF86DRIDestroyDrawable
:{
1251 EPHYR_LOG("leave\n");
1252 return ProcXF86DRIDestroyDrawable(client
);
1254 case X_XF86DRIGetDrawableInfo
:{
1255 EPHYR_LOG("leave\n");
1256 return ProcXF86DRIGetDrawableInfo(client
);
1258 case X_XF86DRIGetDeviceInfo
:{
1259 EPHYR_LOG("leave\n");
1260 return ProcXF86DRIGetDeviceInfo(client
);
1262 case X_XF86DRIAuthConnection
:{
1263 EPHYR_LOG("leave\n");
1264 return ProcXF86DRIAuthConnection(client
);
1266 /* {Open,Close}FullScreen are deprecated now */
1268 EPHYR_LOG("leave\n");
1275 SProcXF86DRIQueryVersion(register ClientPtr client
)
1277 REQUEST(xXF86DRIQueryVersionReq
);
1278 swaps(&stuff
->length
);
1279 return ProcXF86DRIQueryVersion(client
);
1283 SProcXF86DRIQueryDirectRenderingCapable(register ClientPtr client
)
1285 REQUEST(xXF86DRIQueryDirectRenderingCapableReq
);
1286 swaps(&stuff
->length
);
1287 swapl(&stuff
->screen
);
1288 return ProcXF86DRIQueryDirectRenderingCapable(client
);
1292 SProcXF86DRIDispatch(register ClientPtr client
)
1296 EPHYR_LOG("enter\n");
1298 * Only local clients are allowed DRI access, but remote clients still need
1299 * these requests to find out cleanly.
1301 switch (stuff
->data
) {
1302 case X_XF86DRIQueryVersion
:{
1303 EPHYR_LOG("leave\n");
1304 return SProcXF86DRIQueryVersion(client
);
1306 case X_XF86DRIQueryDirectRenderingCapable
:{
1307 EPHYR_LOG("leave\n");
1308 return SProcXF86DRIQueryDirectRenderingCapable(client
);
1311 EPHYR_LOG("leave\n");
1312 return DRIErrorBase
+ XF86DRIClientNotLocal
;
1318 ephyrDRIExtensionInit(ScreenPtr a_screen
)
1321 ExtensionEntry
*extEntry
= NULL
;
1322 EphyrDRIScreenPrivPtr screen_priv
= NULL
;
1324 EPHYR_LOG("enter\n");
1325 if (!host_has_extension(&xcb_xf86dri_id
)) {
1326 EPHYR_LOG("host does not have DRI extension\n");
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");
1334 EPHYR_LOG("host X does have XShape extension\n");
1336 #ifdef XF86DRI_EVENTS
1337 EventType
= CreateNewResourceType(XF86DRIFreeEvents
, "DRIEvents");
1339 EPHYR_LOG_ERROR("failed to register DRI event resource type\n");
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
;
1354 EPHYR_LOG_ERROR("failed to register DRI extension\n");
1357 if (!dixRegisterPrivateKey(&ephyrDRIScreenKeyRec
, PRIVATE_SCREEN
, 0))
1359 if (!dixRegisterPrivateKey(&ephyrDRIWindowKeyRec
, PRIVATE_WINDOW
, 0))
1361 screen_priv
= calloc(1, sizeof(EphyrDRIScreenPrivRec
));
1363 EPHYR_LOG_ERROR("failed to allocate screen_priv\n");
1366 dixSetPrivate(&a_screen
->devPrivates
, ephyrDRIScreenKey
, screen_priv
);
1368 if (!ephyrDRIScreenInit(a_screen
)) {
1369 EPHYR_LOG_ERROR("ephyrDRIScreenInit() failed\n");
1372 EphyrMirrorHostVisuals(a_screen
);
1375 EPHYR_LOG("leave\n");