xref: /OK3568_Linux_fs/external/xserver/randr/rrprovider.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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