static Bool xf86RandR12CrtcSet (ScreenPtr pScreen, RRCrtcPtr randr_crtc, RRModePtr randr_mode, int x, int y, Rotation rotation, int num_randr_outputs, RROutputPtr *randr_outputs) { ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); xf86CrtcPtr crtc = randr_crtc->devPrivate; Bool changed = FALSE; int o, ro; xf86CrtcPtr *save_crtcs; Bool save_enabled = crtc->enabled; save_crtcs = ALLOCATE_LOCAL(config->num_output * sizeof (xf86CrtcPtr)); if ((randr_mode != NULL) != crtc->enabled) changed = TRUE; else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) changed = TRUE; if (rotation != crtc->rotation) changed = TRUE; if (x != crtc->x || y != crtc->y) changed = TRUE; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; xf86CrtcPtr new_crtc; save_crtcs[o] = output->crtc; if (output->crtc == crtc) new_crtc = NULL; else new_crtc = output->crtc; for (ro = 0; ro < num_randr_outputs; ro++) if (output->randr_output == randr_outputs[ro]) { new_crtc = crtc; break; } if (new_crtc != output->crtc) { changed = TRUE; output->crtc = new_crtc; } } for (ro = 0; ro < num_randr_outputs; ro++) if (randr_outputs[ro]->pendingProperties) changed = TRUE; /* XXX need device-independent mode setting code through an API */ if (changed) { crtc->enabled = randr_mode != NULL; if (randr_mode) { DisplayModeRec mode; xf86RandRModeConvert (pScrn, randr_mode, &mode); if (!xf86CrtcSetMode (crtc, &mode, rotation, x, y)) { crtc->enabled = save_enabled; for (o = 0; o < config->num_output; o++) { xf86OutputPtr output = config->output[o]; output->crtc = save_crtcs[o]; } DEALLOCATE_LOCAL(save_crtcs); return FALSE; } /* * Save the last successful setting for EnterVT */ crtc->desiredMode = mode; crtc->desiredRotation = rotation; crtc->desiredX = x; crtc->desiredY = y; } xf86DisableUnusedFunctions (pScrn); } DEALLOCATE_LOCAL(save_crtcs); return xf86RandR12CrtcNotify (randr_crtc); }
static Bool G80SorSetProperty(xf86OutputPtr output, Atom prop, RRPropertyValuePtr val) { G80OutputPrivPtr pPriv = output->driver_private; if(prop == properties.dither.atom) { INT32 i; if(val->type != XA_INTEGER || val->format != 32 || val->size != 1) return FALSE; i = *(INT32*)val->data; if(i < properties.dither.range[0] || i > properties.dither.range[1]) return FALSE; G80CrtcSetDither(output->crtc, i, TRUE); } else if(prop == properties.scale.atom) { const char *s; enum G80ScaleMode oldScale, scale; int i; const struct { const char *name; enum G80ScaleMode scale; } modes[] = { { "off", G80_SCALE_OFF }, { "aspect", G80_SCALE_ASPECT }, { "fill", G80_SCALE_FILL }, { "center", G80_SCALE_CENTER }, { NULL, 0 }, }; if(val->type != XA_STRING || val->format != 8) return FALSE; s = (char*)val->data; for(i = 0; modes[i].name; i++) { const char *name = modes[i].name; const int len = strlen(name); if(val->size == len && !strncmp(name, s, len)) { scale = modes[i].scale; break; } } if(!modes[i].name) return FALSE; if(scale == G80_SCALE_OFF && pPriv->panelType == LVDS) // LVDS requires scaling return FALSE; oldScale = pPriv->scale; pPriv->scale = scale; if(output->crtc) { xf86CrtcPtr crtc = output->crtc; if(!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Failed to set scaling to %s for output %s\n", modes[i].name, output->name); // Restore old scale and try again. pPriv->scale = oldScale; if(!xf86CrtcSetMode(crtc, &crtc->desiredMode, crtc->desiredRotation, crtc->desiredX, crtc->desiredY)) { xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR, "Failed to restore old scaling for output %s\n", output->name); } return FALSE; } } } return TRUE; }