| @@ -1,246 +1,246 @@ | | | @@ -1,246 +1,246 @@ |
1 | /* | | 1 | /* |
2 | * Copyright © 2011 Dave Airlie | | 2 | * Copyright © 2011 Dave Airlie |
3 | * | | 3 | * |
4 | * Permission to use, copy, modify, distribute, and sell this software and its | | 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 | | 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 | | 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 | | 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 | | 8 | * that the name of the copyright holders not be used in advertising or |
9 | * publicity pertaining to distribution of the software without specific, | | 9 | * publicity pertaining to distribution of the software without specific, |
10 | * written prior permission. The copyright holders make no representations | | 10 | * written prior permission. The copyright holders make no representations |
11 | * about the suitability of this software for any purpose. It is provided "as | | 11 | * about the suitability of this software for any purpose. It is provided "as |
12 | * is" without express or implied warranty. | | 12 | * is" without express or implied warranty. |
13 | * | | 13 | * |
14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | | 14 | * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO | | 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
16 | * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR | | 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, | | 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 | | 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 | | 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
20 | * OF THIS SOFTWARE. | | 20 | * OF THIS SOFTWARE. |
21 | */ | | 21 | */ |
22 | | | 22 | |
23 | | | 23 | |
24 | #ifdef HAVE_CONFIG_H | | 24 | #ifdef HAVE_CONFIG_H |
25 | #include <config.h> | | 25 | #include <config.h> |
26 | #endif | | 26 | #endif |
27 | | | 27 | |
28 | #include <limits.h> | | 28 | #include <limits.h> |
29 | #include <stdio.h> | | 29 | #include <stdio.h> |
30 | #include <X11/Xlib.h> | | 30 | #include <X11/Xlib.h> |
31 | /* we need to be able to manipulate the Display structure on events */ | | 31 | /* we need to be able to manipulate the Display structure on events */ |
32 | #include <X11/Xlibint.h> | | 32 | #include <X11/Xlibint.h> |
33 | #include <X11/extensions/render.h> | | 33 | #include <X11/extensions/render.h> |
34 | #include <X11/extensions/Xrender.h> | | 34 | #include <X11/extensions/Xrender.h> |
35 | #include "Xrandrint.h" | | 35 | #include "Xrandrint.h" |
36 | | | 36 | |
37 | XRRProviderResources * | | 37 | XRRProviderResources * |
38 | XRRGetProviderResources(Display *dpy, Window window) | | 38 | XRRGetProviderResources(Display *dpy, Window window) |
39 | { | | 39 | { |
40 | XExtDisplayInfo *info = XRRFindDisplay(dpy); | | 40 | XExtDisplayInfo *info = XRRFindDisplay(dpy); |
41 | xRRGetProvidersReply rep; | | 41 | xRRGetProvidersReply rep; |
42 | xRRGetProvidersReq *req; | | 42 | xRRGetProvidersReq *req; |
43 | XRRProviderResources *xrpr; | | 43 | XRRProviderResources *xrpr; |
44 | long nbytes, nbytesRead; | | 44 | long nbytes, nbytesRead; |
45 | int rbytes; | | 45 | int rbytes; |
46 | | | 46 | |
47 | RRCheckExtension (dpy, info, NULL); | | 47 | RRCheckExtension (dpy, info, NULL); |
48 | | | 48 | |
49 | LockDisplay (dpy); | | 49 | LockDisplay (dpy); |
50 | | | 50 | |
51 | GetReq(RRGetProviders, req); | | 51 | GetReq(RRGetProviders, req); |
52 | req->reqType = info->codes->major_opcode; | | 52 | req->reqType = info->codes->major_opcode; |
53 | req->randrReqType = X_RRGetProviders; | | 53 | req->randrReqType = X_RRGetProviders; |
54 | req->window = window; | | 54 | req->window = window; |
55 | | | 55 | |
56 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) | | 56 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) |
57 | { | | 57 | { |
58 | UnlockDisplay (dpy); | | 58 | UnlockDisplay (dpy); |
59 | SyncHandle (); | | 59 | SyncHandle (); |
60 | return NULL; | | 60 | return NULL; |
61 | } | | 61 | } |
62 | | | 62 | |
63 | if (rep.length < INT_MAX >> 2) { | | 63 | if (rep.length < (INT_MAX >> 2)) { |
64 | nbytes = (long) rep.length << 2; | | 64 | nbytes = (long) rep.length << 2; |
65 | | | 65 | |
66 | nbytesRead = (long) (rep.nProviders * 4); | | 66 | nbytesRead = (long) (rep.nProviders * 4); |
67 | | | 67 | |
68 | rbytes = (sizeof(XRRProviderResources) + rep.nProviders * | | 68 | rbytes = (sizeof(XRRProviderResources) + rep.nProviders * |
69 | sizeof(RRProvider)); | | 69 | sizeof(RRProvider)); |
70 | xrpr = (XRRProviderResources *) Xmalloc(rbytes); | | 70 | xrpr = (XRRProviderResources *) Xmalloc(rbytes); |
71 | } else { | | 71 | } else { |
72 | nbytes = 0; | | 72 | nbytes = 0; |
73 | nbytesRead = 0; | | 73 | nbytesRead = 0; |
74 | rbytes = 0; | | 74 | rbytes = 0; |
75 | xrpr = NULL; | | 75 | xrpr = NULL; |
76 | } | | 76 | } |
77 | | | 77 | |
78 | if (xrpr == NULL) { | | 78 | if (xrpr == NULL) { |
79 | _XEatDataWords (dpy, rep.length); | | 79 | _XEatDataWords (dpy, rep.length); |
80 | UnlockDisplay (dpy); | | 80 | UnlockDisplay (dpy); |
81 | SyncHandle (); | | 81 | SyncHandle (); |
82 | return NULL; | | 82 | return NULL; |
83 | } | | 83 | } |
84 | | | 84 | |
85 | xrpr->timestamp = rep.timestamp; | | 85 | xrpr->timestamp = rep.timestamp; |
86 | xrpr->nproviders = rep.nProviders; | | 86 | xrpr->nproviders = rep.nProviders; |
87 | xrpr->providers = (RRProvider *)(xrpr + 1); | | 87 | xrpr->providers = (RRProvider *)(xrpr + 1); |
88 | | | 88 | |
89 | _XRead32(dpy, (long *) xrpr->providers, rep.nProviders << 2); | | 89 | _XRead32(dpy, (long *) xrpr->providers, rep.nProviders << 2); |
90 | | | 90 | |
91 | if (nbytes > nbytesRead) | | 91 | if (nbytes > nbytesRead) |
92 | _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); | | 92 | _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); |
93 | | | 93 | |
94 | | | 94 | |
95 | UnlockDisplay (dpy); | | 95 | UnlockDisplay (dpy); |
96 | SyncHandle(); | | 96 | SyncHandle(); |
97 | | | 97 | |
98 | return (XRRProviderResources *) xrpr; | | 98 | return (XRRProviderResources *) xrpr; |
99 | } | | 99 | } |
100 | | | 100 | |
101 | void | | 101 | void |
102 | XRRFreeProviderResources(XRRProviderResources *provider_resources) | | 102 | XRRFreeProviderResources(XRRProviderResources *provider_resources) |
103 | { | | 103 | { |
104 | free(provider_resources); | | 104 | free(provider_resources); |
105 | } | | 105 | } |
106 | | | 106 | |
107 | #define ProviderInfoExtra (SIZEOF(xRRGetProviderInfoReply) - 32) | | 107 | #define ProviderInfoExtra (SIZEOF(xRRGetProviderInfoReply) - 32) |
108 | XRRProviderInfo * | | 108 | XRRProviderInfo * |
109 | XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider) | | 109 | XRRGetProviderInfo(Display *dpy, XRRScreenResources *resources, RRProvider provider) |
110 | { | | 110 | { |
111 | XExtDisplayInfo *info = XRRFindDisplay(dpy); | | 111 | XExtDisplayInfo *info = XRRFindDisplay(dpy); |
112 | xRRGetProviderInfoReply rep; | | 112 | xRRGetProviderInfoReply rep; |
113 | xRRGetProviderInfoReq *req; | | 113 | xRRGetProviderInfoReq *req; |
114 | int nbytes, nbytesRead, rbytes; | | 114 | int nbytes, nbytesRead, rbytes; |
115 | XRRProviderInfo *xpi; | | 115 | XRRProviderInfo *xpi; |
116 | | | 116 | |
117 | RRCheckExtension (dpy, info, NULL); | | 117 | RRCheckExtension (dpy, info, NULL); |
118 | | | 118 | |
119 | LockDisplay (dpy); | | 119 | LockDisplay (dpy); |
120 | GetReq (RRGetProviderInfo, req); | | 120 | GetReq (RRGetProviderInfo, req); |
121 | req->reqType = info->codes->major_opcode; | | 121 | req->reqType = info->codes->major_opcode; |
122 | req->randrReqType = X_RRGetProviderInfo; | | 122 | req->randrReqType = X_RRGetProviderInfo; |
123 | req->provider = provider; | | 123 | req->provider = provider; |
124 | req->configTimestamp = resources->configTimestamp; | | 124 | req->configTimestamp = resources->configTimestamp; |
125 | | | 125 | |
126 | if (!_XReply (dpy, (xReply *) &rep, ProviderInfoExtra >> 2, xFalse)) | | 126 | if (!_XReply (dpy, (xReply *) &rep, ProviderInfoExtra >> 2, xFalse)) |
127 | { | | 127 | { |
128 | UnlockDisplay (dpy); | | 128 | UnlockDisplay (dpy); |
129 | SyncHandle (); | | 129 | SyncHandle (); |
130 | return NULL; | | 130 | return NULL; |
131 | } | | 131 | } |
132 | | | 132 | |
133 | if (rep.length > INT_MAX >> 2 || rep.length < ProviderInfoExtra >> 2) | | 133 | if (rep.length > (INT_MAX >> 2) || rep.length < (ProviderInfoExtra >> 2)) |
134 | { | | 134 | { |
135 | if (rep.length < ProviderInfoExtra >> 2) | | 135 | if (rep.length < (ProviderInfoExtra >> 2)) |
136 | _XEatDataWords (dpy, rep.length); | | 136 | _XEatDataWords (dpy, rep.length); |
137 | else | | 137 | else |
138 | _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2)); | | 138 | _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2)); |
139 | UnlockDisplay (dpy); | | 139 | UnlockDisplay (dpy); |
140 | SyncHandle (); | | 140 | SyncHandle (); |
141 | return NULL; | | 141 | return NULL; |
142 | } | | 142 | } |
143 | | | 143 | |
144 | nbytes = ((long) rep.length << 2) - ProviderInfoExtra; | | 144 | nbytes = ((long) rep.length << 2) - ProviderInfoExtra; |
145 | | | 145 | |
146 | nbytesRead = (long)(rep.nCrtcs * 4 + | | 146 | nbytesRead = (long)(rep.nCrtcs * 4 + |
147 | rep.nOutputs * 4 + | | 147 | rep.nOutputs * 4 + |
148 | rep.nAssociatedProviders * 8 + | | 148 | rep.nAssociatedProviders * 8 + |
149 | ((rep.nameLength + 3) & ~3)); | | 149 | ((rep.nameLength + 3) & ~3)); |
150 | | | 150 | |
151 | rbytes = (sizeof(XRRProviderInfo) + | | 151 | rbytes = (sizeof(XRRProviderInfo) + |
152 | rep.nCrtcs * sizeof(RRCrtc) + | | 152 | rep.nCrtcs * sizeof(RRCrtc) + |
153 | rep.nOutputs * sizeof(RROutput) + | | 153 | rep.nOutputs * sizeof(RROutput) + |
154 | rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+ | | 154 | rep.nAssociatedProviders * (sizeof(RRProvider) + sizeof(unsigned int))+ |
155 | rep.nameLength + 1); | | 155 | rep.nameLength + 1); |
156 | | | 156 | |
157 | xpi = (XRRProviderInfo *)Xmalloc(rbytes); | | 157 | xpi = (XRRProviderInfo *)Xmalloc(rbytes); |
158 | if (xpi == NULL) { | | 158 | if (xpi == NULL) { |
159 | _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2)); | | 159 | _XEatDataWords (dpy, rep.length - (ProviderInfoExtra >> 2)); |
160 | UnlockDisplay (dpy); | | 160 | UnlockDisplay (dpy); |
161 | SyncHandle (); | | 161 | SyncHandle (); |
162 | return NULL; | | 162 | return NULL; |
163 | } | | 163 | } |
164 | | | 164 | |
165 | xpi->capabilities = rep.capabilities; | | 165 | xpi->capabilities = rep.capabilities; |
166 | xpi->ncrtcs = rep.nCrtcs; | | 166 | xpi->ncrtcs = rep.nCrtcs; |
167 | xpi->noutputs = rep.nOutputs; | | 167 | xpi->noutputs = rep.nOutputs; |
168 | xpi->nassociatedproviders = rep.nAssociatedProviders; | | 168 | xpi->nassociatedproviders = rep.nAssociatedProviders; |
169 | xpi->crtcs = (RRCrtc *)(xpi + 1); | | 169 | xpi->crtcs = (RRCrtc *)(xpi + 1); |
170 | xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs); | | 170 | xpi->outputs = (RROutput *)(xpi->crtcs + rep.nCrtcs); |
171 | xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs); | | 171 | xpi->associated_providers = (RRProvider *)(xpi->outputs + rep.nOutputs); |
172 | xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders); | | 172 | xpi->associated_capability = (unsigned int *)(xpi->associated_providers + rep.nAssociatedProviders); |
173 | xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders); | | 173 | xpi->name = (char *)(xpi->associated_capability + rep.nAssociatedProviders); |
174 | | | 174 | |
175 | _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2); | | 175 | _XRead32(dpy, (long *) xpi->crtcs, rep.nCrtcs << 2); |
176 | _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2); | | 176 | _XRead32(dpy, (long *) xpi->outputs, rep.nOutputs << 2); |
177 | | | 177 | |
178 | _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2); | | 178 | _XRead32(dpy, (long *) xpi->associated_providers, rep.nAssociatedProviders << 2); |
179 | | | 179 | |
180 | /* | | 180 | /* |
181 | * _XRead32 reads a series of 32-bit values from the protocol and writes | | 181 | * _XRead32 reads a series of 32-bit values from the protocol and writes |
182 | * them out as a series of "long int" values, but associated_capability | | 182 | * them out as a series of "long int" values, but associated_capability |
183 | * is defined as unsigned int *, so that won't work for this array. | | 183 | * is defined as unsigned int *, so that won't work for this array. |
184 | * Instead we assume for now that "unsigned int" is also 32-bits, so | | 184 | * Instead we assume for now that "unsigned int" is also 32-bits, so |
185 | * the values can be read without any conversion. | | 185 | * the values can be read without any conversion. |
186 | */ | | 186 | */ |
187 | _XRead(dpy, (char *) xpi->associated_capability, | | 187 | _XRead(dpy, (char *) xpi->associated_capability, |
188 | rep.nAssociatedProviders << 2); | | 188 | rep.nAssociatedProviders << 2); |
189 | | | 189 | |
190 | _XReadPad(dpy, xpi->name, rep.nameLength); | | 190 | _XReadPad(dpy, xpi->name, rep.nameLength); |
191 | xpi->name[rep.nameLength] = '\0'; | | 191 | xpi->name[rep.nameLength] = '\0'; |
192 | | | 192 | |
193 | /* | | 193 | /* |
194 | * Skip any extra data | | 194 | * Skip any extra data |
195 | */ | | 195 | */ |
196 | if (nbytes > nbytesRead) | | 196 | if (nbytes > nbytesRead) |
197 | _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); | | 197 | _XEatData (dpy, (unsigned long) (nbytes - nbytesRead)); |
198 | | | 198 | |
199 | UnlockDisplay (dpy); | | 199 | UnlockDisplay (dpy); |
200 | SyncHandle (); | | 200 | SyncHandle (); |
201 | return (XRRProviderInfo *) xpi; | | 201 | return (XRRProviderInfo *) xpi; |
202 | } | | 202 | } |
203 | | | 203 | |
204 | void | | 204 | void |
205 | XRRFreeProviderInfo(XRRProviderInfo *provider) | | 205 | XRRFreeProviderInfo(XRRProviderInfo *provider) |
206 | { | | 206 | { |
207 | free(provider); | | 207 | free(provider); |
208 | } | | 208 | } |
209 | | | 209 | |
210 | int | | 210 | int |
211 | XRRSetProviderOutputSource(Display *dpy, XID provider, | | 211 | XRRSetProviderOutputSource(Display *dpy, XID provider, |
212 | XID source_provider) | | 212 | XID source_provider) |
213 | { | | 213 | { |
214 | XExtDisplayInfo *info = XRRFindDisplay(dpy); | | 214 | XExtDisplayInfo *info = XRRFindDisplay(dpy); |
215 | xRRSetProviderOutputSourceReq *req; | | 215 | xRRSetProviderOutputSourceReq *req; |
216 | | | 216 | |
217 | RRCheckExtension (dpy, info, 0); | | 217 | RRCheckExtension (dpy, info, 0); |
218 | LockDisplay (dpy); | | 218 | LockDisplay (dpy); |
219 | GetReq (RRSetProviderOutputSource, req); | | 219 | GetReq (RRSetProviderOutputSource, req); |
220 | req->reqType = info->codes->major_opcode; | | 220 | req->reqType = info->codes->major_opcode; |
221 | req->randrReqType = X_RRSetProviderOutputSource; | | 221 | req->randrReqType = X_RRSetProviderOutputSource; |
222 | req->provider = provider; | | 222 | req->provider = provider; |
223 | req->source_provider = source_provider; | | 223 | req->source_provider = source_provider; |
224 | UnlockDisplay (dpy); | | 224 | UnlockDisplay (dpy); |
225 | SyncHandle (); | | 225 | SyncHandle (); |
226 | return 0; | | 226 | return 0; |
227 | } | | 227 | } |
228 | | | 228 | |
229 | int | | 229 | int |
230 | XRRSetProviderOffloadSink(Display *dpy, XID provider, | | 230 | XRRSetProviderOffloadSink(Display *dpy, XID provider, |
231 | XID sink_provider) | | 231 | XID sink_provider) |
232 | { | | 232 | { |
233 | XExtDisplayInfo *info = XRRFindDisplay(dpy); | | 233 | XExtDisplayInfo *info = XRRFindDisplay(dpy); |
234 | xRRSetProviderOffloadSinkReq *req; | | 234 | xRRSetProviderOffloadSinkReq *req; |
235 | | | 235 | |
236 | RRCheckExtension (dpy, info, 0); | | 236 | RRCheckExtension (dpy, info, 0); |
237 | LockDisplay (dpy); | | 237 | LockDisplay (dpy); |
238 | GetReq (RRSetProviderOffloadSink, req); | | 238 | GetReq (RRSetProviderOffloadSink, req); |
239 | req->reqType = info->codes->major_opcode; | | 239 | req->reqType = info->codes->major_opcode; |
240 | req->randrReqType = X_RRSetProviderOffloadSink; | | 240 | req->randrReqType = X_RRSetProviderOffloadSink; |
241 | req->provider = provider; | | 241 | req->provider = provider; |
242 | req->sink_provider = sink_provider; | | 242 | req->sink_provider = sink_provider; |
243 | UnlockDisplay (dpy); | | 243 | UnlockDisplay (dpy); |
244 | SyncHandle (); | | 244 | SyncHandle (); |
245 | return 0; | | 245 | return 0; |
246 | } | | 246 | } |