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