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