135c4bbdfSmrg/* 235c4bbdfSmrg * Copyright © 2012 Red Hat Inc. 3ed6184dfSmrg * Copyright 2019 DisplayLink (UK) Ltd. 435c4bbdfSmrg * 535c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its 635c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that 735c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright 835c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and 935c4bbdfSmrg * that the name of the copyright holders not be used in advertising or 1035c4bbdfSmrg * publicity pertaining to distribution of the software without specific, 1135c4bbdfSmrg * written prior permission. The copyright holders make no representations 1235c4bbdfSmrg * about the suitability of this software for any purpose. It is provided "as 1335c4bbdfSmrg * is" without express or implied warranty. 1435c4bbdfSmrg * 1535c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 1635c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 1735c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 1835c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 1935c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 2035c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 2135c4bbdfSmrg * OF THIS SOFTWARE. 2235c4bbdfSmrg * 2335c4bbdfSmrg * Authors: Dave Airlie 2435c4bbdfSmrg */ 2535c4bbdfSmrg 2635c4bbdfSmrg#include "randrstr.h" 2735c4bbdfSmrg#include "swaprep.h" 2835c4bbdfSmrg 291b5d61b8Smrg#include <X11/Xatom.h> 301b5d61b8Smrg 31a035e2b2SmrgRESTYPE RRProviderType = 0; 3235c4bbdfSmrg 3335c4bbdfSmrg/* 3435c4bbdfSmrg * Initialize provider type error value 3535c4bbdfSmrg */ 3635c4bbdfSmrgvoid 3735c4bbdfSmrgRRProviderInitErrorValue(void) 3835c4bbdfSmrg{ 3935c4bbdfSmrg SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider); 4035c4bbdfSmrg} 4135c4bbdfSmrg 4235c4bbdfSmrg#define ADD_PROVIDER(_pScreen) do { \ 4335c4bbdfSmrg pScrPriv = rrGetScrPriv((_pScreen)); \ 4435c4bbdfSmrg if (pScrPriv->provider) { \ 4535c4bbdfSmrg providers[count_providers] = pScrPriv->provider->id; \ 4635c4bbdfSmrg if (client->swapped) \ 4735c4bbdfSmrg swapl(&providers[count_providers]); \ 4835c4bbdfSmrg count_providers++; \ 4935c4bbdfSmrg } \ 5035c4bbdfSmrg } while(0) 5135c4bbdfSmrg 5235c4bbdfSmrgint 5335c4bbdfSmrgProcRRGetProviders (ClientPtr client) 5435c4bbdfSmrg{ 5535c4bbdfSmrg REQUEST(xRRGetProvidersReq); 5635c4bbdfSmrg xRRGetProvidersReply rep; 5735c4bbdfSmrg WindowPtr pWin; 5835c4bbdfSmrg ScreenPtr pScreen; 5935c4bbdfSmrg rrScrPrivPtr pScrPriv; 6035c4bbdfSmrg int rc; 6135c4bbdfSmrg CARD8 *extra; 6235c4bbdfSmrg unsigned int extraLen; 6335c4bbdfSmrg RRProvider *providers; 6435c4bbdfSmrg int total_providers = 0, count_providers = 0; 6535c4bbdfSmrg ScreenPtr iter; 6635c4bbdfSmrg 6735c4bbdfSmrg REQUEST_SIZE_MATCH(xRRGetProvidersReq); 6835c4bbdfSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); 6935c4bbdfSmrg if (rc != Success) 7035c4bbdfSmrg return rc; 7135c4bbdfSmrg 7235c4bbdfSmrg pScreen = pWin->drawable.pScreen; 7335c4bbdfSmrg 7435c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 7535c4bbdfSmrg 7635c4bbdfSmrg if (pScrPriv->provider) 7735c4bbdfSmrg total_providers++; 78ed6184dfSmrg xorg_list_for_each_entry(iter, &pScreen->secondary_list, secondary_head) { 7935c4bbdfSmrg pScrPriv = rrGetScrPriv(iter); 8035c4bbdfSmrg total_providers += pScrPriv->provider ? 1 : 0; 8135c4bbdfSmrg } 8235c4bbdfSmrg 8335c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 8435c4bbdfSmrg 8535c4bbdfSmrg if (!pScrPriv) 8635c4bbdfSmrg { 8735c4bbdfSmrg rep = (xRRGetProvidersReply) { 8835c4bbdfSmrg .type = X_Reply, 8935c4bbdfSmrg .sequenceNumber = client->sequence, 9035c4bbdfSmrg .length = 0, 9135c4bbdfSmrg .timestamp = currentTime.milliseconds, 9235c4bbdfSmrg .nProviders = 0 9335c4bbdfSmrg }; 9435c4bbdfSmrg extra = NULL; 9535c4bbdfSmrg extraLen = 0; 9635c4bbdfSmrg } else { 9735c4bbdfSmrg rep = (xRRGetProvidersReply) { 9835c4bbdfSmrg .type = X_Reply, 9935c4bbdfSmrg .sequenceNumber = client->sequence, 10035c4bbdfSmrg .timestamp = pScrPriv->lastSetTime.milliseconds, 10135c4bbdfSmrg .nProviders = total_providers, 10235c4bbdfSmrg .length = total_providers 10335c4bbdfSmrg }; 10435c4bbdfSmrg extraLen = rep.length << 2; 10535c4bbdfSmrg if (extraLen) { 10635c4bbdfSmrg extra = malloc(extraLen); 10735c4bbdfSmrg if (!extra) 10835c4bbdfSmrg return BadAlloc; 10935c4bbdfSmrg } else 11035c4bbdfSmrg extra = NULL; 11135c4bbdfSmrg 11235c4bbdfSmrg providers = (RRProvider *)extra; 11335c4bbdfSmrg ADD_PROVIDER(pScreen); 114ed6184dfSmrg xorg_list_for_each_entry(iter, &pScreen->secondary_list, secondary_head) { 11535c4bbdfSmrg ADD_PROVIDER(iter); 11635c4bbdfSmrg } 11735c4bbdfSmrg } 11835c4bbdfSmrg 11935c4bbdfSmrg if (client->swapped) { 12035c4bbdfSmrg swaps(&rep.sequenceNumber); 12135c4bbdfSmrg swapl(&rep.length); 12235c4bbdfSmrg swapl(&rep.timestamp); 12335c4bbdfSmrg swaps(&rep.nProviders); 12435c4bbdfSmrg } 12535c4bbdfSmrg WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep); 12635c4bbdfSmrg if (extraLen) 12735c4bbdfSmrg { 12835c4bbdfSmrg WriteToClient (client, extraLen, (char *) extra); 12935c4bbdfSmrg free(extra); 13035c4bbdfSmrg } 13135c4bbdfSmrg return Success; 13235c4bbdfSmrg} 13335c4bbdfSmrg 13435c4bbdfSmrgint 13535c4bbdfSmrgProcRRGetProviderInfo (ClientPtr client) 13635c4bbdfSmrg{ 13735c4bbdfSmrg REQUEST(xRRGetProviderInfoReq); 13835c4bbdfSmrg xRRGetProviderInfoReply rep; 13935c4bbdfSmrg rrScrPrivPtr pScrPriv, pScrProvPriv; 14035c4bbdfSmrg RRProviderPtr provider; 14135c4bbdfSmrg ScreenPtr pScreen; 14235c4bbdfSmrg CARD8 *extra; 14335c4bbdfSmrg unsigned int extraLen = 0; 14435c4bbdfSmrg RRCrtc *crtcs; 14535c4bbdfSmrg RROutput *outputs; 14635c4bbdfSmrg int i; 14735c4bbdfSmrg char *name; 14835c4bbdfSmrg ScreenPtr provscreen; 14935c4bbdfSmrg RRProvider *providers; 15035c4bbdfSmrg uint32_t *prov_cap; 15135c4bbdfSmrg 15235c4bbdfSmrg REQUEST_SIZE_MATCH(xRRGetProviderInfoReq); 15335c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); 15435c4bbdfSmrg 15535c4bbdfSmrg pScreen = provider->pScreen; 15635c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 15735c4bbdfSmrg 15835c4bbdfSmrg rep = (xRRGetProviderInfoReply) { 15935c4bbdfSmrg .type = X_Reply, 16035c4bbdfSmrg .status = RRSetConfigSuccess, 16135c4bbdfSmrg .sequenceNumber = client->sequence, 16235c4bbdfSmrg .length = 0, 16335c4bbdfSmrg .capabilities = provider->capabilities, 16435c4bbdfSmrg .nameLength = provider->nameLength, 16535c4bbdfSmrg .timestamp = pScrPriv->lastSetTime.milliseconds, 16635c4bbdfSmrg .nCrtcs = pScrPriv->numCrtcs, 16735c4bbdfSmrg .nOutputs = pScrPriv->numOutputs, 16835c4bbdfSmrg .nAssociatedProviders = 0 16935c4bbdfSmrg }; 17035c4bbdfSmrg 17135c4bbdfSmrg /* count associated providers */ 17235c4bbdfSmrg if (provider->offload_sink) 17335c4bbdfSmrg rep.nAssociatedProviders++; 1741b5d61b8Smrg if (provider->output_source && 1751b5d61b8Smrg provider->output_source != provider->offload_sink) 17635c4bbdfSmrg rep.nAssociatedProviders++; 177ed6184dfSmrg xorg_list_for_each_entry(provscreen, &pScreen->secondary_list, secondary_head) { 178ed6184dfSmrg if (provscreen->is_output_secondary || provscreen->is_offload_secondary) 1791b5d61b8Smrg rep.nAssociatedProviders++; 1801b5d61b8Smrg } 18135c4bbdfSmrg 18235c4bbdfSmrg rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs + 18335c4bbdfSmrg (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength)); 18435c4bbdfSmrg 18535c4bbdfSmrg extraLen = rep.length << 2; 18635c4bbdfSmrg if (extraLen) { 18735c4bbdfSmrg extra = malloc(extraLen); 18835c4bbdfSmrg if (!extra) 18935c4bbdfSmrg return BadAlloc; 19035c4bbdfSmrg } 19135c4bbdfSmrg else 19235c4bbdfSmrg extra = NULL; 19335c4bbdfSmrg 19435c4bbdfSmrg crtcs = (RRCrtc *)extra; 19535c4bbdfSmrg outputs = (RROutput *)(crtcs + rep.nCrtcs); 19635c4bbdfSmrg providers = (RRProvider *)(outputs + rep.nOutputs); 19735c4bbdfSmrg prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders); 19835c4bbdfSmrg name = (char *)(prov_cap + rep.nAssociatedProviders); 19935c4bbdfSmrg 20035c4bbdfSmrg for (i = 0; i < pScrPriv->numCrtcs; i++) { 20135c4bbdfSmrg crtcs[i] = pScrPriv->crtcs[i]->id; 20235c4bbdfSmrg if (client->swapped) 20335c4bbdfSmrg swapl(&crtcs[i]); 20435c4bbdfSmrg } 20535c4bbdfSmrg 20635c4bbdfSmrg for (i = 0; i < pScrPriv->numOutputs; i++) { 20735c4bbdfSmrg outputs[i] = pScrPriv->outputs[i]->id; 20835c4bbdfSmrg if (client->swapped) 20935c4bbdfSmrg swapl(&outputs[i]); 21035c4bbdfSmrg } 21135c4bbdfSmrg 21235c4bbdfSmrg i = 0; 21335c4bbdfSmrg if (provider->offload_sink) { 21435c4bbdfSmrg providers[i] = provider->offload_sink->id; 21535c4bbdfSmrg if (client->swapped) 21635c4bbdfSmrg swapl(&providers[i]); 21735c4bbdfSmrg prov_cap[i] = RR_Capability_SinkOffload; 21835c4bbdfSmrg if (client->swapped) 21935c4bbdfSmrg swapl(&prov_cap[i]); 22035c4bbdfSmrg i++; 22135c4bbdfSmrg } 22235c4bbdfSmrg if (provider->output_source) { 22335c4bbdfSmrg providers[i] = provider->output_source->id; 22435c4bbdfSmrg if (client->swapped) 22535c4bbdfSmrg swapl(&providers[i]); 22635c4bbdfSmrg prov_cap[i] = RR_Capability_SourceOutput; 22735c4bbdfSmrg swapl(&prov_cap[i]); 22835c4bbdfSmrg i++; 22935c4bbdfSmrg } 230ed6184dfSmrg xorg_list_for_each_entry(provscreen, &pScreen->secondary_list, secondary_head) { 231ed6184dfSmrg if (!provscreen->is_output_secondary && !provscreen->is_offload_secondary) 2321b5d61b8Smrg continue; 23335c4bbdfSmrg pScrProvPriv = rrGetScrPriv(provscreen); 23435c4bbdfSmrg providers[i] = pScrProvPriv->provider->id; 23535c4bbdfSmrg if (client->swapped) 23635c4bbdfSmrg swapl(&providers[i]); 2371b5d61b8Smrg prov_cap[i] = 0; 238ed6184dfSmrg if (provscreen->is_output_secondary) 2391b5d61b8Smrg prov_cap[i] |= RR_Capability_SinkOutput; 240ed6184dfSmrg if (provscreen->is_offload_secondary) 2411b5d61b8Smrg prov_cap[i] |= RR_Capability_SourceOffload; 24235c4bbdfSmrg if (client->swapped) 24335c4bbdfSmrg swapl(&prov_cap[i]); 24435c4bbdfSmrg i++; 24535c4bbdfSmrg } 24635c4bbdfSmrg 24735c4bbdfSmrg memcpy(name, provider->name, rep.nameLength); 24835c4bbdfSmrg if (client->swapped) { 24935c4bbdfSmrg swaps(&rep.sequenceNumber); 25035c4bbdfSmrg swapl(&rep.length); 25135c4bbdfSmrg swapl(&rep.capabilities); 25235c4bbdfSmrg swaps(&rep.nCrtcs); 25335c4bbdfSmrg swaps(&rep.nOutputs); 25435c4bbdfSmrg swaps(&rep.nameLength); 25535c4bbdfSmrg } 25635c4bbdfSmrg WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep); 25735c4bbdfSmrg if (extraLen) 25835c4bbdfSmrg { 25935c4bbdfSmrg WriteToClient (client, extraLen, (char *) extra); 26035c4bbdfSmrg free(extra); 26135c4bbdfSmrg } 26235c4bbdfSmrg return Success; 26335c4bbdfSmrg} 26435c4bbdfSmrg 2651b5d61b8Smrgstatic void 2661b5d61b8SmrgRRInitPrimeSyncProps(ScreenPtr pScreen) 2671b5d61b8Smrg{ 2681b5d61b8Smrg /* 2691b5d61b8Smrg * TODO: When adding support for different sources for different outputs, 2701b5d61b8Smrg * make sure this sets up the output properties only on outputs associated 2711b5d61b8Smrg * with the correct source provider. 2721b5d61b8Smrg */ 2731b5d61b8Smrg 2741b5d61b8Smrg rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); 2751b5d61b8Smrg 2761b5d61b8Smrg const char *syncStr = PRIME_SYNC_PROP; 2771b5d61b8Smrg Atom syncProp = MakeAtom(syncStr, strlen(syncStr), TRUE); 2781b5d61b8Smrg 2791b5d61b8Smrg int defaultVal = TRUE; 2801b5d61b8Smrg INT32 validVals[2] = {FALSE, TRUE}; 2811b5d61b8Smrg 2821b5d61b8Smrg int i; 2831b5d61b8Smrg for (i = 0; i < pScrPriv->numOutputs; i++) { 2841b5d61b8Smrg if (!RRQueryOutputProperty(pScrPriv->outputs[i], syncProp)) { 2851b5d61b8Smrg RRConfigureOutputProperty(pScrPriv->outputs[i], syncProp, 2861b5d61b8Smrg TRUE, FALSE, FALSE, 2871b5d61b8Smrg 2, &validVals[0]); 2881b5d61b8Smrg RRChangeOutputProperty(pScrPriv->outputs[i], syncProp, XA_INTEGER, 2891b5d61b8Smrg 8, PropModeReplace, 1, &defaultVal, 2901b5d61b8Smrg FALSE, FALSE); 2911b5d61b8Smrg } 2921b5d61b8Smrg } 2931b5d61b8Smrg} 2941b5d61b8Smrg 2951b5d61b8Smrgstatic void 2961b5d61b8SmrgRRFiniPrimeSyncProps(ScreenPtr pScreen) 2971b5d61b8Smrg{ 2981b5d61b8Smrg /* 2991b5d61b8Smrg * TODO: When adding support for different sources for different outputs, 3001b5d61b8Smrg * make sure this tears down the output properties only on outputs 3011b5d61b8Smrg * associated with the correct source provider. 3021b5d61b8Smrg */ 3031b5d61b8Smrg 3041b5d61b8Smrg rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen); 3051b5d61b8Smrg int i; 3061b5d61b8Smrg 3071b5d61b8Smrg const char *syncStr = PRIME_SYNC_PROP; 3081b5d61b8Smrg Atom syncProp = MakeAtom(syncStr, strlen(syncStr), FALSE); 3091b5d61b8Smrg if (syncProp == None) 3101b5d61b8Smrg return; 3111b5d61b8Smrg 3121b5d61b8Smrg for (i = 0; i < pScrPriv->numOutputs; i++) { 3131b5d61b8Smrg RRDeleteOutputProperty(pScrPriv->outputs[i], syncProp); 3141b5d61b8Smrg } 3151b5d61b8Smrg} 3161b5d61b8Smrg 31735c4bbdfSmrgint 31835c4bbdfSmrgProcRRSetProviderOutputSource(ClientPtr client) 31935c4bbdfSmrg{ 32035c4bbdfSmrg REQUEST(xRRSetProviderOutputSourceReq); 32135c4bbdfSmrg rrScrPrivPtr pScrPriv; 32235c4bbdfSmrg RRProviderPtr provider, source_provider = NULL; 32335c4bbdfSmrg ScreenPtr pScreen; 32435c4bbdfSmrg 32535c4bbdfSmrg REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq); 32635c4bbdfSmrg 32735c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); 32835c4bbdfSmrg 32935c4bbdfSmrg if (!(provider->capabilities & RR_Capability_SinkOutput)) 33035c4bbdfSmrg return BadValue; 33135c4bbdfSmrg 33235c4bbdfSmrg if (stuff->source_provider) { 33335c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess); 33435c4bbdfSmrg 33535c4bbdfSmrg if (!(source_provider->capabilities & RR_Capability_SourceOutput)) 33635c4bbdfSmrg return BadValue; 33735c4bbdfSmrg } 33835c4bbdfSmrg 33935c4bbdfSmrg pScreen = provider->pScreen; 34035c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 34135c4bbdfSmrg 3421b5d61b8Smrg if (!pScreen->isGPU) 3431b5d61b8Smrg return BadValue; 3441b5d61b8Smrg 34535c4bbdfSmrg pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider); 34635c4bbdfSmrg 3471b5d61b8Smrg RRInitPrimeSyncProps(pScreen); 3481b5d61b8Smrg 34935c4bbdfSmrg provider->changed = TRUE; 35035c4bbdfSmrg RRSetChanged(pScreen); 35135c4bbdfSmrg 35235c4bbdfSmrg RRTellChanged (pScreen); 35335c4bbdfSmrg 35435c4bbdfSmrg return Success; 35535c4bbdfSmrg} 35635c4bbdfSmrg 35735c4bbdfSmrgint 35835c4bbdfSmrgProcRRSetProviderOffloadSink(ClientPtr client) 35935c4bbdfSmrg{ 36035c4bbdfSmrg REQUEST(xRRSetProviderOffloadSinkReq); 36135c4bbdfSmrg rrScrPrivPtr pScrPriv; 36235c4bbdfSmrg RRProviderPtr provider, sink_provider = NULL; 36335c4bbdfSmrg ScreenPtr pScreen; 36435c4bbdfSmrg 36535c4bbdfSmrg REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq); 36635c4bbdfSmrg 36735c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess); 36835c4bbdfSmrg if (!(provider->capabilities & RR_Capability_SourceOffload)) 36935c4bbdfSmrg return BadValue; 37035c4bbdfSmrg if (!provider->pScreen->isGPU) 37135c4bbdfSmrg return BadValue; 37235c4bbdfSmrg 37335c4bbdfSmrg if (stuff->sink_provider) { 37435c4bbdfSmrg VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess); 37535c4bbdfSmrg if (!(sink_provider->capabilities & RR_Capability_SinkOffload)) 37635c4bbdfSmrg return BadValue; 37735c4bbdfSmrg } 37835c4bbdfSmrg pScreen = provider->pScreen; 37935c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 38035c4bbdfSmrg 38135c4bbdfSmrg pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider); 38235c4bbdfSmrg 38335c4bbdfSmrg provider->changed = TRUE; 38435c4bbdfSmrg RRSetChanged(pScreen); 38535c4bbdfSmrg 38635c4bbdfSmrg RRTellChanged (pScreen); 38735c4bbdfSmrg 38835c4bbdfSmrg return Success; 38935c4bbdfSmrg} 39035c4bbdfSmrg 39135c4bbdfSmrgRRProviderPtr 39235c4bbdfSmrgRRProviderCreate(ScreenPtr pScreen, const char *name, 39335c4bbdfSmrg int nameLength) 39435c4bbdfSmrg{ 39535c4bbdfSmrg RRProviderPtr provider; 39635c4bbdfSmrg rrScrPrivPtr pScrPriv; 39735c4bbdfSmrg 39835c4bbdfSmrg pScrPriv = rrGetScrPriv(pScreen); 39935c4bbdfSmrg 40035c4bbdfSmrg provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1); 40135c4bbdfSmrg if (!provider) 40235c4bbdfSmrg return NULL; 40335c4bbdfSmrg 40435c4bbdfSmrg provider->id = FakeClientID(0); 40535c4bbdfSmrg provider->pScreen = pScreen; 40635c4bbdfSmrg provider->name = (char *) (provider + 1); 40735c4bbdfSmrg provider->nameLength = nameLength; 40835c4bbdfSmrg memcpy(provider->name, name, nameLength); 40935c4bbdfSmrg provider->name[nameLength] = '\0'; 41035c4bbdfSmrg provider->changed = FALSE; 41135c4bbdfSmrg 41235c4bbdfSmrg if (!AddResource (provider->id, RRProviderType, (void *) provider)) 41335c4bbdfSmrg return NULL; 41435c4bbdfSmrg pScrPriv->provider = provider; 41535c4bbdfSmrg return provider; 41635c4bbdfSmrg} 41735c4bbdfSmrg 41835c4bbdfSmrg/* 41935c4bbdfSmrg * Destroy a provider at shutdown 42035c4bbdfSmrg */ 42135c4bbdfSmrgvoid 42235c4bbdfSmrgRRProviderDestroy (RRProviderPtr provider) 42335c4bbdfSmrg{ 4241b5d61b8Smrg RRFiniPrimeSyncProps(provider->pScreen); 42535c4bbdfSmrg FreeResource (provider->id, 0); 42635c4bbdfSmrg} 42735c4bbdfSmrg 42835c4bbdfSmrgvoid 42935c4bbdfSmrgRRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities) 43035c4bbdfSmrg{ 43135c4bbdfSmrg provider->capabilities = capabilities; 43235c4bbdfSmrg} 43335c4bbdfSmrg 43435c4bbdfSmrgstatic int 43535c4bbdfSmrgRRProviderDestroyResource (void *value, XID pid) 43635c4bbdfSmrg{ 43735c4bbdfSmrg RRProviderPtr provider = (RRProviderPtr)value; 43835c4bbdfSmrg ScreenPtr pScreen = provider->pScreen; 43935c4bbdfSmrg 44035c4bbdfSmrg if (pScreen) 44135c4bbdfSmrg { 44235c4bbdfSmrg rrScrPriv(pScreen); 44335c4bbdfSmrg 44435c4bbdfSmrg if (pScrPriv->rrProviderDestroy) 44535c4bbdfSmrg (*pScrPriv->rrProviderDestroy)(pScreen, provider); 44635c4bbdfSmrg pScrPriv->provider = NULL; 44735c4bbdfSmrg } 44835c4bbdfSmrg free(provider); 44935c4bbdfSmrg return 1; 45035c4bbdfSmrg} 45135c4bbdfSmrg 45235c4bbdfSmrgBool 45335c4bbdfSmrgRRProviderInit(void) 45435c4bbdfSmrg{ 45535c4bbdfSmrg RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider"); 45635c4bbdfSmrg if (!RRProviderType) 45735c4bbdfSmrg return FALSE; 45835c4bbdfSmrg 45935c4bbdfSmrg return TRUE; 46035c4bbdfSmrg} 46135c4bbdfSmrg 46235c4bbdfSmrgextern _X_EXPORT Bool 46335c4bbdfSmrgRRProviderLookup(XID id, RRProviderPtr *provider_p) 46435c4bbdfSmrg{ 46535c4bbdfSmrg int rc = dixLookupResourceByType((void **)provider_p, id, 46635c4bbdfSmrg RRProviderType, NullClient, DixReadAccess); 46735c4bbdfSmrg if (rc == Success) 46835c4bbdfSmrg return TRUE; 46935c4bbdfSmrg return FALSE; 47035c4bbdfSmrg} 47135c4bbdfSmrg 47235c4bbdfSmrgvoid 47335c4bbdfSmrgRRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider) 47435c4bbdfSmrg{ 47535c4bbdfSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 47635c4bbdfSmrg 47735c4bbdfSmrg rrScrPriv(pScreen); 47835c4bbdfSmrg 47935c4bbdfSmrg xRRProviderChangeNotifyEvent pe = { 48035c4bbdfSmrg .type = RRNotify + RREventBase, 48135c4bbdfSmrg .subCode = RRNotify_ProviderChange, 48235c4bbdfSmrg .timestamp = pScrPriv->lastSetTime.milliseconds, 48335c4bbdfSmrg .window = pWin->drawable.id, 48435c4bbdfSmrg .provider = provider->id 48535c4bbdfSmrg }; 48635c4bbdfSmrg 48735c4bbdfSmrg WriteEventsToClient(client, 1, (xEvent *) &pe); 48835c4bbdfSmrg} 489ed6184dfSmrg 490ed6184dfSmrgvoid 491ed6184dfSmrgRRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr primaryScreen) 492ed6184dfSmrg{ 493ed6184dfSmrg rrScrPrivPtr pScrPriv; 494ed6184dfSmrg rrScrPrivPtr primaryPriv; 495ed6184dfSmrg RRProviderPtr provider; 496ed6184dfSmrg RRProviderPtr primary_provider; 497ed6184dfSmrg 498ed6184dfSmrg /* Bail out if RandR wasn't initialized. */ 499ed6184dfSmrg if (!dixPrivateKeyRegistered(rrPrivKey)) 500ed6184dfSmrg return; 501ed6184dfSmrg 502ed6184dfSmrg pScrPriv = rrGetScrPriv(pScreen); 503ed6184dfSmrg primaryPriv = rrGetScrPriv(primaryScreen); 504ed6184dfSmrg 505ed6184dfSmrg provider = pScrPriv->provider; 506ed6184dfSmrg primary_provider = primaryPriv->provider; 507ed6184dfSmrg 508ed6184dfSmrg if (!provider || !primary_provider) 509ed6184dfSmrg return; 510ed6184dfSmrg 511ed6184dfSmrg if ((provider->capabilities & RR_Capability_SinkOutput) && 512ed6184dfSmrg (primary_provider->capabilities & RR_Capability_SourceOutput)) { 513ed6184dfSmrg pScrPriv->rrProviderSetOutputSource(pScreen, provider, primary_provider); 514ed6184dfSmrg RRInitPrimeSyncProps(pScreen); 515ed6184dfSmrg 516ed6184dfSmrg primaryPriv->configChanged = TRUE; 517ed6184dfSmrg RRSetChanged(primaryScreen); 518ed6184dfSmrg } 519ed6184dfSmrg 520ed6184dfSmrg if ((provider->capabilities & RR_Capability_SourceOffload) && 521ed6184dfSmrg (primary_provider->capabilities & RR_Capability_SinkOffload)) 522ed6184dfSmrg pScrPriv->rrProviderSetOffloadSink(pScreen, provider, primary_provider); 523ed6184dfSmrg} 524