present_request.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. /*
  2. * Copyright © 2013 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. #ifdef HAVE_XORG_CONFIG_H
  23. #include <xorg-config.h>
  24. #endif
  25. #include "present_priv.h"
  26. #include "randrstr.h"
  27. #include <protocol-versions.h>
  28. static int
  29. proc_present_query_version(ClientPtr client)
  30. {
  31. REQUEST(xPresentQueryVersionReq);
  32. xPresentQueryVersionReply rep = {
  33. .type = X_Reply,
  34. .sequenceNumber = client->sequence,
  35. .length = 0,
  36. .majorVersion = SERVER_PRESENT_MAJOR_VERSION,
  37. .minorVersion = SERVER_PRESENT_MINOR_VERSION
  38. };
  39. REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
  40. (void) stuff;
  41. if (client->swapped) {
  42. swaps(&rep.sequenceNumber);
  43. swapl(&rep.length);
  44. swapl(&rep.majorVersion);
  45. swapl(&rep.minorVersion);
  46. }
  47. WriteToClient(client, sizeof(rep), &rep);
  48. return Success;
  49. }
  50. #define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do { \
  51. if ((fence_id) == None) \
  52. (fence_ptr) = NULL; \
  53. else { \
  54. int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \
  55. if (__rc__ != Success) \
  56. return __rc__; \
  57. } \
  58. } while (0)
  59. #define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do { \
  60. if ((crtc_id) == None) \
  61. (crtc_ptr) = NULL; \
  62. else { \
  63. VERIFY_RR_CRTC(crtc_id, crtc_ptr, access); \
  64. } \
  65. } while (0)
  66. static int
  67. proc_present_pixmap(ClientPtr client)
  68. {
  69. REQUEST(xPresentPixmapReq);
  70. WindowPtr window;
  71. PixmapPtr pixmap;
  72. RegionPtr valid = NULL;
  73. RegionPtr update = NULL;
  74. SyncFence *wait_fence;
  75. SyncFence *idle_fence;
  76. RRCrtcPtr target_crtc;
  77. int ret;
  78. int nnotifies;
  79. present_notify_ptr notifies = NULL;
  80. REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
  81. ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess);
  82. if (ret != Success)
  83. return ret;
  84. ret = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess);
  85. if (ret != Success)
  86. return ret;
  87. if (window->drawable.depth != pixmap->drawable.depth)
  88. return BadMatch;
  89. VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
  90. VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
  91. VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
  92. VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
  93. VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
  94. if (stuff->options & ~(PresentAllOptions)) {
  95. client->errorValue = stuff->options;
  96. return BadValue;
  97. }
  98. /*
  99. * Check to see if remainder is sane
  100. */
  101. if (stuff->divisor == 0) {
  102. if (stuff->remainder != 0) {
  103. client->errorValue = (CARD32) stuff->remainder;
  104. return BadValue;
  105. }
  106. } else {
  107. if (stuff->remainder >= stuff->divisor) {
  108. client->errorValue = (CARD32) stuff->remainder;
  109. return BadValue;
  110. }
  111. }
  112. nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq);
  113. if (nnotifies % sizeof (xPresentNotify))
  114. return BadLength;
  115. nnotifies /= sizeof (xPresentNotify);
  116. if (nnotifies) {
  117. ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), &notifies);
  118. if (ret != Success)
  119. return ret;
  120. }
  121. ret = present_pixmap(window, pixmap, stuff->serial, valid, update,
  122. stuff->x_off, stuff->y_off, target_crtc,
  123. wait_fence, idle_fence, stuff->options,
  124. stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies);
  125. if (ret != Success)
  126. present_destroy_notifies(notifies, nnotifies);
  127. return ret;
  128. }
  129. static int
  130. proc_present_notify_msc(ClientPtr client)
  131. {
  132. REQUEST(xPresentNotifyMSCReq);
  133. WindowPtr window;
  134. int rc;
  135. REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
  136. rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
  137. if (rc != Success)
  138. return rc;
  139. /*
  140. * Check to see if remainder is sane
  141. */
  142. if (stuff->divisor == 0) {
  143. if (stuff->remainder != 0) {
  144. client->errorValue = (CARD32) stuff->remainder;
  145. return BadValue;
  146. }
  147. } else {
  148. if (stuff->remainder >= stuff->divisor) {
  149. client->errorValue = (CARD32) stuff->remainder;
  150. return BadValue;
  151. }
  152. }
  153. return present_notify_msc(window, stuff->serial,
  154. stuff->target_msc, stuff->divisor, stuff->remainder);
  155. }
  156. static int
  157. proc_present_select_input (ClientPtr client)
  158. {
  159. REQUEST(xPresentSelectInputReq);
  160. WindowPtr window;
  161. int rc;
  162. REQUEST_SIZE_MATCH(xPresentSelectInputReq);
  163. LEGAL_NEW_RESOURCE(stuff->eid, client);
  164. rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
  165. if (rc != Success)
  166. return rc;
  167. if (stuff->eventMask & ~PresentAllEvents) {
  168. client->errorValue = stuff->eventMask;
  169. return BadValue;
  170. }
  171. return present_select_input(client, stuff->eid, window, stuff->eventMask);
  172. }
  173. static int
  174. proc_present_query_capabilities (ClientPtr client)
  175. {
  176. REQUEST(xPresentQueryCapabilitiesReq);
  177. xPresentQueryCapabilitiesReply rep = {
  178. .type = X_Reply,
  179. .sequenceNumber = client->sequence,
  180. .length = 0,
  181. };
  182. WindowPtr window;
  183. RRCrtcPtr crtc = NULL;
  184. int r;
  185. REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq);
  186. r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess);
  187. switch (r) {
  188. case Success:
  189. crtc = present_get_crtc(window);
  190. break;
  191. case BadWindow:
  192. VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess);
  193. break;
  194. default:
  195. return r;
  196. }
  197. rep.capabilities = present_query_capabilities(crtc);
  198. if (client->swapped) {
  199. swaps(&rep.sequenceNumber);
  200. swapl(&rep.length);
  201. swapl(&rep.capabilities);
  202. }
  203. WriteToClient(client, sizeof(rep), &rep);
  204. return Success;
  205. }
  206. int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = {
  207. proc_present_query_version, /* 0 */
  208. proc_present_pixmap, /* 1 */
  209. proc_present_notify_msc, /* 2 */
  210. proc_present_select_input, /* 3 */
  211. proc_present_query_capabilities, /* 4 */
  212. };
  213. int
  214. proc_present_dispatch(ClientPtr client)
  215. {
  216. REQUEST(xReq);
  217. if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data])
  218. return BadRequest;
  219. return (*proc_present_vector[stuff->data]) (client);
  220. }
  221. static int
  222. sproc_present_query_version(ClientPtr client)
  223. {
  224. REQUEST(xPresentQueryVersionReq);
  225. REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
  226. swaps(&stuff->length);
  227. swapl(&stuff->majorVersion);
  228. swapl(&stuff->minorVersion);
  229. return (*proc_present_vector[stuff->presentReqType]) (client);
  230. }
  231. static int
  232. sproc_present_pixmap(ClientPtr client)
  233. {
  234. REQUEST(xPresentPixmapReq);
  235. REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
  236. swaps(&stuff->length);
  237. swapl(&stuff->window);
  238. swapl(&stuff->pixmap);
  239. swapl(&stuff->valid);
  240. swapl(&stuff->update);
  241. swaps(&stuff->x_off);
  242. swaps(&stuff->y_off);
  243. swapll(&stuff->target_msc);
  244. swapll(&stuff->divisor);
  245. swapll(&stuff->remainder);
  246. swapl(&stuff->idle_fence);
  247. return (*proc_present_vector[stuff->presentReqType]) (client);
  248. }
  249. static int
  250. sproc_present_notify_msc(ClientPtr client)
  251. {
  252. REQUEST(xPresentNotifyMSCReq);
  253. REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
  254. swaps(&stuff->length);
  255. swapl(&stuff->window);
  256. swapll(&stuff->target_msc);
  257. swapll(&stuff->divisor);
  258. swapll(&stuff->remainder);
  259. return (*proc_present_vector[stuff->presentReqType]) (client);
  260. }
  261. static int
  262. sproc_present_select_input (ClientPtr client)
  263. {
  264. REQUEST(xPresentSelectInputReq);
  265. REQUEST_SIZE_MATCH(xPresentSelectInputReq);
  266. swaps(&stuff->length);
  267. swapl(&stuff->window);
  268. swapl(&stuff->eventMask);
  269. return (*proc_present_vector[stuff->presentReqType]) (client);
  270. }
  271. static int
  272. sproc_present_query_capabilities (ClientPtr client)
  273. {
  274. REQUEST(xPresentQueryCapabilitiesReq);
  275. REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq);
  276. swaps(&stuff->length);
  277. swapl(&stuff->target);
  278. return (*proc_present_vector[stuff->presentReqType]) (client);
  279. }
  280. int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = {
  281. sproc_present_query_version, /* 0 */
  282. sproc_present_pixmap, /* 1 */
  283. sproc_present_notify_msc, /* 2 */
  284. sproc_present_select_input, /* 3 */
  285. sproc_present_query_capabilities, /* 4 */
  286. };
  287. int
  288. sproc_present_dispatch(ClientPtr client)
  289. {
  290. REQUEST(xReq);
  291. if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data])
  292. return BadRequest;
  293. return (*sproc_present_vector[stuff->data]) (client);
  294. }