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