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