summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Clark <rob@ti.com>2012-03-08 15:47:24 -0600
committerRob Clark <rob@ti.com>2012-08-23 14:37:53 -0500
commit8c19eee2ebe41e8d6c79ae88edbca1d590f451dc (patch)
tree3a82fb6ea82c803029ec35f30ed8275e89bf16e1
parent8bb109f8b021a93cdabc44cd16777201ad3690cd (diff)
xrandr rotation
If XF86_CRTC_VERSION >= 4, on platforms with dmm/tiler (OMAP4+), use tiled buffers for scanout buffer to enable rotatated and/or mirrored scanout. This utilizes the RFC crtc/plane properties support to configure rotation. Tiled buffers are only used if rotation is enabled. Signed-off-by: Rob Clark <rob@ti.com>
-rw-r--r--configure.ac2
-rw-r--r--src/drmmode_display.c208
-rw-r--r--src/omap_dri2.c18
-rw-r--r--src/omap_driver.c40
-rw-r--r--src/omap_driver.h13
-rw-r--r--src/omap_exa.c2
-rw-r--r--src/omap_exa.h8
7 files changed, 229 insertions, 62 deletions
diff --git a/configure.ac b/configure.ac
index 14052e3..50e33e4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -44,7 +44,7 @@ XORG_DRIVER_CHECK_EXT(XV, videoproto)
XORG_DRIVER_CHECK_EXT(DPMSExtension, xextproto)
# Checks for pkg-config packages
-PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3] xproto fontsproto libdrm libdrm_omap xf86driproto $REQUIRED_MODULES)
+PKG_CHECK_MODULES(XORG, [xorg-server >= 1.3] xproto fontsproto [libdrm >= 2.4.36] libdrm_omap xf86driproto $REQUIRED_MODULES)
sdkdir=$(pkg-config --variable=sdkdir xorg-server)
# Checks for header files.
diff --git a/src/drmmode_display.c b/src/drmmode_display.c
index 473cfa7..901782d 100644
--- a/src/drmmode_display.c
+++ b/src/drmmode_display.c
@@ -84,6 +84,7 @@
#endif
#include "omap_driver.h"
+#include "omap_drm.h"
#include "xf86Crtc.h"
@@ -111,11 +112,16 @@ typedef struct {
struct udev_monitor *uevent_monitor;
InputHandlerProc uevent_handler;
drmmode_cursor_ptr cursor;
+ int rotated_crtcs;
} drmmode_rec, *drmmode_ptr;
typedef struct {
drmmode_ptr drmmode;
drmModeCrtcPtr mode_crtc;
+ Rotation rotation;
+
+ /* properties that we care about: */
+ uint32_t prop_rotation;
} drmmode_crtc_private_rec, *drmmode_crtc_private_ptr;
typedef struct {
@@ -215,6 +221,34 @@ drmmode_crtc_dpms(xf86CrtcPtr drmmode_crtc, int mode)
// FIXME - Implement this function
}
+#define SUPPORTED_ROTATIONS (RR_Rotate_0 | RR_Rotate_90 | RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y)
+
+static Bool
+drmmode_set_rotation(xf86CrtcPtr crtc, Rotation rotation)
+{
+#if XF86_CRTC_VERSION >= 4
+ ScrnInfoPtr pScrn = crtc->scrn;
+ drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private;
+
+ if (!(rotation & ~SUPPORTED_ROTATIONS)) {
+ int ret;
+
+ ret = drmModeObjectSetProperty(drmmode_crtc->drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id,
+ DRM_MODE_OBJECT_CRTC,
+ drmmode_crtc->prop_rotation,
+ rotation);
+ if (ret) {
+ ERROR_MSG("failed to set orientation %s", strerror(errno));
+ return FALSE;
+ }
+
+ crtc->driverIsPerformingTransform = TRUE;
+ }
+#endif
+ return xf86CrtcRotate(crtc);
+}
+
static Bool
drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
Rotation rotation, int x, int y)
@@ -233,15 +267,48 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
int i;
int fb_id;
drmModeModeInfo kmode;
+ Bool was_rotated = drmmode->rotated_crtcs > 0;
TRACE_ENTER();
/* remove old fb if it exists */
drmmode_remove_fb(pScrn);
+ /* 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 =
- OMAPCalculateStride(pScrn->virtualX, pScrn->bitsPerPixel);
+ unsigned int pitch = pScrn->displayWidth * (pScrn->bitsPerPixel / 8);
DEBUG_MSG("create framebuffer: %dx%d",
pScrn->virtualX, pScrn->virtualY);
@@ -290,9 +357,6 @@ drmmode_set_mode_major(xf86CrtcPtr crtc, DisplayModePtr mode,
output_count++;
}
- if (!xf86CrtcRotate(crtc))
- goto done;
-
// 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,
@@ -333,7 +397,7 @@ done:
free(output_ids);
}
if (!ret) {
- /* If there was a problem, resture the old mode: */
+ /* If there was a problem, restore the old mode: */
crtc->x = saved_x;
crtc->y = saved_y;
crtc->rotation = saved_rotation;
@@ -405,6 +469,15 @@ drmmode_show_cursor(xf86CrtcPtr crtc)
h = crtc->mode.VDisplay - crtc_y;
}
+#if XF86_CRTC_VERSION >= 4
+ /* NOTE: driver is taking care of rotation in hw, which means
+ * we need to deal w/ transformation of mouse cursor ourself:
+ */
+ if (crtc->driverIsPerformingTransform) {
+ xf86CrtcTransformCursorPos(crtc, &crtc_x, &crtc_y);
+ }
+#endif
+
/* note src coords (last 4 args) are in Q16 format */
drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id,
drmmode_crtc->mode_crtc->crtc_id, cursor->fb_id, 0,
@@ -550,6 +623,7 @@ static const xf86CrtcFuncsRec drmmode_crtc_funcs = {
static void
drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
{
+ drmModeObjectPropertiesPtr props;
xf86CrtcPtr crtc;
drmmode_crtc_private_ptr drmmode_crtc;
@@ -563,8 +637,23 @@ drmmode_crtc_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
drmmode_crtc->mode_crtc = drmModeGetCrtc(drmmode->fd,
drmmode->mode_res->crtcs[num]);
drmmode_crtc->drmmode = drmmode;
-
- // FIXME - potentially add code to allocate a HW cursor here.
+ drmmode_crtc->rotation = RR_Rotate_0;
+
+ /* find properties that we care about: */
+ props = drmModeObjectGetProperties(drmmode->fd,
+ drmmode_crtc->mode_crtc->crtc_id, DRM_MODE_OBJECT_CRTC);
+ if (props) {
+ drmModePropertyPtr prop;
+ int i;
+ for (i = 0; i < props->count_props; i++) {
+ prop = drmModeGetProperty(drmmode->fd, props->props[i]);
+ if (!strcmp(prop->name, "rotation")) {
+ drmmode_crtc->prop_rotation = prop->prop_id;
+ }
+ drmModeFreeProperty(prop);
+ }
+ drmModeFreeObjectProperties(props);
+ }
crtc->driver_private = drmmode_crtc;
@@ -1016,55 +1105,98 @@ drmmode_output_init(ScrnInfoPtr pScrn, drmmode_ptr drmmode, int num)
return;
}
-static Bool
-drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+Bool
+drmmode_is_rotated(ScrnInfoPtr pScrn)
+{
+ OMAPPtr pOMAP = OMAPPTR(pScrn);
+ drmmode_ptr drmmode = drmmode_from_scrn(pScrn);
+ return has_rotation(pOMAP) && drmmode->rotated_crtcs > 0;
+}
+
+Bool
+drmmode_reallocate_scanout(ScrnInfoPtr pScrn, Bool redraw)
{
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);
- TRACE_ENTER();
-
- /* if fb required size has changed, realloc! */
-
- DEBUG_MSG("Resize! %dx%d", width, height);
-
- pScrn->virtualX = width;
- pScrn->virtualY = height;
+ 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);
+ }
- pitch = OMAPCalculateStride(width, pScrn->bitsPerPixel);
+ if (pOMAP->scanout) {
+ if ((pitch * height) != omap_bo_size(pOMAP->scanout)) {
+ changed = TRUE;
+ }
+ } else {
+ changed = TRUE;
+ }
- if ((pitch * height) != omap_bo_size(pOMAP->scanout)) {
- /* hmm, should we remove fb here.. we don't want to keep
- * scanning out a deallocated buffer..
- */
- drmmode_remove_fb(pScrn);
+ if (changed) {
+ if (pScreen && pScrn->EnableDisableFBAccess && redraw)
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, FALSE);
/* delete old scanout buffer */
omap_bo_del(pOMAP->scanout);
- DEBUG_MSG("allocating new scanout buffer: %dx%d (%d)",
- width, height, pitch);
+ if (rotate) {
+ DEBUG_MSG("allocating tiled scanout buffer: %dx%d (%d)",
+ width, height, pitch);
+ flags |= OMAPTiledFlags(pScrn->bitsPerPixel);
+ pOMAP->scanout = omap_bo_new_tiled(pOMAP->dev,
+ width, height, flags);
+ } else {
+ DEBUG_MSG("allocating linear scanout buffer: %dx%d (%d)",
+ width, height, pitch);
+ pOMAP->scanout = omap_bo_new(pOMAP->dev, height * pitch, flags);
+ }
- /* allocate new scanout buffer */
- pOMAP->scanout = omap_bo_new(pOMAP->dev, height * pitch,
- OMAP_BO_SCANOUT | OMAP_BO_WC);
if (!pOMAP->scanout) {
xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
"Error reallocating scanout buffer\n");
return FALSE;
}
- }
- 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));
+ pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
+
+ 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));
+ }
+
+ if (pScreen && pScrn->EnableDisableFBAccess && redraw)
+ pScrn->EnableDisableFBAccess(pScrn->scrnIndex, TRUE);
}
- TRACE_EXIT();
+ return TRUE;
+}
+
+static Bool
+drmmode_xf86crtc_resize(ScrnInfoPtr pScrn, int width, int height)
+{
+ DEBUG_MSG("Resize! %dx%d", width, height);
+
+ pScrn->virtualX = width;
+ pScrn->virtualY = height;
+
+ if (!drmmode_reallocate_scanout(pScrn, FALSE))
+ return FALSE;
+
return TRUE;
}
@@ -1338,6 +1470,8 @@ drmmode_wakeup_handler(pointer data, int err, pointer p)
if (pScrn == NULL || err < 0)
return;
+ drmmode = drmmode_from_scrn(pScrn);
+
if (FD_ISSET(drmmode->fd, read_mask))
drmHandleEvent(drmmode->fd, &event_context);
}
diff --git a/src/omap_dri2.c b/src/omap_dri2.c
index 53db098..6c90f27 100644
--- a/src/omap_dri2.c
+++ b/src/omap_dri2.c
@@ -195,10 +195,15 @@ exchangebufs(DrawablePtr pDraw, DRI2BufferPtr a, DRI2BufferPtr b)
}
static PixmapPtr
-createpix(DrawablePtr pDraw)
+createpix(DrawablePtr pDraw, Bool scanout)
{
ScreenPtr pScreen = pDraw->pScreen;
- int flags = canflip(pDraw) ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
+ int flags = scanout ? OMAP_CREATE_PIXMAP_SCANOUT : 0;
+ if (scanout) {
+ ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
+ Bool rotated = drmmode_is_rotated(pScrn);
+ flags |= rotated ? OMAP_CREATE_PIXMAP_TILED : 0;
+ }
return pScreen->CreatePixmap(pScreen,
pDraw->width, pDraw->height, pDraw->depth, flags);
}
@@ -248,7 +253,7 @@ OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
(OMAPPixmapBo(pPixmap) != pOMAP->scanout)) {
/* need to re-allocate pixmap to get a scanout capable buffer */
- PixmapPtr pNewPix = createpix(pDraw);
+ PixmapPtr pNewPix = createpix(pDraw, TRUE);
// TODO copy contents..
@@ -259,7 +264,7 @@ OMAPDRI2CreateBuffer(DrawablePtr pDraw, unsigned int attachment,
pPixmap->refcnt++;
} else {
- pPixmap = createpix(pDraw);
+ pPixmap = createpix(pDraw, canflip(pDraw));
}
bo = OMAPPixmapBo(pPixmap);
@@ -426,9 +431,12 @@ OMAPDRI2SwapDispatch(DrawablePtr pDraw, OMAPDRISwapCmd *cmd)
ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
OMAPDRI2DrawablePtr pPriv = OMAPDRI2GetDrawable(pDraw);
OMAPDRI2BufferPtr src = OMAPBUF(cmd->pSrcBuffer);
+ Bool ok_to_flip = drmmode_is_rotated(pScrn) ?
+ OMAPPixmapTiled(src->pPixmap) : TRUE;
/* if we can flip, do so: */
- if (canflip(pDraw) && drmmode_page_flip(pDraw, src->pPixmap, cmd)) {
+ if (ok_to_flip && canflip(pDraw) &&
+ drmmode_page_flip(pDraw, src->pPixmap, cmd)) {
OMAPPTR(pScrn)->pending_page_flips++;
cmd->type = DRI2_FLIP_COMPLETE;
} else if (canexchange(pDraw, cmd->pSrcBuffer, cmd->pDstBuffer)) {
diff --git a/src/omap_driver.c b/src/omap_driver.c
index 178a4cd..86862bc 100644
--- a/src/omap_driver.c
+++ b/src/omap_driver.c
@@ -196,29 +196,21 @@ OMAPCalculateTiledStride(unsigned int width, unsigned int bitsPerPixel)
return stride;
}
+unsigned int
+OMAPTiledFlags(unsigned int bitsPerPixel)
+{
+ switch(bitsPerPixel) {
+ case 32: return OMAP_BO_TILED_32;
+ case 16: return OMAP_BO_TILED_16;
+ case 8: return OMAP_BO_TILED_8;
+ default: return 0;
+ }
+}
static Bool
OMAPMapMem(ScrnInfoPtr pScrn)
{
- OMAPPtr pOMAP = OMAPPTR(pScrn);
- int pitch;
-
- pitch = OMAPCalculateStride(pScrn->virtualX, pScrn->bitsPerPixel);
-
- DEBUG_MSG("allocating new scanout buffer: %dx%d (%d)",
- pScrn->virtualX, pScrn->virtualY, pitch);
-
- pOMAP->scanout = omap_bo_new(pOMAP->dev, pScrn->virtualY * pitch,
- OMAP_BO_SCANOUT | OMAP_BO_WC);
- if (!pOMAP->scanout) {
- xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
- "Error allocating scanout buffer\n");
- return FALSE;
- }
-
- pScrn->displayWidth = pitch / (pScrn->bitsPerPixel / 8);
-
- return TRUE;
+ return drmmode_reallocate_scanout(pScrn, FALSE);
}
@@ -816,6 +808,16 @@ OMAPScreenInit(SCREEN_INIT_ARGS_DECL)
goto fail;
}
+ if (has_rotation(pOMAP)) {
+ xf86RandR12SetRotations(pScreen, RR_Rotate_0 | RR_Rotate_90 |
+ RR_Rotate_180 | RR_Rotate_270 | RR_Reflect_X | RR_Reflect_Y);
+ } else {
+#if XF86_CRTC_VERSION < 4
+ WARNING_MSG("rotation not supported by XF86_CRTC_VERSION version: %d",
+ XF86_CRTC_VERSION);
+#endif
+ }
+
if (!miCreateDefColormap(pScreen)) {
ERROR_MSG("Cannot create colormap!");
goto fail;
diff --git a/src/omap_driver.h b/src/omap_driver.h
index b1a98af..aa639fc 100644
--- a/src/omap_driver.h
+++ b/src/omap_driver.h
@@ -116,6 +116,7 @@ extern unsigned int
OMAPCalculateStride(unsigned int fbWidth, unsigned int bitsPerPixel);
extern unsigned int
OMAPCalculateTiledStride(unsigned int width, unsigned int bitsPerPixel);
+unsigned int OMAPTiledFlags(unsigned int bitsPerPixel);
@@ -182,6 +183,16 @@ static inline Bool has_dmm(OMAPPtr pOMAP)
return pOMAP->chipset >= 0x4430;
}
+static inline Bool has_rotation(OMAPPtr pOMAP)
+{
+#if XF86_CRTC_VERSION >= 4
+ // TODO .. should somehow check if driver has rotation property..
+ return has_dmm(pOMAP);
+#else
+ return FALSE;
+#endif
+}
+
/** Return a pointer to the driver's private structure. */
#define OMAPPTR(p) ((OMAPPtr)((p)->driverPrivate))
#define OMAPPTR_FROM_SCREEN(pScreen) \
@@ -225,6 +236,8 @@ void drmmode_remove_fb(ScrnInfoPtr pScrn);
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);
/**
diff --git a/src/omap_exa.c b/src/omap_exa.c
index 15c396f..33844be 100644
--- a/src/omap_exa.c
+++ b/src/omap_exa.c
@@ -163,8 +163,10 @@ OMAPModifyPixmapHeader(PixmapPtr pPixmap, int width, int height,
omap_bo_del(priv->bo);
if (flags & OMAP_BO_TILED) {
priv->bo = omap_bo_new_tiled(pOMAP->dev, width, height, flags);
+ priv->tiled = TRUE;
} else {
priv->bo = omap_bo_new(pOMAP->dev, size, flags);
+ priv->tiled = FALSE;
}
}
diff --git a/src/omap_exa.h b/src/omap_exa.h
index acc86b8..94ac9cc 100644
--- a/src/omap_exa.h
+++ b/src/omap_exa.h
@@ -125,6 +125,7 @@ draw2pix(DrawablePtr pDraw)
typedef struct {
void *priv; /* EXA submodule private data */
struct omap_bo *bo;
+ Bool tiled;
} OMAPPixmapPrivRec, *OMAPPixmapPrivPtr;
#define OMAP_CREATE_PIXMAP_SCANOUT 0x80000000
@@ -150,6 +151,13 @@ OMAPPixmapBo(PixmapPtr pPixmap)
return priv->bo;
}
+static inline Bool
+OMAPPixmapTiled(PixmapPtr pPixmap)
+{
+ OMAPPixmapPrivPtr priv = exaGetPixmapDriverPrivate(pPixmap);
+ return priv->tiled;
+}
+
void OMAPPixmapExchange(PixmapPtr a, PixmapPtr b);
#endif /* OMAP_EXA_COMMON_H_ */