xserver

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

rrmode.c (9641B)


      1 /*
      2  * Copyright © 2006 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 
     25 RESTYPE RRModeType;
     26 
     27 static Bool
     28 RRModeEqual(xRRModeInfo * a, xRRModeInfo * b)
     29 {
     30     if (a->width != b->width)
     31         return FALSE;
     32     if (a->height != b->height)
     33         return FALSE;
     34     if (a->dotClock != b->dotClock)
     35         return FALSE;
     36     if (a->hSyncStart != b->hSyncStart)
     37         return FALSE;
     38     if (a->hSyncEnd != b->hSyncEnd)
     39         return FALSE;
     40     if (a->hTotal != b->hTotal)
     41         return FALSE;
     42     if (a->hSkew != b->hSkew)
     43         return FALSE;
     44     if (a->vSyncStart != b->vSyncStart)
     45         return FALSE;
     46     if (a->vSyncEnd != b->vSyncEnd)
     47         return FALSE;
     48     if (a->vTotal != b->vTotal)
     49         return FALSE;
     50     if (a->nameLength != b->nameLength)
     51         return FALSE;
     52     if (a->modeFlags != b->modeFlags)
     53         return FALSE;
     54     return TRUE;
     55 }
     56 
     57 /*
     58  * Keep a list so it's easy to find modes in the resource database.
     59  */
     60 static int num_modes;
     61 static RRModePtr *modes;
     62 
     63 static RRModePtr
     64 RRModeCreate(xRRModeInfo * modeInfo, const char *name, ScreenPtr userScreen)
     65 {
     66     RRModePtr mode, *newModes;
     67 
     68     if (!RRInit())
     69         return NULL;
     70 
     71     mode = malloc(sizeof(RRModeRec) + modeInfo->nameLength + 1);
     72     if (!mode)
     73         return NULL;
     74     mode->refcnt = 1;
     75     mode->mode = *modeInfo;
     76     mode->name = (char *) (mode + 1);
     77     memcpy(mode->name, name, modeInfo->nameLength);
     78     mode->name[modeInfo->nameLength] = '\0';
     79     mode->userScreen = userScreen;
     80 
     81     if (num_modes)
     82         newModes = reallocarray(modes, num_modes + 1, sizeof(RRModePtr));
     83     else
     84         newModes = malloc(sizeof(RRModePtr));
     85 
     86     if (!newModes) {
     87         free(mode);
     88         return NULL;
     89     }
     90 
     91     mode->mode.id = FakeClientID(0);
     92     if (!AddResource(mode->mode.id, RRModeType, (void *) mode)) {
     93         free(newModes);
     94         return NULL;
     95     }
     96     modes = newModes;
     97     modes[num_modes++] = mode;
     98 
     99     /*
    100      * give the caller a reference to this mode
    101      */
    102     ++mode->refcnt;
    103     return mode;
    104 }
    105 
    106 static RRModePtr
    107 RRModeFindByName(const char *name, CARD16 nameLength)
    108 {
    109     int i;
    110     RRModePtr mode;
    111 
    112     for (i = 0; i < num_modes; i++) {
    113         mode = modes[i];
    114         if (mode->mode.nameLength == nameLength &&
    115             !memcmp(name, mode->name, nameLength)) {
    116             return mode;
    117         }
    118     }
    119     return NULL;
    120 }
    121 
    122 RRModePtr
    123 RRModeGet(xRRModeInfo * modeInfo, const char *name)
    124 {
    125     int i;
    126 
    127     for (i = 0; i < num_modes; i++) {
    128         RRModePtr mode = modes[i];
    129 
    130         if (RRModeEqual(&mode->mode, modeInfo) &&
    131             !memcmp(name, mode->name, modeInfo->nameLength)) {
    132             ++mode->refcnt;
    133             return mode;
    134         }
    135     }
    136 
    137     return RRModeCreate(modeInfo, name, NULL);
    138 }
    139 
    140 static RRModePtr
    141 RRModeCreateUser(ScreenPtr pScreen,
    142                  xRRModeInfo * modeInfo, const char *name, int *error)
    143 {
    144     RRModePtr mode;
    145 
    146     mode = RRModeFindByName(name, modeInfo->nameLength);
    147     if (mode) {
    148         *error = BadName;
    149         return NULL;
    150     }
    151 
    152     mode = RRModeCreate(modeInfo, name, pScreen);
    153     if (!mode) {
    154         *error = BadAlloc;
    155         return NULL;
    156     }
    157     *error = Success;
    158     return mode;
    159 }
    160 
    161 RRModePtr *
    162 RRModesForScreen(ScreenPtr pScreen, int *num_ret)
    163 {
    164     rrScrPriv(pScreen);
    165     int o, c, m;
    166     RRModePtr *screen_modes;
    167     int num_screen_modes = 0;
    168 
    169     screen_modes = xallocarray((num_modes ? num_modes : 1), sizeof(RRModePtr));
    170     if (!screen_modes)
    171         return NULL;
    172 
    173     /*
    174      * Add modes from all outputs
    175      */
    176     for (o = 0; o < pScrPriv->numOutputs; o++) {
    177         RROutputPtr output = pScrPriv->outputs[o];
    178         int n;
    179 
    180         for (m = 0; m < output->numModes + output->numUserModes; m++) {
    181             RRModePtr mode = (m < output->numModes ?
    182                               output->modes[m] :
    183                               output->userModes[m - output->numModes]);
    184             for (n = 0; n < num_screen_modes; n++)
    185                 if (screen_modes[n] == mode)
    186                     break;
    187             if (n == num_screen_modes)
    188                 screen_modes[num_screen_modes++] = mode;
    189         }
    190     }
    191     /*
    192      * Add modes from all crtcs. The goal is to
    193      * make sure all available and active modes
    194      * are visible to the client
    195      */
    196     for (c = 0; c < pScrPriv->numCrtcs; c++) {
    197         RRCrtcPtr crtc = pScrPriv->crtcs[c];
    198         RRModePtr mode = crtc->mode;
    199         int n;
    200 
    201         if (!mode)
    202             continue;
    203         for (n = 0; n < num_screen_modes; n++)
    204             if (screen_modes[n] == mode)
    205                 break;
    206         if (n == num_screen_modes)
    207             screen_modes[num_screen_modes++] = mode;
    208     }
    209     /*
    210      * Add all user modes for this screen
    211      */
    212     for (m = 0; m < num_modes; m++) {
    213         RRModePtr mode = modes[m];
    214         int n;
    215 
    216         if (mode->userScreen != pScreen)
    217             continue;
    218         for (n = 0; n < num_screen_modes; n++)
    219             if (screen_modes[n] == mode)
    220                 break;
    221         if (n == num_screen_modes)
    222             screen_modes[num_screen_modes++] = mode;
    223     }
    224 
    225     *num_ret = num_screen_modes;
    226     return screen_modes;
    227 }
    228 
    229 void
    230 RRModeDestroy(RRModePtr mode)
    231 {
    232     int m;
    233 
    234     if (--mode->refcnt > 0)
    235         return;
    236     for (m = 0; m < num_modes; m++) {
    237         if (modes[m] == mode) {
    238             memmove(modes + m, modes + m + 1,
    239                     (num_modes - m - 1) * sizeof(RRModePtr));
    240             num_modes--;
    241             if (!num_modes) {
    242                 free(modes);
    243                 modes = NULL;
    244             }
    245             break;
    246         }
    247     }
    248 
    249     free(mode);
    250 }
    251 
    252 static int
    253 RRModeDestroyResource(void *value, XID pid)
    254 {
    255     RRModeDestroy((RRModePtr) value);
    256     return 1;
    257 }
    258 
    259 /*
    260  * Initialize mode type
    261  */
    262 Bool
    263 RRModeInit(void)
    264 {
    265     assert(num_modes == 0);
    266     assert(modes == NULL);
    267     RRModeType = CreateNewResourceType(RRModeDestroyResource, "MODE");
    268     if (!RRModeType)
    269         return FALSE;
    270 
    271     return TRUE;
    272 }
    273 
    274 /*
    275  * Initialize mode type error value
    276  */
    277 void
    278 RRModeInitErrorValue(void)
    279 {
    280     SetResourceTypeErrorValue(RRModeType, RRErrorBase + BadRRMode);
    281 }
    282 
    283 int
    284 ProcRRCreateMode(ClientPtr client)
    285 {
    286     REQUEST(xRRCreateModeReq);
    287     xRRCreateModeReply rep;
    288     WindowPtr pWin;
    289     ScreenPtr pScreen;
    290     xRRModeInfo *modeInfo;
    291     long units_after;
    292     char *name;
    293     int error, rc;
    294     RRModePtr mode;
    295 
    296     REQUEST_AT_LEAST_SIZE(xRRCreateModeReq);
    297     rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
    298     if (rc != Success)
    299         return rc;
    300 
    301     pScreen = pWin->drawable.pScreen;
    302 
    303     modeInfo = &stuff->modeInfo;
    304     name = (char *) (stuff + 1);
    305     units_after = (stuff->length - bytes_to_int32(sizeof(xRRCreateModeReq)));
    306 
    307     /* check to make sure requested name fits within the data provided */
    308     if (bytes_to_int32(modeInfo->nameLength) > units_after)
    309         return BadLength;
    310 
    311     mode = RRModeCreateUser(pScreen, modeInfo, name, &error);
    312     if (!mode)
    313         return error;
    314 
    315     rep = (xRRCreateModeReply) {
    316         .type = X_Reply,
    317         .sequenceNumber = client->sequence,
    318         .length = 0,
    319         .mode = mode->mode.id
    320 	};
    321     if (client->swapped) {
    322         swaps(&rep.sequenceNumber);
    323         swapl(&rep.length);
    324         swapl(&rep.mode);
    325     }
    326     WriteToClient(client, sizeof(xRRCreateModeReply), &rep);
    327     /* Drop out reference to this mode */
    328     RRModeDestroy(mode);
    329     return Success;
    330 }
    331 
    332 int
    333 ProcRRDestroyMode(ClientPtr client)
    334 {
    335     REQUEST(xRRDestroyModeReq);
    336     RRModePtr mode;
    337 
    338     REQUEST_SIZE_MATCH(xRRDestroyModeReq);
    339     VERIFY_RR_MODE(stuff->mode, mode, DixDestroyAccess);
    340 
    341     if (!mode->userScreen)
    342         return BadMatch;
    343     if (mode->refcnt > 1)
    344         return BadAccess;
    345     FreeResource(stuff->mode, 0);
    346     return Success;
    347 }
    348 
    349 int
    350 ProcRRAddOutputMode(ClientPtr client)
    351 {
    352     REQUEST(xRRAddOutputModeReq);
    353     RRModePtr mode;
    354     RROutputPtr output;
    355 
    356     REQUEST_SIZE_MATCH(xRRAddOutputModeReq);
    357     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
    358     VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
    359 
    360     if (RROutputIsLeased(output))
    361         return BadAccess;
    362 
    363     return RROutputAddUserMode(output, mode);
    364 }
    365 
    366 int
    367 ProcRRDeleteOutputMode(ClientPtr client)
    368 {
    369     REQUEST(xRRDeleteOutputModeReq);
    370     RRModePtr mode;
    371     RROutputPtr output;
    372 
    373     REQUEST_SIZE_MATCH(xRRDeleteOutputModeReq);
    374     VERIFY_RR_OUTPUT(stuff->output, output, DixReadAccess);
    375     VERIFY_RR_MODE(stuff->mode, mode, DixUseAccess);
    376 
    377     if (RROutputIsLeased(output))
    378         return BadAccess;
    379 
    380     return RROutputDeleteUserMode(output, mode);
    381 }