Imported Upstream version 1.15.1
[deb_xorg-server.git] / hw / xfree86 / modes / xf86RandR12.c
CommitLineData
a09e091a
JB
1/*
2 * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc.
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#ifdef HAVE_XORG_CONFIG_H
24#include <xorg-config.h>
25#else
26#ifdef HAVE_CONFIG_H
27#include <config.h>
28#endif
29#endif
30
31#include "xf86.h"
32#include "os.h"
33#include "globals.h"
34#include "xf86Modes.h"
35#include "xf86Priv.h"
36#include "xf86DDC.h"
37#include "mipointer.h"
38#include "windowstr.h"
39#include "inputstr.h"
40#include <randrstr.h>
41#include <X11/extensions/render.h>
42
43#include "xf86Crtc.h"
44#include "xf86RandR12.h"
45
46typedef struct _xf86RandR12Info {
47 int virtualX;
48 int virtualY;
49 int mmWidth;
50 int mmHeight;
51 int maxX;
52 int maxY;
53 int pointerX;
54 int pointerY;
55 Rotation rotation; /* current mode */
56 Rotation supported_rotations; /* driver supported */
57
58 /* Used to wrap EnterVT so we can re-probe the outputs when a laptop unsuspends
59 * (actually, any time that we switch back into our VT).
60 *
61 * See https://bugs.freedesktop.org/show_bug.cgi?id=21554
62 */
63 xf86EnterVTProc *orig_EnterVT;
64
65 Bool panning;
66 ConstrainCursorHarderProcPtr orig_ConstrainCursorHarder;
67} XF86RandRInfoRec, *XF86RandRInfoPtr;
68
69#ifdef RANDR_12_INTERFACE
70static Bool xf86RandR12Init12(ScreenPtr pScreen);
71static Bool xf86RandR12CreateScreenResources12(ScreenPtr pScreen);
72#endif
73
74static int xf86RandR12Generation;
75
76static DevPrivateKeyRec xf86RandR12KeyRec;
77static DevPrivateKey xf86RandR12Key;
78
79#define XF86RANDRINFO(p) ((XF86RandRInfoPtr) \
80 dixLookupPrivate(&(p)->devPrivates, xf86RandR12Key))
81
82static int
83xf86RandR12ModeRefresh(DisplayModePtr mode)
84{
85 if (mode->VRefresh)
86 return (int) (mode->VRefresh + 0.5);
87 else
88 return (int) (mode->Clock * 1000.0 / mode->HTotal / mode->VTotal + 0.5);
89}
90
91/* Adapt panning area; return TRUE if panning area was valid without adaption */
92static int
93xf86RandR13VerifyPanningArea(xf86CrtcPtr crtc, int screenWidth,
94 int screenHeight)
95{
96 int ret = TRUE;
97
98 if (crtc->version < 2)
99 return FALSE;
100
101 if (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1) {
102 /* Panning in X is disabled */
103 if (crtc->panningTotalArea.x1 || crtc->panningTotalArea.x2)
104 /* Illegal configuration -> fail/disable */
105 ret = FALSE;
106 crtc->panningTotalArea.x1 = crtc->panningTotalArea.x2 = 0;
107 crtc->panningTrackingArea.x1 = crtc->panningTrackingArea.x2 = 0;
108 crtc->panningBorder[0] = crtc->panningBorder[2] = 0;
109 }
110 else {
111 /* Panning in X is enabled */
112 if (crtc->panningTotalArea.x1 < 0) {
113 /* Panning region outside screen -> move inside */
114 crtc->panningTotalArea.x2 -= crtc->panningTotalArea.x1;
115 crtc->panningTotalArea.x1 = 0;
116 ret = FALSE;
117 }
118 if (crtc->panningTotalArea.x2 <
119 crtc->panningTotalArea.x1 + crtc->mode.HDisplay) {
120 /* Panning region smaller than displayed area -> crop to displayed area */
121 crtc->panningTotalArea.x2 =
122 crtc->panningTotalArea.x1 + crtc->mode.HDisplay;
123 ret = FALSE;
124 }
125 if (crtc->panningTotalArea.x2 > screenWidth) {
126 /* Panning region larger than screen -> move inside, then crop to screen */
127 crtc->panningTotalArea.x1 -=
128 crtc->panningTotalArea.x2 - screenWidth;
129 crtc->panningTotalArea.x2 = screenWidth;
130 ret = FALSE;
131 if (crtc->panningTotalArea.x1 < 0)
132 crtc->panningTotalArea.x1 = 0;
133 }
134 if (crtc->panningBorder[0] + crtc->panningBorder[2] >
135 crtc->mode.HDisplay) {
136 /* Borders too large -> set to 0 */
137 crtc->panningBorder[0] = crtc->panningBorder[2] = 0;
138 ret = FALSE;
139 }
140 }
141
142 if (crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1) {
143 /* Panning in Y is disabled */
144 if (crtc->panningTotalArea.y1 || crtc->panningTotalArea.y2)
145 /* Illegal configuration -> fail/disable */
146 ret = FALSE;
147 crtc->panningTotalArea.y1 = crtc->panningTotalArea.y2 = 0;
148 crtc->panningTrackingArea.y1 = crtc->panningTrackingArea.y2 = 0;
149 crtc->panningBorder[1] = crtc->panningBorder[3] = 0;
150 }
151 else {
152 /* Panning in Y is enabled */
153 if (crtc->panningTotalArea.y1 < 0) {
154 /* Panning region outside screen -> move inside */
155 crtc->panningTotalArea.y2 -= crtc->panningTotalArea.y1;
156 crtc->panningTotalArea.y1 = 0;
157 ret = FALSE;
158 }
159 if (crtc->panningTotalArea.y2 <
160 crtc->panningTotalArea.y1 + crtc->mode.VDisplay) {
161 /* Panning region smaller than displayed area -> crop to displayed area */
162 crtc->panningTotalArea.y2 =
163 crtc->panningTotalArea.y1 + crtc->mode.VDisplay;
164 ret = FALSE;
165 }
166 if (crtc->panningTotalArea.y2 > screenHeight) {
167 /* Panning region larger than screen -> move inside, then crop to screen */
168 crtc->panningTotalArea.y1 -=
169 crtc->panningTotalArea.y2 - screenHeight;
170 crtc->panningTotalArea.y2 = screenHeight;
171 ret = FALSE;
172 if (crtc->panningTotalArea.y1 < 0)
173 crtc->panningTotalArea.y1 = 0;
174 }
175 if (crtc->panningBorder[1] + crtc->panningBorder[3] >
176 crtc->mode.VDisplay) {
177 /* Borders too large -> set to 0 */
178 crtc->panningBorder[1] = crtc->panningBorder[3] = 0;
179 ret = FALSE;
180 }
181 }
182
183 return ret;
184}
185
186/*
187 * The heart of the panning operation:
188 *
189 * Given a frame buffer position (fb_x, fb_y),
190 * and a crtc position (crtc_x, crtc_y),
191 * and a transform matrix which maps frame buffer to crtc,
192 * compute a panning position (pan_x, pan_y) that
193 * makes the resulting transform line those two up
194 */
195
196static void
197xf86ComputeCrtcPan(Bool transform_in_use,
198 struct pixman_f_transform *m,
199 double screen_x, double screen_y,
200 double crtc_x, double crtc_y,
201 int old_pan_x, int old_pan_y, int *new_pan_x, int *new_pan_y)
202{
203 if (transform_in_use) {
204 /*
205 * Given the current transform, M, the current position
206 * on the Screen, S, and the desired position on the CRTC,
207 * C, compute a translation, T, such that:
208 *
209 * M T S = C
210 *
211 * where T is of the form
212 *
213 * | 1 0 dx |
214 * | 0 1 dy |
215 * | 0 0 1 |
216 *
217 * M T S =
218 * | M00 Sx + M01 Sy + M00 dx + M01 dy + M02 | | Cx F |
219 * | M10 Sx + M11 Sy + M10 dx + M11 dy + M12 | = | Cy F |
220 * | M20 Sx + M21 Sy + M20 dx + M21 dy + M22 | | F |
221 *
222 * R = M S
223 *
224 * Cx F = M00 dx + M01 dy + R0
225 * Cy F = M10 dx + M11 dy + R1
226 * F = M20 dx + M21 dy + R2
227 *
228 * Zero out dx, then dy
229 *
230 * F (Cx M10 - Cy M00) =
231 * (M10 M01 - M00 M11) dy + M10 R0 - M00 R1
232 * F (M10 - Cy M20) =
233 * (M10 M21 - M20 M11) dy + M10 R2 - M20 R1
234 *
235 * F (Cx M11 - Cy M01) =
236 * (M11 M00 - M01 M10) dx + M11 R0 - M01 R1
237 * F (M11 - Cy M21) =
238 * (M11 M20 - M21 M10) dx + M11 R2 - M21 R1
239 *
240 * Make some temporaries
241 *
242 * T = | Cx M10 - Cy M00 |
243 * | Cx M11 - Cy M01 |
244 *
245 * U = | M10 M01 - M00 M11 |
246 * | M11 M00 - M01 M10 |
247 *
248 * Q = | M10 R0 - M00 R1 |
249 * | M11 R0 - M01 R1 |
250 *
251 * P = | M10 - Cy M20 |
252 * | M11 - Cy M21 |
253 *
254 * W = | M10 M21 - M20 M11 |
255 * | M11 M20 - M21 M10 |
256 *
257 * V = | M10 R2 - M20 R1 |
258 * | M11 R2 - M21 R1 |
259 *
260 * Rewrite:
261 *
262 * F T0 = U0 dy + Q0
263 * F P0 = W0 dy + V0
264 * F T1 = U1 dx + Q1
265 * F P1 = W1 dx + V1
266 *
267 * Solve for F (two ways)
268 *
269 * F (W0 T0 - U0 P0) = W0 Q0 - U0 V0
270 *
271 * W0 Q0 - U0 V0
272 * F = -------------
273 * W0 T0 - U0 P0
274 *
275 * F (W1 T1 - U1 P1) = W1 Q1 - U1 V1
276 *
277 * W1 Q1 - U1 V1
278 * F = -------------
279 * W1 T1 - U1 P1
280 *
281 * We'll use which ever solution works (denominator != 0)
282 *
283 * Finally, solve for dx and dy:
284 *
285 * dx = (F T1 - Q1) / U1
286 * dx = (F P1 - V1) / W1
287 *
288 * dy = (F T0 - Q0) / U0
289 * dy = (F P0 - V0) / W0
290 */
291 double r[3];
292 double q[2], u[2], t[2], v[2], w[2], p[2];
293 double f;
294 struct pict_f_vector d;
295 int i;
296
297 /* Get the un-normalized crtc coordinates again */
298 for (i = 0; i < 3; i++)
299 r[i] = m->m[i][0] * screen_x + m->m[i][1] * screen_y + m->m[i][2];
300
301 /* Combine values into temporaries */
302 for (i = 0; i < 2; i++) {
303 q[i] = m->m[1][i] * r[0] - m->m[0][i] * r[1];
304 u[i] = m->m[1][i] * m->m[0][1 - i] - m->m[0][i] * m->m[1][1 - i];
305 t[i] = m->m[1][i] * crtc_x - m->m[0][i] * crtc_y;
306
307 v[i] = m->m[1][i] * r[2] - m->m[2][i] * r[1];
308 w[i] = m->m[1][i] * m->m[2][1 - i] - m->m[2][i] * m->m[1][1 - i];
309 p[i] = m->m[1][i] - m->m[2][i] * crtc_y;
310 }
311
312 /* Find a way to compute f */
313 f = 0;
314 for (i = 0; i < 2; i++) {
315 double a = w[i] * q[i] - u[i] * v[i];
316 double b = w[i] * t[i] - u[i] * p[i];
317
318 if (b != 0) {
319 f = a / b;
320 break;
321 }
322 }
323
324 /* Solve for the resulting transform vector */
325 for (i = 0; i < 2; i++) {
326 if (u[i])
327 d.v[1 - i] = (t[i] * f - q[i]) / u[i];
328 else if (w[1])
329 d.v[1 - i] = (p[i] * f - v[i]) / w[i];
330 else
331 d.v[1 - i] = 0;
332 }
333 *new_pan_x = old_pan_x - floor(d.v[0] + 0.5);
334 *new_pan_y = old_pan_y - floor(d.v[1] + 0.5);
335 }
336 else {
337 *new_pan_x = screen_x - crtc_x;
338 *new_pan_y = screen_y - crtc_y;
339 }
340}
341
342static void
343xf86RandR13Pan(xf86CrtcPtr crtc, int x, int y)
344{
345 int newX, newY;
346 int width, height;
347 Bool panned = FALSE;
348
349 if (crtc->version < 2)
350 return;
351
352 if (!crtc->enabled ||
353 (crtc->panningTotalArea.x2 <= crtc->panningTotalArea.x1 &&
354 crtc->panningTotalArea.y2 <= crtc->panningTotalArea.y1))
355 return;
356
357 newX = crtc->x;
358 newY = crtc->y;
359 width = crtc->mode.HDisplay;
360 height = crtc->mode.VDisplay;
361
362 if ((crtc->panningTrackingArea.x2 <= crtc->panningTrackingArea.x1 ||
363 (x >= crtc->panningTrackingArea.x1 &&
364 x < crtc->panningTrackingArea.x2)) &&
365 (crtc->panningTrackingArea.y2 <= crtc->panningTrackingArea.y1 ||
366 (y >= crtc->panningTrackingArea.y1 &&
367 y < crtc->panningTrackingArea.y2))) {
368 struct pict_f_vector c;
369
370 /*
371 * Pre-clip the mouse position to the panning area so that we don't
372 * push the crtc outside. This doesn't deal with changes to the
373 * panning values, only mouse position changes.
374 */
375 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
376 if (x < crtc->panningTotalArea.x1)
377 x = crtc->panningTotalArea.x1;
378 if (x >= crtc->panningTotalArea.x2)
379 x = crtc->panningTotalArea.x2 - 1;
380 }
381 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
382 if (y < crtc->panningTotalArea.y1)
383 y = crtc->panningTotalArea.y1;
384 if (y >= crtc->panningTotalArea.y2)
385 y = crtc->panningTotalArea.y2 - 1;
386 }
387
388 c.v[0] = x;
389 c.v[1] = y;
390 c.v[2] = 1.0;
391 if (crtc->transform_in_use) {
392 pixman_f_transform_point(&crtc->f_framebuffer_to_crtc, &c);
393 }
394 else {
395 c.v[0] -= crtc->x;
396 c.v[1] -= crtc->y;
397 }
398
399 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
400 if (c.v[0] < crtc->panningBorder[0]) {
401 c.v[0] = crtc->panningBorder[0];
402 panned = TRUE;
403 }
404 if (c.v[0] >= width - crtc->panningBorder[2]) {
405 c.v[0] = width - crtc->panningBorder[2] - 1;
406 panned = TRUE;
407 }
408 }
409 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
410 if (c.v[1] < crtc->panningBorder[1]) {
411 c.v[1] = crtc->panningBorder[1];
412 panned = TRUE;
413 }
414 if (c.v[1] >= height - crtc->panningBorder[3]) {
415 c.v[1] = height - crtc->panningBorder[3] - 1;
416 panned = TRUE;
417 }
418 }
419 if (panned)
420 xf86ComputeCrtcPan(crtc->transform_in_use,
421 &crtc->f_framebuffer_to_crtc,
422 x, y, c.v[0], c.v[1], newX, newY, &newX, &newY);
423 }
424
425 /*
426 * Ensure that the crtc is within the panning region.
427 *
428 * XXX This computation only works when we do not have a transform
429 * in use.
430 */
431 if (!crtc->transform_in_use) {
432 /* Validate against [xy]1 after [xy]2, to be sure that results are > 0 for [xy]1 > 0 */
433 if (crtc->panningTotalArea.x2 > crtc->panningTotalArea.x1) {
434 if (newX > crtc->panningTotalArea.x2 - width)
435 newX = crtc->panningTotalArea.x2 - width;
436 if (newX < crtc->panningTotalArea.x1)
437 newX = crtc->panningTotalArea.x1;
438 }
439 if (crtc->panningTotalArea.y2 > crtc->panningTotalArea.y1) {
440 if (newY > crtc->panningTotalArea.y2 - height)
441 newY = crtc->panningTotalArea.y2 - height;
442 if (newY < crtc->panningTotalArea.y1)
443 newY = crtc->panningTotalArea.y1;
444 }
445 }
446 if (newX != crtc->x || newY != crtc->y)
447 xf86CrtcSetOrigin(crtc, newX, newY);
448}
449
450static Bool
451xf86RandR12GetInfo(ScreenPtr pScreen, Rotation * rotations)
452{
453 RRScreenSizePtr pSize;
454 ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
455 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
456 DisplayModePtr mode;
457 int refresh0 = 60;
458 int maxX = 0, maxY = 0;
459
460 *rotations = randrp->supported_rotations;
461
462 if (randrp->virtualX == -1 || randrp->virtualY == -1) {
463 randrp->virtualX = scrp->virtualX;
464 randrp->virtualY = scrp->virtualY;
465 }
466
467 /* Re-probe the outputs for new monitors or modes */
468 if (scrp->vtSema) {
469 xf86ProbeOutputModes(scrp, 0, 0);
470 xf86SetScrnInfoModes(scrp);
471 }
472
473 for (mode = scrp->modes;; mode = mode->next) {
474 int refresh = xf86RandR12ModeRefresh(mode);
475
476 if (randrp->maxX == 0 || randrp->maxY == 0) {
477 if (maxX < mode->HDisplay)
478 maxX = mode->HDisplay;
479 if (maxY < mode->VDisplay)
480 maxY = mode->VDisplay;
481 }
482 if (mode == scrp->modes)
483 refresh0 = refresh;
484 pSize = RRRegisterSize(pScreen,
485 mode->HDisplay, mode->VDisplay,
486 randrp->mmWidth, randrp->mmHeight);
487 if (!pSize)
488 return FALSE;
489 RRRegisterRate(pScreen, pSize, refresh);
490
491 if (xf86ModesEqual(mode, scrp->currentMode)) {
492 RRSetCurrentConfig(pScreen, randrp->rotation, refresh, pSize);
493 }
494 if (mode->next == scrp->modes)
495 break;
496 }
497
498 if (randrp->maxX == 0 || randrp->maxY == 0) {
499 randrp->maxX = maxX;
500 randrp->maxY = maxY;
501 }
502
503 return TRUE;
504}
505
506static Bool
507xf86RandR12SetMode(ScreenPtr pScreen,
508 DisplayModePtr mode,
509 Bool useVirtual, int mmWidth, int mmHeight)
510{
511 ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
512 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
513 int oldWidth = pScreen->width;
514 int oldHeight = pScreen->height;
515 int oldmmWidth = pScreen->mmWidth;
516 int oldmmHeight = pScreen->mmHeight;
517 WindowPtr pRoot = pScreen->root;
518 DisplayModePtr currentMode = NULL;
519 Bool ret = TRUE;
520
521 if (pRoot)
522 (*scrp->EnableDisableFBAccess) (scrp, FALSE);
523 if (useVirtual) {
524 scrp->virtualX = randrp->virtualX;
525 scrp->virtualY = randrp->virtualY;
526 }
527 else {
528 scrp->virtualX = mode->HDisplay;
529 scrp->virtualY = mode->VDisplay;
530 }
531
532 if (randrp->rotation & (RR_Rotate_90 | RR_Rotate_270)) {
533 /* If the screen is rotated 90 or 270 degrees, swap the sizes. */
534 pScreen->width = scrp->virtualY;
535 pScreen->height = scrp->virtualX;
536 pScreen->mmWidth = mmHeight;
537 pScreen->mmHeight = mmWidth;
538 }
539 else {
540 pScreen->width = scrp->virtualX;
541 pScreen->height = scrp->virtualY;
542 pScreen->mmWidth = mmWidth;
543 pScreen->mmHeight = mmHeight;
544 }
545 if (scrp->currentMode == mode) {
546 /* Save current mode */
547 currentMode = scrp->currentMode;
548 /* Reset, just so we ensure the drivers SwitchMode is called */
549 scrp->currentMode = NULL;
550 }
551 /*
552 * We know that if the driver failed to SwitchMode to the rotated
553 * version, then it should revert back to it's prior mode.
554 */
555 if (!xf86SwitchMode(pScreen, mode)) {
556 ret = FALSE;
557 scrp->virtualX = pScreen->width = oldWidth;
558 scrp->virtualY = pScreen->height = oldHeight;
559 pScreen->mmWidth = oldmmWidth;
560 pScreen->mmHeight = oldmmHeight;
561 scrp->currentMode = currentMode;
562 }
563
564 /*
565 * Make sure the layout is correct
566 */
567 xf86ReconfigureLayout();
568
569 /*
570 * Make sure the whole screen is visible
571 */
572 xf86SetViewport(pScreen, pScreen->width, pScreen->height);
573 xf86SetViewport(pScreen, 0, 0);
574 if (pRoot)
575 (*scrp->EnableDisableFBAccess) (scrp, TRUE);
576 return ret;
577}
578
579Bool
580xf86RandR12SetConfig(ScreenPtr pScreen,
581 Rotation rotation, int rate, RRScreenSizePtr pSize)
582{
583 ScrnInfoPtr scrp = xf86ScreenToScrn(pScreen);
584 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
585 DisplayModePtr mode;
586 int pos[MAXDEVICES][2];
587 Bool useVirtual = FALSE;
588 int maxX = 0, maxY = 0;
589 Rotation oldRotation = randrp->rotation;
590 DeviceIntPtr dev;
591 Bool view_adjusted = FALSE;
592
593 randrp->rotation = rotation;
594
595 if (randrp->virtualX == -1 || randrp->virtualY == -1) {
596 randrp->virtualX = scrp->virtualX;
597 randrp->virtualY = scrp->virtualY;
598 }
599
600 for (dev = inputInfo.devices; dev; dev = dev->next) {
601 if (!IsMaster(dev) && !IsFloating(dev))
602 continue;
603
604 miPointerGetPosition(dev, &pos[dev->id][0], &pos[dev->id][1]);
605 }
606
607 for (mode = scrp->modes;; mode = mode->next) {
608 if (randrp->maxX == 0 || randrp->maxY == 0) {
609 if (maxX < mode->HDisplay)
610 maxX = mode->HDisplay;
611 if (maxY < mode->VDisplay)
612 maxY = mode->VDisplay;
613 }
614 if (mode->HDisplay == pSize->width &&
615 mode->VDisplay == pSize->height &&
616 (rate == 0 || xf86RandR12ModeRefresh(mode) == rate))
617 break;
618 if (mode->next == scrp->modes) {
619 if (pSize->width == randrp->virtualX &&
620 pSize->height == randrp->virtualY) {
621 mode = scrp->modes;
622 useVirtual = TRUE;
623 break;
624 }
625 if (randrp->maxX == 0 || randrp->maxY == 0) {
626 randrp->maxX = maxX;
627 randrp->maxY = maxY;
628 }
629 return FALSE;
630 }
631 }
632
633 if (randrp->maxX == 0 || randrp->maxY == 0) {
634 randrp->maxX = maxX;
635 randrp->maxY = maxY;
636 }
637
638 if (!xf86RandR12SetMode(pScreen, mode, useVirtual, pSize->mmWidth,
639 pSize->mmHeight)) {
640 randrp->rotation = oldRotation;
641 return FALSE;
642 }
643
644 /*
645 * Move the cursor back where it belongs; SwitchMode repositions it
646 * FIXME: duplicated code, see modes/xf86RandR12.c
647 */
648 for (dev = inputInfo.devices; dev; dev = dev->next) {
649 if (!IsMaster(dev) && !IsFloating(dev))
650 continue;
651
652 if (pScreen == miPointerGetScreen(dev)) {
653 int px = pos[dev->id][0];
654 int py = pos[dev->id][1];
655
656 px = (px >= pScreen->width ? (pScreen->width - 1) : px);
657 py = (py >= pScreen->height ? (pScreen->height - 1) : py);
658
659 /* Setting the viewpoint makes only sense on one device */
660 if (!view_adjusted && IsMaster(dev)) {
661 xf86SetViewport(pScreen, px, py);
662 view_adjusted = TRUE;
663 }
664
665 (*pScreen->SetCursorPosition) (dev, pScreen, px, py, FALSE);
666 }
667 }
668
669 return TRUE;
670}
671
672#define PANNING_ENABLED(crtc) \
673 ((crtc)->panningTotalArea.x2 > (crtc)->panningTotalArea.x1 || \
674 (crtc)->panningTotalArea.y2 > (crtc)->panningTotalArea.y1)
675
676static Bool
677xf86RandR12ScreenSetSize(ScreenPtr pScreen,
678 CARD16 width,
679 CARD16 height, CARD32 mmWidth, CARD32 mmHeight)
680{
681 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
682 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
683 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
684 WindowPtr pRoot = pScreen->root;
685 PixmapPtr pScrnPix;
686 Bool ret = FALSE;
687 Bool panning = FALSE;
688 int c;
689
690 if (xf86RandR12Key) {
691 if (randrp->virtualX == -1 || randrp->virtualY == -1) {
692 randrp->virtualX = pScrn->virtualX;
693 randrp->virtualY = pScrn->virtualY;
694 }
695 }
696 if (pRoot && pScrn->vtSema)
697 (*pScrn->EnableDisableFBAccess) (pScrn, FALSE);
698
699 /* Let the driver update virtualX and virtualY */
700 if (!(*config->funcs->resize) (pScrn, width, height))
701 goto finish;
702
703 ret = TRUE;
704 /* Update panning information */
705 for (c = 0; c < config->num_crtc; c++) {
706 xf86CrtcPtr crtc = config->crtc[c];
707
708 if (PANNING_ENABLED (crtc)) {
709 if (crtc->panningTotalArea.x2 > crtc->panningTrackingArea.x1)
710 crtc->panningTotalArea.x2 += width - pScreen->width;
711 if (crtc->panningTotalArea.y2 > crtc->panningTrackingArea.y1)
712 crtc->panningTotalArea.y2 += height - pScreen->height;
713 if (crtc->panningTrackingArea.x2 > crtc->panningTrackingArea.x1)
714 crtc->panningTrackingArea.x2 += width - pScreen->width;
715 if (crtc->panningTrackingArea.y2 > crtc->panningTrackingArea.y1)
716 crtc->panningTrackingArea.y2 += height - pScreen->height;
717 xf86RandR13VerifyPanningArea(crtc, width, height);
718 xf86RandR13Pan(crtc, randrp->pointerX, randrp->pointerY);
719 panning = TRUE;
720 }
721 }
722
723 pScrnPix = (*pScreen->GetScreenPixmap) (pScreen);
724 pScreen->width = pScrnPix->drawable.width = width;
725 pScreen->height = pScrnPix->drawable.height = height;
726 randrp->mmWidth = pScreen->mmWidth = mmWidth;
727 randrp->mmHeight = pScreen->mmHeight = mmHeight;
728
729 xf86SetViewport(pScreen, pScreen->width - 1, pScreen->height - 1);
730 xf86SetViewport(pScreen, 0, 0);
731
732 finish:
733 update_desktop_dimensions();
734
735 if (pRoot && pScrn->vtSema)
736 (*pScrn->EnableDisableFBAccess) (pScrn, TRUE);
737#if RANDR_12_INTERFACE
738 if (xf86RandR12Key && pScreen->root && ret)
739 RRScreenSizeNotify(pScreen);
740#endif
741 return ret;
742}
743
744Rotation
745xf86RandR12GetRotation(ScreenPtr pScreen)
746{
747 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
748
749 return randrp->rotation;
750}
751
752Bool
753xf86RandR12CreateScreenResources(ScreenPtr pScreen)
754{
755 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
756 xf86CrtcConfigPtr config;
757 XF86RandRInfoPtr randrp;
758 int c;
759 int width, height;
760 int mmWidth, mmHeight;
761
762#ifdef PANORAMIX
763 /* XXX disable RandR when using Xinerama */
764 if (!noPanoramiXExtension)
765 return TRUE;
766#endif
767
768 config = XF86_CRTC_CONFIG_PTR(pScrn);
769 randrp = XF86RANDRINFO(pScreen);
770 /*
771 * Compute size of screen
772 */
773 width = 0;
774 height = 0;
775 for (c = 0; c < config->num_crtc; c++) {
776 xf86CrtcPtr crtc = config->crtc[c];
777 int crtc_width = crtc->x + xf86ModeWidth(&crtc->mode, crtc->rotation);
778 int crtc_height = crtc->y + xf86ModeHeight(&crtc->mode, crtc->rotation);
779
780 if (crtc->enabled) {
781 if (crtc_width > width)
782 width = crtc_width;
783 if (crtc_height > height)
784 height = crtc_height;
785 if (crtc->panningTotalArea.x2 > width)
786 width = crtc->panningTotalArea.x2;
787 if (crtc->panningTotalArea.y2 > height)
788 height = crtc->panningTotalArea.y2;
789 }
790 }
791
792 if (width && height) {
793 /*
794 * Compute physical size of screen
795 */
796 if (monitorResolution) {
797 mmWidth = width * 25.4 / monitorResolution;
798 mmHeight = height * 25.4 / monitorResolution;
799 }
800 else {
801 xf86OutputPtr output = xf86CompatOutput(pScrn);
802
803 if (output &&
804 output->conf_monitor &&
805 (output->conf_monitor->mon_width > 0 &&
806 output->conf_monitor->mon_height > 0)) {
807 /*
808 * Prefer user configured DisplaySize
809 */
810 mmWidth = output->conf_monitor->mon_width;
811 mmHeight = output->conf_monitor->mon_height;
812 }
813 else {
814 /*
815 * Otherwise, just set the screen to DEFAULT_DPI
816 */
817 mmWidth = width * 25.4 / DEFAULT_DPI;
818 mmHeight = height * 25.4 / DEFAULT_DPI;
819 }
820 }
821 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
822 "Setting screen physical size to %d x %d\n",
823 mmWidth, mmHeight);
824 /*
825 * This is the initial setting of the screen size.
826 * We have to pre-set it here, otherwise panning would be adapted
827 * to the new screen size.
828 */
829 pScreen->width = width;
830 pScreen->height = height;
831 xf86RandR12ScreenSetSize(pScreen, width, height, mmWidth, mmHeight);
832 }
833
834 if (xf86RandR12Key == NULL)
835 return TRUE;
836
837 if (randrp->virtualX == -1 || randrp->virtualY == -1) {
838 randrp->virtualX = pScrn->virtualX;
839 randrp->virtualY = pScrn->virtualY;
840 }
841 xf86CrtcSetScreenSubpixelOrder(pScreen);
842#if RANDR_12_INTERFACE
843 if (xf86RandR12CreateScreenResources12(pScreen))
844 return TRUE;
845#endif
846 return TRUE;
847}
848
849Bool
850xf86RandR12Init(ScreenPtr pScreen)
851{
852 rrScrPrivPtr rp;
853 XF86RandRInfoPtr randrp;
854
855#ifdef PANORAMIX
856 /* XXX disable RandR when using Xinerama */
857 if (!noPanoramiXExtension) {
858 if (xf86NumScreens == 1)
859 noPanoramiXExtension = TRUE;
860 else
861 return TRUE;
862 }
863#endif
864
865 if (xf86RandR12Generation != serverGeneration)
866 xf86RandR12Generation = serverGeneration;
867
868 xf86RandR12Key = &xf86RandR12KeyRec;
869 if (!dixRegisterPrivateKey(&xf86RandR12KeyRec, PRIVATE_SCREEN, 0))
870 return FALSE;
871
872 randrp = malloc(sizeof(XF86RandRInfoRec));
873 if (!randrp)
874 return FALSE;
875
876 if (!RRScreenInit(pScreen)) {
877 free(randrp);
878 return FALSE;
879 }
880 rp = rrGetScrPriv(pScreen);
881 rp->rrGetInfo = xf86RandR12GetInfo;
882 rp->rrSetConfig = xf86RandR12SetConfig;
883
884 randrp->virtualX = -1;
885 randrp->virtualY = -1;
886 randrp->mmWidth = pScreen->mmWidth;
887 randrp->mmHeight = pScreen->mmHeight;
888
889 randrp->rotation = RR_Rotate_0; /* initial rotated mode */
890
891 randrp->supported_rotations = RR_Rotate_0;
892
893 randrp->maxX = randrp->maxY = 0;
894
895 dixSetPrivate(&pScreen->devPrivates, xf86RandR12Key, randrp);
896
897#if RANDR_12_INTERFACE
898 if (!xf86RandR12Init12(pScreen))
899 return FALSE;
900#endif
901 return TRUE;
902}
903
904void
905xf86RandR12CloseScreen(ScreenPtr pScreen)
906{
907 XF86RandRInfoPtr randrp;
908
909 if (xf86RandR12Key == NULL)
910 return;
911
912 randrp = XF86RANDRINFO(pScreen);
913#if RANDR_12_INTERFACE
914 xf86ScreenToScrn(pScreen)->EnterVT = randrp->orig_EnterVT;
915 pScreen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder;
916#endif
917
918 free(randrp);
919}
920
921void
922xf86RandR12SetRotations(ScreenPtr pScreen, Rotation rotations)
923{
924 XF86RandRInfoPtr randrp;
925
926#if RANDR_12_INTERFACE
927 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
928 int c;
929 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
930#endif
931
932 if (xf86RandR12Key == NULL)
933 return;
934
935 randrp = XF86RANDRINFO(pScreen);
936#if RANDR_12_INTERFACE
937 for (c = 0; c < config->num_crtc; c++) {
938 xf86CrtcPtr crtc = config->crtc[c];
939
940 RRCrtcSetRotations(crtc->randr_crtc, rotations);
941 }
942#endif
943 randrp->supported_rotations = rotations;
944}
945
946void
947xf86RandR12SetTransformSupport(ScreenPtr pScreen, Bool transforms)
948{
949 XF86RandRInfoPtr randrp;
950
951#if RANDR_13_INTERFACE
952 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
953 int c;
954 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
955#endif
956
957 if (xf86RandR12Key == NULL)
958 return;
959
960 randrp = XF86RANDRINFO(pScreen);
961#if RANDR_13_INTERFACE
962 for (c = 0; c < config->num_crtc; c++) {
963 xf86CrtcPtr crtc = config->crtc[c];
964
965 RRCrtcSetTransformSupport(crtc->randr_crtc, transforms);
966 }
967#endif
968}
969
970void
971xf86RandR12GetOriginalVirtualSize(ScrnInfoPtr pScrn, int *x, int *y)
972{
973 ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
974
975 if (xf86RandR12Generation != serverGeneration ||
976 XF86RANDRINFO(pScreen)->virtualX == -1) {
977 *x = pScrn->virtualX;
978 *y = pScrn->virtualY;
979 }
980 else {
981 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
982
983 *x = randrp->virtualX;
984 *y = randrp->virtualY;
985 }
986}
987
988#if RANDR_12_INTERFACE
989
990#define FLAG_BITS (RR_HSyncPositive | \
991 RR_HSyncNegative | \
992 RR_VSyncPositive | \
993 RR_VSyncNegative | \
994 RR_Interlace | \
995 RR_DoubleScan | \
996 RR_CSync | \
997 RR_CSyncPositive | \
998 RR_CSyncNegative | \
999 RR_HSkewPresent | \
1000 RR_BCast | \
1001 RR_PixelMultiplex | \
1002 RR_DoubleClock | \
1003 RR_ClockDivideBy2)
1004
1005static Bool
1006xf86RandRModeMatches(RRModePtr randr_mode, DisplayModePtr mode)
1007{
1008#if 0
1009 if (match_name) {
1010 /* check for same name */
1011 int len = strlen(mode->name);
1012
1013 if (randr_mode->mode.nameLength != len)
1014 return FALSE;
1015 if (memcmp(randr_mode->name, mode->name, len) != 0)
1016 return FALSE;
1017 }
1018#endif
1019
1020 /* check for same timings */
1021 if (randr_mode->mode.dotClock / 1000 != mode->Clock)
1022 return FALSE;
1023 if (randr_mode->mode.width != mode->HDisplay)
1024 return FALSE;
1025 if (randr_mode->mode.hSyncStart != mode->HSyncStart)
1026 return FALSE;
1027 if (randr_mode->mode.hSyncEnd != mode->HSyncEnd)
1028 return FALSE;
1029 if (randr_mode->mode.hTotal != mode->HTotal)
1030 return FALSE;
1031 if (randr_mode->mode.hSkew != mode->HSkew)
1032 return FALSE;
1033 if (randr_mode->mode.height != mode->VDisplay)
1034 return FALSE;
1035 if (randr_mode->mode.vSyncStart != mode->VSyncStart)
1036 return FALSE;
1037 if (randr_mode->mode.vSyncEnd != mode->VSyncEnd)
1038 return FALSE;
1039 if (randr_mode->mode.vTotal != mode->VTotal)
1040 return FALSE;
1041
1042 /* check for same flags (using only the XF86 valid flag bits) */
1043 if ((randr_mode->mode.modeFlags & FLAG_BITS) != (mode->Flags & FLAG_BITS))
1044 return FALSE;
1045
1046 /* everything matches */
1047 return TRUE;
1048}
1049
1050static Bool
1051xf86RandR12CrtcNotify(RRCrtcPtr randr_crtc)
1052{
1053 ScreenPtr pScreen = randr_crtc->pScreen;
1054 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1055 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1056 RRModePtr randr_mode = NULL;
1057 int x;
1058 int y;
1059 Rotation rotation;
1060 int numOutputs;
1061 RROutputPtr *randr_outputs;
1062 RROutputPtr randr_output;
1063 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1064 xf86OutputPtr output;
1065 int i, j;
1066 DisplayModePtr mode = &crtc->mode;
1067 Bool ret;
1068
1069 randr_outputs = malloc(config->num_output * sizeof(RROutputPtr));
1070 if (!randr_outputs)
1071 return FALSE;
1072 x = crtc->x;
1073 y = crtc->y;
1074 rotation = crtc->rotation;
1075 numOutputs = 0;
1076 randr_mode = NULL;
1077 for (i = 0; i < config->num_output; i++) {
1078 output = config->output[i];
1079 if (output->crtc == crtc) {
1080 randr_output = output->randr_output;
1081 randr_outputs[numOutputs++] = randr_output;
1082 /*
1083 * We make copies of modes, so pointer equality
1084 * isn't sufficient
1085 */
1086 for (j = 0; j < randr_output->numModes + randr_output->numUserModes;
1087 j++) {
1088 RRModePtr m =
1089 (j <
1090 randr_output->numModes ? randr_output->
1091 modes[j] : randr_output->userModes[j -
1092 randr_output->
1093 numModes]);
1094
1095 if (xf86RandRModeMatches(m, mode)) {
1096 randr_mode = m;
1097 break;
1098 }
1099 }
1100 }
1101 }
1102 ret = RRCrtcNotify(randr_crtc, randr_mode, x, y,
1103 rotation,
1104 crtc->transformPresent ? &crtc->transform : NULL,
1105 numOutputs, randr_outputs);
1106 free(randr_outputs);
1107 return ret;
1108}
1109
1110/*
1111 * Convert a RandR mode to a DisplayMode
1112 */
1113static void
1114xf86RandRModeConvert(ScrnInfoPtr scrn,
1115 RRModePtr randr_mode, DisplayModePtr mode)
1116{
1117 memset(mode, 0, sizeof(DisplayModeRec));
1118 mode->status = MODE_OK;
1119
1120 mode->Clock = randr_mode->mode.dotClock / 1000;
1121
1122 mode->HDisplay = randr_mode->mode.width;
1123 mode->HSyncStart = randr_mode->mode.hSyncStart;
1124 mode->HSyncEnd = randr_mode->mode.hSyncEnd;
1125 mode->HTotal = randr_mode->mode.hTotal;
1126 mode->HSkew = randr_mode->mode.hSkew;
1127
1128 mode->VDisplay = randr_mode->mode.height;
1129 mode->VSyncStart = randr_mode->mode.vSyncStart;
1130 mode->VSyncEnd = randr_mode->mode.vSyncEnd;
1131 mode->VTotal = randr_mode->mode.vTotal;
1132 mode->VScan = 0;
1133
1134 mode->Flags = randr_mode->mode.modeFlags & FLAG_BITS;
1135
1136 xf86SetModeCrtc(mode, scrn->adjustFlags);
1137}
1138
1139static Bool
1140xf86RandR12CrtcSet(ScreenPtr pScreen,
1141 RRCrtcPtr randr_crtc,
1142 RRModePtr randr_mode,
1143 int x,
1144 int y,
1145 Rotation rotation,
1146 int num_randr_outputs, RROutputPtr * randr_outputs)
1147{
1148 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1149 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1150 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1151 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1152 RRTransformPtr transform;
1153 Bool changed = FALSE;
1154 int o, ro;
1155 xf86CrtcPtr *save_crtcs;
1156 Bool save_enabled = crtc->enabled;
1157
1158 if (!crtc->scrn->vtSema)
1159 return FALSE;
1160
1161 save_crtcs = malloc(config->num_output * sizeof(xf86CrtcPtr));
1162 if ((randr_mode != NULL) != crtc->enabled)
1163 changed = TRUE;
1164 else if (randr_mode && !xf86RandRModeMatches(randr_mode, &crtc->mode))
1165 changed = TRUE;
1166
1167 if (rotation != crtc->rotation)
1168 changed = TRUE;
1169
1170 if (crtc->current_scanout != randr_crtc->scanout_pixmap)
1171 changed = TRUE;
1172
1173 transform = RRCrtcGetTransform(randr_crtc);
1174 if ((transform != NULL) != crtc->transformPresent)
1175 changed = TRUE;
1176 else if (transform &&
1177 memcmp(&transform->transform, &crtc->transform.transform,
1178 sizeof(transform->transform)) != 0)
1179 changed = TRUE;
1180
1181 if (x != crtc->x || y != crtc->y)
1182 changed = TRUE;
1183 for (o = 0; o < config->num_output; o++) {
1184 xf86OutputPtr output = config->output[o];
1185 xf86CrtcPtr new_crtc;
1186
1187 save_crtcs[o] = output->crtc;
1188
1189 if (output->crtc == crtc)
1190 new_crtc = NULL;
1191 else
1192 new_crtc = output->crtc;
1193 for (ro = 0; ro < num_randr_outputs; ro++)
1194 if (output->randr_output == randr_outputs[ro]) {
1195 new_crtc = crtc;
1196 break;
1197 }
1198 if (new_crtc != output->crtc) {
1199 changed = TRUE;
1200 output->crtc = new_crtc;
1201 }
1202 }
1203 for (ro = 0; ro < num_randr_outputs; ro++)
1204 if (randr_outputs[ro]->pendingProperties)
1205 changed = TRUE;
1206
1207 /* XXX need device-independent mode setting code through an API */
1208 if (changed) {
1209 crtc->enabled = randr_mode != NULL;
1210
1211 if (randr_mode) {
1212 DisplayModeRec mode;
1213 RRTransformPtr transform = RRCrtcGetTransform(randr_crtc);
1214
1215 xf86RandRModeConvert(pScrn, randr_mode, &mode);
1216 if (!xf86CrtcSetModeTransform
1217 (crtc, &mode, rotation, transform, x, y)) {
1218 crtc->enabled = save_enabled;
1219 for (o = 0; o < config->num_output; o++) {
1220 xf86OutputPtr output = config->output[o];
1221
1222 output->crtc = save_crtcs[o];
1223 }
1224 free(save_crtcs);
1225 return FALSE;
1226 }
1227 xf86RandR13VerifyPanningArea(crtc, pScreen->width, pScreen->height);
1228 xf86RandR13Pan(crtc, randrp->pointerX, randrp->pointerY);
1229 randrp->panning = PANNING_ENABLED (crtc);
1230 /*
1231 * Save the last successful setting for EnterVT
1232 */
1233 xf86SaveModeContents(&crtc->desiredMode, &mode);
1234 crtc->desiredRotation = rotation;
1235 crtc->current_scanout = randr_crtc->scanout_pixmap;
1236 if (transform) {
1237 crtc->desiredTransform = *transform;
1238 crtc->desiredTransformPresent = TRUE;
1239 }
1240 else
1241 crtc->desiredTransformPresent = FALSE;
1242
1243 crtc->desiredX = x;
1244 crtc->desiredY = y;
1245 }
1246 xf86DisableUnusedFunctions(pScrn);
1247 }
1248 free(save_crtcs);
1249 return xf86RandR12CrtcNotify(randr_crtc);
1250}
1251
1252static Bool
1253xf86RandR12CrtcSetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc)
1254{
1255 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1256
1257 if (crtc->funcs->gamma_set == NULL)
1258 return FALSE;
1259
1260 if (!crtc->scrn->vtSema)
1261 return TRUE;
1262
1263 /* Realloc local gamma if needed. */
1264 if (randr_crtc->gammaSize != crtc->gamma_size) {
1265 CARD16 *tmp_ptr;
1266
1267 tmp_ptr =
1268 realloc(crtc->gamma_red, 3 * crtc->gamma_size * sizeof(CARD16));
1269 if (!tmp_ptr)
1270 return FALSE;
1271 crtc->gamma_red = tmp_ptr;
1272 crtc->gamma_green = crtc->gamma_red + crtc->gamma_size;
1273 crtc->gamma_blue = crtc->gamma_green + crtc->gamma_size;
1274 }
1275
1276 crtc->gamma_size = randr_crtc->gammaSize;
1277 memcpy(crtc->gamma_red, randr_crtc->gammaRed,
1278 crtc->gamma_size * sizeof(CARD16));
1279 memcpy(crtc->gamma_green, randr_crtc->gammaGreen,
1280 crtc->gamma_size * sizeof(CARD16));
1281 memcpy(crtc->gamma_blue, randr_crtc->gammaBlue,
1282 crtc->gamma_size * sizeof(CARD16));
1283
1284 /* Only set it when the crtc is actually running.
1285 * Otherwise it will be set when it's activated.
1286 */
1287 if (crtc->active)
1288 crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
1289 crtc->gamma_blue, crtc->gamma_size);
1290
1291 return TRUE;
1292}
1293
1294static Bool
1295xf86RandR12CrtcGetGamma(ScreenPtr pScreen, RRCrtcPtr randr_crtc)
1296{
1297 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1298
1299 if (!crtc->gamma_size)
1300 return FALSE;
1301
1302 if (!crtc->gamma_red || !crtc->gamma_green || !crtc->gamma_blue)
1303 return FALSE;
1304
1305 /* Realloc randr gamma if needed. */
1306 if (randr_crtc->gammaSize != crtc->gamma_size) {
1307 CARD16 *tmp_ptr;
1308
1309 tmp_ptr =
1310 realloc(randr_crtc->gammaRed,
1311 3 * crtc->gamma_size * sizeof(CARD16));
1312 if (!tmp_ptr)
1313 return FALSE;
1314 randr_crtc->gammaRed = tmp_ptr;
1315 randr_crtc->gammaGreen = randr_crtc->gammaRed + crtc->gamma_size;
1316 randr_crtc->gammaBlue = randr_crtc->gammaGreen + crtc->gamma_size;
1317 }
1318 randr_crtc->gammaSize = crtc->gamma_size;
1319 memcpy(randr_crtc->gammaRed, crtc->gamma_red,
1320 crtc->gamma_size * sizeof(CARD16));
1321 memcpy(randr_crtc->gammaGreen, crtc->gamma_green,
1322 crtc->gamma_size * sizeof(CARD16));
1323 memcpy(randr_crtc->gammaBlue, crtc->gamma_blue,
1324 crtc->gamma_size * sizeof(CARD16));
1325
1326 return TRUE;
1327}
1328
1329static Bool
1330xf86RandR12OutputSetProperty(ScreenPtr pScreen,
1331 RROutputPtr randr_output,
1332 Atom property, RRPropertyValuePtr value)
1333{
1334 xf86OutputPtr output = randr_output->devPrivate;
1335
1336 /* If we don't have any property handler, then we don't care what the
1337 * user is setting properties to.
1338 */
1339 if (output->funcs->set_property == NULL)
1340 return TRUE;
1341
1342 /*
1343 * This function gets called even when vtSema is FALSE, as
1344 * drivers will need to remember the correct value to apply
1345 * when the VT switch occurs
1346 */
1347 return output->funcs->set_property(output, property, value);
1348}
1349
1350static Bool
1351xf86RandR13OutputGetProperty(ScreenPtr pScreen,
1352 RROutputPtr randr_output, Atom property)
1353{
1354 xf86OutputPtr output = randr_output->devPrivate;
1355
1356 if (output->funcs->get_property == NULL)
1357 return TRUE;
1358
1359 /* Should be safe even w/o vtSema */
1360 return output->funcs->get_property(output, property);
1361}
1362
1363static Bool
1364xf86RandR12OutputValidateMode(ScreenPtr pScreen,
1365 RROutputPtr randr_output, RRModePtr randr_mode)
1366{
1367 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1368 xf86OutputPtr output = randr_output->devPrivate;
1369 DisplayModeRec mode;
1370
1371 xf86RandRModeConvert(pScrn, randr_mode, &mode);
1372 /*
1373 * This function may be called when vtSema is FALSE, so
1374 * the underlying function must either avoid touching the hardware
1375 * or return FALSE when vtSema is FALSE
1376 */
1377 if (output->funcs->mode_valid(output, &mode) != MODE_OK)
1378 return FALSE;
1379 return TRUE;
1380}
1381
1382static void
1383xf86RandR12ModeDestroy(ScreenPtr pScreen, RRModePtr randr_mode)
1384{
1385}
1386
1387/**
1388 * Given a list of xf86 modes and a RandR Output object, construct
1389 * RandR modes and assign them to the output
1390 */
1391static Bool
1392xf86RROutputSetModes(RROutputPtr randr_output, DisplayModePtr modes)
1393{
1394 DisplayModePtr mode;
1395 RRModePtr *rrmodes = NULL;
1396 int nmode = 0;
1397 int npreferred = 0;
1398 Bool ret = TRUE;
1399 int pref;
1400
1401 for (mode = modes; mode; mode = mode->next)
1402 nmode++;
1403
1404 if (nmode) {
1405 rrmodes = malloc(nmode * sizeof(RRModePtr));
1406
1407 if (!rrmodes)
1408 return FALSE;
1409 nmode = 0;
1410
1411 for (pref = 1; pref >= 0; pref--) {
1412 for (mode = modes; mode; mode = mode->next) {
1413 if ((pref != 0) == ((mode->type & M_T_PREFERRED) != 0)) {
1414 xRRModeInfo modeInfo;
1415 RRModePtr rrmode;
1416
1417 modeInfo.nameLength = strlen(mode->name);
1418 modeInfo.width = mode->HDisplay;
1419 modeInfo.dotClock = mode->Clock * 1000;
1420 modeInfo.hSyncStart = mode->HSyncStart;
1421 modeInfo.hSyncEnd = mode->HSyncEnd;
1422 modeInfo.hTotal = mode->HTotal;
1423 modeInfo.hSkew = mode->HSkew;
1424
1425 modeInfo.height = mode->VDisplay;
1426 modeInfo.vSyncStart = mode->VSyncStart;
1427 modeInfo.vSyncEnd = mode->VSyncEnd;
1428 modeInfo.vTotal = mode->VTotal;
1429 modeInfo.modeFlags = mode->Flags;
1430
1431 rrmode = RRModeGet(&modeInfo, mode->name);
1432 if (rrmode) {
1433 rrmodes[nmode++] = rrmode;
1434 npreferred += pref;
1435 }
1436 }
1437 }
1438 }
1439 }
1440
1441 ret = RROutputSetModes(randr_output, rrmodes, nmode, npreferred);
1442 free(rrmodes);
1443 return ret;
1444}
1445
1446/*
1447 * Mirror the current mode configuration to RandR
1448 */
1449static Bool
1450xf86RandR12SetInfo12(ScreenPtr pScreen)
1451{
1452 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1453 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1454 RROutputPtr *clones;
1455 RRCrtcPtr *crtcs;
1456 int ncrtc;
1457 int o, c, l;
1458 RRCrtcPtr randr_crtc;
1459 int nclone;
1460
1461 clones = malloc(config->num_output * sizeof(RROutputPtr));
1462 crtcs = malloc(config->num_crtc * sizeof(RRCrtcPtr));
1463 for (o = 0; o < config->num_output; o++) {
1464 xf86OutputPtr output = config->output[o];
1465
1466 ncrtc = 0;
1467 for (c = 0; c < config->num_crtc; c++)
1468 if (output->possible_crtcs & (1 << c))
1469 crtcs[ncrtc++] = config->crtc[c]->randr_crtc;
1470
1471 if (output->crtc)
1472 randr_crtc = output->crtc->randr_crtc;
1473 else
1474 randr_crtc = NULL;
1475
1476 if (!RROutputSetCrtcs(output->randr_output, crtcs, ncrtc)) {
1477 free(crtcs);
1478 free(clones);
1479 return FALSE;
1480 }
1481
1482 RROutputSetPhysicalSize(output->randr_output,
1483 output->mm_width, output->mm_height);
1484 xf86RROutputSetModes(output->randr_output, output->probed_modes);
1485
1486 switch (output->status) {
1487 case XF86OutputStatusConnected:
1488 RROutputSetConnection(output->randr_output, RR_Connected);
1489 break;
1490 case XF86OutputStatusDisconnected:
1491 RROutputSetConnection(output->randr_output, RR_Disconnected);
1492 break;
1493 case XF86OutputStatusUnknown:
1494 RROutputSetConnection(output->randr_output, RR_UnknownConnection);
1495 break;
1496 }
1497
1498 RROutputSetSubpixelOrder(output->randr_output, output->subpixel_order);
1499
1500 /*
1501 * Valid clones
1502 */
1503 nclone = 0;
1504 for (l = 0; l < config->num_output; l++) {
1505 xf86OutputPtr clone = config->output[l];
1506
1507 if (l != o && (output->possible_clones & (1 << l)))
1508 clones[nclone++] = clone->randr_output;
1509 }
1510 if (!RROutputSetClones(output->randr_output, clones, nclone)) {
1511 free(crtcs);
1512 free(clones);
1513 return FALSE;
1514 }
1515 }
1516 free(crtcs);
1517 free(clones);
1518 return TRUE;
1519}
1520
1521/*
1522 * Query the hardware for the current state, then mirror
1523 * that to RandR
1524 */
1525static Bool
1526xf86RandR12GetInfo12(ScreenPtr pScreen, Rotation * rotations)
1527{
1528 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1529
1530 if (!pScrn->vtSema)
1531 return TRUE;
1532 xf86ProbeOutputModes(pScrn, 0, 0);
1533 xf86SetScrnInfoModes(pScrn);
1534 return xf86RandR12SetInfo12(pScreen);
1535}
1536
1537static Bool
1538xf86RandR12CreateObjects12(ScreenPtr pScreen)
1539{
1540 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1541 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1542 int c;
1543 int o;
1544
1545 if (!RRInit())
1546 return FALSE;
1547
1548 /*
1549 * Configure crtcs
1550 */
1551 for (c = 0; c < config->num_crtc; c++) {
1552 xf86CrtcPtr crtc = config->crtc[c];
1553
1554 crtc->randr_crtc = RRCrtcCreate(pScreen, crtc);
1555 RRCrtcGammaSetSize(crtc->randr_crtc, 256);
1556 }
1557 /*
1558 * Configure outputs
1559 */
1560 for (o = 0; o < config->num_output; o++) {
1561 xf86OutputPtr output = config->output[o];
1562
1563 output->randr_output = RROutputCreate(pScreen, output->name,
1564 strlen(output->name), output);
1565
1566 if (output->funcs->create_resources != NULL)
1567 output->funcs->create_resources(output);
1568 RRPostPendingProperties(output->randr_output);
1569 }
1570
1571 if (config->name) {
1572 config->randr_provider = RRProviderCreate(pScreen, config->name,
1573 strlen(config->name));
1574
1575 RRProviderSetCapabilities(config->randr_provider, pScrn->capabilities);
1576 }
1577
1578 return TRUE;
1579}
1580
1581static Bool
1582xf86RandR12CreateScreenResources12(ScreenPtr pScreen)
1583{
1584 int c;
1585 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1586 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1587
1588 if (xf86RandR12Key == NULL)
1589 return TRUE;
1590
1591 for (c = 0; c < config->num_crtc; c++)
1592 xf86RandR12CrtcNotify(config->crtc[c]->randr_crtc);
1593
1594 RRScreenSetSizeRange(pScreen, config->minWidth, config->minHeight,
1595 config->maxWidth, config->maxHeight);
1596 return TRUE;
1597}
1598
1599/*
1600 * Something happened within the screen configuration due
1601 * to DGA, VidMode or hot key. Tell RandR
1602 */
1603
1604void
1605xf86RandR12TellChanged(ScreenPtr pScreen)
1606{
1607 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1608 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1609 int c;
1610
1611 if (xf86RandR12Key == NULL)
1612 return;
1613
1614 xf86RandR12SetInfo12(pScreen);
1615 for (c = 0; c < config->num_crtc; c++)
1616 xf86RandR12CrtcNotify(config->crtc[c]->randr_crtc);
1617
1618 RRTellChanged(pScreen);
1619}
1620
1621static void
1622xf86RandR12PointerMoved(ScrnInfoPtr pScrn, int x, int y)
1623{
1624 ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1625 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1626 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1627 int c;
1628
1629 randrp->pointerX = x;
1630 randrp->pointerY = y;
1631 for (c = 0; c < config->num_crtc; c++)
1632 xf86RandR13Pan(config->crtc[c], x, y);
1633}
1634
1635static Bool
1636xf86RandR13GetPanning(ScreenPtr pScreen,
1637 RRCrtcPtr randr_crtc,
1638 BoxPtr totalArea, BoxPtr trackingArea, INT16 *border)
1639{
1640 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1641
1642 if (crtc->version < 2)
1643 return FALSE;
1644 if (totalArea)
1645 memcpy(totalArea, &crtc->panningTotalArea, sizeof(BoxRec));
1646 if (trackingArea)
1647 memcpy(trackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
1648 if (border)
1649 memcpy(border, crtc->panningBorder, 4 * sizeof(INT16));
1650
1651 return TRUE;
1652}
1653
1654static Bool
1655xf86RandR13SetPanning(ScreenPtr pScreen,
1656 RRCrtcPtr randr_crtc,
1657 BoxPtr totalArea, BoxPtr trackingArea, INT16 *border)
1658{
1659 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1660 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1661 BoxRec oldTotalArea;
1662 BoxRec oldTrackingArea;
1663 INT16 oldBorder[4];
1664 Bool oldPanning = randrp->panning;
1665
1666 if (crtc->version < 2)
1667 return FALSE;
1668
1669 memcpy(&oldTotalArea, &crtc->panningTotalArea, sizeof(BoxRec));
1670 memcpy(&oldTrackingArea, &crtc->panningTrackingArea, sizeof(BoxRec));
1671 memcpy(oldBorder, crtc->panningBorder, 4 * sizeof(INT16));
1672
1673 if (totalArea)
1674 memcpy(&crtc->panningTotalArea, totalArea, sizeof(BoxRec));
1675 if (trackingArea)
1676 memcpy(&crtc->panningTrackingArea, trackingArea, sizeof(BoxRec));
1677 if (border)
1678 memcpy(crtc->panningBorder, border, 4 * sizeof(INT16));
1679
1680 if (xf86RandR13VerifyPanningArea(crtc, pScreen->width, pScreen->height)) {
1681 xf86RandR13Pan(crtc, randrp->pointerX, randrp->pointerY);
1682 randrp->panning = PANNING_ENABLED (crtc);
1683 return TRUE;
1684 }
1685 else {
1686 /* Restore old settings */
1687 memcpy(&crtc->panningTotalArea, &oldTotalArea, sizeof(BoxRec));
1688 memcpy(&crtc->panningTrackingArea, &oldTrackingArea, sizeof(BoxRec));
1689 memcpy(crtc->panningBorder, oldBorder, 4 * sizeof(INT16));
1690 randrp->panning = oldPanning;
1691 return FALSE;
1692 }
1693}
1694
1695/*
1696 * Compatibility with XF86VidMode's gamma changer. This necessarily clobbers
1697 * any per-crtc setup. You asked for it...
1698 */
1699
1700static void
1701gamma_to_ramp(float gamma, CARD16 *ramp, int size)
1702{
1703 int i;
1704
1705 for (i = 0; i < size; i++) {
1706 if (gamma == 1.0)
1707 ramp[i] = i | i << 8;
1708 else
1709 ramp[i] =
1710 (CARD16) (pow((double) i / (double) (size - 1), 1. / gamma)
1711 * (double) (size - 1) * 257);
1712 }
1713}
1714
1715static int
1716xf86RandR12ChangeGamma(ScrnInfoPtr pScrn, Gamma gamma)
1717{
1718 CARD16 *points, *red, *green, *blue;
1719 RRCrtcPtr crtc = xf86CompatRRCrtc(pScrn);
1720 int size;
1721
1722 if (!crtc)
1723 return Success;
1724
1725 size = max(0, crtc->gammaSize);
1726 if (!size)
1727 return Success;
1728
1729 points = calloc(size, 3 * sizeof(CARD16));
1730 if (!points)
1731 return BadAlloc;
1732
1733 red = points;
1734 green = points + size;
1735 blue = points + 2 * size;
1736
1737 gamma_to_ramp(gamma.red, red, size);
1738 gamma_to_ramp(gamma.green, green, size);
1739 gamma_to_ramp(gamma.blue, blue, size);
1740 RRCrtcGammaSet(crtc, red, green, blue);
1741
1742 free(points);
1743
1744 pScrn->gamma = gamma;
1745
1746 return Success;
1747}
1748
1749static Bool
1750xf86RandR12EnterVT(ScrnInfoPtr pScrn)
1751{
1752 ScreenPtr pScreen = xf86ScrnToScreen(pScrn);
1753 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1754 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1755 Bool ret;
1756 int i;
1757
1758 if (randrp->orig_EnterVT) {
1759 pScrn->EnterVT = randrp->orig_EnterVT;
1760 ret = pScrn->EnterVT(pScrn);
1761 randrp->orig_EnterVT = pScrn->EnterVT;
1762 pScrn->EnterVT = xf86RandR12EnterVT;
1763 if (!ret)
1764 return FALSE;
1765 }
1766
1767 /* reload gamma */
1768 for (i = 0; i < rp->numCrtcs; i++)
1769 xf86RandR12CrtcSetGamma(pScreen, rp->crtcs[i]);
1770
1771 return RRGetInfo(pScreen, TRUE); /* force a re-probe of outputs and notify clients about changes */
1772}
1773
1774static void
1775xf86DetachOutputGPU(ScreenPtr pScreen)
1776{
1777 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1778 int i;
1779
1780 /* make sure there are no attached shared scanout pixmaps first */
1781 for (i = 0; i < rp->numCrtcs; i++)
1782 RRCrtcDetachScanoutPixmap(rp->crtcs[i]);
1783
1784 DetachOutputGPU(pScreen);
1785}
1786
1787static Bool
1788xf86RandR14ProviderSetOutputSource(ScreenPtr pScreen,
1789 RRProviderPtr provider,
1790 RRProviderPtr source_provider)
1791{
1792 if (!source_provider) {
1793 if (provider->output_source) {
1794 ScreenPtr cmScreen = pScreen->current_master;
1795
1796 xf86DetachOutputGPU(pScreen);
1797 AttachUnboundGPU(cmScreen, pScreen);
1798 }
1799 provider->output_source = NULL;
1800 return TRUE;
1801 }
1802
1803 if (provider->output_source == source_provider)
1804 return TRUE;
1805
1806 SetRootClip(source_provider->pScreen, FALSE);
1807
1808 DetachUnboundGPU(pScreen);
1809 AttachOutputGPU(source_provider->pScreen, pScreen);
1810
1811 provider->output_source = source_provider;
1812 SetRootClip(source_provider->pScreen, TRUE);
1813 return TRUE;
1814}
1815
1816static Bool
1817xf86RandR14ProviderSetOffloadSink(ScreenPtr pScreen,
1818 RRProviderPtr provider,
1819 RRProviderPtr sink_provider)
1820{
1821 if (!sink_provider) {
1822 if (provider->offload_sink) {
1823 ScreenPtr cmScreen = pScreen->current_master;
1824 xf86DetachOutputGPU(pScreen);
1825 AttachUnboundGPU(cmScreen, pScreen);
1826 }
1827
1828 provider->offload_sink = NULL;
1829 return TRUE;
1830 }
1831
1832 if (provider->offload_sink == sink_provider)
1833 return TRUE;
1834
1835 DetachUnboundGPU(pScreen);
1836 AttachOffloadGPU(sink_provider->pScreen, pScreen);
1837
1838 provider->offload_sink = sink_provider;
1839 return TRUE;
1840}
1841
1842static Bool
1843xf86RandR14ProviderSetProperty(ScreenPtr pScreen,
1844 RRProviderPtr randr_provider,
1845 Atom property, RRPropertyValuePtr value)
1846{
1847 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1848 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1849
1850 /* If we don't have any property handler, then we don't care what the
1851 * user is setting properties to.
1852 */
1853 if (config->provider_funcs->set_property == NULL)
1854 return TRUE;
1855
1856 /*
1857 * This function gets called even when vtSema is FALSE, as
1858 * drivers will need to remember the correct value to apply
1859 * when the VT switch occurs
1860 */
1861 return config->provider_funcs->set_property(pScrn, property, value);
1862}
1863
1864static Bool
1865xf86RandR14ProviderGetProperty(ScreenPtr pScreen,
1866 RRProviderPtr randr_provider, Atom property)
1867{
1868 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1869 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
1870
1871 if (config->provider_funcs->get_property == NULL)
1872 return TRUE;
1873
1874 /* Should be safe even w/o vtSema */
1875 return config->provider_funcs->get_property(pScrn, property);
1876}
1877
1878static Bool
1879xf86CrtcSetScanoutPixmap(RRCrtcPtr randr_crtc, PixmapPtr pixmap)
1880{
1881 xf86CrtcPtr crtc = randr_crtc->devPrivate;
1882 if (!crtc->funcs->set_scanout_pixmap)
1883 return FALSE;
1884 return crtc->funcs->set_scanout_pixmap(crtc, pixmap);
1885}
1886
1887static void
1888xf86RandR13ConstrainCursorHarder(DeviceIntPtr dev, ScreenPtr screen, int mode, int *x, int *y)
1889{
1890 XF86RandRInfoPtr randrp = XF86RANDRINFO(screen);
1891
1892 if (randrp->panning)
1893 return;
1894
1895 if (randrp->orig_ConstrainCursorHarder) {
1896 screen->ConstrainCursorHarder = randrp->orig_ConstrainCursorHarder;
1897 screen->ConstrainCursorHarder(dev, screen, mode, x, y);
1898 screen->ConstrainCursorHarder = xf86RandR13ConstrainCursorHarder;
1899 }
1900}
1901
1902static void
1903xf86RandR14ProviderDestroy(ScreenPtr screen, RRProviderPtr provider)
1904{
1905 ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
1906 xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
1907
1908 if (config->randr_provider == provider) {
1909 if (config->randr_provider->offload_sink) {
1910 DetachOffloadGPU(screen);
1911 config->randr_provider->offload_sink = NULL;
1912 RRSetChanged(screen);
1913 }
1914 else if (config->randr_provider->output_source) {
1915 xf86DetachOutputGPU(screen);
1916 config->randr_provider->output_source = NULL;
1917 RRSetChanged(screen);
1918 }
1919 else if (screen->current_master)
1920 DetachUnboundGPU(screen);
1921 }
1922 config->randr_provider = NULL;
1923}
1924
1925static Bool
1926xf86RandR12Init12(ScreenPtr pScreen)
1927{
1928 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
1929 rrScrPrivPtr rp = rrGetScrPriv(pScreen);
1930 XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
1931 int i;
1932
1933 rp->rrGetInfo = xf86RandR12GetInfo12;
1934 rp->rrScreenSetSize = xf86RandR12ScreenSetSize;
1935 rp->rrCrtcSet = xf86RandR12CrtcSet;
1936 rp->rrCrtcSetGamma = xf86RandR12CrtcSetGamma;
1937 rp->rrCrtcGetGamma = xf86RandR12CrtcGetGamma;
1938 rp->rrOutputSetProperty = xf86RandR12OutputSetProperty;
1939 rp->rrOutputValidateMode = xf86RandR12OutputValidateMode;
1940#if RANDR_13_INTERFACE
1941 rp->rrOutputGetProperty = xf86RandR13OutputGetProperty;
1942 rp->rrGetPanning = xf86RandR13GetPanning;
1943 rp->rrSetPanning = xf86RandR13SetPanning;
1944#endif
1945 rp->rrModeDestroy = xf86RandR12ModeDestroy;
1946 rp->rrSetConfig = NULL;
1947
1948 rp->rrProviderSetOutputSource = xf86RandR14ProviderSetOutputSource;
1949 rp->rrProviderSetOffloadSink = xf86RandR14ProviderSetOffloadSink;
1950
1951 rp->rrProviderSetProperty = xf86RandR14ProviderSetProperty;
1952 rp->rrProviderGetProperty = xf86RandR14ProviderGetProperty;
1953 rp->rrCrtcSetScanoutPixmap = xf86CrtcSetScanoutPixmap;
1954 rp->rrProviderDestroy = xf86RandR14ProviderDestroy;
1955
1956 pScrn->PointerMoved = xf86RandR12PointerMoved;
1957 pScrn->ChangeGamma = xf86RandR12ChangeGamma;
1958
1959 randrp->orig_EnterVT = pScrn->EnterVT;
1960 pScrn->EnterVT = xf86RandR12EnterVT;
1961
1962 randrp->panning = FALSE;
1963 randrp->orig_ConstrainCursorHarder = pScreen->ConstrainCursorHarder;
1964 pScreen->ConstrainCursorHarder = xf86RandR13ConstrainCursorHarder;
1965
1966 if (!xf86RandR12CreateObjects12(pScreen))
1967 return FALSE;
1968
1969 /*
1970 * Configure output modes
1971 */
1972 if (!xf86RandR12SetInfo12(pScreen))
1973 return FALSE;
1974 for (i = 0; i < rp->numCrtcs; i++) {
1975 xf86RandR12CrtcGetGamma(pScreen, rp->crtcs[i]);
1976 }
1977 return TRUE;
1978}
1979
1980#endif
1981
1982Bool
1983xf86RandR12PreInit(ScrnInfoPtr pScrn)
1984{
1985 return TRUE;
1986}