xf86dri.c revision 6747b715
1/************************************************************************** 2 3Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4Copyright 2000 VA Linux Systems, Inc. 5All Rights Reserved. 6 7Permission is hereby granted, free of charge, to any person obtaining a 8copy of this software and associated documentation files (the 9"Software"), to deal in the Software without restriction, including 10without limitation the rights to use, copy, modify, merge, publish, 11distribute, sub license, and/or sell copies of the Software, and to 12permit persons to whom the Software is furnished to do so, subject to 13the following conditions: 14 15The above copyright notice and this permission notice (including the 16next paragraph) shall be included in all copies or substantial portions 17of the Software. 18 19THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 23ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26 27**************************************************************************/ 28 29/* 30 * Authors: 31 * Kevin E. Martin <martin@valinux.com> 32 * Jens Owen <jens@tungstengraphics.com> 33 * Rickard E. (Rik) Faith <faith@valinux.com> 34 * 35 */ 36 37#ifdef HAVE_XORG_CONFIG_H 38#include <xorg-config.h> 39#endif 40 41#include <string.h> 42 43#include "xf86.h" 44 45#include <X11/X.h> 46#include <X11/Xproto.h> 47#include "misc.h" 48#include "dixstruct.h" 49#include "extnsionst.h" 50#include "colormapst.h" 51#include "cursorstr.h" 52#include "scrnintstr.h" 53#include "servermd.h" 54#define _XF86DRI_SERVER_ 55#include <X11/dri/xf86driproto.h> 56#include "swaprep.h" 57#include "xf86str.h" 58#include "dri.h" 59#include "sarea.h" 60#include "dristruct.h" 61#include "xf86.h" 62#include "xf86drm.h" 63#include "protocol-versions.h" 64 65static int DRIErrorBase; 66 67static DISPATCH_PROC(ProcXF86DRIQueryVersion); 68static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable); 69static DISPATCH_PROC(ProcXF86DRIOpenConnection); 70static DISPATCH_PROC(ProcXF86DRICloseConnection); 71static DISPATCH_PROC(ProcXF86DRIGetClientDriverName); 72static DISPATCH_PROC(ProcXF86DRICreateContext); 73static DISPATCH_PROC(ProcXF86DRIDestroyContext); 74static DISPATCH_PROC(ProcXF86DRICreateDrawable); 75static DISPATCH_PROC(ProcXF86DRIDestroyDrawable); 76static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo); 77static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo); 78static DISPATCH_PROC(ProcXF86DRIDispatch); 79static DISPATCH_PROC(ProcXF86DRIAuthConnection); 80 81static DISPATCH_PROC(SProcXF86DRIQueryVersion); 82static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable); 83static DISPATCH_PROC(SProcXF86DRIDispatch); 84 85static void XF86DRIResetProc(ExtensionEntry* extEntry); 86 87static unsigned char DRIReqCode = 0; 88 89extern void XFree86DRIExtensionInit(void); 90 91void 92XFree86DRIExtensionInit(void) 93{ 94 ExtensionEntry* extEntry; 95 96#ifdef XF86DRI_EVENTS 97 EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); 98#endif 99 100 if ( 101 DRIExtensionInit() && 102#ifdef XF86DRI_EVENTS 103 EventType && ScreenPrivateIndex != -1 && 104#endif 105 (extEntry = AddExtension(XF86DRINAME, 106 XF86DRINumberEvents, 107 XF86DRINumberErrors, 108 ProcXF86DRIDispatch, 109 SProcXF86DRIDispatch, 110 XF86DRIResetProc, 111 StandardMinorOpcode))) { 112 DRIReqCode = (unsigned char)extEntry->base; 113 DRIErrorBase = extEntry->errorBase; 114 } 115} 116 117/*ARGSUSED*/ 118static void 119XF86DRIResetProc ( 120 ExtensionEntry* extEntry 121) 122{ 123 DRIReset(); 124} 125 126static int 127ProcXF86DRIQueryVersion( 128 register ClientPtr client 129) 130{ 131 xXF86DRIQueryVersionReply rep; 132 register int n; 133 134 REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); 135 rep.type = X_Reply; 136 rep.length = 0; 137 rep.sequenceNumber = client->sequence; 138 rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; 139 rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; 140 rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; 141 if (client->swapped) { 142 swaps(&rep.sequenceNumber, n); 143 swapl(&rep.length, n); 144 swaps(&rep.majorVersion, n); 145 swaps(&rep.minorVersion, n); 146 swapl(&rep.patchVersion, n); 147 } 148 WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); 149 return Success; 150} 151 152static int 153ProcXF86DRIQueryDirectRenderingCapable( 154 register ClientPtr client 155) 156{ 157 xXF86DRIQueryDirectRenderingCapableReply rep; 158 Bool isCapable; 159 register int n; 160 161 REQUEST(xXF86DRIQueryDirectRenderingCapableReq); 162 REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); 163 if (stuff->screen >= screenInfo.numScreens) { 164 client->errorValue = stuff->screen; 165 return BadValue; 166 } 167 168 rep.type = X_Reply; 169 rep.length = 0; 170 rep.sequenceNumber = client->sequence; 171 172 if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], 173 &isCapable)) { 174 return BadValue; 175 } 176 rep.isCapable = isCapable; 177 178 if (!LocalClient(client) || client->swapped) 179 rep.isCapable = 0; 180 181 if (client->swapped) { 182 swaps(&rep.sequenceNumber, n); 183 swapl(&rep.length, n); 184 } 185 186 WriteToClient(client, 187 sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); 188 return Success; 189} 190 191static int 192ProcXF86DRIOpenConnection( 193 register ClientPtr client 194) 195{ 196 xXF86DRIOpenConnectionReply rep; 197 drm_handle_t hSAREA; 198 char* busIdString; 199 200 REQUEST(xXF86DRIOpenConnectionReq); 201 REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); 202 if (stuff->screen >= screenInfo.numScreens) { 203 client->errorValue = stuff->screen; 204 return BadValue; 205 } 206 207 if (!DRIOpenConnection( screenInfo.screens[stuff->screen], 208 &hSAREA, 209 &busIdString)) { 210 return BadValue; 211 } 212 213 rep.type = X_Reply; 214 rep.sequenceNumber = client->sequence; 215 rep.busIdStringLength = 0; 216 if (busIdString) 217 rep.busIdStringLength = strlen(busIdString); 218 rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + 219 pad_to_int32(rep.busIdStringLength)); 220 221 rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); 222#if defined(LONG64) && !defined(__linux__) 223 rep.hSAREAHigh = (CARD32)(hSAREA >> 32); 224#else 225 rep.hSAREAHigh = 0; 226#endif 227 228 WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); 229 if (rep.busIdStringLength) 230 WriteToClient(client, rep.busIdStringLength, busIdString); 231 return Success; 232} 233 234static int 235ProcXF86DRIAuthConnection( 236 register ClientPtr client 237) 238{ 239 xXF86DRIAuthConnectionReply rep; 240 241 REQUEST(xXF86DRIAuthConnectionReq); 242 REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); 243 if (stuff->screen >= screenInfo.numScreens) { 244 client->errorValue = stuff->screen; 245 return BadValue; 246 } 247 248 rep.type = X_Reply; 249 rep.length = 0; 250 rep.sequenceNumber = client->sequence; 251 rep.authenticated = 1; 252 253 if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { 254 ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); 255 rep.authenticated = 0; 256 } 257 WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); 258 return Success; 259} 260 261static int 262ProcXF86DRICloseConnection( 263 register ClientPtr client 264) 265{ 266 REQUEST(xXF86DRICloseConnectionReq); 267 REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); 268 if (stuff->screen >= screenInfo.numScreens) { 269 client->errorValue = stuff->screen; 270 return BadValue; 271 } 272 273 DRICloseConnection( screenInfo.screens[stuff->screen]); 274 275 return Success; 276} 277 278static int 279ProcXF86DRIGetClientDriverName( 280 register ClientPtr client 281) 282{ 283 xXF86DRIGetClientDriverNameReply rep; 284 char* clientDriverName; 285 286 REQUEST(xXF86DRIGetClientDriverNameReq); 287 REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); 288 if (stuff->screen >= screenInfo.numScreens) { 289 client->errorValue = stuff->screen; 290 return BadValue; 291 } 292 293 DRIGetClientDriverName( screenInfo.screens[stuff->screen], 294 (int *)&rep.ddxDriverMajorVersion, 295 (int *)&rep.ddxDriverMinorVersion, 296 (int *)&rep.ddxDriverPatchVersion, 297 &clientDriverName); 298 299 rep.type = X_Reply; 300 rep.sequenceNumber = client->sequence; 301 rep.clientDriverNameLength = 0; 302 if (clientDriverName) 303 rep.clientDriverNameLength = strlen(clientDriverName); 304 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - 305 SIZEOF(xGenericReply) + 306 pad_to_int32(rep.clientDriverNameLength)); 307 308 WriteToClient(client, 309 sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); 310 if (rep.clientDriverNameLength) 311 WriteToClient(client, 312 rep.clientDriverNameLength, 313 clientDriverName); 314 return Success; 315} 316 317static int 318ProcXF86DRICreateContext( 319 register ClientPtr client 320) 321{ 322 xXF86DRICreateContextReply rep; 323 ScreenPtr pScreen; 324 325 REQUEST(xXF86DRICreateContextReq); 326 REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); 327 if (stuff->screen >= screenInfo.numScreens) { 328 client->errorValue = stuff->screen; 329 return BadValue; 330 } 331 332 rep.type = X_Reply; 333 rep.length = 0; 334 rep.sequenceNumber = client->sequence; 335 336 pScreen = screenInfo.screens[stuff->screen]; 337 338 if (!DRICreateContext( pScreen, 339 NULL, 340 stuff->context, 341 (drm_context_t *)&rep.hHWContext)) { 342 return BadValue; 343 } 344 345 WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); 346 return Success; 347} 348 349static int 350ProcXF86DRIDestroyContext( 351 register ClientPtr client 352) 353{ 354 REQUEST(xXF86DRIDestroyContextReq); 355 REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); 356 if (stuff->screen >= screenInfo.numScreens) { 357 client->errorValue = stuff->screen; 358 return BadValue; 359 } 360 361 if (!DRIDestroyContext( screenInfo.screens[stuff->screen], 362 stuff->context)) { 363 return BadValue; 364 } 365 366 return Success; 367} 368 369static int 370ProcXF86DRICreateDrawable( 371 ClientPtr client 372) 373{ 374 xXF86DRICreateDrawableReply rep; 375 DrawablePtr pDrawable; 376 int rc; 377 378 REQUEST(xXF86DRICreateDrawableReq); 379 REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); 380 if (stuff->screen >= screenInfo.numScreens) { 381 client->errorValue = stuff->screen; 382 return BadValue; 383 } 384 385 rep.type = X_Reply; 386 rep.length = 0; 387 rep.sequenceNumber = client->sequence; 388 389 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 390 DixReadAccess); 391 if (rc != Success) 392 return rc; 393 394 if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, 395 pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { 396 return BadValue; 397 } 398 399 WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); 400 return Success; 401} 402 403static int 404ProcXF86DRIDestroyDrawable( 405 register ClientPtr client 406) 407{ 408 REQUEST(xXF86DRIDestroyDrawableReq); 409 DrawablePtr pDrawable; 410 int rc; 411 REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); 412 413 if (stuff->screen >= screenInfo.numScreens) { 414 client->errorValue = stuff->screen; 415 return BadValue; 416 } 417 418 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 419 DixReadAccess); 420 if (rc != Success) 421 return rc; 422 423 if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, 424 pDrawable)) { 425 return BadValue; 426 } 427 428 return Success; 429} 430 431static int 432ProcXF86DRIGetDrawableInfo( 433 register ClientPtr client 434) 435{ 436 xXF86DRIGetDrawableInfoReply rep; 437 DrawablePtr pDrawable; 438 int X, Y, W, H; 439 drm_clip_rect_t * pClipRects, *pClippedRects; 440 drm_clip_rect_t * pBackClipRects; 441 int backX, backY, rc; 442 443 REQUEST(xXF86DRIGetDrawableInfoReq); 444 REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); 445 if (stuff->screen >= screenInfo.numScreens) { 446 client->errorValue = stuff->screen; 447 return BadValue; 448 } 449 450 rep.type = X_Reply; 451 rep.length = 0; 452 rep.sequenceNumber = client->sequence; 453 454 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 455 DixReadAccess); 456 if (rc != Success) 457 return rc; 458 459 if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], 460 pDrawable, 461 (unsigned int*)&rep.drawableTableIndex, 462 (unsigned int*)&rep.drawableTableStamp, 463 (int*)&X, 464 (int*)&Y, 465 (int*)&W, 466 (int*)&H, 467 (int*)&rep.numClipRects, 468 &pClipRects, 469 &backX, 470 &backY, 471 (int*)&rep.numBackClipRects, 472 &pBackClipRects)) { 473 return BadValue; 474 } 475 476 rep.drawableX = X; 477 rep.drawableY = Y; 478 rep.drawableWidth = W; 479 rep.drawableHeight = H; 480 rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - 481 SIZEOF(xGenericReply)); 482 483 rep.backX = backX; 484 rep.backY = backY; 485 486 if (rep.numBackClipRects) 487 rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; 488 489 pClippedRects = pClipRects; 490 491 if (rep.numClipRects) { 492 /* Clip cliprects to screen dimensions (redirected windows) */ 493 pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t)); 494 495 if (pClippedRects) { 496 ScreenPtr pScreen = screenInfo.screens[stuff->screen]; 497 int i, j; 498 499 for (i = 0, j = 0; i < rep.numClipRects; i++) { 500 pClippedRects[j].x1 = max(pClipRects[i].x1, 0); 501 pClippedRects[j].y1 = max(pClipRects[i].y1, 0); 502 pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); 503 pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); 504 505 if (pClippedRects[j].x1 < pClippedRects[j].x2 && 506 pClippedRects[j].y1 < pClippedRects[j].y2) { 507 j++; 508 } 509 } 510 511 rep.numClipRects = j; 512 } else { 513 rep.numClipRects = 0; 514 } 515 516 rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; 517 } 518 519 rep.length = bytes_to_int32(rep.length); 520 521 WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); 522 523 if (rep.numClipRects) { 524 WriteToClient(client, 525 sizeof(drm_clip_rect_t) * rep.numClipRects, 526 (char *)pClippedRects); 527 free(pClippedRects); 528 } 529 530 if (rep.numBackClipRects) { 531 WriteToClient(client, 532 sizeof(drm_clip_rect_t) * rep.numBackClipRects, 533 (char *)pBackClipRects); 534 } 535 536 return Success; 537} 538 539static int 540ProcXF86DRIGetDeviceInfo( 541 register ClientPtr client 542) 543{ 544 xXF86DRIGetDeviceInfoReply rep; 545 drm_handle_t hFrameBuffer; 546 void *pDevPrivate; 547 548 REQUEST(xXF86DRIGetDeviceInfoReq); 549 REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); 550 if (stuff->screen >= screenInfo.numScreens) { 551 client->errorValue = stuff->screen; 552 return BadValue; 553 } 554 555 rep.type = X_Reply; 556 rep.length = 0; 557 rep.sequenceNumber = client->sequence; 558 559 if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], 560 &hFrameBuffer, 561 (int*)&rep.framebufferOrigin, 562 (int*)&rep.framebufferSize, 563 (int*)&rep.framebufferStride, 564 (int*)&rep.devPrivateSize, 565 &pDevPrivate)) { 566 return BadValue; 567 } 568 569 rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); 570#if defined(LONG64) && !defined(__linux__) 571 rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); 572#else 573 rep.hFrameBufferHigh = 0; 574#endif 575 576 rep.length = 0; 577 if (rep.devPrivateSize) { 578 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - 579 SIZEOF(xGenericReply) + 580 pad_to_int32(rep.devPrivateSize)); 581 } 582 583 WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); 584 if (rep.length) { 585 WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); 586 } 587 return Success; 588} 589 590static int 591ProcXF86DRIDispatch ( 592 register ClientPtr client 593) 594{ 595 REQUEST(xReq); 596 597 switch (stuff->data) 598 { 599 case X_XF86DRIQueryVersion: 600 return ProcXF86DRIQueryVersion(client); 601 case X_XF86DRIQueryDirectRenderingCapable: 602 return ProcXF86DRIQueryDirectRenderingCapable(client); 603 } 604 605 if (!LocalClient(client)) 606 return DRIErrorBase + XF86DRIClientNotLocal; 607 608 switch (stuff->data) 609 { 610 case X_XF86DRIOpenConnection: 611 return ProcXF86DRIOpenConnection(client); 612 case X_XF86DRICloseConnection: 613 return ProcXF86DRICloseConnection(client); 614 case X_XF86DRIGetClientDriverName: 615 return ProcXF86DRIGetClientDriverName(client); 616 case X_XF86DRICreateContext: 617 return ProcXF86DRICreateContext(client); 618 case X_XF86DRIDestroyContext: 619 return ProcXF86DRIDestroyContext(client); 620 case X_XF86DRICreateDrawable: 621 return ProcXF86DRICreateDrawable(client); 622 case X_XF86DRIDestroyDrawable: 623 return ProcXF86DRIDestroyDrawable(client); 624 case X_XF86DRIGetDrawableInfo: 625 return ProcXF86DRIGetDrawableInfo(client); 626 case X_XF86DRIGetDeviceInfo: 627 return ProcXF86DRIGetDeviceInfo(client); 628 case X_XF86DRIAuthConnection: 629 return ProcXF86DRIAuthConnection(client); 630 /* {Open,Close}FullScreen are deprecated now */ 631 default: 632 return BadRequest; 633 } 634} 635 636static int 637SProcXF86DRIQueryVersion( 638 register ClientPtr client 639) 640{ 641 register int n; 642 REQUEST(xXF86DRIQueryVersionReq); 643 swaps(&stuff->length, n); 644 return ProcXF86DRIQueryVersion(client); 645} 646 647static int 648SProcXF86DRIQueryDirectRenderingCapable( 649 register ClientPtr client 650) 651{ 652 register int n; 653 REQUEST(xXF86DRIQueryDirectRenderingCapableReq); 654 swaps(&stuff->length, n); 655 swapl(&stuff->screen, n); 656 return ProcXF86DRIQueryDirectRenderingCapable(client); 657} 658 659static int 660SProcXF86DRIDispatch ( 661 register ClientPtr client 662) 663{ 664 REQUEST(xReq); 665 666 /* 667 * Only local clients are allowed DRI access, but remote clients still need 668 * these requests to find out cleanly. 669 */ 670 switch (stuff->data) 671 { 672 case X_XF86DRIQueryVersion: 673 return SProcXF86DRIQueryVersion(client); 674 case X_XF86DRIQueryDirectRenderingCapable: 675 return SProcXF86DRIQueryDirectRenderingCapable(client); 676 default: 677 return DRIErrorBase + XF86DRIClientNotLocal; 678 } 679} 680