xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

rrprovider.c (15355B)


      1 /*
      2  * Copyright © 2012 Red Hat Inc.
      3  * Copyright 2019 DisplayLink (UK) Ltd.
      4  *
      5  * Permission to use, copy, modify, distribute, and sell this software and its
      6  * documentation for any purpose is hereby granted without fee, provided that
      7  * the above copyright notice appear in all copies and that both that copyright
      8  * notice and this permission notice appear in supporting documentation, and
      9  * that the name of the copyright holders not be used in advertising or
     10  * publicity pertaining to distribution of the software without specific,
     11  * written prior permission.  The copyright holders make no representations
     12  * about the suitability of this software for any purpose.  It is provided "as
     13  * is" without express or implied warranty.
     14  *
     15  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     16  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     17  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     18  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     19  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     20  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     21  * OF THIS SOFTWARE.
     22  *
     23  * Authors: Dave Airlie
     24  */
     25 
     26 #include "randrstr.h"
     27 #include "swaprep.h"
     28 
     29 #include <X11/Xatom.h>
     30 
     31 RESTYPE RRProviderType = 0;
     32 
     33 /*
     34  * Initialize provider type error value
     35  */
     36 void
     37 RRProviderInitErrorValue(void)
     38 {
     39     SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
     40 }
     41 
     42 #define ADD_PROVIDER(_pScreen) do {                                 \
     43     pScrPriv = rrGetScrPriv((_pScreen));                            \
     44     if (pScrPriv->provider) {                                   \
     45         providers[count_providers] = pScrPriv->provider->id;    \
     46         if (client->swapped)                                    \
     47             swapl(&providers[count_providers]);                 \
     48         count_providers++;                                      \
     49     }                                                           \
     50     } while(0)
     51 
     52 int
     53 ProcRRGetProviders (ClientPtr client)
     54 {
     55     REQUEST(xRRGetProvidersReq);
     56     xRRGetProvidersReply rep;
     57     WindowPtr pWin;
     58     ScreenPtr pScreen;
     59     rrScrPrivPtr pScrPriv;
     60     int rc;
     61     CARD8 *extra;
     62     unsigned int extraLen;
     63     RRProvider *providers;
     64     int total_providers = 0, count_providers = 0;
     65     ScreenPtr iter;
     66 
     67     REQUEST_SIZE_MATCH(xRRGetProvidersReq);
     68     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
     69     if (rc != Success)
     70         return rc;
     71 
     72     pScreen = pWin->drawable.pScreen;
     73 
     74     pScrPriv = rrGetScrPriv(pScreen);
     75 
     76     if (pScrPriv->provider)
     77         total_providers++;
     78     xorg_list_for_each_entry(iter, &pScreen->secondary_list, secondary_head) {
     79         pScrPriv = rrGetScrPriv(iter);
     80         total_providers += pScrPriv->provider ? 1 : 0;
     81     }
     82 
     83     pScrPriv = rrGetScrPriv(pScreen);
     84 
     85     if (!pScrPriv)
     86     {
     87         rep = (xRRGetProvidersReply) {
     88             .type = X_Reply,
     89             .sequenceNumber = client->sequence,
     90             .length = 0,
     91             .timestamp = currentTime.milliseconds,
     92             .nProviders = 0
     93         };
     94         extra = NULL;
     95         extraLen = 0;
     96     } else {
     97         rep = (xRRGetProvidersReply) {
     98             .type = X_Reply,
     99             .sequenceNumber = client->sequence,
    100             .timestamp = pScrPriv->lastSetTime.milliseconds,
    101             .nProviders = total_providers,
    102             .length = total_providers
    103         };
    104         extraLen = rep.length << 2;
    105         if (extraLen) {
    106             extra = malloc(extraLen);
    107             if (!extra)
    108                 return BadAlloc;
    109         } else
    110             extra = NULL;
    111 
    112         providers = (RRProvider *)extra;
    113         ADD_PROVIDER(pScreen);
    114         xorg_list_for_each_entry(iter, &pScreen->secondary_list, secondary_head) {
    115             ADD_PROVIDER(iter);
    116         }
    117     }
    118 
    119     if (client->swapped) {
    120         swaps(&rep.sequenceNumber);
    121         swapl(&rep.length);
    122         swapl(&rep.timestamp);
    123         swaps(&rep.nProviders);
    124     }
    125     WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep);
    126     if (extraLen)
    127     {
    128         WriteToClient (client, extraLen, (char *) extra);
    129         free(extra);
    130     }
    131     return Success;
    132 }
    133 
    134 int
    135 ProcRRGetProviderInfo (ClientPtr client)
    136 {
    137     REQUEST(xRRGetProviderInfoReq);
    138     xRRGetProviderInfoReply rep;
    139     rrScrPrivPtr pScrPriv, pScrProvPriv;
    140     RRProviderPtr provider;
    141     ScreenPtr pScreen;
    142     CARD8 *extra;
    143     unsigned int extraLen = 0;
    144     RRCrtc *crtcs;
    145     RROutput *outputs;
    146     int i;
    147     char *name;
    148     ScreenPtr provscreen;
    149     RRProvider *providers;
    150     uint32_t *prov_cap;
    151 
    152     REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
    153     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
    154 
    155     pScreen = provider->pScreen;
    156     pScrPriv = rrGetScrPriv(pScreen);
    157 
    158     rep = (xRRGetProviderInfoReply) {
    159         .type = X_Reply,
    160         .status = RRSetConfigSuccess,
    161         .sequenceNumber = client->sequence,
    162         .length = 0,
    163         .capabilities = provider->capabilities,
    164         .nameLength = provider->nameLength,
    165         .timestamp = pScrPriv->lastSetTime.milliseconds,
    166         .nCrtcs = pScrPriv->numCrtcs,
    167         .nOutputs = pScrPriv->numOutputs,
    168         .nAssociatedProviders = 0
    169     };
    170 
    171     /* count associated providers */
    172     if (provider->offload_sink)
    173         rep.nAssociatedProviders++;
    174     if (provider->output_source &&
    175             provider->output_source != provider->offload_sink)
    176         rep.nAssociatedProviders++;
    177     xorg_list_for_each_entry(provscreen, &pScreen->secondary_list, secondary_head) {
    178         if (provscreen->is_output_secondary || provscreen->is_offload_secondary)
    179             rep.nAssociatedProviders++;
    180     }
    181 
    182     rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
    183                   (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
    184 
    185     extraLen = rep.length << 2;
    186     if (extraLen) {
    187         extra = malloc(extraLen);
    188         if (!extra)
    189             return BadAlloc;
    190     }
    191     else
    192         extra = NULL;
    193 
    194     crtcs = (RRCrtc *)extra;
    195     outputs = (RROutput *)(crtcs + rep.nCrtcs);
    196     providers = (RRProvider *)(outputs + rep.nOutputs);
    197     prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders);
    198     name = (char *)(prov_cap + rep.nAssociatedProviders);
    199 
    200     for (i = 0; i < pScrPriv->numCrtcs; i++) {
    201         crtcs[i] = pScrPriv->crtcs[i]->id;
    202         if (client->swapped)
    203             swapl(&crtcs[i]);
    204     }
    205 
    206     for (i = 0; i < pScrPriv->numOutputs; i++) {
    207         outputs[i] = pScrPriv->outputs[i]->id;
    208         if (client->swapped)
    209             swapl(&outputs[i]);
    210     }
    211 
    212     i = 0;
    213     if (provider->offload_sink) {
    214         providers[i] = provider->offload_sink->id;
    215         if (client->swapped)
    216             swapl(&providers[i]);
    217         prov_cap[i] = RR_Capability_SinkOffload;
    218         if (client->swapped)
    219             swapl(&prov_cap[i]);
    220         i++;
    221     }
    222     if (provider->output_source) {
    223         providers[i] = provider->output_source->id;
    224         if (client->swapped)
    225             swapl(&providers[i]);
    226         prov_cap[i] = RR_Capability_SourceOutput;
    227             swapl(&prov_cap[i]);
    228         i++;
    229     }
    230     xorg_list_for_each_entry(provscreen, &pScreen->secondary_list, secondary_head) {
    231         if (!provscreen->is_output_secondary && !provscreen->is_offload_secondary)
    232             continue;
    233         pScrProvPriv = rrGetScrPriv(provscreen);
    234         providers[i] = pScrProvPriv->provider->id;
    235         if (client->swapped)
    236             swapl(&providers[i]);
    237         prov_cap[i] = 0;
    238         if (provscreen->is_output_secondary)
    239             prov_cap[i] |= RR_Capability_SinkOutput;
    240         if (provscreen->is_offload_secondary)
    241             prov_cap[i] |= RR_Capability_SourceOffload;
    242         if (client->swapped)
    243             swapl(&prov_cap[i]);
    244         i++;
    245     }
    246 
    247     memcpy(name, provider->name, rep.nameLength);
    248     if (client->swapped) {
    249               swaps(&rep.sequenceNumber);
    250         swapl(&rep.length);
    251         swapl(&rep.capabilities);
    252         swaps(&rep.nCrtcs);
    253         swaps(&rep.nOutputs);
    254         swaps(&rep.nameLength);
    255     }
    256     WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep);
    257     if (extraLen)
    258     {
    259         WriteToClient (client, extraLen, (char *) extra);
    260         free(extra);
    261     }
    262     return Success;
    263 }
    264 
    265 static void
    266 RRInitPrimeSyncProps(ScreenPtr pScreen)
    267 {
    268     /*
    269      * TODO: When adding support for different sources for different outputs,
    270      * make sure this sets up the output properties only on outputs associated
    271      * with the correct source provider.
    272      */
    273 
    274     rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
    275 
    276     const char *syncStr = PRIME_SYNC_PROP;
    277     Atom syncProp = MakeAtom(syncStr, strlen(syncStr), TRUE);
    278 
    279     int defaultVal = TRUE;
    280     INT32 validVals[2] = {FALSE, TRUE};
    281 
    282     int i;
    283     for (i = 0; i < pScrPriv->numOutputs; i++) {
    284         if (!RRQueryOutputProperty(pScrPriv->outputs[i], syncProp)) {
    285             RRConfigureOutputProperty(pScrPriv->outputs[i], syncProp,
    286                                       TRUE, FALSE, FALSE,
    287                                       2, &validVals[0]);
    288             RRChangeOutputProperty(pScrPriv->outputs[i], syncProp, XA_INTEGER,
    289                                    8, PropModeReplace, 1, &defaultVal,
    290                                    FALSE, FALSE);
    291         }
    292     }
    293 }
    294 
    295 static void
    296 RRFiniPrimeSyncProps(ScreenPtr pScreen)
    297 {
    298     /*
    299      * TODO: When adding support for different sources for different outputs,
    300      * make sure this tears down the output properties only on outputs
    301      * associated with the correct source provider.
    302      */
    303 
    304     rrScrPrivPtr pScrPriv = rrGetScrPriv(pScreen);
    305     int i;
    306 
    307     const char *syncStr = PRIME_SYNC_PROP;
    308     Atom syncProp = MakeAtom(syncStr, strlen(syncStr), FALSE);
    309     if (syncProp == None)
    310         return;
    311 
    312     for (i = 0; i < pScrPriv->numOutputs; i++) {
    313         RRDeleteOutputProperty(pScrPriv->outputs[i], syncProp);
    314     }
    315 }
    316 
    317 int
    318 ProcRRSetProviderOutputSource(ClientPtr client)
    319 {
    320     REQUEST(xRRSetProviderOutputSourceReq);
    321     rrScrPrivPtr pScrPriv;
    322     RRProviderPtr provider, source_provider = NULL;
    323     ScreenPtr pScreen;
    324 
    325     REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq);
    326 
    327     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
    328 
    329     if (!(provider->capabilities & RR_Capability_SinkOutput))
    330         return BadValue;
    331 
    332     if (stuff->source_provider) {
    333         VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess);
    334 
    335         if (!(source_provider->capabilities & RR_Capability_SourceOutput))
    336             return BadValue;
    337     }
    338 
    339     pScreen = provider->pScreen;
    340     pScrPriv = rrGetScrPriv(pScreen);
    341 
    342     if (!pScreen->isGPU)
    343         return BadValue;
    344 
    345     pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider);
    346 
    347     RRInitPrimeSyncProps(pScreen);
    348 
    349     provider->changed = TRUE;
    350     RRSetChanged(pScreen);
    351 
    352     RRTellChanged (pScreen);
    353 
    354     return Success;
    355 }
    356 
    357 int
    358 ProcRRSetProviderOffloadSink(ClientPtr client)
    359 {
    360     REQUEST(xRRSetProviderOffloadSinkReq);
    361     rrScrPrivPtr pScrPriv;
    362     RRProviderPtr provider, sink_provider = NULL;
    363     ScreenPtr pScreen;
    364 
    365     REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq);
    366 
    367     VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
    368     if (!(provider->capabilities & RR_Capability_SourceOffload))
    369         return BadValue;
    370     if (!provider->pScreen->isGPU)
    371         return BadValue;
    372 
    373     if (stuff->sink_provider) {
    374         VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess);
    375         if (!(sink_provider->capabilities & RR_Capability_SinkOffload))
    376             return BadValue;
    377     }
    378     pScreen = provider->pScreen;
    379     pScrPriv = rrGetScrPriv(pScreen);
    380 
    381     pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider);
    382 
    383     provider->changed = TRUE;
    384     RRSetChanged(pScreen);
    385 
    386     RRTellChanged (pScreen);
    387 
    388     return Success;
    389 }
    390 
    391 RRProviderPtr
    392 RRProviderCreate(ScreenPtr pScreen, const char *name,
    393                  int nameLength)
    394 {
    395     RRProviderPtr provider;
    396     rrScrPrivPtr pScrPriv;
    397 
    398     pScrPriv = rrGetScrPriv(pScreen);
    399 
    400     provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1);
    401     if (!provider)
    402         return NULL;
    403 
    404     provider->id = FakeClientID(0);
    405     provider->pScreen = pScreen;
    406     provider->name = (char *) (provider + 1);
    407     provider->nameLength = nameLength;
    408     memcpy(provider->name, name, nameLength);
    409     provider->name[nameLength] = '\0';
    410     provider->changed = FALSE;
    411 
    412     if (!AddResource (provider->id, RRProviderType, (void *) provider))
    413         return NULL;
    414     pScrPriv->provider = provider;
    415     return provider;
    416 }
    417 
    418 /*
    419  * Destroy a provider at shutdown
    420  */
    421 void
    422 RRProviderDestroy (RRProviderPtr provider)
    423 {
    424     RRFiniPrimeSyncProps(provider->pScreen);
    425     FreeResource (provider->id, 0);
    426 }
    427 
    428 void
    429 RRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities)
    430 {
    431     provider->capabilities = capabilities;
    432 }
    433 
    434 static int
    435 RRProviderDestroyResource (void *value, XID pid)
    436 {
    437     RRProviderPtr provider = (RRProviderPtr)value;
    438     ScreenPtr pScreen = provider->pScreen;
    439 
    440     if (pScreen)
    441     {
    442         rrScrPriv(pScreen);
    443 
    444         if (pScrPriv->rrProviderDestroy)
    445             (*pScrPriv->rrProviderDestroy)(pScreen, provider);
    446         pScrPriv->provider = NULL;
    447     }
    448     free(provider);
    449     return 1;
    450 }
    451 
    452 Bool
    453 RRProviderInit(void)
    454 {
    455     RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider");
    456     if (!RRProviderType)
    457         return FALSE;
    458 
    459     return TRUE;
    460 }
    461 
    462 extern _X_EXPORT Bool
    463 RRProviderLookup(XID id, RRProviderPtr *provider_p)
    464 {
    465     int rc = dixLookupResourceByType((void **)provider_p, id,
    466                                    RRProviderType, NullClient, DixReadAccess);
    467     if (rc == Success)
    468         return TRUE;
    469     return FALSE;
    470 }
    471 
    472 void
    473 RRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
    474 {
    475     ScreenPtr pScreen = pWin->drawable.pScreen;
    476 
    477     rrScrPriv(pScreen);
    478 
    479     xRRProviderChangeNotifyEvent pe = {
    480         .type = RRNotify + RREventBase,
    481         .subCode = RRNotify_ProviderChange,
    482         .timestamp = pScrPriv->lastSetTime.milliseconds,
    483         .window = pWin->drawable.id,
    484         .provider = provider->id
    485     };
    486 
    487     WriteEventsToClient(client, 1, (xEvent *) &pe);
    488 }
    489 
    490 void
    491 RRProviderAutoConfigGpuScreen(ScreenPtr pScreen, ScreenPtr primaryScreen)
    492 {
    493     rrScrPrivPtr pScrPriv;
    494     rrScrPrivPtr primaryPriv;
    495     RRProviderPtr provider;
    496     RRProviderPtr primary_provider;
    497 
    498     /* Bail out if RandR wasn't initialized. */
    499     if (!dixPrivateKeyRegistered(rrPrivKey))
    500         return;
    501 
    502     pScrPriv = rrGetScrPriv(pScreen);
    503     primaryPriv = rrGetScrPriv(primaryScreen);
    504 
    505     provider = pScrPriv->provider;
    506     primary_provider = primaryPriv->provider;
    507 
    508     if (!provider || !primary_provider)
    509         return;
    510 
    511     if ((provider->capabilities & RR_Capability_SinkOutput) &&
    512         (primary_provider->capabilities & RR_Capability_SourceOutput)) {
    513         pScrPriv->rrProviderSetOutputSource(pScreen, provider, primary_provider);
    514         RRInitPrimeSyncProps(pScreen);
    515 
    516         primaryPriv->configChanged = TRUE;
    517         RRSetChanged(primaryScreen);
    518     }
    519 
    520     if ((provider->capabilities & RR_Capability_SourceOffload) &&
    521         (primary_provider->capabilities & RR_Capability_SinkOffload))
    522         pScrPriv->rrProviderSetOffloadSink(pScreen, provider, primary_provider);
    523 }