Add patch that contain Mali fixes.
[deb_xorg-server.git] / randr / rrprovider.c
1 /*
2 * Copyright © 2012 Red Hat Inc.
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 * Authors: Dave Airlie
23 */
24
25 #include "randrstr.h"
26 #include "swaprep.h"
27
28 RESTYPE RRProviderType;
29
30 /*
31 * Initialize provider type error value
32 */
33 void
34 RRProviderInitErrorValue(void)
35 {
36 SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
37 }
38
39 #define ADD_PROVIDER(_pScreen) do { \
40 pScrPriv = rrGetScrPriv((_pScreen)); \
41 if (pScrPriv->provider) { \
42 providers[count_providers] = pScrPriv->provider->id; \
43 if (client->swapped) \
44 swapl(&providers[count_providers]); \
45 count_providers++; \
46 } \
47 } while(0)
48
49 int
50 ProcRRGetProviders (ClientPtr client)
51 {
52 REQUEST(xRRGetProvidersReq);
53 xRRGetProvidersReply rep;
54 WindowPtr pWin;
55 ScreenPtr pScreen;
56 rrScrPrivPtr pScrPriv;
57 int rc;
58 CARD8 *extra;
59 unsigned int extraLen;
60 RRProvider *providers;
61 int total_providers = 0, count_providers = 0;
62 ScreenPtr iter;
63
64 REQUEST_SIZE_MATCH(xRRGetProvidersReq);
65 rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
66 if (rc != Success)
67 return rc;
68
69 pScreen = pWin->drawable.pScreen;
70
71 pScrPriv = rrGetScrPriv(pScreen);
72
73 if (pScrPriv->provider)
74 total_providers++;
75 xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
76 pScrPriv = rrGetScrPriv(iter);
77 total_providers += pScrPriv->provider ? 1 : 0;
78 }
79 xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
80 pScrPriv = rrGetScrPriv(iter);
81 total_providers += pScrPriv->provider ? 1 : 0;
82 }
83 xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
84 pScrPriv = rrGetScrPriv(iter);
85 total_providers += pScrPriv->provider ? 1 : 0;
86 }
87
88 pScrPriv = rrGetScrPriv(pScreen);
89
90 if (!pScrPriv)
91 {
92 rep = (xRRGetProvidersReply) {
93 .type = X_Reply,
94 .sequenceNumber = client->sequence,
95 .length = 0,
96 .timestamp = currentTime.milliseconds,
97 .nProviders = 0
98 };
99 extra = NULL;
100 extraLen = 0;
101 } else {
102 rep = (xRRGetProvidersReply) {
103 .type = X_Reply,
104 .sequenceNumber = client->sequence,
105 .timestamp = pScrPriv->lastSetTime.milliseconds,
106 .nProviders = total_providers,
107 .length = total_providers
108 };
109 extraLen = rep.length << 2;
110 if (extraLen) {
111 extra = malloc(extraLen);
112 if (!extra)
113 return BadAlloc;
114 } else
115 extra = NULL;
116
117 providers = (RRProvider *)extra;
118 ADD_PROVIDER(pScreen);
119 xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
120 ADD_PROVIDER(iter);
121 }
122 xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
123 ADD_PROVIDER(iter);
124 }
125 xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
126 ADD_PROVIDER(iter);
127 }
128 }
129
130 if (client->swapped) {
131 swaps(&rep.sequenceNumber);
132 swapl(&rep.length);
133 swapl(&rep.timestamp);
134 swaps(&rep.nProviders);
135 }
136 WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep);
137 if (extraLen)
138 {
139 WriteToClient (client, extraLen, (char *) extra);
140 free(extra);
141 }
142 return Success;
143 }
144
145 int
146 ProcRRGetProviderInfo (ClientPtr client)
147 {
148 REQUEST(xRRGetProviderInfoReq);
149 xRRGetProviderInfoReply rep;
150 rrScrPrivPtr pScrPriv, pScrProvPriv;
151 RRProviderPtr provider;
152 ScreenPtr pScreen;
153 CARD8 *extra;
154 unsigned int extraLen = 0;
155 RRCrtc *crtcs;
156 RROutput *outputs;
157 int i;
158 char *name;
159 ScreenPtr provscreen;
160 RRProvider *providers;
161 uint32_t *prov_cap;
162
163 REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
164 VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
165
166 pScreen = provider->pScreen;
167 pScrPriv = rrGetScrPriv(pScreen);
168
169 rep = (xRRGetProviderInfoReply) {
170 .type = X_Reply,
171 .status = RRSetConfigSuccess,
172 .sequenceNumber = client->sequence,
173 .length = 0,
174 .capabilities = provider->capabilities,
175 .nameLength = provider->nameLength,
176 .timestamp = pScrPriv->lastSetTime.milliseconds,
177 .nCrtcs = pScrPriv->numCrtcs,
178 .nOutputs = pScrPriv->numOutputs,
179 .nAssociatedProviders = 0
180 };
181
182 /* count associated providers */
183 if (provider->offload_sink)
184 rep.nAssociatedProviders++;
185 if (provider->output_source)
186 rep.nAssociatedProviders++;
187 xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head)
188 rep.nAssociatedProviders++;
189 xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head)
190 rep.nAssociatedProviders++;
191
192 rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
193 (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
194
195 extraLen = rep.length << 2;
196 if (extraLen) {
197 extra = malloc(extraLen);
198 if (!extra)
199 return BadAlloc;
200 }
201 else
202 extra = NULL;
203
204 crtcs = (RRCrtc *)extra;
205 outputs = (RROutput *)(crtcs + rep.nCrtcs);
206 providers = (RRProvider *)(outputs + rep.nOutputs);
207 prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders);
208 name = (char *)(prov_cap + rep.nAssociatedProviders);
209
210 for (i = 0; i < pScrPriv->numCrtcs; i++) {
211 crtcs[i] = pScrPriv->crtcs[i]->id;
212 if (client->swapped)
213 swapl(&crtcs[i]);
214 }
215
216 for (i = 0; i < pScrPriv->numOutputs; i++) {
217 outputs[i] = pScrPriv->outputs[i]->id;
218 if (client->swapped)
219 swapl(&outputs[i]);
220 }
221
222 i = 0;
223 if (provider->offload_sink) {
224 providers[i] = provider->offload_sink->id;
225 if (client->swapped)
226 swapl(&providers[i]);
227 prov_cap[i] = RR_Capability_SinkOffload;
228 if (client->swapped)
229 swapl(&prov_cap[i]);
230 i++;
231 }
232 if (provider->output_source) {
233 providers[i] = provider->output_source->id;
234 if (client->swapped)
235 swapl(&providers[i]);
236 prov_cap[i] = RR_Capability_SourceOutput;
237 swapl(&prov_cap[i]);
238 i++;
239 }
240 xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) {
241 pScrProvPriv = rrGetScrPriv(provscreen);
242 providers[i] = pScrProvPriv->provider->id;
243 if (client->swapped)
244 swapl(&providers[i]);
245 prov_cap[i] = RR_Capability_SinkOutput;
246 if (client->swapped)
247 swapl(&prov_cap[i]);
248 i++;
249 }
250 xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) {
251 pScrProvPriv = rrGetScrPriv(provscreen);
252 providers[i] = pScrProvPriv->provider->id;
253 if (client->swapped)
254 swapl(&providers[i]);
255 prov_cap[i] = RR_Capability_SourceOffload;
256 if (client->swapped)
257 swapl(&prov_cap[i]);
258 i++;
259 }
260
261
262 memcpy(name, provider->name, rep.nameLength);
263 if (client->swapped) {
264 swaps(&rep.sequenceNumber);
265 swapl(&rep.length);
266 swapl(&rep.capabilities);
267 swaps(&rep.nCrtcs);
268 swaps(&rep.nOutputs);
269 swaps(&rep.nameLength);
270 }
271 WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep);
272 if (extraLen)
273 {
274 WriteToClient (client, extraLen, (char *) extra);
275 free(extra);
276 }
277 return Success;
278 }
279
280 int
281 ProcRRSetProviderOutputSource(ClientPtr client)
282 {
283 REQUEST(xRRSetProviderOutputSourceReq);
284 rrScrPrivPtr pScrPriv;
285 RRProviderPtr provider, source_provider = NULL;
286 ScreenPtr pScreen;
287
288 REQUEST_AT_LEAST_SIZE(xRRSetProviderOutputSourceReq);
289
290 VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
291
292 if (!(provider->capabilities & RR_Capability_SinkOutput))
293 return BadValue;
294
295 if (stuff->source_provider) {
296 VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess);
297
298 if (!(source_provider->capabilities & RR_Capability_SourceOutput))
299 return BadValue;
300 }
301
302 pScreen = provider->pScreen;
303 pScrPriv = rrGetScrPriv(pScreen);
304
305 pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider);
306
307 provider->changed = TRUE;
308 RRSetChanged(pScreen);
309
310 RRTellChanged (pScreen);
311
312 return Success;
313 }
314
315 int
316 ProcRRSetProviderOffloadSink(ClientPtr client)
317 {
318 REQUEST(xRRSetProviderOffloadSinkReq);
319 rrScrPrivPtr pScrPriv;
320 RRProviderPtr provider, sink_provider = NULL;
321 ScreenPtr pScreen;
322
323 REQUEST_AT_LEAST_SIZE(xRRSetProviderOffloadSinkReq);
324
325 VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
326 if (!(provider->capabilities & RR_Capability_SourceOffload))
327 return BadValue;
328
329 if (stuff->sink_provider) {
330 VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess);
331 if (!(sink_provider->capabilities & RR_Capability_SinkOffload))
332 return BadValue;
333 }
334 pScreen = provider->pScreen;
335 pScrPriv = rrGetScrPriv(pScreen);
336
337 pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider);
338
339 provider->changed = TRUE;
340 RRSetChanged(pScreen);
341
342 RRTellChanged (pScreen);
343
344 return Success;
345 }
346
347 RRProviderPtr
348 RRProviderCreate(ScreenPtr pScreen, const char *name,
349 int nameLength)
350 {
351 RRProviderPtr provider;
352 rrScrPrivPtr pScrPriv;
353
354 pScrPriv = rrGetScrPriv(pScreen);
355
356 provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1);
357 if (!provider)
358 return NULL;
359
360 provider->id = FakeClientID(0);
361 provider->pScreen = pScreen;
362 provider->name = (char *) (provider + 1);
363 provider->nameLength = nameLength;
364 memcpy(provider->name, name, nameLength);
365 provider->name[nameLength] = '\0';
366 provider->changed = FALSE;
367
368 if (!AddResource (provider->id, RRProviderType, (pointer) provider))
369 return NULL;
370 pScrPriv->provider = provider;
371 return provider;
372 }
373
374 /*
375 * Destroy a provider at shutdown
376 */
377 void
378 RRProviderDestroy (RRProviderPtr provider)
379 {
380 FreeResource (provider->id, 0);
381 }
382
383 void
384 RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities)
385 {
386 provider->capabilities = capabilities;
387 }
388
389 static int
390 RRProviderDestroyResource (pointer value, XID pid)
391 {
392 RRProviderPtr provider = (RRProviderPtr)value;
393 ScreenPtr pScreen = provider->pScreen;
394
395 if (pScreen)
396 {
397 rrScrPriv(pScreen);
398
399 if (pScrPriv->rrProviderDestroy)
400 (*pScrPriv->rrProviderDestroy)(pScreen, provider);
401 pScrPriv->provider = NULL;
402 }
403 free(provider);
404 return 1;
405 }
406
407 Bool
408 RRProviderInit(void)
409 {
410 RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider");
411 if (!RRProviderType)
412 return FALSE;
413
414 return TRUE;
415 }
416
417 extern _X_EXPORT Bool
418 RRProviderLookup(XID id, RRProviderPtr *provider_p)
419 {
420 int rc = dixLookupResourceByType((void **)provider_p, id,
421 RRProviderType, NullClient, DixReadAccess);
422 if (rc == Success)
423 return TRUE;
424 return FALSE;
425 }
426
427 void
428 RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
429 {
430 ScreenPtr pScreen = pWin->drawable.pScreen;
431
432 rrScrPriv(pScreen);
433
434 xRRProviderChangeNotifyEvent pe = {
435 .type = RRNotify + RREventBase,
436 .subCode = RRNotify_ProviderChange,
437 .timestamp = pScrPriv->lastSetTime.milliseconds,
438 .window = pWin->drawable.id,
439 .provider = provider->id
440 };
441
442 WriteEventsToClient(client, 1, (xEvent *) &pe);
443 }