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