rrprovider.c revision 35c4bbdf
135c4bbdfSmrg/*
235c4bbdfSmrg * Copyright © 2012 Red Hat Inc.
335c4bbdfSmrg *
435c4bbdfSmrg * Permission to use, copy, modify, distribute, and sell this software and its
535c4bbdfSmrg * documentation for any purpose is hereby granted without fee, provided that
635c4bbdfSmrg * the above copyright notice appear in all copies and that both that copyright
735c4bbdfSmrg * notice and this permission notice appear in supporting documentation, and
835c4bbdfSmrg * that the name of the copyright holders not be used in advertising or
935c4bbdfSmrg * publicity pertaining to distribution of the software without specific,
1035c4bbdfSmrg * written prior permission.  The copyright holders make no representations
1135c4bbdfSmrg * about the suitability of this software for any purpose.  It is provided "as
1235c4bbdfSmrg * is" without express or implied warranty.
1335c4bbdfSmrg *
1435c4bbdfSmrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
1535c4bbdfSmrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
1635c4bbdfSmrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
1735c4bbdfSmrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
1835c4bbdfSmrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
1935c4bbdfSmrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
2035c4bbdfSmrg * OF THIS SOFTWARE.
2135c4bbdfSmrg *
2235c4bbdfSmrg * Authors: Dave Airlie
2335c4bbdfSmrg */
2435c4bbdfSmrg
2535c4bbdfSmrg#include "randrstr.h"
2635c4bbdfSmrg#include "swaprep.h"
2735c4bbdfSmrg
2835c4bbdfSmrgRESTYPE RRProviderType;
2935c4bbdfSmrg
3035c4bbdfSmrg/*
3135c4bbdfSmrg * Initialize provider type error value
3235c4bbdfSmrg */
3335c4bbdfSmrgvoid
3435c4bbdfSmrgRRProviderInitErrorValue(void)
3535c4bbdfSmrg{
3635c4bbdfSmrg    SetResourceTypeErrorValue(RRProviderType, RRErrorBase + BadRRProvider);
3735c4bbdfSmrg}
3835c4bbdfSmrg
3935c4bbdfSmrg#define ADD_PROVIDER(_pScreen) do {                                 \
4035c4bbdfSmrg    pScrPriv = rrGetScrPriv((_pScreen));                            \
4135c4bbdfSmrg    if (pScrPriv->provider) {                                   \
4235c4bbdfSmrg        providers[count_providers] = pScrPriv->provider->id;    \
4335c4bbdfSmrg        if (client->swapped)                                    \
4435c4bbdfSmrg            swapl(&providers[count_providers]);                 \
4535c4bbdfSmrg        count_providers++;                                      \
4635c4bbdfSmrg    }                                                           \
4735c4bbdfSmrg    } while(0)
4835c4bbdfSmrg
4935c4bbdfSmrgint
5035c4bbdfSmrgProcRRGetProviders (ClientPtr client)
5135c4bbdfSmrg{
5235c4bbdfSmrg    REQUEST(xRRGetProvidersReq);
5335c4bbdfSmrg    xRRGetProvidersReply rep;
5435c4bbdfSmrg    WindowPtr pWin;
5535c4bbdfSmrg    ScreenPtr pScreen;
5635c4bbdfSmrg    rrScrPrivPtr pScrPriv;
5735c4bbdfSmrg    int rc;
5835c4bbdfSmrg    CARD8 *extra;
5935c4bbdfSmrg    unsigned int extraLen;
6035c4bbdfSmrg    RRProvider *providers;
6135c4bbdfSmrg    int total_providers = 0, count_providers = 0;
6235c4bbdfSmrg    ScreenPtr iter;
6335c4bbdfSmrg
6435c4bbdfSmrg    REQUEST_SIZE_MATCH(xRRGetProvidersReq);
6535c4bbdfSmrg    rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
6635c4bbdfSmrg    if (rc != Success)
6735c4bbdfSmrg        return rc;
6835c4bbdfSmrg
6935c4bbdfSmrg    pScreen = pWin->drawable.pScreen;
7035c4bbdfSmrg
7135c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
7235c4bbdfSmrg
7335c4bbdfSmrg    if (pScrPriv->provider)
7435c4bbdfSmrg        total_providers++;
7535c4bbdfSmrg    xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
7635c4bbdfSmrg        pScrPriv = rrGetScrPriv(iter);
7735c4bbdfSmrg        total_providers += pScrPriv->provider ? 1 : 0;
7835c4bbdfSmrg    }
7935c4bbdfSmrg    xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
8035c4bbdfSmrg        pScrPriv = rrGetScrPriv(iter);
8135c4bbdfSmrg        total_providers += pScrPriv->provider ? 1 : 0;
8235c4bbdfSmrg    }
8335c4bbdfSmrg    xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
8435c4bbdfSmrg        pScrPriv = rrGetScrPriv(iter);
8535c4bbdfSmrg        total_providers += pScrPriv->provider ? 1 : 0;
8635c4bbdfSmrg    }
8735c4bbdfSmrg
8835c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
8935c4bbdfSmrg
9035c4bbdfSmrg    if (!pScrPriv)
9135c4bbdfSmrg    {
9235c4bbdfSmrg        rep = (xRRGetProvidersReply) {
9335c4bbdfSmrg            .type = X_Reply,
9435c4bbdfSmrg            .sequenceNumber = client->sequence,
9535c4bbdfSmrg            .length = 0,
9635c4bbdfSmrg            .timestamp = currentTime.milliseconds,
9735c4bbdfSmrg            .nProviders = 0
9835c4bbdfSmrg        };
9935c4bbdfSmrg        extra = NULL;
10035c4bbdfSmrg        extraLen = 0;
10135c4bbdfSmrg    } else {
10235c4bbdfSmrg        rep = (xRRGetProvidersReply) {
10335c4bbdfSmrg            .type = X_Reply,
10435c4bbdfSmrg            .sequenceNumber = client->sequence,
10535c4bbdfSmrg            .timestamp = pScrPriv->lastSetTime.milliseconds,
10635c4bbdfSmrg            .nProviders = total_providers,
10735c4bbdfSmrg            .length = total_providers
10835c4bbdfSmrg        };
10935c4bbdfSmrg        extraLen = rep.length << 2;
11035c4bbdfSmrg        if (extraLen) {
11135c4bbdfSmrg            extra = malloc(extraLen);
11235c4bbdfSmrg            if (!extra)
11335c4bbdfSmrg                return BadAlloc;
11435c4bbdfSmrg        } else
11535c4bbdfSmrg            extra = NULL;
11635c4bbdfSmrg
11735c4bbdfSmrg        providers = (RRProvider *)extra;
11835c4bbdfSmrg        ADD_PROVIDER(pScreen);
11935c4bbdfSmrg        xorg_list_for_each_entry(iter, &pScreen->output_slave_list, output_head) {
12035c4bbdfSmrg            ADD_PROVIDER(iter);
12135c4bbdfSmrg        }
12235c4bbdfSmrg        xorg_list_for_each_entry(iter, &pScreen->offload_slave_list, offload_head) {
12335c4bbdfSmrg            ADD_PROVIDER(iter);
12435c4bbdfSmrg        }
12535c4bbdfSmrg        xorg_list_for_each_entry(iter, &pScreen->unattached_list, unattached_head) {
12635c4bbdfSmrg            ADD_PROVIDER(iter);
12735c4bbdfSmrg        }
12835c4bbdfSmrg    }
12935c4bbdfSmrg
13035c4bbdfSmrg    if (client->swapped) {
13135c4bbdfSmrg        swaps(&rep.sequenceNumber);
13235c4bbdfSmrg        swapl(&rep.length);
13335c4bbdfSmrg        swapl(&rep.timestamp);
13435c4bbdfSmrg        swaps(&rep.nProviders);
13535c4bbdfSmrg    }
13635c4bbdfSmrg    WriteToClient(client, sizeof(xRRGetProvidersReply), (char *)&rep);
13735c4bbdfSmrg    if (extraLen)
13835c4bbdfSmrg    {
13935c4bbdfSmrg        WriteToClient (client, extraLen, (char *) extra);
14035c4bbdfSmrg        free(extra);
14135c4bbdfSmrg    }
14235c4bbdfSmrg    return Success;
14335c4bbdfSmrg}
14435c4bbdfSmrg
14535c4bbdfSmrgint
14635c4bbdfSmrgProcRRGetProviderInfo (ClientPtr client)
14735c4bbdfSmrg{
14835c4bbdfSmrg    REQUEST(xRRGetProviderInfoReq);
14935c4bbdfSmrg    xRRGetProviderInfoReply rep;
15035c4bbdfSmrg    rrScrPrivPtr pScrPriv, pScrProvPriv;
15135c4bbdfSmrg    RRProviderPtr provider;
15235c4bbdfSmrg    ScreenPtr pScreen;
15335c4bbdfSmrg    CARD8 *extra;
15435c4bbdfSmrg    unsigned int extraLen = 0;
15535c4bbdfSmrg    RRCrtc *crtcs;
15635c4bbdfSmrg    RROutput *outputs;
15735c4bbdfSmrg    int i;
15835c4bbdfSmrg    char *name;
15935c4bbdfSmrg    ScreenPtr provscreen;
16035c4bbdfSmrg    RRProvider *providers;
16135c4bbdfSmrg    uint32_t *prov_cap;
16235c4bbdfSmrg
16335c4bbdfSmrg    REQUEST_SIZE_MATCH(xRRGetProviderInfoReq);
16435c4bbdfSmrg    VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
16535c4bbdfSmrg
16635c4bbdfSmrg    pScreen = provider->pScreen;
16735c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
16835c4bbdfSmrg
16935c4bbdfSmrg    rep = (xRRGetProviderInfoReply) {
17035c4bbdfSmrg        .type = X_Reply,
17135c4bbdfSmrg        .status = RRSetConfigSuccess,
17235c4bbdfSmrg        .sequenceNumber = client->sequence,
17335c4bbdfSmrg        .length = 0,
17435c4bbdfSmrg        .capabilities = provider->capabilities,
17535c4bbdfSmrg        .nameLength = provider->nameLength,
17635c4bbdfSmrg        .timestamp = pScrPriv->lastSetTime.milliseconds,
17735c4bbdfSmrg        .nCrtcs = pScrPriv->numCrtcs,
17835c4bbdfSmrg        .nOutputs = pScrPriv->numOutputs,
17935c4bbdfSmrg        .nAssociatedProviders = 0
18035c4bbdfSmrg    };
18135c4bbdfSmrg
18235c4bbdfSmrg    /* count associated providers */
18335c4bbdfSmrg    if (provider->offload_sink)
18435c4bbdfSmrg        rep.nAssociatedProviders++;
18535c4bbdfSmrg    if (provider->output_source)
18635c4bbdfSmrg        rep.nAssociatedProviders++;
18735c4bbdfSmrg    xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head)
18835c4bbdfSmrg        rep.nAssociatedProviders++;
18935c4bbdfSmrg    xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head)
19035c4bbdfSmrg        rep.nAssociatedProviders++;
19135c4bbdfSmrg
19235c4bbdfSmrg    rep.length = (pScrPriv->numCrtcs + pScrPriv->numOutputs +
19335c4bbdfSmrg                  (rep.nAssociatedProviders * 2) + bytes_to_int32(rep.nameLength));
19435c4bbdfSmrg
19535c4bbdfSmrg    extraLen = rep.length << 2;
19635c4bbdfSmrg    if (extraLen) {
19735c4bbdfSmrg        extra = malloc(extraLen);
19835c4bbdfSmrg        if (!extra)
19935c4bbdfSmrg            return BadAlloc;
20035c4bbdfSmrg    }
20135c4bbdfSmrg    else
20235c4bbdfSmrg        extra = NULL;
20335c4bbdfSmrg
20435c4bbdfSmrg    crtcs = (RRCrtc *)extra;
20535c4bbdfSmrg    outputs = (RROutput *)(crtcs + rep.nCrtcs);
20635c4bbdfSmrg    providers = (RRProvider *)(outputs + rep.nOutputs);
20735c4bbdfSmrg    prov_cap = (unsigned int *)(providers + rep.nAssociatedProviders);
20835c4bbdfSmrg    name = (char *)(prov_cap + rep.nAssociatedProviders);
20935c4bbdfSmrg
21035c4bbdfSmrg    for (i = 0; i < pScrPriv->numCrtcs; i++) {
21135c4bbdfSmrg        crtcs[i] = pScrPriv->crtcs[i]->id;
21235c4bbdfSmrg        if (client->swapped)
21335c4bbdfSmrg            swapl(&crtcs[i]);
21435c4bbdfSmrg    }
21535c4bbdfSmrg
21635c4bbdfSmrg    for (i = 0; i < pScrPriv->numOutputs; i++) {
21735c4bbdfSmrg        outputs[i] = pScrPriv->outputs[i]->id;
21835c4bbdfSmrg        if (client->swapped)
21935c4bbdfSmrg            swapl(&outputs[i]);
22035c4bbdfSmrg    }
22135c4bbdfSmrg
22235c4bbdfSmrg    i = 0;
22335c4bbdfSmrg    if (provider->offload_sink) {
22435c4bbdfSmrg        providers[i] = provider->offload_sink->id;
22535c4bbdfSmrg        if (client->swapped)
22635c4bbdfSmrg            swapl(&providers[i]);
22735c4bbdfSmrg        prov_cap[i] = RR_Capability_SinkOffload;
22835c4bbdfSmrg        if (client->swapped)
22935c4bbdfSmrg            swapl(&prov_cap[i]);
23035c4bbdfSmrg        i++;
23135c4bbdfSmrg    }
23235c4bbdfSmrg    if (provider->output_source) {
23335c4bbdfSmrg        providers[i] = provider->output_source->id;
23435c4bbdfSmrg        if (client->swapped)
23535c4bbdfSmrg            swapl(&providers[i]);
23635c4bbdfSmrg        prov_cap[i] = RR_Capability_SourceOutput;
23735c4bbdfSmrg            swapl(&prov_cap[i]);
23835c4bbdfSmrg        i++;
23935c4bbdfSmrg    }
24035c4bbdfSmrg    xorg_list_for_each_entry(provscreen, &pScreen->output_slave_list, output_head) {
24135c4bbdfSmrg        pScrProvPriv = rrGetScrPriv(provscreen);
24235c4bbdfSmrg        providers[i] = pScrProvPriv->provider->id;
24335c4bbdfSmrg        if (client->swapped)
24435c4bbdfSmrg            swapl(&providers[i]);
24535c4bbdfSmrg        prov_cap[i] = RR_Capability_SinkOutput;
24635c4bbdfSmrg        if (client->swapped)
24735c4bbdfSmrg            swapl(&prov_cap[i]);
24835c4bbdfSmrg        i++;
24935c4bbdfSmrg    }
25035c4bbdfSmrg    xorg_list_for_each_entry(provscreen, &pScreen->offload_slave_list, offload_head) {
25135c4bbdfSmrg        pScrProvPriv = rrGetScrPriv(provscreen);
25235c4bbdfSmrg        providers[i] = pScrProvPriv->provider->id;
25335c4bbdfSmrg        if (client->swapped)
25435c4bbdfSmrg            swapl(&providers[i]);
25535c4bbdfSmrg        prov_cap[i] = RR_Capability_SourceOffload;
25635c4bbdfSmrg        if (client->swapped)
25735c4bbdfSmrg            swapl(&prov_cap[i]);
25835c4bbdfSmrg        i++;
25935c4bbdfSmrg    }
26035c4bbdfSmrg
26135c4bbdfSmrg
26235c4bbdfSmrg    memcpy(name, provider->name, rep.nameLength);
26335c4bbdfSmrg    if (client->swapped) {
26435c4bbdfSmrg              swaps(&rep.sequenceNumber);
26535c4bbdfSmrg        swapl(&rep.length);
26635c4bbdfSmrg        swapl(&rep.capabilities);
26735c4bbdfSmrg        swaps(&rep.nCrtcs);
26835c4bbdfSmrg        swaps(&rep.nOutputs);
26935c4bbdfSmrg        swaps(&rep.nameLength);
27035c4bbdfSmrg    }
27135c4bbdfSmrg    WriteToClient(client, sizeof(xRRGetProviderInfoReply), (char *)&rep);
27235c4bbdfSmrg    if (extraLen)
27335c4bbdfSmrg    {
27435c4bbdfSmrg        WriteToClient (client, extraLen, (char *) extra);
27535c4bbdfSmrg        free(extra);
27635c4bbdfSmrg    }
27735c4bbdfSmrg    return Success;
27835c4bbdfSmrg}
27935c4bbdfSmrg
28035c4bbdfSmrgint
28135c4bbdfSmrgProcRRSetProviderOutputSource(ClientPtr client)
28235c4bbdfSmrg{
28335c4bbdfSmrg    REQUEST(xRRSetProviderOutputSourceReq);
28435c4bbdfSmrg    rrScrPrivPtr pScrPriv;
28535c4bbdfSmrg    RRProviderPtr provider, source_provider = NULL;
28635c4bbdfSmrg    ScreenPtr pScreen;
28735c4bbdfSmrg
28835c4bbdfSmrg    REQUEST_SIZE_MATCH(xRRSetProviderOutputSourceReq);
28935c4bbdfSmrg
29035c4bbdfSmrg    VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
29135c4bbdfSmrg
29235c4bbdfSmrg    if (!(provider->capabilities & RR_Capability_SinkOutput))
29335c4bbdfSmrg        return BadValue;
29435c4bbdfSmrg
29535c4bbdfSmrg    if (stuff->source_provider) {
29635c4bbdfSmrg        VERIFY_RR_PROVIDER(stuff->source_provider, source_provider, DixReadAccess);
29735c4bbdfSmrg
29835c4bbdfSmrg        if (!(source_provider->capabilities & RR_Capability_SourceOutput))
29935c4bbdfSmrg            return BadValue;
30035c4bbdfSmrg    }
30135c4bbdfSmrg
30235c4bbdfSmrg    pScreen = provider->pScreen;
30335c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
30435c4bbdfSmrg
30535c4bbdfSmrg    pScrPriv->rrProviderSetOutputSource(pScreen, provider, source_provider);
30635c4bbdfSmrg
30735c4bbdfSmrg    provider->changed = TRUE;
30835c4bbdfSmrg    RRSetChanged(pScreen);
30935c4bbdfSmrg
31035c4bbdfSmrg    RRTellChanged (pScreen);
31135c4bbdfSmrg
31235c4bbdfSmrg    return Success;
31335c4bbdfSmrg}
31435c4bbdfSmrg
31535c4bbdfSmrgint
31635c4bbdfSmrgProcRRSetProviderOffloadSink(ClientPtr client)
31735c4bbdfSmrg{
31835c4bbdfSmrg    REQUEST(xRRSetProviderOffloadSinkReq);
31935c4bbdfSmrg    rrScrPrivPtr pScrPriv;
32035c4bbdfSmrg    RRProviderPtr provider, sink_provider = NULL;
32135c4bbdfSmrg    ScreenPtr pScreen;
32235c4bbdfSmrg
32335c4bbdfSmrg    REQUEST_SIZE_MATCH(xRRSetProviderOffloadSinkReq);
32435c4bbdfSmrg
32535c4bbdfSmrg    VERIFY_RR_PROVIDER(stuff->provider, provider, DixReadAccess);
32635c4bbdfSmrg    if (!(provider->capabilities & RR_Capability_SourceOffload))
32735c4bbdfSmrg        return BadValue;
32835c4bbdfSmrg    if (!provider->pScreen->isGPU)
32935c4bbdfSmrg        return BadValue;
33035c4bbdfSmrg
33135c4bbdfSmrg    if (stuff->sink_provider) {
33235c4bbdfSmrg        VERIFY_RR_PROVIDER(stuff->sink_provider, sink_provider, DixReadAccess);
33335c4bbdfSmrg        if (!(sink_provider->capabilities & RR_Capability_SinkOffload))
33435c4bbdfSmrg            return BadValue;
33535c4bbdfSmrg    }
33635c4bbdfSmrg    pScreen = provider->pScreen;
33735c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
33835c4bbdfSmrg
33935c4bbdfSmrg    pScrPriv->rrProviderSetOffloadSink(pScreen, provider, sink_provider);
34035c4bbdfSmrg
34135c4bbdfSmrg    provider->changed = TRUE;
34235c4bbdfSmrg    RRSetChanged(pScreen);
34335c4bbdfSmrg
34435c4bbdfSmrg    RRTellChanged (pScreen);
34535c4bbdfSmrg
34635c4bbdfSmrg    return Success;
34735c4bbdfSmrg}
34835c4bbdfSmrg
34935c4bbdfSmrgRRProviderPtr
35035c4bbdfSmrgRRProviderCreate(ScreenPtr pScreen, const char *name,
35135c4bbdfSmrg                 int nameLength)
35235c4bbdfSmrg{
35335c4bbdfSmrg    RRProviderPtr provider;
35435c4bbdfSmrg    rrScrPrivPtr pScrPriv;
35535c4bbdfSmrg
35635c4bbdfSmrg    pScrPriv = rrGetScrPriv(pScreen);
35735c4bbdfSmrg
35835c4bbdfSmrg    provider = calloc(1, sizeof(RRProviderRec) + nameLength + 1);
35935c4bbdfSmrg    if (!provider)
36035c4bbdfSmrg        return NULL;
36135c4bbdfSmrg
36235c4bbdfSmrg    provider->id = FakeClientID(0);
36335c4bbdfSmrg    provider->pScreen = pScreen;
36435c4bbdfSmrg    provider->name = (char *) (provider + 1);
36535c4bbdfSmrg    provider->nameLength = nameLength;
36635c4bbdfSmrg    memcpy(provider->name, name, nameLength);
36735c4bbdfSmrg    provider->name[nameLength] = '\0';
36835c4bbdfSmrg    provider->changed = FALSE;
36935c4bbdfSmrg
37035c4bbdfSmrg    if (!AddResource (provider->id, RRProviderType, (void *) provider))
37135c4bbdfSmrg        return NULL;
37235c4bbdfSmrg    pScrPriv->provider = provider;
37335c4bbdfSmrg    return provider;
37435c4bbdfSmrg}
37535c4bbdfSmrg
37635c4bbdfSmrg/*
37735c4bbdfSmrg * Destroy a provider at shutdown
37835c4bbdfSmrg */
37935c4bbdfSmrgvoid
38035c4bbdfSmrgRRProviderDestroy (RRProviderPtr provider)
38135c4bbdfSmrg{
38235c4bbdfSmrg    FreeResource (provider->id, 0);
38335c4bbdfSmrg}
38435c4bbdfSmrg
38535c4bbdfSmrgvoid
38635c4bbdfSmrgRRProviderSetCapabilities(RRProviderPtr provider, uint32_t capabilities)
38735c4bbdfSmrg{
38835c4bbdfSmrg    provider->capabilities = capabilities;
38935c4bbdfSmrg}
39035c4bbdfSmrg
39135c4bbdfSmrgstatic int
39235c4bbdfSmrgRRProviderDestroyResource (void *value, XID pid)
39335c4bbdfSmrg{
39435c4bbdfSmrg    RRProviderPtr provider = (RRProviderPtr)value;
39535c4bbdfSmrg    ScreenPtr pScreen = provider->pScreen;
39635c4bbdfSmrg
39735c4bbdfSmrg    if (pScreen)
39835c4bbdfSmrg    {
39935c4bbdfSmrg        rrScrPriv(pScreen);
40035c4bbdfSmrg
40135c4bbdfSmrg        if (pScrPriv->rrProviderDestroy)
40235c4bbdfSmrg            (*pScrPriv->rrProviderDestroy)(pScreen, provider);
40335c4bbdfSmrg        pScrPriv->provider = NULL;
40435c4bbdfSmrg    }
40535c4bbdfSmrg    free(provider);
40635c4bbdfSmrg    return 1;
40735c4bbdfSmrg}
40835c4bbdfSmrg
40935c4bbdfSmrgBool
41035c4bbdfSmrgRRProviderInit(void)
41135c4bbdfSmrg{
41235c4bbdfSmrg    RRProviderType = CreateNewResourceType(RRProviderDestroyResource, "Provider");
41335c4bbdfSmrg    if (!RRProviderType)
41435c4bbdfSmrg        return FALSE;
41535c4bbdfSmrg
41635c4bbdfSmrg    return TRUE;
41735c4bbdfSmrg}
41835c4bbdfSmrg
41935c4bbdfSmrgextern _X_EXPORT Bool
42035c4bbdfSmrgRRProviderLookup(XID id, RRProviderPtr *provider_p)
42135c4bbdfSmrg{
42235c4bbdfSmrg    int rc = dixLookupResourceByType((void **)provider_p, id,
42335c4bbdfSmrg                                   RRProviderType, NullClient, DixReadAccess);
42435c4bbdfSmrg    if (rc == Success)
42535c4bbdfSmrg        return TRUE;
42635c4bbdfSmrg    return FALSE;
42735c4bbdfSmrg}
42835c4bbdfSmrg
42935c4bbdfSmrgvoid
43035c4bbdfSmrgRRDeliverProviderEvent(ClientPtr client, WindowPtr pWin, RRProviderPtr provider)
43135c4bbdfSmrg{
43235c4bbdfSmrg    ScreenPtr pScreen = pWin->drawable.pScreen;
43335c4bbdfSmrg
43435c4bbdfSmrg    rrScrPriv(pScreen);
43535c4bbdfSmrg
43635c4bbdfSmrg    xRRProviderChangeNotifyEvent pe = {
43735c4bbdfSmrg        .type = RRNotify + RREventBase,
43835c4bbdfSmrg        .subCode = RRNotify_ProviderChange,
43935c4bbdfSmrg        .timestamp = pScrPriv->lastSetTime.milliseconds,
44035c4bbdfSmrg        .window = pWin->drawable.id,
44135c4bbdfSmrg        .provider = provider->id
44235c4bbdfSmrg    };
44335c4bbdfSmrg
44435c4bbdfSmrg    WriteEventsToClient(client, 1, (xEvent *) &pe);
44535c4bbdfSmrg}
446