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