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