From 135da294106f7158bb68eeeb9e6c171bcddd94f3 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 13 Feb 2014 11:58:15 +0000 Subject: [PATCH] sna: Extend native rotation support to sprites The sprite plane can be independently rotated to the CRTC primary plane. To rotate the sprite plane, we just set a property on the plane similar to how we rotate the CRTC, so we can refactor them together to use the same routines. Signed-off-by: Chris Wilson --- src/sna/sna.h | 3 +- src/sna/sna_display.c | 230 ++++++++++++++++++++++--------------- src/sna/sna_video_sprite.c | 14 ++- 3 files changed, 148 insertions(+), 99 deletions(-) diff --git a/src/sna/sna.h b/src/sna/sna.h index 78330953..7dc5067a 100644 --- a/src/sna/sna.h +++ b/src/sna/sna.h @@ -439,8 +439,9 @@ static inline void sna_dri_close(struct sna *sna, ScreenPtr pScreen) { } #endif void sna_dri_pixmap_update_bo(struct sna *sna, PixmapPtr pixmap); +extern bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation); extern int sna_crtc_to_pipe(xf86CrtcPtr crtc); -extern uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc); +extern uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc); extern uint32_t sna_crtc_id(xf86CrtcPtr crtc); CARD32 sna_format_for_depth(int depth); diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 5c0a5a3e..e123f482 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -93,22 +93,29 @@ union compat_mode_get_connector{ extern XF86ConfigPtr xf86configptr; +struct rotation { + uint32_t obj_id, obj_type; + uint32_t prop_id; + uint32_t supported; + uint32_t current; +}; + struct sna_crtc { struct drm_mode_modeinfo kmode; int dpms_mode; PixmapPtr scanout_pixmap; struct kgem_bo *bo, *shadow_bo; uint32_t cursor; + uint32_t sprite; bool shadow; bool fallback_shadow; bool transform; uint8_t id; uint8_t pipe; - uint8_t plane; - uint32_t rotation_id; - uint32_t supported_rotations; - uint32_t rotation, last_rotation; + uint32_t rotation; + struct rotation primary_rotation; + struct rotation sprite_rotation; }; struct sna_property { @@ -199,9 +206,9 @@ int sna_crtc_to_pipe(xf86CrtcPtr crtc) return to_sna_crtc(crtc)->pipe; } -uint32_t sna_crtc_to_plane(xf86CrtcPtr crtc) +uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc) { - return to_sna_crtc(crtc)->plane; + return to_sna_crtc(crtc)->sprite; } #ifndef NDEBUG @@ -861,6 +868,43 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc) to_sna_crtc(crtc)->dpms_mode = DPMSModeOff; } +static bool +rotation_set(struct sna *sna, struct rotation *r, uint32_t desired) +{ + if (desired == r->current) + return true; + + if ((desired & r->supported) == 0) + return false; + + DBG(("%s: obj=%d, type=%u set-rotation=%x\n", + __FUNCTION__, r->obj_id, r->obj_type, desired)); + + assert(r->obj_id); + assert(r->obj_type); + assert(r->prop_id); + + if (drmModeObjectSetProperty(sna->kgem.fd, + r->obj_id, r->obj_type, + r->prop_id, desired)) + return false; + + r->current = desired; + return true; +} + +bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation) +{ + DBG(("%s: CRTC:%d [pipe=%d], sprite=%u set-rotation=%x\n", + __FUNCTION__, + to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite, + rotation)); + + return rotation_set(to_sna(crtc->scrn), + &to_sna_crtc(crtc)->sprite_rotation, + rotation); +} + static bool sna_crtc_apply(xf86CrtcPtr crtc) { @@ -876,30 +920,13 @@ sna_crtc_apply(xf86CrtcPtr crtc) assert(config->num_output < ARRAY_SIZE(output_ids)); - if (sna_crtc->rotation != sna_crtc->last_rotation) { - assert(sna_crtc->rotation_id); - - DBG(("%s: disabling CRTC:%d [pipe=%d] before changing rotation from %x to %x\n", - __FUNCTION__, sna_crtc->id, sna_crtc->pipe, - sna_crtc->last_rotation, sna_crtc->rotation)); - - memset(&arg, 0, sizeof(arg)); - arg.crtc_id = sna_crtc->id; - (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg); - - if (drmModeObjectSetProperty(sna->kgem.fd, sna_crtc->id, - DRM_MODE_OBJECT_CRTC, - sna_crtc->rotation_id, - sna_crtc->rotation)) { - ERR(("%s: set-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n", - __FUNCTION__, sna_crtc->rotation_id, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno)); - return false; - } - - sna_crtc->last_rotation = sna_crtc->rotation; - DBG(("%s: CRTC:%d [pipe=%d] rotation set to %x\n", - __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->rotation)); + if (!rotation_set(sna, &sna_crtc->primary_rotation, sna_crtc->rotation)) { + ERR(("%s: set-primary-rotation failed (rotation-id=%d, rotation=%d) on CRTC:%d [pipe=%d], errno=%d\n", + __FUNCTION__, sna_crtc->primary_rotation.prop_id, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno)); + return false; } + DBG(("%s: CRTC:%d [pipe=%d] primary rotation set to %x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->rotation)); for (i = 0; i < config->num_output; i++) { xf86OutputPtr output = config->output[i]; @@ -1156,14 +1183,7 @@ sna_crtc_disable(xf86CrtcPtr crtc) arg.crtc_id = sna_crtc->id; (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETCRTC, &arg); - if (sna_crtc->last_rotation != RR_Rotate_0) { - assert(sna_crtc->rotation_id); - (void)drmModeObjectSetProperty(sna->kgem.fd, sna_crtc->id, - DRM_MODE_OBJECT_CRTC, - sna_crtc->rotation_id, - RR_Rotate_0); - sna_crtc->last_rotation = RR_Rotate_0; - } + rotation_set(sna, &sna_crtc->primary_rotation, RR_Rotate_0); sna_crtc_disable_shadow(sna, sna_crtc); @@ -1399,9 +1419,9 @@ static bool use_shadow(struct sna *sna, xf86CrtcPtr crtc) &f_fb_to_crtc)) { bool needs_transform = true; DBG(("%s: natively supported rotation? rotation=%x & supported=%x == %d\n", - __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->supported_rotations, - !!(crtc->rotation & to_sna_crtc(crtc)->supported_rotations))); - if (to_sna_crtc(crtc)->supported_rotations & crtc->rotation) + __FUNCTION__, crtc->rotation, to_sna_crtc(crtc)->primary_rotation.supported, + !!(crtc->rotation & to_sna_crtc(crtc)->primary_rotation.supported))); + if (to_sna_crtc(crtc)->primary_rotation.supported & crtc->rotation) needs_transform = RRTransformCompute(crtc->x, crtc->y, crtc->mode.HDisplay, crtc->mode.VDisplay, RR_Rotate_0, transform, @@ -1545,6 +1565,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) return NULL; assert(!sna_crtc->shadow); + assert(sna_crtc->primary_rotation.supported & crtc->rotation); sna_crtc->rotation = crtc->rotation; return kgem_bo_reference(bo); } @@ -1944,7 +1965,7 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = { }; static int -sna_crtc_find_plane(struct sna *sna, int pipe) +sna_crtc_find_sprite(struct sna *sna, int pipe) { #ifdef DRM_IOCTL_MODE_GETPLANERESOURCES struct drm_mode_get_plane_res r; @@ -1992,74 +2013,93 @@ sna_crtc_find_plane(struct sna *sna, int pipe) } static void -sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc) +rotation_init(struct sna *sna, struct rotation *r, uint32_t obj_id, uint32_t obj_type) { - drmModeObjectPropertiesPtr props; - - sna_crtc->supported_rotations = RR_Rotate_0; - sna_crtc->rotation = sna_crtc->last_rotation = RR_Rotate_0; - #if USE_ROTATION - props = drmModeObjectGetProperties(sna->kgem.fd, - sna_crtc->id, - DRM_MODE_OBJECT_CRTC); - if (props) { - int i, j; + drmModeObjectPropertiesPtr props; + int i, j; - DBG(("%s: CRTC:%d has %d props\n", __FUNCTION__, sna_crtc->id, props->count_props)); + props = drmModeObjectGetProperties(sna->kgem.fd, obj_id, obj_type); + if (props == NULL) + return; - for (i = 0; i < props->count_props; i++) { - struct drm_mode_get_property prop; - struct drm_mode_property_enum *enums; + DBG(("%s: object %d (type %u) has %d props\n", __FUNCTION__, + obj_id, obj_type, props->count_props)); - memset(&prop, 0, sizeof(prop)); - prop.prop_id = props->props[i]; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) - continue; + for (i = 0; i < props->count_props; i++) { + struct drm_mode_get_property prop; + struct drm_mode_property_enum *enums; - DBG(("%s: prop[%d] .id=%d, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i, - props->props[i], prop.name, prop.flags, props->prop_values[i])); - if ((prop.flags & DRM_MODE_PROP_BITMASK) == 0) - continue; + memset(&prop, 0, sizeof(prop)); + prop.prop_id = props->props[i]; + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) + continue; - if (strcmp(prop.name, "rotation")) - continue; + DBG(("%s: prop[%d] .id=%d, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i, + props->props[i], prop.name, prop.flags, props->prop_values[i])); + if ((prop.flags & DRM_MODE_PROP_BITMASK) == 0) + continue; - /* Note that this property only controls the primary - * plane, not the cursor or sprite planes. - */ - sna_crtc->rotation_id = props->props[i]; - sna_crtc->rotation = sna_crtc->last_rotation = props->prop_values[i]; + if (strcmp(prop.name, "rotation")) + continue; - DBG(("%s: found rotation property .id=%d, num_enums=%d\n", - __FUNCTION__, prop.prop_id, prop.count_enum_blobs)); - enums = malloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)); - if (enums != NULL) { - prop.count_values = 0; - prop.enum_blob_ptr = (uintptr_t)enums; + r->obj_id = obj_id; + r->obj_type = obj_type; + r->prop_id = props->props[i]; + r->current = props->prop_values[i]; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop) == 0) { - /* XXX we assume that the mapping between kernel enum and - * RandR remains fixed for our lifetimes. - */ - for (j = 0; j < prop.count_enum_blobs; j++) { - DBG(("%s: CRTC:%d rotation[%d] = %s [%x]\n", __FUNCTION__, sna_crtc->id, j, - enums[j].name, enums[j].value)); - sna_crtc->supported_rotations |= 1 << enums[j].value; - } + DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n", + __FUNCTION__, prop.prop_id, (long)props->prop_values[i], prop.count_enum_blobs)); + enums = malloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)); + if (enums != NULL) { + prop.count_values = 0; + prop.enum_blob_ptr = (uintptr_t)enums; + + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop) == 0) { + /* XXX we assume that the mapping between kernel enum and + * RandR remains fixed for our lifetimes. + */ + for (j = 0; j < prop.count_enum_blobs; j++) { + DBG(("%s: rotation[%d] = %s [%x]\n", __FUNCTION__, + j, enums[j].name, enums[j].value)); + r->supported |= 1 << enums[j].value; } - - free(enums); } - break; + free(enums); } - drmModeFreeObjectProperties(props); + break; } + + drmModeFreeObjectProperties(props); #endif - DBG(("%s: CRTC:%d [pipe=%d], supported-rotations=%x, current-rotation=%x\n", - __FUNCTION__, sna_crtc->id, sna_crtc->pipe, sna_crtc->supported_rotations, sna_crtc->last_rotation)); +} + +static void +rotation_reset(struct rotation *r) +{ + if (r->prop_id == 0) + return; + + r->current = 0; +} + +static void +sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc) +{ + sna_crtc->rotation = RR_Rotate_0; + sna_crtc->primary_rotation.supported = RR_Rotate_0; + sna_crtc->primary_rotation.current = RR_Rotate_0; + sna_crtc->sprite_rotation = sna_crtc->primary_rotation; + + rotation_init(sna, &sna_crtc->primary_rotation, sna_crtc->id, DRM_MODE_OBJECT_CRTC); + rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, DRM_MODE_OBJECT_PLANE); + + DBG(("%s: CRTC:%d [pipe=%d], primary: supported-rotations=%x, current-rotation=%x, sprite: supported-rotations=%x, current-rotation=%x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, + sna_crtc->primary_rotation.supported, sna_crtc->primary_rotation.current, + sna_crtc->sprite_rotation.supported, sna_crtc->sprite_rotation.current)); } static bool @@ -2089,7 +2129,7 @@ sna_crtc_init(ScrnInfoPtr scrn, struct sna_mode *mode, int num) return false; } sna_crtc->pipe = get_pipe.pipe; - sna_crtc->plane = sna_crtc_find_plane(sna, sna_crtc->pipe); + sna_crtc->sprite = sna_crtc_find_sprite(sna, sna_crtc->pipe); if (xf86IsEntityShared(scrn->entityList[0]) && scrn->confScreen->device->screen != sna_crtc->pipe) { @@ -4316,6 +4356,10 @@ void sna_mode_reset(struct sna *sna) continue; sna_crtc->dpms_mode = DPMSModeOff; + + /* Force the rotation property to be reset on next use */ + rotation_reset(&sna_crtc->primary_rotation); + rotation_reset(&sna_crtc->sprite_rotation); } for (i = 0; i < config->num_output; i++) { diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index b6a7950d..f4dcb82d 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -205,10 +205,10 @@ sna_video_sprite_show(struct sna *sna, /* XXX handle video spanning multiple CRTC */ VG_CLEAR(s); - s.plane_id = sna_crtc_to_plane(crtc); + s.plane_id = sna_crtc_to_sprite(crtc); update_dst_box_to_crtc_coords(sna, crtc, dstBox); - if (crtc->rotation & (RR_Rotate_90 | RR_Rotate_270)) { + if (video->rotation & (RR_Rotate_90 | RR_Rotate_270)) { int tmp = frame->width; frame->width = frame->height; frame->height = tmp; @@ -383,11 +383,15 @@ static int sna_video_sprite_put_image(ClientPtr client, &clip)) goto invisible; - if (!crtc || sna_crtc_to_plane(crtc) == 0) + if (!crtc || sna_crtc_to_sprite(crtc) == 0) goto invisible; - /* sprites can't handle rotation natively, store it for the copy func */ - video->rotation = crtc->rotation; + /* if sprite can't handle rotation natively, store it for the copy func */ + video->rotation = RR_Rotate_0; + if (!sna_crtc_set_sprite_rotation(crtc, crtc->rotation)) { + sna_crtc_set_sprite_rotation(crtc, RR_Rotate_0); + video->rotation = crtc->rotation; + } if (xvmc_passthrough(format->id)) { DBG(("%s: using passthough, name=%d\n",