Home | History | Annotate | Line # | Download | only in ephyr
      1 /*
      2  * Xephyr - A kdrive X server thats runs in a host X window.
      3  *          Authored by Matthew Allum <mallum (at) 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 (at) 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 
     59 typedef struct {
     60     int foo;
     61 } EphyrDRIWindowPrivRec;
     62 typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr;
     63 
     64 typedef struct {
     65     CreateWindowProcPtr CreateWindow ;
     66     DestroyWindowProcPtr DestroyWindow ;
     67     MoveWindowProcPtr MoveWindow ;
     68     PositionWindowProcPtr PositionWindow ;
     69     ClipNotifyProcPtr ClipNotify ;
     70 } EphyrDRIScreenPrivRec;
     71 typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr;
     72 
     73 static int DRIErrorBase;
     74 
     75 
     76 
     77 static Bool ephyrDRIScreenInit (ScreenPtr a_screen) ;
     78 static Bool ephyrDRICreateWindow (WindowPtr a_win) ;
     79 static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ;
     80 static void ephyrDRIMoveWindow (WindowPtr a_win,
     81                                 int a_x, int a_y,
     82                                 WindowPtr a_siblings,
     83                                 VTKind a_kind);
     84 static Bool ephyrDRIPositionWindow (WindowPtr a_win,
     85                                     int x, int y) ;
     86 static void ephyrDRIClipNotify (WindowPtr a_win,
     87                                 int a_x, int a_y) ;
     88 
     89 static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ;
     90 static Bool destroyHostPeerWindow (const WindowPtr a_win) ;
     91 static Bool findWindowPairFromLocal (WindowPtr a_local,
     92                                      EphyrWindowPair **a_pair);
     93 
     94 static unsigned char DRIReqCode = 0;
     95 
     96 static DevPrivateKeyRec ephyrDRIWindowKeyRec;
     97 #define ephyrDRIWindowKey (&ephyrDRIWindowKeyRec)
     98 static 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 
    106 static Bool
    107 ephyrDRIScreenInit (ScreenPtr a_screen)
    108 {
    109     Bool is_ok=FALSE ;
    110     EphyrDRIScreenPrivPtr screen_priv=NULL ;
    111 
    112     EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ;
    113 
    114     screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ;
    115     EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ;
    116 
    117     screen_priv->CreateWindow = a_screen->CreateWindow ;
    118     screen_priv->DestroyWindow = a_screen->DestroyWindow ;
    119     screen_priv->MoveWindow = a_screen->MoveWindow ;
    120     screen_priv->PositionWindow = a_screen->PositionWindow ;
    121     screen_priv->ClipNotify = a_screen->ClipNotify ;
    122 
    123     a_screen->CreateWindow = ephyrDRICreateWindow ;
    124     a_screen->DestroyWindow = ephyrDRIDestroyWindow ;
    125     a_screen->MoveWindow = ephyrDRIMoveWindow ;
    126     a_screen->PositionWindow = ephyrDRIPositionWindow ;
    127     a_screen->ClipNotify = ephyrDRIClipNotify ;
    128 
    129     is_ok = TRUE ;
    130 
    131     return is_ok ;
    132 }
    133 
    134 static Bool
    135 ephyrDRICreateWindow (WindowPtr a_win)
    136 {
    137     Bool is_ok=FALSE ;
    138     ScreenPtr screen=NULL ;
    139     EphyrDRIScreenPrivPtr screen_priv =NULL;
    140 
    141     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
    142     screen = a_win->drawable.pScreen ;
    143     EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
    144     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
    145     EPHYR_RETURN_VAL_IF_FAIL (screen_priv
    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 
    161 static Bool
    162 ephyrDRIDestroyWindow (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 
    194 static void
    195 ephyrDRIMoveWindow (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 
    251 out:
    252     EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
    253     /*do cleanup here*/
    254 }
    255 
    256 static Bool
    257 ephyrDRIPositionWindow (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 
    303 out:
    304     EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
    305     /*do cleanup here*/
    306     return is_ok ;
    307 }
    308 
    309 static void
    310 ephyrDRIClipNotify (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 
    367 out:
    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  */
    384 static Bool
    385 EphyrDuplicateVisual (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 ;
    492 out:
    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  */
    506 static Bool
    507 EphyrMirrorHostVisuals (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 ;
    534 out:
    535     EPHYR_LOG ("leave\n") ;
    536     return is_ok;
    537 }
    538 
    539 
    540 static int
    541 ProcXF86DRIQueryVersion (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 
    567 static int
    568 ProcXF86DRIQueryDirectRenderingCapable (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 
    605 static int
    606 ProcXF86DRIOpenConnection (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 
    649 static int
    650 ProcXF86DRIAuthConnection  (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 
    676 static int
    677 ProcXF86DRICloseConnection (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 
    695 static int
    696 ProcXF86DRIGetClientDriverName (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 
    734 static int
    735 ProcXF86DRICreateContext (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 
    780 static int
    781 ProcXF86DRIDestroyContext (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 
    800 static Bool
    801 getWindowVisual (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
    822 static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ;
    823 
    824 static Bool
    825 appendWindowPairToList (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 
    844 static Bool
    845 findWindowPairFromLocal (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 
    864 Bool
    865 findWindowPairFromRemote (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 
    884 static Bool
    885 createHostPeerWindow (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 ;
    920 out:
    921     EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ;
    922     return is_ok ;
    923 }
    924 
    925 static Bool
    926 destroyHostPeerWindow (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 
    941 out:
    942     EPHYR_LOG ("leave\n") ;
    943     return is_ok;
    944 }
    945 
    946 static int
    947 ProcXF86DRICreateDrawable (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 
   1011 static int
   1012 ProcXF86DRIDestroyDrawable (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 
   1055 static int
   1056 ProcXF86DRIGetDrawableInfo (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 
   1189 static int
   1190 ProcXF86DRIGetDeviceInfo (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 
   1240 static int
   1241 ProcXF86DRIDispatch (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 
   1311 static int
   1312 SProcXF86DRIQueryVersion (register ClientPtr	client)
   1313 {
   1314     register int n;
   1315     REQUEST(xXF86DRIQueryVersionReq);
   1316     swaps(&stuff->length, n);
   1317     return ProcXF86DRIQueryVersion(client);
   1318 }
   1319 
   1320 static int
   1321 SProcXF86DRIQueryDirectRenderingCapable (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 
   1330 static int
   1331 SProcXF86DRIDispatch (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 
   1357 Bool
   1358 ephyrDRIExtensionInit (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 ;
   1414 out:
   1415     EPHYR_LOG ("leave\n") ;
   1416     return is_ok ;
   1417 }
   1418