diff options
author | Rob Clark <rob@ti.com> | 2012-01-08 19:33:18 -0600 |
---|---|---|
committer | Rob Clark <rob@ti.com> | 2012-01-13 11:23:36 -0600 |
commit | 687c60894626d138e6cd8c03b711d1985efd6837 (patch) | |
tree | 6d68b3e529702e441e484d7f5be0c7f8ca316d55 | |
parent | 74210d531f3c43291459babb9ac77afba4e1239c (diff) |
add HW cursor support using drm-plane
-rw-r--r-- | src/drmmode_display.c | 168 | ||||
-rw-r--r-- | src/omap_driver.c | 21 | ||||
-rw-r--r-- | src/omap_driver.h | 2 |
3 files changed, 157 insertions, 34 deletions
diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 4f50f65..0937cf0 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -88,18 +88,29 @@ #include "xf86Crtc.h" #include "xf86drmMode.h" +#include "drm_fourcc.h" #include "X11/Xatom.h" #include <sys/ioctl.h> #include <libudev.h> typedef struct { + /* hardware cursor: */ + drmModePlane *ovr; + struct omap_bo *bo; + uint32_t fb_id; + int x, y; + int visible; +} drmmode_cursor_rec, *drmmode_cursor_ptr; + +typedef struct { int fd; uint32_t fb_id; drmModeResPtr mode_res; int cpp; struct udev_monitor *uevent_monitor; InputHandlerProc uevent_handler; + drmmode_cursor_ptr cursor; } drmmode_rec, *drmmode_ptr; typedef struct { @@ -129,6 +140,16 @@ typedef struct { static void drmmode_output_dpms(xf86OutputPtr output, int mode); void drmmode_remove_fb(ScrnInfoPtr pScrn); +static drmmode_ptr +drmmode_from_scrn(ScrnInfoPtr pScrn) +{ + xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); + drmmode_crtc_private_ptr drmmode_crtc; + + drmmode_crtc = xf86_config->crtc[0]->driver_private; + return drmmode_crtc->drmmode; +} + static void drmmode_ConvertFromKMode(ScrnInfoPtr pScrn, drmModeModeInfo *kmode, DisplayModePtr mode) @@ -324,49 +345,146 @@ done: } static void -drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) +drmmode_hide_cursor(xf86CrtcPtr crtc) { -#if 0 // Fixme - address this function when we address HW cursor functionality drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; + drmmode_cursor_ptr cursor = drmmode->cursor; - drmModeMoveCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, x, y); -#endif + if (!cursor) + return; + + cursor->visible = FALSE; + + /* set plane's fb_id to 0 to disable it */ + drmModeSetPlane(drmmode->fd, cursor->ovr->plane_id, + drmmode_crtc->mode_crtc->crtc_id, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0); } static void -drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) +drmmode_show_cursor(xf86CrtcPtr crtc) { -#if 0 // Fixme - address this function when we address HW cursor functionality -#endif + drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; + drmmode_ptr drmmode = drmmode_crtc->drmmode; + drmmode_cursor_ptr cursor = drmmode->cursor; + + if (!cursor) + return; + + cursor->visible = TRUE; + + /* 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, + cursor->x, cursor->y, 64, 64, + 0, 0, 64<<16, 64<<16); } static void -drmmode_hide_cursor(xf86CrtcPtr crtc) +drmmode_set_cursor_position(xf86CrtcPtr crtc, int x, int y) { -#if 0 // Fixme - address this function when we address HW cursor functionality drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; + drmmode_cursor_ptr cursor = drmmode->cursor; - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - 0, 64, 64); - drmmode_crtc->cursor_visible = FALSE; -#endif + if (!cursor) + return; + + cursor->x = x; + cursor->y = y; + + if (cursor->visible) + drmmode_show_cursor(crtc); } static void -drmmode_show_cursor(xf86CrtcPtr crtc) +drmmode_load_cursor_argb(xf86CrtcPtr crtc, CARD32 *image) { -#if 0 // Fixme - address this function when we address HW cursor functionality drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; + drmmode_cursor_ptr cursor = drmmode->cursor; + + if (!cursor) + return; - // Fixme - Do we may need a different data structure for the cursor handle?: - drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, - drmmode_crtc->cursor->handle, 64, 64); + if (cursor->visible) + drmmode_hide_cursor(crtc); - drmmode_crtc->cursor_visible = TRUE; -#endif + memcpy(omap_bo_map(cursor->bo), image, omap_bo_size(cursor->bo)); + + if (cursor->visible) + drmmode_show_cursor(crtc); +} + +Bool +drmmode_cursor_init(ScreenPtr pScreen) +{ + ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; + OMAPPtr pOMAP = OMAPPTR(pScrn); + drmmode_ptr drmmode = drmmode_from_scrn(pScrn); + drmmode_cursor_ptr cursor; + drmModePlaneRes *plane_resources; + drmModePlane *ovr; + + /* technically we probably don't have any size limit.. since we + * are just using an overlay... but xserver will always create + * cursor images in the max size, so don't use width/height values + * that are too big + */ + int w = 64, h = 64; + uint32_t handles[4], pitches[4], offsets[4]; /* we only use [0] */ + + if (drmmode->cursor) { + INFO_MSG("cursor already initialized"); + return TRUE; + } + + cursor = calloc(1, sizeof(drmmode_cursor_rec)); + + /* find an unused plane which can be used as a mouse cursor. Note + * that we cheat a bit, in order to not burn one overlay per crtc, + * and only show the mouse cursor on one crtc at a time + */ + plane_resources = drmModeGetPlaneResources(drmmode->fd); + if (!plane_resources) { + ERROR_MSG("drmModeGetPlaneResources failed: %s", strerror(errno)); + return FALSE; + } + + if (plane_resources->count_planes < 1) { + ERROR_MSG("not enough planes for HW cursor"); + return FALSE; + } + + ovr = drmModeGetPlane(drmmode->fd, plane_resources->planes[0]); + if (!ovr) { + ERROR_MSG("drmModeGetPlane failed: %s\n", strerror(errno)); + return FALSE; + } + + cursor->ovr = ovr; + cursor->bo = omap_bo_new(pOMAP->dev, w*h*4, + OMAP_BO_SCANOUT | OMAP_BO_WC); + + handles[0] = omap_bo_handle(cursor->bo); + pitches[0] = w*4; + offsets[0] = 0; + + if (drmModeAddFB2(drmmode->fd, w, h, DRM_FORMAT_ARGB8888, + handles, pitches, offsets, &cursor->fb_id, 0)) { + ERROR_MSG("drmModeAddFB2 failed: %s", strerror(errno)); + return FALSE; + } + + if (xf86_cursors_init(pScreen, w, h, HARDWARE_CURSOR_ARGB)) { + INFO_MSG("HW cursor initialized"); + drmmode->cursor = cursor; + return TRUE; + } + + // TODO cleanup when things fail.. + return FALSE; } static void @@ -1049,16 +1167,6 @@ drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv) * Hot Plug Event handling: */ -static drmmode_ptr -drmmode_from_scrn(ScrnInfoPtr pScrn) -{ - xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); - drmmode_crtc_private_ptr drmmode_crtc; - - drmmode_crtc = xf86_config->crtc[0]->driver_private; - return drmmode_crtc->drmmode; -} - static void drmmode_handle_uevents(int fd, void *closure) { diff --git a/src/omap_driver.c b/src/omap_driver.c index 6bc1c28..34424ea 100644 --- a/src/omap_driver.c +++ b/src/omap_driver.c @@ -96,6 +96,7 @@ typedef enum { OPTION_DEBUG, OPTION_DRI, OPTION_NO_ACCEL, + OPTION_HW_CURSOR, /* TODO: probably need to add an option to let user specify bus-id */ } OMAPOpts; @@ -104,6 +105,7 @@ static const OptionInfoRec OMAPOptions[] = { { OPTION_DEBUG, "Debug", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_DRI, "DRI", OPTV_BOOLEAN, {0}, FALSE }, { OPTION_NO_ACCEL, "NoAccel", OPTV_BOOLEAN, {0}, FALSE }, + { OPTION_HW_CURSOR, "HWcursor", OPTV_BOOLEAN, {0}, FALSE }, { -1, NULL, OPTV_NONE, {0}, FALSE } }; @@ -544,10 +546,14 @@ OMAPPreInit(ScrnInfoPtr pScrn, int flags) pOMAP->dri = xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_DRI, TRUE); + /* Determine if user wants to disable hw mouse cursor: */ + pOMAP->HWCursor = xf86ReturnOptValBool(pOMAP->pOptionInfo, + OPTION_HW_CURSOR, TRUE); + INFO_MSG("Using %s cursor", pOMAP->HWCursor ? "HW" : "SW"); /* Determine if the user wants to disable acceleration: */ - pOMAP->NoAccel = - xf86ReturnOptValBool(pOMAP->pOptionInfo, OPTION_NO_ACCEL, FALSE); + pOMAP->NoAccel = xf86ReturnOptValBool(pOMAP->pOptionInfo, + OPTION_NO_ACCEL, FALSE); /* * Select the video modes: @@ -765,11 +771,18 @@ OMAPScreenInit(int scrnIndex, ScreenPtr pScreen, int argc, char **argv) miInitializeBackingStore(pScreen); xf86SetBackingStore(pScreen); + /* Cause the cursor position to be updated by the mouse signal handler: */ + xf86SetSilkenMouse(pScreen); + /* Initialize the cursor: */ miDCInitialize(pScreen, xf86GetPointerScreenFuncs()); - /* Cause the cursor position to be updated by the mouse signal handler: */ - xf86SetSilkenMouse(pScreen); + if (pOMAP->HWCursor) { + if (!drmmode_cursor_init(pScreen)) { + ERROR_MSG("Hardware cursor initialization failed"); + pOMAP->HWCursor = FALSE; + } + } /* XXX -- Is this the right place for this? The Intel i830 driver says: * "Must force it before EnterVT, so we are in control of VT..." diff --git a/src/omap_driver.h b/src/omap_driver.h index f9d7e9f..f4300d6 100644 --- a/src/omap_driver.h +++ b/src/omap_driver.h @@ -164,6 +164,7 @@ typedef struct _OMAPRec /** various user-configurable options: */ Bool dri; + Bool HWCursor; Bool NoAccel; /** File descriptor of the connection with the DRM. */ @@ -242,6 +243,7 @@ void drmmode_screen_fini(ScrnInfoPtr pScrn); void drmmode_adjust_frame(ScrnInfoPtr pScrn, int x, int y, int flags); void drmmode_remove_fb(ScrnInfoPtr pScrn); Bool drmmode_page_flip(DrawablePtr draw, uint32_t fb_id, void *priv); +Bool drmmode_cursor_init(ScreenPtr pScreen); /** |