summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2012-09-30 18:21:59 +0200
committerRob Clark <rob@ti.com>2012-09-30 18:21:59 +0200
commit64a970788e0b95e1a0ce005ad050f00891c8bab8 (patch)
tree5f1099a16204ec57bce7640d3f10c2d9b8ad4772
parent6ea931ea247e1f6ab159e180e7bbf11bf2d3f58f (diff)
fix multi-display + rotation
If the fb is reallocated due to rotated CRTC in drmmode_set_mode_major() then we need to reconfigure the CRTCs that are torn down by the kernel when the previous fb was destroyed. Signed-off-by: Rob Clark <rob@ti.com>
-rw-r--r--src/drmmode_display.c213
-rw-r--r--src/omap_driver.c2
-rw-r--r--src/omap_driver.h5
3 files changed, 122 insertions, 98 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 8a5506f..3deb952 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -250,59 +250,18 @@ drmmode_set_rotation(xf86CrtcPtr crtc, Rotation rotation)
}
static Bool
-drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
- Rotation rotation, int x, int y)
+drmmode_restore_crtc(xf86CrtcPtr crtc)
{
ScrnInfoPtr pScrn = crtc->scrn;
OMAPPtr pOMAP = OMAPPTR(pScrn);
xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn);
drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
drmmode_ptr drmmode = drmmode_crtc->drmmode;
- int saved_x, saved_y;
- Rotation saved_rotation;
- DisplayModeRec saved_mode;
uint32_t *output_ids = NULL;
int output_count = 0;
int ret = TRUE;
int i;
- int fb_id;
drmModeModeInfo kmode;
- Bool was_rotated = drmmode->rotated_crtcs > 0;
-
- TRACE_ENTER();
-
- /* update the count of number of rotated CRTCs.. if we have one or more
- * rotated outputs then we want to use a tiled buffer, but otherwise
- * stick with non-tiled
- */
- if ((drmmode_crtc->rotation != RR_Rotate_0) &&
- (rotation == RR_Rotate_0)) {
- DEBUG_MSG("disabling rotation for crtc: %u",
- drmmode_crtc->mode_crtc->crtc_id);
- drmmode->rotated_crtcs--;
- } else if ((drmmode_crtc->rotation == RR_Rotate_0) &&
- (rotation != RR_Rotate_0)) {
- DEBUG_MSG("enabling rotation for crtc: %u",
- drmmode_crtc->mode_crtc->crtc_id);
- drmmode->rotated_crtcs++;
- }
-
- drmmode_crtc->rotation = rotation;
-
- /* at this point, if we are switching from unrotated to rotated
- * or visa versa, then we need to reallocate the scanout buffer..
- */
- if (was_rotated != (drmmode->rotated_crtcs > 0)) {
- /* reallocate scanout buffer.. */
- drmmode_reallocate_scanout(pScrn, TRUE);
- }
-
- /* note: this needs to be done before setting the mode, otherwise
- * drm core will reject connecting the fb to crtc due to mismatched
- * dimensions:
- */
- if (!drmmode_set_rotation(crtc, rotation))
- goto done;
if (drmmode->fb_id == 0) {
unsigned int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
@@ -316,29 +275,15 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
pitch, omap_bo_handle(pOMAP->scanout),
&drmmode->fb_id);
if (ret < 0) {
- // Fixme - improve this error message:
- ErrorF("failed to add fb\n");
+ ERROR_MSG("failed to add fb: %s", strerror(errno));
return FALSE;
}
}
- /* Save the current mode in case there's a problem: */
- saved_mode = crtc->mode;
- saved_x = crtc->x;
- saved_y = crtc->y;
- saved_rotation = crtc->rotation;
-
- /* Set the new mode: */
- crtc->mode = *mode;
- crtc->x = x;
- crtc->y = y;
- crtc->rotation = rotation;
-
output_ids = calloc(sizeof(uint32_t), xf86_config->num_output);
if (!output_ids) {
- // Fixme - have an error message?
- ret = FALSE;
- goto done;
+ ERROR_MSG("allocation failed");
+ return FALSE;
}
for (i = 0; i < xf86_config->num_output; i++) {
@@ -354,26 +299,18 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
output_count++;
}
- // Fixme - Intel puts this function here, and Nouveau puts it at the end
- // of this function -> determine what's best for TI'S OMAP4:
- crtc->funcs->gamma_set(crtc, crtc->gamma_red, crtc->gamma_green,
- crtc->gamma_blue, crtc->gamma_size);
-
- drmmode_ConvertToKMode(crtc->scrn, &kmode, mode);
-
- fb_id = drmmode->fb_id;
+ drmmode_ConvertToKMode(crtc->scrn, &kmode, &crtc->mode);
ret = drmModeSetCrtc(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id,
- fb_id, x, y, output_ids, output_count, &kmode);
+ drmmode->fb_id, crtc->x, crtc->y,
+ output_ids, output_count, &kmode);
if (ret) {
- xf86DrvMsg(crtc->scrn->scrnIndex, X_ERROR,
- "failed to set mode: %s\n", strerror(-ret));
+ ERROR_MSG("failed to set mode: %s", strerror(-ret));
+ ret = FALSE;
} else {
ret = TRUE;
}
- // FIXME - DO WE NEED TO CALL TO THE PVR EXA/DRI2 CODE TO UPDATE THEM???
-
/* Turn on any outputs on this crtc that may have been disabled: */
for (i = 0; i < xf86_config->num_output; i++) {
xf86OutputPtr output = xf86_config->output[i];
@@ -384,15 +321,77 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
drmmode_output_dpms(output, DPMSModeOn);
}
- // TODO: only call this if we are not using sw cursor.. ie. bad to call this
- // if we haven't called xf86InitCursor()!!
- // if (pScrn->pScreen)
- // xf86_reload_cursors(pScrn->pScreen);
-
-done:
if (output_ids) {
free(output_ids);
}
+
+ return ret;
+}
+
+static Bool
+drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
+ Rotation rotation, int x, int y)
+{
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+ drmmode_ptr drmmode = drmmode_crtc->drmmode;
+ int saved_x, saved_y;
+ Rotation saved_rotation;
+ DisplayModeRec saved_mode;
+ int ret = TRUE;
+ Bool was_rotated = drmmode->rotated_crtcs > 0;
+
+ TRACE_ENTER();
+
+ /* update the count of number of rotated CRTCs.. if we have one or more
+ * rotated outputs then we want to use a tiled buffer, but otherwise
+ * stick with non-tiled
+ */
+ if ((drmmode_crtc->rotation != RR_Rotate_0) &&
+ (rotation == RR_Rotate_0)) {
+ DEBUG_MSG("disabling rotation for crtc: %u",
+ drmmode_crtc->mode_crtc->crtc_id);
+ drmmode->rotated_crtcs--;
+ } else if ((drmmode_crtc->rotation == RR_Rotate_0) &&
+ (rotation != RR_Rotate_0)) {
+ DEBUG_MSG("enabling rotation for crtc: %u",
+ drmmode_crtc->mode_crtc->crtc_id);
+ drmmode->rotated_crtcs++;
+ }
+
+ drmmode_crtc->rotation = rotation;
+
+ /* at this point, if we are switching from unrotated to rotated
+ * or visa versa, then we need to reallocate the scanout buffer..
+ */
+ if (was_rotated != (drmmode->rotated_crtcs > 0)) {
+ /* reallocate scanout buffer.. */
+ drmmode_reallocate_scanout(pScrn, TRUE, crtc);
+ }
+
+ /* note: this needs to be done before setting the mode, otherwise
+ * drm core will reject connecting the fb to crtc due to mismatched
+ * dimensions:
+ */
+ if (!drmmode_set_rotation(crtc, rotation)) {
+ ERROR_MSG("could not set rotation");
+ return FALSE;
+ }
+
+ /* Save the current mode in case there's a problem: */
+ saved_mode = crtc->mode;
+ saved_x = crtc->x;
+ saved_y = crtc->y;
+ saved_rotation = crtc->rotation;
+
+ /* Set the new mode: */
+ crtc->mode = *mode;
+ crtc->x = x;
+ crtc->y = y;
+ crtc->rotation = rotation;
+
+ ret = drmmode_restore_crtc(crtc);
+
if (!ret) {
/* If there was a problem, restore the old mode: */
crtc->x = saved_x;
@@ -1111,37 +1110,26 @@ drmmode_is_rotated(ScrnInfoPtr pScrn)
}
Bool
-drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
+drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw, xf86CrtcPtr crtc)
{
OMAPPtr pOMAP = OMAPPTR(pScrn);
ScreenPtr pScreen = pScrn->pScreen;
- Bool changed = FALSE;
- uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
int width = pScrn->virtualX;
int height = pScrn->virtualY;
- unsigned int pitch;
Bool rotate = drmmode_is_rotated(pScrn);
+ unsigned int pitch;
if (rotate) {
- /* if we are using tiled buffers, we really should check if
- * width/height has changed, rather than size.. for now, just
- * always re-alloc:
- */
- changed = TRUE;
pitch = OMAPCalculateTiledStride(width, pScrn->bitsPerPixel);
} else {
pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel);
}
- if (pOMAP->scanout) {
- if ((pitch * height) != omap_bo_size(pOMAP->scanout)) {
- changed = TRUE;
- }
- } else {
- changed = TRUE;
- }
+ if ((width != pOMAP->scanout_w) ||
+ (height != pOMAP->scanout_h) ||
+ (rotate != pOMAP->scanout_rotate)) {
+ uint32_t flags = OMAP_BO_SCANOUT | OMAP_BO_WC;
- if (changed) {
/* remove old fb if it exists */
drmmode_remove_fb(pScrn);
@@ -1169,6 +1157,10 @@ drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
return FALSE;
}
+ pOMAP->scanout_w = width;
+ pOMAP->scanout_h = height;
+ pOMAP->scanout_rotate = rotate;
+
pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
if (pScreen && pScreen->ModifyPixmapHeader) {
@@ -1181,6 +1173,35 @@ drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
if (pScreen && pScrn->EnableDisableFBAccess && redraw)
pScrn->EnableDisableFBAccess(ENABLE_DISABLE_FB_ACCESS_ARGS(pScrn, TRUE));
+
+ /* if reallocation triggered by a mode-set, we need to reconfigure any
+ * other crtc's which have just been torn down by destroying the old fb:
+ */
+ if (crtc) {
+ xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(pScrn);
+ int i;
+ DEBUG_MSG("restoring CRTCs");
+ for (i = 0; i < config->num_crtc; i++) {
+ if (config->crtc[i] != crtc) {
+ int ret;
+ DEBUG_MSG("restore CRTC %d", i);
+ ret = drmmode_restore_crtc(config->crtc[i]);
+ if (!ret) {
+ ERROR_MSG("failed to reconfig crtc %d", i);
+ /* hmm, I guess just keep trying the rest? */
+ }
+ }
+ }
+ }
+ } else {
+
+ if (pScreen && pScreen->ModifyPixmapHeader) {
+ PixmapPtr rootPixmap = pScreen->GetScreenPixmap(pScreen);
+ pScreen->ModifyPixmapHeader(rootPixmap,
+ pScrn->virtualX, pScrn->virtualY,
+ pScrn->depth, pScrn->bitsPerPixel, pitch,
+ omap_bo_map(pOMAP->scanout));
+ }
}
return TRUE;
@@ -1194,7 +1215,7 @@ drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
pScrn->virtualX = width;
pScrn->virtualY = height;
- if (!drmmode_reallocate_scanout(pScrn, FALSE))
+ if (!drmmode_reallocate_scanout(pScrn, FALSE, NULL))
return FALSE;
return TRUE;
diff --git a/src/omap_driver.c b/src/omap_driver.c
index 983d24c..96ab937 100644
--- a/src/omap_driver.c
+++ b/src/omap_driver.c
@@ -217,7 +217,7 @@ OMAPTiledFlags(unsigned int bitsPerPixel)
static Bool
OMAPMapMem(ScrnInfoPtr pScrn)
{
- return drmmode_reallocate_scanout(pScrn, FALSE);
+ return drmmode_reallocate_scanout(pScrn, FALSE, NULL);
}
diff --git a/src/omap_driver.h b/src/omap_driver.h
index 7bfedc0..f3f0450 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -150,6 +150,8 @@ typedef struct _OMAPRec
/** Scan-out buffer. */
struct omap_bo *scanout;
+ int scanout_w, scanout_h;
+ Bool scanout_rotate;
/** Pointer to the options for this screen. */
OptionInfoPtr pOptionInfo;
@@ -240,7 +242,8 @@ Bool drmmode_page_flip(DrawablePtr pDraw, PixmapPtr back, void *priv);
void drmmode_wait_for_event(ScrnInfoPtr pScrn);
Bool drmmode_cursor_init(ScreenPtr pScreen);
Bool drmmode_is_rotated(ScrnInfoPtr pScrn);
-Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw);
+Bool drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw,
+ xf86CrtcPtr crtc);
/**