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