diff options
author | Dave Airlie <airlied@linux.ie> | 2007-03-06 22:06:31 +1100 |
---|---|---|
committer | Dave Airlie <airlied@linux.ie> | 2007-03-06 22:06:31 +1100 |
commit | f608a523ec5dbade80f33fcc137c4584cc5e1ca2 (patch) | |
tree | 650a0d1e988c438125b1bcd8c7a68d5773d4250c | |
parent | 2cfbdb224ef5352dab42879d4047433b4ed680a0 (diff) | |
download | xorg-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.c | 14 | ||||
-rw-r--r-- | src/nv_driver.c | 16 | ||||
-rw-r--r-- | src/nv_output.c | 21 | ||||
-rw-r--r-- | src/nv_randr.c | 64 | ||||
-rw-r--r-- | src/nv_xf86Crtc.c | 455 | ||||
-rw-r--r-- | src/nv_xf86Crtc.h | 130 | ||||
-rw-r--r-- | src/nv_xf86Rotate.c | 185 |
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; |