xf86dri.c revision 9ace9065
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 67 68 69static void XF86DRIResetProc(ExtensionEntry* extEntry); 70 71static unsigned char DRIReqCode = 0; 72 73extern void XFree86DRIExtensionInit(void); 74 75/*ARGSUSED*/ 76static void 77XF86DRIResetProc ( 78 ExtensionEntry* extEntry 79) 80{ 81 DRIReset(); 82} 83 84static int 85ProcXF86DRIQueryVersion( 86 register ClientPtr client 87) 88{ 89 xXF86DRIQueryVersionReply rep; 90 register int n; 91 92 REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq); 93 rep.type = X_Reply; 94 rep.length = 0; 95 rep.sequenceNumber = client->sequence; 96 rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION; 97 rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION; 98 rep.patchVersion = SERVER_XF86DRI_PATCH_VERSION; 99 if (client->swapped) { 100 swaps(&rep.sequenceNumber, n); 101 swapl(&rep.length, n); 102 swaps(&rep.majorVersion, n); 103 swaps(&rep.minorVersion, n); 104 swapl(&rep.patchVersion, n); 105 } 106 WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep); 107 return Success; 108} 109 110static int 111ProcXF86DRIQueryDirectRenderingCapable( 112 register ClientPtr client 113) 114{ 115 xXF86DRIQueryDirectRenderingCapableReply rep; 116 Bool isCapable; 117 register int n; 118 119 REQUEST(xXF86DRIQueryDirectRenderingCapableReq); 120 REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq); 121 if (stuff->screen >= screenInfo.numScreens) { 122 client->errorValue = stuff->screen; 123 return BadValue; 124 } 125 126 rep.type = X_Reply; 127 rep.length = 0; 128 rep.sequenceNumber = client->sequence; 129 130 if (!DRIQueryDirectRenderingCapable( screenInfo.screens[stuff->screen], 131 &isCapable)) { 132 return BadValue; 133 } 134 rep.isCapable = isCapable; 135 136 if (!LocalClient(client) || client->swapped) 137 rep.isCapable = 0; 138 139 if (client->swapped) { 140 swaps(&rep.sequenceNumber, n); 141 swapl(&rep.length, n); 142 } 143 144 WriteToClient(client, 145 sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep); 146 return Success; 147} 148 149static int 150ProcXF86DRIOpenConnection( 151 register ClientPtr client 152) 153{ 154 xXF86DRIOpenConnectionReply rep; 155 drm_handle_t hSAREA; 156 char* busIdString; 157 158 REQUEST(xXF86DRIOpenConnectionReq); 159 REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq); 160 if (stuff->screen >= screenInfo.numScreens) { 161 client->errorValue = stuff->screen; 162 return BadValue; 163 } 164 165 if (!DRIOpenConnection( screenInfo.screens[stuff->screen], 166 &hSAREA, 167 &busIdString)) { 168 return BadValue; 169 } 170 171 rep.type = X_Reply; 172 rep.sequenceNumber = client->sequence; 173 rep.busIdStringLength = 0; 174 if (busIdString) 175 rep.busIdStringLength = strlen(busIdString); 176 rep.length = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) + 177 pad_to_int32(rep.busIdStringLength)); 178 179 rep.hSAREALow = (CARD32)(hSAREA & 0xffffffff); 180#if defined(LONG64) && !defined(__linux__) 181 rep.hSAREAHigh = (CARD32)(hSAREA >> 32); 182#else 183 rep.hSAREAHigh = 0; 184#endif 185 186 WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep); 187 if (rep.busIdStringLength) 188 WriteToClient(client, rep.busIdStringLength, busIdString); 189 return Success; 190} 191 192static int 193ProcXF86DRIAuthConnection( 194 register ClientPtr client 195) 196{ 197 xXF86DRIAuthConnectionReply rep; 198 199 REQUEST(xXF86DRIAuthConnectionReq); 200 REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq); 201 if (stuff->screen >= screenInfo.numScreens) { 202 client->errorValue = stuff->screen; 203 return BadValue; 204 } 205 206 rep.type = X_Reply; 207 rep.length = 0; 208 rep.sequenceNumber = client->sequence; 209 rep.authenticated = 1; 210 211 if (!DRIAuthConnection( screenInfo.screens[stuff->screen], stuff->magic)) { 212 ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic); 213 rep.authenticated = 0; 214 } 215 WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep); 216 return Success; 217} 218 219static int 220ProcXF86DRICloseConnection( 221 register ClientPtr client 222) 223{ 224 REQUEST(xXF86DRICloseConnectionReq); 225 REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq); 226 if (stuff->screen >= screenInfo.numScreens) { 227 client->errorValue = stuff->screen; 228 return BadValue; 229 } 230 231 DRICloseConnection( screenInfo.screens[stuff->screen]); 232 233 return Success; 234} 235 236static int 237ProcXF86DRIGetClientDriverName( 238 register ClientPtr client 239) 240{ 241 xXF86DRIGetClientDriverNameReply rep; 242 char* clientDriverName; 243 244 REQUEST(xXF86DRIGetClientDriverNameReq); 245 REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq); 246 if (stuff->screen >= screenInfo.numScreens) { 247 client->errorValue = stuff->screen; 248 return BadValue; 249 } 250 251 DRIGetClientDriverName( screenInfo.screens[stuff->screen], 252 (int *)&rep.ddxDriverMajorVersion, 253 (int *)&rep.ddxDriverMinorVersion, 254 (int *)&rep.ddxDriverPatchVersion, 255 &clientDriverName); 256 257 rep.type = X_Reply; 258 rep.sequenceNumber = client->sequence; 259 rep.clientDriverNameLength = 0; 260 if (clientDriverName) 261 rep.clientDriverNameLength = strlen(clientDriverName); 262 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) - 263 SIZEOF(xGenericReply) + 264 pad_to_int32(rep.clientDriverNameLength)); 265 266 WriteToClient(client, 267 sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep); 268 if (rep.clientDriverNameLength) 269 WriteToClient(client, 270 rep.clientDriverNameLength, 271 clientDriverName); 272 return Success; 273} 274 275static int 276ProcXF86DRICreateContext( 277 register ClientPtr client 278) 279{ 280 xXF86DRICreateContextReply rep; 281 ScreenPtr pScreen; 282 283 REQUEST(xXF86DRICreateContextReq); 284 REQUEST_SIZE_MATCH(xXF86DRICreateContextReq); 285 if (stuff->screen >= screenInfo.numScreens) { 286 client->errorValue = stuff->screen; 287 return BadValue; 288 } 289 290 rep.type = X_Reply; 291 rep.length = 0; 292 rep.sequenceNumber = client->sequence; 293 294 pScreen = screenInfo.screens[stuff->screen]; 295 296 if (!DRICreateContext( pScreen, 297 NULL, 298 stuff->context, 299 (drm_context_t *)&rep.hHWContext)) { 300 return BadValue; 301 } 302 303 WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep); 304 return Success; 305} 306 307static int 308ProcXF86DRIDestroyContext( 309 register ClientPtr client 310) 311{ 312 REQUEST(xXF86DRIDestroyContextReq); 313 REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq); 314 if (stuff->screen >= screenInfo.numScreens) { 315 client->errorValue = stuff->screen; 316 return BadValue; 317 } 318 319 if (!DRIDestroyContext( screenInfo.screens[stuff->screen], 320 stuff->context)) { 321 return BadValue; 322 } 323 324 return Success; 325} 326 327static int 328ProcXF86DRICreateDrawable( 329 ClientPtr client 330) 331{ 332 xXF86DRICreateDrawableReply rep; 333 DrawablePtr pDrawable; 334 int rc; 335 336 REQUEST(xXF86DRICreateDrawableReq); 337 REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq); 338 if (stuff->screen >= screenInfo.numScreens) { 339 client->errorValue = stuff->screen; 340 return BadValue; 341 } 342 343 rep.type = X_Reply; 344 rep.length = 0; 345 rep.sequenceNumber = client->sequence; 346 347 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 348 DixReadAccess); 349 if (rc != Success) 350 return rc; 351 352 if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client, 353 pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) { 354 return BadValue; 355 } 356 357 WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep); 358 return Success; 359} 360 361static int 362ProcXF86DRIDestroyDrawable( 363 register ClientPtr client 364) 365{ 366 REQUEST(xXF86DRIDestroyDrawableReq); 367 DrawablePtr pDrawable; 368 int rc; 369 REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq); 370 371 if (stuff->screen >= screenInfo.numScreens) { 372 client->errorValue = stuff->screen; 373 return BadValue; 374 } 375 376 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 377 DixReadAccess); 378 if (rc != Success) 379 return rc; 380 381 if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client, 382 pDrawable)) { 383 return BadValue; 384 } 385 386 return Success; 387} 388 389static int 390ProcXF86DRIGetDrawableInfo( 391 register ClientPtr client 392) 393{ 394 xXF86DRIGetDrawableInfoReply rep; 395 DrawablePtr pDrawable; 396 int X, Y, W, H; 397 drm_clip_rect_t * pClipRects, *pClippedRects; 398 drm_clip_rect_t * pBackClipRects; 399 int backX, backY, rc; 400 401 REQUEST(xXF86DRIGetDrawableInfoReq); 402 REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq); 403 if (stuff->screen >= screenInfo.numScreens) { 404 client->errorValue = stuff->screen; 405 return BadValue; 406 } 407 408 rep.type = X_Reply; 409 rep.length = 0; 410 rep.sequenceNumber = client->sequence; 411 412 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 413 DixReadAccess); 414 if (rc != Success) 415 return rc; 416 417 if (!DRIGetDrawableInfo( screenInfo.screens[stuff->screen], 418 pDrawable, 419 (unsigned int*)&rep.drawableTableIndex, 420 (unsigned int*)&rep.drawableTableStamp, 421 (int*)&X, 422 (int*)&Y, 423 (int*)&W, 424 (int*)&H, 425 (int*)&rep.numClipRects, 426 &pClipRects, 427 &backX, 428 &backY, 429 (int*)&rep.numBackClipRects, 430 &pBackClipRects)) { 431 return BadValue; 432 } 433 434 rep.drawableX = X; 435 rep.drawableY = Y; 436 rep.drawableWidth = W; 437 rep.drawableHeight = H; 438 rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) - 439 SIZEOF(xGenericReply)); 440 441 rep.backX = backX; 442 rep.backY = backY; 443 444 if (rep.numBackClipRects) 445 rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects; 446 447 pClippedRects = pClipRects; 448 449 if (rep.numClipRects) { 450 /* Clip cliprects to screen dimensions (redirected windows) */ 451 pClippedRects = malloc(rep.numClipRects * sizeof(drm_clip_rect_t)); 452 453 if (pClippedRects) { 454 ScreenPtr pScreen = screenInfo.screens[stuff->screen]; 455 int i, j; 456 457 for (i = 0, j = 0; i < rep.numClipRects; i++) { 458 pClippedRects[j].x1 = max(pClipRects[i].x1, 0); 459 pClippedRects[j].y1 = max(pClipRects[i].y1, 0); 460 pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width); 461 pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height); 462 463 if (pClippedRects[j].x1 < pClippedRects[j].x2 && 464 pClippedRects[j].y1 < pClippedRects[j].y2) { 465 j++; 466 } 467 } 468 469 rep.numClipRects = j; 470 } else { 471 rep.numClipRects = 0; 472 } 473 474 rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects; 475 } 476 477 rep.length = bytes_to_int32(rep.length); 478 479 WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep); 480 481 if (rep.numClipRects) { 482 WriteToClient(client, 483 sizeof(drm_clip_rect_t) * rep.numClipRects, 484 (char *)pClippedRects); 485 free(pClippedRects); 486 } 487 488 if (rep.numBackClipRects) { 489 WriteToClient(client, 490 sizeof(drm_clip_rect_t) * rep.numBackClipRects, 491 (char *)pBackClipRects); 492 } 493 494 return Success; 495} 496 497static int 498ProcXF86DRIGetDeviceInfo( 499 register ClientPtr client 500) 501{ 502 xXF86DRIGetDeviceInfoReply rep; 503 drm_handle_t hFrameBuffer; 504 void *pDevPrivate; 505 506 REQUEST(xXF86DRIGetDeviceInfoReq); 507 REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq); 508 if (stuff->screen >= screenInfo.numScreens) { 509 client->errorValue = stuff->screen; 510 return BadValue; 511 } 512 513 rep.type = X_Reply; 514 rep.length = 0; 515 rep.sequenceNumber = client->sequence; 516 517 if (!DRIGetDeviceInfo( screenInfo.screens[stuff->screen], 518 &hFrameBuffer, 519 (int*)&rep.framebufferOrigin, 520 (int*)&rep.framebufferSize, 521 (int*)&rep.framebufferStride, 522 (int*)&rep.devPrivateSize, 523 &pDevPrivate)) { 524 return BadValue; 525 } 526 527 rep.hFrameBufferLow = (CARD32)(hFrameBuffer & 0xffffffff); 528#if defined(LONG64) && !defined(__linux__) 529 rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32); 530#else 531 rep.hFrameBufferHigh = 0; 532#endif 533 534 rep.length = 0; 535 if (rep.devPrivateSize) { 536 rep.length = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) - 537 SIZEOF(xGenericReply) + 538 pad_to_int32(rep.devPrivateSize)); 539 } 540 541 WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep); 542 if (rep.length) { 543 WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate); 544 } 545 return Success; 546} 547 548static int 549ProcXF86DRIDispatch ( 550 register ClientPtr client 551) 552{ 553 REQUEST(xReq); 554 555 switch (stuff->data) 556 { 557 case X_XF86DRIQueryVersion: 558 return ProcXF86DRIQueryVersion(client); 559 case X_XF86DRIQueryDirectRenderingCapable: 560 return ProcXF86DRIQueryDirectRenderingCapable(client); 561 } 562 563 if (!LocalClient(client)) 564 return DRIErrorBase + XF86DRIClientNotLocal; 565 566 switch (stuff->data) 567 { 568 case X_XF86DRIOpenConnection: 569 return ProcXF86DRIOpenConnection(client); 570 case X_XF86DRICloseConnection: 571 return ProcXF86DRICloseConnection(client); 572 case X_XF86DRIGetClientDriverName: 573 return ProcXF86DRIGetClientDriverName(client); 574 case X_XF86DRICreateContext: 575 return ProcXF86DRICreateContext(client); 576 case X_XF86DRIDestroyContext: 577 return ProcXF86DRIDestroyContext(client); 578 case X_XF86DRICreateDrawable: 579 return ProcXF86DRICreateDrawable(client); 580 case X_XF86DRIDestroyDrawable: 581 return ProcXF86DRIDestroyDrawable(client); 582 case X_XF86DRIGetDrawableInfo: 583 return ProcXF86DRIGetDrawableInfo(client); 584 case X_XF86DRIGetDeviceInfo: 585 return ProcXF86DRIGetDeviceInfo(client); 586 case X_XF86DRIAuthConnection: 587 return ProcXF86DRIAuthConnection(client); 588 /* {Open,Close}FullScreen are deprecated now */ 589 default: 590 return BadRequest; 591 } 592} 593 594static int 595SProcXF86DRIQueryVersion( 596 register ClientPtr client 597) 598{ 599 register int n; 600 REQUEST(xXF86DRIQueryVersionReq); 601 swaps(&stuff->length, n); 602 return ProcXF86DRIQueryVersion(client); 603} 604 605static int 606SProcXF86DRIQueryDirectRenderingCapable( 607 register ClientPtr client 608) 609{ 610 register int n; 611 REQUEST(xXF86DRIQueryDirectRenderingCapableReq); 612 swaps(&stuff->length, n); 613 swapl(&stuff->screen, n); 614 return ProcXF86DRIQueryDirectRenderingCapable(client); 615} 616 617static int 618SProcXF86DRIDispatch ( 619 register ClientPtr client 620) 621{ 622 REQUEST(xReq); 623 624 /* 625 * Only local clients are allowed DRI access, but remote clients still need 626 * these requests to find out cleanly. 627 */ 628 switch (stuff->data) 629 { 630 case X_XF86DRIQueryVersion: 631 return SProcXF86DRIQueryVersion(client); 632 case X_XF86DRIQueryDirectRenderingCapable: 633 return SProcXF86DRIQueryDirectRenderingCapable(client); 634 default: 635 return DRIErrorBase + XF86DRIClientNotLocal; 636 } 637} 638 639void 640XFree86DRIExtensionInit(void) 641{ 642 ExtensionEntry* extEntry; 643 644#ifdef XF86DRI_EVENTS 645 EventType = CreateNewResourceType(XF86DRIFreeEvents, "DRIEvent"); 646#endif 647 648 if ( 649 DRIExtensionInit() && 650#ifdef XF86DRI_EVENTS 651 EventType && ScreenPrivateIndex != -1 && 652#endif 653 (extEntry = AddExtension(XF86DRINAME, 654 XF86DRINumberEvents, 655 XF86DRINumberErrors, 656 ProcXF86DRIDispatch, 657 SProcXF86DRIDispatch, 658 XF86DRIResetProc, 659 StandardMinorOpcode))) { 660 DRIReqCode = (unsigned char)extEntry->base; 661 DRIErrorBase = extEntry->errorBase; 662 } 663} 664