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