| From dea4ead559635bf2408d43ab558d13a79f42413f Mon Sep 17 00:00:00 2001 |
| From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= <ville.syrjala@linux.intel.com> |
| Date: Fri, 18 May 2012 15:52:09 +0300 |
| Subject: [PATCH 7/9] libdrm: atomic mode set |
| |
| --- |
| include/drm/drm.h | 1 + |
| include/drm/drm_mode.h | 22 ++++ |
| xf86drmMode.c | 273 +++++++++++++++++++++++++++++++++++++++++++++++++ |
| xf86drmMode.h | 20 ++++ |
| 4 files changed, 316 insertions(+) |
| |
| diff --git a/include/drm/drm.h b/include/drm/drm.h |
| index 229a29f..768b7db 100644 |
| --- a/include/drm/drm.h |
| +++ b/include/drm/drm.h |
| @@ -758,6 +758,7 @@ struct drm_prime_handle { |
| #define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties) |
| #define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property) |
| #define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2) |
| +#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic) |
| |
| /** |
| * Device specific ioctls should only be in their respective headers |
| diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h |
| index a2ab88a..1c3f620 100644 |
| --- a/include/drm/drm_mode.h |
| +++ b/include/drm/drm_mode.h |
| @@ -507,4 +507,26 @@ struct drm_mode_destroy_dumb { |
| __u32 handle; |
| }; |
| |
| +/* page-flip flags are valid, plus: */ |
| +#define DRM_MODE_ATOMIC_TEST_ONLY 0x0100 |
| +#define DRM_MODE_ATOMIC_NONBLOCK 0x0200 |
| + |
| +#define DRM_MODE_ATOMIC_FLAGS (\ |
| + DRM_MODE_PAGE_FLIP_EVENT |\ |
| + DRM_MODE_PAGE_FLIP_ASYNC |\ |
| + DRM_MODE_ATOMIC_TEST_ONLY |\ |
| + DRM_MODE_ATOMIC_NONBLOCK) |
| + |
| +/* FIXME come up with some sane error reporting mechanism? */ |
| +struct drm_mode_atomic { |
| + __u32 flags; |
| + __u32 count_objs; |
| + __u64 objs_ptr; |
| + __u64 count_props_ptr; |
| + __u64 props_ptr; |
| + __u64 prop_values_ptr; |
| + __u64 blob_values_ptr; |
| + __u64 user_data; |
| +}; |
| + |
| #endif |
| diff --git a/xf86drmMode.c b/xf86drmMode.c |
| index 1333da4..0485113 100644 |
| --- a/xf86drmMode.c |
| +++ b/xf86drmMode.c |
| @@ -40,6 +40,7 @@ |
| #include <stdint.h> |
| #include <sys/ioctl.h> |
| #include <stdio.h> |
| +#include <stdbool.h> |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| @@ -1147,3 +1148,275 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, |
| |
| return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); |
| } |
| + |
| +typedef struct _drmModePropertySetItem drmModePropertySetItem, *drmModePropertySetItemPtr; |
| + |
| +struct _drmModePropertySetItem { |
| + uint32_t object_id; |
| + uint32_t property_id; |
| + bool is_blob; |
| + uint64_t value; |
| + void *blob; |
| + drmModePropertySetItemPtr next; |
| +}; |
| + |
| +struct _drmModePropertySet { |
| + unsigned int count_objs; |
| + unsigned int count_props; |
| + unsigned int count_blobs; |
| + drmModePropertySetItem list; |
| +}; |
| + |
| +drmModePropertySetPtr drmModePropertySetAlloc(void) |
| +{ |
| + drmModePropertySetPtr set; |
| + |
| + set = drmMalloc(sizeof *set); |
| + if (!set) |
| + return NULL; |
| + |
| + set->list.next = NULL; |
| + set->count_props = 0; |
| + set->count_objs = 0; |
| + |
| + return set; |
| +} |
| + |
| +int drmModePropertySetAdd(drmModePropertySetPtr set, |
| + uint32_t object_id, |
| + uint32_t property_id, |
| + uint64_t value) |
| +{ |
| + drmModePropertySetItemPtr prev = &set->list; |
| + bool new_obj = false; |
| + |
| + /* keep it sorted by object_id and property_id */ |
| + while (prev->next) { |
| + if (prev->next->object_id > object_id) { |
| + new_obj = true; |
| + break; |
| + } |
| + |
| + if (prev->next->object_id == object_id && |
| + prev->next->property_id >= property_id) |
| + break; |
| + |
| + prev = prev->next; |
| + } |
| + |
| + if (!prev->next && |
| + (prev == &set->list || prev->object_id != object_id)) |
| + new_obj = true; |
| + |
| + /* replace or add? */ |
| + if (prev->next && |
| + prev->next->object_id == object_id && |
| + prev->next->property_id == property_id) { |
| + drmModePropertySetItemPtr item = prev->next; |
| + |
| + if (item->is_blob) |
| + return -EINVAL; |
| + |
| + item->value = value; |
| + } else { |
| + drmModePropertySetItemPtr item; |
| + |
| + item = drmMalloc(sizeof *item); |
| + if (!item) |
| + return -1; |
| + |
| + item->object_id = object_id; |
| + item->property_id = property_id; |
| + item->value = value; |
| + item->is_blob = false; |
| + item->blob = NULL; |
| + |
| + item->next = prev->next; |
| + prev->next = item; |
| + |
| + set->count_props++; |
| + } |
| + |
| + if (new_obj) |
| + set->count_objs++; |
| + |
| + return 0; |
| +} |
| + |
| +int drmModePropertySetAddBlob(drmModePropertySetPtr set, |
| + uint32_t object_id, |
| + uint32_t property_id, |
| + uint64_t length, |
| + void *data) |
| +{ |
| + drmModePropertySetItemPtr prev = &set->list; |
| + bool new_obj = false; |
| + |
| + /* keep it sorted by object_id and property_id */ |
| + while (prev->next) { |
| + if (prev->next->object_id > object_id) { |
| + new_obj = true; |
| + break; |
| + } |
| + |
| + if (prev->next->object_id == object_id && |
| + prev->next->property_id >= property_id) |
| + break; |
| + |
| + prev = prev->next; |
| + } |
| + |
| + if (!prev->next && |
| + (prev == &set->list || prev->object_id != object_id)) |
| + new_obj = true; |
| + |
| + /* replace or add? */ |
| + if (prev->next && |
| + prev->next->object_id == object_id && |
| + prev->next->property_id == property_id) { |
| + drmModePropertySetItemPtr item = prev->next; |
| + |
| + if (!item->is_blob) |
| + return -EINVAL; |
| + |
| + item->value = length; |
| + item->blob = data; |
| + } else { |
| + drmModePropertySetItemPtr item; |
| + |
| + item = drmMalloc(sizeof *item); |
| + if (!item) |
| + return -1; |
| + |
| + item->object_id = object_id; |
| + item->property_id = property_id; |
| + item->is_blob = true; |
| + item->value = length; |
| + item->blob = data; |
| + |
| + item->next = prev->next; |
| + prev->next = item; |
| + |
| + set->count_props++; |
| + set->count_blobs++; |
| + } |
| + |
| + if (new_obj) |
| + set->count_objs++; |
| + |
| + return 0; |
| +} |
| + |
| +void drmModePropertySetFree(drmModePropertySetPtr set) |
| +{ |
| + drmModePropertySetItemPtr item; |
| + |
| + if (!set) |
| + return; |
| + |
| + item = set->list.next; |
| + |
| + while (item) { |
| + drmModePropertySetItemPtr next = item->next; |
| + |
| + drmFree(item); |
| + |
| + item = next; |
| + } |
| + |
| + drmFree(set); |
| +} |
| + |
| +int drmModePropertySetCommit(int fd, uint32_t flags, void *user_data, |
| + drmModePropertySetPtr set) |
| +{ |
| + drmModePropertySetItemPtr item; |
| + uint32_t *objs_ptr = NULL; |
| + uint32_t *count_props_ptr = NULL; |
| + uint32_t *props_ptr = NULL; |
| + uint64_t *prop_values_ptr = NULL; |
| + uint64_t *blob_values_ptr = NULL; |
| + struct drm_mode_atomic atomic = { 0 }; |
| + unsigned int obj_idx = 0; |
| + unsigned int prop_idx = 0; |
| + unsigned int blob_idx = 0; |
| + int ret = -1; |
| + |
| + if (!set) |
| + return -1; |
| + |
| + objs_ptr = drmMalloc(set->count_objs * sizeof objs_ptr[0]); |
| + if (!objs_ptr) { |
| + errno = ENOMEM; |
| + goto out; |
| + } |
| + |
| + count_props_ptr = drmMalloc(set->count_objs * sizeof count_props_ptr[0]); |
| + if (!count_props_ptr) { |
| + errno = ENOMEM; |
| + goto out; |
| + } |
| + |
| + props_ptr = drmMalloc(set->count_props * sizeof props_ptr[0]); |
| + if (!props_ptr) { |
| + errno = ENOMEM; |
| + goto out; |
| + } |
| + |
| + prop_values_ptr = drmMalloc(set->count_props * sizeof prop_values_ptr[0]); |
| + if (!prop_values_ptr) { |
| + errno = ENOMEM; |
| + goto out; |
| + } |
| + |
| + blob_values_ptr = drmMalloc(set->count_blobs * sizeof blob_values_ptr[0]); |
| + if (!blob_values_ptr) { |
| + errno = ENOMEM; |
| + goto out; |
| + } |
| + |
| + item = set->list.next; |
| + |
| + while (item) { |
| + int count_props = 0; |
| + drmModePropertySetItemPtr next = item; |
| + |
| + objs_ptr[obj_idx] = item->object_id; |
| + |
| + while (next && next->object_id == item->object_id) { |
| + props_ptr[prop_idx] = next->property_id; |
| + prop_values_ptr[prop_idx] = next->value; |
| + prop_idx++; |
| + |
| + if (next->is_blob) |
| + blob_values_ptr[blob_idx++] = VOID2U64(next->blob); |
| + |
| + count_props++; |
| + |
| + next = next->next; |
| + } |
| + |
| + count_props_ptr[obj_idx++] = count_props; |
| + |
| + item = next; |
| + } |
| + |
| + atomic.count_objs = set->count_objs; |
| + atomic.flags = flags; |
| + atomic.objs_ptr = VOID2U64(objs_ptr); |
| + atomic.count_props_ptr = VOID2U64(count_props_ptr); |
| + atomic.props_ptr = VOID2U64(props_ptr); |
| + atomic.prop_values_ptr = VOID2U64(prop_values_ptr); |
| + atomic.blob_values_ptr = VOID2U64(blob_values_ptr); |
| + atomic.user_data = VOID2U64(user_data); |
| + |
| + ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ATOMIC, &atomic); |
| + |
| +out: |
| + drmFree(objs_ptr); |
| + drmFree(count_props_ptr); |
| + drmFree(props_ptr); |
| + drmFree(prop_values_ptr); |
| + |
| + return ret; |
| +} |
| diff --git a/xf86drmMode.h b/xf86drmMode.h |
| index 20c3f15..003e158 100644 |
| --- a/xf86drmMode.h |
| +++ b/xf86drmMode.h |
| @@ -484,6 +484,26 @@ extern int drmModeObjectSetProperty(int fd, uint32_t object_id, |
| uint32_t object_type, uint32_t property_id, |
| uint64_t value); |
| |
| + |
| +typedef struct _drmModePropertySet drmModePropertySet, *drmModePropertySetPtr; |
| + |
| +extern drmModePropertySetPtr drmModePropertySetAlloc(void); |
| + |
| +extern int drmModePropertySetAdd(drmModePropertySetPtr set, |
| + uint32_t object_id, |
| + uint32_t property_id, |
| + uint64_t value); |
| +extern int drmModePropertySetAddBlob(drmModePropertySetPtr set, |
| + uint32_t object_id, |
| + uint32_t property_id, |
| + uint64_t length, |
| + void *blob); |
| + |
| +extern int drmModePropertySetCommit(int fd, uint32_t flags, |
| + void *user_data, drmModePropertySetPtr set); |
| + |
| +extern void drmModePropertySetFree(drmModePropertySetPtr set); |
| + |
| #if defined(__cplusplus) || defined(c_plusplus) |
| } |
| #endif |
| -- |
| 2.3.1 |
| |