1706f2543Smrg/* 2706f2543Smrg * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. 3706f2543Smrg * 4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its 5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that 6706f2543Smrg * the above copyright notice appear in all copies and that both that copyright 7706f2543Smrg * notice and this permission notice appear in supporting documentation, and 8706f2543Smrg * that the name of the copyright holders not be used in advertising or 9706f2543Smrg * publicity pertaining to distribution of the software without specific, 10706f2543Smrg * written prior permission. The copyright holders make no representations 11706f2543Smrg * about the suitability of this software for any purpose. It is provided "as 12706f2543Smrg * is" without express or implied warranty. 13706f2543Smrg * 14706f2543Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 16706f2543Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR 17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 20706f2543Smrg * OF THIS SOFTWARE. 21706f2543Smrg */ 22706f2543Smrg 23706f2543Smrg#ifdef HAVE_XORG_CONFIG_H 24706f2543Smrg#include <xorg-config.h> 25706f2543Smrg#else 26706f2543Smrg#ifdef HAVE_CONFIG_H 27706f2543Smrg#include <config.h> 28706f2543Smrg#endif 29706f2543Smrg#endif 30706f2543Smrg 31706f2543Smrg#include "xf86.h" 32706f2543Smrg#include "os.h" 33706f2543Smrg#include "globals.h" 34706f2543Smrg#include "xf86.h" 35706f2543Smrg#include "xf86Modes.h" 36706f2543Smrg#include "xf86Priv.h" 37706f2543Smrg#include "xf86DDC.h" 38706f2543Smrg#include "mipointer.h" 39706f2543Smrg#include "windowstr.h" 40706f2543Smrg#include "inputstr.h" 41706f2543Smrg#include <randrstr.h> 42706f2543Smrg#include <X11/extensions/render.h> 43706f2543Smrg 44706f2543Smrg#include "xf86Crtc.h" 45706f2543Smrg#include "xf86RandR12.h" 46706f2543Smrg 47706f2543Smrgtypedef struct _xf86RandR12Info { 48706f2543Smrg int virtualX; 49706f2543Smrg int virtualY; 50706f2543Smrg int mmWidth; 51706f2543Smrg int mmHeight; 52706f2543Smrg int maxX; 53706f2543Smrg int maxY; 54706f2543Smrg int pointerX; 55706f2543Smrg int pointerY; 56706f2543Smrg Rotation rotation; /* current mode */ 57706f2543Smrg Rotation supported_rotations; /* driver supported */ 58706f2543Smrg 59706f2543Smrg /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends 60706f2543Smrg * (actually, any time that we switch back into our VT). 61706f2543Smrg * 62706f2543Smrg * See https://bugs.freedesktop.org/show_bug.cgi?id=21554 63706f2543Smrg */ 64706f2543Smrg xf86EnterVTProc *orig_EnterVT; 65706f2543Smrg} XF86RandRInfoRec, *XF86RandRInfoPtr; 66706f2543Smrg 67706f2543Smrg#ifdef RANDR_12_INTERFACE 68706f2543Smrgstatic Bool xf86RandR12Init12 (ScreenPtr pScreen); 69706f2543Smrgstatic Bool xf86RandR12CreateScreenResources12 (ScreenPtr pScreen); 70706f2543Smrg#endif 71706f2543Smrg 72706f2543Smrgstatic int xf86RandR12Generation; 73706f2543Smrg 74706f2543Smrgstatic DevPrivateKeyRec xf86RandR12KeyRec; 75706f2543Smrgstatic DevPrivateKey xf86RandR12Key; 76706f2543Smrg#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \ 77706f2543Smrg dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key)) 78706f2543Smrg 79706f2543Smrg 80706f2543Smrgstatic int 81706f2543Smrgxf86RandR12ModeRefresh (DisplayModePtr mode) 82706f2543Smrg{ 83706f2543Smrg if (mode->VRefresh) 84706f2543Smrg return (int) (mode->VRefresh + 0.5); 85706f2543Smrg else 86706f2543Smrg return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5); 87706f2543Smrg} 88706f2543Smrg 89706f2543Smrg/* Adapt panning area; return TRUE if panning area was valid without adaption */ 90706f2543Smrgstatic int 91706f2543Smrgxf86RandR13VerifyPanningArea (xf86CrtcPtr crtc, int screenWidth, int screenHeight) 92706f2543Smrg{ 93706f2543Smrg int ret = TRUE; 94706f2543Smrg 95706f2543Smrg if (crtc->version < 2) 96706f2543Smrg return FALSE; 97706f2543Smrg 98706f2543Smrg if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) { 99706f2543Smrg /* Panning in X is disabled */ 100706f2543Smrg if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2) 101706f2543Smrg /* Illegal configuration -> fail/disable */ 102706f2543Smrg ret = FALSE; 103706f2543Smrg crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0; 104706f2543Smrg crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0; 105706f2543Smrg crtc->panningBorder[0] = crtc->panningBorder[2] = 0; 106706f2543Smrg } else { 107706f2543Smrg /* Panning in X is enabled */ 108706f2543Smrg if (crtc->panningTotalArea.x1 < 0) { 109706f2543Smrg /* Panning region outside screen -> move inside */ 110706f2543Smrg crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1; 111706f2543Smrg crtc->panningTotalArea.x1 = 0; 112706f2543Smrg ret = FALSE; 113706f2543Smrg } 114706f2543Smrg if (crtc->panningTotalArea.x2 < crtc->panningTotalArea.x1 + crtc->mode.HDisplay) { 115706f2543Smrg /* Panning region smaller than displayed area -> crop to displayed area */ 116706f2543Smrg crtc->panningTotalArea.x2 = crtc->panningTotalArea.x1 + crtc->mode.HDisplay; 117706f2543Smrg ret = FALSE; 118706f2543Smrg } 119706f2543Smrg if (crtc->panningTotalArea.x2 > screenWidth) { 120706f2543Smrg /* Panning region larger than screen -> move inside, then crop to screen */ 121706f2543Smrg crtc->panningTotalArea.x1 -= crtc->panningTotalArea.x2 - screenWidth; 122706f2543Smrg crtc->panningTotalArea.x2 = screenWidth; 123706f2543Smrg ret = FALSE; 124706f2543Smrg if (crtc->panningTotalArea.x1 < 0) 125706f2543Smrg crtc->panningTotalArea.x1 = 0; 126706f2543Smrg } 127706f2543Smrg if (crtc->panningBorder[0] + crtc->panningBorder[2] > crtc->mode.HDisplay) { 128706f2543Smrg /* Borders too large -> set to 0 */ 129706f2543Smrg crtc->panningBorder[0] = crtc->panningBorder[2] = 0; 130706f2543Smrg ret = FALSE; 131706f2543Smrg } 132706f2543Smrg } 133706f2543Smrg 134706f2543Smrg if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) { 135706f2543Smrg /* Panning in Y is disabled */ 136706f2543Smrg if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2) 137706f2543Smrg /* Illegal configuration -> fail/disable */ 138706f2543Smrg ret = FALSE; 139706f2543Smrg crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0; 140706f2543Smrg crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0; 141706f2543Smrg crtc->panningBorder[1] = crtc->panningBorder[3] = 0; 142706f2543Smrg } else { 143706f2543Smrg /* Panning in Y is enabled */ 144706f2543Smrg if (crtc->panningTotalArea.y1 < 0) { 145706f2543Smrg /* Panning region outside screen -> move inside */ 146706f2543Smrg crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1; 147706f2543Smrg crtc->panningTotalArea.y1 = 0; 148706f2543Smrg ret = FALSE; 149706f2543Smrg } 150706f2543Smrg if (crtc->panningTotalArea.y2 < crtc->panningTotalArea.y1 + crtc->mode.VDisplay) { 151706f2543Smrg /* Panning region smaller than displayed area -> crop to displayed area */ 152706f2543Smrg crtc->panningTotalArea.y2 = crtc->panningTotalArea.y1 + crtc->mode.VDisplay; 153706f2543Smrg ret = FALSE; 154706f2543Smrg } 155706f2543Smrg if (crtc->panningTotalArea.y2 > screenHeight) { 156706f2543Smrg /* Panning region larger than screen -> move inside, then crop to screen */ 157706f2543Smrg crtc->panningTotalArea.y1 -= crtc->panningTotalArea.y2 - screenHeight; 158706f2543Smrg crtc->panningTotalArea.y2 = screenHeight; 159706f2543Smrg ret = FALSE; 160706f2543Smrg if (crtc->panningTotalArea.y1 < 0) 161706f2543Smrg crtc->panningTotalArea.y1 = 0; 162706f2543Smrg } 163706f2543Smrg if (crtc->panningBorder[1] + crtc->panningBorder[3] > crtc->mode.VDisplay) { 164706f2543Smrg /* Borders too large -> set to 0 */ 165706f2543Smrg crtc->panningBorder[1] = crtc->panningBorder[3] = 0; 166706f2543Smrg ret = FALSE; 167706f2543Smrg } 168706f2543Smrg } 169706f2543Smrg 170706f2543Smrg return ret; 171706f2543Smrg} 172706f2543Smrg 173706f2543Smrg/* 174706f2543Smrg * The heart of the panning operation: 175706f2543Smrg * 176706f2543Smrg * Given a frame buffer position (fb_x, fb_y), 177706f2543Smrg * and a crtc position (crtc_x, crtc_y), 178706f2543Smrg * and a transform matrix which maps frame buffer to crtc, 179706f2543Smrg * compute a panning position (pan_x, pan_y) that 180706f2543Smrg * makes the resulting transform line those two up 181706f2543Smrg */ 182706f2543Smrg 183706f2543Smrgstatic void 184706f2543Smrgxf86ComputeCrtcPan (Bool transform_in_use, 185706f2543Smrg struct pixman_f_transform *m, 186706f2543Smrg double screen_x, double screen_y, 187706f2543Smrg double crtc_x, double crtc_y, 188706f2543Smrg int old_pan_x, int old_pan_y, 189706f2543Smrg int *new_pan_x, int *new_pan_y) 190706f2543Smrg{ 191706f2543Smrg if (transform_in_use) { 192706f2543Smrg /* 193706f2543Smrg * Given the current transform, M, the current position 194706f2543Smrg * on the Screen, S, and the desired position on the CRTC, 195706f2543Smrg * C, compute a translation, T, such that: 196706f2543Smrg * 197706f2543Smrg * M T S = C 198706f2543Smrg * 199706f2543Smrg * where T is of the form 200706f2543Smrg * 201706f2543Smrg * | 1 0 dx | 202706f2543Smrg * | 0 1 dy | 203706f2543Smrg * | 0 0 1 | 204706f2543Smrg * 205706f2543Smrg * M T S = 206706f2543Smrg * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F | 207706f2543Smrg * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F | 208706f2543Smrg * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F | 209706f2543Smrg * 210706f2543Smrg * R = M S 211706f2543Smrg * 212706f2543Smrg * Cx F = M00 dx + M01 dy + R0 213706f2543Smrg * Cy F = M10 dx + M11 dy + R1 214706f2543Smrg * F = M20 dx + M21 dy + R2 215706f2543Smrg * 216706f2543Smrg * Zero out dx, then dy 217706f2543Smrg * 218706f2543Smrg * F (Cx M10 - Cy M00) = 219706f2543Smrg * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1 220706f2543Smrg * F (M10 - Cy M20) = 221706f2543Smrg * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1 222706f2543Smrg * 223706f2543Smrg * F (Cx M11 - Cy M01) = 224706f2543Smrg * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1 225706f2543Smrg * F (M11 - Cy M21) = 226706f2543Smrg * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1 227706f2543Smrg * 228706f2543Smrg * Make some temporaries 229706f2543Smrg * 230706f2543Smrg * T = | Cx M10 - Cy M00 | 231706f2543Smrg * | Cx M11 - Cy M01 | 232706f2543Smrg * 233706f2543Smrg * U = | M10 M01 - M00 M11 | 234706f2543Smrg * | M11 M00 - M01 M10 | 235706f2543Smrg * 236706f2543Smrg * Q = | M10 R0 - M00 R1 | 237706f2543Smrg * | M11 R0 - M01 R1 | 238706f2543Smrg * 239706f2543Smrg * P = | M10 - Cy M20 | 240706f2543Smrg * | M11 - Cy M21 | 241706f2543Smrg * 242706f2543Smrg * W = | M10 M21 - M20 M11 | 243706f2543Smrg * | M11 M20 - M21 M10 | 244706f2543Smrg * 245706f2543Smrg * V = | M10 R2 - M20 R1 | 246706f2543Smrg * | M11 R2 - M21 R1 | 247706f2543Smrg * 248706f2543Smrg * Rewrite: 249706f2543Smrg * 250706f2543Smrg * F T0 = U0 dy + Q0 251706f2543Smrg * F P0 = W0 dy + V0 252706f2543Smrg * F T1 = U1 dx + Q1 253706f2543Smrg * F P1 = W1 dx + V1 254706f2543Smrg * 255706f2543Smrg * Solve for F (two ways) 256706f2543Smrg * 257706f2543Smrg * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0 258706f2543Smrg * 259706f2543Smrg * W0 Q0 - U0 V0 260706f2543Smrg * F = ------------- 261706f2543Smrg * W0 T0 - U0 P0 262706f2543Smrg * 263706f2543Smrg * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1 264706f2543Smrg * 265706f2543Smrg * W1 Q1 - U1 V1 266706f2543Smrg * F = ------------- 267706f2543Smrg * W1 T1 - U1 P1 268706f2543Smrg * 269706f2543Smrg * We'll use which ever solution works (denominator != 0) 270706f2543Smrg * 271706f2543Smrg * Finally, solve for dx and dy: 272706f2543Smrg * 273706f2543Smrg * dx = (F T1 - Q1) / U1 274706f2543Smrg * dx = (F P1 - V1) / W1 275706f2543Smrg * 276706f2543Smrg * dy = (F T0 - Q0) / U0 277706f2543Smrg * dy = (F P0 - V0) / W0 278706f2543Smrg */ 279706f2543Smrg double r[3]; 280706f2543Smrg double q[2], u[2], t[2], v[2], w[2], p[2]; 281706f2543Smrg double f; 282706f2543Smrg struct pict_f_vector d; 283706f2543Smrg int i; 284706f2543Smrg 285706f2543Smrg /* Get the un-normalized crtc coordinates again */ 286706f2543Smrg for (i = 0; i < 3; i++) 287706f2543Smrg r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2]; 288706f2543Smrg 289706f2543Smrg /* Combine values into temporaries */ 290706f2543Smrg for (i = 0; i < 2; i++) { 291706f2543Smrg q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1]; 292706f2543Smrg u[i] = m->m[1][i] * m->m[0][1-i] - m->m[0][i] * m->m[1][1-i]; 293706f2543Smrg t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y; 294706f2543Smrg 295706f2543Smrg v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1]; 296706f2543Smrg w[i] = m->m[1][i] * m->m[2][1-i] - m->m[2][i] * m->m[1][1-i]; 297706f2543Smrg p[i] = m->m[1][i] - m->m[2][i] * crtc_y; 298706f2543Smrg } 299706f2543Smrg 300706f2543Smrg /* Find a way to compute f */ 301706f2543Smrg f = 0; 302706f2543Smrg for (i = 0; i < 2; i++) { 303706f2543Smrg double a = w[i] * q[i] - u[i] * v[i]; 304706f2543Smrg double b = w[i] * t[i] - u[i] * p[i]; 305706f2543Smrg if (b != 0) { 306706f2543Smrg f = a/b; 307706f2543Smrg break; 308706f2543Smrg } 309706f2543Smrg } 310706f2543Smrg 311706f2543Smrg /* Solve for the resulting transform vector */ 312706f2543Smrg for (i = 0; i < 2; i++) { 313706f2543Smrg if (u[i]) 314706f2543Smrg d.v[1-i] = (t[i] * f - q[i]) / u[i]; 315706f2543Smrg else if (w[1]) 316706f2543Smrg d.v[1-i] = (p[i] * f - v[i]) / w[i]; 317706f2543Smrg else 318706f2543Smrg d.v[1-i] = 0; 319706f2543Smrg } 320706f2543Smrg *new_pan_x = old_pan_x - floor (d.v[0] + 0.5); 321706f2543Smrg *new_pan_y = old_pan_y - floor (d.v[1] + 0.5); 322706f2543Smrg } else { 323706f2543Smrg *new_pan_x = screen_x - crtc_x; 324706f2543Smrg *new_pan_y = screen_y - crtc_y; 325706f2543Smrg } 326706f2543Smrg} 327706f2543Smrg 328706f2543Smrgstatic void 329706f2543Smrgxf86RandR13Pan (xf86CrtcPtr crtc, int x, int y) 330706f2543Smrg{ 331706f2543Smrg int newX, newY; 332706f2543Smrg int width, height; 333706f2543Smrg Bool panned = FALSE; 334706f2543Smrg 335706f2543Smrg if (crtc->version < 2) 336706f2543Smrg return; 337706f2543Smrg 338706f2543Smrg if (! crtc->enabled || 339706f2543Smrg (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 && 340706f2543Smrg crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1)) 341706f2543Smrg return; 342706f2543Smrg 343706f2543Smrg newX = crtc->x; 344706f2543Smrg newY = crtc->y; 345706f2543Smrg width = crtc->mode.HDisplay; 346706f2543Smrg height = crtc->mode.VDisplay; 347706f2543Smrg 348706f2543Smrg if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 || 349706f2543Smrg (x >= crtc->panningTrackingArea.x1 && x < crtc->panningTrackingArea.x2)) && 350706f2543Smrg (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 || 351706f2543Smrg (y >= crtc->panningTrackingArea.y1 && y < crtc->panningTrackingArea.y2))) 352706f2543Smrg { 353706f2543Smrg struct pict_f_vector c; 354706f2543Smrg 355706f2543Smrg /* 356706f2543Smrg * Pre-clip the mouse position to the panning area so that we don't 357706f2543Smrg * push the crtc outside. This doesn't deal with changes to the 358706f2543Smrg * panning values, only mouse position changes. 359706f2543Smrg */ 360706f2543Smrg if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) 361706f2543Smrg { 362706f2543Smrg if (x < crtc->panningTotalArea.x1) 363706f2543Smrg x = crtc->panningTotalArea.x1; 364706f2543Smrg if (x >= crtc->panningTotalArea.x2) 365706f2543Smrg x = crtc->panningTotalArea.x2 - 1; 366706f2543Smrg } 367706f2543Smrg if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) 368706f2543Smrg { 369706f2543Smrg if (y < crtc->panningTotalArea.y1) 370706f2543Smrg y = crtc->panningTotalArea.y1; 371706f2543Smrg if (y >= crtc->panningTotalArea.y2) 372706f2543Smrg y = crtc->panningTotalArea.y2 - 1; 373706f2543Smrg } 374706f2543Smrg 375706f2543Smrg c.v[0] = x; 376706f2543Smrg c.v[1] = y; 377706f2543Smrg c.v[2] = 1.0; 378706f2543Smrg if (crtc->transform_in_use) { 379706f2543Smrg pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c); 380706f2543Smrg } else { 381706f2543Smrg c.v[0] -= crtc->x; 382706f2543Smrg c.v[1] -= crtc->y; 383706f2543Smrg } 384706f2543Smrg 385706f2543Smrg if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { 386706f2543Smrg if (c.v[0] < crtc->panningBorder[0]) { 387706f2543Smrg c.v[0] = crtc->panningBorder[0]; 388706f2543Smrg panned = TRUE; 389706f2543Smrg } 390706f2543Smrg if (c.v[0] >= width - crtc->panningBorder[2]) { 391706f2543Smrg c.v[0] = width - crtc->panningBorder[2] - 1; 392706f2543Smrg panned = TRUE; 393706f2543Smrg } 394706f2543Smrg } 395706f2543Smrg if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { 396706f2543Smrg if (c.v[1] < crtc->panningBorder[1]) { 397706f2543Smrg c.v[1] = crtc->panningBorder[1]; 398706f2543Smrg panned = TRUE; 399706f2543Smrg } 400706f2543Smrg if (c.v[1] >= height - crtc->panningBorder[3]) { 401706f2543Smrg c.v[1] = height - crtc->panningBorder[3] - 1; 402706f2543Smrg panned = TRUE; 403706f2543Smrg } 404706f2543Smrg } 405706f2543Smrg if (panned) 406706f2543Smrg xf86ComputeCrtcPan (crtc->transform_in_use, 407706f2543Smrg &crtc->f_framebuffer_to_crtc, 408706f2543Smrg x, y, c.v[0], c.v[1], 409706f2543Smrg newX, newY, &newX, &newY); 410706f2543Smrg } 411706f2543Smrg 412706f2543Smrg /* 413706f2543Smrg * Ensure that the crtc is within the panning region. 414706f2543Smrg * 415706f2543Smrg * XXX This computation only works when we do not have a transform 416706f2543Smrg * in use. 417706f2543Smrg */ 418706f2543Smrg if (!crtc->transform_in_use) 419706f2543Smrg { 420706f2543Smrg /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */ 421706f2543Smrg if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) { 422706f2543Smrg if (newX > crtc->panningTotalArea.x2 - width) 423706f2543Smrg newX = crtc->panningTotalArea.x2 - width; 424706f2543Smrg if (newX < crtc->panningTotalArea.x1) 425706f2543Smrg newX = crtc->panningTotalArea.x1; 426706f2543Smrg } 427706f2543Smrg if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { 428706f2543Smrg if (newY > crtc->panningTotalArea.y2 - height) 429706f2543Smrg newY = crtc->panningTotalArea.y2 - height; 430706f2543Smrg if (newY < crtc->panningTotalArea.y1) 431706f2543Smrg newY = crtc->panningTotalArea.y1; 432706f2543Smrg } 433706f2543Smrg } 434706f2543Smrg if (newX != crtc->x || newY != crtc->y) 435706f2543Smrg xf86CrtcSetOrigin (crtc, newX, newY); 436706f2543Smrg} 437706f2543Smrg 438706f2543Smrgstatic Bool 439706f2543Smrgxf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations) 440706f2543Smrg{ 441706f2543Smrg RRScreenSizePtr pSize; 442706f2543Smrg ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); 443706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 444706f2543Smrg DisplayModePtr mode; 445706f2543Smrg int refresh0 = 60; 446706f2543Smrg int maxX = 0, maxY = 0; 447706f2543Smrg 448706f2543Smrg *rotations = randrp->supported_rotations; 449706f2543Smrg 450706f2543Smrg if (randrp->virtualX == -1 || randrp->virtualY == -1) 451706f2543Smrg { 452706f2543Smrg randrp->virtualX = scrp->virtualX; 453706f2543Smrg randrp->virtualY = scrp->virtualY; 454706f2543Smrg } 455706f2543Smrg 456706f2543Smrg /* Re-probe the outputs for new monitors or modes */ 457706f2543Smrg if (scrp->vtSema) 458706f2543Smrg { 459706f2543Smrg xf86ProbeOutputModes (scrp, 0, 0); 460706f2543Smrg xf86SetScrnInfoModes (scrp); 461706f2543Smrg } 462706f2543Smrg 463706f2543Smrg for (mode = scrp->modes; ; mode = mode->next) 464706f2543Smrg { 465706f2543Smrg int refresh = xf86RandR12ModeRefresh (mode); 466706f2543Smrg if (randrp->maxX == 0 || randrp->maxY == 0) 467706f2543Smrg { 468706f2543Smrg if (maxX < mode->HDisplay) 469706f2543Smrg maxX = mode->HDisplay; 470706f2543Smrg if (maxY < mode->VDisplay) 471706f2543Smrg maxY = mode->VDisplay; 472706f2543Smrg } 473706f2543Smrg if (mode == scrp->modes) 474706f2543Smrg refresh0 = refresh; 475706f2543Smrg pSize = RRRegisterSize (pScreen, 476706f2543Smrg mode->HDisplay, mode->VDisplay, 477706f2543Smrg randrp->mmWidth, randrp->mmHeight); 478706f2543Smrg if (!pSize) 479706f2543Smrg return FALSE; 480706f2543Smrg RRRegisterRate (pScreen, pSize, refresh); 481706f2543Smrg 482706f2543Smrg if (xf86ModesEqual(mode, scrp->currentMode)) 483706f2543Smrg { 484706f2543Smrg RRSetCurrentConfig (pScreen, randrp->rotation, refresh, pSize); 485706f2543Smrg } 486706f2543Smrg if (mode->next == scrp->modes) 487706f2543Smrg break; 488706f2543Smrg } 489706f2543Smrg 490706f2543Smrg if (randrp->maxX == 0 || randrp->maxY == 0) 491706f2543Smrg { 492706f2543Smrg randrp->maxX = maxX; 493706f2543Smrg randrp->maxY = maxY; 494706f2543Smrg } 495706f2543Smrg 496706f2543Smrg return TRUE; 497706f2543Smrg} 498706f2543Smrg 499706f2543Smrgstatic Bool 500706f2543Smrgxf86RandR12SetMode (ScreenPtr pScreen, 501706f2543Smrg DisplayModePtr mode, 502706f2543Smrg Bool useVirtual, 503706f2543Smrg int mmWidth, 504706f2543Smrg int mmHeight) 505706f2543Smrg{ 506706f2543Smrg ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); 507706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 508706f2543Smrg int oldWidth = pScreen->width; 509706f2543Smrg int oldHeight = pScreen->height; 510706f2543Smrg int oldmmWidth = pScreen->mmWidth; 511706f2543Smrg int oldmmHeight = pScreen->mmHeight; 512706f2543Smrg WindowPtr pRoot = pScreen->root; 513706f2543Smrg DisplayModePtr currentMode = NULL; 514706f2543Smrg Bool ret = TRUE; 515706f2543Smrg 516706f2543Smrg if (pRoot) 517706f2543Smrg (*scrp->EnableDisableFBAccess) (pScreen->myNum, FALSE); 518706f2543Smrg if (useVirtual) 519706f2543Smrg { 520706f2543Smrg scrp->virtualX = randrp->virtualX; 521706f2543Smrg scrp->virtualY = randrp->virtualY; 522706f2543Smrg } 523706f2543Smrg else 524706f2543Smrg { 525706f2543Smrg scrp->virtualX = mode->HDisplay; 526706f2543Smrg scrp->virtualY = mode->VDisplay; 527706f2543Smrg } 528706f2543Smrg 529706f2543Smrg if(randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) 530706f2543Smrg { 531706f2543Smrg /* If the screen is rotated 90 or 270 degrees, swap the sizes. */ 532706f2543Smrg pScreen->width = scrp->virtualY; 533706f2543Smrg pScreen->height = scrp->virtualX; 534706f2543Smrg pScreen->mmWidth = mmHeight; 535706f2543Smrg pScreen->mmHeight = mmWidth; 536706f2543Smrg } 537706f2543Smrg else 538706f2543Smrg { 539706f2543Smrg pScreen->width = scrp->virtualX; 540706f2543Smrg pScreen->height = scrp->virtualY; 541706f2543Smrg pScreen->mmWidth = mmWidth; 542706f2543Smrg pScreen->mmHeight = mmHeight; 543706f2543Smrg } 544706f2543Smrg if (scrp->currentMode == mode) { 545706f2543Smrg /* Save current mode */ 546706f2543Smrg currentMode = scrp->currentMode; 547706f2543Smrg /* Reset, just so we ensure the drivers SwitchMode is called */ 548706f2543Smrg scrp->currentMode = NULL; 549706f2543Smrg } 550706f2543Smrg /* 551706f2543Smrg * We know that if the driver failed to SwitchMode to the rotated 552706f2543Smrg * version, then it should revert back to it's prior mode. 553706f2543Smrg */ 554706f2543Smrg if (!xf86SwitchMode (pScreen, mode)) 555706f2543Smrg { 556706f2543Smrg ret = FALSE; 557706f2543Smrg scrp->virtualX = pScreen->width = oldWidth; 558706f2543Smrg scrp->virtualY = pScreen->height = oldHeight; 559706f2543Smrg pScreen->mmWidth = oldmmWidth; 560706f2543Smrg pScreen->mmHeight = oldmmHeight; 561706f2543Smrg scrp->currentMode = currentMode; 562706f2543Smrg } 563706f2543Smrg 564706f2543Smrg /* 565706f2543Smrg * Make sure the layout is correct 566706f2543Smrg */ 567706f2543Smrg xf86ReconfigureLayout(); 568706f2543Smrg 569706f2543Smrg /* 570706f2543Smrg * Make sure the whole screen is visible 571706f2543Smrg */ 572706f2543Smrg xf86SetViewport (pScreen, pScreen->width, pScreen->height); 573706f2543Smrg xf86SetViewport (pScreen, 0, 0); 574706f2543Smrg if (pRoot) 575706f2543Smrg (*scrp->EnableDisableFBAccess) (pScreen->myNum, TRUE); 576706f2543Smrg return ret; 577706f2543Smrg} 578706f2543Smrg 579706f2543SmrgBool 580706f2543Smrgxf86RandR12SetConfig (ScreenPtr pScreen, 581706f2543Smrg Rotation rotation, 582706f2543Smrg int rate, 583706f2543Smrg RRScreenSizePtr pSize) 584706f2543Smrg{ 585706f2543Smrg ScrnInfoPtr scrp = XF86SCRNINFO(pScreen); 586706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 587706f2543Smrg DisplayModePtr mode; 588706f2543Smrg int px, py; 589706f2543Smrg Bool useVirtual = FALSE; 590706f2543Smrg int maxX = 0, maxY = 0; 591706f2543Smrg Rotation oldRotation = randrp->rotation; 592706f2543Smrg 593706f2543Smrg randrp->rotation = rotation; 594706f2543Smrg 595706f2543Smrg if (randrp->virtualX == -1 || randrp->virtualY == -1) 596706f2543Smrg { 597706f2543Smrg randrp->virtualX = scrp->virtualX; 598706f2543Smrg randrp->virtualY = scrp->virtualY; 599706f2543Smrg } 600706f2543Smrg 601706f2543Smrg miPointerGetPosition (inputInfo.pointer, &px, &py); 602706f2543Smrg for (mode = scrp->modes; ; mode = mode->next) 603706f2543Smrg { 604706f2543Smrg if (randrp->maxX == 0 || randrp->maxY == 0) 605706f2543Smrg { 606706f2543Smrg if (maxX < mode->HDisplay) 607706f2543Smrg maxX = mode->HDisplay; 608706f2543Smrg if (maxY < mode->VDisplay) 609706f2543Smrg maxY = mode->VDisplay; 610706f2543Smrg } 611706f2543Smrg if (mode->HDisplay == pSize->width && 612706f2543Smrg mode->VDisplay == pSize->height && 613706f2543Smrg (rate == 0 || xf86RandR12ModeRefresh (mode) == rate)) 614706f2543Smrg break; 615706f2543Smrg if (mode->next == scrp->modes) 616706f2543Smrg { 617706f2543Smrg if (pSize->width == randrp->virtualX && 618706f2543Smrg pSize->height == randrp->virtualY) 619706f2543Smrg { 620706f2543Smrg mode = scrp->modes; 621706f2543Smrg useVirtual = TRUE; 622706f2543Smrg break; 623706f2543Smrg } 624706f2543Smrg if (randrp->maxX == 0 || randrp->maxY == 0) 625706f2543Smrg { 626706f2543Smrg randrp->maxX = maxX; 627706f2543Smrg randrp->maxY = maxY; 628706f2543Smrg } 629706f2543Smrg return FALSE; 630706f2543Smrg } 631706f2543Smrg } 632706f2543Smrg 633706f2543Smrg if (randrp->maxX == 0 || randrp->maxY == 0) 634706f2543Smrg { 635706f2543Smrg randrp->maxX = maxX; 636706f2543Smrg randrp->maxY = maxY; 637706f2543Smrg } 638706f2543Smrg 639706f2543Smrg if (!xf86RandR12SetMode (pScreen, mode, useVirtual, pSize->mmWidth, 640706f2543Smrg pSize->mmHeight)) { 641706f2543Smrg randrp->rotation = oldRotation; 642706f2543Smrg return FALSE; 643706f2543Smrg } 644706f2543Smrg 645706f2543Smrg /* 646706f2543Smrg * Move the cursor back where it belongs; SwitchMode repositions it 647706f2543Smrg */ 648706f2543Smrg if (pScreen == miPointerGetScreen(inputInfo.pointer)) 649706f2543Smrg { 650706f2543Smrg px = (px >= pScreen->width ? (pScreen->width - 1) : px); 651706f2543Smrg py = (py >= pScreen->height ? (pScreen->height - 1) : py); 652706f2543Smrg 653706f2543Smrg xf86SetViewport(pScreen, px, py); 654706f2543Smrg 655706f2543Smrg (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); 656706f2543Smrg } 657706f2543Smrg 658706f2543Smrg return TRUE; 659706f2543Smrg} 660706f2543Smrg 661706f2543Smrgstatic Bool 662706f2543Smrgxf86RandR12ScreenSetSize (ScreenPtr pScreen, 663706f2543Smrg CARD16 width, 664706f2543Smrg CARD16 height, 665706f2543Smrg CARD32 mmWidth, 666706f2543Smrg CARD32 mmHeight) 667706f2543Smrg{ 668706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 669706f2543Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 670706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 671706f2543Smrg WindowPtr pRoot = pScreen->root; 672706f2543Smrg PixmapPtr pScrnPix; 673706f2543Smrg Bool ret = FALSE; 674706f2543Smrg int c; 675706f2543Smrg 676706f2543Smrg if (xf86RandR12Key) { 677706f2543Smrg if (randrp->virtualX == -1 || randrp->virtualY == -1) 678706f2543Smrg { 679706f2543Smrg randrp->virtualX = pScrn->virtualX; 680706f2543Smrg randrp->virtualY = pScrn->virtualY; 681706f2543Smrg } 682706f2543Smrg } 683706f2543Smrg if (pRoot && pScrn->vtSema) 684706f2543Smrg (*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE); 685706f2543Smrg 686706f2543Smrg /* Let the driver update virtualX and virtualY */ 687706f2543Smrg if (!(*config->funcs->resize)(pScrn, width, height)) 688706f2543Smrg goto finish; 689706f2543Smrg 690706f2543Smrg ret = TRUE; 691706f2543Smrg /* Update panning information */ 692706f2543Smrg for (c = 0; c < config->num_crtc; c++) { 693706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 694706f2543Smrg if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1 || 695706f2543Smrg crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) { 696706f2543Smrg if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1) 697706f2543Smrg crtc->panningTotalArea.x2 += width - pScreen->width; 698706f2543Smrg if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1) 699706f2543Smrg crtc->panningTotalArea.y2 += height - pScreen->height; 700706f2543Smrg if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1) 701706f2543Smrg crtc->panningTrackingArea.x2 += width - pScreen->width; 702706f2543Smrg if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1) 703706f2543Smrg crtc->panningTrackingArea.y2 += height - pScreen->height; 704706f2543Smrg xf86RandR13VerifyPanningArea (crtc, width, height); 705706f2543Smrg xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); 706706f2543Smrg } 707706f2543Smrg } 708706f2543Smrg 709706f2543Smrg pScrnPix = (*pScreen->GetScreenPixmap)(pScreen); 710706f2543Smrg pScreen->width = pScrnPix->drawable.width = width; 711706f2543Smrg pScreen->height = pScrnPix->drawable.height = height; 712706f2543Smrg randrp->mmWidth = pScreen->mmWidth = mmWidth; 713706f2543Smrg randrp->mmHeight = pScreen->mmHeight = mmHeight; 714706f2543Smrg 715706f2543Smrg xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1); 716706f2543Smrg xf86SetViewport (pScreen, 0, 0); 717706f2543Smrg 718706f2543Smrgfinish: 719706f2543Smrg if (pRoot && pScrn->vtSema) 720706f2543Smrg (*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE); 721706f2543Smrg#if RANDR_12_INTERFACE 722706f2543Smrg if (xf86RandR12Key && pScreen->root && ret) 723706f2543Smrg RRScreenSizeNotify (pScreen); 724706f2543Smrg#endif 725706f2543Smrg return ret; 726706f2543Smrg} 727706f2543Smrg 728706f2543SmrgRotation 729706f2543Smrgxf86RandR12GetRotation(ScreenPtr pScreen) 730706f2543Smrg{ 731706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 732706f2543Smrg 733706f2543Smrg return randrp->rotation; 734706f2543Smrg} 735706f2543Smrg 736706f2543SmrgBool 737706f2543Smrgxf86RandR12CreateScreenResources (ScreenPtr pScreen) 738706f2543Smrg{ 739706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 740706f2543Smrg xf86CrtcConfigPtr config; 741706f2543Smrg XF86RandRInfoPtr randrp; 742706f2543Smrg int c; 743706f2543Smrg int width, height; 744706f2543Smrg int mmWidth, mmHeight; 745706f2543Smrg#ifdef PANORAMIX 746706f2543Smrg /* XXX disable RandR when using Xinerama */ 747706f2543Smrg if (!noPanoramiXExtension) 748706f2543Smrg return TRUE; 749706f2543Smrg#endif 750706f2543Smrg 751706f2543Smrg config = XF86_CRTC_CONFIG_PTR(pScrn); 752706f2543Smrg randrp = XF86RANDRINFO(pScreen); 753706f2543Smrg /* 754706f2543Smrg * Compute size of screen 755706f2543Smrg */ 756706f2543Smrg width = 0; height = 0; 757706f2543Smrg for (c = 0; c < config->num_crtc; c++) 758706f2543Smrg { 759706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 760706f2543Smrg int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation); 761706f2543Smrg int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation); 762706f2543Smrg 763706f2543Smrg if (crtc->enabled) { 764706f2543Smrg if (crtc_width > width) 765706f2543Smrg width = crtc_width; 766706f2543Smrg if (crtc_height > height) 767706f2543Smrg height = crtc_height; 768706f2543Smrg if (crtc->panningTotalArea.x2 > width) 769706f2543Smrg width = crtc->panningTotalArea.x2; 770706f2543Smrg if (crtc->panningTotalArea.y2 > height) 771706f2543Smrg height = crtc->panningTotalArea.y2; 772706f2543Smrg } 773706f2543Smrg } 774706f2543Smrg 775706f2543Smrg if (width && height) 776706f2543Smrg { 777706f2543Smrg /* 778706f2543Smrg * Compute physical size of screen 779706f2543Smrg */ 780706f2543Smrg if (monitorResolution) 781706f2543Smrg { 782706f2543Smrg mmWidth = width * 25.4 / monitorResolution; 783706f2543Smrg mmHeight = height * 25.4 / monitorResolution; 784706f2543Smrg } 785706f2543Smrg else 786706f2543Smrg { 787706f2543Smrg xf86OutputPtr output = xf86CompatOutput(pScrn); 788706f2543Smrg 789706f2543Smrg if (output && 790706f2543Smrg output->conf_monitor && 791706f2543Smrg (output->conf_monitor->mon_width > 0 && 792706f2543Smrg output->conf_monitor->mon_height > 0)) 793706f2543Smrg { 794706f2543Smrg /* 795706f2543Smrg * Prefer user configured DisplaySize 796706f2543Smrg */ 797706f2543Smrg mmWidth = output->conf_monitor->mon_width; 798706f2543Smrg mmHeight = output->conf_monitor->mon_height; 799706f2543Smrg } 800706f2543Smrg else 801706f2543Smrg { 802706f2543Smrg /* 803706f2543Smrg * Otherwise, just set the screen to DEFAULT_DPI 804706f2543Smrg */ 805706f2543Smrg mmWidth = width * 25.4 / DEFAULT_DPI; 806706f2543Smrg mmHeight = height * 25.4 / DEFAULT_DPI; 807706f2543Smrg } 808706f2543Smrg } 809706f2543Smrg xf86DrvMsg(pScrn->scrnIndex, X_INFO, 810706f2543Smrg "Setting screen physical size to %d x %d\n", 811706f2543Smrg mmWidth, mmHeight); 812706f2543Smrg /* 813706f2543Smrg * This is the initial setting of the screen size. 814706f2543Smrg * We have to pre-set it here, otherwise panning would be adapted 815706f2543Smrg * to the new screen size. 816706f2543Smrg */ 817706f2543Smrg pScreen->width = width; 818706f2543Smrg pScreen->height = height; 819706f2543Smrg xf86RandR12ScreenSetSize (pScreen, 820706f2543Smrg width, 821706f2543Smrg height, 822706f2543Smrg mmWidth, 823706f2543Smrg mmHeight); 824706f2543Smrg } 825706f2543Smrg 826706f2543Smrg if (xf86RandR12Key == NULL) 827706f2543Smrg return TRUE; 828706f2543Smrg 829706f2543Smrg if (randrp->virtualX == -1 || randrp->virtualY == -1) 830706f2543Smrg { 831706f2543Smrg randrp->virtualX = pScrn->virtualX; 832706f2543Smrg randrp->virtualY = pScrn->virtualY; 833706f2543Smrg } 834706f2543Smrg xf86CrtcSetScreenSubpixelOrder (pScreen); 835706f2543Smrg#if RANDR_12_INTERFACE 836706f2543Smrg if (xf86RandR12CreateScreenResources12 (pScreen)) 837706f2543Smrg return TRUE; 838706f2543Smrg#endif 839706f2543Smrg return TRUE; 840706f2543Smrg} 841706f2543Smrg 842706f2543Smrg 843706f2543SmrgBool 844706f2543Smrgxf86RandR12Init (ScreenPtr pScreen) 845706f2543Smrg{ 846706f2543Smrg rrScrPrivPtr rp; 847706f2543Smrg XF86RandRInfoPtr randrp; 848706f2543Smrg 849706f2543Smrg#ifdef PANORAMIX 850706f2543Smrg /* XXX disable RandR when using Xinerama */ 851706f2543Smrg if (!noPanoramiXExtension) 852706f2543Smrg { 853706f2543Smrg if (xf86NumScreens == 1) 854706f2543Smrg noPanoramiXExtension = TRUE; 855706f2543Smrg else 856706f2543Smrg return TRUE; 857706f2543Smrg } 858706f2543Smrg#endif 859706f2543Smrg 860706f2543Smrg if (xf86RandR12Generation != serverGeneration) 861706f2543Smrg xf86RandR12Generation = serverGeneration; 862706f2543Smrg 863706f2543Smrg xf86RandR12Key = &xf86RandR12KeyRec; 864706f2543Smrg if (!dixRegisterPrivateKey(&xf86RandR12KeyRec, PRIVATE_SCREEN, 0)) 865706f2543Smrg return FALSE; 866706f2543Smrg 867706f2543Smrg randrp = malloc(sizeof (XF86RandRInfoRec)); 868706f2543Smrg if (!randrp) 869706f2543Smrg return FALSE; 870706f2543Smrg 871706f2543Smrg if (!RRScreenInit(pScreen)) 872706f2543Smrg { 873706f2543Smrg free(randrp); 874706f2543Smrg return FALSE; 875706f2543Smrg } 876706f2543Smrg rp = rrGetScrPriv(pScreen); 877706f2543Smrg rp->rrGetInfo = xf86RandR12GetInfo; 878706f2543Smrg rp->rrSetConfig = xf86RandR12SetConfig; 879706f2543Smrg 880706f2543Smrg randrp->virtualX = -1; 881706f2543Smrg randrp->virtualY = -1; 882706f2543Smrg randrp->mmWidth = pScreen->mmWidth; 883706f2543Smrg randrp->mmHeight = pScreen->mmHeight; 884706f2543Smrg 885706f2543Smrg randrp->rotation = RR_Rotate_0; /* initial rotated mode */ 886706f2543Smrg 887706f2543Smrg randrp->supported_rotations = RR_Rotate_0; 888706f2543Smrg 889706f2543Smrg randrp->maxX = randrp->maxY = 0; 890706f2543Smrg 891706f2543Smrg dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp); 892706f2543Smrg 893706f2543Smrg#if RANDR_12_INTERFACE 894706f2543Smrg if (!xf86RandR12Init12 (pScreen)) 895706f2543Smrg return FALSE; 896706f2543Smrg#endif 897706f2543Smrg return TRUE; 898706f2543Smrg} 899706f2543Smrg 900706f2543Smrgvoid 901706f2543Smrgxf86RandR12CloseScreen (ScreenPtr pScreen) 902706f2543Smrg{ 903706f2543Smrg XF86RandRInfoPtr randrp; 904706f2543Smrg 905706f2543Smrg if (xf86RandR12Key == NULL) 906706f2543Smrg return; 907706f2543Smrg 908706f2543Smrg randrp = XF86RANDRINFO(pScreen); 909706f2543Smrg#if RANDR_12_INTERFACE 910706f2543Smrg xf86Screens[pScreen->myNum]->EnterVT = randrp->orig_EnterVT; 911706f2543Smrg#endif 912706f2543Smrg 913706f2543Smrg free(randrp); 914706f2543Smrg} 915706f2543Smrg 916706f2543Smrgvoid 917706f2543Smrgxf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations) 918706f2543Smrg{ 919706f2543Smrg XF86RandRInfoPtr randrp; 920706f2543Smrg#if RANDR_12_INTERFACE 921706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 922706f2543Smrg int c; 923706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 924706f2543Smrg#endif 925706f2543Smrg 926706f2543Smrg if (xf86RandR12Key == NULL) 927706f2543Smrg return; 928706f2543Smrg 929706f2543Smrg randrp = XF86RANDRINFO(pScreen); 930706f2543Smrg#if RANDR_12_INTERFACE 931706f2543Smrg for (c = 0; c < config->num_crtc; c++) { 932706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 933706f2543Smrg 934706f2543Smrg RRCrtcSetRotations (crtc->randr_crtc, rotations); 935706f2543Smrg } 936706f2543Smrg#endif 937706f2543Smrg randrp->supported_rotations = rotations; 938706f2543Smrg} 939706f2543Smrg 940706f2543Smrgvoid 941706f2543Smrgxf86RandR12SetTransformSupport (ScreenPtr pScreen, Bool transforms) 942706f2543Smrg{ 943706f2543Smrg XF86RandRInfoPtr randrp; 944706f2543Smrg#if RANDR_13_INTERFACE 945706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 946706f2543Smrg int c; 947706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 948706f2543Smrg#endif 949706f2543Smrg 950706f2543Smrg if (xf86RandR12Key == NULL) 951706f2543Smrg return; 952706f2543Smrg 953706f2543Smrg randrp = XF86RANDRINFO(pScreen); 954706f2543Smrg#if RANDR_13_INTERFACE 955706f2543Smrg for (c = 0; c < config->num_crtc; c++) { 956706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 957706f2543Smrg 958706f2543Smrg RRCrtcSetTransformSupport (crtc->randr_crtc, transforms); 959706f2543Smrg } 960706f2543Smrg#endif 961706f2543Smrg} 962706f2543Smrg 963706f2543Smrgvoid 964706f2543Smrgxf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y) 965706f2543Smrg{ 966706f2543Smrg ScreenPtr pScreen = screenInfo.screens[pScrn->scrnIndex]; 967706f2543Smrg 968706f2543Smrg if (xf86RandR12Generation != serverGeneration || 969706f2543Smrg XF86RANDRINFO(pScreen)->virtualX == -1) 970706f2543Smrg { 971706f2543Smrg *x = pScrn->virtualX; 972706f2543Smrg *y = pScrn->virtualY; 973706f2543Smrg } else { 974706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 975706f2543Smrg 976706f2543Smrg *x = randrp->virtualX; 977706f2543Smrg *y = randrp->virtualY; 978706f2543Smrg } 979706f2543Smrg} 980706f2543Smrg 981706f2543Smrg#if RANDR_12_INTERFACE 982706f2543Smrg 983706f2543Smrg#define FLAG_BITS (RR_HSyncPositive | \ 984706f2543Smrg RR_HSyncNegative | \ 985706f2543Smrg RR_VSyncPositive | \ 986706f2543Smrg RR_VSyncNegative | \ 987706f2543Smrg RR_Interlace | \ 988706f2543Smrg RR_DoubleScan | \ 989706f2543Smrg RR_CSync | \ 990706f2543Smrg RR_CSyncPositive | \ 991706f2543Smrg RR_CSyncNegative | \ 992706f2543Smrg RR_HSkewPresent | \ 993706f2543Smrg RR_BCast | \ 994706f2543Smrg RR_PixelMultiplex | \ 995706f2543Smrg RR_DoubleClock | \ 996706f2543Smrg RR_ClockDivideBy2) 997706f2543Smrg 998706f2543Smrgstatic Bool 999706f2543Smrgxf86RandRModeMatches (RRModePtr randr_mode, 1000706f2543Smrg DisplayModePtr mode) 1001706f2543Smrg{ 1002706f2543Smrg#if 0 1003706f2543Smrg if (match_name) 1004706f2543Smrg { 1005706f2543Smrg /* check for same name */ 1006706f2543Smrg int len = strlen (mode->name); 1007706f2543Smrg if (randr_mode->mode.nameLength != len) return FALSE; 1008706f2543Smrg if (memcmp (randr_mode->name, mode->name, len) != 0) return FALSE; 1009706f2543Smrg } 1010706f2543Smrg#endif 1011706f2543Smrg 1012706f2543Smrg /* check for same timings */ 1013706f2543Smrg if (randr_mode->mode.dotClock / 1000 != mode->Clock) return FALSE; 1014706f2543Smrg if (randr_mode->mode.width != mode->HDisplay) return FALSE; 1015706f2543Smrg if (randr_mode->mode.hSyncStart != mode->HSyncStart) return FALSE; 1016706f2543Smrg if (randr_mode->mode.hSyncEnd != mode->HSyncEnd) return FALSE; 1017706f2543Smrg if (randr_mode->mode.hTotal != mode->HTotal) return FALSE; 1018706f2543Smrg if (randr_mode->mode.hSkew != mode->HSkew) return FALSE; 1019706f2543Smrg if (randr_mode->mode.height != mode->VDisplay) return FALSE; 1020706f2543Smrg if (randr_mode->mode.vSyncStart != mode->VSyncStart) return FALSE; 1021706f2543Smrg if (randr_mode->mode.vSyncEnd != mode->VSyncEnd) return FALSE; 1022706f2543Smrg if (randr_mode->mode.vTotal != mode->VTotal) return FALSE; 1023706f2543Smrg 1024706f2543Smrg /* check for same flags (using only the XF86 valid flag bits) */ 1025706f2543Smrg if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS)) 1026706f2543Smrg return FALSE; 1027706f2543Smrg 1028706f2543Smrg /* everything matches */ 1029706f2543Smrg return TRUE; 1030706f2543Smrg} 1031706f2543Smrg 1032706f2543Smrgstatic Bool 1033706f2543Smrgxf86RandR12CrtcNotify (RRCrtcPtr randr_crtc) 1034706f2543Smrg{ 1035706f2543Smrg ScreenPtr pScreen = randr_crtc->pScreen; 1036706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1037706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1038706f2543Smrg RRModePtr randr_mode = NULL; 1039706f2543Smrg int x; 1040706f2543Smrg int y; 1041706f2543Smrg Rotation rotation; 1042706f2543Smrg int numOutputs; 1043706f2543Smrg RROutputPtr *randr_outputs; 1044706f2543Smrg RROutputPtr randr_output; 1045706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1046706f2543Smrg xf86OutputPtr output; 1047706f2543Smrg int i, j; 1048706f2543Smrg DisplayModePtr mode = &crtc->mode; 1049706f2543Smrg Bool ret; 1050706f2543Smrg 1051706f2543Smrg randr_outputs = malloc(config->num_output * sizeof (RROutputPtr)); 1052706f2543Smrg if (!randr_outputs) 1053706f2543Smrg return FALSE; 1054706f2543Smrg x = crtc->x; 1055706f2543Smrg y = crtc->y; 1056706f2543Smrg rotation = crtc->rotation; 1057706f2543Smrg numOutputs = 0; 1058706f2543Smrg randr_mode = NULL; 1059706f2543Smrg for (i = 0; i < config->num_output; i++) 1060706f2543Smrg { 1061706f2543Smrg output = config->output[i]; 1062706f2543Smrg if (output->crtc == crtc) 1063706f2543Smrg { 1064706f2543Smrg randr_output = output->randr_output; 1065706f2543Smrg randr_outputs[numOutputs++] = randr_output; 1066706f2543Smrg /* 1067706f2543Smrg * We make copies of modes, so pointer equality 1068706f2543Smrg * isn't sufficient 1069706f2543Smrg */ 1070706f2543Smrg for (j = 0; j < randr_output->numModes + randr_output->numUserModes; j++) 1071706f2543Smrg { 1072706f2543Smrg RRModePtr m = (j < randr_output->numModes ? 1073706f2543Smrg randr_output->modes[j] : 1074706f2543Smrg randr_output->userModes[j-randr_output->numModes]); 1075706f2543Smrg 1076706f2543Smrg if (xf86RandRModeMatches (m, mode)) 1077706f2543Smrg { 1078706f2543Smrg randr_mode = m; 1079706f2543Smrg break; 1080706f2543Smrg } 1081706f2543Smrg } 1082706f2543Smrg } 1083706f2543Smrg } 1084706f2543Smrg ret = RRCrtcNotify (randr_crtc, randr_mode, x, y, 1085706f2543Smrg rotation, 1086706f2543Smrg crtc->transformPresent ? &crtc->transform : NULL, 1087706f2543Smrg numOutputs, randr_outputs); 1088706f2543Smrg free(randr_outputs); 1089706f2543Smrg return ret; 1090706f2543Smrg} 1091706f2543Smrg 1092706f2543Smrg/* 1093706f2543Smrg * Convert a RandR mode to a DisplayMode 1094706f2543Smrg */ 1095706f2543Smrgstatic void 1096706f2543Smrgxf86RandRModeConvert (ScrnInfoPtr scrn, 1097706f2543Smrg RRModePtr randr_mode, 1098706f2543Smrg DisplayModePtr mode) 1099706f2543Smrg{ 1100706f2543Smrg memset(mode, 0, sizeof(DisplayModeRec)); 1101706f2543Smrg mode->status = MODE_OK; 1102706f2543Smrg 1103706f2543Smrg mode->Clock = randr_mode->mode.dotClock / 1000; 1104706f2543Smrg 1105706f2543Smrg mode->HDisplay = randr_mode->mode.width; 1106706f2543Smrg mode->HSyncStart = randr_mode->mode.hSyncStart; 1107706f2543Smrg mode->HSyncEnd = randr_mode->mode.hSyncEnd; 1108706f2543Smrg mode->HTotal = randr_mode->mode.hTotal; 1109706f2543Smrg mode->HSkew = randr_mode->mode.hSkew; 1110706f2543Smrg 1111706f2543Smrg mode->VDisplay = randr_mode->mode.height; 1112706f2543Smrg mode->VSyncStart = randr_mode->mode.vSyncStart; 1113706f2543Smrg mode->VSyncEnd = randr_mode->mode.vSyncEnd; 1114706f2543Smrg mode->VTotal = randr_mode->mode.vTotal; 1115706f2543Smrg mode->VScan = 0; 1116706f2543Smrg 1117706f2543Smrg mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS; 1118706f2543Smrg 1119706f2543Smrg xf86SetModeCrtc (mode, scrn->adjustFlags); 1120706f2543Smrg} 1121706f2543Smrg 1122706f2543Smrgstatic Bool 1123706f2543Smrgxf86RandR12CrtcSet (ScreenPtr pScreen, 1124706f2543Smrg RRCrtcPtr randr_crtc, 1125706f2543Smrg RRModePtr randr_mode, 1126706f2543Smrg int x, 1127706f2543Smrg int y, 1128706f2543Smrg Rotation rotation, 1129706f2543Smrg int num_randr_outputs, 1130706f2543Smrg RROutputPtr *randr_outputs) 1131706f2543Smrg{ 1132706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 1133706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1134706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1135706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1136706f2543Smrg RRTransformPtr transform; 1137706f2543Smrg Bool changed = FALSE; 1138706f2543Smrg int o, ro; 1139706f2543Smrg xf86CrtcPtr *save_crtcs; 1140706f2543Smrg Bool save_enabled = crtc->enabled; 1141706f2543Smrg 1142706f2543Smrg if (!crtc->scrn->vtSema) 1143706f2543Smrg return FALSE; 1144706f2543Smrg 1145706f2543Smrg save_crtcs = malloc(config->num_output * sizeof (xf86CrtcPtr)); 1146706f2543Smrg if ((randr_mode != NULL) != crtc->enabled) 1147706f2543Smrg changed = TRUE; 1148706f2543Smrg else if (randr_mode && !xf86RandRModeMatches (randr_mode, &crtc->mode)) 1149706f2543Smrg changed = TRUE; 1150706f2543Smrg 1151706f2543Smrg if (rotation != crtc->rotation) 1152706f2543Smrg changed = TRUE; 1153706f2543Smrg 1154706f2543Smrg transform = RRCrtcGetTransform (randr_crtc); 1155706f2543Smrg if ((transform != NULL) != crtc->transformPresent) 1156706f2543Smrg changed = TRUE; 1157706f2543Smrg else if (transform && memcmp (&transform->transform, &crtc->transform.transform, 1158706f2543Smrg sizeof (transform->transform)) != 0) 1159706f2543Smrg changed = TRUE; 1160706f2543Smrg 1161706f2543Smrg if (x != crtc->x || y != crtc->y) 1162706f2543Smrg changed = TRUE; 1163706f2543Smrg for (o = 0; o < config->num_output; o++) 1164706f2543Smrg { 1165706f2543Smrg xf86OutputPtr output = config->output[o]; 1166706f2543Smrg xf86CrtcPtr new_crtc; 1167706f2543Smrg 1168706f2543Smrg save_crtcs[o] = output->crtc; 1169706f2543Smrg 1170706f2543Smrg if (output->crtc == crtc) 1171706f2543Smrg new_crtc = NULL; 1172706f2543Smrg else 1173706f2543Smrg new_crtc = output->crtc; 1174706f2543Smrg for (ro = 0; ro < num_randr_outputs; ro++) 1175706f2543Smrg if (output->randr_output == randr_outputs[ro]) 1176706f2543Smrg { 1177706f2543Smrg new_crtc = crtc; 1178706f2543Smrg break; 1179706f2543Smrg } 1180706f2543Smrg if (new_crtc != output->crtc) 1181706f2543Smrg { 1182706f2543Smrg changed = TRUE; 1183706f2543Smrg output->crtc = new_crtc; 1184706f2543Smrg } 1185706f2543Smrg } 1186706f2543Smrg for (ro = 0; ro < num_randr_outputs; ro++) 1187706f2543Smrg if (randr_outputs[ro]->pendingProperties) 1188706f2543Smrg changed = TRUE; 1189706f2543Smrg 1190706f2543Smrg /* XXX need device-independent mode setting code through an API */ 1191706f2543Smrg if (changed) 1192706f2543Smrg { 1193706f2543Smrg crtc->enabled = randr_mode != NULL; 1194706f2543Smrg 1195706f2543Smrg if (randr_mode) 1196706f2543Smrg { 1197706f2543Smrg DisplayModeRec mode; 1198706f2543Smrg RRTransformPtr transform = RRCrtcGetTransform (randr_crtc); 1199706f2543Smrg 1200706f2543Smrg xf86RandRModeConvert (pScrn, randr_mode, &mode); 1201706f2543Smrg if (!xf86CrtcSetModeTransform (crtc, &mode, rotation, transform, x, y)) 1202706f2543Smrg { 1203706f2543Smrg crtc->enabled = save_enabled; 1204706f2543Smrg for (o = 0; o < config->num_output; o++) 1205706f2543Smrg { 1206706f2543Smrg xf86OutputPtr output = config->output[o]; 1207706f2543Smrg output->crtc = save_crtcs[o]; 1208706f2543Smrg } 1209706f2543Smrg free(save_crtcs); 1210706f2543Smrg return FALSE; 1211706f2543Smrg } 1212706f2543Smrg xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height); 1213706f2543Smrg xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); 1214706f2543Smrg /* 1215706f2543Smrg * Save the last successful setting for EnterVT 1216706f2543Smrg */ 1217706f2543Smrg crtc->desiredMode = mode; 1218706f2543Smrg crtc->desiredRotation = rotation; 1219706f2543Smrg if (transform) { 1220706f2543Smrg crtc->desiredTransform = *transform; 1221706f2543Smrg crtc->desiredTransformPresent = TRUE; 1222706f2543Smrg } else 1223706f2543Smrg crtc->desiredTransformPresent = FALSE; 1224706f2543Smrg 1225706f2543Smrg crtc->desiredX = x; 1226706f2543Smrg crtc->desiredY = y; 1227706f2543Smrg } 1228706f2543Smrg xf86DisableUnusedFunctions (pScrn); 1229706f2543Smrg } 1230706f2543Smrg free(save_crtcs); 1231706f2543Smrg return xf86RandR12CrtcNotify (randr_crtc); 1232706f2543Smrg} 1233706f2543Smrg 1234706f2543Smrgstatic Bool 1235706f2543Smrgxf86RandR12CrtcSetGamma (ScreenPtr pScreen, 1236706f2543Smrg RRCrtcPtr randr_crtc) 1237706f2543Smrg{ 1238706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1239706f2543Smrg 1240706f2543Smrg if (crtc->funcs->gamma_set == NULL) 1241706f2543Smrg return FALSE; 1242706f2543Smrg 1243706f2543Smrg if (!crtc->scrn->vtSema) 1244706f2543Smrg return TRUE; 1245706f2543Smrg 1246706f2543Smrg /* Realloc local gamma if needed. */ 1247706f2543Smrg if (randr_crtc->gammaSize != crtc->gamma_size) { 1248706f2543Smrg CARD16 *tmp_ptr; 1249706f2543Smrg tmp_ptr = realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof (CARD16)); 1250706f2543Smrg if (!tmp_ptr) 1251706f2543Smrg return FALSE; 1252706f2543Smrg crtc->gamma_red = tmp_ptr; 1253706f2543Smrg crtc->gamma_green = crtc->gamma_red + crtc->gamma_size; 1254706f2543Smrg crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size; 1255706f2543Smrg } 1256706f2543Smrg 1257706f2543Smrg crtc->gamma_size = randr_crtc->gammaSize; 1258706f2543Smrg memcpy (crtc->gamma_red, randr_crtc->gammaRed, crtc->gamma_size * sizeof (CARD16)); 1259706f2543Smrg memcpy (crtc->gamma_green, randr_crtc->gammaGreen, crtc->gamma_size * sizeof (CARD16)); 1260706f2543Smrg memcpy (crtc->gamma_blue, randr_crtc->gammaBlue, crtc->gamma_size * sizeof (CARD16)); 1261706f2543Smrg 1262706f2543Smrg /* Only set it when the crtc is actually running. 1263706f2543Smrg * Otherwise it will be set when it's activated. 1264706f2543Smrg */ 1265706f2543Smrg if (crtc->active) 1266706f2543Smrg crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green, 1267706f2543Smrg crtc->gamma_blue, crtc->gamma_size); 1268706f2543Smrg 1269706f2543Smrg return TRUE; 1270706f2543Smrg} 1271706f2543Smrg 1272706f2543Smrgstatic Bool 1273706f2543Smrgxf86RandR12CrtcGetGamma (ScreenPtr pScreen, 1274706f2543Smrg RRCrtcPtr randr_crtc) 1275706f2543Smrg{ 1276706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1277706f2543Smrg 1278706f2543Smrg if (!crtc->gamma_size) 1279706f2543Smrg return FALSE; 1280706f2543Smrg 1281706f2543Smrg if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue) 1282706f2543Smrg return FALSE; 1283706f2543Smrg 1284706f2543Smrg /* Realloc randr gamma if needed. */ 1285706f2543Smrg if (randr_crtc->gammaSize != crtc->gamma_size) { 1286706f2543Smrg CARD16 *tmp_ptr; 1287706f2543Smrg tmp_ptr = realloc(randr_crtc->gammaRed, 3 * crtc->gamma_size * sizeof (CARD16)); 1288706f2543Smrg if (!tmp_ptr) 1289706f2543Smrg return FALSE; 1290706f2543Smrg randr_crtc->gammaRed = tmp_ptr; 1291706f2543Smrg randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size; 1292706f2543Smrg randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size; 1293706f2543Smrg } 1294706f2543Smrg randr_crtc->gammaSize = crtc->gamma_size; 1295706f2543Smrg memcpy (randr_crtc->gammaRed, crtc->gamma_red, crtc->gamma_size * sizeof (CARD16)); 1296706f2543Smrg memcpy (randr_crtc->gammaGreen, crtc->gamma_green, crtc->gamma_size * sizeof (CARD16)); 1297706f2543Smrg memcpy (randr_crtc->gammaBlue, crtc->gamma_blue, crtc->gamma_size * sizeof (CARD16)); 1298706f2543Smrg 1299706f2543Smrg return TRUE; 1300706f2543Smrg} 1301706f2543Smrg 1302706f2543Smrgstatic Bool 1303706f2543Smrgxf86RandR12OutputSetProperty (ScreenPtr pScreen, 1304706f2543Smrg RROutputPtr randr_output, 1305706f2543Smrg Atom property, 1306706f2543Smrg RRPropertyValuePtr value) 1307706f2543Smrg{ 1308706f2543Smrg xf86OutputPtr output = randr_output->devPrivate; 1309706f2543Smrg 1310706f2543Smrg /* If we don't have any property handler, then we don't care what the 1311706f2543Smrg * user is setting properties to. 1312706f2543Smrg */ 1313706f2543Smrg if (output->funcs->set_property == NULL) 1314706f2543Smrg return TRUE; 1315706f2543Smrg 1316706f2543Smrg /* 1317706f2543Smrg * This function gets called even when vtSema is FALSE, as 1318706f2543Smrg * drivers will need to remember the correct value to apply 1319706f2543Smrg * when the VT switch occurs 1320706f2543Smrg */ 1321706f2543Smrg return output->funcs->set_property(output, property, value); 1322706f2543Smrg} 1323706f2543Smrg 1324706f2543Smrgstatic Bool 1325706f2543Smrgxf86RandR13OutputGetProperty (ScreenPtr pScreen, 1326706f2543Smrg RROutputPtr randr_output, 1327706f2543Smrg Atom property) 1328706f2543Smrg{ 1329706f2543Smrg xf86OutputPtr output = randr_output->devPrivate; 1330706f2543Smrg 1331706f2543Smrg if (output->funcs->get_property == NULL) 1332706f2543Smrg return TRUE; 1333706f2543Smrg 1334706f2543Smrg /* Should be safe even w/o vtSema */ 1335706f2543Smrg return output->funcs->get_property(output, property); 1336706f2543Smrg} 1337706f2543Smrg 1338706f2543Smrgstatic Bool 1339706f2543Smrgxf86RandR12OutputValidateMode (ScreenPtr pScreen, 1340706f2543Smrg RROutputPtr randr_output, 1341706f2543Smrg RRModePtr randr_mode) 1342706f2543Smrg{ 1343706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1344706f2543Smrg xf86OutputPtr output = randr_output->devPrivate; 1345706f2543Smrg DisplayModeRec mode; 1346706f2543Smrg 1347706f2543Smrg xf86RandRModeConvert (pScrn, randr_mode, &mode); 1348706f2543Smrg /* 1349706f2543Smrg * This function may be called when vtSema is FALSE, so 1350706f2543Smrg * the underlying function must either avoid touching the hardware 1351706f2543Smrg * or return FALSE when vtSema is FALSE 1352706f2543Smrg */ 1353706f2543Smrg if (output->funcs->mode_valid (output, &mode) != MODE_OK) 1354706f2543Smrg return FALSE; 1355706f2543Smrg return TRUE; 1356706f2543Smrg} 1357706f2543Smrg 1358706f2543Smrgstatic void 1359706f2543Smrgxf86RandR12ModeDestroy (ScreenPtr pScreen, RRModePtr randr_mode) 1360706f2543Smrg{ 1361706f2543Smrg} 1362706f2543Smrg 1363706f2543Smrg/** 1364706f2543Smrg * Given a list of xf86 modes and a RandR Output object, construct 1365706f2543Smrg * RandR modes and assign them to the output 1366706f2543Smrg */ 1367706f2543Smrgstatic Bool 1368706f2543Smrgxf86RROutputSetModes (RROutputPtr randr_output, DisplayModePtr modes) 1369706f2543Smrg{ 1370706f2543Smrg DisplayModePtr mode; 1371706f2543Smrg RRModePtr *rrmodes = NULL; 1372706f2543Smrg int nmode = 0; 1373706f2543Smrg int npreferred = 0; 1374706f2543Smrg Bool ret = TRUE; 1375706f2543Smrg int pref; 1376706f2543Smrg 1377706f2543Smrg for (mode = modes; mode; mode = mode->next) 1378706f2543Smrg nmode++; 1379706f2543Smrg 1380706f2543Smrg if (nmode) { 1381706f2543Smrg rrmodes = malloc(nmode * sizeof (RRModePtr)); 1382706f2543Smrg 1383706f2543Smrg if (!rrmodes) 1384706f2543Smrg return FALSE; 1385706f2543Smrg nmode = 0; 1386706f2543Smrg 1387706f2543Smrg for (pref = 1; pref >= 0; pref--) { 1388706f2543Smrg for (mode = modes; mode; mode = mode->next) { 1389706f2543Smrg if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) { 1390706f2543Smrg xRRModeInfo modeInfo; 1391706f2543Smrg RRModePtr rrmode; 1392706f2543Smrg 1393706f2543Smrg modeInfo.nameLength = strlen (mode->name); 1394706f2543Smrg modeInfo.width = mode->HDisplay; 1395706f2543Smrg modeInfo.dotClock = mode->Clock * 1000; 1396706f2543Smrg modeInfo.hSyncStart = mode->HSyncStart; 1397706f2543Smrg modeInfo.hSyncEnd = mode->HSyncEnd; 1398706f2543Smrg modeInfo.hTotal = mode->HTotal; 1399706f2543Smrg modeInfo.hSkew = mode->HSkew; 1400706f2543Smrg 1401706f2543Smrg modeInfo.height = mode->VDisplay; 1402706f2543Smrg modeInfo.vSyncStart = mode->VSyncStart; 1403706f2543Smrg modeInfo.vSyncEnd = mode->VSyncEnd; 1404706f2543Smrg modeInfo.vTotal = mode->VTotal; 1405706f2543Smrg modeInfo.modeFlags = mode->Flags; 1406706f2543Smrg 1407706f2543Smrg rrmode = RRModeGet (&modeInfo, mode->name); 1408706f2543Smrg if (rrmode) { 1409706f2543Smrg rrmodes[nmode++] = rrmode; 1410706f2543Smrg npreferred += pref; 1411706f2543Smrg } 1412706f2543Smrg } 1413706f2543Smrg } 1414706f2543Smrg } 1415706f2543Smrg } 1416706f2543Smrg 1417706f2543Smrg ret = RROutputSetModes (randr_output, rrmodes, nmode, npreferred); 1418706f2543Smrg free(rrmodes); 1419706f2543Smrg return ret; 1420706f2543Smrg} 1421706f2543Smrg 1422706f2543Smrg/* 1423706f2543Smrg * Mirror the current mode configuration to RandR 1424706f2543Smrg */ 1425706f2543Smrgstatic Bool 1426706f2543Smrgxf86RandR12SetInfo12 (ScreenPtr pScreen) 1427706f2543Smrg{ 1428706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1429706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1430706f2543Smrg RROutputPtr *clones; 1431706f2543Smrg RRCrtcPtr *crtcs; 1432706f2543Smrg int ncrtc; 1433706f2543Smrg int o, c, l; 1434706f2543Smrg RRCrtcPtr randr_crtc; 1435706f2543Smrg int nclone; 1436706f2543Smrg 1437706f2543Smrg clones = malloc(config->num_output * sizeof (RROutputPtr)); 1438706f2543Smrg crtcs = malloc(config->num_crtc * sizeof (RRCrtcPtr)); 1439706f2543Smrg for (o = 0; o < config->num_output; o++) 1440706f2543Smrg { 1441706f2543Smrg xf86OutputPtr output = config->output[o]; 1442706f2543Smrg 1443706f2543Smrg ncrtc = 0; 1444706f2543Smrg for (c = 0; c < config->num_crtc; c++) 1445706f2543Smrg if (output->possible_crtcs & (1 << c)) 1446706f2543Smrg crtcs[ncrtc++] = config->crtc[c]->randr_crtc; 1447706f2543Smrg 1448706f2543Smrg if (output->crtc) 1449706f2543Smrg randr_crtc = output->crtc->randr_crtc; 1450706f2543Smrg else 1451706f2543Smrg randr_crtc = NULL; 1452706f2543Smrg 1453706f2543Smrg if (!RROutputSetCrtcs (output->randr_output, crtcs, ncrtc)) 1454706f2543Smrg { 1455706f2543Smrg free(crtcs); 1456706f2543Smrg free(clones); 1457706f2543Smrg return FALSE; 1458706f2543Smrg } 1459706f2543Smrg 1460706f2543Smrg RROutputSetPhysicalSize(output->randr_output, 1461706f2543Smrg output->mm_width, 1462706f2543Smrg output->mm_height); 1463706f2543Smrg xf86RROutputSetModes (output->randr_output, output->probed_modes); 1464706f2543Smrg 1465706f2543Smrg switch (output->status) { 1466706f2543Smrg case XF86OutputStatusConnected: 1467706f2543Smrg RROutputSetConnection (output->randr_output, RR_Connected); 1468706f2543Smrg break; 1469706f2543Smrg case XF86OutputStatusDisconnected: 1470706f2543Smrg RROutputSetConnection (output->randr_output, RR_Disconnected); 1471706f2543Smrg break; 1472706f2543Smrg case XF86OutputStatusUnknown: 1473706f2543Smrg RROutputSetConnection (output->randr_output, RR_UnknownConnection); 1474706f2543Smrg break; 1475706f2543Smrg } 1476706f2543Smrg 1477706f2543Smrg RROutputSetSubpixelOrder (output->randr_output, output->subpixel_order); 1478706f2543Smrg 1479706f2543Smrg /* 1480706f2543Smrg * Valid clones 1481706f2543Smrg */ 1482706f2543Smrg nclone = 0; 1483706f2543Smrg for (l = 0; l < config->num_output; l++) 1484706f2543Smrg { 1485706f2543Smrg xf86OutputPtr clone = config->output[l]; 1486706f2543Smrg 1487706f2543Smrg if (l != o && (output->possible_clones & (1 << l))) 1488706f2543Smrg clones[nclone++] = clone->randr_output; 1489706f2543Smrg } 1490706f2543Smrg if (!RROutputSetClones (output->randr_output, clones, nclone)) 1491706f2543Smrg { 1492706f2543Smrg free(crtcs); 1493706f2543Smrg free(clones); 1494706f2543Smrg return FALSE; 1495706f2543Smrg } 1496706f2543Smrg } 1497706f2543Smrg free(crtcs); 1498706f2543Smrg free(clones); 1499706f2543Smrg return TRUE; 1500706f2543Smrg} 1501706f2543Smrg 1502706f2543Smrg 1503706f2543Smrg 1504706f2543Smrg/* 1505706f2543Smrg * Query the hardware for the current state, then mirror 1506706f2543Smrg * that to RandR 1507706f2543Smrg */ 1508706f2543Smrgstatic Bool 1509706f2543Smrgxf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations) 1510706f2543Smrg{ 1511706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1512706f2543Smrg 1513706f2543Smrg if (!pScrn->vtSema) 1514706f2543Smrg return TRUE; 1515706f2543Smrg xf86ProbeOutputModes (pScrn, 0, 0); 1516706f2543Smrg xf86SetScrnInfoModes (pScrn); 1517706f2543Smrg return xf86RandR12SetInfo12 (pScreen); 1518706f2543Smrg} 1519706f2543Smrg 1520706f2543Smrgstatic Bool 1521706f2543Smrgxf86RandR12CreateObjects12 (ScreenPtr pScreen) 1522706f2543Smrg{ 1523706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1524706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1525706f2543Smrg int c; 1526706f2543Smrg int o; 1527706f2543Smrg 1528706f2543Smrg if (!RRInit ()) 1529706f2543Smrg return FALSE; 1530706f2543Smrg 1531706f2543Smrg /* 1532706f2543Smrg * Configure crtcs 1533706f2543Smrg */ 1534706f2543Smrg for (c = 0; c < config->num_crtc; c++) 1535706f2543Smrg { 1536706f2543Smrg xf86CrtcPtr crtc = config->crtc[c]; 1537706f2543Smrg 1538706f2543Smrg crtc->randr_crtc = RRCrtcCreate (pScreen, crtc); 1539706f2543Smrg RRCrtcGammaSetSize (crtc->randr_crtc, 256); 1540706f2543Smrg } 1541706f2543Smrg /* 1542706f2543Smrg * Configure outputs 1543706f2543Smrg */ 1544706f2543Smrg for (o = 0; o < config->num_output; o++) 1545706f2543Smrg { 1546706f2543Smrg xf86OutputPtr output = config->output[o]; 1547706f2543Smrg 1548706f2543Smrg output->randr_output = RROutputCreate (pScreen, output->name, 1549706f2543Smrg strlen (output->name), 1550706f2543Smrg output); 1551706f2543Smrg 1552706f2543Smrg if (output->funcs->create_resources != NULL) 1553706f2543Smrg output->funcs->create_resources(output); 1554706f2543Smrg RRPostPendingProperties (output->randr_output); 1555706f2543Smrg } 1556706f2543Smrg return TRUE; 1557706f2543Smrg} 1558706f2543Smrg 1559706f2543Smrgstatic Bool 1560706f2543Smrgxf86RandR12CreateScreenResources12 (ScreenPtr pScreen) 1561706f2543Smrg{ 1562706f2543Smrg int c; 1563706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1564706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1565706f2543Smrg 1566706f2543Smrg if (xf86RandR12Key == NULL) 1567706f2543Smrg return TRUE; 1568706f2543Smrg 1569706f2543Smrg for (c = 0; c < config->num_crtc; c++) 1570706f2543Smrg xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); 1571706f2543Smrg 1572706f2543Smrg RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight, 1573706f2543Smrg config->maxWidth, config->maxHeight); 1574706f2543Smrg return TRUE; 1575706f2543Smrg} 1576706f2543Smrg 1577706f2543Smrg/* 1578706f2543Smrg * Something happened within the screen configuration due 1579706f2543Smrg * to DGA, VidMode or hot key. Tell RandR 1580706f2543Smrg */ 1581706f2543Smrg 1582706f2543Smrgvoid 1583706f2543Smrgxf86RandR12TellChanged (ScreenPtr pScreen) 1584706f2543Smrg{ 1585706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1586706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1587706f2543Smrg int c; 1588706f2543Smrg 1589706f2543Smrg if (xf86RandR12Key == NULL) 1590706f2543Smrg return; 1591706f2543Smrg 1592706f2543Smrg xf86RandR12SetInfo12 (pScreen); 1593706f2543Smrg for (c = 0; c < config->num_crtc; c++) 1594706f2543Smrg xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc); 1595706f2543Smrg 1596706f2543Smrg RRTellChanged (pScreen); 1597706f2543Smrg} 1598706f2543Smrg 1599706f2543Smrgstatic void 1600706f2543Smrgxf86RandR12PointerMoved (int scrnIndex, int x, int y) 1601706f2543Smrg{ 1602706f2543Smrg ScreenPtr pScreen = screenInfo.screens[scrnIndex]; 1603706f2543Smrg ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen); 1604706f2543Smrg xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn); 1605706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 1606706f2543Smrg int c; 1607706f2543Smrg 1608706f2543Smrg randrp->pointerX = x; 1609706f2543Smrg randrp->pointerY = y; 1610706f2543Smrg for (c = 0; c < config->num_crtc; c++) 1611706f2543Smrg xf86RandR13Pan (config->crtc[c], x, y); 1612706f2543Smrg} 1613706f2543Smrg 1614706f2543Smrgstatic Bool 1615706f2543Smrgxf86RandR13GetPanning (ScreenPtr pScreen, 1616706f2543Smrg RRCrtcPtr randr_crtc, 1617706f2543Smrg BoxPtr totalArea, 1618706f2543Smrg BoxPtr trackingArea, 1619706f2543Smrg INT16 *border) 1620706f2543Smrg{ 1621706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1622706f2543Smrg 1623706f2543Smrg if (crtc->version < 2) 1624706f2543Smrg return FALSE; 1625706f2543Smrg if (totalArea) 1626706f2543Smrg memcpy (totalArea, &crtc->panningTotalArea, sizeof(BoxRec)); 1627706f2543Smrg if (trackingArea) 1628706f2543Smrg memcpy (trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); 1629706f2543Smrg if (border) 1630706f2543Smrg memcpy (border, crtc->panningBorder, 4*sizeof(INT16)); 1631706f2543Smrg 1632706f2543Smrg return TRUE; 1633706f2543Smrg} 1634706f2543Smrg 1635706f2543Smrgstatic Bool 1636706f2543Smrgxf86RandR13SetPanning (ScreenPtr pScreen, 1637706f2543Smrg RRCrtcPtr randr_crtc, 1638706f2543Smrg BoxPtr totalArea, 1639706f2543Smrg BoxPtr trackingArea, 1640706f2543Smrg INT16 *border) 1641706f2543Smrg{ 1642706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 1643706f2543Smrg xf86CrtcPtr crtc = randr_crtc->devPrivate; 1644706f2543Smrg BoxRec oldTotalArea; 1645706f2543Smrg BoxRec oldTrackingArea; 1646706f2543Smrg INT16 oldBorder[4]; 1647706f2543Smrg 1648706f2543Smrg 1649706f2543Smrg if (crtc->version < 2) 1650706f2543Smrg return FALSE; 1651706f2543Smrg 1652706f2543Smrg memcpy (&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec)); 1653706f2543Smrg memcpy (&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec)); 1654706f2543Smrg memcpy (oldBorder, crtc->panningBorder, 4*sizeof(INT16)); 1655706f2543Smrg 1656706f2543Smrg if (totalArea) 1657706f2543Smrg memcpy (&crtc->panningTotalArea, totalArea, sizeof(BoxRec)); 1658706f2543Smrg if (trackingArea) 1659706f2543Smrg memcpy (&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec)); 1660706f2543Smrg if (border) 1661706f2543Smrg memcpy (crtc->panningBorder, border, 4*sizeof(INT16)); 1662706f2543Smrg 1663706f2543Smrg if (xf86RandR13VerifyPanningArea (crtc, pScreen->width, pScreen->height)) { 1664706f2543Smrg xf86RandR13Pan (crtc, randrp->pointerX, randrp->pointerY); 1665706f2543Smrg return TRUE; 1666706f2543Smrg } else { 1667706f2543Smrg /* Restore old settings */ 1668706f2543Smrg memcpy (&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec)); 1669706f2543Smrg memcpy (&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec)); 1670706f2543Smrg memcpy (crtc->panningBorder, oldBorder, 4*sizeof(INT16)); 1671706f2543Smrg return FALSE; 1672706f2543Smrg } 1673706f2543Smrg} 1674706f2543Smrg 1675706f2543Smrg/* 1676706f2543Smrg * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers 1677706f2543Smrg * any per-crtc setup. You asked for it... 1678706f2543Smrg */ 1679706f2543Smrg 1680706f2543Smrgstatic void 1681706f2543Smrggamma_to_ramp(float gamma, CARD16 *ramp, int size) 1682706f2543Smrg{ 1683706f2543Smrg int i; 1684706f2543Smrg 1685706f2543Smrg for (i = 0; i < size; i++) { 1686706f2543Smrg if (gamma == 1.0) 1687706f2543Smrg ramp[i] = i << 8; 1688706f2543Smrg else 1689706f2543Smrg ramp[i] = (CARD16)(pow((double)i / (double)(size - 1), 1. / gamma) 1690706f2543Smrg * (double)(size - 1) * 256); 1691706f2543Smrg } 1692706f2543Smrg} 1693706f2543Smrg 1694706f2543Smrgstatic int 1695706f2543Smrgxf86RandR12ChangeGamma(int scrnIndex, Gamma gamma) 1696706f2543Smrg{ 1697706f2543Smrg CARD16 *points, *red, *green, *blue; 1698706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[scrnIndex]; 1699706f2543Smrg RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn); 1700706f2543Smrg int size; 1701706f2543Smrg 1702706f2543Smrg if (!crtc) 1703706f2543Smrg return Success; 1704706f2543Smrg 1705706f2543Smrg size = max(0, crtc->gammaSize); 1706706f2543Smrg if (!size) 1707706f2543Smrg return Success; 1708706f2543Smrg 1709706f2543Smrg points = calloc(size, 3 * sizeof(CARD16)); 1710706f2543Smrg if (!points) 1711706f2543Smrg return BadAlloc; 1712706f2543Smrg 1713706f2543Smrg red = points; 1714706f2543Smrg green = points + size; 1715706f2543Smrg blue = points + 2 * size; 1716706f2543Smrg 1717706f2543Smrg gamma_to_ramp(gamma.red, red, size); 1718706f2543Smrg gamma_to_ramp(gamma.green, green, size); 1719706f2543Smrg gamma_to_ramp(gamma.blue, blue, size); 1720706f2543Smrg RRCrtcGammaSet(crtc, red, green, blue); 1721706f2543Smrg 1722706f2543Smrg free(points); 1723706f2543Smrg 1724706f2543Smrg pScrn->gamma = gamma; 1725706f2543Smrg 1726706f2543Smrg return Success; 1727706f2543Smrg} 1728706f2543Smrg 1729706f2543Smrgstatic Bool 1730706f2543Smrgxf86RandR12EnterVT (int screen_index, int flags) 1731706f2543Smrg{ 1732706f2543Smrg ScreenPtr pScreen = screenInfo.screens[screen_index]; 1733706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[screen_index]; 1734706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 1735706f2543Smrg rrScrPrivPtr rp = rrGetScrPriv(pScreen); 1736706f2543Smrg Bool ret; 1737706f2543Smrg 1738706f2543Smrg if (randrp->orig_EnterVT) { 1739706f2543Smrg pScrn->EnterVT = randrp->orig_EnterVT; 1740706f2543Smrg ret = pScrn->EnterVT (screen_index, flags); 1741706f2543Smrg randrp->orig_EnterVT = pScrn->EnterVT; 1742706f2543Smrg pScrn->EnterVT = xf86RandR12EnterVT; 1743706f2543Smrg if (!ret) 1744706f2543Smrg return FALSE; 1745706f2543Smrg } 1746706f2543Smrg 1747706f2543Smrg /* reload gamma */ 1748706f2543Smrg int i; 1749706f2543Smrg for (i = 0; i < rp->numCrtcs; i++) 1750706f2543Smrg xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]); 1751706f2543Smrg 1752706f2543Smrg return RRGetInfo (pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */ 1753706f2543Smrg} 1754706f2543Smrg 1755706f2543Smrgstatic Bool 1756706f2543Smrgxf86RandR12Init12 (ScreenPtr pScreen) 1757706f2543Smrg{ 1758706f2543Smrg ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 1759706f2543Smrg rrScrPrivPtr rp = rrGetScrPriv(pScreen); 1760706f2543Smrg XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen); 1761706f2543Smrg int i; 1762706f2543Smrg 1763706f2543Smrg rp->rrGetInfo = xf86RandR12GetInfo12; 1764706f2543Smrg rp->rrScreenSetSize = xf86RandR12ScreenSetSize; 1765706f2543Smrg rp->rrCrtcSet = xf86RandR12CrtcSet; 1766706f2543Smrg rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma; 1767706f2543Smrg rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma; 1768706f2543Smrg rp->rrOutputSetProperty = xf86RandR12OutputSetProperty; 1769706f2543Smrg rp->rrOutputValidateMode = xf86RandR12OutputValidateMode; 1770706f2543Smrg#if RANDR_13_INTERFACE 1771706f2543Smrg rp->rrOutputGetProperty = xf86RandR13OutputGetProperty; 1772706f2543Smrg rp->rrGetPanning = xf86RandR13GetPanning; 1773706f2543Smrg rp->rrSetPanning = xf86RandR13SetPanning; 1774706f2543Smrg#endif 1775706f2543Smrg rp->rrModeDestroy = xf86RandR12ModeDestroy; 1776706f2543Smrg rp->rrSetConfig = NULL; 1777706f2543Smrg pScrn->PointerMoved = xf86RandR12PointerMoved; 1778706f2543Smrg pScrn->ChangeGamma = xf86RandR12ChangeGamma; 1779706f2543Smrg 1780706f2543Smrg randrp->orig_EnterVT = pScrn->EnterVT; 1781706f2543Smrg pScrn->EnterVT = xf86RandR12EnterVT; 1782706f2543Smrg 1783706f2543Smrg if (!xf86RandR12CreateObjects12 (pScreen)) 1784706f2543Smrg return FALSE; 1785706f2543Smrg 1786706f2543Smrg /* 1787706f2543Smrg * Configure output modes 1788706f2543Smrg */ 1789706f2543Smrg if (!xf86RandR12SetInfo12 (pScreen)) 1790706f2543Smrg return FALSE; 1791706f2543Smrg for (i = 0; i < rp->numCrtcs; i++) { 1792706f2543Smrg xf86RandR12CrtcGetGamma(pScreen, rp->crtcs[i]); 1793706f2543Smrg } 1794706f2543Smrg return TRUE; 1795706f2543Smrg} 1796706f2543Smrg 1797706f2543Smrg#endif 1798706f2543Smrg 1799706f2543SmrgBool 1800706f2543Smrgxf86RandR12PreInit (ScrnInfoPtr pScrn) 1801706f2543Smrg{ 1802706f2543Smrg return TRUE; 1803706f2543Smrg} 1804