You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

RandrGlue.c 7.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
  2. * Copyright 2011-2015 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_DIX_CONFIG_H
  20. #include <dix-config.h>
  21. #endif
  22. #include <assert.h>
  23. #include <string.h>
  24. #include "scrnintstr.h"
  25. #include "randrstr.h"
  26. #include "RandrGlue.h"
  27. #include "XorgGlue.h"
  28. static int scrIdx;
  29. void vncSetGlueContext(int screenIndex);
  30. void vncSetGlueContext(int screenIndex)
  31. {
  32. scrIdx = screenIndex;
  33. }
  34. int vncGetScreenWidth(void)
  35. {
  36. return screenInfo.screens[scrIdx]->width;
  37. }
  38. int vncGetScreenHeight(void)
  39. {
  40. return screenInfo.screens[scrIdx]->height;
  41. }
  42. int vncRandRIsValidScreenSize(int width, int height)
  43. {
  44. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  45. if (width < rp->minWidth || rp->maxWidth < width)
  46. return 0;
  47. if (height < rp->minHeight || rp->maxHeight < height)
  48. return 0;
  49. return 1;
  50. }
  51. int vncRandRResizeScreen(int width, int height)
  52. {
  53. ScreenPtr pScreen = screenInfo.screens[scrIdx];
  54. /* Try to retain DPI when we resize */
  55. return RRScreenSizeSet(pScreen, width, height,
  56. pScreen->mmWidth * width / pScreen->width,
  57. pScreen->mmHeight * height / pScreen->height);
  58. }
  59. void vncRandRUpdateSetTime(void)
  60. {
  61. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  62. rp->lastSetTime = currentTime;
  63. }
  64. int vncRandRHasOutputClones(void)
  65. {
  66. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  67. for (int i = 0;i < rp->numCrtcs;i++) {
  68. if (rp->crtcs[i]->numOutputs > 1)
  69. return 1;
  70. }
  71. return 0;
  72. }
  73. int vncRandRGetOutputCount(void)
  74. {
  75. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  76. return rp->numOutputs;
  77. }
  78. int vncRandRGetAvailableOutputs(void)
  79. {
  80. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  81. int availableOutputs;
  82. RRCrtcPtr *usedCrtcs;
  83. int numUsed;
  84. int i, j, k;
  85. usedCrtcs = malloc(sizeof(RRCrtcPtr) * rp->numCrtcs);
  86. if (usedCrtcs == NULL)
  87. return 0;
  88. /*
  89. * This gets slightly complicated because we might need to hook a CRTC
  90. * up to the output, but also check that we don't try to use the same
  91. * CRTC for multiple outputs.
  92. */
  93. availableOutputs = 0;
  94. numUsed = 0;
  95. for (i = 0;i < rp->numOutputs;i++) {
  96. RROutputPtr output;
  97. output = rp->outputs[i];
  98. if (output->crtc != NULL)
  99. availableOutputs++;
  100. else {
  101. for (j = 0;j < output->numCrtcs;j++) {
  102. if (output->crtcs[j]->numOutputs != 0)
  103. continue;
  104. for (k = 0;k < numUsed;k++) {
  105. if (usedCrtcs[k] == output->crtcs[j])
  106. break;
  107. }
  108. if (k != numUsed)
  109. continue;
  110. availableOutputs++;
  111. usedCrtcs[numUsed] = output->crtcs[j];
  112. numUsed++;
  113. break;
  114. }
  115. }
  116. }
  117. free(usedCrtcs);
  118. return availableOutputs;
  119. }
  120. char *vncRandRGetOutputName(int outputIdx)
  121. {
  122. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  123. return strdup(rp->outputs[outputIdx]->name);
  124. }
  125. int vncRandRIsOutputEnabled(int outputIdx)
  126. {
  127. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  128. if (rp->outputs[outputIdx]->crtc == NULL)
  129. return 0;
  130. if (rp->outputs[outputIdx]->crtc->mode == NULL)
  131. return 0;
  132. return 1;
  133. }
  134. int vncRandRIsOutputUsable(int outputIdx)
  135. {
  136. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  137. RROutputPtr output;
  138. int i;
  139. output = rp->outputs[outputIdx];
  140. if (output->crtc != NULL)
  141. return 1;
  142. /* Any unused CRTCs? */
  143. for (i = 0;i < output->numCrtcs;i++) {
  144. if (output->crtcs[i]->numOutputs == 0)
  145. return 1;
  146. }
  147. return 0;
  148. }
  149. int vncRandRIsOutputConnected(int outputIdx)
  150. {
  151. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  152. RROutputPtr output;
  153. output = rp->outputs[outputIdx];
  154. return (output->connection == RR_Connected);
  155. }
  156. static RRModePtr vncRandRGetMatchingMode(int outputIdx, int width, int height)
  157. {
  158. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  159. RROutputPtr output;
  160. output = rp->outputs[outputIdx];
  161. if (output->crtc != NULL) {
  162. unsigned int swap;
  163. switch (output->crtc->rotation) {
  164. case RR_Rotate_90:
  165. case RR_Rotate_270:
  166. swap = width;
  167. width = height;
  168. height = swap;
  169. break;
  170. }
  171. }
  172. for (int i = 0; i < output->numModes; i++) {
  173. if ((output->modes[i]->mode.width == width) &&
  174. (output->modes[i]->mode.height == height))
  175. return output->modes[i];
  176. }
  177. return NULL;
  178. }
  179. int vncRandRCheckOutputMode(int outputIdx, int width, int height)
  180. {
  181. if (vncRandRGetMatchingMode(outputIdx, width, height) != NULL)
  182. return 1;
  183. if (vncRandRCanCreateModes())
  184. return 1;
  185. return 0;
  186. }
  187. int vncRandRDisableOutput(int outputIdx)
  188. {
  189. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  190. RRCrtcPtr crtc;
  191. int i;
  192. RROutputPtr *outputs;
  193. int numOutputs = 0;
  194. RRModePtr mode;
  195. int ret;
  196. crtc = rp->outputs[outputIdx]->crtc;
  197. if (crtc == NULL)
  198. return 1;
  199. /* Remove this output from the CRTC configuration */
  200. outputs = malloc(crtc->numOutputs * sizeof(RROutputPtr));
  201. if (!outputs) {
  202. return 0;
  203. }
  204. for (i = 0; i < crtc->numOutputs; i++) {
  205. if (rp->outputs[outputIdx] != crtc->outputs[i]) {
  206. outputs[numOutputs++] = crtc->outputs[i];
  207. }
  208. }
  209. if (numOutputs == 0) {
  210. mode = NULL;
  211. } else {
  212. mode = crtc->mode;
  213. }
  214. ret = RRCrtcSet(crtc, mode, crtc->x, crtc->y, crtc->rotation, numOutputs, outputs);
  215. free(outputs);
  216. return ret;
  217. }
  218. unsigned int vncRandRGetOutputId(int outputIdx)
  219. {
  220. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  221. return rp->outputs[outputIdx]->id;
  222. }
  223. int vncRandRGetOutputDimensions(int outputIdx,
  224. int *x, int *y, int *width, int *height)
  225. {
  226. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  227. RRCrtcPtr crtc;
  228. int swap;
  229. *x = *y = *width = *height = 0;
  230. crtc = rp->outputs[outputIdx]->crtc;
  231. if (crtc == NULL || !crtc->mode)
  232. return 1;
  233. *x = crtc->x;
  234. *y = crtc->y;
  235. *width = crtc->mode->mode.width;
  236. *height = crtc->mode->mode.height;
  237. switch (crtc->rotation & 0xf) {
  238. case RR_Rotate_90:
  239. case RR_Rotate_270:
  240. swap = *width;
  241. *width = *height;
  242. *height = swap;
  243. break;
  244. }
  245. return 0;
  246. }
  247. int vncRandRReconfigureOutput(int outputIdx, int x, int y,
  248. int width, int height)
  249. {
  250. rrScrPrivPtr rp = rrGetScrPriv(screenInfo.screens[scrIdx]);
  251. RROutputPtr output;
  252. RRCrtcPtr crtc;
  253. RRModePtr mode;
  254. int i;
  255. output = rp->outputs[outputIdx];
  256. crtc = output->crtc;
  257. /* Need a CRTC? */
  258. if (crtc == NULL) {
  259. for (i = 0;i < output->numCrtcs;i++) {
  260. if (output->crtcs[i]->numOutputs != 0)
  261. continue;
  262. crtc = output->crtcs[i];
  263. break;
  264. }
  265. /* Couldn't find one... */
  266. if (crtc == NULL)
  267. return 0;
  268. }
  269. /* Make sure we have the mode we want */
  270. mode = vncRandRGetMatchingMode(outputIdx, width, height);
  271. if (mode == NULL) {
  272. mode = vncRandRCreateMode(output, width, height);
  273. if (mode == NULL)
  274. return 0;
  275. }
  276. mode = vncRandRSetPreferredMode(output, mode);
  277. if (mode == NULL)
  278. return 0;
  279. /* Reconfigure new mode and position */
  280. return RRCrtcSet(crtc, mode, x, y, crtc->rotation, 1, &output);
  281. }
  282. int vncRandRCanCreateOutputs(int extraOutputs)
  283. {
  284. return vncRandRCanCreateScreenOutputs(scrIdx, extraOutputs);
  285. }
  286. int vncRandRCreateOutputs(int extraOutputs)
  287. {
  288. return vncRandRCreateScreenOutputs(scrIdx, extraOutputs);
  289. }