2 * Copyright © 2012 Red Hat Inc.
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.
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
22 * Authors: Dave Airlie
28 RESTYPE RRProviderType
;
31 * Initialize provider type error value
34 RRProviderInitErrorValue(void)
36 SetResourceTypeErrorValue(RRProviderType
, RRErrorBase
+ BadRRProvider
);
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]); \
50 ProcRRGetProviders (ClientPtr client
)
52 REQUEST(xRRGetProvidersReq
);
53 xRRGetProvidersReply rep
;
56 rrScrPrivPtr pScrPriv
;
59 unsigned int extraLen
;
60 RRProvider
*providers
;
61 int total_providers
= 0, count_providers
= 0;
64 REQUEST_SIZE_MATCH(xRRGetProvidersReq
);
65 rc
= dixLookupWindow(&pWin
, stuff
->window
, client
, DixGetAttrAccess
);
69 pScreen
= pWin
->drawable
.pScreen
;
71 pScrPriv
= rrGetScrPriv(pScreen
);
73 if (pScrPriv
->provider
)
75 xorg_list_for_each_entry(iter
, &pScreen
->output_slave_list
, output_head
) {
76 pScrPriv
= rrGetScrPriv(iter
);
77 total_providers
+= pScrPriv
->provider
? 1 : 0;
79 xorg_list_for_each_entry(iter
, &pScreen
->offload_slave_list
, offload_head
) {
80 pScrPriv
= rrGetScrPriv(iter
);
81 total_providers
+= pScrPriv
->provider
? 1 : 0;
83 xorg_list_for_each_entry(iter
, &pScreen
->unattached_list
, unattached_head
) {
84 pScrPriv
= rrGetScrPriv(iter
);
85 total_providers
+= pScrPriv
->provider
? 1 : 0;
88 pScrPriv
= rrGetScrPriv(pScreen
);
92 rep
= (xRRGetProvidersReply
) {
94 .sequenceNumber
= client
->sequence
,
96 .timestamp
= currentTime
.milliseconds
,
102 rep
= (xRRGetProvidersReply
) {
104 .sequenceNumber
= client
->sequence
,
105 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
106 .nProviders
= total_providers
,
107 .length
= total_providers
109 extraLen
= rep
.length
<< 2;
111 extra
= malloc(extraLen
);
117 providers
= (RRProvider
*)extra
;
118 ADD_PROVIDER(pScreen
);
119 xorg_list_for_each_entry(iter
, &pScreen
->output_slave_list
, output_head
) {
122 xorg_list_for_each_entry(iter
, &pScreen
->offload_slave_list
, offload_head
) {
125 xorg_list_for_each_entry(iter
, &pScreen
->unattached_list
, unattached_head
) {
130 if (client
->swapped
) {
131 swaps(&rep
.sequenceNumber
);
133 swapl(&rep
.timestamp
);
134 swaps(&rep
.nProviders
);
136 WriteToClient(client
, sizeof(xRRGetProvidersReply
), (char *)&rep
);
139 WriteToClient (client
, extraLen
, (char *) extra
);
146 ProcRRGetProviderInfo (ClientPtr client
)
148 REQUEST(xRRGetProviderInfoReq
);
149 xRRGetProviderInfoReply rep
;
150 rrScrPrivPtr pScrPriv
, pScrProvPriv
;
151 RRProviderPtr provider
;
154 unsigned int extraLen
= 0;
159 ScreenPtr provscreen
;
160 RRProvider
*providers
;
163 REQUEST_SIZE_MATCH(xRRGetProviderInfoReq
);
164 VERIFY_RR_PROVIDER(stuff
->provider
, provider
, DixReadAccess
);
166 pScreen
= provider
->pScreen
;
167 pScrPriv
= rrGetScrPriv(pScreen
);
169 rep
= (xRRGetProviderInfoReply
) {
171 .status
= RRSetConfigSuccess
,
172 .sequenceNumber
= client
->sequence
,
174 .capabilities
= provider
->capabilities
,
175 .nameLength
= provider
->nameLength
,
176 .timestamp
= pScrPriv
->lastSetTime
.milliseconds
,
177 .nCrtcs
= pScrPriv
->numCrtcs
,
178 .nOutputs
= pScrPriv
->numOutputs
,
179 .nAssociatedProviders
= 0
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
++;
192 rep
.length
= (pScrPriv
->numCrtcs
+ pScrPriv
->numOutputs
+
193 (rep
.nAssociatedProviders
* 2) + bytes_to_int32(rep
.nameLength
));
195 extraLen
= rep
.length
<< 2;
197 extra
= malloc(extraLen
);
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
);
210 for (i
= 0; i
< pScrPriv
->numCrtcs
; i
++) {
211 crtcs
[i
] = pScrPriv
->crtcs
[i
]->id
;
216 for (i
= 0; i
< pScrPriv
->numOutputs
; i
++) {
217 outputs
[i
] = pScrPriv
->outputs
[i
]->id
;
223 if (provider
->offload_sink
) {
224 providers
[i
] = provider
->offload_sink
->id
;
226 swapl(&providers
[i
]);
227 prov_cap
[i
] = RR_Capability_SinkOffload
;
232 if (provider
->output_source
) {
233 providers
[i
] = provider
->output_source
->id
;
235 swapl(&providers
[i
]);
236 prov_cap
[i
] = RR_Capability_SourceOutput
;
240 xorg_list_for_each_entry(provscreen
, &pScreen
->output_slave_list
, output_head
) {
241 pScrProvPriv
= rrGetScrPriv(provscreen
);
242 providers
[i
] = pScrProvPriv
->provider
->id
;
244 swapl(&providers
[i
]);
245 prov_cap
[i
] = RR_Capability_SinkOutput
;
250 xorg_list_for_each_entry(provscreen
, &pScreen
->offload_slave_list
, offload_head
) {
251 pScrProvPriv
= rrGetScrPriv(provscreen
);
252 providers
[i
] = pScrProvPriv
->provider
->id
;
254 swapl(&providers
[i
]);
255 prov_cap
[i
] = RR_Capability_SourceOffload
;
262 memcpy(name
, provider
->name
, rep
.nameLength
);
263 if (client
->swapped
) {
264 swaps(&rep
.sequenceNumber
);
266 swapl(&rep
.capabilities
);
268 swaps(&rep
.nOutputs
);
269 swaps(&rep
.nameLength
);
271 WriteToClient(client
, sizeof(xRRGetProviderInfoReply
), (char *)&rep
);
274 WriteToClient (client
, extraLen
, (char *) extra
);
281 ProcRRSetProviderOutputSource(ClientPtr client
)
283 REQUEST(xRRSetProviderOutputSourceReq
);
284 rrScrPrivPtr pScrPriv
;
285 RRProviderPtr provider
, source_provider
= NULL
;
288 REQUEST_AT_LEAST_SIZE(xRRSetProviderOutputSourceReq
);
290 VERIFY_RR_PROVIDER(stuff
->provider
, provider
, DixReadAccess
);
292 if (!(provider
->capabilities
& RR_Capability_SinkOutput
))
295 if (stuff
->source_provider
) {
296 VERIFY_RR_PROVIDER(stuff
->source_provider
, source_provider
, DixReadAccess
);
298 if (!(source_provider
->capabilities
& RR_Capability_SourceOutput
))
302 pScreen
= provider
->pScreen
;
303 pScrPriv
= rrGetScrPriv(pScreen
);
305 pScrPriv
->rrProviderSetOutputSource(pScreen
, provider
, source_provider
);
307 provider
->changed
= TRUE
;
308 RRSetChanged(pScreen
);
310 RRTellChanged (pScreen
);
316 ProcRRSetProviderOffloadSink(ClientPtr client
)
318 REQUEST(xRRSetProviderOffloadSinkReq
);
319 rrScrPrivPtr pScrPriv
;
320 RRProviderPtr provider
, sink_provider
= NULL
;
323 REQUEST_AT_LEAST_SIZE(xRRSetProviderOffloadSinkReq
);
325 VERIFY_RR_PROVIDER(stuff
->provider
, provider
, DixReadAccess
);
326 if (!(provider
->capabilities
& RR_Capability_SourceOffload
))
329 if (stuff
->sink_provider
) {
330 VERIFY_RR_PROVIDER(stuff
->sink_provider
, sink_provider
, DixReadAccess
);
331 if (!(sink_provider
->capabilities
& RR_Capability_SinkOffload
))
334 pScreen
= provider
->pScreen
;
335 pScrPriv
= rrGetScrPriv(pScreen
);
337 pScrPriv
->rrProviderSetOffloadSink(pScreen
, provider
, sink_provider
);
339 provider
->changed
= TRUE
;
340 RRSetChanged(pScreen
);
342 RRTellChanged (pScreen
);
348 RRProviderCreate(ScreenPtr pScreen
, const char *name
,
351 RRProviderPtr provider
;
352 rrScrPrivPtr pScrPriv
;
354 pScrPriv
= rrGetScrPriv(pScreen
);
356 provider
= calloc(1, sizeof(RRProviderRec
) + nameLength
+ 1);
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
;
368 if (!AddResource (provider
->id
, RRProviderType
, (pointer
) provider
))
370 pScrPriv
->provider
= provider
;
375 * Destroy a provider at shutdown
378 RRProviderDestroy (RRProviderPtr provider
)
380 FreeResource (provider
->id
, 0);
384 RRProviderSetCapabilities(RRProviderPtr provider
, uint32_t capabilities
)
386 provider
->capabilities
= capabilities
;
390 RRProviderDestroyResource (pointer value
, XID pid
)
392 RRProviderPtr provider
= (RRProviderPtr
)value
;
393 ScreenPtr pScreen
= provider
->pScreen
;
399 if (pScrPriv
->rrProviderDestroy
)
400 (*pScrPriv
->rrProviderDestroy
)(pScreen
, provider
);
401 pScrPriv
->provider
= NULL
;
410 RRProviderType
= CreateNewResourceType(RRProviderDestroyResource
, "Provider");
417 extern _X_EXPORT Bool
418 RRProviderLookup(XID id
, RRProviderPtr
*provider_p
)
420 int rc
= dixLookupResourceByType((void **)provider_p
, id
,
421 RRProviderType
, NullClient
, DixReadAccess
);
428 RRDeliverProviderEvent(ClientPtr client
, WindowPtr pWin
, RRProviderPtr provider
)
430 ScreenPtr pScreen
= pWin
->drawable
.pScreen
;
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
442 WriteEventsToClient(client
, 1, (xEvent
*) &pe
);