summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/sna/sna_display.c426
-rw-r--r--src/sna/sna_video_sprite.c133
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(&reg)) {
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