appledri.c revision d9252ffb
1/************************************************************************** 2 3 Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas. 4 Copyright 2000 VA Linux Systems, Inc. 5 Copyright (c) 2002, 2009-2012 Apple Inc. 6 All Rights Reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a 9 copy of this software and associated documentation files (the 10 "Software"), to deal in the Software without restriction, including 11 without limitation the rights to use, copy, modify, merge, publish, 12 distribute, sub license, and/or sell copies of the Software, and to 13 permit persons to whom the Software is furnished to do so, subject to 14 the following conditions: 15 16 The above copyright notice and this permission notice (including the 17 next paragraph) shall be included in all copies or substantial portions 18 of the Software. 19 20 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 21 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 23 IN NO EVENT SHALL PRECISION INSIGHT AND/OR ITS SUPPLIERS BE LIABLE FOR 24 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 25 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 26 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 27 28**************************************************************************/ 29 30/* 31 * Authors: 32 * Kevin E. Martin <martin@valinux.com> 33 * Jens Owen <jens@valinux.com> 34 * Rickard E. (Rik) Faith <faith@valinux.com> 35 * Jeremy Huddleston <jeremyhu@apple.com> 36 * 37 */ 38 39#ifdef HAVE_DIX_CONFIG_H 40#include <dix-config.h> 41#endif 42 43#include <X11/X.h> 44#include <X11/Xproto.h> 45#include "misc.h" 46#include "dixstruct.h" 47#include "extnsionst.h" 48#include "colormapst.h" 49#include "cursorstr.h" 50#include "scrnintstr.h" 51#include "servermd.h" 52#define _APPLEDRI_SERVER_ 53#include "appledristr.h" 54#include "swaprep.h" 55#include "dri.h" 56#include "dristruct.h" 57#include "xpr.h" 58#include "x-hash.h" 59#include "protocol-versions.h" 60 61static int DRIErrorBase = 0; 62 63static void 64AppleDRIResetProc(ExtensionEntry* extEntry); 65static int 66ProcAppleDRICreatePixmap(ClientPtr client); 67 68static unsigned char DRIReqCode = 0; 69static int DRIEventBase = 0; 70 71static void 72SNotifyEvent(xAppleDRINotifyEvent *from, xAppleDRINotifyEvent *to); 73 74typedef struct _DRIEvent *DRIEventPtr; 75typedef struct _DRIEvent { 76 DRIEventPtr next; 77 ClientPtr client; 78 XID clientResource; 79 unsigned int mask; 80} DRIEventRec; 81 82/*ARGSUSED*/ 83static void 84AppleDRIResetProc(ExtensionEntry* extEntry) 85{ 86 DRIReset(); 87} 88 89static int 90ProcAppleDRIQueryVersion(register ClientPtr client) 91{ 92 xAppleDRIQueryVersionReply rep; 93 94 REQUEST_SIZE_MATCH(xAppleDRIQueryVersionReq); 95 rep.type = X_Reply; 96 rep.length = 0; 97 rep.sequenceNumber = client->sequence; 98 rep.majorVersion = SERVER_APPLEDRI_MAJOR_VERSION; 99 rep.minorVersion = SERVER_APPLEDRI_MINOR_VERSION; 100 rep.patchVersion = SERVER_APPLEDRI_PATCH_VERSION; 101 if (client->swapped) { 102 swaps(&rep.sequenceNumber); 103 swapl(&rep.length); 104 swaps(&rep.majorVersion); 105 swaps(&rep.minorVersion); 106 swapl(&rep.patchVersion); 107 } 108 WriteToClient(client, sizeof(xAppleDRIQueryVersionReply), &rep); 109 return Success; 110} 111 112/* surfaces */ 113 114static int 115ProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client) 116{ 117 xAppleDRIQueryDirectRenderingCapableReply rep; 118 Bool isCapable; 119 120 REQUEST(xAppleDRIQueryDirectRenderingCapableReq); 121 REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); 122 rep.type = X_Reply; 123 rep.length = 0; 124 rep.sequenceNumber = client->sequence; 125 126 if (stuff->screen >= screenInfo.numScreens) { 127 return BadValue; 128 } 129 130 if (!DRIQueryDirectRenderingCapable(screenInfo.screens[stuff->screen], 131 &isCapable)) { 132 return BadValue; 133 } 134 rep.isCapable = isCapable; 135 136 if (!client->local) 137 rep.isCapable = 0; 138 139 if (client->swapped) { 140 swaps(&rep.sequenceNumber); 141 swapl(&rep.length); 142 } 143 144 WriteToClient(client, 145 sizeof(xAppleDRIQueryDirectRenderingCapableReply), 146 &rep); 147 return Success; 148} 149 150static int 151ProcAppleDRIAuthConnection(register ClientPtr client) 152{ 153 xAppleDRIAuthConnectionReply rep; 154 155 REQUEST(xAppleDRIAuthConnectionReq); 156 REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); 157 158 rep.type = X_Reply; 159 rep.length = 0; 160 rep.sequenceNumber = client->sequence; 161 rep.authenticated = 1; 162 163 if (!DRIAuthConnection(screenInfo.screens[stuff->screen], 164 stuff->magic)) { 165 ErrorF("Failed to authenticate %u\n", (unsigned int)stuff->magic); 166 rep.authenticated = 0; 167 } 168 169 if (client->swapped) { 170 swaps(&rep.sequenceNumber); 171 swapl(&rep.length); 172 swapl(&rep.authenticated); /* Yes, this is a CARD32 ... sigh */ 173 } 174 175 WriteToClient(client, sizeof(xAppleDRIAuthConnectionReply), &rep); 176 return Success; 177} 178 179static void 180surface_notify(void *_arg, 181 void *data) 182{ 183 DRISurfaceNotifyArg *arg = _arg; 184 int client_index = (int)x_cvt_vptr_to_uint(data); 185 xAppleDRINotifyEvent se; 186 187 if (client_index < 0 || client_index >= currentMaxClients) 188 return; 189 190 se.type = DRIEventBase + AppleDRISurfaceNotify; 191 se.kind = arg->kind; 192 se.arg = arg->id; 193 se.time = currentTime.milliseconds; 194 WriteEventsToClient(clients[client_index], 1, (xEvent *)&se); 195} 196 197static int 198ProcAppleDRICreateSurface(ClientPtr client) 199{ 200 xAppleDRICreateSurfaceReply rep; 201 DrawablePtr pDrawable; 202 xp_surface_id sid; 203 unsigned int key[2]; 204 int rc; 205 206 REQUEST(xAppleDRICreateSurfaceReq); 207 REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); 208 rep.type = X_Reply; 209 rep.length = 0; 210 rep.sequenceNumber = client->sequence; 211 212 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 213 DixReadAccess); 214 if (rc != Success) 215 return rc; 216 217 rep.key_0 = rep.key_1 = rep.uid = 0; 218 219 if (!DRICreateSurface(screenInfo.screens[stuff->screen], 220 (Drawable)stuff->drawable, pDrawable, 221 stuff->client_id, &sid, key, 222 surface_notify, 223 x_cvt_uint_to_vptr(client->index))) { 224 return BadValue; 225 } 226 227 rep.key_0 = key[0]; 228 rep.key_1 = key[1]; 229 rep.uid = sid; 230 231 if (client->swapped) { 232 swaps(&rep.sequenceNumber); 233 swapl(&rep.length); 234 swapl(&rep.key_0); 235 swapl(&rep.key_1); 236 swapl(&rep.uid); 237 } 238 239 WriteToClient(client, sizeof(xAppleDRICreateSurfaceReply), &rep); 240 return Success; 241} 242 243static int 244ProcAppleDRIDestroySurface(register ClientPtr client) 245{ 246 int rc; 247 REQUEST(xAppleDRIDestroySurfaceReq); 248 DrawablePtr pDrawable; 249 REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); 250 251 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 252 DixReadAccess); 253 if (rc != Success) 254 return rc; 255 256 if (!DRIDestroySurface(screenInfo.screens[stuff->screen], 257 (Drawable)stuff->drawable, 258 pDrawable, NULL, NULL)) { 259 return BadValue; 260 } 261 262 return Success; 263} 264 265static int 266ProcAppleDRICreatePixmap(ClientPtr client) 267{ 268 REQUEST(xAppleDRICreatePixmapReq); 269 DrawablePtr pDrawable; 270 int rc; 271 char path[PATH_MAX]; 272 xAppleDRICreatePixmapReply rep; 273 int width, height, pitch, bpp; 274 void *ptr; 275 CARD32 stringLength; 276 277 REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); 278 279 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 280 DixReadAccess); 281 282 if (rc != Success) 283 return rc; 284 285 if (!DRICreatePixmap(screenInfo.screens[stuff->screen], 286 (Drawable)stuff->drawable, 287 pDrawable, 288 path, PATH_MAX)) { 289 return BadValue; 290 } 291 292 if (!DRIGetPixmapData(pDrawable, &width, &height, 293 &pitch, &bpp, &ptr)) { 294 return BadValue; 295 } 296 297 rep.stringLength = strlen(path) + 1; 298 299 rep.type = X_Reply; 300 rep.length = bytes_to_int32(rep.stringLength); 301 rep.sequenceNumber = client->sequence; 302 rep.width = width; 303 rep.height = height; 304 rep.pitch = pitch; 305 rep.bpp = bpp; 306 rep.size = pitch * height; 307 308 if (sizeof(rep) != sz_xAppleDRICreatePixmapReply) 309 ErrorF("error sizeof(rep) is %zu\n", sizeof(rep)); 310 311 stringLength = rep.stringLength; /* save unswapped value */ 312 if (client->swapped) { 313 swaps(&rep.sequenceNumber); 314 swapl(&rep.length); 315 swapl(&rep.stringLength); 316 swapl(&rep.width); 317 swapl(&rep.height); 318 swapl(&rep.pitch); 319 swapl(&rep.bpp); 320 swapl(&rep.size); 321 } 322 323 WriteToClient(client, sizeof(rep), &rep); 324 WriteToClient(client, stringLength, path); 325 326 return Success; 327} 328 329static int 330ProcAppleDRIDestroyPixmap(ClientPtr client) 331{ 332 DrawablePtr pDrawable; 333 int rc; 334 REQUEST(xAppleDRIDestroyPixmapReq); 335 REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); 336 337 rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, 338 DixReadAccess); 339 340 if (rc != Success) 341 return rc; 342 343 DRIDestroyPixmap(pDrawable); 344 345 return Success; 346} 347 348/* dispatch */ 349 350static int 351ProcAppleDRIDispatch(register ClientPtr client) 352{ 353 REQUEST(xReq); 354 355 switch (stuff->data) { 356 case X_AppleDRIQueryVersion: 357 return ProcAppleDRIQueryVersion(client); 358 359 case X_AppleDRIQueryDirectRenderingCapable: 360 return ProcAppleDRIQueryDirectRenderingCapable(client); 361 } 362 363 if (!client->local) 364 return DRIErrorBase + AppleDRIClientNotLocal; 365 366 switch (stuff->data) { 367 case X_AppleDRIAuthConnection: 368 return ProcAppleDRIAuthConnection(client); 369 370 case X_AppleDRICreateSurface: 371 return ProcAppleDRICreateSurface(client); 372 373 case X_AppleDRIDestroySurface: 374 return ProcAppleDRIDestroySurface(client); 375 376 case X_AppleDRICreatePixmap: 377 return ProcAppleDRICreatePixmap(client); 378 379 case X_AppleDRIDestroyPixmap: 380 return ProcAppleDRIDestroyPixmap(client); 381 382 default: 383 return BadRequest; 384 } 385} 386 387static void 388SNotifyEvent(xAppleDRINotifyEvent *from, 389 xAppleDRINotifyEvent *to) 390{ 391 to->type = from->type; 392 to->kind = from->kind; 393 cpswaps(from->sequenceNumber, to->sequenceNumber); 394 cpswapl(from->time, to->time); 395 cpswapl(from->arg, to->arg); 396} 397 398static int 399SProcAppleDRIQueryVersion(register ClientPtr client) 400{ 401 REQUEST(xAppleDRIQueryVersionReq); 402 swaps(&stuff->length); 403 return ProcAppleDRIQueryVersion(client); 404} 405 406static int 407SProcAppleDRIQueryDirectRenderingCapable(register ClientPtr client) 408{ 409 REQUEST(xAppleDRIQueryDirectRenderingCapableReq); 410 swaps(&stuff->length); 411 REQUEST_SIZE_MATCH(xAppleDRIQueryDirectRenderingCapableReq); 412 swapl(&stuff->screen); 413 return ProcAppleDRIQueryDirectRenderingCapable(client); 414} 415 416static int 417SProcAppleDRIAuthConnection(register ClientPtr client) 418{ 419 REQUEST(xAppleDRIAuthConnectionReq); 420 swaps(&stuff->length); 421 REQUEST_SIZE_MATCH(xAppleDRIAuthConnectionReq); 422 swapl(&stuff->screen); 423 swapl(&stuff->magic); 424 return ProcAppleDRIAuthConnection(client); 425} 426 427static int 428SProcAppleDRICreateSurface(register ClientPtr client) 429{ 430 REQUEST(xAppleDRICreateSurfaceReq); 431 swaps(&stuff->length); 432 REQUEST_SIZE_MATCH(xAppleDRICreateSurfaceReq); 433 swapl(&stuff->screen); 434 swapl(&stuff->drawable); 435 swapl(&stuff->client_id); 436 return ProcAppleDRICreateSurface(client); 437} 438 439static int 440SProcAppleDRIDestroySurface(register ClientPtr client) 441{ 442 REQUEST(xAppleDRIDestroySurfaceReq); 443 swaps(&stuff->length); 444 REQUEST_SIZE_MATCH(xAppleDRIDestroySurfaceReq); 445 swapl(&stuff->screen); 446 swapl(&stuff->drawable); 447 return ProcAppleDRIDestroySurface(client); 448} 449 450static int 451SProcAppleDRICreatePixmap(register ClientPtr client) 452{ 453 REQUEST(xAppleDRICreatePixmapReq); 454 swaps(&stuff->length); 455 REQUEST_SIZE_MATCH(xAppleDRICreatePixmapReq); 456 swapl(&stuff->screen); 457 swapl(&stuff->drawable); 458 return ProcAppleDRICreatePixmap(client); 459} 460 461static int 462SProcAppleDRIDestroyPixmap(register ClientPtr client) 463{ 464 REQUEST(xAppleDRIDestroyPixmapReq); 465 swaps(&stuff->length); 466 REQUEST_SIZE_MATCH(xAppleDRIDestroyPixmapReq); 467 swapl(&stuff->drawable); 468 return ProcAppleDRIDestroyPixmap(client); 469} 470 471static int 472SProcAppleDRIDispatch(register ClientPtr client) 473{ 474 REQUEST(xReq); 475 476 switch (stuff->data) { 477 case X_AppleDRIQueryVersion: 478 return SProcAppleDRIQueryVersion(client); 479 480 case X_AppleDRIQueryDirectRenderingCapable: 481 return SProcAppleDRIQueryDirectRenderingCapable(client); 482 } 483 484 if (!client->local) 485 return DRIErrorBase + AppleDRIClientNotLocal; 486 487 switch (stuff->data) { 488 case X_AppleDRIAuthConnection: 489 return SProcAppleDRIAuthConnection(client); 490 491 case X_AppleDRICreateSurface: 492 return SProcAppleDRICreateSurface(client); 493 494 case X_AppleDRIDestroySurface: 495 return SProcAppleDRIDestroySurface(client); 496 497 case X_AppleDRICreatePixmap: 498 return SProcAppleDRICreatePixmap(client); 499 500 case X_AppleDRIDestroyPixmap: 501 return SProcAppleDRIDestroyPixmap(client); 502 503 default: 504 return BadRequest; 505 } 506} 507 508void 509AppleDRIExtensionInit(void) 510{ 511 ExtensionEntry* extEntry; 512 513 if (DRIExtensionInit() && 514 (extEntry = AddExtension(APPLEDRINAME, 515 AppleDRINumberEvents, 516 AppleDRINumberErrors, 517 ProcAppleDRIDispatch, 518 SProcAppleDRIDispatch, 519 AppleDRIResetProc, 520 StandardMinorOpcode))) { 521 size_t i; 522 DRIReqCode = (unsigned char)extEntry->base; 523 DRIErrorBase = extEntry->errorBase; 524 DRIEventBase = extEntry->eventBase; 525 for (i = 0; i < AppleDRINumberEvents; i++) 526 EventSwapVector[DRIEventBase + i] = (EventSwapPtr)SNotifyEvent; 527 } 528} 529