From: Ville Syrjälä <ville.syrj...@linux.intel.com>

---
 include/drm/drm.h      |    1 +
 include/drm/drm_mode.h |   13 +++
 xf86drmMode.c          |  270 ++++++++++++++++++++++++++++++++++++++++++++++++
 xf86drmMode.h          |   19 ++++
 4 files changed, 303 insertions(+), 0 deletions(-)
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 5e6cd29..c3236e1 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -733,6 +733,7 @@ struct drm_prime_handle {
 #define DRM_IOCTL_MODE_ADDFB2          DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
 #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_ATOMIC  DRM_IOWR(0xBB, 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 62ba997..5b2f294 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -462,4 +462,17 @@ struct drm_mode_destroy_dumb {
        __u32 handle;
 };
 
+#define DRM_MODE_ATOMIC_TEST_ONLY (1<<0)
+
+/* 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;
+};
+
 #endif
diff --git a/xf86drmMode.c b/xf86drmMode.c
index 04fdf1f..18cd10b 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -40,6 +40,7 @@
 #include <stdint.h>
 #include <sys/ioctl.h>
 #include <stdio.h>
+#include <stdbool.h>
 
 #include "xf86drmMode.h"
 #include "xf86drm.h"
@@ -1057,3 +1058,272 @@ 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, 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);
+
+       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 8e40034..3500616 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -442,6 +442,25 @@ 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, 
drmModePropertySetPtr set);
+
+extern void drmModePropertySetFree(drmModePropertySetPtr set);
+
 #if defined(__cplusplus) || defined(c_plusplus)
 }
 #endif
-- 
1.7.3.4

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to