summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Airlie <airlied@linux.ie>2007-03-06 22:06:31 +1100
committerDave Airlie <airlied@linux.ie>2007-03-06 22:06:31 +1100
commitf608a523ec5dbade80f33fcc137c4584cc5e1ca2 (patch)
tree650a0d1e988c438125b1bcd8c7a68d5773d4250c
parent2cfbdb224ef5352dab42879d4047433b4ed680a0 (diff)
downloadxorg-driver-xf86-video-nouveau-f608a523ec5dbade80f33fcc137c4584cc5e1ca2.tar.gz
update randr code to latest from intel - probably won't work yet
-rw-r--r--src/nv_crtc.c14
-rw-r--r--src/nv_driver.c16
-rw-r--r--src/nv_output.c21
-rw-r--r--src/nv_randr.c64
-rw-r--r--src/nv_xf86Crtc.c455
-rw-r--r--src/nv_xf86Crtc.h130
-rw-r--r--src/nv_xf86Rotate.c185
7 files changed, 720 insertions, 165 deletions
diff --git a/src/nv_crtc.c b/src/nv_crtc.c
index 81f5b95..7d0797e 100644
--- a/src/nv_crtc.c
+++ b/src/nv_crtc.c
@@ -997,12 +997,26 @@ void nv_crtc_restore(xf86CrtcPtr crtc)
}
+void nv_crtc_prepare(xf86CrtcPtr crtc)
+{
+
+
+}
+
+void nv_crtc_commit(xf86CrtcPtr crtc)
+{
+
+
+}
+
static const xf86CrtcFuncsRec nv_crtc_funcs = {
.dpms = nv_crtc_dpms,
.save = nv_crtc_save, /* XXX */
.restore = nv_crtc_restore, /* XXX */
.mode_fixup = nv_crtc_mode_fixup,
.mode_set = nv_crtc_mode_set,
+ .prepare = nv_crtc_prepare,
+ .commit = nv_crtc_commit,
.destroy = NULL, /* XXX */
};
diff --git a/src/nv_driver.c b/src/nv_driver.c
index 02033a6..8a6cfba 100644
--- a/src/nv_driver.c
+++ b/src/nv_driver.c
@@ -1111,6 +1111,18 @@ static Bool NVPreInitDRI(ScrnInfoPtr pScrn)
return TRUE;
}
+static Bool
+nv_xf86crtc_resize (ScrnInfoPtr scrn, int width, int height)
+{
+ scrn->virtualX = width;
+ scrn->virtualY = height;
+ return TRUE;
+}
+
+static const xf86CrtcConfigFuncsRec nv_xf86crtc_config_funcs = {
+ nv_xf86crtc_resize
+};
+
/* Mandatory */
Bool
NVPreInit(ScrnInfoPtr pScrn, int flags)
@@ -1581,7 +1593,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
/* Allocate an xf86CrtcConfig */
- xf86CrtcConfigInit (pScrn);
+ xf86CrtcConfigInit (pScrn, &nv_xf86crtc_config_funcs);
xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
max_width = 16384;
@@ -1612,7 +1624,7 @@ NVPreInit(ScrnInfoPtr pScrn, int flags)
output->status = (*output->funcs->detect) (output);
}
- if (!xf86InitialConfiguration (pScrn)) {
+ if (!xf86InitialConfiguration (pScrn, FALSE)) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "No valid modes.\n");
return FALSE;
}
diff --git a/src/nv_output.c b/src/nv_output.c
index 59fbae0..8cb31ef 100644
--- a/src/nv_output.c
+++ b/src/nv_output.c
@@ -531,6 +531,19 @@ nv_output_destroy (xf86OutputPtr output)
}
+static void
+nv_output_prepare(xf86OutputPtr output)
+{
+
+}
+
+static void
+nv_output_commit(xf86OutputPtr output)
+{
+
+
+}
+
static const xf86OutputFuncsRec nv_output_funcs = {
.dpms = nv_output_dpms,
.save = nv_output_save,
@@ -540,7 +553,9 @@ static const xf86OutputFuncsRec nv_output_funcs = {
.mode_set = nv_output_mode_set,
.detect = nv_output_detect,
.get_modes = nv_output_get_modes,
- .destroy = nv_output_destroy
+ .destroy = nv_output_destroy,
+ .prepare = nv_output_prepare,
+ .commit = nv_output_commit,
};
static xf86OutputStatus
@@ -574,7 +589,9 @@ static const xf86OutputFuncsRec nv_lvds_output_funcs = {
.mode_set = nv_output_mode_set,
.detect = nv_output_lvds_detect,
.get_modes = nv_output_lvds_get_modes,
- .destroy = nv_output_destroy
+ .destroy = nv_output_destroy,
+ .prepare = nv_output_prepare,
+ .commit = nv_output_commit,
};
/**
diff --git a/src/nv_randr.c b/src/nv_randr.c
index 9537925..84b2de4 100644
--- a/src/nv_randr.c
+++ b/src/nv_randr.c
@@ -34,8 +34,6 @@
#include "xf86.h"
#include "xf86Priv.h"
#include "xf86DDC.h"
-#include "X11/Xatom.h"
-
#include "mipointer.h"
#include "windowstr.h"
#include <randrstr.h>
@@ -97,6 +95,7 @@ xf86RandR12GetInfo (ScreenPtr pScreen, Rotation *rotations)
/* Re-probe the outputs for new monitors or modes */
xf86ProbeOutputModes (scrp, 0, 0);
xf86SetScrnInfoModes (scrp);
+ xf86DiDGAReInit (pScreen);
for (mode = scrp->modes; ; mode = mode->next)
{
@@ -333,8 +332,9 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
ScrnInfoPtr pScrn = XF86SCRNINFO(pScreen);
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
WindowPtr pRoot = WindowTable[pScreen->myNum];
- Bool ret = TRUE;
+ Bool ret = FALSE;
if (randrp->virtualX == -1 || randrp->virtualY == -1)
{
@@ -343,20 +343,26 @@ xf86RandR12ScreenSetSize (ScreenPtr pScreen,
}
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, FALSE);
- pScrn->virtualX = width;
- pScrn->virtualY = height;
- pScreen->width = pScrn->virtualX;
- pScreen->height = pScrn->virtualY;
+ /* Let the driver update virtualX and virtualY */
+ if (!(*config->funcs->resize)(pScrn, width, height))
+ goto finish;
+
+ ret = TRUE;
+
+ pScreen->width = width;
+ pScreen->height = height;
pScreen->mmWidth = mmWidth;
pScreen->mmHeight = mmHeight;
xf86SetViewport (pScreen, pScreen->width-1, pScreen->height-1);
xf86SetViewport (pScreen, 0, 0);
+
+finish:
if (pRoot)
(*pScrn->EnableDisableFBAccess) (pScreen->myNum, TRUE);
#if RANDR_12_INTERFACE
- if (WindowTable[pScreen->myNum])
+ if (WindowTable[pScreen->myNum] && ret)
RRScreenSizeNotify (pScreen);
#endif
return ret;
@@ -392,8 +398,8 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
for (c = 0; c < config->num_crtc; c++)
{
xf86CrtcPtr crtc = config->crtc[c];
- int crtc_width = crtc->x + crtc->mode.HDisplay;
- int crtc_height = crtc->y + crtc->mode.VDisplay;
+ int crtc_width = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ int crtc_height = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
if (crtc->enabled && crtc_width > width)
width = crtc_width;
@@ -413,8 +419,28 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
}
else
{
- mmWidth = pScreen->mmWidth;
- mmHeight = pScreen->mmHeight;
+ xf86OutputPtr output = config->output[config->compat_output];
+ xf86CrtcPtr crtc = output->crtc;
+
+ if (crtc && crtc->mode.HDisplay &&
+ output->mm_width && output->mm_height)
+ {
+ /*
+ * If the output has a mode and a declared size, use that
+ * to scale the screen size
+ */
+ DisplayModePtr mode = &crtc->mode;
+ mmWidth = output->mm_width * width / mode->HDisplay;
+ mmHeight = output->mm_height * height / mode->VDisplay;
+ }
+ else
+ {
+ /*
+ * Otherwise, just set the screen to 96dpi
+ */
+ mmWidth = width * 25.4 / 96;
+ mmHeight = height * 25.4 / 96;
+ }
}
xf86DrvMsg(pScrn->scrnIndex, X_INFO,
"Setting screen physical size to %d x %d\n",
@@ -431,6 +457,7 @@ xf86RandR12CreateScreenResources (ScreenPtr pScreen)
randrp->virtualX = pScrn->virtualX;
randrp->virtualY = pScrn->virtualY;
}
+ xf86CrtcSetScreenSubpixelOrder (pScreen);
#if RANDR_12_INTERFACE
if (xf86RandR12CreateScreenResources12 (pScreen))
return TRUE;
@@ -493,19 +520,18 @@ void
xf86RandR12SetRotations (ScreenPtr pScreen, Rotation rotations)
{
XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
+#if RANDR_12_INTERFACE
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
int c;
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
- randrp->supported_rotations = rotations;
-
-#if RANDR_12_INTERFACE
for (c = 0; c < config->num_crtc; c++) {
xf86CrtcPtr crtc = config->crtc[c];
RRCrtcSetRotations (crtc->randr_crtc, rotations);
}
#endif
+ randrp->supported_rotations = rotations;
}
void
@@ -862,6 +888,7 @@ xf86RandR12GetInfo12 (ScreenPtr pScreen, Rotation *rotations)
xf86ProbeOutputModes (pScrn, 0, 0);
xf86SetScrnInfoModes (pScrn);
+ xf86DiDGAReInit (pScreen);
return xf86RandR12SetInfo12 (pScreen);
}
@@ -910,15 +937,14 @@ xf86RandR12CreateScreenResources12 (ScreenPtr pScreen)
{
int c;
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
- XF86RandRInfoPtr randrp = XF86RANDRINFO(pScreen);
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
for (c = 0; c < config->num_crtc; c++)
xf86RandR12CrtcNotify (config->crtc[c]->randr_crtc);
- RRScreenSetSizeRange (pScreen, 320, 240,
- randrp->virtualX, randrp->virtualY);
+ RRScreenSetSizeRange (pScreen, config->minWidth, config->minHeight,
+ config->maxWidth, config->maxHeight);
return TRUE;
}
diff --git a/src/nv_xf86Crtc.c b/src/nv_xf86Crtc.c
index 11ae68e..d5f6137 100644
--- a/src/nv_xf86Crtc.c
+++ b/src/nv_xf86Crtc.c
@@ -35,6 +35,9 @@
#define DPMS_SERVER
#include "X11/extensions/dpms.h"
#include "X11/Xatom.h"
+#ifdef RENDER
+#include "picturestr.h"
+#endif
/*
* Initialize xf86CrtcConfig structure
@@ -43,13 +46,17 @@
int xf86CrtcConfigPrivateIndex = -1;
void
-xf86CrtcConfigInit (ScrnInfoPtr scrn)
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs)
{
xf86CrtcConfigPtr config;
if (xf86CrtcConfigPrivateIndex == -1)
xf86CrtcConfigPrivateIndex = xf86AllocateScrnInfoPrivateIndex();
config = xnfcalloc (1, sizeof (xf86CrtcConfigRec));
+
+ config->funcs = funcs;
+
scrn->privates[xf86CrtcConfigPrivateIndex].ptr = config;
}
@@ -138,6 +145,71 @@ xf86CrtcInUse (xf86CrtcPtr crtc)
return FALSE;
}
+void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen)
+{
+#ifdef RENDER
+ int subpixel_order = SubPixelUnknown;
+ Bool has_none = FALSE;
+ ScrnInfoPtr scrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c, o;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ for (o = 0; o < xf86_config->num_output; o++)
+ {
+ xf86OutputPtr output = xf86_config->output[o];
+
+ if (output->crtc == crtc)
+ {
+ switch (output->subpixel_order) {
+ case SubPixelNone:
+ has_none = TRUE;
+ break;
+ case SubPixelUnknown:
+ break;
+ default:
+ subpixel_order = output->subpixel_order;
+ break;
+ }
+ }
+ if (subpixel_order != SubPixelUnknown)
+ break;
+ }
+ if (subpixel_order != SubPixelUnknown)
+ {
+ static const int circle[4] = {
+ SubPixelHorizontalRGB,
+ SubPixelVerticalRGB,
+ SubPixelHorizontalBGR,
+ SubPixelVerticalBGR,
+ };
+ int rotate;
+ int c;
+ for (rotate = 0; rotate < 4; rotate++)
+ if (crtc->rotation & (1 << rotate))
+ break;
+ for (c = 0; c < 4; c++)
+ if (circle[c] == subpixel_order)
+ break;
+ c = (c + rotate) & 0x3;
+ if ((crtc->rotation & RR_Reflect_X) && !(c & 1))
+ c ^= 2;
+ if ((crtc->rotation & RR_Reflect_Y) && (c & 1))
+ c ^= 2;
+ subpixel_order = circle[c];
+ break;
+ }
+ }
+ if (subpixel_order == SubPixelUnknown && has_none)
+ subpixel_order = SubPixelNone;
+ PictureSetSubpixelOrder (pScreen, subpixel_order);
+#endif
+}
+
/**
* Sets the given video mode on the given crtc
*/
@@ -204,7 +276,7 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
goto done;
}
- /* Disable the outputs and CRTCs before setting the mode. */
+ /* Prepare the outputs and CRTCs before setting the mode. */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -212,10 +284,10 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
continue;
/* Disable the output as the first thing we do. */
- output->funcs->dpms(output, DPMSModeOff);
+ output->funcs->prepare(output);
}
- crtc->funcs->dpms(crtc, DPMSModeOff);
+ crtc->funcs->prepare(crtc);
/* Set up the DPLL and any output state that needs to adjust or depend
* on the DPLL.
@@ -229,16 +301,19 @@ xf86CrtcSetMode (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation,
}
/* Now, enable the clocks, plane, pipe, and outputs that we set up. */
- crtc->funcs->dpms(crtc, DPMSModeOn);
+ crtc->funcs->commit(crtc);
for (i = 0; i < xf86_config->num_output; i++)
{
xf86OutputPtr output = xf86_config->output[i];
if (output->crtc == crtc)
- output->funcs->dpms(output, DPMSModeOn);
+ output->funcs->commit(output);
}
/* XXX free adjustedmode */
ret = TRUE;
+ if (scrn->pScreen)
+ xf86CrtcSetScreenSubpixelOrder (scrn->pScreen);
+
done:
if (!ret) {
crtc->x = saved_x;
@@ -271,6 +346,7 @@ typedef enum {
OPTION_MIN_CLOCK,
OPTION_MAX_CLOCK,
OPTION_IGNORE,
+ OPTION_ROTATE,
} OutputOpts;
static OptionInfoRec xf86OutputOptions[] = {
@@ -285,6 +361,7 @@ static OptionInfoRec xf86OutputOptions[] = {
{OPTION_MIN_CLOCK, "MinClock", OPTV_FREQ, {0}, FALSE },
{OPTION_MAX_CLOCK, "MaxClock", OPTV_FREQ, {0}, FALSE },
{OPTION_IGNORE, "Ignore", OPTV_BOOLEAN, {0}, FALSE },
+ {OPTION_ROTATE, "Rotate", OPTV_STRING, {0}, FALSE },
{-1, NULL, OPTV_NONE, {0}, FALSE },
};
@@ -340,6 +417,29 @@ xf86OutputIgnored (xf86OutputPtr output)
return xf86ReturnOptValBool (output->options, OPTION_IGNORE, FALSE);
}
+static char *direction[4] = {
+ "normal",
+ "left",
+ "inverted",
+ "right"
+};
+
+static Rotation
+xf86OutputInitialRotation (xf86OutputPtr output)
+{
+ char *rotate_name = xf86GetOptValString (output->options,
+ OPTION_ROTATE);
+ int i;
+
+ if (!rotate_name)
+ return RR_Rotate_0;
+
+ for (i = 0; i < 4; i++)
+ if (xf86nameCompare (direction[i], rotate_name) == 0)
+ return (1 << i);
+ return RR_Rotate_0;
+}
+
xf86OutputPtr
xf86OutputCreate (ScrnInfoPtr scrn,
const xf86OutputFuncsRec *funcs,
@@ -460,8 +560,12 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height)
int preferred = (mode->type & M_T_PREFERRED) != 0;
int diff;
- if (mode->HDisplay > width || mode->VDisplay > height) continue;
- dpi = (mode->HDisplay * 254) / (mm_height * 10);
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
+ /* yes, use VDisplay here, not xf86ModeHeight */
+ dpi = (mode->VDisplay * 254) / (mm_height * 10);
diff = dpi - 96;
diff = diff < 0 ? -diff : diff;
if (target_mode == NULL || (preferred > target_preferred) ||
@@ -476,7 +580,8 @@ xf86DefaultMode (xf86OutputPtr output, int width, int height)
}
static DisplayModePtr
-xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match,
+xf86ClosestMode (xf86OutputPtr output,
+ DisplayModePtr match, Rotation match_rotation,
int width, int height)
{
DisplayModePtr target_mode = NULL;
@@ -491,14 +596,17 @@ xf86ClosestMode (xf86OutputPtr output, DisplayModePtr match,
int dx, dy;
int diff;
- if (mode->HDisplay > width || mode->VDisplay > height) continue;
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
/* exact matches are preferred */
- if (xf86ModesEqual (mode, match))
+ if (output->initial_rotation == match_rotation &&
+ xf86ModesEqual (mode, match))
return mode;
- dx = match->HDisplay - mode->HDisplay;
- dy = match->VDisplay - mode->VDisplay;
+ dx = xf86ModeWidth (match, match_rotation) - xf86ModeWidth (mode, output->initial_rotation);
+ dy = xf86ModeHeight (match, match_rotation) - xf86ModeHeight (mode, output->initial_rotation);
diff = dx * dx + dy * dy;
if (target_mode == NULL || diff < target_diff)
{
@@ -516,7 +624,10 @@ xf86OutputHasPreferredMode (xf86OutputPtr output, int width, int height)
for (mode = output->probed_modes; mode; mode = mode->next)
{
- if (mode->HDisplay > width || mode->VDisplay > height) continue;
+ if (xf86ModeWidth (mode, output->initial_rotation) > width ||
+ xf86ModeHeight (mode, output->initial_rotation) > height)
+ continue;
+
if (mode->type & M_T_PREFERRED)
return TRUE;
}
@@ -532,7 +643,7 @@ xf86PickCrtcs (ScrnInfoPtr scrn,
int height)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
- int c, o, l;
+ int c, o;
xf86OutputPtr output;
xf86CrtcPtr crtc;
xf86CrtcPtr *crtcs;
@@ -590,13 +701,11 @@ xf86PickCrtcs (ScrnInfoPtr scrn,
* see if they can be cloned
*/
if (xf86ModesEqual (modes[o], modes[n]) &&
+ config->output[0]->initial_rotation == config->output[n]->initial_rotation &&
config->output[o]->initial_x == config->output[n]->initial_x &&
config->output[o]->initial_y == config->output[n]->initial_y)
{
- for (l = 0; l < config->num_output; l++)
- if (output->possible_clones & (1 << l))
- break;
- if (l == config->num_output)
+ if ((output->possible_clones & (1 << o)) == 0)
continue; /* nope, try next CRTC */
}
else
@@ -619,12 +728,16 @@ xf86PickCrtcs (ScrnInfoPtr scrn,
/*
* Compute the virtual size necessary to place all of the available
- * crtcs in the specified configuration and also large enough to
- * resize any crtc to the largest available mode
+ * crtcs in the specified configuration.
+ *
+ * canGrow indicates that the driver can make the screen larger than its initial
+ * configuration. If FALSE, this function will enlarge the screen to include
+ * the largest available mode.
*/
static void
-xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
+xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp,
+ Bool canGrow)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
int width = 0, height = 0;
@@ -639,25 +752,31 @@ xf86DefaultScreenLimits (ScrnInfoPtr scrn, int *widthp, int *heightp)
if (crtc->enabled)
{
- crtc_width = crtc->x + crtc->desiredMode.HDisplay;
- crtc_height = crtc->y + crtc->desiredMode.VDisplay;
+ crtc_width = crtc->x + xf86ModeWidth (&crtc->desiredMode, crtc->desiredRotation);
+ crtc_height = crtc->y + xf86ModeHeight (&crtc->desiredMode, crtc->desiredRotation);
}
- for (o = 0; o < config->num_output; o++)
- {
- xf86OutputPtr output = config->output[o];
+ if (!canGrow) {
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
- for (s = 0; s < config->num_crtc; s++)
- if (output->possible_crtcs & (1 << s))
- {
- DisplayModePtr mode;
- for (mode = output->probed_modes; mode; mode = mode->next)
+ for (s = 0; s < config->num_crtc; s++)
+ if (output->possible_crtcs & (1 << s))
{
- if (mode->HDisplay > crtc_width)
- crtc_width = mode->HDisplay;
- if (mode->VDisplay > crtc_height)
- crtc_height = mode->VDisplay;
+ DisplayModePtr mode;
+ for (mode = output->probed_modes; mode; mode = mode->next)
+ {
+ if (mode->HDisplay > crtc_width)
+ crtc_width = mode->HDisplay;
+ if (mode->VDisplay > crtc_width)
+ crtc_width = mode->VDisplay;
+ if (mode->VDisplay > crtc_height)
+ crtc_height = mode->VDisplay;
+ if (mode->HDisplay > crtc_height)
+ crtc_height = mode->HDisplay;
+ }
}
- }
+ }
}
if (crtc_width > width)
width = crtc_width;
@@ -754,13 +873,17 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
{
xf86OutputPtr out_rel = config->output[or];
XF86ConfMonitorPtr rel_mon = out_rel->conf_monitor;
- char *name;
if (rel_mon)
- name = rel_mon->mon_identifier;
- else
- name = out_rel->name;
- if (!strcmp (relative_name, name))
+ {
+ if (xf86nameCompare (rel_mon->mon_identifier,
+ relative_name) == 0)
+ {
+ relative = config->output[or];
+ break;
+ }
+ }
+ if (strcmp (out_rel->name, relative_name) == 0)
{
relative = config->output[or];
break;
@@ -785,16 +908,16 @@ xf86InitialOutputPositions (ScrnInfoPtr scrn, DisplayModePtr *modes)
output->initial_y = relative->initial_y;
switch (relation) {
case OPTION_BELOW:
- output->initial_y += modes[or]->VDisplay;
+ output->initial_y += xf86ModeHeight (modes[or], relative->initial_rotation);
break;
case OPTION_RIGHT_OF:
- output->initial_x += modes[or]->HDisplay;
+ output->initial_x += xf86ModeWidth (modes[or], relative->initial_rotation);
break;
case OPTION_ABOVE:
- output->initial_y -= modes[o]->VDisplay;
+ output->initial_y -= xf86ModeHeight (modes[or], relative->initial_rotation);
break;
case OPTION_LEFT_OF:
- output->initial_x -= modes[o]->HDisplay;
+ output->initial_x -= xf86ModeWidth (modes[or], relative->initial_rotation);
break;
default:
break;
@@ -883,7 +1006,7 @@ xf86PruneDuplicateMonitorModes (MonPtr Monitor)
/** Return - 0 + if a should be earlier, same or later than b in list
*/
static int
-nvxf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
+xf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
{
int diff;
@@ -901,7 +1024,7 @@ nvxf86ModeCompare (DisplayModePtr a, DisplayModePtr b)
* Insertion sort input in-place and return the resulting head
*/
static DisplayModePtr
-nvxf86SortModes (DisplayModePtr input)
+xf86SortModes (DisplayModePtr input)
{
DisplayModePtr output = NULL, i, o, n, *op, prev;
@@ -911,7 +1034,7 @@ nvxf86SortModes (DisplayModePtr input)
i = input;
input = input->next;
for (op = &output; (o = *op); op = &o->next)
- if (nvxf86ModeCompare (o, i) > 0)
+ if (xf86ModeCompare (o, i) > 0)
break;
i->next = *op;
*op = i;
@@ -1106,7 +1229,7 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
xf86PruneInvalidModes(scrn, &output->probed_modes, TRUE);
- output->probed_modes = nvxf86SortModes (output->probed_modes);
+ output->probed_modes = xf86SortModes (output->probed_modes);
/* Check for a configured preference for a particular mode */
preferred_mode = xf86GetOptValString (output->options,
@@ -1135,6 +1258,8 @@ xf86ProbeOutputModes (ScrnInfoPtr scrn, int maxX, int maxY)
}
}
+ output->initial_rotation = xf86OutputInitialRotation (output);
+
#ifdef DEBUG_REPROBE
if (output->probed_modes != NULL) {
xf86DrvMsg(scrn->scrnIndex, X_INFO,
@@ -1229,14 +1354,22 @@ xf86SetScrnInfoModes (ScrnInfoPtr scrn)
*
* Given auto-detected (and, eventually, configured) values,
* construct a usable configuration for the system
+ *
+ * canGrow indicates that the driver can resize the screen to larger than its
+ * initially configured size via the config->funcs->resize hook. If TRUE, this
+ * function will set virtualX and virtualY to match the initial configuration
+ * and leave config->max{Width,Height} alone. If FALSE, it will bloat
+ * virtual[XY] to include the largest modes and set config->max{Width,Height}
+ * accordingly.
*/
Bool
-xf86InitialConfiguration (ScrnInfoPtr scrn)
+xf86InitialConfiguration (ScrnInfoPtr scrn, Bool canGrow)
{
xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
int o, c;
DisplayModePtr target_mode = NULL;
+ Rotation target_rotation = RR_Rotate_0;
xf86CrtcPtr *crtcs;
DisplayModePtr *modes;
Bool *enabled;
@@ -1278,6 +1411,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
xf86OutputHasPreferredMode (output, width, height))
{
target_mode = xf86DefaultMode (output, width, height);
+ target_rotation = output->initial_rotation;
if (target_mode)
{
modes[o] = target_mode;
@@ -1294,6 +1428,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
if (enabled[o])
{
target_mode = xf86DefaultMode (output, width, height);
+ target_rotation = output->initial_rotation;
if (target_mode)
{
modes[o] = target_mode;
@@ -1308,7 +1443,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
xf86OutputPtr output = config->output[o];
if (enabled[o] && !modes[o])
- modes[o] = xf86ClosestMode (output, target_mode, width, height);
+ modes[o] = xf86ClosestMode (output, target_mode, target_rotation, width, height);
}
/*
@@ -1356,6 +1491,7 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
if (mode && crtc)
{
crtc->desiredMode = *mode;
+ crtc->desiredRotation = output->initial_rotation;
crtc->enabled = TRUE;
crtc->x = output->initial_x;
crtc->y = output->initial_y;
@@ -1366,9 +1502,10 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
if (scrn->display->virtualX == 0)
{
/*
- * Expand virtual size to cover potential mode switches
+ * Expand virtual size to cover the current config and potential mode
+ * switches, if the driver can't enlarge the screen later.
*/
- xf86DefaultScreenLimits (scrn, &width, &height);
+ xf86DefaultScreenLimits (scrn, &width, &height, canGrow);
scrn->display->virtualX = width;
scrn->display->virtualY = height;
@@ -1378,7 +1515,23 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
scrn->virtualX = width;
if (height > scrn->virtualY)
scrn->virtualY = height;
-
+
+ /*
+ * Make sure the configuration isn't too small.
+ */
+ if (width < config->minWidth || height < config->minHeight)
+ return FALSE;
+
+ /*
+ * Limit the crtc config to virtual[XY] if the driver can't grow the
+ * desktop.
+ */
+ if (!canGrow)
+ {
+ xf86CrtcSetSizeRange (scrn, config->minWidth, config->minHeight,
+ width, height);
+ }
+
/* Mirror output modes to scrn mode list */
xf86SetScrnInfoModes (scrn);
@@ -1387,6 +1540,189 @@ xf86InitialConfiguration (ScrnInfoPtr scrn)
return TRUE;
}
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+Bool
+xf86SetDesiredModes (ScrnInfoPtr scrn)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(scrn);
+ int c;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ xf86OutputPtr output = NULL;
+ int o;
+
+ if (config->output[config->compat_output]->crtc == crtc)
+ output = config->output[config->compat_output];
+ else
+ {
+ for (o = 0; o < config->num_output; o++)
+ if (config->output[o]->crtc == crtc)
+ {
+ output = config->output[o];
+ break;
+ }
+ }
+ /*
+ * Skip disabled crtcs
+ */
+ if (!output)
+ continue;
+
+ /* Mark that we'll need to re-set the mode for sure */
+ memset(&crtc->mode, 0, sizeof(crtc->mode));
+ if (!crtc->desiredMode.CrtcHDisplay)
+ {
+ DisplayModePtr mode = xf86OutputFindClosestMode (output, scrn->currentMode);
+
+ if (!mode)
+ return FALSE;
+ crtc->desiredMode = *mode;
+ crtc->desiredRotation = RR_Rotate_0;
+ crtc->desiredX = 0;
+ crtc->desiredY = 0;
+ }
+
+ if (!xf86CrtcSetMode (crtc, &crtc->desiredMode, crtc->desiredRotation,
+ crtc->desiredX, crtc->desiredY))
+ return FALSE;
+ }
+
+ xf86DisableUnusedFunctions(scrn);
+ return TRUE;
+}
+
+/**
+ * In the current world order, there are lists of modes per output, which may
+ * or may not include the mode that was asked to be set by XFree86's mode
+ * selection. Find the closest one, in the following preference order:
+ *
+ * - Equality
+ * - Closer in size to the requested mode, but no larger
+ * - Closer in refresh rate to the requested mode.
+ */
+
+DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired)
+{
+ DisplayModePtr best = NULL, scan = NULL;
+
+ for (scan = output->probed_modes; scan != NULL; scan = scan->next)
+ {
+ /* If there's an exact match, we're done. */
+ if (xf86ModesEqual(scan, desired)) {
+ best = desired;
+ break;
+ }
+
+ /* Reject if it's larger than the desired mode. */
+ if (scan->HDisplay > desired->HDisplay ||
+ scan->VDisplay > desired->VDisplay)
+ {
+ continue;
+ }
+
+ /*
+ * If we haven't picked a best mode yet, use the first
+ * one in the size range
+ */
+ if (best == NULL)
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's closer to the right size than the current best
+ * option.
+ */
+ if ((scan->HDisplay > best->HDisplay &&
+ scan->VDisplay >= best->VDisplay) ||
+ (scan->HDisplay >= best->HDisplay &&
+ scan->VDisplay > best->VDisplay))
+ {
+ best = scan;
+ continue;
+ }
+
+ /* Find if it's still closer to the right refresh than the current
+ * best resolution.
+ */
+ if (scan->HDisplay == best->HDisplay &&
+ scan->VDisplay == best->VDisplay &&
+ (fabs(scan->VRefresh - desired->VRefresh) <
+ fabs(best->VRefresh - desired->VRefresh))) {
+ best = scan;
+ }
+ }
+ return best;
+}
+
+/**
+ * When setting a mode through XFree86-VidModeExtension or XFree86-DGA,
+ * take the specified mode and apply it to the crtc connected to the compat
+ * output. Then, find similar modes for the other outputs, as with the
+ * InitialConfiguration code above. The goal is to clone the desired
+ * mode across all outputs that are currently active.
+ */
+
+Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation)
+{
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ Bool ok = TRUE;
+ xf86OutputPtr compat_output = config->output[config->compat_output];
+ DisplayModePtr compat_mode;
+ int c;
+
+ /*
+ * Let the compat output drive the final mode selection
+ */
+ compat_mode = xf86OutputFindClosestMode (compat_output, desired);
+ if (compat_mode)
+ desired = compat_mode;
+
+ for (c = 0; c < config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = config->crtc[c];
+ DisplayModePtr crtc_mode = NULL;
+ int o;
+
+ if (!crtc->enabled)
+ continue;
+
+ for (o = 0; o < config->num_output; o++)
+ {
+ xf86OutputPtr output = config->output[o];
+ DisplayModePtr output_mode;
+
+ /* skip outputs not on this crtc */
+ if (output->crtc != crtc)
+ continue;
+
+ if (crtc_mode)
+ {
+ output_mode = xf86OutputFindClosestMode (output, crtc_mode);
+ if (output_mode != crtc_mode)
+ output->crtc = NULL;
+ }
+ else
+ crtc_mode = xf86OutputFindClosestMode (output, desired);
+ }
+ if (!xf86CrtcSetMode (crtc, crtc_mode, rotation, 0, 0))
+ ok = FALSE;
+ else
+ crtc->desiredMode = *crtc_mode;
+ }
+ xf86DisableUnusedFunctions(pScrn);
+ return ok;
+}
+
+
/**
* Set the DPMS power mode of all outputs and CRTCs.
*
@@ -1583,3 +1919,12 @@ xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus)
return xf86DoEDID_DDC2 (scrn->scrnIndex, pDDCBus);
}
+
+static char *_xf86ConnectorNames[] = { "None", "VGA", "DVI-I", "DVI-D",
+ "DVI-A", "Composite", "S-Video",
+ "Component", "LFP", "Proprietary" };
+char *
+xf86ConnectorGetName(xf86ConnectorType connector)
+{
+ return _xf86ConnectorNames[connector];
+}
diff --git a/src/nv_xf86Crtc.h b/src/nv_xf86Crtc.h
index dc8663e..d0909f0 100644
--- a/src/nv_xf86Crtc.h
+++ b/src/nv_xf86Crtc.h
@@ -39,6 +39,20 @@
typedef struct _xf86Crtc xf86CrtcRec, *xf86CrtcPtr;
typedef struct _xf86Output xf86OutputRec, *xf86OutputPtr;
+/* define a standard for connector types */
+typedef enum _xf86ConnectorType {
+ XF86ConnectorNone,
+ XF86ConnectorVGA,
+ XF86ConnectorDVI_I,
+ XF86ConnectorDVI_D,
+ XF86ConnectorDVI_A,
+ XF86ConnectorComposite,
+ XF86ConnectorSvideo,
+ XF86ConnectorComponent,
+ XF86ConnectorLFP,
+ XF86ConnectorProprietary,
+} xf86ConnectorType;
+
typedef enum _xf86OutputStatus {
XF86OutputStatusConnected,
XF86OutputStatusDisconnected,
@@ -95,6 +109,12 @@ typedef struct _xf86CrtcFuncs {
DisplayModePtr adjusted_mode);
/**
+ * Prepare CRTC for an upcoming mode set.
+ */
+ void
+ (*prepare)(xf86CrtcPtr crtc);
+
+ /**
* Callback for setting up a video mode after fixups have been made.
*/
void
@@ -103,22 +123,34 @@ typedef struct _xf86CrtcFuncs {
DisplayModePtr adjusted_mode,
int x, int y);
+ /**
+ * Commit mode changes to a CRTC
+ */
+ void
+ (*commit)(xf86CrtcPtr crtc);
+
/* Set the color ramps for the CRTC to the given values. */
void
(*gamma_set)(xf86CrtcPtr crtc, CARD16 *red, CARD16 *green, CARD16 *blue,
int size);
/**
+ * Allocate the shadow area, delay the pixmap creation until needed
+ */
+ void *
+ (*shadow_allocate) (xf86CrtcPtr crtc, int width, int height);
+
+ /**
* Create shadow pixmap for rotation support
*/
PixmapPtr
- (*shadow_create) (xf86CrtcPtr crtc, int width, int height);
+ (*shadow_create) (xf86CrtcPtr crtc, void *data, int width, int height);
/**
* Destroy shadow pixmap
*/
void
- (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap);
+ (*shadow_destroy) (xf86CrtcPtr crtc, PixmapPtr pPixmap, void *data);
/**
* Clean up driver-specific bits of the crtc
@@ -156,6 +188,8 @@ struct _xf86Crtc {
DisplayModeRec mode;
Rotation rotation;
PixmapPtr rotatedPixmap;
+ void *rotatedData;
+
/**
* Position on screen
*
@@ -254,6 +288,18 @@ typedef struct _xf86OutputFuncs {
DisplayModePtr adjusted_mode);
/**
+ * Callback for preparing mode changes on an output
+ */
+ void
+ (*prepare)(xf86OutputPtr output);
+
+ /**
+ * Callback for committing mode changes on an output
+ */
+ void
+ (*commit)(xf86OutputPtr output);
+
+ /**
* Callback for setting up a video mode after fixups have been made.
*
* This is only called while the output is disabled. The dpms callback
@@ -354,6 +400,11 @@ struct _xf86Output {
int initial_x, initial_y;
/**
+ * Desired initial rotation
+ */
+ Rotation initial_rotation;
+
+ /**
* Current connection status
*
* This indicates whether a monitor is known to be connected
@@ -392,6 +443,25 @@ struct _xf86Output {
#endif
};
+typedef struct _xf86CrtcConfigFuncs {
+ /**
+ * Requests that the driver resize the screen.
+ *
+ * The driver is responsible for updating scrn->virtualX and scrn->virtualY.
+ * If the requested size cannot be set, the driver should leave those values
+ * alone and return FALSE.
+ *
+ * A naive driver that cannot reallocate the screen may simply change
+ * virtual[XY]. A more advanced driver will want to also change the
+ * devPrivate.ptr and devKind of the screen pixmap, update any offscreen
+ * pixmaps it may have moved, and change pScrn->displayWidth.
+ */
+ Bool
+ (*resize)(ScrnInfoPtr scrn,
+ int width,
+ int height);
+} xf86CrtcConfigFuncsRec, *xf86CrtcConfigFuncsPtr;
+
typedef struct _xf86CrtcConfig {
int num_output;
xf86OutputPtr *output;
@@ -413,7 +483,14 @@ typedef struct _xf86CrtcConfig {
DamagePtr rotationDamage;
/* DGA */
- unsigned int dga_flags;
+ unsigned int dga_flags;
+ unsigned long dga_address;
+ DGAModePtr dga_modes;
+ int dga_nmode;
+ int dga_width, dga_height, dga_stride;
+ DisplayModePtr dga_save_mode;
+
+ const xf86CrtcConfigFuncsRec *funcs;
} xf86CrtcConfigRec, *xf86CrtcConfigPtr;
@@ -426,7 +503,8 @@ extern int xf86CrtcConfigPrivateIndex;
*/
void
-xf86CrtcConfigInit (ScrnInfoPtr scrn);
+xf86CrtcConfigInit (ScrnInfoPtr scrn,
+ const xf86CrtcConfigFuncsRec *funcs);
void
xf86CrtcSetSizeRange (ScrnInfoPtr scrn,
@@ -503,7 +581,7 @@ void
xf86SetScrnInfoModes (ScrnInfoPtr pScrn);
Bool
-xf86InitialConfiguration (ScrnInfoPtr pScrn);
+xf86InitialConfiguration (ScrnInfoPtr pScrn, Bool canGrow);
void
xf86DPMSSet(ScrnInfoPtr pScrn, int PowerManagementMode, int flags);
@@ -514,6 +592,12 @@ xf86SaveScreen(ScreenPtr pScreen, int mode);
void
xf86DisableUnusedFunctions(ScrnInfoPtr pScrn);
+DisplayModePtr
+xf86OutputFindClosestMode (xf86OutputPtr output, DisplayModePtr desired);
+
+Bool
+xf86SetSingleMode (ScrnInfoPtr pScrn, DisplayModePtr desired, Rotation rotation);
+
/**
* Set the EDID information for the specified output
*/
@@ -530,4 +614,40 @@ xf86OutputGetEDIDModes (xf86OutputPtr output);
xf86MonPtr
xf86OutputGetEDID (xf86OutputPtr output, I2CBusPtr pDDCBus);
+/**
+ * Initialize dga for this screen
+ */
+
+Bool
+xf86DiDGAInit (ScreenPtr pScreen, unsigned long dga_address);
+
+/**
+ * Re-initialize dga for this screen (as when the set of modes changes)
+ */
+
+Bool
+xf86DiDGAReInit (ScreenPtr pScreen);
+
+/*
+ * Set the subpixel order reported for the screen using
+ * the information from the outputs
+ */
+
+void
+xf86CrtcSetScreenSubpixelOrder (ScreenPtr pScreen);
+
+/*
+ * Get a standard string name for a connector type
+ */
+char *
+xf86ConnectorGetName(xf86ConnectorType connector);
+
+/*
+ * Using the desired mode information in each crtc, set
+ * modes (used in EnterVT functions, or at server startup)
+ */
+
+Bool
+xf86SetDesiredModes (ScrnInfoPtr pScrn);
+
#endif /* _XF86CRTC_H_ */
diff --git a/src/nv_xf86Rotate.c b/src/nv_xf86Rotate.c
index e38185f..a4537ca 100644
--- a/src/nv_xf86Rotate.c
+++ b/src/nv_xf86Rotate.c
@@ -40,36 +40,6 @@
#include "X11/extensions/dpms.h"
#include "X11/Xatom.h"
-static int
-mode_height (DisplayModePtr mode, Rotation rotation)
-{
- switch (rotation & 0xf) {
- case RR_Rotate_0:
- case RR_Rotate_180:
- return mode->VDisplay;
- case RR_Rotate_90:
- case RR_Rotate_270:
- return mode->HDisplay;
- default:
- return 0;
- }
-}
-
-static int
-mode_width (DisplayModePtr mode, Rotation rotation)
-{
- switch (rotation & 0xf) {
- case RR_Rotate_0:
- case RR_Rotate_180:
- return mode->HDisplay;
- case RR_Rotate_90:
- case RR_Rotate_270:
- return mode->VDisplay;
- default:
- return 0;
- }
-}
-
/* borrowed from composite extension, move to Render and publish? */
static VisualPtr
@@ -95,31 +65,44 @@ compWindowFormat (WindowPtr pWin)
}
static void
-xf86RotateBox (BoxPtr dst, BoxPtr src, Rotation rotation,
- int dest_width, int dest_height)
+xf86TranslateBox (BoxPtr b, int dx, int dy)
+{
+ b->x1 += dx;
+ b->y1 += dy;
+ b->x2 += dx;
+ b->y2 += dy;
+}
+
+static void
+xf86TransformBox (BoxPtr dst, BoxPtr src, Rotation rotation,
+ int xoff, int yoff,
+ int dest_width, int dest_height)
{
+ BoxRec stmp = *src;
+
+ xf86TranslateBox (&stmp, -xoff, -yoff);
switch (rotation & 0xf) {
default:
case RR_Rotate_0:
- *dst = *src;
+ *dst = stmp;
break;
case RR_Rotate_90:
- dst->x1 = src->y1;
- dst->y1 = dest_height - src->x2;
- dst->x2 = src->y2;
- dst->y2 = dest_height - src->x1;
+ dst->x1 = stmp.y1;
+ dst->y1 = dest_height - stmp.x2;
+ dst->x2 = stmp.y2;
+ dst->y2 = dest_height - stmp.x1;
break;
case RR_Rotate_180:
- dst->x1 = dest_width - src->x2;
- dst->y1 = dest_height - src->y2;
- dst->x2 = dest_width - src->x1;
- dst->y2 = dest_height - src->y1;
+ dst->x1 = dest_width - stmp.x2;
+ dst->y1 = dest_height - stmp.y2;
+ dst->x2 = dest_width - stmp.x1;
+ dst->y2 = dest_height - stmp.y1;
break;
case RR_Rotate_270:
- dst->x1 = dest_width - src->y2;
- dst->y1 = src->x1;
- dst->y2 = src->x2;
- dst->x2 = dest_width - src->y1;
+ dst->x1 = dest_width - stmp.y2;
+ dst->y1 = stmp.x1;
+ dst->y2 = stmp.x2;
+ dst->x2 = dest_width - stmp.y1;
break;
}
if (rotation & RR_Reflect_X) {
@@ -156,10 +139,9 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
&include_inferiors,
serverClient,
&error);
- if (!src) {
- ErrorF("couldn't create src pict\n");
+ if (!src)
return;
- }
+
dst = CreatePicture (None,
&dst_pixmap->drawable,
format,
@@ -167,10 +149,8 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
NULL,
serverClient,
&error);
- if (!dst) {
- ErrorF("couldn't create src pict\n");
+ if (!dst)
return;
- }
memset (&transform, '\0', sizeof (transform));
transform.matrix[2][2] = IntToxFixed(1);
@@ -196,7 +176,7 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
case RR_Rotate_270:
transform.matrix[0][1] = IntToxFixed(1);
transform.matrix[1][0] = IntToxFixed(-1);
- transform.matrix[1][2] += IntToxFixed(crtc->mode.VDisplay);
+ transform.matrix[1][2] += IntToxFixed(crtc->mode.HDisplay);
break;
}
@@ -211,17 +191,16 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
}
error = SetPictureTransform (src, &transform);
- if (error) {
- ErrorF("Couldn't set transform\n");
+ if (error)
return;
- }
while (n--)
{
BoxRec dst_box;
- xf86RotateBox (&dst_box, b, crtc->rotation,
- crtc->mode.HDisplay, crtc->mode.VDisplay);
+ xf86TransformBox (&dst_box, b, crtc->rotation,
+ crtc->x, crtc->y,
+ crtc->mode.HDisplay, crtc->mode.VDisplay);
CompositePicture (PictOpSrc,
src, NULL, dst,
dst_box.x1, dst_box.y1, 0, 0, dst_box.x1, dst_box.y1,
@@ -234,6 +213,50 @@ xf86RotateCrtcRedisplay (xf86CrtcPtr crtc, RegionPtr region)
}
static void
+xf86CrtcDamageShadow (xf86CrtcPtr crtc)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ BoxRec damage_box;
+ RegionRec damage_region;
+ ScreenPtr pScreen = pScrn->pScreen;
+
+ damage_box.x1 = crtc->x;
+ damage_box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
+ damage_box.y1 = crtc->y;
+ damage_box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
+ REGION_INIT (pScreen, &damage_region, &damage_box, 1);
+ DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+ &damage_region);
+ REGION_UNINIT (pScreen, &damage_region);
+}
+
+static void
+xf86RotatePrepare (ScreenPtr pScreen)
+{
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int c;
+
+ for (c = 0; c < xf86_config->num_crtc; c++)
+ {
+ xf86CrtcPtr crtc = xf86_config->crtc[c];
+
+ if (crtc->rotatedData && !crtc->rotatedPixmap)
+ {
+ crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+ crtc->rotatedData,
+ crtc->mode.HDisplay,
+ crtc->mode.VDisplay);
+ /* Hook damage to screen pixmap */
+ DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
+ xf86_config->rotationDamage);
+
+ xf86CrtcDamageShadow (crtc);
+ }
+ }
+}
+
+static void
xf86RotateRedisplay(ScreenPtr pScreen)
{
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
@@ -243,6 +266,7 @@ xf86RotateRedisplay(ScreenPtr pScreen)
if (!damage)
return;
+ xf86RotatePrepare (pScreen);
region = DamageRegion(damage);
if (REGION_NOTEMPTY(pScreen, region))
{
@@ -259,9 +283,9 @@ xf86RotateRedisplay(ScreenPtr pScreen)
/* compute portion of damage that overlaps crtc */
box.x1 = crtc->x;
- box.x2 = crtc->x + mode_width (&crtc->mode, crtc->rotation);
+ box.x2 = crtc->x + xf86ModeWidth (&crtc->mode, crtc->rotation);
box.y1 = crtc->y;
- box.y2 = crtc->y + mode_height (&crtc->mode, crtc->rotation);
+ box.y2 = crtc->y + xf86ModeHeight (&crtc->mode, crtc->rotation);
REGION_INIT(pScreen, &crtc_damage, &box, 1);
REGION_INTERSECT (pScreen, &crtc_damage, &crtc_damage, region);
@@ -299,10 +323,11 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
if (rotation == RR_Rotate_0)
{
/* Free memory from rotation */
- if (crtc->rotatedPixmap)
+ if (crtc->rotatedPixmap || crtc->rotatedData)
{
- crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap);
+ crtc->funcs->shadow_destroy (crtc, crtc->rotatedPixmap, crtc->rotatedData);
crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
}
if (xf86_config->rotationDamage)
@@ -327,24 +352,30 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
*/
int width = mode->HDisplay;
int height = mode->VDisplay;
+ void *shadowData = crtc->rotatedData;
PixmapPtr shadow = crtc->rotatedPixmap;
int old_width = shadow ? shadow->drawable.width : 0;
int old_height = shadow ? shadow->drawable.height : 0;
- BoxRec damage_box;
- RegionRec damage_region;
/* Allocate memory for rotation */
if (old_width != width || old_height != height)
{
- if (shadow)
+ if (shadow || shadowData)
{
- crtc->funcs->shadow_destroy (crtc, shadow);
+ crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
}
- shadow = crtc->funcs->shadow_create (crtc, width, height);
- if (!shadow)
+ shadowData = crtc->funcs->shadow_allocate (crtc, width, height);
+ if (!shadowData)
goto bail1;
- crtc->rotatedPixmap = shadow;
+ crtc->rotatedData = shadowData;
+ /* shadow will be damaged in xf86RotatePrepare */
+ }
+ else
+ {
+ /* mark shadowed area as damaged so it will be repainted */
+ xf86CrtcDamageShadow (crtc);
}
if (!xf86_config->rotationDamage)
@@ -356,10 +387,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
if (!xf86_config->rotationDamage)
goto bail2;
- /* Hook damage to screen pixmap */
- DamageRegister (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
- xf86_config->rotationDamage);
-
/* Assign block/wakeup handler */
if (!RegisterBlockAndWakeupHandlers (xf86RotateBlockHandler,
xf86RotateWakeupHandler,
@@ -367,14 +394,6 @@ xf86CrtcRotate (xf86CrtcPtr crtc, DisplayModePtr mode, Rotation rotation)
{
goto bail3;
}
- damage_box.x1 = 0;
- damage_box.y1 = 0;
- damage_box.x2 = mode_width (mode, rotation);
- damage_box.y2 = mode_height (mode, rotation);
- REGION_INIT (pScreen, &damage_region, &damage_box, 1);
- DamageDamageRegion (&(*pScreen->GetScreenPixmap)(pScreen)->drawable,
- &damage_region);
- REGION_UNINIT (pScreen, &damage_region);
}
if (0)
{
@@ -383,14 +402,16 @@ bail3:
xf86_config->rotationDamage = NULL;
bail2:
- if (shadow)
+ if (shadow || shadowData)
{
- crtc->funcs->shadow_destroy (crtc, shadow);
+ crtc->funcs->shadow_destroy (crtc, shadow, shadowData);
crtc->rotatedPixmap = NULL;
+ crtc->rotatedData = NULL;
}
bail1:
if (old_width && old_height)
crtc->rotatedPixmap = crtc->funcs->shadow_create (crtc,
+ NULL,
old_width,
old_height);
return FALSE;