diff options
-rw-r--r-- | src/sna/sna_display.c | 426 | ||||
-rw-r--r-- | src/sna/sna_video_sprite.c | 133 |
2 files changed, 342 insertions, 217 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 2f2d52f4..8bd0d0e5 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -90,6 +90,22 @@ union compat_mode_get_connector{ #define DRM_MODE_PAGE_FLIP_ASYNC 0x02 +#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 +#define DRM_PLANE_TYPE_OVERLAY 0 +#define DRM_PLANE_TYPE_PRIMARY 1 +#define DRM_PLANE_TYPE_CURSOR 2 + +#define LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xb9, struct local_mode_obj_get_properties) +struct local_mode_obj_get_properties { + uint64_t props_ptr; + uint64_t prop_values_ptr; + uint32_t count_props; + uint32_t obj_id; + uint32_t obj_type; + uint32_t pad; +}; +#define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee + #if 0 #define __DBG DBG #else @@ -105,7 +121,6 @@ struct sna_crtc { PixmapPtr scanout_pixmap; struct kgem_bo *bo, *shadow_bo; struct sna_cursor *cursor; - uint32_t sprite; uint32_t offset; bool shadow; bool fallback_shadow; @@ -114,12 +129,14 @@ struct sna_crtc { uint8_t pipe; uint32_t rotation; - struct rotation { - uint32_t obj_id, obj_type; - uint32_t prop_id; - uint32_t supported; - uint32_t current; - } primary_rotation, sprite_rotation; + struct plane { + uint32_t id; + struct { + uint32_t prop; + uint32_t supported; + uint32_t current; + } rotation; + } primary, sprite; uint32_t mode_serial, flip_serial; @@ -242,7 +259,7 @@ int sna_crtc_to_pipe(xf86CrtcPtr crtc) uint32_t sna_crtc_to_sprite(xf86CrtcPtr crtc) { assert(to_sna_crtc(crtc)); - return to_sna_crtc(crtc)->sprite; + return to_sna_crtc(crtc)->sprite.id; } bool sna_crtc_is_on(xf86CrtcPtr crtc) @@ -809,101 +826,10 @@ sna_crtc_force_outputs_off(xf86CrtcPtr crtc) to_sna_crtc(crtc)->dpms_mode = DPMSModeOff; } -#define LOCAL_MODE_OBJECT_CRTC 0xcccccccc -#define LOCAL_MODE_OBJECT_PLANE 0xeeeeeeee -static void -rotation_init(struct sna *sna, struct rotation *r, uint32_t obj_id, uint32_t obj_type) -{ -#if USE_ROTATION -#define LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct local_mode_obj_get_properties) - struct local_mode_obj_get_properties { - uint64_t props_ptr; - uint64_t prop_values_ptr; - uint32_t count_props; - uint32_t obj_id; - uint32_t obj_type; - uint32_t pad; - } props; - uint64_t *prop_values; - int i, j; - - memset(&props, 0, sizeof(struct local_mode_obj_get_properties)); - props.obj_id = obj_id; - props.obj_type = obj_type; - - if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &props)) - return; - - DBG(("%s: object %d (type %u) has %d props\n", __FUNCTION__, - obj_id, obj_type, props.count_props)); - - if (props.count_props == 0) - return; - - prop_values = malloc(2*sizeof(uint64_t)*props.count_props); - if (prop_values == NULL) - return; - - props.props_ptr = (uintptr_t)prop_values; - props.prop_values_ptr = (uintptr_t)(prop_values + props.count_props); - - if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &props)) - props.count_props = 0; - - for (i = 0; i < props.count_props; i++) { - struct drm_mode_get_property prop; - struct drm_mode_property_enum *enums; - - memset(&prop, 0, sizeof(prop)); - prop.prop_id = prop_values[i]; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) - continue; - - DBG(("%s: prop[%d] .id=%ld, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i, - (long)prop_values[i], prop.name, prop.flags, (long)prop_values[i+props.count_props])); - if ((prop.flags & (1 << 5)) == 0) - continue; - - if (strcmp(prop.name, "rotation")) - continue; - - r->obj_id = obj_id; - r->obj_type = obj_type; - r->prop_id = prop_values[i]; - r->current = prop_values[i + props.count_props]; - - DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n", - __FUNCTION__, prop.prop_id, (long)prop_values[i+props.count_props], 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 [%lx]\n", __FUNCTION__, - j, enums[j].name, (long)enums[j].value)); - r->supported |= 1 << enums[j].value; - } - } - - free(enums); - } - - break; - } - - free(prop_values); -#endif -} - static bool -rotation_set(struct sna *sna, struct rotation *r, uint32_t desired) +rotation_set(struct sna *sna, struct plane *p, uint32_t desired) { -#define LOCAL_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct local_mode_obj_set_property) +#define LOCAL_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xbA, struct local_mode_obj_set_property) struct local_mode_obj_set_property { uint64_t value; uint32_t prop_id; @@ -912,38 +838,37 @@ rotation_set(struct sna *sna, struct rotation *r, uint32_t desired) uint32_t pad; } prop; - if (desired == r->current) + if (desired == p->rotation.current) return true; - if ((desired & r->supported) == 0) + if ((desired & p->rotation.supported) == 0) return false; - DBG(("%s: obj=%d, type=%u set-rotation=%x\n", - __FUNCTION__, r->obj_id, r->obj_type, desired)); + DBG(("%s: obj=%d, type=%x prop=%d set-rotation=%x\n", + __FUNCTION__, p->id, LOCAL_MODE_OBJECT_PLANE, p->rotation.prop, desired)); - assert(r->obj_id); - assert(r->obj_type); - assert(r->prop_id); + assert(p->id); + assert(p->rotation.prop); - prop.obj_id = r->obj_id; - prop.obj_type = r->obj_type; - prop.prop_id = r->prop_id; + prop.obj_id = p->id; + prop.obj_type = LOCAL_MODE_OBJECT_PLANE; + prop.prop_id = p->rotation.prop; prop.value = desired; if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_SETPROPERTY, &prop)) return false; - r->current = desired; + p->rotation.current = desired; return true; } static void -rotation_reset(struct rotation *r) +rotation_reset(struct plane *p) { - if (r->prop_id == 0) + if (p->rotation.prop == 0) return; - r->current = 0; + p->rotation.current = 0; } bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation) @@ -951,11 +876,11 @@ bool sna_crtc_set_sprite_rotation(xf86CrtcPtr crtc, uint32_t rotation) assert(to_sna_crtc(crtc)); 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, + to_sna_crtc(crtc)->id, to_sna_crtc(crtc)->pipe, to_sna_crtc(crtc)->sprite.id, rotation)); return rotation_set(to_sna(crtc->scrn), - &to_sna_crtc(crtc)->sprite_rotation, + &to_sna_crtc(crtc)->sprite, rotation); } @@ -975,9 +900,10 @@ sna_crtc_apply(xf86CrtcPtr crtc) assert(sna->mode.num_real_output < ARRAY_SIZE(output_ids)); sna_crtc_disable_cursor(sna, sna_crtc); - if (!rotation_set(sna, &sna_crtc->primary_rotation, sna_crtc->rotation)) { + if (!rotation_set(sna, &sna_crtc->primary, 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)); + __FUNCTION__, sna_crtc->primary.rotation.prop, sna_crtc->rotation, sna_crtc->id, sna_crtc->pipe, errno)); + sna_crtc->primary.rotation.supported &= ~sna_crtc->rotation; return false; } DBG(("%s: CRTC:%d [pipe=%d] primary rotation set to %x\n", @@ -1433,7 +1359,7 @@ sna_crtc_disable(xf86CrtcPtr crtc) sna_crtc->mode_serial++; sna_crtc_disable_cursor(sna, sna_crtc); - rotation_set(sna, &sna_crtc->primary_rotation, RR_Rotate_0); + rotation_set(sna, &sna_crtc->primary, RR_Rotate_0); sna_crtc_disable_shadow(sna, sna_crtc); if (sna_crtc->bo) { @@ -1682,9 +1608,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)->primary_rotation.supported, - !!(crtc->rotation & to_sna_crtc(crtc)->primary_rotation.supported))); - if (to_sna_crtc(crtc)->primary_rotation.supported & 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, @@ -1849,7 +1775,7 @@ static struct kgem_bo *sna_crtc_attach(xf86CrtcPtr crtc) } else sna_crtc_disable_shadow(sna, sna_crtc); - assert(sna_crtc->primary_rotation.supported & crtc->rotation); + assert(sna_crtc->primary.rotation.supported & crtc->rotation); sna_crtc->rotation = crtc->rotation; return kgem_bo_reference(bo); } @@ -2191,69 +2117,217 @@ static const xf86CrtcFuncsRec sna_crtc_funcs = { #endif }; -static int -sna_crtc_find_sprite(struct sna *sna, int pipe) +inline static bool prop_is_rotation(struct drm_mode_get_property *prop) +{ +#if USE_ROTATION + if ((prop->flags & (1 << 5)) == 0) + return false; + + if (strcmp(prop->name, "rotation")) + return false; + + return true; +#else + return false; +#endif +} + +static int plane_details(struct sna *sna, struct plane *p) +{ + struct local_mode_obj_get_properties arg; + uint64_t stack_props[24]; + uint32_t *props = (uint32_t *)stack_props; + uint64_t *values = stack_props + 8; + int i, type = DRM_PLANE_TYPE_OVERLAY; + + memset(&arg, 0, sizeof(struct local_mode_obj_get_properties)); + arg.obj_id = p->id; + arg.obj_type = LOCAL_MODE_OBJECT_PLANE; + + arg.props_ptr = (uintptr_t)props; + arg.prop_values_ptr = (uintptr_t)values; + arg.count_props = 16; + + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &arg)) + return -1; + + DBG(("%s: object %d (type %x) has %d props\n", __FUNCTION__, + p->id, LOCAL_MODE_OBJECT_PLANE, arg.count_props)); + + if (arg.count_props > 16) { + props = malloc(2*sizeof(uint64_t)*arg.count_props); + if (props == NULL) + return -1; + + values = (uint64_t *)props + arg.count_props; + + arg.props_ptr = (uintptr_t)props; + arg.prop_values_ptr = (uintptr_t)values; + + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_OBJ_GETPROPERTIES, &arg)) + arg.count_props = 0; + } + + for (i = 0; i < arg.count_props; i++) { + struct drm_mode_get_property prop; + + memset(&prop, 0, sizeof(prop)); + prop.prop_id = props[i]; + if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) { + ERR(("%s: prop[%d].id=%d GETPROPERTY failed with errno=%d\n", + __FUNCTION__, i, props[i], errno)); + continue; + } + + DBG(("%s: prop[%d] .id=%d, .name=%s, .flags=%x, .value=%ld\n", __FUNCTION__, i, + (long)props[i], prop.name, prop.flags, (long)values[i])); + + if (strcmp(prop.name, "type") == 0) { + type = values[i]; + } else if (prop_is_rotation(&prop)) { + struct drm_mode_property_enum *enums; + + p->rotation.prop = props[i]; + p->rotation.current = values[i]; + + DBG(("%s: found rotation property .id=%d, value=%ld, num_enums=%d\n", + __FUNCTION__, prop.prop_id, (long)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) { + int j; + + /* 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 [%lx]\n", __FUNCTION__, + j, enums[j].name, (long)enums[j].value)); + p->rotation.supported |= 1 << enums[j].value; + } + } + + free(enums); + } + } + } + + if (props != (uint32_t *)stack_props) + free(props); + + DBG(("%s: plane=%d type=%d\n", __FUNCTION__, p->id, type)); + return type; +} + +static void +sna_crtc_find_planes(struct sna *sna, struct sna_crtc *crtc) { -#ifdef DRM_IOCTL_MODE_GETPLANERESOURCES - struct drm_mode_get_plane_res r; - uint32_t *planes, id = 0; +#define LOCAL_IOCTL_SET_CAP DRM_IOWR(0x0d, struct local_set_cap) +#define LOCAL_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xb5, struct local_mode_get_plane_res) +#define LOCAL_IOCTL_MODE_GETPLANE DRM_IOWR(0xb6, struct local_mode_get_plane) + struct local_set_cap { + uint64_t name; + uint64_t value; + } cap; + struct local_mode_get_plane_res { + uint64_t plane_id_ptr; + uint64_t count_planes; + } r; + uint32_t stack_planes[32]; + uint32_t *planes = stack_planes; int i; + VG_CLEAR(cap); + cap.name = DRM_CLIENT_CAP_UNIVERSAL_PLANES; + cap.value = 1; + (void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_SET_CAP, &cap); + VG_CLEAR(r); - r.count_planes = 0; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &r)) - return 0; + r.plane_id_ptr = (uintptr_t)planes; + r.count_planes = ARRAY_SIZE(stack_planes); + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANERESOURCES, &r)) { + ERR(("%s: GETPLANERESOURCES failed with errno=%d\n", __FUNCTION__, errno)); + return; + } - if (!r.count_planes) - return 0; + DBG(("%s: %d planes\n", __FUNCTION__, r.count_planes)); - planes = malloc(sizeof(uint32_t)*r.count_planes); - if (planes == NULL) - return 0; + if (r.count_planes > ARRAY_SIZE(stack_planes)) { + planes = malloc(sizeof(uint32_t)*r.count_planes); + if (planes == NULL) + return; - r.plane_id_ptr = (uintptr_t)planes; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &r)) - r.count_planes = 0; + r.plane_id_ptr = (uintptr_t)planes; + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANERESOURCES, &r)) + r.count_planes = 0; + } VG(VALGRIND_MAKE_MEM_DEFINED(planes, sizeof(uint32_t)*r.count_planes)); for (i = 0; i < r.count_planes; i++) { - struct drm_mode_get_plane p; + struct local_mode_get_plane { + uint32_t plane_id; + + uint32_t crtc_id; + uint32_t fb_id; + + uint32_t possible_crtcs; + uint32_t gamma_size; + + uint32_t count_format_types; + uint64_t format_type_ptr; + } p; + struct plane details; VG_CLEAR(p); p.plane_id = planes[i]; p.count_format_types = 0; - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANE, &p) == 0) { - if (p.possible_crtcs & (1 << pipe)) { - id = p.plane_id; - break; - } + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_GETPLANE, &p)) + continue; + + if ((p.possible_crtcs & (1 << crtc->pipe)) == 0) + continue; + + DBG(("%s: plane %d is attached to our pipe=%d\n", + __FUNCTION__, planes[i], crtc->pipe)); + + details.id = p.plane_id; + details.rotation.prop = 0; + details.rotation.supported = RR_Rotate_0; + details.rotation.current = RR_Rotate_0; + + switch (plane_details(sna, &details)) { + default: + break; + + case DRM_PLANE_TYPE_PRIMARY: + crtc->primary = details; + break; + + case DRM_PLANE_TYPE_CURSOR: + break; + + case DRM_PLANE_TYPE_OVERLAY: + if (crtc->sprite.id == 0) + crtc->sprite = details; + break; } } - free(planes); - assert(id); - return id; -#else - return 0; -#endif + if (planes != stack_planes) + free(planes); } static void -sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *sna_crtc) +sna_crtc_init__rotation(struct sna *sna, struct sna_crtc *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, LOCAL_MODE_OBJECT_CRTC); - rotation_init(sna, &sna_crtc->sprite_rotation, sna_crtc->sprite, LOCAL_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)); + crtc->rotation = RR_Rotate_0; + crtc->primary.rotation.supported = RR_Rotate_0; + crtc->primary.rotation.current = RR_Rotate_0; + crtc->sprite.rotation = crtc->primary.rotation; } static void @@ -2297,9 +2371,6 @@ sna_crtc_add(ScrnInfoPtr scrn, int id) return false; } sna_crtc->pipe = get_pipe.pipe; - sna_crtc->sprite = sna_crtc_find_sprite(sna, sna_crtc->pipe); - - list_init(&sna_crtc->shadow_link); if (xf86IsEntityShared(scrn->entityList[0]) && scrn->confScreen->device->screen != sna_crtc->pipe) { @@ -2307,13 +2378,23 @@ sna_crtc_add(ScrnInfoPtr scrn, int id) return true; } + sna_crtc_init__rotation(sna, sna_crtc); + + sna_crtc_find_planes(sna, sna_crtc); + + DBG(("%s: CRTC:%d [pipe=%d], primary id=%x: supported-rotations=%x, current-rotation=%x, sprite id=%x: supported-rotations=%x, current-rotation=%x\n", + __FUNCTION__, sna_crtc->id, sna_crtc->pipe, + sna_crtc->primary.id, sna_crtc->primary.rotation.supported, sna_crtc->primary.rotation.current, + sna_crtc->sprite.id, sna_crtc->sprite.rotation.supported, sna_crtc->sprite.rotation.current)); + + list_init(&sna_crtc->shadow_link); + crtc = xf86CrtcCreate(scrn, &sna_crtc_funcs); if (crtc == NULL) { free(sna_crtc); return false; } - sna_crtc_init__rotation(sna, sna_crtc); sna_crtc_init__cursor(sna, sna_crtc); crtc->driver_private = sna_crtc; @@ -5076,7 +5157,7 @@ static bool sna_probe_initial_configuration(struct sna *sna) continue; mode_from_kmode(scrn, &mode.mode, &crtc->desiredMode); - crtc->desiredRotation = sna_crtc->primary_rotation.current; + crtc->desiredRotation = sna_crtc->primary.rotation.current; crtc->desiredX = mode.x; crtc->desiredY = mode.y; crtc->desiredTransformPresent = FALSE; @@ -5225,7 +5306,6 @@ static bool has_flip(struct sna *sna) static bool has_flip__async(struct sna *sna) { -#define LOCAL_IOCTL_GET_CAP DRM_IOWR(0x0c, struct local_get_cap) #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 struct local_get_cap { uint64_t name; @@ -5895,8 +5975,8 @@ void sna_mode_reset(struct sna *sna) sna_crtc->dpms_mode = -1; /* Force the rotation property to be reset on next use */ - rotation_reset(&sna_crtc->primary_rotation); - rotation_reset(&sna_crtc->sprite_rotation); + rotation_reset(&sna_crtc->primary); + rotation_reset(&sna_crtc->sprite); } /* VT switching, likely to fbcon so make the backlight usable */ diff --git a/src/sna/sna_video_sprite.c b/src/sna/sna_video_sprite.c index 78b046b5..1106c00b 100644 --- a/src/sna/sna_video_sprite.c +++ b/src/sna/sna_video_sprite.c @@ -41,8 +41,27 @@ #include <i915_drm.h> #include <errno.h> -#ifdef DRM_IOCTL_MODE_GETPLANERESOURCES -#include <drm_fourcc.h> +#define fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24)) +#define DRM_FORMAT_RGB565 fourcc_code('R', 'G', '1', '6') /* [15:0] R:G:B 5:6:5 little endian */ +#define DRM_FORMAT_XRGB8888 fourcc_code('X', 'R', '2', '4') /* [31:0] x:R:G:B 8:8:8:8 little endian */ +#define DRM_FORMAT_YUYV fourcc_code('Y', 'U', 'Y', 'V') /* [31:0] Cr0:Y1:Cb0:Y0 8:8:8:8 little endian */ +#define DRM_FORMAT_UYVY fourcc_code('U', 'Y', 'V', 'Y') /* [31:0] Y1:Cr0:Y0:Cb0 8:8:8:8 little endian */ + +#define LOCAL_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct local_mode_set_plane) +struct local_mode_set_plane { + uint32_t plane_id; + uint32_t crtc_id; + uint32_t fb_id; /* fb object contains surface format type */ + uint32_t flags; + + /* Signed dest location allows it to be partially off screen */ + int32_t crtc_x, crtc_y; + uint32_t crtc_w, crtc_h; + + /* Source values are 16.16 fixed point */ + uint32_t src_x, src_y; + uint32_t src_h, src_w; +}; #define IMAGE_MAX_WIDTH 2048 #define IMAGE_MAX_HEIGHT 2048 @@ -63,7 +82,7 @@ static int sna_video_sprite_stop(ClientPtr client, DrawablePtr draw) { struct sna_video *video = port->devPriv.ptr; - struct drm_mode_set_plane s; + struct local_mode_set_plane s; xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(video->sna->scrn); int i; @@ -80,7 +99,7 @@ static int sna_video_sprite_stop(ClientPtr client, memset(&s, 0, sizeof(s)); s.plane_id = sna_crtc_to_sprite(crtc); - if (drmIoctl(video->sna->kgem.fd, DRM_IOCTL_MODE_SETPLANE, &s)) + if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s)) xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR, "failed to disable plane\n"); @@ -218,7 +237,7 @@ sna_video_sprite_show(struct sna *sna, xf86CrtcPtr crtc, BoxPtr dstBox) { - struct drm_mode_set_plane s; + struct local_mode_set_plane s; int pipe = sna_crtc_to_pipe(crtc); /* XXX handle video spanning multiple CRTC */ @@ -227,8 +246,17 @@ sna_video_sprite_show(struct sna *sna, s.plane_id = sna_crtc_to_sprite(crtc); #define DRM_I915_SET_SPRITE_COLORKEY 0x2b +#define LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct local_intel_sprite_colorkey) +#define LOCAL_IOCTL_MODE_ADDFB2 DRM_IOWR(0xb8, struct local_mode_fb_cmd2) + if (video->color_key_changed & (1 << pipe) && video->has_color_key) { - struct drm_intel_sprite_colorkey set; + struct local_intel_sprite_colorkey { + uint32_t plane_id; + uint32_t min_value; + uint32_t channel_mask; + uint32_t max_value; + uint32_t flags; + } set; DBG(("%s: updating color key: %x\n", __FUNCTION__, video->color_key)); @@ -239,10 +267,10 @@ sna_video_sprite_show(struct sna *sna, set.channel_mask = 0x7 << 24 | 0xff << 16 | 0xff << 8 | 0xff << 0; set.flags = 0; if (!video->AlwaysOnTop) - set.flags = I915_SET_COLORKEY_DESTINATION; + set.flags |= 1 << 1; /* COLORKEY_DESTINATION */ if (drmIoctl(sna->kgem.fd, - DRM_IOCTL_I915_SET_SPRITE_COLORKEY, + LOCAL_IOCTL_I915_SET_SPRITE_COLORKEY, &set)) { xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR, "failed to update color key, disabling future updates\n"); @@ -263,45 +291,55 @@ sna_video_sprite_show(struct sna *sna, } if (frame->bo->delta == 0) { - uint32_t offsets[4], pitches[4], handles[4]; - uint32_t pixel_format; + struct local_mode_fb_cmd2 { + uint32_t fb_id; + uint32_t width, height; + uint32_t pixel_format; + uint32_t flags; + + uint32_t handles[4]; + uint32_t pitches[4]; /* pitch for each plane */ + uint32_t offsets[4]; /* offset of each plane */ + } f; bool purged = true; - handles[0] = frame->bo->handle; - pitches[0] = frame->pitch[0]; - offsets[0] = 0; + memset(&f, 0, sizeof(f)); + f.width = frame->width; + f.height = frame->height; + f.handles[0] = frame->bo->handle; + f.pitches[0] = frame->pitch[0]; switch (frame->id) { case FOURCC_RGB565: - pixel_format = DRM_FORMAT_RGB565; + f.pixel_format = DRM_FORMAT_RGB565; purged = sna->scrn->depth != 16; break; case FOURCC_RGB888: - pixel_format = DRM_FORMAT_XRGB8888; + f.pixel_format = DRM_FORMAT_XRGB8888; purged = sna->scrn->depth != 24; break; case FOURCC_UYVY: - pixel_format = DRM_FORMAT_UYVY; + f.pixel_format = DRM_FORMAT_UYVY; break; case FOURCC_YUY2: default: - pixel_format = DRM_FORMAT_YUYV; + f.pixel_format = DRM_FORMAT_YUYV; break; } - DBG(("%s: creating new fb for handle=%d, width=%d, height=%d, stride=%d\n", - __FUNCTION__, frame->bo->handle, - frame->width, frame->height, pitches[0])); + DBG(("%s: creating new fb for handle=%d, width=%d, height=%d, stride=%d, format=%x\n", + __FUNCTION__, frame->bo->handle, frame->width, frame->height, + f.pitches[0], f.pixel_format)); - if (drmModeAddFB2(sna->kgem.fd, - frame->width, frame->height, pixel_format, - handles, pitches, offsets, - &frame->bo->delta, 0)) { + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_ADDFB2, &f)) { + ERR(("%s: ADDFB2 failed, errno=%d\n", __FUNCTION__, errno)); xf86DrvMsg(sna->scrn->scrnIndex, - X_ERROR, "failed to add fb\n"); + X_ERROR, "failed to add fb, unable to update video\n"); return false; } + frame->bo->delta = f.fb_id; + frame->bo->scanout = true; /* Don't allow the scanout to be cached if not suitable for front */ frame->bo->purged = purged; @@ -327,11 +365,11 @@ sna_video_sprite_show(struct sna *sna, s.crtc_x, s.crtc_y, s.crtc_w, s.crtc_h, s.src_x >> 16, s.src_y >> 16, s.src_w >> 16, s.src_h >> 16)); - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETPLANE, &s)) { + if (drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s)) { DBG(("SET_PLANE failed: ret=%d\n", errno)); memset(&s, 0, sizeof(s)); s.plane_id = video->plane; - (void)drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_SETPLANE, &s); + (void)drmIoctl(sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s); if (video->bo[pipe]) { kgem_bo_destroy(&sna->kgem, video->bo[pipe]); video->bo[pipe] = NULL; @@ -414,10 +452,10 @@ static int sna_video_sprite_put_image(ClientPtr client, if (RegionNil(®)) { off: if (video->bo[pipe]) { - struct drm_mode_set_plane s; + struct local_mode_set_plane s; memset(&s, 0, sizeof(s)); s.plane_id = sna_crtc_to_sprite(crtc); - if (drmIoctl(video->sna->kgem.fd, DRM_IOCTL_MODE_SETPLANE, &s)) + if (drmIoctl(video->sna->kgem.fd, LOCAL_IOCTL_MODE_SETPLANE, &s)) xf86DrvMsg(video->sna->scrn->scrnIndex, X_ERROR, "failed to disable plane\n"); video->bo[pipe] = NULL; @@ -598,22 +636,34 @@ static int sna_video_sprite_color_key(struct sna *sna) return color_key & ((1 << scrn->depth) - 1); } +static bool sna_video_has_sprites(struct sna *sna) +{ + xf86CrtcConfigPtr config = XF86_CRTC_CONFIG_PTR(sna->scrn); + int i; + + DBG(("%s: num_crtc=%d\n", __FUNCTION__, sna->mode.num_real_crtc)); + + if (sna->mode.num_real_crtc == 0) + return false; + + for (i = 0; i < sna->mode.num_real_crtc; i++) { + if (!sna_crtc_to_sprite(config->crtc[i])) { + DBG(("%s: no sprite found on pipe %d\n", __FUNCTION__, sna_crtc_to_pipe(config->crtc[i]))); + return false; + } + } + + DBG(("%s: yes\n", __FUNCTION__)); + return true; +} + void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen) { XvAdaptorPtr adaptor; - struct drm_mode_get_plane_res r; struct sna_video *video; XvPortPtr port; - if (sna->flags & SNA_IS_HOSTED) - return; - - memset(&r, 0, sizeof(struct drm_mode_get_plane_res)); - if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETPLANERESOURCES, &r)) - return; - - DBG(("%s: %d sprite planes\n", __FUNCTION__, r.count_planes)); - if (r.count_planes == 0) + if (!sna_video_has_sprites(sna)) return; adaptor = sna_xv_adaptor_alloc(sna); @@ -699,8 +749,3 @@ void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen) xvAlwaysOnTop = MAKE_ATOM("XV_ALWAYS_ON_TOP"); xvSyncToVblank = MAKE_ATOM("XV_SYNC_TO_VBLANK"); } -#else -void sna_video_sprite_setup(struct sna *sna, ScreenPtr screen) -{ -} -#endif |