xref: /OK3568_Linux_fs/external/xserver/present/present_request.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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
proc_present_query_version(ClientPtr client)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     /* 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 
85 static int
proc_present_pixmap(ClientPtr client)86 proc_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), &notifies);
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 
159 static int
proc_present_notify_msc(ClientPtr client)160 proc_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 
190 static int
proc_present_select_input(ClientPtr client)191 proc_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 
210 static int
proc_present_query_capabilities(ClientPtr client)211 proc_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 
247 static 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 
255 int
proc_present_dispatch(ClientPtr client)256 proc_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 
264 static int _X_COLD
sproc_present_query_version(ClientPtr client)265 sproc_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 
276 static int _X_COLD
sproc_present_pixmap(ClientPtr client)277 sproc_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 
296 static int _X_COLD
sproc_present_notify_msc(ClientPtr client)297 sproc_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 
310 static int _X_COLD
sproc_present_select_input(ClientPtr client)311 sproc_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 
322 static int _X_COLD
sproc_present_query_capabilities(ClientPtr client)323 sproc_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 
332 static 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 
340 int _X_COLD
sproc_present_dispatch(ClientPtr client)341 sproc_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