xref: /OK3568_Linux_fs/external/xserver/present/present_request.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright © 2013 Keith Packard
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Permission to use, copy, modify, distribute, and sell this software and its
5*4882a593Smuzhiyun  * documentation for any purpose is hereby granted without fee, provided that
6*4882a593Smuzhiyun  * the above copyright notice appear in all copies and that both that copyright
7*4882a593Smuzhiyun  * notice and this permission notice appear in supporting documentation, and
8*4882a593Smuzhiyun  * that the name of the copyright holders not be used in advertising or
9*4882a593Smuzhiyun  * publicity pertaining to distribution of the software without specific,
10*4882a593Smuzhiyun  * written prior permission.  The copyright holders make no representations
11*4882a593Smuzhiyun  * about the suitability of this software for any purpose.  It is provided "as
12*4882a593Smuzhiyun  * is" without express or implied warranty.
13*4882a593Smuzhiyun  *
14*4882a593Smuzhiyun  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15*4882a593Smuzhiyun  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16*4882a593Smuzhiyun  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17*4882a593Smuzhiyun  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18*4882a593Smuzhiyun  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19*4882a593Smuzhiyun  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20*4882a593Smuzhiyun  * OF THIS SOFTWARE.
21*4882a593Smuzhiyun  */
22*4882a593Smuzhiyun 
23*4882a593Smuzhiyun #ifdef HAVE_XORG_CONFIG_H
24*4882a593Smuzhiyun #include <xorg-config.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include "present_priv.h"
28*4882a593Smuzhiyun #include "randrstr.h"
29*4882a593Smuzhiyun #include <protocol-versions.h>
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static int
proc_present_query_version(ClientPtr client)32*4882a593Smuzhiyun proc_present_query_version(ClientPtr client)
33*4882a593Smuzhiyun {
34*4882a593Smuzhiyun     REQUEST(xPresentQueryVersionReq);
35*4882a593Smuzhiyun     xPresentQueryVersionReply rep = {
36*4882a593Smuzhiyun         .type = X_Reply,
37*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
38*4882a593Smuzhiyun         .length = 0,
39*4882a593Smuzhiyun         .majorVersion = SERVER_PRESENT_MAJOR_VERSION,
40*4882a593Smuzhiyun         .minorVersion = SERVER_PRESENT_MINOR_VERSION
41*4882a593Smuzhiyun     };
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
44*4882a593Smuzhiyun     /* From presentproto:
45*4882a593Smuzhiyun      *
46*4882a593Smuzhiyun      * The client sends the highest supported version to the server
47*4882a593Smuzhiyun      * and the server sends the highest version it supports, but no
48*4882a593Smuzhiyun      * higher than the requested version.
49*4882a593Smuzhiyun      */
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun     if (rep.majorVersion > stuff->majorVersion ||
52*4882a593Smuzhiyun         rep.minorVersion > stuff->minorVersion) {
53*4882a593Smuzhiyun         rep.majorVersion = stuff->majorVersion;
54*4882a593Smuzhiyun         rep.minorVersion = stuff->minorVersion;
55*4882a593Smuzhiyun     }
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun     if (client->swapped) {
58*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
59*4882a593Smuzhiyun         swapl(&rep.length);
60*4882a593Smuzhiyun         swapl(&rep.majorVersion);
61*4882a593Smuzhiyun         swapl(&rep.minorVersion);
62*4882a593Smuzhiyun     }
63*4882a593Smuzhiyun     WriteToClient(client, sizeof(rep), &rep);
64*4882a593Smuzhiyun     return Success;
65*4882a593Smuzhiyun }
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun #define VERIFY_FENCE_OR_NONE(fence_ptr, fence_id, client, access) do {  \
68*4882a593Smuzhiyun         if ((fence_id) == None)                                         \
69*4882a593Smuzhiyun             (fence_ptr) = NULL;                                         \
70*4882a593Smuzhiyun         else {                                                          \
71*4882a593Smuzhiyun             int __rc__ = SyncVerifyFence(&fence_ptr, fence_id, client, access); \
72*4882a593Smuzhiyun             if (__rc__ != Success)                                      \
73*4882a593Smuzhiyun                 return __rc__;                                          \
74*4882a593Smuzhiyun         }                                                               \
75*4882a593Smuzhiyun     } while (0)
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define VERIFY_CRTC_OR_NONE(crtc_ptr, crtc_id, client, access) do {     \
78*4882a593Smuzhiyun         if ((crtc_id) == None)                                          \
79*4882a593Smuzhiyun             (crtc_ptr) = NULL;                                          \
80*4882a593Smuzhiyun         else {                                                          \
81*4882a593Smuzhiyun             VERIFY_RR_CRTC(crtc_id, crtc_ptr, access);                  \
82*4882a593Smuzhiyun         }                                                               \
83*4882a593Smuzhiyun     } while (0)
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun static int
proc_present_pixmap(ClientPtr client)86*4882a593Smuzhiyun proc_present_pixmap(ClientPtr client)
87*4882a593Smuzhiyun {
88*4882a593Smuzhiyun     REQUEST(xPresentPixmapReq);
89*4882a593Smuzhiyun     WindowPtr           window;
90*4882a593Smuzhiyun     PixmapPtr           pixmap;
91*4882a593Smuzhiyun     RegionPtr           valid = NULL;
92*4882a593Smuzhiyun     RegionPtr           update = NULL;
93*4882a593Smuzhiyun     SyncFence           *wait_fence;
94*4882a593Smuzhiyun     SyncFence           *idle_fence;
95*4882a593Smuzhiyun     RRCrtcPtr           target_crtc;
96*4882a593Smuzhiyun     int                 ret;
97*4882a593Smuzhiyun     int                 nnotifies;
98*4882a593Smuzhiyun     present_notify_ptr  notifies = NULL;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
101*4882a593Smuzhiyun     ret = dixLookupWindow(&window, stuff->window, client, DixWriteAccess);
102*4882a593Smuzhiyun     if (ret != Success)
103*4882a593Smuzhiyun         return ret;
104*4882a593Smuzhiyun     ret = dixLookupResourceByType((void **) &pixmap, stuff->pixmap, RT_PIXMAP, client, DixReadAccess);
105*4882a593Smuzhiyun     if (ret != Success)
106*4882a593Smuzhiyun         return ret;
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun     if (window->drawable.depth != pixmap->drawable.depth)
109*4882a593Smuzhiyun         return BadMatch;
110*4882a593Smuzhiyun 
111*4882a593Smuzhiyun     VERIFY_REGION_OR_NONE(valid, stuff->valid, client, DixReadAccess);
112*4882a593Smuzhiyun     VERIFY_REGION_OR_NONE(update, stuff->update, client, DixReadAccess);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun     VERIFY_CRTC_OR_NONE(target_crtc, stuff->target_crtc, client, DixReadAccess);
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun     VERIFY_FENCE_OR_NONE(wait_fence, stuff->wait_fence, client, DixReadAccess);
117*4882a593Smuzhiyun     VERIFY_FENCE_OR_NONE(idle_fence, stuff->idle_fence, client, DixWriteAccess);
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun     if (stuff->options & ~(PresentAllOptions)) {
120*4882a593Smuzhiyun         client->errorValue = stuff->options;
121*4882a593Smuzhiyun         return BadValue;
122*4882a593Smuzhiyun     }
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun     /*
125*4882a593Smuzhiyun      * Check to see if remainder is sane
126*4882a593Smuzhiyun      */
127*4882a593Smuzhiyun     if (stuff->divisor == 0) {
128*4882a593Smuzhiyun         if (stuff->remainder != 0) {
129*4882a593Smuzhiyun             client->errorValue = (CARD32) stuff->remainder;
130*4882a593Smuzhiyun             return BadValue;
131*4882a593Smuzhiyun         }
132*4882a593Smuzhiyun     } else {
133*4882a593Smuzhiyun         if (stuff->remainder >= stuff->divisor) {
134*4882a593Smuzhiyun             client->errorValue = (CARD32) stuff->remainder;
135*4882a593Smuzhiyun             return BadValue;
136*4882a593Smuzhiyun         }
137*4882a593Smuzhiyun     }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun     nnotifies = (client->req_len << 2) - sizeof (xPresentPixmapReq);
140*4882a593Smuzhiyun     if (nnotifies % sizeof (xPresentNotify))
141*4882a593Smuzhiyun         return BadLength;
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun     nnotifies /= sizeof (xPresentNotify);
144*4882a593Smuzhiyun     if (nnotifies) {
145*4882a593Smuzhiyun         ret = present_create_notifies(client, nnotifies, (xPresentNotify *) (stuff + 1), &notifies);
146*4882a593Smuzhiyun         if (ret != Success)
147*4882a593Smuzhiyun             return ret;
148*4882a593Smuzhiyun     }
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun     ret = present_pixmap(window, pixmap, stuff->serial, valid, update,
151*4882a593Smuzhiyun                          stuff->x_off, stuff->y_off, target_crtc,
152*4882a593Smuzhiyun                          wait_fence, idle_fence, stuff->options,
153*4882a593Smuzhiyun                          stuff->target_msc, stuff->divisor, stuff->remainder, notifies, nnotifies);
154*4882a593Smuzhiyun     if (ret != Success)
155*4882a593Smuzhiyun         present_destroy_notifies(notifies, nnotifies);
156*4882a593Smuzhiyun     return ret;
157*4882a593Smuzhiyun }
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun static int
proc_present_notify_msc(ClientPtr client)160*4882a593Smuzhiyun proc_present_notify_msc(ClientPtr client)
161*4882a593Smuzhiyun {
162*4882a593Smuzhiyun     REQUEST(xPresentNotifyMSCReq);
163*4882a593Smuzhiyun     WindowPtr   window;
164*4882a593Smuzhiyun     int         rc;
165*4882a593Smuzhiyun 
166*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
167*4882a593Smuzhiyun     rc = dixLookupWindow(&window, stuff->window, client, DixReadAccess);
168*4882a593Smuzhiyun     if (rc != Success)
169*4882a593Smuzhiyun         return rc;
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun     /*
172*4882a593Smuzhiyun      * Check to see if remainder is sane
173*4882a593Smuzhiyun      */
174*4882a593Smuzhiyun     if (stuff->divisor == 0) {
175*4882a593Smuzhiyun         if (stuff->remainder != 0) {
176*4882a593Smuzhiyun             client->errorValue = (CARD32) stuff->remainder;
177*4882a593Smuzhiyun             return BadValue;
178*4882a593Smuzhiyun         }
179*4882a593Smuzhiyun     } else {
180*4882a593Smuzhiyun         if (stuff->remainder >= stuff->divisor) {
181*4882a593Smuzhiyun             client->errorValue = (CARD32) stuff->remainder;
182*4882a593Smuzhiyun             return BadValue;
183*4882a593Smuzhiyun         }
184*4882a593Smuzhiyun     }
185*4882a593Smuzhiyun 
186*4882a593Smuzhiyun     return present_notify_msc(window, stuff->serial,
187*4882a593Smuzhiyun                               stuff->target_msc, stuff->divisor, stuff->remainder);
188*4882a593Smuzhiyun }
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun static int
proc_present_select_input(ClientPtr client)191*4882a593Smuzhiyun proc_present_select_input (ClientPtr client)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun     REQUEST(xPresentSelectInputReq);
194*4882a593Smuzhiyun     WindowPtr window;
195*4882a593Smuzhiyun     int rc;
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentSelectInputReq);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun     rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
200*4882a593Smuzhiyun     if (rc != Success)
201*4882a593Smuzhiyun         return rc;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun     if (stuff->eventMask & ~PresentAllEvents) {
204*4882a593Smuzhiyun         client->errorValue = stuff->eventMask;
205*4882a593Smuzhiyun         return BadValue;
206*4882a593Smuzhiyun     }
207*4882a593Smuzhiyun     return present_select_input(client, stuff->eid, window, stuff->eventMask);
208*4882a593Smuzhiyun }
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun static int
proc_present_query_capabilities(ClientPtr client)211*4882a593Smuzhiyun proc_present_query_capabilities (ClientPtr client)
212*4882a593Smuzhiyun {
213*4882a593Smuzhiyun     REQUEST(xPresentQueryCapabilitiesReq);
214*4882a593Smuzhiyun     xPresentQueryCapabilitiesReply rep = {
215*4882a593Smuzhiyun         .type = X_Reply,
216*4882a593Smuzhiyun         .sequenceNumber = client->sequence,
217*4882a593Smuzhiyun         .length = 0,
218*4882a593Smuzhiyun     };
219*4882a593Smuzhiyun     WindowPtr   window;
220*4882a593Smuzhiyun     RRCrtcPtr   crtc = NULL;
221*4882a593Smuzhiyun     int         r;
222*4882a593Smuzhiyun 
223*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq);
224*4882a593Smuzhiyun     r = dixLookupWindow(&window, stuff->target, client, DixGetAttrAccess);
225*4882a593Smuzhiyun     switch (r) {
226*4882a593Smuzhiyun     case Success:
227*4882a593Smuzhiyun         crtc = present_get_crtc(window);
228*4882a593Smuzhiyun         break;
229*4882a593Smuzhiyun     case BadWindow:
230*4882a593Smuzhiyun         VERIFY_RR_CRTC(stuff->target, crtc, DixGetAttrAccess);
231*4882a593Smuzhiyun         break;
232*4882a593Smuzhiyun     default:
233*4882a593Smuzhiyun         return r;
234*4882a593Smuzhiyun     }
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun     rep.capabilities = present_query_capabilities(crtc);
237*4882a593Smuzhiyun 
238*4882a593Smuzhiyun     if (client->swapped) {
239*4882a593Smuzhiyun         swaps(&rep.sequenceNumber);
240*4882a593Smuzhiyun         swapl(&rep.length);
241*4882a593Smuzhiyun         swapl(&rep.capabilities);
242*4882a593Smuzhiyun     }
243*4882a593Smuzhiyun     WriteToClient(client, sizeof(rep), &rep);
244*4882a593Smuzhiyun     return Success;
245*4882a593Smuzhiyun }
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun static int (*proc_present_vector[PresentNumberRequests]) (ClientPtr) = {
248*4882a593Smuzhiyun     proc_present_query_version,            /* 0 */
249*4882a593Smuzhiyun     proc_present_pixmap,                   /* 1 */
250*4882a593Smuzhiyun     proc_present_notify_msc,               /* 2 */
251*4882a593Smuzhiyun     proc_present_select_input,             /* 3 */
252*4882a593Smuzhiyun     proc_present_query_capabilities,       /* 4 */
253*4882a593Smuzhiyun };
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun int
proc_present_dispatch(ClientPtr client)256*4882a593Smuzhiyun proc_present_dispatch(ClientPtr client)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun     REQUEST(xReq);
259*4882a593Smuzhiyun     if (stuff->data >= PresentNumberRequests || !proc_present_vector[stuff->data])
260*4882a593Smuzhiyun         return BadRequest;
261*4882a593Smuzhiyun     return (*proc_present_vector[stuff->data]) (client);
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun static int _X_COLD
sproc_present_query_version(ClientPtr client)265*4882a593Smuzhiyun sproc_present_query_version(ClientPtr client)
266*4882a593Smuzhiyun {
267*4882a593Smuzhiyun     REQUEST(xPresentQueryVersionReq);
268*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentQueryVersionReq);
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun     swaps(&stuff->length);
271*4882a593Smuzhiyun     swapl(&stuff->majorVersion);
272*4882a593Smuzhiyun     swapl(&stuff->minorVersion);
273*4882a593Smuzhiyun     return (*proc_present_vector[stuff->presentReqType]) (client);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun 
276*4882a593Smuzhiyun static int _X_COLD
sproc_present_pixmap(ClientPtr client)277*4882a593Smuzhiyun sproc_present_pixmap(ClientPtr client)
278*4882a593Smuzhiyun {
279*4882a593Smuzhiyun     REQUEST(xPresentPixmapReq);
280*4882a593Smuzhiyun     REQUEST_AT_LEAST_SIZE(xPresentPixmapReq);
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun     swaps(&stuff->length);
283*4882a593Smuzhiyun     swapl(&stuff->window);
284*4882a593Smuzhiyun     swapl(&stuff->pixmap);
285*4882a593Smuzhiyun     swapl(&stuff->valid);
286*4882a593Smuzhiyun     swapl(&stuff->update);
287*4882a593Smuzhiyun     swaps(&stuff->x_off);
288*4882a593Smuzhiyun     swaps(&stuff->y_off);
289*4882a593Smuzhiyun     swapll(&stuff->target_msc);
290*4882a593Smuzhiyun     swapll(&stuff->divisor);
291*4882a593Smuzhiyun     swapll(&stuff->remainder);
292*4882a593Smuzhiyun     swapl(&stuff->idle_fence);
293*4882a593Smuzhiyun     return (*proc_present_vector[stuff->presentReqType]) (client);
294*4882a593Smuzhiyun }
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun static int _X_COLD
sproc_present_notify_msc(ClientPtr client)297*4882a593Smuzhiyun sproc_present_notify_msc(ClientPtr client)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun     REQUEST(xPresentNotifyMSCReq);
300*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentNotifyMSCReq);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun     swaps(&stuff->length);
303*4882a593Smuzhiyun     swapl(&stuff->window);
304*4882a593Smuzhiyun     swapll(&stuff->target_msc);
305*4882a593Smuzhiyun     swapll(&stuff->divisor);
306*4882a593Smuzhiyun     swapll(&stuff->remainder);
307*4882a593Smuzhiyun     return (*proc_present_vector[stuff->presentReqType]) (client);
308*4882a593Smuzhiyun }
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun static int _X_COLD
sproc_present_select_input(ClientPtr client)311*4882a593Smuzhiyun sproc_present_select_input (ClientPtr client)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun     REQUEST(xPresentSelectInputReq);
314*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentSelectInputReq);
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun     swaps(&stuff->length);
317*4882a593Smuzhiyun     swapl(&stuff->window);
318*4882a593Smuzhiyun     swapl(&stuff->eventMask);
319*4882a593Smuzhiyun     return (*proc_present_vector[stuff->presentReqType]) (client);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun 
322*4882a593Smuzhiyun static int _X_COLD
sproc_present_query_capabilities(ClientPtr client)323*4882a593Smuzhiyun sproc_present_query_capabilities (ClientPtr client)
324*4882a593Smuzhiyun {
325*4882a593Smuzhiyun     REQUEST(xPresentQueryCapabilitiesReq);
326*4882a593Smuzhiyun     REQUEST_SIZE_MATCH(xPresentQueryCapabilitiesReq);
327*4882a593Smuzhiyun     swaps(&stuff->length);
328*4882a593Smuzhiyun     swapl(&stuff->target);
329*4882a593Smuzhiyun     return (*proc_present_vector[stuff->presentReqType]) (client);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun static int (*sproc_present_vector[PresentNumberRequests]) (ClientPtr) = {
333*4882a593Smuzhiyun     sproc_present_query_version,           /* 0 */
334*4882a593Smuzhiyun     sproc_present_pixmap,                  /* 1 */
335*4882a593Smuzhiyun     sproc_present_notify_msc,              /* 2 */
336*4882a593Smuzhiyun     sproc_present_select_input,            /* 3 */
337*4882a593Smuzhiyun     sproc_present_query_capabilities,      /* 4 */
338*4882a593Smuzhiyun };
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun int _X_COLD
sproc_present_dispatch(ClientPtr client)341*4882a593Smuzhiyun sproc_present_dispatch(ClientPtr client)
342*4882a593Smuzhiyun {
343*4882a593Smuzhiyun     REQUEST(xReq);
344*4882a593Smuzhiyun     if (stuff->data >= PresentNumberRequests || !sproc_present_vector[stuff->data])
345*4882a593Smuzhiyun         return BadRequest;
346*4882a593Smuzhiyun     return (*sproc_present_vector[stuff->data]) (client);
347*4882a593Smuzhiyun }
348