rrinfo.c revision 35c4bbdf
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#ifdef RANDR_10_INTERFACE 26static RRModePtr 27RROldModeAdd(RROutputPtr output, RRScreenSizePtr size, int refresh) 28{ 29 ScreenPtr pScreen = output->pScreen; 30 31 rrScrPriv(pScreen); 32 xRRModeInfo modeInfo; 33 char name[100]; 34 RRModePtr mode; 35 int i; 36 RRModePtr *modes; 37 38 memset(&modeInfo, '\0', sizeof(modeInfo)); 39 snprintf(name, sizeof(name), "%dx%d", size->width, size->height); 40 41 modeInfo.width = size->width; 42 modeInfo.height = size->height; 43 modeInfo.hTotal = size->width; 44 modeInfo.vTotal = size->height; 45 modeInfo.dotClock = ((CARD32) size->width * (CARD32) size->height * 46 (CARD32) refresh); 47 modeInfo.nameLength = strlen(name); 48 mode = RRModeGet(&modeInfo, name); 49 if (!mode) 50 return NULL; 51 for (i = 0; i < output->numModes; i++) 52 if (output->modes[i] == mode) { 53 RRModeDestroy(mode); 54 return mode; 55 } 56 57 if (output->numModes) 58 modes = reallocarray(output->modes, 59 output->numModes + 1, sizeof(RRModePtr)); 60 else 61 modes = malloc(sizeof(RRModePtr)); 62 if (!modes) { 63 RRModeDestroy(mode); 64 FreeResource(mode->mode.id, 0); 65 return NULL; 66 } 67 modes[output->numModes++] = mode; 68 output->modes = modes; 69 output->changed = TRUE; 70 pScrPriv->changed = TRUE; 71 pScrPriv->configChanged = TRUE; 72 return mode; 73} 74 75static void 76RRScanOldConfig(ScreenPtr pScreen, Rotation rotations) 77{ 78 rrScrPriv(pScreen); 79 RROutputPtr output; 80 RRCrtcPtr crtc; 81 RRModePtr mode, newMode = NULL; 82 int i; 83 CARD16 minWidth = MAXSHORT, minHeight = MAXSHORT; 84 CARD16 maxWidth = 0, maxHeight = 0; 85 CARD16 width, height; 86 87 /* 88 * First time through, create a crtc and output and hook 89 * them together 90 */ 91 if (pScrPriv->numOutputs == 0 && pScrPriv->numCrtcs == 0) { 92 crtc = RRCrtcCreate(pScreen, NULL); 93 if (!crtc) 94 return; 95 output = RROutputCreate(pScreen, "default", 7, NULL); 96 if (!output) 97 return; 98 RROutputSetCrtcs(output, &crtc, 1); 99 RROutputSetConnection(output, RR_Connected); 100 RROutputSetSubpixelOrder(output, PictureGetSubpixelOrder(pScreen)); 101 } 102 103 output = pScrPriv->outputs[0]; 104 if (!output) 105 return; 106 crtc = pScrPriv->crtcs[0]; 107 if (!crtc) 108 return; 109 110 /* check rotations */ 111 if (rotations != crtc->rotations) { 112 crtc->rotations = rotations; 113 crtc->changed = TRUE; 114 pScrPriv->changed = TRUE; 115 } 116 117 /* regenerate mode list */ 118 for (i = 0; i < pScrPriv->nSizes; i++) { 119 RRScreenSizePtr size = &pScrPriv->pSizes[i]; 120 int r; 121 122 if (size->nRates) { 123 for (r = 0; r < size->nRates; r++) { 124 mode = RROldModeAdd(output, size, size->pRates[r].rate); 125 if (i == pScrPriv->size && 126 size->pRates[r].rate == pScrPriv->rate) { 127 newMode = mode; 128 } 129 } 130 free(size->pRates); 131 } 132 else { 133 mode = RROldModeAdd(output, size, 0); 134 if (i == pScrPriv->size) 135 newMode = mode; 136 } 137 } 138 if (pScrPriv->nSizes) 139 free(pScrPriv->pSizes); 140 pScrPriv->pSizes = NULL; 141 pScrPriv->nSizes = 0; 142 143 /* find size bounds */ 144 for (i = 0; i < output->numModes + output->numUserModes; i++) { 145 mode = (i < output->numModes ? 146 output->modes[i] : 147 output->userModes[i - output->numModes]); 148 width = mode->mode.width; 149 height = mode->mode.height; 150 151 if (width < minWidth) 152 minWidth = width; 153 if (width > maxWidth) 154 maxWidth = width; 155 if (height < minHeight) 156 minHeight = height; 157 if (height > maxHeight) 158 maxHeight = height; 159 } 160 161 RRScreenSetSizeRange(pScreen, minWidth, minHeight, maxWidth, maxHeight); 162 163 /* notice current mode */ 164 if (newMode) 165 RRCrtcNotify(crtc, newMode, 0, 0, pScrPriv->rotation, NULL, 1, &output); 166} 167#endif 168 169/* 170 * Poll the driver for changed information 171 */ 172Bool 173RRGetInfo(ScreenPtr pScreen, Bool force_query) 174{ 175 rrScrPriv(pScreen); 176 Rotation rotations; 177 int i; 178 179 /* Return immediately if we don't need to re-query and we already have the 180 * information. 181 */ 182 if (!force_query) { 183 if (pScrPriv->numCrtcs != 0 || pScrPriv->numOutputs != 0) 184 return TRUE; 185 } 186 187 for (i = 0; i < pScrPriv->numOutputs; i++) 188 pScrPriv->outputs[i]->changed = FALSE; 189 for (i = 0; i < pScrPriv->numCrtcs; i++) 190 pScrPriv->crtcs[i]->changed = FALSE; 191 192 rotations = 0; 193 pScrPriv->changed = FALSE; 194 pScrPriv->configChanged = FALSE; 195 196 if (!(*pScrPriv->rrGetInfo) (pScreen, &rotations)) 197 return FALSE; 198 199#if RANDR_10_INTERFACE 200 if (pScrPriv->nSizes) 201 RRScanOldConfig(pScreen, rotations); 202#endif 203 RRTellChanged(pScreen); 204 return TRUE; 205} 206 207/* 208 * Register the range of sizes for the screen 209 */ 210void 211RRScreenSetSizeRange(ScreenPtr pScreen, 212 CARD16 minWidth, 213 CARD16 minHeight, CARD16 maxWidth, CARD16 maxHeight) 214{ 215 rrScrPriv(pScreen); 216 217 if (!pScrPriv) 218 return; 219 if (pScrPriv->minWidth == minWidth && pScrPriv->minHeight == minHeight && 220 pScrPriv->maxWidth == maxWidth && pScrPriv->maxHeight == maxHeight) { 221 return; 222 } 223 224 pScrPriv->minWidth = minWidth; 225 pScrPriv->minHeight = minHeight; 226 pScrPriv->maxWidth = maxWidth; 227 pScrPriv->maxHeight = maxHeight; 228 RRSetChanged(pScreen); 229 pScrPriv->configChanged = TRUE; 230} 231 232#ifdef RANDR_10_INTERFACE 233static Bool 234RRScreenSizeMatches(RRScreenSizePtr a, RRScreenSizePtr b) 235{ 236 if (a->width != b->width) 237 return FALSE; 238 if (a->height != b->height) 239 return FALSE; 240 if (a->mmWidth != b->mmWidth) 241 return FALSE; 242 if (a->mmHeight != b->mmHeight) 243 return FALSE; 244 return TRUE; 245} 246 247RRScreenSizePtr 248RRRegisterSize(ScreenPtr pScreen, 249 short width, short height, short mmWidth, short mmHeight) 250{ 251 rrScrPriv(pScreen); 252 int i; 253 RRScreenSize tmp; 254 RRScreenSizePtr pNew; 255 256 if (!pScrPriv) 257 return 0; 258 259 tmp.id = 0; 260 tmp.width = width; 261 tmp.height = height; 262 tmp.mmWidth = mmWidth; 263 tmp.mmHeight = mmHeight; 264 tmp.pRates = 0; 265 tmp.nRates = 0; 266 for (i = 0; i < pScrPriv->nSizes; i++) 267 if (RRScreenSizeMatches(&tmp, &pScrPriv->pSizes[i])) 268 return &pScrPriv->pSizes[i]; 269 pNew = reallocarray(pScrPriv->pSizes, 270 pScrPriv->nSizes + 1, sizeof(RRScreenSize)); 271 if (!pNew) 272 return 0; 273 pNew[pScrPriv->nSizes++] = tmp; 274 pScrPriv->pSizes = pNew; 275 return &pNew[pScrPriv->nSizes - 1]; 276} 277 278Bool 279RRRegisterRate(ScreenPtr pScreen, RRScreenSizePtr pSize, int rate) 280{ 281 rrScrPriv(pScreen); 282 int i; 283 RRScreenRatePtr pNew, pRate; 284 285 if (!pScrPriv) 286 return FALSE; 287 288 for (i = 0; i < pSize->nRates; i++) 289 if (pSize->pRates[i].rate == rate) 290 return TRUE; 291 292 pNew = reallocarray(pSize->pRates, pSize->nRates + 1, sizeof(RRScreenRate)); 293 if (!pNew) 294 return FALSE; 295 pRate = &pNew[pSize->nRates++]; 296 pRate->rate = rate; 297 pSize->pRates = pNew; 298 return TRUE; 299} 300 301Rotation 302RRGetRotation(ScreenPtr pScreen) 303{ 304 RROutputPtr output = RRFirstOutput(pScreen); 305 306 if (!output) 307 return RR_Rotate_0; 308 309 return output->crtc->rotation; 310} 311 312void 313RRSetCurrentConfig(ScreenPtr pScreen, 314 Rotation rotation, int rate, RRScreenSizePtr pSize) 315{ 316 rrScrPriv(pScreen); 317 318 if (!pScrPriv) 319 return; 320 pScrPriv->size = pSize - pScrPriv->pSizes; 321 pScrPriv->rotation = rotation; 322 pScrPriv->rate = rate; 323} 324#endif 325