rrscreen.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. /*
  2. * Copyright © 2006 Keith Packard
  3. *
  4. * Permission to use, copy, modify, distribute, and sell this software and its
  5. * documentation for any purpose is hereby granted without fee, provided that
  6. * the above copyright notice appear in all copies and that both that copyright
  7. * notice and this permission notice appear in supporting documentation, and
  8. * that the name of the copyright holders not be used in advertising or
  9. * publicity pertaining to distribution of the software without specific,
  10. * written prior permission. The copyright holders make no representations
  11. * about the suitability of this software for any purpose. It is provided "as
  12. * is" without express or implied warranty.
  13. *
  14. * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15. * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16. * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17. * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
  18. * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
  19. * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  20. * OF THIS SOFTWARE.
  21. */
  22. #include "randrstr.h"
  23. extern char *ConnectionInfo;
  24. static int padlength[4] = { 0, 3, 2, 1 };
  25. /*
  26. * Edit connection information block so that new clients
  27. * see the current screen size on connect
  28. */
  29. static void
  30. RREditConnectionInfo(ScreenPtr pScreen)
  31. {
  32. xConnSetup *connSetup;
  33. char *vendor;
  34. xPixmapFormat *formats;
  35. xWindowRoot *root;
  36. xDepth *depth;
  37. xVisualType *visual;
  38. int screen = 0;
  39. int d;
  40. connSetup = (xConnSetup *) ConnectionInfo;
  41. vendor = (char *) connSetup + sizeof(xConnSetup);
  42. formats = (xPixmapFormat *) ((char *) vendor +
  43. connSetup->nbytesVendor +
  44. padlength[connSetup->nbytesVendor & 3]);
  45. root = (xWindowRoot *) ((char *) formats +
  46. sizeof(xPixmapFormat) *
  47. screenInfo.numPixmapFormats);
  48. while (screen != pScreen->myNum) {
  49. depth = (xDepth *) ((char *) root + sizeof(xWindowRoot));
  50. for (d = 0; d < root->nDepths; d++) {
  51. visual = (xVisualType *) ((char *) depth + sizeof(xDepth));
  52. depth = (xDepth *) ((char *) visual +
  53. depth->nVisuals * sizeof(xVisualType));
  54. }
  55. root = (xWindowRoot *) ((char *) depth);
  56. screen++;
  57. }
  58. root->pixWidth = pScreen->width;
  59. root->pixHeight = pScreen->height;
  60. root->mmWidth = pScreen->mmWidth;
  61. root->mmHeight = pScreen->mmHeight;
  62. }
  63. void
  64. RRSendConfigNotify(ScreenPtr pScreen)
  65. {
  66. WindowPtr pWin = WindowTable[pScreen->myNum];
  67. xEvent event;
  68. event.u.u.type = ConfigureNotify;
  69. event.u.configureNotify.window = pWin->drawable.id;
  70. event.u.configureNotify.aboveSibling = None;
  71. event.u.configureNotify.x = 0;
  72. event.u.configureNotify.y = 0;
  73. /* XXX xinerama stuff ? */
  74. event.u.configureNotify.width = pWin->drawable.width;
  75. event.u.configureNotify.height = pWin->drawable.height;
  76. event.u.configureNotify.borderWidth = wBorderWidth(pWin);
  77. event.u.configureNotify.override = pWin->overrideRedirect;
  78. DeliverEvents(pWin, &event, 1, NullWindow);
  79. }
  80. void
  81. RRDeliverScreenEvent(ClientPtr client, WindowPtr pWin, ScreenPtr pScreen)
  82. {
  83. rrScrPriv(pScreen);
  84. xRRScreenChangeNotifyEvent se;
  85. RRCrtcPtr crtc = pScrPriv->numCrtcs ? pScrPriv->crtcs[0] : NULL;
  86. RROutputPtr output = pScrPriv->numOutputs ? pScrPriv->outputs[0] : NULL;
  87. RRModePtr mode = crtc ? crtc->mode : NULL;
  88. WindowPtr pRoot = WindowTable[pScreen->myNum];
  89. int i;
  90. se.type = RRScreenChangeNotify + RREventBase;
  91. se.rotation = (CARD8) (crtc ? crtc->rotation : RR_Rotate_0);
  92. se.timestamp = pScrPriv->lastSetTime.milliseconds;
  93. se.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
  94. se.root = pRoot->drawable.id;
  95. se.window = pWin->drawable.id;
  96. se.subpixelOrder = PictureGetSubpixelOrder(pScreen);
  97. if (mode) {
  98. se.sizeID = -1;
  99. for (i = 0; i < output->numModes; i++)
  100. if (mode == output->modes[i]) {
  101. se.sizeID = i;
  102. break;
  103. }
  104. se.widthInPixels = mode->mode.width;
  105. se.heightInPixels = mode->mode.height;
  106. se.widthInMillimeters = pScreen->mmWidth;
  107. se.heightInMillimeters = pScreen->mmHeight;
  108. }
  109. else {
  110. /*
  111. * This "shouldn't happen", but a broken DDX can
  112. * forget to set the current configuration on GetInfo
  113. */
  114. se.sizeID = 0xffff;
  115. se.widthInPixels = 0;
  116. se.heightInPixels = 0;
  117. se.widthInMillimeters = 0;
  118. se.heightInMillimeters = 0;
  119. }
  120. WriteEventsToClient(client, 1, (xEvent *) &se);
  121. }
  122. /*
  123. * Notify the extension that the screen size has been changed.
  124. * The driver is responsible for calling this whenever it has changed
  125. * the size of the screen
  126. */
  127. void
  128. RRScreenSizeNotify(ScreenPtr pScreen)
  129. {
  130. rrScrPriv(pScreen);
  131. /*
  132. * Deliver ConfigureNotify events when root changes
  133. * pixel size
  134. */
  135. if (pScrPriv->width == pScreen->width &&
  136. pScrPriv->height == pScreen->height &&
  137. pScrPriv->mmWidth == pScreen->mmWidth &&
  138. pScrPriv->mmHeight == pScreen->mmHeight)
  139. return;
  140. pScrPriv->width = pScreen->width;
  141. pScrPriv->height = pScreen->height;
  142. pScrPriv->mmWidth = pScreen->mmWidth;
  143. pScrPriv->mmHeight = pScreen->mmHeight;
  144. pScrPriv->changed = TRUE;
  145. /* pScrPriv->sizeChanged = TRUE; */
  146. RRTellChanged(pScreen);
  147. RRSendConfigNotify(pScreen);
  148. RREditConnectionInfo(pScreen);
  149. RRPointerScreenConfigured(pScreen);
  150. /*
  151. * Fix pointer bounds and location
  152. */
  153. ScreenRestructured(pScreen);
  154. }
  155. /*
  156. * Request that the screen be resized
  157. */
  158. Bool
  159. RRScreenSizeSet(ScreenPtr pScreen,
  160. CARD16 width, CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
  161. {
  162. rrScrPriv(pScreen);
  163. #if RANDR_12_INTERFACE
  164. if (pScrPriv->rrScreenSetSize) {
  165. return (*pScrPriv->rrScreenSetSize) (pScreen,
  166. width, height, mmWidth, mmHeight);
  167. }
  168. #endif
  169. #if RANDR_10_INTERFACE
  170. if (pScrPriv->rrSetConfig) {
  171. return TRUE; /* can't set size separately */
  172. }
  173. #endif
  174. return FALSE;
  175. }
  176. /*
  177. * Retrieve valid screen size range
  178. */
  179. int
  180. ProcRRGetScreenSizeRange(ClientPtr client)
  181. {
  182. REQUEST(xRRGetScreenSizeRangeReq);
  183. xRRGetScreenSizeRangeReply rep;
  184. WindowPtr pWin;
  185. ScreenPtr pScreen;
  186. rrScrPrivPtr pScrPriv;
  187. REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
  188. pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
  189. SecurityReadAccess);
  190. if (!pWin)
  191. return BadWindow;
  192. pScreen = pWin->drawable.pScreen;
  193. pScrPriv = rrGetScrPriv(pScreen);
  194. rep.type = X_Reply;
  195. rep.pad = 0;
  196. rep.sequenceNumber = client->sequence;
  197. rep.length = 0;
  198. if (pScrPriv) {
  199. if (!RRGetInfo(pScreen))
  200. return BadAlloc;
  201. rep.minWidth = pScrPriv->minWidth;
  202. rep.minHeight = pScrPriv->minHeight;
  203. rep.maxWidth = pScrPriv->maxWidth;
  204. rep.maxHeight = pScrPriv->maxHeight;
  205. }
  206. else {
  207. rep.maxWidth = rep.minWidth = pScreen->width;
  208. rep.maxHeight = rep.minHeight = pScreen->height;
  209. }
  210. if (client->swapped) {
  211. swaps(&rep.sequenceNumber);
  212. swapl(&rep.length);
  213. swaps(&rep.minWidth);
  214. swaps(&rep.minHeight);
  215. swaps(&rep.maxWidth);
  216. swaps(&rep.maxHeight);
  217. }
  218. WriteToClient(client, sizeof(xRRGetScreenSizeRangeReply), (char *) &rep);
  219. return (client->noClientException);
  220. }
  221. int
  222. ProcRRSetScreenSize(ClientPtr client)
  223. {
  224. REQUEST(xRRSetScreenSizeReq);
  225. WindowPtr pWin;
  226. ScreenPtr pScreen;
  227. rrScrPrivPtr pScrPriv;
  228. int i;
  229. REQUEST_SIZE_MATCH(xRRSetScreenSizeReq);
  230. pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
  231. SecurityReadAccess);
  232. if (!pWin)
  233. return BadWindow;
  234. pScreen = pWin->drawable.pScreen;
  235. pScrPriv = rrGetScrPriv(pScreen);
  236. if (stuff->width < pScrPriv->minWidth || pScrPriv->maxWidth < stuff->width) {
  237. client->errorValue = stuff->width;
  238. return BadValue;
  239. }
  240. if (stuff->height < pScrPriv->minHeight ||
  241. pScrPriv->maxHeight < stuff->height) {
  242. client->errorValue = stuff->height;
  243. return BadValue;
  244. }
  245. for (i = 0; i < pScrPriv->numCrtcs; i++) {
  246. RRCrtcPtr crtc = pScrPriv->crtcs[i];
  247. RRModePtr mode = crtc->mode;
  248. if (mode) {
  249. int source_width = mode->mode.width;
  250. int source_height = mode->mode.height;
  251. Rotation rotation = crtc->rotation;
  252. if (rotation == RR_Rotate_90 || rotation == RR_Rotate_270) {
  253. source_width = mode->mode.height;
  254. source_height = mode->mode.width;
  255. }
  256. if (crtc->x + source_width > stuff->width ||
  257. crtc->y + source_height > stuff->height)
  258. return BadMatch;
  259. }
  260. }
  261. if (stuff->widthInMillimeters == 0 || stuff->heightInMillimeters == 0) {
  262. client->errorValue = 0;
  263. return BadValue;
  264. }
  265. if (!RRScreenSizeSet(pScreen,
  266. stuff->width, stuff->height,
  267. stuff->widthInMillimeters,
  268. stuff->heightInMillimeters)) {
  269. return BadMatch;
  270. }
  271. return Success;
  272. }
  273. int
  274. ProcRRGetScreenResources(ClientPtr client)
  275. {
  276. REQUEST(xRRGetScreenResourcesReq);
  277. xRRGetScreenResourcesReply rep;
  278. WindowPtr pWin;
  279. ScreenPtr pScreen;
  280. rrScrPrivPtr pScrPriv;
  281. CARD8 *extra;
  282. unsigned long extraLen;
  283. int i;
  284. RRCrtc *crtcs;
  285. RROutput *outputs;
  286. xRRModeInfo *modeinfos;
  287. CARD8 *names;
  288. REQUEST_SIZE_MATCH(xRRGetScreenResourcesReq);
  289. pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
  290. SecurityReadAccess);
  291. if (!pWin)
  292. return BadWindow;
  293. pScreen = pWin->drawable.pScreen;
  294. pScrPriv = rrGetScrPriv(pScreen);
  295. rep.pad = 0;
  296. if (pScrPriv)
  297. if (!RRGetInfo(pScreen))
  298. return BadAlloc;
  299. if (!pScrPriv) {
  300. rep.type = X_Reply;
  301. rep.sequenceNumber = client->sequence;
  302. rep.length = 0;
  303. rep.timestamp = currentTime.milliseconds;
  304. rep.configTimestamp = currentTime.milliseconds;
  305. rep.nCrtcs = 0;
  306. rep.nOutputs = 0;
  307. rep.nModes = 0;
  308. rep.nbytesNames = 0;
  309. extra = NULL;
  310. extraLen = 0;
  311. }
  312. else {
  313. RRModePtr *modes;
  314. int num_modes;
  315. modes = RRModesForScreen(pScreen, &num_modes);
  316. if (!modes)
  317. return BadAlloc;
  318. rep.type = X_Reply;
  319. rep.sequenceNumber = client->sequence;
  320. rep.length = 0;
  321. rep.timestamp = pScrPriv->lastSetTime.milliseconds;
  322. rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
  323. rep.nCrtcs = pScrPriv->numCrtcs;
  324. rep.nOutputs = pScrPriv->numOutputs;
  325. rep.nModes = num_modes;
  326. rep.nbytesNames = 0;
  327. for (i = 0; i < num_modes; i++)
  328. rep.nbytesNames += modes[i]->mode.nameLength;
  329. rep.length = (pScrPriv->numCrtcs +
  330. pScrPriv->numOutputs +
  331. num_modes * (SIZEOF(xRRModeInfo) >> 2) +
  332. ((rep.nbytesNames + 3) >> 2));
  333. extraLen = rep.length << 2;
  334. if (extraLen) {
  335. extra = malloc(extraLen);
  336. if (!extra) {
  337. free(modes);
  338. return BadAlloc;
  339. }
  340. }
  341. else
  342. extra = NULL;
  343. crtcs = (RRCrtc *) extra;
  344. outputs = (RROutput *) (crtcs + pScrPriv->numCrtcs);
  345. modeinfos = (xRRModeInfo *) (outputs + pScrPriv->numOutputs);
  346. names = (CARD8 *) (modeinfos + num_modes);
  347. for (i = 0; i < pScrPriv->numCrtcs; i++) {
  348. crtcs[i] = pScrPriv->crtcs[i]->id;
  349. if (client->swapped)
  350. swapl(&crtcs[i]);
  351. }
  352. for (i = 0; i < pScrPriv->numOutputs; i++) {
  353. outputs[i] = pScrPriv->outputs[i]->id;
  354. if (client->swapped)
  355. swapl(&outputs[i]);
  356. }
  357. for (i = 0; i < num_modes; i++) {
  358. RRModePtr mode = modes[i];
  359. modeinfos[i] = mode->mode;
  360. if (client->swapped) {
  361. swapl(&modeinfos[i].id);
  362. swaps(&modeinfos[i].width);
  363. swaps(&modeinfos[i].height);
  364. swapl(&modeinfos[i].dotClock);
  365. swaps(&modeinfos[i].hSyncStart);
  366. swaps(&modeinfos[i].hSyncEnd);
  367. swaps(&modeinfos[i].hTotal);
  368. swaps(&modeinfos[i].hSkew);
  369. swaps(&modeinfos[i].vSyncStart);
  370. swaps(&modeinfos[i].vSyncEnd);
  371. swaps(&modeinfos[i].vTotal);
  372. swaps(&modeinfos[i].nameLength);
  373. swapl(&modeinfos[i].modeFlags);
  374. }
  375. memcpy(names, mode->name, mode->mode.nameLength);
  376. names += mode->mode.nameLength;
  377. }
  378. free(modes);
  379. assert(((((char *) names - (char *) extra) + 3) >> 2) == rep.length);
  380. }
  381. if (client->swapped) {
  382. swaps(&rep.sequenceNumber);
  383. swapl(&rep.length);
  384. swapl(&rep.timestamp);
  385. swapl(&rep.configTimestamp);
  386. swaps(&rep.nCrtcs);
  387. swaps(&rep.nOutputs);
  388. swaps(&rep.nModes);
  389. swaps(&rep.nbytesNames);
  390. }
  391. WriteToClient(client, sizeof(xRRGetScreenResourcesReply), (char *) &rep);
  392. if (extraLen) {
  393. WriteToClient(client, extraLen, (char *) extra);
  394. free(extra);
  395. }
  396. return client->noClientException;
  397. }
  398. typedef struct _RR10Data {
  399. RRScreenSizePtr sizes;
  400. int nsize;
  401. int nrefresh;
  402. int size;
  403. CARD16 refresh;
  404. } RR10DataRec, *RR10DataPtr;
  405. /*
  406. * Convert 1.2 monitor data into 1.0 screen data
  407. */
  408. static RR10DataPtr
  409. RR10GetData(ScreenPtr pScreen, RROutputPtr output)
  410. {
  411. RR10DataPtr data;
  412. RRScreenSizePtr size;
  413. int nmode = output->numModes;
  414. int o, os, l, r;
  415. RRScreenRatePtr refresh;
  416. CARD16 vRefresh;
  417. RRModePtr mode;
  418. Bool *used;
  419. /* Make sure there is plenty of space for any combination */
  420. data = malloc(sizeof(RR10DataRec) +
  421. sizeof(RRScreenSize) * nmode +
  422. sizeof(RRScreenRate) * nmode + sizeof(Bool) * nmode);
  423. if (!data)
  424. return NULL;
  425. size = (RRScreenSizePtr) (data + 1);
  426. refresh = (RRScreenRatePtr) (size + nmode);
  427. used = (Bool *) (refresh + nmode);
  428. memset(used, '\0', sizeof(Bool) * nmode);
  429. data->sizes = size;
  430. data->nsize = 0;
  431. data->nrefresh = 0;
  432. data->size = 0;
  433. data->refresh = 0;
  434. /*
  435. * find modes not yet listed
  436. */
  437. for (o = 0; o < output->numModes; o++) {
  438. if (used[o])
  439. continue;
  440. mode = output->modes[o];
  441. l = data->nsize;
  442. size[l].id = data->nsize;
  443. size[l].width = mode->mode.width;
  444. size[l].height = mode->mode.height;
  445. if (output->mmWidth && output->mmHeight) {
  446. size[l].mmWidth = output->mmWidth;
  447. size[l].mmHeight = output->mmHeight;
  448. }
  449. else {
  450. size[l].mmWidth = pScreen->mmWidth;
  451. size[l].mmHeight = pScreen->mmHeight;
  452. }
  453. size[l].nRates = 0;
  454. size[l].pRates = &refresh[data->nrefresh];
  455. data->nsize++;
  456. /*
  457. * Find all modes with matching size
  458. */
  459. for (os = o; os < output->numModes; os++) {
  460. mode = output->modes[os];
  461. if (mode->mode.width == size[l].width &&
  462. mode->mode.height == size[l].height) {
  463. vRefresh = RRVerticalRefresh(&mode->mode);
  464. used[os] = TRUE;
  465. for (r = 0; r < size[l].nRates; r++)
  466. if (vRefresh == size[l].pRates[r].rate)
  467. break;
  468. if (r == size[l].nRates) {
  469. size[l].pRates[r].rate = vRefresh;
  470. size[l].pRates[r].mode = mode;
  471. size[l].nRates++;
  472. data->nrefresh++;
  473. }
  474. if (mode == output->crtc->mode) {
  475. data->size = l;
  476. data->refresh = vRefresh;
  477. }
  478. }
  479. }
  480. }
  481. return data;
  482. }
  483. int
  484. ProcRRGetScreenInfo(ClientPtr client)
  485. {
  486. REQUEST(xRRGetScreenInfoReq);
  487. xRRGetScreenInfoReply rep;
  488. WindowPtr pWin;
  489. ScreenPtr pScreen;
  490. rrScrPrivPtr pScrPriv;
  491. CARD8 *extra;
  492. unsigned long extraLen;
  493. RROutputPtr output;
  494. REQUEST_SIZE_MATCH(xRRGetScreenInfoReq);
  495. pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
  496. SecurityReadAccess);
  497. if (!pWin)
  498. return BadWindow;
  499. pScreen = pWin->drawable.pScreen;
  500. pScrPriv = rrGetScrPriv(pScreen);
  501. rep.pad = 0;
  502. if (pScrPriv)
  503. if (!RRGetInfo(pScreen))
  504. return BadAlloc;
  505. output = RRFirstOutput(pScreen);
  506. if (!pScrPriv || !output) {
  507. rep.type = X_Reply;
  508. rep.setOfRotations = RR_Rotate_0;;
  509. rep.sequenceNumber = client->sequence;
  510. rep.length = 0;
  511. rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
  512. rep.timestamp = currentTime.milliseconds;
  513. rep.configTimestamp = currentTime.milliseconds;
  514. rep.nSizes = 0;
  515. rep.sizeID = 0;
  516. rep.rotation = RR_Rotate_0;
  517. rep.rate = 0;
  518. rep.nrateEnts = 0;
  519. extra = 0;
  520. extraLen = 0;
  521. }
  522. else {
  523. int i, j;
  524. xScreenSizes *size;
  525. CARD16 *rates;
  526. CARD8 *data8;
  527. Bool has_rate = RRClientKnowsRates(client);
  528. RR10DataPtr pData;
  529. RRScreenSizePtr pSize;
  530. pData = RR10GetData(pScreen, output);
  531. if (!pData)
  532. return BadAlloc;
  533. rep.type = X_Reply;
  534. rep.setOfRotations = output->crtc->rotations;
  535. rep.sequenceNumber = client->sequence;
  536. rep.length = 0;
  537. rep.root = WindowTable[pWin->drawable.pScreen->myNum]->drawable.id;
  538. rep.timestamp = pScrPriv->lastSetTime.milliseconds;
  539. rep.configTimestamp = pScrPriv->lastConfigTime.milliseconds;
  540. rep.rotation = output->crtc->rotation;
  541. rep.nSizes = pData->nsize;
  542. rep.nrateEnts = pData->nrefresh + pData->nsize;
  543. rep.sizeID = pData->size;
  544. rep.rate = pData->refresh;
  545. extraLen = (rep.nSizes * sizeof(xScreenSizes) +
  546. rep.nrateEnts * sizeof(CARD16));
  547. if (extraLen) {
  548. extra = malloc(extraLen);
  549. if (!extra) {
  550. free(pData);
  551. return BadAlloc;
  552. }
  553. }
  554. else
  555. extra = NULL;
  556. /*
  557. * First comes the size information
  558. */
  559. size = (xScreenSizes *) extra;
  560. rates = (CARD16 *) (size + rep.nSizes);
  561. for (i = 0; i < pData->nsize; i++) {
  562. pSize = &pData->sizes[i];
  563. size->widthInPixels = pSize->width;
  564. size->heightInPixels = pSize->height;
  565. size->widthInMillimeters = pSize->mmWidth;
  566. size->heightInMillimeters = pSize->mmHeight;
  567. if (client->swapped) {
  568. swaps(&size->widthInPixels);
  569. swaps(&size->heightInPixels);
  570. swaps(&size->widthInMillimeters);
  571. swaps(&size->heightInMillimeters);
  572. }
  573. size++;
  574. if (has_rate) {
  575. *rates = pSize->nRates;
  576. if (client->swapped) {
  577. swaps(rates);
  578. }
  579. rates++;
  580. for (j = 0; j < pSize->nRates; j++) {
  581. *rates = pSize->pRates[j].rate;
  582. if (client->swapped) {
  583. swaps(rates);
  584. }
  585. rates++;
  586. }
  587. }
  588. }
  589. free(pData);
  590. data8 = (CARD8 *) rates;
  591. if (data8 - (CARD8 *) extra != extraLen)
  592. FatalError("RRGetScreenInfo bad extra len %ld != %ld\n",
  593. (unsigned long) (data8 - (CARD8 *) extra), extraLen);
  594. rep.length = (extraLen + 3) >> 2;
  595. }
  596. if (client->swapped) {
  597. swaps(&rep.sequenceNumber);
  598. swapl(&rep.length);
  599. swapl(&rep.timestamp);
  600. swaps(&rep.rotation);
  601. swaps(&rep.nSizes);
  602. swaps(&rep.sizeID);
  603. swaps(&rep.rate);
  604. swaps(&rep.nrateEnts);
  605. }
  606. WriteToClient(client, sizeof(xRRGetScreenInfoReply), (char *) &rep);
  607. if (extraLen) {
  608. WriteToClient(client, extraLen, (char *) extra);
  609. free(extra);
  610. }
  611. return (client->noClientException);
  612. }
  613. int
  614. ProcRRSetScreenConfig(ClientPtr client)
  615. {
  616. REQUEST(xRRSetScreenConfigReq);
  617. xRRSetScreenConfigReply rep;
  618. DrawablePtr pDraw;
  619. ScreenPtr pScreen;
  620. rrScrPrivPtr pScrPriv;
  621. TimeStamp configTime;
  622. TimeStamp time;
  623. int i;
  624. Rotation rotation;
  625. int rate;
  626. Bool has_rate;
  627. RROutputPtr output;
  628. RRModePtr mode;
  629. RR10DataPtr pData = NULL;
  630. RRScreenSizePtr pSize;
  631. UpdateCurrentTime();
  632. if (RRClientKnowsRates(client)) {
  633. REQUEST_SIZE_MATCH(xRRSetScreenConfigReq);
  634. has_rate = TRUE;
  635. }
  636. else {
  637. REQUEST_SIZE_MATCH(xRR1_0SetScreenConfigReq);
  638. has_rate = FALSE;
  639. }
  640. SECURITY_VERIFY_DRAWABLE(pDraw, stuff->drawable, client,
  641. SecurityWriteAccess);
  642. pScreen = pDraw->pScreen;
  643. pScrPriv = rrGetScrPriv(pScreen);
  644. time = ClientTimeToServerTime(stuff->timestamp);
  645. configTime = ClientTimeToServerTime(stuff->configTimestamp);
  646. if (!pScrPriv) {
  647. rep.status = RRSetConfigFailed;
  648. goto sendReply;
  649. }
  650. if (!RRGetInfo(pScreen))
  651. return BadAlloc;
  652. output = RRFirstOutput(pScreen);
  653. if (!output) {
  654. rep.status = RRSetConfigFailed;
  655. goto sendReply;
  656. }
  657. /*
  658. * if the client's config timestamp is not the same as the last config
  659. * timestamp, then the config information isn't up-to-date and
  660. * can't even be validated
  661. */
  662. if (CompareTimeStamps(configTime, pScrPriv->lastConfigTime) != 0) {
  663. rep.status = RRSetConfigInvalidConfigTime;
  664. goto sendReply;
  665. }
  666. pData = RR10GetData(pScreen, output);
  667. if (!pData)
  668. return BadAlloc;
  669. if (stuff->sizeID >= pData->nsize) {
  670. /*
  671. * Invalid size ID
  672. */
  673. client->errorValue = stuff->sizeID;
  674. free(pData);
  675. return BadValue;
  676. }
  677. pSize = &pData->sizes[stuff->sizeID];
  678. /*
  679. * Validate requested rotation
  680. */
  681. rotation = (Rotation) stuff->rotation;
  682. /* test the rotation bits only! */
  683. switch (rotation & 0xf) {
  684. case RR_Rotate_0:
  685. case RR_Rotate_90:
  686. case RR_Rotate_180:
  687. case RR_Rotate_270:
  688. break;
  689. default:
  690. /*
  691. * Invalid rotation
  692. */
  693. client->errorValue = stuff->rotation;
  694. free(pData);
  695. return BadValue;
  696. }
  697. if ((~output->crtc->rotations) & rotation) {
  698. /*
  699. * requested rotation or reflection not supported by screen
  700. */
  701. client->errorValue = stuff->rotation;
  702. free(pData);
  703. return BadMatch;
  704. }
  705. /*
  706. * Validate requested refresh
  707. */
  708. if (has_rate)
  709. rate = (int) stuff->rate;
  710. else
  711. rate = 0;
  712. if (rate) {
  713. for (i = 0; i < pSize->nRates; i++) {
  714. if (pSize->pRates[i].rate == rate)
  715. break;
  716. }
  717. if (i == pSize->nRates) {
  718. /*
  719. * Invalid rate
  720. */
  721. client->errorValue = rate;
  722. free(pData);
  723. return BadValue;
  724. }
  725. mode = pSize->pRates[i].mode;
  726. }
  727. else
  728. mode = pSize->pRates[0].mode;
  729. /*
  730. * Make sure the requested set-time is not older than
  731. * the last set-time
  732. */
  733. if (CompareTimeStamps(time, pScrPriv->lastSetTime) < 0) {
  734. rep.status = RRSetConfigInvalidTime;
  735. goto sendReply;
  736. }
  737. /*
  738. * If the screen size is changing, adjust all of the other outputs
  739. * to fit the new size, mirroring as much as possible
  740. */
  741. if (mode->mode.width != pScreen->width ||
  742. mode->mode.height != pScreen->height) {
  743. int c;
  744. for (c = 0; c < pScrPriv->numCrtcs; c++) {
  745. if (!RRCrtcSet(pScrPriv->crtcs[c], NULL, 0, 0, RR_Rotate_0,
  746. 0, NULL)) {
  747. rep.status = RRSetConfigFailed;
  748. /* XXX recover from failure */
  749. goto sendReply;
  750. }
  751. }
  752. if (!RRScreenSizeSet(pScreen, mode->mode.width, mode->mode.height,
  753. pScreen->mmWidth, pScreen->mmHeight)) {
  754. rep.status = RRSetConfigFailed;
  755. /* XXX recover from failure */
  756. goto sendReply;
  757. }
  758. }
  759. if (!RRCrtcSet(output->crtc, mode, 0, 0, stuff->rotation, 1, &output))
  760. rep.status = RRSetConfigFailed;
  761. else
  762. rep.status = RRSetConfigSuccess;
  763. /*
  764. * XXX Configure other crtcs to mirror as much as possible
  765. */
  766. sendReply:
  767. if (pData)
  768. free(pData);
  769. rep.type = X_Reply;
  770. /* rep.status has already been filled in */
  771. rep.length = 0;
  772. rep.sequenceNumber = client->sequence;
  773. rep.newTimestamp = pScrPriv->lastSetTime.milliseconds;
  774. rep.newConfigTimestamp = pScrPriv->lastConfigTime.milliseconds;
  775. rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
  776. if (client->swapped) {
  777. swaps(&rep.sequenceNumber);
  778. swapl(&rep.length);
  779. swapl(&rep.newTimestamp);
  780. swapl(&rep.newConfigTimestamp);
  781. swapl(&rep.root);
  782. }
  783. WriteToClient(client, sizeof(xRRSetScreenConfigReply), (char *) &rep);
  784. return (client->noClientException);
  785. }