Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size.
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/drm_ioctl.c | 12 ++++++++++++ include/drm/drm_crtc.h | 3 +++ include/uapi/drm/drm.h | 2 ++ 3 files changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index dffc836..f4dc9b7 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break; + case DRM_CAP_CURSOR_WIDTH: + if (dev->mode_config.cursor_width) + req->value = dev->mode_config.cursor_width; + else + req->value = 64; + break; + case DRM_CAP_CURSOR_HEIGHT: + if (dev->mode_config.cursor_height) + req->value = dev->mode_config.cursor_height; + else + req->value = 64; + break; default: return -EINVAL; } diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 71727b6..8f3dee0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -907,6 +907,9 @@ struct drm_mode_config {
/* whether async page flip is supported or not */ bool async_page_flip; + + /* cursor size */ + uint32_t cursor_width, cursor_height; };
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3c9a833..b06c8ed 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -619,6 +619,8 @@ struct drm_gem_open { #define DRM_PRIME_CAP_EXPORT 0x2 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9
/** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap {
CIK parts are 128x128, older parts are 64x64.
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- drivers/gpu/drm/radeon/radeon_display.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index d680608..fbd8b93 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c @@ -571,6 +571,8 @@ static void radeon_crtc_init(struct drm_device *dev, int index) radeon_crtc->max_cursor_width = CURSOR_WIDTH; radeon_crtc->max_cursor_height = CURSOR_HEIGHT; } + dev->mode_config.cursor_width = radeon_crtc->max_cursor_width; + dev->mode_config.cursor_height = radeon_crtc->max_cursor_height;
#if 0 radeon_crtc->mode_set.crtc = &radeon_crtc->base;
Use new drm caps. This allows hw cursors to work correctly on gpus with non-64x64 cursors.
Signed-off-by: Alex Deucher alexander.deucher@amd.com --- src/driver.c | 21 ++++++++++++++++++++- src/driver.h | 1 + src/drmmode_display.c | 20 +++++++++++++++----- 3 files changed, 36 insertions(+), 6 deletions(-)
diff --git a/src/driver.c b/src/driver.c index b84624e..b28622a 100644 --- a/src/driver.c +++ b/src/driver.c @@ -566,6 +566,14 @@ FreeRec(ScrnInfoPtr pScrn)
}
+#ifndef DRM_CAP_CURSOR_WIDTH +#define DRM_CAP_CURSOR_WIDTH 0x8 +#endif + +#ifndef DRM_CAP_CURSOR_HEIGHT +#define DRM_CAP_CURSOR_HEIGHT 0x9 +#endif + static Bool PreInit(ScrnInfoPtr pScrn, int flags) { @@ -706,6 +714,17 @@ PreInit(ScrnInfoPtr pScrn, int flags) prefer_shadow = !!value; }
+ ms->cursor_width = 64; + ms->cursor_height = 64; + ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_WIDTH, &value); + if (!ret) { + ms->cursor_width = value; + } + ret = drmGetCap(ms->fd, DRM_CAP_CURSOR_HEIGHT, &value); + if (!ret) { + ms->cursor_height = value; + } + ms->drmmode.shadow_enable = xf86ReturnOptValBool(ms->Options, OPTION_SHADOW_FB, prefer_shadow);
xf86DrvMsg(pScrn->scrnIndex, X_INFO, "ShadowFB: preferred %s, enabled %s\n", prefer_shadow ? "YES" : "NO", ms->drmmode.shadow_enable ? "YES" : "NO"); @@ -933,7 +952,7 @@ ScreenInit(SCREEN_INIT_ARGS_DECL)
/* Need to extend HWcursor support to handle mask interleave */ if (!ms->drmmode.sw_cursor) - xf86_cursors_init(pScreen, 64, 64, + xf86_cursors_init(pScreen, ms->cursor_width, ms->cursor_height, HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64 | HARDWARE_CURSOR_ARGB);
diff --git a/src/driver.h b/src/driver.h index 79561c8..e84d748 100644 --- a/src/driver.h +++ b/src/driver.h @@ -76,6 +76,7 @@ typedef struct _modesettingRec DamagePtr damage; Bool dirty_enabled;
+ uint32_t cursor_width, cursor_height; } modesettingRec, *modesettingPtr;
#define modesettingPTR(p) ((modesettingPtr)((p)->driverPrivate)) diff --git a/src/drmmode_display.c b/src/drmmode_display.c index 25641ce..ccfd75f 100644 --- a/src/drmmode_display.c +++ b/src/drmmode_display.c @@ -52,6 +52,8 @@ #endif #include "compat-api.h"
+#include "driver.h" + static struct dumb_bo *dumb_bo_create(int fd, const unsigned width, const unsigned height, const unsigned bpp) @@ -445,6 +447,7 @@ drmmode_set_cursor_position (xf86CrtcPtr crtc, int x, int y) static void drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) { + modesettingPtr ms = modesettingPTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; int i; uint32_t *ptr; @@ -453,10 +456,11 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) /* cursor should be mapped already */ ptr = (uint32_t *)(drmmode_crtc->cursor_bo->ptr);
- for (i = 0; i < 64 * 64; i++) + for (i = 0; i < ms->cursor_width * ms->cursor_height; i++) ptr[i] = image[i];// cpu_to_le32(image[i]);
- ret = drmModeSetCursor(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); + ret = drmModeSetCursor(drmmode_crtc->drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, + ms->cursor_width, ms->cursor_height); if (ret) { xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(crtc->scrn); xf86CursorInfoPtr cursor_info = xf86_config->cursor_info; @@ -471,21 +475,25 @@ drmmode_load_cursor_argb (xf86CrtcPtr crtc, CARD32 *image) static void drmmode_hide_cursor (xf86CrtcPtr crtc) { + modesettingPtr ms = modesettingPTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode;
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, 64, 64); + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, 0, + ms->cursor_width, ms->cursor_height);
}
static void drmmode_show_cursor (xf86CrtcPtr crtc) { + modesettingPtr ms = modesettingPTR(crtc->scrn); drmmode_crtc_private_ptr drmmode_crtc = crtc->driver_private; drmmode_ptr drmmode = drmmode_crtc->drmmode; uint32_t handle = drmmode_crtc->cursor_bo->handle;
- drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, 64, 64); + drmModeSetCursor(drmmode->fd, drmmode_crtc->mode_crtc->crtc_id, handle, + ms->cursor_width, ms->cursor_height); }
static void @@ -1485,6 +1493,7 @@ void drmmode_uevent_fini(ScrnInfoPtr scrn, drmmode_ptr drmmode) /* create front and cursor BOs */ Bool drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode) { + modesettingPtr ms = modesettingPTR(pScrn); xf86CrtcConfigPtr xf86_config = XF86_CRTC_CONFIG_PTR(pScrn); int width; int height; @@ -1500,7 +1509,8 @@ Bool drmmode_create_initial_bos(ScrnInfoPtr pScrn, drmmode_ptr drmmode) return FALSE; pScrn->displayWidth = drmmode->front_bo->pitch / cpp;
- width = height = 64; + width = ms->cursor_width; + height = ms->cursor_height; bpp = 32; for (i = 0; i < xf86_config->num_crtc; i++) { xf86CrtcPtr crtc = xf86_config->crtc[i];
On Mit, 2014-02-12 at 13:28 -0500, Alex Deucher wrote:
Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size.
The patches look good, but what's your plan for dealing with other KMS apps such as Wayland compositors (weston is also affected by this, I assume so is gnome-shell, maybe more)? I was thinking it might be good to have a backup plan in the kernel, e.g. copying from the BO passed in by userspace to a different BO if the former doesn't match the hardware size.
On Wed, Feb 12, 2014 at 8:37 PM, Michel Dänzer michel@daenzer.net wrote:
On Mit, 2014-02-12 at 13:28 -0500, Alex Deucher wrote:
Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size.
The patches look good, but what's your plan for dealing with other KMS apps such as Wayland compositors (weston is also affected by this, I assume so is gnome-shell, maybe more)? I was thinking it might be good to have a backup plan in the kernel, e.g. copying from the BO passed in by userspace to a different BO if the former doesn't match the hardware size.
I think the easiest fix would be for them to fix up support similarly to what I did for xf86-video-modesetting so they are ready to go once distros start enabling them by default. Adjusting the image on the fly in the kernel seems a like pain.
Alex
-- Earthling Michel Dänzer | http://www.amd.com Libre software enthusiast | Mesa and X developer
On Wed, Feb 12, 2014 at 1:28 PM, Alex Deucher alexdeucher@gmail.com wrote:
Some hardware may not support standard 64x64 cursors. Add a drm cap to query the cursor size from the kernel. Some examples include radeon CIK parts (128x128 cursors) and armada (32x64 or 64x32). This allows things like device specific ddxes to remove asics specific logic and also allows xf86-video-modesetting to work properly with hw cursors on this hardware. Default to 64 if the driver doesn't specify a size.
Signed-off-by: Alex Deucher alexander.deucher@amd.com
Reviewed-by: Rob Clark robdclark@gmail.com
drivers/gpu/drm/drm_ioctl.c | 12 ++++++++++++ include/drm/drm_crtc.h | 3 +++ include/uapi/drm/drm.h | 2 ++ 3 files changed, 17 insertions(+)
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index dffc836..f4dc9b7 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -296,6 +296,18 @@ int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv) case DRM_CAP_ASYNC_PAGE_FLIP: req->value = dev->mode_config.async_page_flip; break;
case DRM_CAP_CURSOR_WIDTH:
if (dev->mode_config.cursor_width)
req->value = dev->mode_config.cursor_width;
else
req->value = 64;
break;
case DRM_CAP_CURSOR_HEIGHT:
if (dev->mode_config.cursor_height)
req->value = dev->mode_config.cursor_height;
else
req->value = 64;
break; default: return -EINVAL; }
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h index 71727b6..8f3dee0 100644 --- a/include/drm/drm_crtc.h +++ b/include/drm/drm_crtc.h @@ -907,6 +907,9 @@ struct drm_mode_config {
/* whether async page flip is supported or not */ bool async_page_flip;
/* cursor size */
uint32_t cursor_width, cursor_height;
};
#define obj_to_crtc(x) container_of(x, struct drm_crtc, base) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 3c9a833..b06c8ed 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -619,6 +619,8 @@ struct drm_gem_open { #define DRM_PRIME_CAP_EXPORT 0x2 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +#define DRM_CAP_CURSOR_WIDTH 0x8 +#define DRM_CAP_CURSOR_HEIGHT 0x9
/** DRM_IOCTL_GET_CAP ioctl argument type */ struct drm_get_cap { -- 1.8.3.1
dri-devel mailing list dri-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/dri-devel
dri-devel@lists.freedesktop.org