xserver

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

rrlease.c (9077B)


      1 /*
      2  * Copyright © 2017 Keith Packard
      3  *
      4  * Permission to use, copy, modify, distribute, and sell this software and its
      5  * documentation for any purpose is hereby granted without fee, provided that
      6  * the above copyright notice appear in all copies and that both that copyright
      7  * notice and this permission notice appear in supporting documentation, and
      8  * that the name of the copyright holders not be used in advertising or
      9  * publicity pertaining to distribution of the software without specific,
     10  * written prior permission.  The copyright holders make no representations
     11  * about the suitability of this software for any purpose.  It is provided "as
     12  * is" without express or implied warranty.
     13  *
     14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
     15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
     16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
     17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
     18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
     19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
     20  * OF THIS SOFTWARE.
     21  */
     22 
     23 #include "randrstr.h"
     24 #include "swaprep.h"
     25 #include <unistd.h>
     26 
     27 RESTYPE RRLeaseType;
     28 
     29 /*
     30  * Notify of some lease change
     31  */
     32 void
     33 RRDeliverLeaseEvent(ClientPtr client, WindowPtr window)
     34 {
     35     ScreenPtr screen = window->drawable.pScreen;
     36     rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
     37     RRLeasePtr lease;
     38 
     39     UpdateCurrentTimeIf();
     40     xorg_list_for_each_entry(lease, &scr_priv->leases, list) {
     41         if (lease->id != None && (lease->state == RRLeaseCreating ||
     42                                   lease->state == RRLeaseTerminating))
     43         {
     44             xRRLeaseNotifyEvent le = (xRRLeaseNotifyEvent) {
     45                 .type = RRNotify + RREventBase,
     46                 .subCode = RRNotify_Lease,
     47                 .timestamp = currentTime.milliseconds,
     48                 .window = window->drawable.id,
     49                 .lease = lease->id,
     50                 .created = lease->state == RRLeaseCreating,
     51             };
     52             WriteEventsToClient(client, 1, (xEvent *) &le);
     53         }
     54     }
     55 }
     56 
     57 /*
     58  * Change the state of a lease and let anyone watching leases know
     59  */
     60 static void
     61 RRLeaseChangeState(RRLeasePtr lease, RRLeaseState old, RRLeaseState new)
     62 {
     63     ScreenPtr screen = lease->screen;
     64     rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
     65 
     66     lease->state = old;
     67     scr_priv->leasesChanged = TRUE;
     68     RRSetChanged(lease->screen);
     69     RRTellChanged(lease->screen);
     70     scr_priv->leasesChanged = FALSE;
     71     lease->state = new;
     72 }
     73 
     74 /*
     75  * Allocate and initialize a lease
     76  */
     77 static RRLeasePtr
     78 RRLeaseAlloc(ScreenPtr screen, RRLease lid, int numCrtcs, int numOutputs)
     79 {
     80     RRLeasePtr lease;
     81     lease = calloc(1,
     82                    sizeof(RRLeaseRec) +
     83                    numCrtcs * sizeof (RRCrtcPtr) +
     84                    numOutputs * sizeof(RROutputPtr));
     85     if (!lease)
     86         return NULL;
     87     lease->screen = screen;
     88     xorg_list_init(&lease->list);
     89     lease->id = lid;
     90     lease->state = RRLeaseCreating;
     91     lease->numCrtcs = numCrtcs;
     92     lease->numOutputs = numOutputs;
     93     lease->crtcs = (RRCrtcPtr *) (lease + 1);
     94     lease->outputs = (RROutputPtr *) (lease->crtcs + numCrtcs);
     95     return lease;
     96 }
     97 
     98 /*
     99  * Check if a crtc is leased
    100  */
    101 Bool
    102 RRCrtcIsLeased(RRCrtcPtr crtc)
    103 {
    104     ScreenPtr screen = crtc->pScreen;
    105     rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
    106     RRLeasePtr lease;
    107     int c;
    108 
    109     xorg_list_for_each_entry(lease, &scr_priv->leases, list) {
    110         for (c = 0; c < lease->numCrtcs; c++)
    111             if (lease->crtcs[c] == crtc)
    112                 return TRUE;
    113     }
    114     return FALSE;
    115 }
    116 
    117 /*
    118  * Check if an output is leased
    119  */
    120 Bool
    121 RROutputIsLeased(RROutputPtr output)
    122 {
    123     ScreenPtr screen = output->pScreen;
    124     rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
    125     RRLeasePtr lease;
    126     int o;
    127 
    128     xorg_list_for_each_entry(lease, &scr_priv->leases, list) {
    129         for (o = 0; o < lease->numOutputs; o++)
    130             if (lease->outputs[o] == output)
    131                 return TRUE;
    132     }
    133     return FALSE;
    134 }
    135 
    136 /*
    137  * A lease has been terminated.
    138  * The driver is responsible for noticing and
    139  * calling this function when that happens
    140  */
    141 
    142 void
    143 RRLeaseTerminated(RRLeasePtr lease)
    144 {
    145     /* Notify clients with events, but only if this isn't during lease creation */
    146     if (lease->state == RRLeaseRunning)
    147         RRLeaseChangeState(lease, RRLeaseTerminating, RRLeaseTerminating);
    148 
    149     if (lease->id != None)
    150         FreeResource(lease->id, RT_NONE);
    151 
    152     xorg_list_del(&lease->list);
    153 }
    154 
    155 /*
    156  * A lease is completely shut down and is
    157  * ready to be deallocated
    158  */
    159 
    160 void
    161 RRLeaseFree(RRLeasePtr lease)
    162 {
    163     free(lease);
    164 }
    165 
    166 /*
    167  * Ask the driver to terminate a lease. The
    168  * driver will call RRLeaseTerminated when that has
    169  * finished, which may be some time after this function returns
    170  * if the driver operation is asynchronous
    171  */
    172 void
    173 RRTerminateLease(RRLeasePtr lease)
    174 {
    175     ScreenPtr screen = lease->screen;
    176     rrScrPrivPtr scr_priv = rrGetScrPriv(screen);
    177 
    178     scr_priv->rrTerminateLease(screen, lease);
    179 }
    180 
    181 /*
    182  * Destroy a lease resource ID. All this
    183  * does is note that the lease no longer has an ID, and
    184  * so doesn't appear over the protocol anymore.
    185  */
    186 static int
    187 RRLeaseDestroyResource(void *value, XID pid)
    188 {
    189     RRLeasePtr lease = value;
    190 
    191     lease->id = None;
    192     return 1;
    193 }
    194 
    195 /*
    196  * Create the lease resource type during server initialization
    197  */
    198 Bool
    199 RRLeaseInit(void)
    200 {
    201     RRLeaseType = CreateNewResourceType(RRLeaseDestroyResource, "LEASE");
    202     if (!RRLeaseType)
    203         return FALSE;
    204     return TRUE;
    205 }
    206 
    207 int
    208 ProcRRCreateLease(ClientPtr client)
    209 {
    210     REQUEST(xRRCreateLeaseReq);
    211     xRRCreateLeaseReply rep;
    212     WindowPtr window;
    213     ScreenPtr screen;
    214     rrScrPrivPtr scr_priv;
    215     RRLeasePtr lease;
    216     RRCrtc *crtcIds;
    217     RROutput *outputIds;
    218     int fd;
    219     int rc;
    220     unsigned long len;
    221     int c, o;
    222 
    223     REQUEST_AT_LEAST_SIZE(xRRCreateLeaseReq);
    224 
    225     LEGAL_NEW_RESOURCE(stuff->lid, client);
    226 
    227     rc = dixLookupWindow(&window, stuff->window, client, DixGetAttrAccess);
    228     if (rc != Success)
    229         return rc;
    230 
    231     len = client->req_len - bytes_to_int32(sizeof(xRRCreateLeaseReq));
    232 
    233     if (len != stuff->nCrtcs + stuff->nOutputs)
    234         return BadLength;
    235 
    236     screen = window->drawable.pScreen;
    237     scr_priv = rrGetScrPriv(screen);
    238 
    239     if (!scr_priv)
    240         return BadMatch;
    241 
    242     if (!scr_priv->rrCreateLease)
    243         return BadMatch;
    244 
    245     /* Allocate a structure to hold all of the lease information */
    246 
    247     lease = RRLeaseAlloc(screen, stuff->lid, stuff->nCrtcs, stuff->nOutputs);
    248     if (!lease)
    249         return BadAlloc;
    250 
    251     /* Look up all of the crtcs */
    252     crtcIds = (RRCrtc *) (stuff + 1);
    253     for (c = 0; c < stuff->nCrtcs; c++) {
    254         RRCrtcPtr crtc;
    255 
    256 	rc = dixLookupResourceByType((void **)&crtc, crtcIds[c],
    257                                      RRCrtcType, client, DixSetAttrAccess);
    258 
    259         if (rc != Success) {
    260             client->errorValue = crtcIds[c];
    261             goto bail_lease;
    262         }
    263 
    264         if (RRCrtcIsLeased(crtc)) {
    265             client->errorValue = crtcIds[c];
    266             rc = BadAccess;
    267             goto bail_lease;
    268         }
    269 
    270         lease->crtcs[c] = crtc;
    271     }
    272 
    273     /* Look up all of the outputs */
    274     outputIds = (RROutput *) (crtcIds + stuff->nCrtcs);
    275     for (o = 0; o < stuff->nOutputs; o++) {
    276         RROutputPtr output;
    277 
    278 	rc = dixLookupResourceByType((void **)&output, outputIds[o],
    279                                      RROutputType, client, DixSetAttrAccess);
    280         if (rc != Success) {
    281             client->errorValue = outputIds[o];
    282             goto bail_lease;
    283         }
    284 
    285         if (RROutputIsLeased(output)) {
    286             client->errorValue = outputIds[o];
    287             rc = BadAccess;
    288             goto bail_lease;
    289         }
    290 
    291         lease->outputs[o] = output;
    292     }
    293 
    294     rc = scr_priv->rrCreateLease(screen, lease, &fd);
    295     if (rc != Success)
    296         goto bail_lease;
    297 
    298     xorg_list_add(&lease->list, &scr_priv->leases);
    299 
    300     if (!AddResource(stuff->lid, RRLeaseType, lease)) {
    301         close(fd);
    302         return BadAlloc;
    303     }
    304 
    305     if (WriteFdToClient(client, fd, TRUE) < 0) {
    306         RRTerminateLease(lease);
    307         close(fd);
    308         return BadAlloc;
    309     }
    310 
    311     RRLeaseChangeState(lease, RRLeaseCreating, RRLeaseRunning);
    312 
    313     rep = (xRRCreateLeaseReply) {
    314         .type = X_Reply,
    315         .nfd = 1,
    316         .sequenceNumber = client->sequence,
    317         .length = 0,
    318     };
    319 
    320     if (client->swapped) {
    321         swaps(&rep.sequenceNumber);
    322         swapl(&rep.length);
    323     }
    324 
    325     WriteToClient(client, sizeof (rep), &rep);
    326 
    327     return Success;
    328 
    329 bail_lease:
    330     free(lease);
    331     return rc;
    332 }
    333 
    334 int
    335 ProcRRFreeLease(ClientPtr client)
    336 {
    337     REQUEST(xRRFreeLeaseReq);
    338     RRLeasePtr lease;
    339 
    340     REQUEST_SIZE_MATCH(xRRFreeLeaseReq);
    341 
    342     VERIFY_RR_LEASE(stuff->lid, lease, DixDestroyAccess);
    343 
    344     if (stuff->terminate)
    345         RRTerminateLease(lease);
    346     else
    347         /* Get rid of the resource database entry */
    348         FreeResource(stuff->lid, RT_NONE);
    349 
    350     return Success;
    351 }