PageRenderTime 84ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/dix/dispatch.c

https://github.com/cubanismo/xserver
C | 3954 lines | 3129 code | 518 blank | 307 comment | 679 complexity | a5f6722dc3f3ce4f37c2982ae68d9e31 MD5 | raw file
Possible License(s): MIT
  1. /************************************************************
  2. Copyright 1987, 1989, 1998 The Open Group
  3. Permission to use, copy, modify, distribute, and sell this software and its
  4. documentation for any purpose is hereby granted without fee, provided that
  5. the above copyright notice appear in all copies and that both that
  6. copyright notice and this permission notice appear in supporting
  7. documentation.
  8. The above copyright notice and this permission notice shall be included in
  9. all copies or substantial portions of the Software.
  10. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  11. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  12. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  13. OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
  14. AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  15. CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  16. Except as contained in this notice, the name of The Open Group shall not be
  17. used in advertising or otherwise to promote the sale, use or other dealings
  18. in this Software without prior written authorization from The Open Group.
  19. Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
  20. All Rights Reserved
  21. Permission to use, copy, modify, and distribute this software and its
  22. documentation for any purpose and without fee is hereby granted,
  23. provided that the above copyright notice appear in all copies and that
  24. both that copyright notice and this permission notice appear in
  25. supporting documentation, and that the name of Digital not be
  26. used in advertising or publicity pertaining to distribution of the
  27. software without specific, written prior permission.
  28. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
  29. ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
  30. DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
  31. ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  32. WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
  33. ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  34. SOFTWARE.
  35. ********************************************************/
  36. /* The panoramix components contained the following notice */
  37. /*****************************************************************
  38. Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
  39. Permission is hereby granted, free of charge, to any person obtaining a copy
  40. of this software and associated documentation files (the "Software"), to deal
  41. in the Software without restriction, including without limitation the rights
  42. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  43. copies of the Software.
  44. The above copyright notice and this permission notice shall be included in
  45. all copies or substantial portions of the Software.
  46. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  47. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  48. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  49. DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
  50. BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
  51. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
  52. IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  53. Except as contained in this notice, the name of Digital Equipment Corporation
  54. shall not be used in advertising or otherwise to promote the sale, use or other
  55. dealings in this Software without prior written authorization from Digital
  56. Equipment Corporation.
  57. ******************************************************************/
  58. /* XSERVER_DTRACE additions:
  59. * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
  60. *
  61. * Permission is hereby granted, free of charge, to any person obtaining a
  62. * copy of this software and associated documentation files (the "Software"),
  63. * to deal in the Software without restriction, including without limitation
  64. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  65. * and/or sell copies of the Software, and to permit persons to whom the
  66. * Software is furnished to do so, subject to the following conditions:
  67. *
  68. * The above copyright notice and this permission notice (including the next
  69. * paragraph) shall be included in all copies or substantial portions of the
  70. * Software.
  71. *
  72. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  73. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  74. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  75. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  76. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  77. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  78. * DEALINGS IN THE SOFTWARE.
  79. */
  80. #ifdef HAVE_DIX_CONFIG_H
  81. #include <dix-config.h>
  82. #include <version-config.h>
  83. #endif
  84. #ifdef PANORAMIX_DEBUG
  85. #include <stdio.h>
  86. int ProcInitialConnection();
  87. #endif
  88. #include "windowstr.h"
  89. #include <X11/fonts/fontstruct.h>
  90. #include "dixfontstr.h"
  91. #include "gcstruct.h"
  92. #include "selection.h"
  93. #include "colormapst.h"
  94. #include "cursorstr.h"
  95. #include "scrnintstr.h"
  96. #include "opaque.h"
  97. #include "input.h"
  98. #include "servermd.h"
  99. #include "extnsionst.h"
  100. #include "dixfont.h"
  101. #include "dispatch.h"
  102. #include "swaprep.h"
  103. #include "swapreq.h"
  104. #include "privates.h"
  105. #include "xace.h"
  106. #include "inputstr.h"
  107. #include "xkbsrv.h"
  108. #include "site.h"
  109. #include "client.h"
  110. #ifdef XSERVER_DTRACE
  111. #include "registry.h"
  112. #include <sys/types.h>
  113. typedef const char *string;
  114. #include "Xserver-dtrace.h"
  115. #endif
  116. #define mskcnt ((MAXCLIENTS + 31) / 32)
  117. #define BITMASK(i) (1U << ((i) & 31))
  118. #define MASKIDX(i) ((i) >> 5)
  119. #define MASKWORD(buf, i) buf[MASKIDX(i)]
  120. #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
  121. #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
  122. #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
  123. xConnSetupPrefix connSetupPrefix;
  124. PaddingInfo PixmapWidthPaddingInfo[33];
  125. static ClientPtr grabClient;
  126. #define GrabNone 0
  127. #define GrabActive 1
  128. #define GrabKickout 2
  129. static int grabState = GrabNone;
  130. static long grabWaiters[mskcnt];
  131. CallbackListPtr ServerGrabCallback = NULL;
  132. HWEventQueuePtr checkForInput[2];
  133. int connBlockScreenStart;
  134. static void KillAllClients(void);
  135. static int nextFreeClientID; /* always MIN free client ID */
  136. static int nClients; /* number of authorized clients */
  137. CallbackListPtr ClientStateCallback;
  138. /* dispatchException & isItTimeToYield must be declared volatile since they
  139. * are modified by signal handlers - otherwise optimizer may assume it doesn't
  140. * need to actually check value in memory when used and may miss changes from
  141. * signal handlers.
  142. */
  143. volatile char dispatchException = 0;
  144. volatile char isItTimeToYield;
  145. #define SAME_SCREENS(a, b) (\
  146. (a.pScreen == b.pScreen))
  147. void
  148. SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
  149. {
  150. checkForInput[0] = c0;
  151. checkForInput[1] = c1;
  152. }
  153. void
  154. UpdateCurrentTime(void)
  155. {
  156. TimeStamp systime;
  157. /* To avoid time running backwards, we must call GetTimeInMillis before
  158. * calling ProcessInputEvents.
  159. */
  160. systime.months = currentTime.months;
  161. systime.milliseconds = GetTimeInMillis();
  162. if (systime.milliseconds < currentTime.milliseconds)
  163. systime.months++;
  164. if (*checkForInput[0] != *checkForInput[1])
  165. ProcessInputEvents();
  166. if (CompareTimeStamps(systime, currentTime) == LATER)
  167. currentTime = systime;
  168. }
  169. /* Like UpdateCurrentTime, but can't call ProcessInputEvents */
  170. void
  171. UpdateCurrentTimeIf(void)
  172. {
  173. TimeStamp systime;
  174. systime.months = currentTime.months;
  175. systime.milliseconds = GetTimeInMillis();
  176. if (systime.milliseconds < currentTime.milliseconds)
  177. systime.months++;
  178. if (CompareTimeStamps(systime, currentTime) == LATER)
  179. currentTime = systime;
  180. }
  181. #undef SMART_DEBUG
  182. /* in milliseconds */
  183. #define SMART_SCHEDULE_DEFAULT_INTERVAL 5
  184. #define SMART_SCHEDULE_MAX_SLICE 15
  185. #if defined(WIN32) && !defined(__CYGWIN__)
  186. Bool SmartScheduleDisable = TRUE;
  187. #else
  188. Bool SmartScheduleDisable = FALSE;
  189. #endif
  190. long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
  191. long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
  192. long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
  193. long SmartScheduleTime;
  194. int SmartScheduleLatencyLimited = 0;
  195. static ClientPtr SmartLastClient;
  196. static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
  197. #ifdef SMART_DEBUG
  198. long SmartLastPrint;
  199. #endif
  200. void Dispatch(void);
  201. static int
  202. SmartScheduleClient(int *clientReady, int nready)
  203. {
  204. ClientPtr pClient;
  205. int i;
  206. int client;
  207. int bestPrio, best = 0;
  208. int bestRobin, robin;
  209. long now = SmartScheduleTime;
  210. long idle;
  211. bestPrio = -0x7fffffff;
  212. bestRobin = 0;
  213. idle = 2 * SmartScheduleSlice;
  214. for (i = 0; i < nready; i++) {
  215. client = clientReady[i];
  216. pClient = clients[client];
  217. /* Praise clients which haven't run in a while */
  218. if ((now - pClient->smart_stop_tick) >= idle) {
  219. if (pClient->smart_priority < 0)
  220. pClient->smart_priority++;
  221. }
  222. /* check priority to select best client */
  223. robin =
  224. (pClient->index -
  225. SmartLastIndex[pClient->smart_priority -
  226. SMART_MIN_PRIORITY]) & 0xff;
  227. if (pClient->smart_priority > bestPrio ||
  228. (pClient->smart_priority == bestPrio && robin > bestRobin)) {
  229. bestPrio = pClient->smart_priority;
  230. bestRobin = robin;
  231. best = client;
  232. }
  233. #ifdef SMART_DEBUG
  234. if ((now - SmartLastPrint) >= 5000)
  235. fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
  236. #endif
  237. }
  238. #ifdef SMART_DEBUG
  239. if ((now - SmartLastPrint) >= 5000) {
  240. fprintf(stderr, " use %2d\n", best);
  241. SmartLastPrint = now;
  242. }
  243. #endif
  244. pClient = clients[best];
  245. SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
  246. /*
  247. * Set current client pointer
  248. */
  249. if (SmartLastClient != pClient) {
  250. pClient->smart_start_tick = now;
  251. SmartLastClient = pClient;
  252. }
  253. /*
  254. * Adjust slice
  255. */
  256. if (nready == 1 && SmartScheduleLatencyLimited == 0) {
  257. /*
  258. * If it's been a long time since another client
  259. * has run, bump the slice up to get maximal
  260. * performance from a single client
  261. */
  262. if ((now - pClient->smart_start_tick) > 1000 &&
  263. SmartScheduleSlice < SmartScheduleMaxSlice) {
  264. SmartScheduleSlice += SmartScheduleInterval;
  265. }
  266. }
  267. else {
  268. SmartScheduleSlice = SmartScheduleInterval;
  269. }
  270. return best;
  271. }
  272. void
  273. EnableLimitedSchedulingLatency(void)
  274. {
  275. ++SmartScheduleLatencyLimited;
  276. SmartScheduleSlice = SmartScheduleInterval;
  277. }
  278. void
  279. DisableLimitedSchedulingLatency(void)
  280. {
  281. --SmartScheduleLatencyLimited;
  282. /* protect against bugs */
  283. if (SmartScheduleLatencyLimited < 0)
  284. SmartScheduleLatencyLimited = 0;
  285. }
  286. void
  287. Dispatch(void)
  288. {
  289. int *clientReady; /* array of request ready clients */
  290. int result;
  291. ClientPtr client;
  292. int nready;
  293. HWEventQueuePtr *icheck = checkForInput;
  294. long start_tick;
  295. nextFreeClientID = 1;
  296. nClients = 0;
  297. clientReady = malloc(sizeof(int) * MaxClients);
  298. if (!clientReady)
  299. return;
  300. SmartScheduleSlice = SmartScheduleInterval;
  301. while (!dispatchException) {
  302. if (*icheck[0] != *icheck[1]) {
  303. ProcessInputEvents();
  304. FlushIfCriticalOutputPending();
  305. }
  306. nready = WaitForSomething(clientReady);
  307. if (nready && !SmartScheduleDisable) {
  308. clientReady[0] = SmartScheduleClient(clientReady, nready);
  309. nready = 1;
  310. }
  311. /*****************
  312. * Handle events in round robin fashion, doing input between
  313. * each round
  314. *****************/
  315. while (!dispatchException && (--nready >= 0)) {
  316. client = clients[clientReady[nready]];
  317. if (!client) {
  318. /* KillClient can cause this to happen */
  319. continue;
  320. }
  321. /* GrabServer activation can cause this to be true */
  322. if (grabState == GrabKickout) {
  323. grabState = GrabActive;
  324. break;
  325. }
  326. isItTimeToYield = FALSE;
  327. start_tick = SmartScheduleTime;
  328. while (!isItTimeToYield) {
  329. if (*icheck[0] != *icheck[1])
  330. ProcessInputEvents();
  331. FlushIfCriticalOutputPending();
  332. if (!SmartScheduleDisable &&
  333. (SmartScheduleTime - start_tick) >= SmartScheduleSlice) {
  334. /* Penalize clients which consume ticks */
  335. if (client->smart_priority > SMART_MIN_PRIORITY)
  336. client->smart_priority--;
  337. break;
  338. }
  339. /* now, finally, deal with client requests */
  340. /* Update currentTime so request time checks, such as for input
  341. * device grabs, are calculated correctly */
  342. UpdateCurrentTimeIf();
  343. result = ReadRequestFromClient(client);
  344. if (result <= 0) {
  345. if (result < 0)
  346. CloseDownClient(client);
  347. break;
  348. }
  349. client->sequence++;
  350. client->majorOp = ((xReq *) client->requestBuffer)->reqType;
  351. client->minorOp = 0;
  352. if (client->majorOp >= EXTENSION_BASE) {
  353. ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
  354. if (ext)
  355. client->minorOp = ext->MinorOpcode(client);
  356. }
  357. #ifdef XSERVER_DTRACE
  358. if (XSERVER_REQUEST_START_ENABLED())
  359. XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
  360. client->majorOp,
  361. ((xReq *) client->requestBuffer)->length,
  362. client->index,
  363. client->requestBuffer);
  364. #endif
  365. if (result > (maxBigRequestSize << 2))
  366. result = BadLength;
  367. else {
  368. result = XaceHookDispatch(client, client->majorOp);
  369. if (result == Success)
  370. result =
  371. (*client->requestVector[client->majorOp]) (client);
  372. XaceHookAuditEnd(client, result);
  373. }
  374. #ifdef XSERVER_DTRACE
  375. if (XSERVER_REQUEST_DONE_ENABLED())
  376. XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
  377. client->majorOp, client->sequence,
  378. client->index, result);
  379. #endif
  380. if (client->noClientException != Success) {
  381. CloseDownClient(client);
  382. break;
  383. }
  384. else if (result != Success) {
  385. SendErrorToClient(client, client->majorOp,
  386. client->minorOp,
  387. client->errorValue, result);
  388. break;
  389. }
  390. }
  391. FlushAllOutput();
  392. client = clients[clientReady[nready]];
  393. if (client)
  394. client->smart_stop_tick = SmartScheduleTime;
  395. }
  396. dispatchException &= ~DE_PRIORITYCHANGE;
  397. }
  398. #if defined(DDXBEFORERESET)
  399. ddxBeforeReset();
  400. #endif
  401. KillAllClients();
  402. free(clientReady);
  403. dispatchException &= ~DE_RESET;
  404. SmartScheduleLatencyLimited = 0;
  405. ResetOsBuffers();
  406. }
  407. static int VendorRelease = VENDOR_RELEASE;
  408. static const char *VendorString = VENDOR_NAME;
  409. void
  410. SetVendorRelease(int release)
  411. {
  412. VendorRelease = release;
  413. }
  414. void
  415. SetVendorString(const char *vendor)
  416. {
  417. VendorString = vendor;
  418. }
  419. Bool
  420. CreateConnectionBlock(void)
  421. {
  422. xConnSetup setup;
  423. xWindowRoot root;
  424. xDepth depth;
  425. xVisualType visual;
  426. xPixmapFormat format;
  427. unsigned long vid;
  428. int i, j, k, lenofblock, sizesofar = 0;
  429. char *pBuf;
  430. memset(&setup, 0, sizeof(xConnSetup));
  431. /* Leave off the ridBase and ridMask, these must be sent with
  432. connection */
  433. setup.release = VendorRelease;
  434. /*
  435. * per-server image and bitmap parameters are defined in Xmd.h
  436. */
  437. setup.imageByteOrder = screenInfo.imageByteOrder;
  438. setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
  439. setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
  440. setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
  441. setup.motionBufferSize = NumMotionEvents();
  442. setup.numRoots = screenInfo.numScreens;
  443. setup.nbytesVendor = strlen(VendorString);
  444. setup.numFormats = screenInfo.numPixmapFormats;
  445. setup.maxRequestSize = MAX_REQUEST_SIZE;
  446. QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
  447. lenofblock = sizeof(xConnSetup) +
  448. pad_to_int32(setup.nbytesVendor) +
  449. (setup.numFormats * sizeof(xPixmapFormat)) +
  450. (setup.numRoots * sizeof(xWindowRoot));
  451. ConnectionInfo = malloc(lenofblock);
  452. if (!ConnectionInfo)
  453. return FALSE;
  454. memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
  455. sizesofar = sizeof(xConnSetup);
  456. pBuf = ConnectionInfo + sizeof(xConnSetup);
  457. memmove(pBuf, VendorString, (int) setup.nbytesVendor);
  458. sizesofar += setup.nbytesVendor;
  459. pBuf += setup.nbytesVendor;
  460. i = padding_for_int32(setup.nbytesVendor);
  461. sizesofar += i;
  462. while (--i >= 0)
  463. *pBuf++ = 0;
  464. memset(&format, 0, sizeof(xPixmapFormat));
  465. for (i = 0; i < screenInfo.numPixmapFormats; i++) {
  466. format.depth = screenInfo.formats[i].depth;
  467. format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
  468. format.scanLinePad = screenInfo.formats[i].scanlinePad;
  469. memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
  470. pBuf += sizeof(xPixmapFormat);
  471. sizesofar += sizeof(xPixmapFormat);
  472. }
  473. connBlockScreenStart = sizesofar;
  474. memset(&depth, 0, sizeof(xDepth));
  475. memset(&visual, 0, sizeof(xVisualType));
  476. for (i = 0; i < screenInfo.numScreens; i++) {
  477. ScreenPtr pScreen;
  478. DepthPtr pDepth;
  479. VisualPtr pVisual;
  480. pScreen = screenInfo.screens[i];
  481. root.windowId = pScreen->root->drawable.id;
  482. root.defaultColormap = pScreen->defColormap;
  483. root.whitePixel = pScreen->whitePixel;
  484. root.blackPixel = pScreen->blackPixel;
  485. root.currentInputMask = 0; /* filled in when sent */
  486. root.pixWidth = pScreen->width;
  487. root.pixHeight = pScreen->height;
  488. root.mmWidth = pScreen->mmWidth;
  489. root.mmHeight = pScreen->mmHeight;
  490. root.minInstalledMaps = pScreen->minInstalledCmaps;
  491. root.maxInstalledMaps = pScreen->maxInstalledCmaps;
  492. root.rootVisualID = pScreen->rootVisual;
  493. root.backingStore = pScreen->backingStoreSupport;
  494. root.saveUnders = FALSE;
  495. root.rootDepth = pScreen->rootDepth;
  496. root.nDepths = pScreen->numDepths;
  497. memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
  498. sizesofar += sizeof(xWindowRoot);
  499. pBuf += sizeof(xWindowRoot);
  500. pDepth = pScreen->allowedDepths;
  501. for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
  502. lenofblock += sizeof(xDepth) +
  503. (pDepth->numVids * sizeof(xVisualType));
  504. pBuf = (char *) realloc(ConnectionInfo, lenofblock);
  505. if (!pBuf) {
  506. free(ConnectionInfo);
  507. return FALSE;
  508. }
  509. ConnectionInfo = pBuf;
  510. pBuf += sizesofar;
  511. depth.depth = pDepth->depth;
  512. depth.nVisuals = pDepth->numVids;
  513. memmove(pBuf, (char *) &depth, sizeof(xDepth));
  514. pBuf += sizeof(xDepth);
  515. sizesofar += sizeof(xDepth);
  516. for (k = 0; k < pDepth->numVids; k++) {
  517. vid = pDepth->vids[k];
  518. for (pVisual = pScreen->visuals;
  519. pVisual->vid != vid; pVisual++);
  520. visual.visualID = vid;
  521. visual.class = pVisual->class;
  522. visual.bitsPerRGB = pVisual->bitsPerRGBValue;
  523. visual.colormapEntries = pVisual->ColormapEntries;
  524. visual.redMask = pVisual->redMask;
  525. visual.greenMask = pVisual->greenMask;
  526. visual.blueMask = pVisual->blueMask;
  527. memmove(pBuf, (char *) &visual, sizeof(xVisualType));
  528. pBuf += sizeof(xVisualType);
  529. sizesofar += sizeof(xVisualType);
  530. }
  531. }
  532. }
  533. connSetupPrefix.success = xTrue;
  534. connSetupPrefix.length = lenofblock / 4;
  535. connSetupPrefix.majorVersion = X_PROTOCOL;
  536. connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
  537. return TRUE;
  538. }
  539. int
  540. ProcBadRequest(ClientPtr client)
  541. {
  542. return BadRequest;
  543. }
  544. int
  545. ProcCreateWindow(ClientPtr client)
  546. {
  547. WindowPtr pParent, pWin;
  548. REQUEST(xCreateWindowReq);
  549. int len, rc;
  550. REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
  551. LEGAL_NEW_RESOURCE(stuff->wid, client);
  552. rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
  553. if (rc != Success)
  554. return rc;
  555. len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
  556. if (Ones(stuff->mask) != len)
  557. return BadLength;
  558. if (!stuff->width || !stuff->height) {
  559. client->errorValue = 0;
  560. return BadValue;
  561. }
  562. pWin = CreateWindow(stuff->wid, pParent, stuff->x,
  563. stuff->y, stuff->width, stuff->height,
  564. stuff->borderWidth, stuff->class,
  565. stuff->mask, (XID *) &stuff[1],
  566. (int) stuff->depth, client, stuff->visual, &rc);
  567. if (pWin) {
  568. Mask mask = pWin->eventMask;
  569. pWin->eventMask = 0; /* subterfuge in case AddResource fails */
  570. if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
  571. return BadAlloc;
  572. pWin->eventMask = mask;
  573. }
  574. return rc;
  575. }
  576. int
  577. ProcChangeWindowAttributes(ClientPtr client)
  578. {
  579. WindowPtr pWin;
  580. REQUEST(xChangeWindowAttributesReq);
  581. int len, rc;
  582. Mask access_mode = 0;
  583. REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
  584. access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
  585. access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
  586. rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
  587. if (rc != Success)
  588. return rc;
  589. len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
  590. if (len != Ones(stuff->valueMask))
  591. return BadLength;
  592. return ChangeWindowAttributes(pWin,
  593. stuff->valueMask, (XID *) &stuff[1], client);
  594. }
  595. int
  596. ProcGetWindowAttributes(ClientPtr client)
  597. {
  598. WindowPtr pWin;
  599. REQUEST(xResourceReq);
  600. xGetWindowAttributesReply wa;
  601. int rc;
  602. REQUEST_SIZE_MATCH(xResourceReq);
  603. rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
  604. if (rc != Success)
  605. return rc;
  606. memset(&wa, 0, sizeof(xGetWindowAttributesReply));
  607. GetWindowAttributes(pWin, client, &wa);
  608. WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
  609. return Success;
  610. }
  611. int
  612. ProcDestroyWindow(ClientPtr client)
  613. {
  614. WindowPtr pWin;
  615. REQUEST(xResourceReq);
  616. int rc;
  617. REQUEST_SIZE_MATCH(xResourceReq);
  618. rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
  619. if (rc != Success)
  620. return rc;
  621. if (pWin->parent) {
  622. rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
  623. DixRemoveAccess);
  624. if (rc != Success)
  625. return rc;
  626. FreeResource(stuff->id, RT_NONE);
  627. }
  628. return Success;
  629. }
  630. int
  631. ProcDestroySubwindows(ClientPtr client)
  632. {
  633. WindowPtr pWin;
  634. REQUEST(xResourceReq);
  635. int rc;
  636. REQUEST_SIZE_MATCH(xResourceReq);
  637. rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
  638. if (rc != Success)
  639. return rc;
  640. DestroySubwindows(pWin, client);
  641. return Success;
  642. }
  643. int
  644. ProcChangeSaveSet(ClientPtr client)
  645. {
  646. WindowPtr pWin;
  647. REQUEST(xChangeSaveSetReq);
  648. int rc;
  649. REQUEST_SIZE_MATCH(xChangeSaveSetReq);
  650. rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
  651. if (rc != Success)
  652. return rc;
  653. if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
  654. return BadMatch;
  655. if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
  656. return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
  657. client->errorValue = stuff->mode;
  658. return BadValue;
  659. }
  660. int
  661. ProcReparentWindow(ClientPtr client)
  662. {
  663. WindowPtr pWin, pParent;
  664. REQUEST(xReparentWindowReq);
  665. int rc;
  666. REQUEST_SIZE_MATCH(xReparentWindowReq);
  667. rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
  668. if (rc != Success)
  669. return rc;
  670. rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
  671. if (rc != Success)
  672. return rc;
  673. if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
  674. return BadMatch;
  675. if ((pWin->backgroundState == ParentRelative) &&
  676. (pParent->drawable.depth != pWin->drawable.depth))
  677. return BadMatch;
  678. if ((pWin->drawable.class != InputOnly) &&
  679. (pParent->drawable.class == InputOnly))
  680. return BadMatch;
  681. return ReparentWindow(pWin, pParent,
  682. (short) stuff->x, (short) stuff->y, client);
  683. }
  684. int
  685. ProcMapWindow(ClientPtr client)
  686. {
  687. WindowPtr pWin;
  688. REQUEST(xResourceReq);
  689. int rc;
  690. REQUEST_SIZE_MATCH(xResourceReq);
  691. rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
  692. if (rc != Success)
  693. return rc;
  694. MapWindow(pWin, client);
  695. /* update cache to say it is mapped */
  696. return Success;
  697. }
  698. int
  699. ProcMapSubwindows(ClientPtr client)
  700. {
  701. WindowPtr pWin;
  702. REQUEST(xResourceReq);
  703. int rc;
  704. REQUEST_SIZE_MATCH(xResourceReq);
  705. rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
  706. if (rc != Success)
  707. return rc;
  708. MapSubwindows(pWin, client);
  709. /* update cache to say it is mapped */
  710. return Success;
  711. }
  712. int
  713. ProcUnmapWindow(ClientPtr client)
  714. {
  715. WindowPtr pWin;
  716. REQUEST(xResourceReq);
  717. int rc;
  718. REQUEST_SIZE_MATCH(xResourceReq);
  719. rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
  720. if (rc != Success)
  721. return rc;
  722. UnmapWindow(pWin, FALSE);
  723. /* update cache to say it is mapped */
  724. return Success;
  725. }
  726. int
  727. ProcUnmapSubwindows(ClientPtr client)
  728. {
  729. WindowPtr pWin;
  730. REQUEST(xResourceReq);
  731. int rc;
  732. REQUEST_SIZE_MATCH(xResourceReq);
  733. rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
  734. if (rc != Success)
  735. return rc;
  736. UnmapSubwindows(pWin);
  737. return Success;
  738. }
  739. int
  740. ProcConfigureWindow(ClientPtr client)
  741. {
  742. WindowPtr pWin;
  743. REQUEST(xConfigureWindowReq);
  744. int len, rc;
  745. REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
  746. rc = dixLookupWindow(&pWin, stuff->window, client,
  747. DixManageAccess | DixSetAttrAccess);
  748. if (rc != Success)
  749. return rc;
  750. len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
  751. if (Ones((Mask) stuff->mask) != len)
  752. return BadLength;
  753. return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
  754. }
  755. int
  756. ProcCirculateWindow(ClientPtr client)
  757. {
  758. WindowPtr pWin;
  759. REQUEST(xCirculateWindowReq);
  760. int rc;
  761. REQUEST_SIZE_MATCH(xCirculateWindowReq);
  762. if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
  763. client->errorValue = stuff->direction;
  764. return BadValue;
  765. }
  766. rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
  767. if (rc != Success)
  768. return rc;
  769. CirculateWindow(pWin, (int) stuff->direction, client);
  770. return Success;
  771. }
  772. static int
  773. GetGeometry(ClientPtr client, xGetGeometryReply * rep)
  774. {
  775. DrawablePtr pDraw;
  776. int rc;
  777. REQUEST(xResourceReq);
  778. REQUEST_SIZE_MATCH(xResourceReq);
  779. rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
  780. if (rc != Success)
  781. return rc;
  782. rep->type = X_Reply;
  783. rep->length = 0;
  784. rep->sequenceNumber = client->sequence;
  785. rep->root = pDraw->pScreen->root->drawable.id;
  786. rep->depth = pDraw->depth;
  787. rep->width = pDraw->width;
  788. rep->height = pDraw->height;
  789. if (WindowDrawable(pDraw->type)) {
  790. WindowPtr pWin = (WindowPtr) pDraw;
  791. rep->x = pWin->origin.x - wBorderWidth(pWin);
  792. rep->y = pWin->origin.y - wBorderWidth(pWin);
  793. rep->borderWidth = pWin->borderWidth;
  794. }
  795. else { /* DRAWABLE_PIXMAP */
  796. rep->x = rep->y = rep->borderWidth = 0;
  797. }
  798. return Success;
  799. }
  800. int
  801. ProcGetGeometry(ClientPtr client)
  802. {
  803. xGetGeometryReply rep = { .type = X_Reply };
  804. int status;
  805. if ((status = GetGeometry(client, &rep)) != Success)
  806. return status;
  807. WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
  808. return Success;
  809. }
  810. int
  811. ProcQueryTree(ClientPtr client)
  812. {
  813. xQueryTreeReply reply;
  814. int rc, numChildren = 0;
  815. WindowPtr pChild, pWin, pHead;
  816. Window *childIDs = (Window *) NULL;
  817. REQUEST(xResourceReq);
  818. REQUEST_SIZE_MATCH(xResourceReq);
  819. rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
  820. if (rc != Success)
  821. return rc;
  822. reply = (xQueryTreeReply) {
  823. .type = X_Reply,
  824. .sequenceNumber = client->sequence,
  825. .root = pWin->drawable.pScreen->root->drawable.id,
  826. .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
  827. };
  828. pHead = RealChildHead(pWin);
  829. for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
  830. numChildren++;
  831. if (numChildren) {
  832. int curChild = 0;
  833. childIDs = malloc(numChildren * sizeof(Window));
  834. if (!childIDs)
  835. return BadAlloc;
  836. for (pChild = pWin->lastChild; pChild != pHead;
  837. pChild = pChild->prevSib)
  838. childIDs[curChild++] = pChild->drawable.id;
  839. }
  840. reply.nChildren = numChildren;
  841. reply.length = bytes_to_int32(numChildren * sizeof(Window));
  842. WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
  843. if (numChildren) {
  844. client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
  845. WriteSwappedDataToClient(client, numChildren * sizeof(Window),
  846. childIDs);
  847. free(childIDs);
  848. }
  849. return Success;
  850. }
  851. int
  852. ProcInternAtom(ClientPtr client)
  853. {
  854. Atom atom;
  855. char *tchar;
  856. REQUEST(xInternAtomReq);
  857. REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
  858. if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
  859. client->errorValue = stuff->onlyIfExists;
  860. return BadValue;
  861. }
  862. tchar = (char *) &stuff[1];
  863. atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
  864. if (atom != BAD_RESOURCE) {
  865. xInternAtomReply reply = {
  866. .type = X_Reply,
  867. .sequenceNumber = client->sequence,
  868. .length = 0,
  869. .atom = atom
  870. };
  871. WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
  872. return Success;
  873. }
  874. else
  875. return BadAlloc;
  876. }
  877. int
  878. ProcGetAtomName(ClientPtr client)
  879. {
  880. const char *str;
  881. REQUEST(xResourceReq);
  882. REQUEST_SIZE_MATCH(xResourceReq);
  883. if ((str = NameForAtom(stuff->id))) {
  884. int len = strlen(str);
  885. xGetAtomNameReply reply = {
  886. .type = X_Reply,
  887. .sequenceNumber = client->sequence,
  888. .length = bytes_to_int32(len),
  889. .nameLength = len
  890. };
  891. WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
  892. WriteToClient(client, len, str);
  893. return Success;
  894. }
  895. else {
  896. client->errorValue = stuff->id;
  897. return BadAtom;
  898. }
  899. }
  900. int
  901. ProcGrabServer(ClientPtr client)
  902. {
  903. int rc;
  904. REQUEST_SIZE_MATCH(xReq);
  905. if (grabState != GrabNone && client != grabClient) {
  906. ResetCurrentRequest(client);
  907. client->sequence--;
  908. BITSET(grabWaiters, client->index);
  909. IgnoreClient(client);
  910. return Success;
  911. }
  912. rc = OnlyListenToOneClient(client);
  913. if (rc != Success)
  914. return rc;
  915. grabState = GrabKickout;
  916. grabClient = client;
  917. if (ServerGrabCallback) {
  918. ServerGrabInfoRec grabinfo;
  919. grabinfo.client = client;
  920. grabinfo.grabstate = SERVER_GRABBED;
  921. CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
  922. }
  923. return Success;
  924. }
  925. static void
  926. UngrabServer(ClientPtr client)
  927. {
  928. int i;
  929. grabState = GrabNone;
  930. ListenToAllClients();
  931. for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
  932. if (i >= 0) {
  933. i <<= 5;
  934. while (!GETBIT(grabWaiters, i))
  935. i++;
  936. BITCLEAR(grabWaiters, i);
  937. AttendClient(clients[i]);
  938. }
  939. if (ServerGrabCallback) {
  940. ServerGrabInfoRec grabinfo;
  941. grabinfo.client = client;
  942. grabinfo.grabstate = SERVER_UNGRABBED;
  943. CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
  944. }
  945. }
  946. int
  947. ProcUngrabServer(ClientPtr client)
  948. {
  949. REQUEST_SIZE_MATCH(xReq);
  950. UngrabServer(client);
  951. return Success;
  952. }
  953. int
  954. ProcTranslateCoords(ClientPtr client)
  955. {
  956. REQUEST(xTranslateCoordsReq);
  957. WindowPtr pWin, pDst;
  958. xTranslateCoordsReply rep;
  959. int rc;
  960. REQUEST_SIZE_MATCH(xTranslateCoordsReq);
  961. rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
  962. if (rc != Success)
  963. return rc;
  964. rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
  965. if (rc != Success)
  966. return rc;
  967. rep = (xTranslateCoordsReply) {
  968. .type = X_Reply,
  969. .sequenceNumber = client->sequence,
  970. .length = 0
  971. };
  972. if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
  973. rep.sameScreen = xFalse;
  974. rep.child = None;
  975. rep.dstX = rep.dstY = 0;
  976. }
  977. else {
  978. INT16 x, y;
  979. rep.sameScreen = xTrue;
  980. rep.child = None;
  981. /* computing absolute coordinates -- adjust to destination later */
  982. x = pWin->drawable.x + stuff->srcX;
  983. y = pWin->drawable.y + stuff->srcY;
  984. pWin = pDst->firstChild;
  985. while (pWin) {
  986. BoxRec box;
  987. if ((pWin->mapped) &&
  988. (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
  989. (x < pWin->drawable.x + (int) pWin->drawable.width +
  990. wBorderWidth(pWin)) &&
  991. (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
  992. (y < pWin->drawable.y + (int) pWin->drawable.height +
  993. wBorderWidth(pWin))
  994. /* When a window is shaped, a further check
  995. * is made to see if the point is inside
  996. * borderSize
  997. */
  998. && (!wBoundingShape(pWin) ||
  999. RegionContainsPoint(&pWin->borderSize, x, y, &box))
  1000. && (!wInputShape(pWin) ||
  1001. RegionContainsPoint(wInputShape(pWin),
  1002. x - pWin->drawable.x,
  1003. y - pWin->drawable.y, &box))
  1004. ) {
  1005. rep.child = pWin->drawable.id;
  1006. pWin = (WindowPtr) NULL;
  1007. }
  1008. else
  1009. pWin = pWin->nextSib;
  1010. }
  1011. /* adjust to destination coordinates */
  1012. rep.dstX = x - pDst->drawable.x;
  1013. rep.dstY = y - pDst->drawable.y;
  1014. }
  1015. WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
  1016. return Success;
  1017. }
  1018. int
  1019. ProcOpenFont(ClientPtr client)
  1020. {
  1021. int err;
  1022. REQUEST(xOpenFontReq);
  1023. REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
  1024. client->errorValue = stuff->fid;
  1025. LEGAL_NEW_RESOURCE(stuff->fid, client);
  1026. err = OpenFont(client, stuff->fid, (Mask) 0,
  1027. stuff->nbytes, (char *) &stuff[1]);
  1028. if (err == Success) {
  1029. return Success;
  1030. }
  1031. else
  1032. return err;
  1033. }
  1034. int
  1035. ProcCloseFont(ClientPtr client)
  1036. {
  1037. FontPtr pFont;
  1038. int rc;
  1039. REQUEST(xResourceReq);
  1040. REQUEST_SIZE_MATCH(xResourceReq);
  1041. rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
  1042. client, DixDestroyAccess);
  1043. if (rc == Success) {
  1044. FreeResource(stuff->id, RT_NONE);
  1045. return Success;
  1046. }
  1047. else {
  1048. client->errorValue = stuff->id;
  1049. return rc;
  1050. }
  1051. }
  1052. int
  1053. ProcQueryFont(ClientPtr client)
  1054. {
  1055. xQueryFontReply *reply;
  1056. FontPtr pFont;
  1057. int rc;
  1058. REQUEST(xResourceReq);
  1059. REQUEST_SIZE_MATCH(xResourceReq);
  1060. rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
  1061. if (rc != Success)
  1062. return rc;
  1063. {
  1064. xCharInfo *pmax = FONTINKMAX(pFont);
  1065. xCharInfo *pmin = FONTINKMIN(pFont);
  1066. int nprotoxcistructs;
  1067. int rlength;
  1068. nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
  1069. pmax->leftSideBearing == pmin->leftSideBearing &&
  1070. pmax->descent == pmin->descent &&
  1071. pmax->ascent == pmin->ascent &&
  1072. pmax->characterWidth == pmin->characterWidth) ?
  1073. 0 : N2dChars(pFont);
  1074. rlength = sizeof(xQueryFontReply) +
  1075. FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
  1076. nprotoxcistructs * sizeof(xCharInfo);
  1077. reply = calloc(1, rlength);
  1078. if (!reply) {
  1079. return BadAlloc;
  1080. }
  1081. reply->type = X_Reply;
  1082. reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
  1083. reply->sequenceNumber = client->sequence;
  1084. QueryFont(pFont, reply, nprotoxcistructs);
  1085. WriteReplyToClient(client, rlength, reply);
  1086. free(reply);
  1087. return Success;
  1088. }
  1089. }
  1090. int
  1091. ProcQueryTextExtents(ClientPtr client)
  1092. {
  1093. xQueryTextExtentsReply reply;
  1094. FontPtr pFont;
  1095. ExtentInfoRec info;
  1096. unsigned long length;
  1097. int rc;
  1098. REQUEST(xQueryTextExtentsReq);
  1099. REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
  1100. rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
  1101. if (rc != Success)
  1102. return rc;
  1103. length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
  1104. length = length << 1;
  1105. if (stuff->oddLength) {
  1106. if (length == 0)
  1107. return BadLength;
  1108. length--;
  1109. }
  1110. if (!QueryTextExtents(pFont, length, (unsigned char *) &stuff[1], &info))
  1111. return BadAlloc;
  1112. reply = (xQueryTextExtentsReply) {
  1113. .type = X_Reply,
  1114. .drawDirection = info.drawDirection,
  1115. .sequenceNumber = client->sequence,
  1116. .length = 0,
  1117. .fontAscent = info.fontAscent,
  1118. .fontDescent = info.fontDescent,
  1119. .overallAscent = info.overallAscent,
  1120. .overallDescent = info.overallDescent,
  1121. .overallWidth = info.overallWidth,
  1122. .overallLeft = info.overallLeft,
  1123. .overallRight = info.overallRight
  1124. };
  1125. WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
  1126. return Success;
  1127. }
  1128. int
  1129. ProcListFonts(ClientPtr client)
  1130. {
  1131. REQUEST(xListFontsReq);
  1132. REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
  1133. return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
  1134. stuff->maxNames);
  1135. }
  1136. int
  1137. ProcListFontsWithInfo(ClientPtr client)
  1138. {
  1139. REQUEST(xListFontsWithInfoReq);
  1140. REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
  1141. return StartListFontsWithInfo(client, stuff->nbytes,
  1142. (unsigned char *) &stuff[1], stuff->maxNames);
  1143. }
  1144. /**
  1145. *
  1146. * \param value must conform to DeleteType
  1147. */
  1148. int
  1149. dixDestroyPixmap(void *value, XID pid)
  1150. {
  1151. PixmapPtr pPixmap = (PixmapPtr) value;
  1152. return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
  1153. }
  1154. int
  1155. ProcCreatePixmap(ClientPtr client)
  1156. {
  1157. PixmapPtr pMap;
  1158. DrawablePtr pDraw;
  1159. REQUEST(xCreatePixmapReq);
  1160. DepthPtr pDepth;
  1161. int i, rc;
  1162. REQUEST_SIZE_MATCH(xCreatePixmapReq);
  1163. client->errorValue = stuff->pid;
  1164. LEGAL_NEW_RESOURCE(stuff->pid, client);
  1165. rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
  1166. DixGetAttrAccess);
  1167. if (rc != Success)
  1168. return rc;
  1169. if (!stuff->width || !stuff->height) {
  1170. client->errorValue = 0;
  1171. return BadValue;
  1172. }
  1173. if (stuff->width > 32767 || stuff->height > 32767) {
  1174. /* It is allowed to try and allocate a pixmap which is larger than
  1175. * 32767 in either dimension. However, all of the framebuffer code
  1176. * is buggy and does not reliably draw to such big pixmaps, basically
  1177. * because the Region data structure operates with signed shorts
  1178. * for the rectangles in it.
  1179. *
  1180. * Furthermore, several places in the X server computes the
  1181. * size in bytes of the pixmap and tries to store it in an
  1182. * integer. This integer can overflow and cause the allocated size
  1183. * to be much smaller.
  1184. *
  1185. * So, such big pixmaps are rejected here with a BadAlloc
  1186. */
  1187. return BadAlloc;
  1188. }
  1189. if (stuff->depth != 1) {
  1190. pDepth = pDraw->pScreen->allowedDepths;
  1191. for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
  1192. if (pDepth->depth == stuff->depth)
  1193. goto CreatePmap;
  1194. client->errorValue = stuff->depth;
  1195. return BadValue;
  1196. }
  1197. CreatePmap:
  1198. pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
  1199. (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
  1200. if (pMap) {
  1201. pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
  1202. pMap->drawable.id = stuff->pid;
  1203. /* security creation/labeling check */
  1204. rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
  1205. pMap, RT_NONE, NULL, DixCreateAccess);
  1206. if (rc != Success) {
  1207. (*pDraw->pScreen->DestroyPixmap) (pMap);
  1208. return rc;
  1209. }
  1210. if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
  1211. return Success;
  1212. }
  1213. return BadAlloc;
  1214. }
  1215. int
  1216. ProcFreePixmap(ClientPtr client)
  1217. {
  1218. PixmapPtr pMap;
  1219. int rc;
  1220. REQUEST(xResourceReq);
  1221. REQUEST_SIZE_MATCH(xResourceReq);
  1222. rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
  1223. client, DixDestroyAccess);
  1224. if (rc == Success) {
  1225. FreeResource(stuff->id, RT_NONE);
  1226. return Success;
  1227. }
  1228. else {
  1229. client->errorValue = stuff->id;
  1230. return rc;
  1231. }
  1232. }
  1233. int
  1234. ProcCreateGC(ClientPtr client)
  1235. {
  1236. int error, rc;
  1237. GC *pGC;
  1238. DrawablePtr pDraw;
  1239. unsigned len;
  1240. REQUEST(xCreateGCReq);
  1241. REQUEST_AT_LEAST_SIZE(xCreateGCReq);
  1242. client->errorValue = stuff->gc;
  1243. LEGAL_NEW_RESOURCE(stuff->gc, client);
  1244. rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
  1245. DixGetAttrAccess);
  1246. if (rc != Success)
  1247. return rc;
  1248. len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
  1249. if (len != Ones(stuff->mask))
  1250. return BadLength;
  1251. pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
  1252. stuff->gc, client);
  1253. if (error != Success)
  1254. return error;
  1255. if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
  1256. return BadAlloc;
  1257. return Success;
  1258. }
  1259. int
  1260. ProcChangeGC(ClientPtr client)
  1261. {
  1262. GC *pGC;
  1263. int result;
  1264. unsigned len;
  1265. REQUEST(xChangeGCReq);
  1266. REQUEST_AT_LEAST_SIZE(xChangeGCReq);
  1267. result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
  1268. if (result != Success)
  1269. return result;
  1270. len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
  1271. if (len != Ones(stuff->mask))
  1272. return BadLength;
  1273. return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
  1274. }
  1275. int
  1276. ProcCopyGC(ClientPtr client)
  1277. {
  1278. GC *dstGC;
  1279. GC *pGC;
  1280. int result;
  1281. REQUEST(xCopyGCReq);
  1282. REQUEST_SIZE_MATCH(xCopyGCReq);
  1283. result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
  1284. if (result != Success)
  1285. return result;
  1286. result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
  1287. if (result != Success)
  1288. return result;
  1289. if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
  1290. return BadMatch;
  1291. if (stuff->mask & ~GCAllBits) {
  1292. client->errorValue = stuff->mask;
  1293. return BadValue;
  1294. }
  1295. return CopyGC(pGC, dstGC, stuff->mask);
  1296. }
  1297. int
  1298. ProcSetDashes(ClientPtr client)
  1299. {
  1300. GC *pGC;
  1301. int result;
  1302. REQUEST(xSetDashesReq);
  1303. REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
  1304. if (stuff->nDashes == 0) {
  1305. client->errorValue = 0;
  1306. return BadValue;
  1307. }
  1308. result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
  1309. if (result != Success)
  1310. return result;
  1311. /* If there's an error, either there's no sensible errorValue,
  1312. * or there was a dash segment of 0. */
  1313. client->errorValue = 0;
  1314. return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
  1315. (unsigned char *) &stuff[1]);
  1316. }
  1317. int
  1318. ProcSetClipRectangles(ClientPtr client)
  1319. {
  1320. int nr, result;
  1321. GC *pGC;
  1322. REQUEST(xSetClipRectanglesReq);
  1323. REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
  1324. if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
  1325. (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
  1326. client->errorValue = stuff->ordering;
  1327. return BadValue;
  1328. }
  1329. result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
  1330. if (result != Success)
  1331. return result;
  1332. nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
  1333. if (nr & 4)
  1334. return BadLength;
  1335. nr >>= 3;
  1336. return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
  1337. nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
  1338. }
  1339. int
  1340. ProcFreeGC(ClientPtr client)
  1341. {
  1342. GC *pGC;
  1343. int rc;
  1344. REQUEST(xResourceReq);
  1345. REQUEST_SIZE_MATCH(xResourceReq);
  1346. rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
  1347. if (rc != Success)
  1348. return rc;
  1349. FreeResource(stuff->id, RT_NONE);
  1350. return Success;
  1351. }
  1352. int
  1353. ProcClearToBackground(ClientPtr client)
  1354. {
  1355. REQUEST(xClearAreaReq);
  1356. WindowPtr pWin;
  1357. int rc;
  1358. REQUEST_SIZE_MATCH(xClearAreaReq);
  1359. rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
  1360. if (rc != Success)
  1361. return rc;
  1362. if (pWin->drawable.class == InputOnly) {
  1363. client->errorValue = stuff->window;
  1364. return BadMatch;
  1365. }
  1366. if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
  1367. client->errorValue = stuff->exposures;
  1368. return BadValue;
  1369. }
  1370. (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
  1371. stuff->width, stuff->height,
  1372. (Bool) stuff->exposures);
  1373. return Success;
  1374. }
  1375. int
  1376. ProcCopyArea(ClientPtr client)
  1377. {
  1378. DrawablePtr pDst;
  1379. DrawablePtr pSrc;
  1380. GC *pGC;
  1381. REQUEST(xCopyAreaReq);
  1382. RegionPtr pRgn;
  1383. int rc;
  1384. REQUEST_SIZE_MATCH(xCopyAreaReq);
  1385. VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
  1386. if (stuff->dstDrawable != stuff->srcDrawable) {
  1387. rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
  1388. DixReadAccess);
  1389. if (rc != Success)
  1390. return rc;
  1391. if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
  1392. client->errorValue = stuff->dstDrawable;
  1393. return BadMatch;
  1394. }
  1395. }
  1396. else
  1397. pSrc = pDst;
  1398. pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
  1399. stuff->width, stuff->height,
  1400. stuff->dstX, stuff->dstY);
  1401. if (pGC->graphicsExposures) {
  1402. (*pDst->pScreen->SendGraphicsExpose)
  1403. (client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
  1404. if (pRgn)
  1405. RegionDestroy(pRgn);
  1406. }
  1407. return Success;
  1408. }
  1409. int
  1410. ProcCopyPlane(ClientPtr client)
  1411. {
  1412. DrawablePtr psrcDraw, pdstDraw;
  1413. GC *pGC;
  1414. REQUEST(xCopyPlaneReq);
  1415. RegionPtr pRgn;
  1416. int rc;
  1417. REQUEST_SIZE_MATCH(xCopyPlaneReq);
  1418. VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
  1419. if (stuff->dstDrawable != stuff->srcDrawable) {
  1420. rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
  1421. DixReadAccess);
  1422. if (rc != Success)
  1423. return rc;
  1424. if (pdstDraw->pScreen != psrcDraw->pScreen) {
  1425. client->errorValue = stuff->dstDrawable;
  1426. return BadMatch;
  1427. }
  1428. }
  1429. else
  1430. psrcDraw = pdstDraw;
  1431. /* Check to see if stuff->bitPlane has exactly ONE good bit set */
  1432. if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
  1433. (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
  1434. client->errorValue = stuff->bitPlane;
  1435. return BadValue;
  1436. }
  1437. pRgn =
  1438. (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
  1439. stuff->srcY, stuff->width, stuff->height,
  1440. stuff->dstX, stuff->dstY, stuff->bitPlane);
  1441. if (pGC->graphicsExposures) {
  1442. (*pdstDraw->pScreen->SendGraphicsExpose)
  1443. (client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
  1444. if (pRgn)
  1445. RegionDestroy(pRgn);
  1446. }
  1447. return Success;
  1448. }
  1449. int
  1450. ProcPolyPoint(ClientPtr client)
  1451. {
  1452. int npoint;
  1453. GC *pGC;
  1454. DrawablePtr pDraw;
  1455. REQUEST(xPolyPointReq);
  1456. REQUEST_AT_LEAST_SIZE(xPolyPointReq);
  1457. if ((stuff->coordMode != CoordModeOrigin) &&
  1458. (stuff->coordMode != CoordModePrevious)) {
  1459. client->errorValue = stuff->coordMode;
  1460. return BadValue;
  1461. }
  1462. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1463. npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
  1464. if (npoint)
  1465. (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
  1466. (xPoint *) &stuff[1]);
  1467. return Success;
  1468. }
  1469. int
  1470. ProcPolyLine(ClientPtr client)
  1471. {
  1472. int npoint;
  1473. GC *pGC;
  1474. DrawablePtr pDraw;
  1475. REQUEST(xPolyLineReq);
  1476. REQUEST_AT_LEAST_SIZE(xPolyLineReq);
  1477. if ((stuff->coordMode != CoordModeOrigin) &&
  1478. (stuff->coordMode != CoordModePrevious)) {
  1479. client->errorValue = stuff->coordMode;
  1480. return BadValue;
  1481. }
  1482. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1483. npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
  1484. if (npoint > 1)
  1485. (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
  1486. (DDXPointPtr) &stuff[1]);
  1487. return Success;
  1488. }
  1489. int
  1490. ProcPolySegment(ClientPtr client)
  1491. {
  1492. int nsegs;
  1493. GC *pGC;
  1494. DrawablePtr pDraw;
  1495. REQUEST(xPolySegmentReq);
  1496. REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
  1497. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1498. nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
  1499. if (nsegs & 4)
  1500. return BadLength;
  1501. nsegs >>= 3;
  1502. if (nsegs)
  1503. (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
  1504. return Success;
  1505. }
  1506. int
  1507. ProcPolyRectangle(ClientPtr client)
  1508. {
  1509. int nrects;
  1510. GC *pGC;
  1511. DrawablePtr pDraw;
  1512. REQUEST(xPolyRectangleReq);
  1513. REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
  1514. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1515. nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
  1516. if (nrects & 4)
  1517. return BadLength;
  1518. nrects >>= 3;
  1519. if (nrects)
  1520. (*pGC->ops->PolyRectangle) (pDraw, pGC,
  1521. nrects, (xRectangle *) &stuff[1]);
  1522. return Success;
  1523. }
  1524. int
  1525. ProcPolyArc(ClientPtr client)
  1526. {
  1527. int narcs;
  1528. GC *pGC;
  1529. DrawablePtr pDraw;
  1530. REQUEST(xPolyArcReq);
  1531. REQUEST_AT_LEAST_SIZE(xPolyArcReq);
  1532. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1533. narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
  1534. if (narcs % sizeof(xArc))
  1535. return BadLength;
  1536. narcs /= sizeof(xArc);
  1537. if (narcs)
  1538. (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
  1539. return Success;
  1540. }
  1541. int
  1542. ProcFillPoly(ClientPtr client)
  1543. {
  1544. int things;
  1545. GC *pGC;
  1546. DrawablePtr pDraw;
  1547. REQUEST(xFillPolyReq);
  1548. REQUEST_AT_LEAST_SIZE(xFillPolyReq);
  1549. if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
  1550. (stuff->shape != Convex)) {
  1551. client->errorValue = stuff->shape;
  1552. return BadValue;
  1553. }
  1554. if ((stuff->coordMode != CoordModeOrigin) &&
  1555. (stuff->coordMode != CoordModePrevious)) {
  1556. client->errorValue = stuff->coordMode;
  1557. return BadValue;
  1558. }
  1559. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1560. things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
  1561. if (things)
  1562. (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
  1563. stuff->coordMode, things,
  1564. (DDXPointPtr) &stuff[1]);
  1565. return Success;
  1566. }
  1567. int
  1568. ProcPolyFillRectangle(ClientPtr client)
  1569. {
  1570. int things;
  1571. GC *pGC;
  1572. DrawablePtr pDraw;
  1573. REQUEST(xPolyFillRectangleReq);
  1574. REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
  1575. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1576. things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
  1577. if (things & 4)
  1578. return BadLength;
  1579. things >>= 3;
  1580. if (things)
  1581. (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
  1582. (xRectangle *) &stuff[1]);
  1583. return Success;
  1584. }
  1585. int
  1586. ProcPolyFillArc(ClientPtr client)
  1587. {
  1588. int narcs;
  1589. GC *pGC;
  1590. DrawablePtr pDraw;
  1591. REQUEST(xPolyFillArcReq);
  1592. REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
  1593. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1594. narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
  1595. if (narcs % sizeof(xArc))
  1596. return BadLength;
  1597. narcs /= sizeof(xArc);
  1598. if (narcs)
  1599. (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
  1600. return Success;
  1601. }
  1602. #ifdef MATCH_CLIENT_ENDIAN
  1603. int
  1604. ServerOrder(void)
  1605. {
  1606. int whichbyte = 1;
  1607. if (*((char *) &whichbyte))
  1608. return LSBFirst;
  1609. return MSBFirst;
  1610. }
  1611. #define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
  1612. void
  1613. ReformatImage(char *base, int nbytes, int bpp, int order)
  1614. {
  1615. switch (bpp) {
  1616. case 1: /* yuck */
  1617. if (BITMAP_BIT_ORDER != order)
  1618. BitOrderInvert((unsigned char *) base, nbytes);
  1619. #if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
  1620. ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
  1621. #endif
  1622. break;
  1623. case 4:
  1624. break; /* yuck */
  1625. case 8:
  1626. break;
  1627. case 16:
  1628. if (IMAGE_BYTE_ORDER != order)
  1629. TwoByteSwap((unsigned char *) base, nbytes);
  1630. break;
  1631. case 32:
  1632. if (IMAGE_BYTE_ORDER != order)
  1633. FourByteSwap((unsigned char *) base, nbytes);
  1634. break;
  1635. }
  1636. }
  1637. #else
  1638. #define ReformatImage(b,n,bpp,o)
  1639. #endif
  1640. /* 64-bit server notes: the protocol restricts padding of images to
  1641. * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
  1642. * to use internally. Removes need for internal alignment checking.
  1643. * All of the PutImage functions could be changed individually, but
  1644. * as currently written, they call other routines which require things
  1645. * to be 64-bit padded on scanlines, so we changed things here.
  1646. * If an image would be padded differently for 64- versus 32-, then
  1647. * copy each scanline to a 64-bit padded scanline.
  1648. * Also, we need to make sure that the image is aligned on a 64-bit
  1649. * boundary, even if the scanlines are padded to our satisfaction.
  1650. */
  1651. int
  1652. ProcPutImage(ClientPtr client)
  1653. {
  1654. GC *pGC;
  1655. DrawablePtr pDraw;
  1656. long length; /* length of scanline server padded */
  1657. long lengthProto; /* length of scanline protocol padded */
  1658. char *tmpImage;
  1659. REQUEST(xPutImageReq);
  1660. REQUEST_AT_LEAST_SIZE(xPutImageReq);
  1661. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1662. if (stuff->format == XYBitmap) {
  1663. if ((stuff->depth != 1) ||
  1664. (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
  1665. return BadMatch;
  1666. length = BitmapBytePad(stuff->width + stuff->leftPad);
  1667. }
  1668. else if (stuff->format == XYPixmap) {
  1669. if ((pDraw->depth != stuff->depth) ||
  1670. (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
  1671. return BadMatch;
  1672. length = BitmapBytePad(stuff->width + stuff->leftPad);
  1673. length *= stuff->depth;
  1674. }
  1675. else if (stuff->format == ZPixmap) {
  1676. if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
  1677. return BadMatch;
  1678. length = PixmapBytePad(stuff->width, stuff->depth);
  1679. }
  1680. else {
  1681. client->errorValue = stuff->format;
  1682. return BadValue;
  1683. }
  1684. tmpImage = (char *) &stuff[1];
  1685. lengthProto = length;
  1686. if ((bytes_to_int32(lengthProto * stuff->height) +
  1687. bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
  1688. return BadLength;
  1689. ReformatImage(tmpImage, lengthProto * stuff->height,
  1690. stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
  1691. ClientOrder(client));
  1692. (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
  1693. stuff->width, stuff->height,
  1694. stuff->leftPad, stuff->format, tmpImage);
  1695. return Success;
  1696. }
  1697. static int
  1698. DoGetImage(ClientPtr client, int format, Drawable drawable,
  1699. int x, int y, int width, int height,
  1700. Mask planemask)
  1701. {
  1702. DrawablePtr pDraw, pBoundingDraw;
  1703. int nlines, linesPerBuf, rc;
  1704. int linesDone;
  1705. /* coordinates relative to the bounding drawable */
  1706. int relx, rely;
  1707. long widthBytesLine, length;
  1708. Mask plane = 0;
  1709. char *pBuf;
  1710. xGetImageReply xgi;
  1711. RegionPtr pVisibleRegion = NULL;
  1712. if ((format != XYPixmap) && (format != ZPixmap)) {
  1713. client->errorValue = format;
  1714. return BadValue;
  1715. }
  1716. rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
  1717. if (rc != Success)
  1718. return rc;
  1719. memset(&xgi, 0, sizeof(xGetImageReply));
  1720. relx = x;
  1721. rely = y;
  1722. if (pDraw->type == DRAWABLE_WINDOW) {
  1723. WindowPtr pWin = (WindowPtr) pDraw;
  1724. /* "If the drawable is a window, the window must be viewable ... or a
  1725. * BadMatch error results" */
  1726. if (!pWin->viewable)
  1727. return BadMatch;
  1728. /* If the drawable is a window, the rectangle must be contained within
  1729. * its bounds (including the border). */
  1730. if (x < -wBorderWidth(pWin) ||
  1731. x + width > wBorderWidth(pWin) + (int) pDraw->width ||
  1732. y < -wBorderWidth(pWin) ||
  1733. y + height > wBorderWidth(pWin) + (int) pDraw->height)
  1734. return BadMatch;
  1735. relx += pDraw->x;
  1736. rely += pDraw->y;
  1737. if (pDraw->pScreen->GetWindowPixmap) {
  1738. PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
  1739. pBoundingDraw = &pPix->drawable;
  1740. #ifdef COMPOSITE
  1741. relx -= pPix->screen_x;
  1742. rely -= pPix->screen_y;
  1743. #endif
  1744. }
  1745. else {
  1746. pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
  1747. }
  1748. xgi.visual = wVisual(pWin);
  1749. }
  1750. else {
  1751. pBoundingDraw = pDraw;
  1752. xgi.visual = None;
  1753. }
  1754. /* "If the drawable is a pixmap, the given rectangle must be wholly
  1755. * contained within the pixmap, or a BadMatch error results. If the
  1756. * drawable is a window [...] it must be the case that if there were no
  1757. * inferiors or overlapping windows, the specified rectangle of the window
  1758. * would be fully visible on the screen and wholly contained within the
  1759. * outside edges of the window, or a BadMatch error results."
  1760. *
  1761. * We relax the window case slightly to mean that the rectangle must exist
  1762. * within the bounds of the window's backing pixmap. In particular, this
  1763. * means that a GetImage request may succeed or fail with BadMatch depending
  1764. * on whether any of its ancestor windows are redirected. */
  1765. if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
  1766. rely < 0 || rely + height > (int) pBoundingDraw->height)
  1767. return BadMatch;
  1768. xgi.type = X_Reply;
  1769. xgi.sequenceNumber = client->sequence;
  1770. xgi.depth = pDraw->depth;
  1771. if (format == ZPixmap) {
  1772. widthBytesLine = PixmapBytePad(width, pDraw->depth);
  1773. length = widthBytesLine * height;
  1774. }
  1775. else {
  1776. widthBytesLine = BitmapBytePad(width);
  1777. plane = ((Mask) 1) << (pDraw->depth - 1);
  1778. /* only planes asked for */
  1779. length = widthBytesLine * height *
  1780. Ones(planemask & (plane | (plane - 1)));
  1781. }
  1782. xgi.length = length;
  1783. xgi.length = bytes_to_int32(xgi.length);
  1784. if (widthBytesLine == 0 || height == 0)
  1785. linesPerBuf = 0;
  1786. else if (widthBytesLine >= IMAGE_BUFSIZE)
  1787. linesPerBuf = 1;
  1788. else {
  1789. linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
  1790. if (linesPerBuf > height)
  1791. linesPerBuf = height;
  1792. }
  1793. length = linesPerBuf * widthBytesLine;
  1794. if (linesPerBuf < height) {
  1795. /* we have to make sure intermediate buffers don't need padding */
  1796. while ((linesPerBuf > 1) &&
  1797. (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
  1798. linesPerBuf--;
  1799. length -= widthBytesLine;
  1800. }
  1801. while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
  1802. linesPerBuf++;
  1803. length += widthBytesLine;
  1804. }
  1805. }
  1806. if (!(pBuf = calloc(1, length)))
  1807. return BadAlloc;
  1808. WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
  1809. if (pDraw->type == DRAWABLE_WINDOW) {
  1810. pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw);
  1811. if (pVisibleRegion) {
  1812. RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
  1813. }
  1814. }
  1815. if (linesPerBuf == 0) {
  1816. /* nothing to do */
  1817. }
  1818. else if (format == ZPixmap) {
  1819. linesDone = 0;
  1820. while (height - linesDone > 0) {
  1821. nlines = min(linesPerBuf, height - linesDone);
  1822. (*pDraw->pScreen->GetImage) (pDraw,
  1823. x,
  1824. y + linesDone,
  1825. width,
  1826. nlines,
  1827. format, planemask, (void *) pBuf);
  1828. if (pVisibleRegion)
  1829. XaceCensorImage(client, pVisibleRegion, widthBytesLine,
  1830. pDraw, x, y + linesDone, width,
  1831. nlines, format, pBuf);
  1832. /* Note that this is NOT a call to WriteSwappedDataToClient,
  1833. as we do NOT byte swap */
  1834. ReformatImage(pBuf, (int) (nlines * widthBytesLine),
  1835. BitsPerPixel(pDraw->depth), ClientOrder(client));
  1836. WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
  1837. linesDone += nlines;
  1838. }
  1839. }
  1840. else { /* XYPixmap */
  1841. for (; plane; plane >>= 1) {
  1842. if (planemask & plane) {
  1843. linesDone = 0;
  1844. while (height - linesDone > 0) {
  1845. nlines = min(linesPerBuf, height - linesDone);
  1846. (*pDraw->pScreen->GetImage) (pDraw,
  1847. x,
  1848. y + linesDone,
  1849. width,
  1850. nlines,
  1851. format, plane, (void *) pBuf);
  1852. if (pVisibleRegion)
  1853. XaceCensorImage(client, pVisibleRegion,
  1854. widthBytesLine,
  1855. pDraw, x, y + linesDone, width,
  1856. nlines, format, pBuf);
  1857. /* Note: NOT a call to WriteSwappedDataToClient,
  1858. as we do NOT byte swap */
  1859. ReformatImage(pBuf, (int) (nlines * widthBytesLine),
  1860. 1, ClientOrder(client));
  1861. WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
  1862. linesDone += nlines;
  1863. }
  1864. }
  1865. }
  1866. }
  1867. if (pVisibleRegion)
  1868. RegionDestroy(pVisibleRegion);
  1869. free(pBuf);
  1870. return Success;
  1871. }
  1872. int
  1873. ProcGetImage(ClientPtr client)
  1874. {
  1875. REQUEST(xGetImageReq);
  1876. REQUEST_SIZE_MATCH(xGetImageReq);
  1877. return DoGetImage(client, stuff->format, stuff->drawable,
  1878. stuff->x, stuff->y,
  1879. (int) stuff->width, (int) stuff->height,
  1880. stuff->planeMask);
  1881. }
  1882. int
  1883. ProcPolyText(ClientPtr client)
  1884. {
  1885. int err;
  1886. REQUEST(xPolyTextReq);
  1887. DrawablePtr pDraw;
  1888. GC *pGC;
  1889. REQUEST_AT_LEAST_SIZE(xPolyTextReq);
  1890. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1891. err = PolyText(client,
  1892. pDraw,
  1893. pGC,
  1894. (unsigned char *) &stuff[1],
  1895. ((unsigned char *) stuff) + (client->req_len << 2),
  1896. stuff->x, stuff->y, stuff->reqType, stuff->drawable);
  1897. if (err == Success) {
  1898. return Success;
  1899. }
  1900. else
  1901. return err;
  1902. }
  1903. int
  1904. ProcImageText8(ClientPtr client)
  1905. {
  1906. int err;
  1907. DrawablePtr pDraw;
  1908. GC *pGC;
  1909. REQUEST(xImageTextReq);
  1910. REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
  1911. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1912. err = ImageText(client,
  1913. pDraw,
  1914. pGC,
  1915. stuff->nChars,
  1916. (unsigned char *) &stuff[1],
  1917. stuff->x, stuff->y, stuff->reqType, stuff->drawable);
  1918. if (err == Success) {
  1919. return Success;
  1920. }
  1921. else
  1922. return err;
  1923. }
  1924. int
  1925. ProcImageText16(ClientPtr client)
  1926. {
  1927. int err;
  1928. DrawablePtr pDraw;
  1929. GC *pGC;
  1930. REQUEST(xImageTextReq);
  1931. REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
  1932. VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
  1933. err = ImageText(client,
  1934. pDraw,
  1935. pGC,
  1936. stuff->nChars,
  1937. (unsigned char *) &stuff[1],
  1938. stuff->x, stuff->y, stuff->reqType, stuff->drawable);
  1939. if (err == Success) {
  1940. return Success;
  1941. }
  1942. else
  1943. return err;
  1944. }
  1945. int
  1946. ProcCreateColormap(ClientPtr client)
  1947. {
  1948. VisualPtr pVisual;
  1949. ColormapPtr pmap;
  1950. Colormap mid;
  1951. WindowPtr pWin;
  1952. ScreenPtr pScreen;
  1953. REQUEST(xCreateColormapReq);
  1954. int i, result;
  1955. REQUEST_SIZE_MATCH(xCreateColormapReq);
  1956. if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
  1957. client->errorValue = stuff->alloc;
  1958. return BadValue;
  1959. }
  1960. mid = stuff->mid;
  1961. LEGAL_NEW_RESOURCE(mid, client);
  1962. result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
  1963. if (result != Success)
  1964. return result;
  1965. pScreen = pWin->drawable.pScreen;
  1966. for (i = 0, pVisual = pScreen->visuals;
  1967. i < pScreen->numVisuals; i++, pVisual++) {
  1968. if (pVisual->vid != stuff->visual)
  1969. continue;
  1970. return CreateColormap(mid, pScreen, pVisual, &pmap,
  1971. (int) stuff->alloc, client->index);
  1972. }
  1973. client->errorValue = stuff->visual;
  1974. return BadMatch;
  1975. }
  1976. int
  1977. ProcFreeColormap(ClientPtr client)
  1978. {
  1979. ColormapPtr pmap;
  1980. int rc;
  1981. REQUEST(xResourceReq);
  1982. REQUEST_SIZE_MATCH(xResourceReq);
  1983. rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
  1984. client, DixDestroyAccess);
  1985. if (rc == Success) {
  1986. /* Freeing a default colormap is a no-op */
  1987. if (!(pmap->flags & IsDefault))
  1988. FreeResource(stuff->id, RT_NONE);
  1989. return Success;
  1990. }
  1991. else {
  1992. client->errorValue = stuff->id;
  1993. return rc;
  1994. }
  1995. }
  1996. int
  1997. ProcCopyColormapAndFree(ClientPtr client)
  1998. {
  1999. Colormap mid;
  2000. ColormapPtr pSrcMap;
  2001. REQUEST(xCopyColormapAndFreeReq);
  2002. int rc;
  2003. REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
  2004. mid = stuff->mid;
  2005. LEGAL_NEW_RESOURCE(mid, client);
  2006. rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
  2007. RT_COLORMAP, client,
  2008. DixReadAccess | DixRemoveAccess);
  2009. if (rc == Success)
  2010. return CopyColormapAndFree(mid, pSrcMap, client->index);
  2011. client->errorValue = stuff->srcCmap;
  2012. return rc;
  2013. }
  2014. int
  2015. ProcInstallColormap(ClientPtr client)
  2016. {
  2017. ColormapPtr pcmp;
  2018. int rc;
  2019. REQUEST(xResourceReq);
  2020. REQUEST_SIZE_MATCH(xResourceReq);
  2021. rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
  2022. client, DixInstallAccess);
  2023. if (rc != Success)
  2024. goto out;
  2025. rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
  2026. if (rc != Success) {
  2027. if (rc == BadValue)
  2028. rc = BadColor;
  2029. goto out;
  2030. }
  2031. (*(pcmp->pScreen->InstallColormap)) (pcmp);
  2032. return Success;
  2033. out:
  2034. client->errorValue = stuff->id;
  2035. return rc;
  2036. }
  2037. int
  2038. ProcUninstallColormap(ClientPtr client)
  2039. {
  2040. ColormapPtr pcmp;
  2041. int rc;
  2042. REQUEST(xResourceReq);
  2043. REQUEST_SIZE_MATCH(xResourceReq);
  2044. rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
  2045. client, DixUninstallAccess);
  2046. if (rc != Success)
  2047. goto out;
  2048. rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
  2049. if (rc != Success) {
  2050. if (rc == BadValue)
  2051. rc = BadColor;
  2052. goto out;
  2053. }
  2054. if (pcmp->mid != pcmp->pScreen->defColormap)
  2055. (*(pcmp->pScreen->UninstallColormap)) (pcmp);
  2056. return Success;
  2057. out:
  2058. client->errorValue = stuff->id;
  2059. return rc;
  2060. }
  2061. int
  2062. ProcListInstalledColormaps(ClientPtr client)
  2063. {
  2064. xListInstalledColormapsReply *preply;
  2065. int nummaps, rc;
  2066. WindowPtr pWin;
  2067. REQUEST(xResourceReq);
  2068. REQUEST_SIZE_MATCH(xResourceReq);
  2069. rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
  2070. if (rc != Success)
  2071. return rc;
  2072. rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
  2073. DixGetAttrAccess);
  2074. if (rc != Success)
  2075. return rc;
  2076. preply = malloc(sizeof(xListInstalledColormapsReply) +
  2077. pWin->drawable.pScreen->maxInstalledCmaps *
  2078. sizeof(Colormap));
  2079. if (!preply)
  2080. return BadAlloc;
  2081. preply->type = X_Reply;
  2082. preply->sequenceNumber = client->sequence;
  2083. nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
  2084. (pWin->drawable.pScreen, (Colormap *) &preply[1]);
  2085. preply->nColormaps = nummaps;
  2086. preply->length = nummaps;
  2087. WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
  2088. client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
  2089. WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
  2090. free(preply);
  2091. return Success;
  2092. }
  2093. int
  2094. ProcAllocColor(ClientPtr client)
  2095. {
  2096. ColormapPtr pmap;
  2097. int rc;
  2098. REQUEST(xAllocColorReq);
  2099. REQUEST_SIZE_MATCH(xAllocColorReq);
  2100. rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
  2101. client, DixAddAccess);
  2102. if (rc == Success) {
  2103. xAllocColorReply acr = {
  2104. .type = X_Reply,
  2105. .sequenceNumber = client->sequence,
  2106. .length = 0,
  2107. .red = stuff->red,
  2108. .green = stuff->green,
  2109. .blue = stuff->blue,
  2110. .pixel = 0
  2111. };
  2112. if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
  2113. &acr.pixel, client->index)))
  2114. return rc;
  2115. #ifdef PANORAMIX
  2116. if (noPanoramiXExtension || !pmap->pScreen->myNum)
  2117. #endif
  2118. WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
  2119. return Success;
  2120. }
  2121. else {
  2122. client->errorValue = stuff->cmap;
  2123. return rc;
  2124. }
  2125. }
  2126. int
  2127. ProcAllocNamedColor(ClientPtr client)
  2128. {
  2129. ColormapPtr pcmp;
  2130. int rc;
  2131. REQUEST(xAllocNamedColorReq);
  2132. REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
  2133. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2134. client, DixAddAccess);
  2135. if (rc == Success) {
  2136. xAllocNamedColorReply ancr = {
  2137. .type = X_Reply,
  2138. .sequenceNumber = client->sequence,
  2139. .length = 0
  2140. };
  2141. if (OsLookupColor
  2142. (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
  2143. &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
  2144. ancr.screenRed = ancr.exactRed;
  2145. ancr.screenGreen = ancr.exactGreen;
  2146. ancr.screenBlue = ancr.exactBlue;
  2147. ancr.pixel = 0;
  2148. if ((rc = AllocColor(pcmp,
  2149. &ancr.screenRed, &ancr.screenGreen,
  2150. &ancr.screenBlue, &ancr.pixel, client->index)))
  2151. return rc;
  2152. #ifdef PANORAMIX
  2153. if (noPanoramiXExtension || !pcmp->pScreen->myNum)
  2154. #endif
  2155. WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
  2156. &ancr);
  2157. return Success;
  2158. }
  2159. else
  2160. return BadName;
  2161. }
  2162. else {
  2163. client->errorValue = stuff->cmap;
  2164. return rc;
  2165. }
  2166. }
  2167. int
  2168. ProcAllocColorCells(ClientPtr client)
  2169. {
  2170. ColormapPtr pcmp;
  2171. int rc;
  2172. REQUEST(xAllocColorCellsReq);
  2173. REQUEST_SIZE_MATCH(xAllocColorCellsReq);
  2174. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2175. client, DixAddAccess);
  2176. if (rc == Success) {
  2177. int npixels, nmasks;
  2178. long length;
  2179. Pixel *ppixels, *pmasks;
  2180. npixels = stuff->colors;
  2181. if (!npixels) {
  2182. client->errorValue = npixels;
  2183. return BadValue;
  2184. }
  2185. if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
  2186. client->errorValue = stuff->contiguous;
  2187. return BadValue;
  2188. }
  2189. nmasks = stuff->planes;
  2190. length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
  2191. ppixels = malloc(length);
  2192. if (!ppixels)
  2193. return BadAlloc;
  2194. pmasks = ppixels + npixels;
  2195. if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
  2196. (Bool) stuff->contiguous, ppixels, pmasks))) {
  2197. free(ppixels);
  2198. return rc;
  2199. }
  2200. #ifdef PANORAMIX
  2201. if (noPanoramiXExtension || !pcmp->pScreen->myNum)
  2202. #endif
  2203. {
  2204. xAllocColorCellsReply accr = {
  2205. .type = X_Reply,
  2206. .sequenceNumber = client->sequence,
  2207. .length = bytes_to_int32(length),
  2208. .nPixels = npixels,
  2209. .nMasks = nmasks
  2210. };
  2211. WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
  2212. client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
  2213. WriteSwappedDataToClient(client, length, ppixels);
  2214. }
  2215. free(ppixels);
  2216. return Success;
  2217. }
  2218. else {
  2219. client->errorValue = stuff->cmap;
  2220. return rc;
  2221. }
  2222. }
  2223. int
  2224. ProcAllocColorPlanes(ClientPtr client)
  2225. {
  2226. ColormapPtr pcmp;
  2227. int rc;
  2228. REQUEST(xAllocColorPlanesReq);
  2229. REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
  2230. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2231. client, DixAddAccess);
  2232. if (rc == Success) {
  2233. xAllocColorPlanesReply acpr;
  2234. int npixels;
  2235. long length;
  2236. Pixel *ppixels;
  2237. npixels = stuff->colors;
  2238. if (!npixels) {
  2239. client->errorValue = npixels;
  2240. return BadValue;
  2241. }
  2242. if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
  2243. client->errorValue = stuff->contiguous;
  2244. return BadValue;
  2245. }
  2246. acpr = (xAllocColorPlanesReply) {
  2247. .type = X_Reply,
  2248. .sequenceNumber = client->sequence,
  2249. .nPixels = npixels
  2250. };
  2251. length = (long) npixels *sizeof(Pixel);
  2252. ppixels = malloc(length);
  2253. if (!ppixels)
  2254. return BadAlloc;
  2255. if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
  2256. (int) stuff->red, (int) stuff->green,
  2257. (int) stuff->blue, (Bool) stuff->contiguous,
  2258. ppixels, &acpr.redMask, &acpr.greenMask,
  2259. &acpr.blueMask))) {
  2260. free(ppixels);
  2261. return rc;
  2262. }
  2263. acpr.length = bytes_to_int32(length);
  2264. #ifdef PANORAMIX
  2265. if (noPanoramiXExtension || !pcmp->pScreen->myNum)
  2266. #endif
  2267. {
  2268. WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
  2269. client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
  2270. WriteSwappedDataToClient(client, length, ppixels);
  2271. }
  2272. free(ppixels);
  2273. return Success;
  2274. }
  2275. else {
  2276. client->errorValue = stuff->cmap;
  2277. return rc;
  2278. }
  2279. }
  2280. int
  2281. ProcFreeColors(ClientPtr client)
  2282. {
  2283. ColormapPtr pcmp;
  2284. int rc;
  2285. REQUEST(xFreeColorsReq);
  2286. REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
  2287. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2288. client, DixRemoveAccess);
  2289. if (rc == Success) {
  2290. int count;
  2291. if (pcmp->flags & AllAllocated)
  2292. return BadAccess;
  2293. count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
  2294. return FreeColors(pcmp, client->index, count,
  2295. (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
  2296. }
  2297. else {
  2298. client->errorValue = stuff->cmap;
  2299. return rc;
  2300. }
  2301. }
  2302. int
  2303. ProcStoreColors(ClientPtr client)
  2304. {
  2305. ColormapPtr pcmp;
  2306. int rc;
  2307. REQUEST(xStoreColorsReq);
  2308. REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
  2309. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2310. client, DixWriteAccess);
  2311. if (rc == Success) {
  2312. int count;
  2313. count = (client->req_len << 2) - sizeof(xStoreColorsReq);
  2314. if (count % sizeof(xColorItem))
  2315. return BadLength;
  2316. count /= sizeof(xColorItem);
  2317. return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
  2318. }
  2319. else {
  2320. client->errorValue = stuff->cmap;
  2321. return rc;
  2322. }
  2323. }
  2324. int
  2325. ProcStoreNamedColor(ClientPtr client)
  2326. {
  2327. ColormapPtr pcmp;
  2328. int rc;
  2329. REQUEST(xStoreNamedColorReq);
  2330. REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
  2331. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2332. client, DixWriteAccess);
  2333. if (rc == Success) {
  2334. xColorItem def;
  2335. if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
  2336. stuff->nbytes, &def.red, &def.green, &def.blue)) {
  2337. def.flags = stuff->flags;
  2338. def.pixel = stuff->pixel;
  2339. return StoreColors(pcmp, 1, &def, client);
  2340. }
  2341. return BadName;
  2342. }
  2343. else {
  2344. client->errorValue = stuff->cmap;
  2345. return rc;
  2346. }
  2347. }
  2348. int
  2349. ProcQueryColors(ClientPtr client)
  2350. {
  2351. ColormapPtr pcmp;
  2352. int rc;
  2353. REQUEST(xQueryColorsReq);
  2354. REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
  2355. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2356. client, DixReadAccess);
  2357. if (rc == Success) {
  2358. int count;
  2359. xrgb *prgbs;
  2360. xQueryColorsReply qcr;
  2361. count =
  2362. bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
  2363. prgbs = calloc(1, count * sizeof(xrgb));
  2364. if (!prgbs && count)
  2365. return BadAlloc;
  2366. if ((rc =
  2367. QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
  2368. free(prgbs);
  2369. return rc;
  2370. }
  2371. qcr = (xQueryColorsReply) {
  2372. .type = X_Reply,
  2373. .sequenceNumber = client->sequence,
  2374. .length = bytes_to_int32(count * sizeof(xrgb)),
  2375. .nColors = count
  2376. };
  2377. WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
  2378. if (count) {
  2379. client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
  2380. WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
  2381. }
  2382. free(prgbs);
  2383. return Success;
  2384. }
  2385. else {
  2386. client->errorValue = stuff->cmap;
  2387. return rc;
  2388. }
  2389. }
  2390. int
  2391. ProcLookupColor(ClientPtr client)
  2392. {
  2393. ColormapPtr pcmp;
  2394. int rc;
  2395. REQUEST(xLookupColorReq);
  2396. REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
  2397. rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
  2398. client, DixReadAccess);
  2399. if (rc == Success) {
  2400. CARD16 exactRed, exactGreen, exactBlue;
  2401. if (OsLookupColor
  2402. (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
  2403. &exactRed, &exactGreen, &exactBlue)) {
  2404. xLookupColorReply lcr = {
  2405. .type = X_Reply,
  2406. .sequenceNumber = client->sequence,
  2407. .length = 0,
  2408. .exactRed = exactRed,
  2409. .exactGreen = exactGreen,
  2410. .exactBlue = exactBlue,
  2411. .screenRed = exactRed,
  2412. .screenGreen = exactGreen,
  2413. .screenBlue = exactBlue
  2414. };
  2415. (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
  2416. &lcr.screenGreen,
  2417. &lcr.screenBlue, pcmp->pVisual);
  2418. WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
  2419. return Success;
  2420. }
  2421. return BadName;
  2422. }
  2423. else {
  2424. client->errorValue = stuff->cmap;
  2425. return rc;
  2426. }
  2427. }
  2428. int
  2429. ProcCreateCursor(ClientPtr client)
  2430. {
  2431. CursorPtr pCursor;
  2432. PixmapPtr src;
  2433. PixmapPtr msk;
  2434. unsigned char *srcbits;
  2435. unsigned char *mskbits;
  2436. unsigned short width, height;
  2437. long n;
  2438. CursorMetricRec cm;
  2439. int rc;
  2440. REQUEST(xCreateCursorReq);
  2441. REQUEST_SIZE_MATCH(xCreateCursorReq);
  2442. LEGAL_NEW_RESOURCE(stuff->cid, client);
  2443. rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
  2444. client, DixReadAccess);
  2445. if (rc != Success) {
  2446. client->errorValue = stuff->source;
  2447. return rc;
  2448. }
  2449. if (src->drawable.depth != 1)
  2450. return (BadMatch);
  2451. /* Find and validate cursor mask pixmap, if one is provided */
  2452. if (stuff->mask != None) {
  2453. rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
  2454. client, DixReadAccess);
  2455. if (rc != Success) {
  2456. client->errorValue = stuff->mask;
  2457. return rc;
  2458. }
  2459. if (src->drawable.width != msk->drawable.width
  2460. || src->drawable.height != msk->drawable.height
  2461. || src->drawable.depth != 1 || msk->drawable.depth != 1)
  2462. return BadMatch;
  2463. }
  2464. else
  2465. msk = NULL;
  2466. width = src->drawable.width;
  2467. height = src->drawable.height;
  2468. if (stuff->x > width || stuff->y > height)
  2469. return BadMatch;
  2470. n = BitmapBytePad(width) * height;
  2471. srcbits = calloc(1, n);
  2472. if (!srcbits)
  2473. return BadAlloc;
  2474. mskbits = malloc(n);
  2475. if (!mskbits) {
  2476. free(srcbits);
  2477. return BadAlloc;
  2478. }
  2479. (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
  2480. XYPixmap, 1, (void *) srcbits);
  2481. if (msk == (PixmapPtr) NULL) {
  2482. unsigned char *bits = mskbits;
  2483. while (--n >= 0)
  2484. *bits++ = ~0;
  2485. }
  2486. else {
  2487. /* zeroing the (pad) bits helps some ddx cursor handling */
  2488. memset((char *) mskbits, 0, n);
  2489. (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
  2490. height, XYPixmap, 1,
  2491. (void *) mskbits);
  2492. }
  2493. cm.width = width;
  2494. cm.height = height;
  2495. cm.xhot = stuff->x;
  2496. cm.yhot = stuff->y;
  2497. rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
  2498. stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
  2499. stuff->backRed, stuff->backGreen, stuff->backBlue,
  2500. &pCursor, client, stuff->cid);
  2501. if (rc != Success)
  2502. goto bail;
  2503. if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
  2504. rc = BadAlloc;
  2505. goto bail;
  2506. }
  2507. return Success;
  2508. bail:
  2509. free(srcbits);
  2510. free(mskbits);
  2511. return rc;
  2512. }
  2513. int
  2514. ProcCreateGlyphCursor(ClientPtr client)
  2515. {
  2516. CursorPtr pCursor;
  2517. int res;
  2518. REQUEST(xCreateGlyphCursorReq);
  2519. REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
  2520. LEGAL_NEW_RESOURCE(stuff->cid, client);
  2521. res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
  2522. stuff->mask, stuff->maskChar,
  2523. stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
  2524. stuff->backRed, stuff->backGreen, stuff->backBlue,
  2525. &pCursor, client, stuff->cid);
  2526. if (res != Success)
  2527. return res;
  2528. if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
  2529. return Success;
  2530. return BadAlloc;
  2531. }
  2532. int
  2533. ProcFreeCursor(ClientPtr client)
  2534. {
  2535. CursorPtr pCursor;
  2536. int rc;
  2537. REQUEST(xResourceReq);
  2538. REQUEST_SIZE_MATCH(xResourceReq);
  2539. rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
  2540. client, DixDestroyAccess);
  2541. if (rc == Success) {
  2542. FreeResource(stuff->id, RT_NONE);
  2543. return Success;
  2544. }
  2545. else {
  2546. client->errorValue = stuff->id;
  2547. return rc;
  2548. }
  2549. }
  2550. int
  2551. ProcQueryBestSize(ClientPtr client)
  2552. {
  2553. xQueryBestSizeReply reply;
  2554. DrawablePtr pDraw;
  2555. ScreenPtr pScreen;
  2556. int rc;
  2557. REQUEST(xQueryBestSizeReq);
  2558. REQUEST_SIZE_MATCH(xQueryBestSizeReq);
  2559. if ((stuff->class != CursorShape) &&
  2560. (stuff->class != TileShape) && (stuff->class != StippleShape)) {
  2561. client->errorValue = stuff->class;
  2562. return BadValue;
  2563. }
  2564. rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
  2565. DixGetAttrAccess);
  2566. if (rc != Success)
  2567. return rc;
  2568. if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
  2569. return BadMatch;
  2570. pScreen = pDraw->pScreen;
  2571. rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
  2572. if (rc != Success)
  2573. return rc;
  2574. (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
  2575. &stuff->height, pScreen);
  2576. reply = (xQueryBestSizeReply) {
  2577. .type = X_Reply,
  2578. .sequenceNumber = client->sequence,
  2579. .length = 0,
  2580. .width = stuff->width,
  2581. .height = stuff->height
  2582. };
  2583. WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
  2584. return Success;
  2585. }
  2586. int
  2587. ProcSetScreenSaver(ClientPtr client)
  2588. {
  2589. int rc, i, blankingOption, exposureOption;
  2590. REQUEST(xSetScreenSaverReq);
  2591. REQUEST_SIZE_MATCH(xSetScreenSaverReq);
  2592. for (i = 0; i < screenInfo.numScreens; i++) {
  2593. rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
  2594. DixSetAttrAccess);
  2595. if (rc != Success)
  2596. return rc;
  2597. }
  2598. blankingOption = stuff->preferBlank;
  2599. if ((blankingOption != DontPreferBlanking) &&
  2600. (blankingOption != PreferBlanking) &&
  2601. (blankingOption != DefaultBlanking)) {
  2602. client->errorValue = blankingOption;
  2603. return BadValue;
  2604. }
  2605. exposureOption = stuff->allowExpose;
  2606. if ((exposureOption != DontAllowExposures) &&
  2607. (exposureOption != AllowExposures) &&
  2608. (exposureOption != DefaultExposures)) {
  2609. client->errorValue = exposureOption;
  2610. return BadValue;
  2611. }
  2612. if (stuff->timeout < -1) {
  2613. client->errorValue = stuff->timeout;
  2614. return BadValue;
  2615. }
  2616. if (stuff->interval < -1) {
  2617. client->errorValue = stuff->interval;
  2618. return BadValue;
  2619. }
  2620. if (blankingOption == DefaultBlanking)
  2621. ScreenSaverBlanking = defaultScreenSaverBlanking;
  2622. else
  2623. ScreenSaverBlanking = blankingOption;
  2624. if (exposureOption == DefaultExposures)
  2625. ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
  2626. else
  2627. ScreenSaverAllowExposures = exposureOption;
  2628. if (stuff->timeout >= 0)
  2629. ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
  2630. else
  2631. ScreenSaverTime = defaultScreenSaverTime;
  2632. if (stuff->interval >= 0)
  2633. ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
  2634. else
  2635. ScreenSaverInterval = defaultScreenSaverInterval;
  2636. SetScreenSaverTimer();
  2637. return Success;
  2638. }
  2639. int
  2640. ProcGetScreenSaver(ClientPtr client)
  2641. {
  2642. xGetScreenSaverReply rep;
  2643. int rc, i;
  2644. REQUEST_SIZE_MATCH(xReq);
  2645. for (i = 0; i < screenInfo.numScreens; i++) {
  2646. rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
  2647. DixGetAttrAccess);
  2648. if (rc != Success)
  2649. return rc;
  2650. }
  2651. rep = (xGetScreenSaverReply) {
  2652. .type = X_Reply,
  2653. .sequenceNumber = client->sequence,
  2654. .length = 0,
  2655. .timeout = ScreenSaverTime / MILLI_PER_SECOND,
  2656. .interval = ScreenSaverInterval / MILLI_PER_SECOND,
  2657. .preferBlanking = ScreenSaverBlanking,
  2658. .allowExposures = ScreenSaverAllowExposures
  2659. };
  2660. WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
  2661. return Success;
  2662. }
  2663. int
  2664. ProcChangeHosts(ClientPtr client)
  2665. {
  2666. REQUEST(xChangeHostsReq);
  2667. REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
  2668. if (stuff->mode == HostInsert)
  2669. return AddHost(client, (int) stuff->hostFamily,
  2670. stuff->hostLength, (void *) &stuff[1]);
  2671. if (stuff->mode == HostDelete)
  2672. return RemoveHost(client, (int) stuff->hostFamily,
  2673. stuff->hostLength, (void *) &stuff[1]);
  2674. client->errorValue = stuff->mode;
  2675. return BadValue;
  2676. }
  2677. int
  2678. ProcListHosts(ClientPtr client)
  2679. {
  2680. xListHostsReply reply;
  2681. int len, nHosts, result;
  2682. BOOL enabled;
  2683. void *pdata;
  2684. /* REQUEST(xListHostsReq); */
  2685. REQUEST_SIZE_MATCH(xListHostsReq);
  2686. /* untrusted clients can't list hosts */
  2687. result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
  2688. if (result != Success)
  2689. return result;
  2690. result = GetHosts(&pdata, &nHosts, &len, &enabled);
  2691. if (result != Success)
  2692. return result;
  2693. reply = (xListHostsReply) {
  2694. .type = X_Reply,
  2695. .enabled = enabled,
  2696. .sequenceNumber = client->sequence,
  2697. .length = bytes_to_int32(len),
  2698. .nHosts = nHosts
  2699. };
  2700. WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
  2701. if (nHosts) {
  2702. client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
  2703. WriteSwappedDataToClient(client, len, pdata);
  2704. }
  2705. free(pdata);
  2706. return Success;
  2707. }
  2708. int
  2709. ProcChangeAccessControl(ClientPtr client)
  2710. {
  2711. REQUEST(xSetAccessControlReq);
  2712. REQUEST_SIZE_MATCH(xSetAccessControlReq);
  2713. if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
  2714. client->errorValue = stuff->mode;
  2715. return BadValue;
  2716. }
  2717. return ChangeAccessControl(client, stuff->mode == EnableAccess);
  2718. }
  2719. /*********************
  2720. * CloseDownRetainedResources
  2721. *
  2722. * Find all clients that are gone and have terminated in RetainTemporary
  2723. * and destroy their resources.
  2724. *********************/
  2725. static void
  2726. CloseDownRetainedResources(void)
  2727. {
  2728. int i;
  2729. ClientPtr client;
  2730. for (i = 1; i < currentMaxClients; i++) {
  2731. client = clients[i];
  2732. if (client && (client->closeDownMode == RetainTemporary)
  2733. && (client->clientGone))
  2734. CloseDownClient(client);
  2735. }
  2736. }
  2737. int
  2738. ProcKillClient(ClientPtr client)
  2739. {
  2740. REQUEST(xResourceReq);
  2741. ClientPtr killclient;
  2742. int rc;
  2743. REQUEST_SIZE_MATCH(xResourceReq);
  2744. if (stuff->id == AllTemporary) {
  2745. CloseDownRetainedResources();
  2746. return Success;
  2747. }
  2748. rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
  2749. if (rc == Success) {
  2750. CloseDownClient(killclient);
  2751. /* if an LBX proxy gets killed, isItTimeToYield will be set */
  2752. if (isItTimeToYield || (client == killclient)) {
  2753. /* force yield and return Success, so that Dispatch()
  2754. * doesn't try to touch client
  2755. */
  2756. isItTimeToYield = TRUE;
  2757. return Success;
  2758. }
  2759. return Success;
  2760. }
  2761. else
  2762. return rc;
  2763. }
  2764. int
  2765. ProcSetFontPath(ClientPtr client)
  2766. {
  2767. unsigned char *ptr;
  2768. unsigned long nbytes, total;
  2769. long nfonts;
  2770. int n;
  2771. REQUEST(xSetFontPathReq);
  2772. REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
  2773. nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
  2774. total = nbytes;
  2775. ptr = (unsigned char *) &stuff[1];
  2776. nfonts = stuff->nFonts;
  2777. while (--nfonts >= 0) {
  2778. if ((total == 0) || (total < (n = (*ptr + 1))))
  2779. return BadLength;
  2780. total -= n;
  2781. ptr += n;
  2782. }
  2783. if (total >= 4)
  2784. return BadLength;
  2785. return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
  2786. }
  2787. int
  2788. ProcGetFontPath(ClientPtr client)
  2789. {
  2790. xGetFontPathReply reply;
  2791. int rc, stringLens, numpaths;
  2792. unsigned char *bufferStart;
  2793. /* REQUEST (xReq); */
  2794. REQUEST_SIZE_MATCH(xReq);
  2795. rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
  2796. if (rc != Success)
  2797. return rc;
  2798. reply = (xGetFontPathReply) {
  2799. .type = X_Reply,
  2800. .sequenceNumber = client->sequence,
  2801. .length = bytes_to_int32(stringLens + numpaths),
  2802. .nPaths = numpaths
  2803. };
  2804. WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
  2805. if (stringLens || numpaths)
  2806. WriteToClient(client, stringLens + numpaths, bufferStart);
  2807. return Success;
  2808. }
  2809. int
  2810. ProcChangeCloseDownMode(ClientPtr client)
  2811. {
  2812. int rc;
  2813. REQUEST(xSetCloseDownModeReq);
  2814. REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
  2815. rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
  2816. if (rc != Success)
  2817. return rc;
  2818. if ((stuff->mode == AllTemporary) ||
  2819. (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
  2820. client->closeDownMode = stuff->mode;
  2821. return Success;
  2822. }
  2823. else {
  2824. client->errorValue = stuff->mode;
  2825. return BadValue;
  2826. }
  2827. }
  2828. int
  2829. ProcForceScreenSaver(ClientPtr client)
  2830. {
  2831. int rc;
  2832. REQUEST(xForceScreenSaverReq);
  2833. REQUEST_SIZE_MATCH(xForceScreenSaverReq);
  2834. if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
  2835. client->errorValue = stuff->mode;
  2836. return BadValue;
  2837. }
  2838. rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
  2839. if (rc != Success)
  2840. return rc;
  2841. return Success;
  2842. }
  2843. int
  2844. ProcNoOperation(ClientPtr client)
  2845. {
  2846. REQUEST_AT_LEAST_SIZE(xReq);
  2847. /* noop -- don't do anything */
  2848. return Success;
  2849. }
  2850. /**********************
  2851. * CloseDownClient
  2852. *
  2853. * Client can either mark his resources destroy or retain. If retained and
  2854. * then killed again, the client is really destroyed.
  2855. *********************/
  2856. char dispatchExceptionAtReset = DE_RESET;
  2857. void
  2858. CloseDownClient(ClientPtr client)
  2859. {
  2860. Bool really_close_down = client->clientGone ||
  2861. client->closeDownMode == DestroyAll;
  2862. if (!client->clientGone) {
  2863. /* ungrab server if grabbing client dies */
  2864. if (grabState != GrabNone && grabClient == client) {
  2865. UngrabServer(client);
  2866. }
  2867. BITCLEAR(grabWaiters, client->index);
  2868. DeleteClientFromAnySelections(client);
  2869. ReleaseActiveGrabs(client);
  2870. DeleteClientFontStuff(client);
  2871. if (!really_close_down) {
  2872. /* This frees resources that should never be retained
  2873. * no matter what the close down mode is. Actually we
  2874. * could do this unconditionally, but it's probably
  2875. * better not to traverse all the client's resources
  2876. * twice (once here, once a few lines down in
  2877. * FreeClientResources) in the common case of
  2878. * really_close_down == TRUE.
  2879. */
  2880. FreeClientNeverRetainResources(client);
  2881. client->clientState = ClientStateRetained;
  2882. if (ClientStateCallback) {
  2883. NewClientInfoRec clientinfo;
  2884. clientinfo.client = client;
  2885. clientinfo.prefix = (xConnSetupPrefix *) NULL;
  2886. clientinfo.setup = (xConnSetup *) NULL;
  2887. CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
  2888. }
  2889. }
  2890. client->clientGone = TRUE; /* so events aren't sent to client */
  2891. if (ClientIsAsleep(client))
  2892. ClientSignal(client);
  2893. ProcessWorkQueueZombies();
  2894. CloseDownConnection(client);
  2895. /* If the client made it to the Running stage, nClients has
  2896. * been incremented on its behalf, so we need to decrement it
  2897. * now. If it hasn't gotten to Running, nClients has *not*
  2898. * been incremented, so *don't* decrement it.
  2899. */
  2900. if (client->clientState != ClientStateInitial) {
  2901. --nClients;
  2902. }
  2903. }
  2904. if (really_close_down) {
  2905. if (client->clientState == ClientStateRunning && nClients == 0)
  2906. dispatchException |= dispatchExceptionAtReset;
  2907. client->clientState = ClientStateGone;
  2908. if (ClientStateCallback) {
  2909. NewClientInfoRec clientinfo;
  2910. clientinfo.client = client;
  2911. clientinfo.prefix = (xConnSetupPrefix *) NULL;
  2912. clientinfo.setup = (xConnSetup *) NULL;
  2913. CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
  2914. }
  2915. TouchListenerGone(client->clientAsMask);
  2916. FreeClientResources(client);
  2917. /* Disable client ID tracking. This must be done after
  2918. * ClientStateCallback. */
  2919. ReleaseClientIds(client);
  2920. #ifdef XSERVER_DTRACE
  2921. XSERVER_CLIENT_DISCONNECT(client->index);
  2922. #endif
  2923. if (client->index < nextFreeClientID)
  2924. nextFreeClientID = client->index;
  2925. clients[client->index] = NullClient;
  2926. SmartLastClient = NullClient;
  2927. dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
  2928. while (!clients[currentMaxClients - 1])
  2929. currentMaxClients--;
  2930. }
  2931. }
  2932. static void
  2933. KillAllClients(void)
  2934. {
  2935. int i;
  2936. for (i = 1; i < currentMaxClients; i++)
  2937. if (clients[i]) {
  2938. /* Make sure Retained clients are released. */
  2939. clients[i]->closeDownMode = DestroyAll;
  2940. CloseDownClient(clients[i]);
  2941. }
  2942. }
  2943. void
  2944. InitClient(ClientPtr client, int i, void *ospriv)
  2945. {
  2946. client->index = i;
  2947. client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
  2948. client->closeDownMode = i ? DestroyAll : RetainPermanent;
  2949. client->requestVector = InitialVector;
  2950. client->osPrivate = ospriv;
  2951. QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
  2952. client->smart_start_tick = SmartScheduleTime;
  2953. client->smart_stop_tick = SmartScheduleTime;
  2954. client->clientIds = NULL;
  2955. }
  2956. /************************
  2957. * int NextAvailableClient(ospriv)
  2958. *
  2959. * OS dependent portion can't assign client id's because of CloseDownModes.
  2960. * Returns NULL if there are no free clients.
  2961. *************************/
  2962. ClientPtr
  2963. NextAvailableClient(void *ospriv)
  2964. {
  2965. int i;
  2966. ClientPtr client;
  2967. xReq data;
  2968. i = nextFreeClientID;
  2969. if (i == MAXCLIENTS)
  2970. return (ClientPtr) NULL;
  2971. clients[i] = client =
  2972. dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
  2973. if (!client)
  2974. return (ClientPtr) NULL;
  2975. InitClient(client, i, ospriv);
  2976. if (!InitClientResources(client)) {
  2977. dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
  2978. return (ClientPtr) NULL;
  2979. }
  2980. data.reqType = 1;
  2981. data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
  2982. if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
  2983. FreeClientResources(client);
  2984. dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
  2985. return (ClientPtr) NULL;
  2986. }
  2987. if (i == currentMaxClients)
  2988. currentMaxClients++;
  2989. while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
  2990. nextFreeClientID++;
  2991. /* Enable client ID tracking. This must be done before
  2992. * ClientStateCallback. */
  2993. ReserveClientIds(client);
  2994. if (ClientStateCallback) {
  2995. NewClientInfoRec clientinfo;
  2996. clientinfo.client = client;
  2997. clientinfo.prefix = (xConnSetupPrefix *) NULL;
  2998. clientinfo.setup = (xConnSetup *) NULL;
  2999. CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
  3000. }
  3001. return client;
  3002. }
  3003. int
  3004. ProcInitialConnection(ClientPtr client)
  3005. {
  3006. REQUEST(xReq);
  3007. xConnClientPrefix *prefix;
  3008. int whichbyte = 1;
  3009. char order;
  3010. prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
  3011. order = prefix->byteOrder;
  3012. if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
  3013. return client->noClientException = -1;
  3014. if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
  3015. (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
  3016. client->swapped = TRUE;
  3017. SwapConnClientPrefix(prefix);
  3018. }
  3019. stuff->reqType = 2;
  3020. stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
  3021. bytes_to_int32(prefix->nbytesAuthString);
  3022. if (client->swapped) {
  3023. swaps(&stuff->length);
  3024. }
  3025. if (order == 'r' || order == 'R') {
  3026. client->local = FALSE;
  3027. }
  3028. ResetCurrentRequest(client);
  3029. return Success;
  3030. }
  3031. static int
  3032. SendConnSetup(ClientPtr client, const char *reason)
  3033. {
  3034. xWindowRoot *root;
  3035. int i;
  3036. int numScreens;
  3037. char *lConnectionInfo;
  3038. xConnSetupPrefix *lconnSetupPrefix;
  3039. if (reason) {
  3040. xConnSetupPrefix csp;
  3041. csp.success = xFalse;
  3042. csp.lengthReason = strlen(reason);
  3043. csp.length = bytes_to_int32(csp.lengthReason);
  3044. csp.majorVersion = X_PROTOCOL;
  3045. csp.minorVersion = X_PROTOCOL_REVISION;
  3046. if (client->swapped)
  3047. WriteSConnSetupPrefix(client, &csp);
  3048. else
  3049. WriteToClient(client, sz_xConnSetupPrefix, &csp);
  3050. WriteToClient(client, (int) csp.lengthReason, reason);
  3051. return client->noClientException = -1;
  3052. }
  3053. numScreens = screenInfo.numScreens;
  3054. lConnectionInfo = ConnectionInfo;
  3055. lconnSetupPrefix = &connSetupPrefix;
  3056. /* We're about to start speaking X protocol back to the client by
  3057. * sending the connection setup info. This means the authorization
  3058. * step is complete, and we can count the client as an
  3059. * authorized one.
  3060. */
  3061. nClients++;
  3062. client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
  3063. client->sequence = 0;
  3064. ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
  3065. ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
  3066. #ifdef MATCH_CLIENT_ENDIAN
  3067. ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
  3068. ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
  3069. #endif
  3070. /* fill in the "currentInputMask" */
  3071. root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
  3072. #ifdef PANORAMIX
  3073. if (noPanoramiXExtension)
  3074. numScreens = screenInfo.numScreens;
  3075. else
  3076. numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
  3077. #endif
  3078. for (i = 0; i < numScreens; i++) {
  3079. unsigned int j;
  3080. xDepth *pDepth;
  3081. WindowPtr pRoot = screenInfo.screens[i]->root;
  3082. root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
  3083. pDepth = (xDepth *) (root + 1);
  3084. for (j = 0; j < root->nDepths; j++) {
  3085. pDepth = (xDepth *) (((char *) (pDepth + 1)) +
  3086. pDepth->nVisuals * sizeof(xVisualType));
  3087. }
  3088. root = (xWindowRoot *) pDepth;
  3089. }
  3090. if (client->swapped) {
  3091. WriteSConnSetupPrefix(client, lconnSetupPrefix);
  3092. WriteSConnectionInfo(client,
  3093. (unsigned long) (lconnSetupPrefix->length << 2),
  3094. lConnectionInfo);
  3095. }
  3096. else {
  3097. WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
  3098. WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
  3099. lConnectionInfo);
  3100. }
  3101. client->clientState = ClientStateRunning;
  3102. if (ClientStateCallback) {
  3103. NewClientInfoRec clientinfo;
  3104. clientinfo.client = client;
  3105. clientinfo.prefix = lconnSetupPrefix;
  3106. clientinfo.setup = (xConnSetup *) lConnectionInfo;
  3107. CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
  3108. }
  3109. return Success;
  3110. }
  3111. int
  3112. ProcEstablishConnection(ClientPtr client)
  3113. {
  3114. const char *reason;
  3115. char *auth_proto, *auth_string;
  3116. xConnClientPrefix *prefix;
  3117. REQUEST(xReq);
  3118. prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
  3119. auth_proto = (char *) prefix + sz_xConnClientPrefix;
  3120. auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
  3121. if ((prefix->majorVersion != X_PROTOCOL) ||
  3122. (prefix->minorVersion != X_PROTOCOL_REVISION))
  3123. reason = "Protocol version mismatch";
  3124. else
  3125. reason = ClientAuthorized(client,
  3126. (unsigned short) prefix->nbytesAuthProto,
  3127. auth_proto,
  3128. (unsigned short) prefix->nbytesAuthString,
  3129. auth_string);
  3130. return (SendConnSetup(client, reason));
  3131. }
  3132. void
  3133. SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
  3134. XID resId, int errorCode)
  3135. {
  3136. xError rep = {
  3137. .type = X_Error,
  3138. .errorCode = errorCode,
  3139. .resourceID = resId,
  3140. .minorCode = minorCode,
  3141. .majorCode = majorCode
  3142. };
  3143. WriteEventsToClient(client, 1, (xEvent *) &rep);
  3144. }
  3145. void
  3146. MarkClientException(ClientPtr client)
  3147. {
  3148. client->noClientException = -1;
  3149. }
  3150. /*
  3151. * This array encodes the answer to the question "what is the log base 2
  3152. * of the number of pixels that fit in a scanline pad unit?"
  3153. * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
  3154. */
  3155. static int answer[6][4] = {
  3156. /* pad pad pad pad */
  3157. /* 8 16 32 64 */
  3158. {3, 4, 5, 6}, /* 1 bit per pixel */
  3159. {1, 2, 3, 4}, /* 4 bits per pixel */
  3160. {0, 1, 2, 3}, /* 8 bits per pixel */
  3161. {~0, 0, 1, 2}, /* 16 bits per pixel */
  3162. {~0, ~0, 0, 1}, /* 24 bits per pixel */
  3163. {~0, ~0, 0, 1} /* 32 bits per pixel */
  3164. };
  3165. /*
  3166. * This array gives the answer to the question "what is the first index for
  3167. * the answer array above given the number of bits per pixel?"
  3168. * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
  3169. */
  3170. static int indexForBitsPerPixel[33] = {
  3171. ~0, 0, ~0, ~0, /* 1 bit per pixel */
  3172. 1, ~0, ~0, ~0, /* 4 bits per pixel */
  3173. 2, ~0, ~0, ~0, /* 8 bits per pixel */
  3174. ~0, ~0, ~0, ~0,
  3175. 3, ~0, ~0, ~0, /* 16 bits per pixel */
  3176. ~0, ~0, ~0, ~0,
  3177. 4, ~0, ~0, ~0, /* 24 bits per pixel */
  3178. ~0, ~0, ~0, ~0,
  3179. 5 /* 32 bits per pixel */
  3180. };
  3181. /*
  3182. * This array gives the bytesperPixel value for cases where the number
  3183. * of bits per pixel is a multiple of 8 but not a power of 2.
  3184. */
  3185. static int answerBytesPerPixel[33] = {
  3186. ~0, 0, ~0, ~0, /* 1 bit per pixel */
  3187. 0, ~0, ~0, ~0, /* 4 bits per pixel */
  3188. 0, ~0, ~0, ~0, /* 8 bits per pixel */
  3189. ~0, ~0, ~0, ~0,
  3190. 0, ~0, ~0, ~0, /* 16 bits per pixel */
  3191. ~0, ~0, ~0, ~0,
  3192. 3, ~0, ~0, ~0, /* 24 bits per pixel */
  3193. ~0, ~0, ~0, ~0,
  3194. 0 /* 32 bits per pixel */
  3195. };
  3196. /*
  3197. * This array gives the answer to the question "what is the second index for
  3198. * the answer array above given the number of bits per scanline pad unit?"
  3199. * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
  3200. */
  3201. static int indexForScanlinePad[65] = {
  3202. ~0, ~0, ~0, ~0,
  3203. ~0, ~0, ~0, ~0,
  3204. 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
  3205. ~0, ~0, ~0, ~0,
  3206. 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
  3207. ~0, ~0, ~0, ~0,
  3208. ~0, ~0, ~0, ~0,
  3209. ~0, ~0, ~0, ~0,
  3210. 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
  3211. ~0, ~0, ~0, ~0,
  3212. ~0, ~0, ~0, ~0,
  3213. ~0, ~0, ~0, ~0,
  3214. ~0, ~0, ~0, ~0,
  3215. ~0, ~0, ~0, ~0,
  3216. ~0, ~0, ~0, ~0,
  3217. ~0, ~0, ~0, ~0,
  3218. 3 /* 64 bits per scanline pad unit */
  3219. };
  3220. /*
  3221. grow the array of screenRecs if necessary.
  3222. call the device-supplied initialization procedure
  3223. with its screen number, a pointer to its ScreenRec, argc, and argv.
  3224. return the number of successfully installed screens.
  3225. */
  3226. static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
  3227. {
  3228. int scanlinepad, format, depth, bitsPerPixel, j, k;
  3229. dixInitScreenSpecificPrivates(pScreen);
  3230. if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
  3231. return -1;
  3232. }
  3233. pScreen->myNum = i;
  3234. if (gpu) {
  3235. pScreen->myNum += GPU_SCREEN_OFFSET;
  3236. pScreen->isGPU = TRUE;
  3237. }
  3238. pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
  3239. pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
  3240. pScreen->CreateScreenResources = 0;
  3241. xorg_list_init(&pScreen->pixmap_dirty_list);
  3242. xorg_list_init(&pScreen->unattached_list);
  3243. xorg_list_init(&pScreen->output_slave_list);
  3244. xorg_list_init(&pScreen->offload_slave_list);
  3245. /*
  3246. * This loop gets run once for every Screen that gets added,
  3247. * but thats ok. If the ddx layer initializes the formats
  3248. * one at a time calling AddScreen() after each, then each
  3249. * iteration will make it a little more accurate. Worst case
  3250. * we do this loop N * numPixmapFormats where N is # of screens.
  3251. * Anyway, this must be called after InitOutput and before the
  3252. * screen init routine is called.
  3253. */
  3254. for (format = 0; format < screenInfo.numPixmapFormats; format++) {
  3255. depth = screenInfo.formats[format].depth;
  3256. bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
  3257. scanlinepad = screenInfo.formats[format].scanlinePad;
  3258. j = indexForBitsPerPixel[bitsPerPixel];
  3259. k = indexForScanlinePad[scanlinepad];
  3260. PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
  3261. PixmapWidthPaddingInfo[depth].padRoundUp =
  3262. (scanlinepad / bitsPerPixel) - 1;
  3263. j = indexForBitsPerPixel[8]; /* bits per byte */
  3264. PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
  3265. PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
  3266. if (answerBytesPerPixel[bitsPerPixel]) {
  3267. PixmapWidthPaddingInfo[depth].notPower2 = 1;
  3268. PixmapWidthPaddingInfo[depth].bytesPerPixel =
  3269. answerBytesPerPixel[bitsPerPixel];
  3270. }
  3271. else {
  3272. PixmapWidthPaddingInfo[depth].notPower2 = 0;
  3273. }
  3274. }
  3275. return 0;
  3276. }
  3277. int
  3278. AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
  3279. int /*argc */ ,
  3280. char ** /*argv */
  3281. ), int argc, char **argv)
  3282. {
  3283. int i;
  3284. ScreenPtr pScreen;
  3285. Bool ret;
  3286. i = screenInfo.numScreens;
  3287. if (i == MAXSCREENS)
  3288. return -1;
  3289. pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
  3290. if (!pScreen)
  3291. return -1;
  3292. ret = init_screen(pScreen, i, FALSE);
  3293. if (ret != 0) {
  3294. free(pScreen);
  3295. return ret;
  3296. }
  3297. /* This is where screen specific stuff gets initialized. Load the
  3298. screen structure, call the hardware, whatever.
  3299. This is also where the default colormap should be allocated and
  3300. also pixel values for blackPixel, whitePixel, and the cursor
  3301. Note that InitScreen is NOT allowed to modify argc, argv, or
  3302. any of the strings pointed to by argv. They may be passed to
  3303. multiple screens.
  3304. */
  3305. screenInfo.screens[i] = pScreen;
  3306. screenInfo.numScreens++;
  3307. if (!(*pfnInit) (pScreen, argc, argv)) {
  3308. dixFreeScreenSpecificPrivates(pScreen);
  3309. dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
  3310. free(pScreen);
  3311. screenInfo.numScreens--;
  3312. return -1;
  3313. }
  3314. update_desktop_dimensions();
  3315. dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
  3316. 0);
  3317. return i;
  3318. }
  3319. int
  3320. AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
  3321. int /*argc */ ,
  3322. char ** /*argv */
  3323. ),
  3324. int argc, char **argv)
  3325. {
  3326. int i;
  3327. ScreenPtr pScreen;
  3328. Bool ret;
  3329. i = screenInfo.numGPUScreens;
  3330. if (i == MAXGPUSCREENS)
  3331. return -1;
  3332. pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
  3333. if (!pScreen)
  3334. return -1;
  3335. ret = init_screen(pScreen, i, TRUE);
  3336. if (ret != 0) {
  3337. free(pScreen);
  3338. return ret;
  3339. }
  3340. /* This is where screen specific stuff gets initialized. Load the
  3341. screen structure, call the hardware, whatever.
  3342. This is also where the default colormap should be allocated and
  3343. also pixel values for blackPixel, whitePixel, and the cursor
  3344. Note that InitScreen is NOT allowed to modify argc, argv, or
  3345. any of the strings pointed to by argv. They may be passed to
  3346. multiple screens.
  3347. */
  3348. screenInfo.gpuscreens[i] = pScreen;
  3349. screenInfo.numGPUScreens++;
  3350. if (!(*pfnInit) (pScreen, argc, argv)) {
  3351. dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
  3352. free(pScreen);
  3353. screenInfo.numGPUScreens--;
  3354. return -1;
  3355. }
  3356. update_desktop_dimensions();
  3357. return i;
  3358. }
  3359. void
  3360. RemoveGPUScreen(ScreenPtr pScreen)
  3361. {
  3362. int idx, j;
  3363. if (!pScreen->isGPU)
  3364. return;
  3365. idx = pScreen->myNum - GPU_SCREEN_OFFSET;
  3366. for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
  3367. screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
  3368. screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
  3369. }
  3370. screenInfo.numGPUScreens--;
  3371. /* this gets freed later in the resource list, but without
  3372. * the screen existing it causes crashes - so remove it here */
  3373. if (pScreen->defColormap)
  3374. FreeResource(pScreen->defColormap, RT_COLORMAP);
  3375. free(pScreen);
  3376. }
  3377. void
  3378. AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
  3379. {
  3380. assert(new->isGPU);
  3381. assert(!new->current_master);
  3382. xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
  3383. new->current_master = pScreen;
  3384. }
  3385. void
  3386. DetachUnboundGPU(ScreenPtr slave)
  3387. {
  3388. assert(slave->isGPU);
  3389. xorg_list_del(&slave->unattached_head);
  3390. slave->current_master = NULL;
  3391. }
  3392. void
  3393. AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
  3394. {
  3395. assert(new->isGPU);
  3396. xorg_list_add(&new->output_head, &pScreen->output_slave_list);
  3397. new->current_master = pScreen;
  3398. }
  3399. void
  3400. DetachOutputGPU(ScreenPtr slave)
  3401. {
  3402. assert(slave->isGPU);
  3403. xorg_list_del(&slave->output_head);
  3404. slave->current_master = NULL;
  3405. }
  3406. void
  3407. AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
  3408. {
  3409. assert(new->isGPU);
  3410. xorg_list_add(&new->offload_head, &pScreen->offload_slave_list);
  3411. new->current_master = pScreen;
  3412. }
  3413. void
  3414. DetachOffloadGPU(ScreenPtr slave)
  3415. {
  3416. assert(slave->isGPU);
  3417. xorg_list_del(&slave->offload_head);
  3418. slave->current_master = NULL;
  3419. }