From patchwork Fri May 22 12:36:55 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Daniel Stone X-Patchwork-Id: 6464151 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 819DD9F1C1 for ; Fri, 22 May 2015 12:37:12 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6FCEF20483 for ; Fri, 22 May 2015 12:37:11 +0000 (UTC) Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by mail.kernel.org (Postfix) with ESMTP id 9769B20494 for ; Fri, 22 May 2015 12:37:05 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9AFBA6EA75; Fri, 22 May 2015 05:37:04 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from bhuna.collabora.co.uk (bhuna.collabora.co.uk [93.93.135.160]) by gabe.freedesktop.org (Postfix) with ESMTP id 0EA126EA75 for ; Fri, 22 May 2015 05:37:03 -0700 (PDT) Received: from [127.0.0.1] (localhost [127.0.0.1]) (Authenticated sender: daniels) with ESMTPSA id D2079601ACB From: Daniel Stone To: dri-devel@lists.freedesktop.org Subject: [PATCH libdrm 1/2] Support atomic modesetting ioctl Date: Fri, 22 May 2015 13:36:55 +0100 Message-Id: <1432298216-22460-2-git-send-email-daniels@collabora.com> X-Mailer: git-send-email 2.4.1 In-Reply-To: <1432298216-22460-1-git-send-email-daniels@collabora.com> References: <1432298216-22460-1-git-send-email-daniels@collabora.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Spam-Status: No, score=-4.2 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Ville Syrjälä Add support for the atomic modesetting ioctl through a property-set API. [daniels: Squashed intermediate patches from Ville, Rob and myself. Updated for current interface.] Signed-off-by: Ville Syrjälä Signed-off-by: Rob Clark Signed-off-by: Daniel Stone --- include/drm/drm.h | 9 +++ include/drm/drm_mode.h | 16 +++++ xf86drmMode.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++++ xf86drmMode.h | 14 ++++ 4 files changed, 225 insertions(+) diff --git a/include/drm/drm.h b/include/drm/drm.h index 229a29f..0b1d2ef 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -635,6 +635,13 @@ struct drm_get_cap { */ #define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2 +/** + * DRM_CLIENT_CAP_ATOMIC + * + * If set to 1, the DRM core will allow atomic modesetting requests. + */ +#define DRM_CLIENT_CAP_ATOMIC 3 + /** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */ struct drm_set_client_cap { __u64 capability; @@ -758,6 +765,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 @@ -806,6 +814,7 @@ struct drm_event_vblank { #define DRM_CAP_PRIME 0x5 #define DRM_CAP_TIMESTAMP_MONOTONIC 0x6 #define DRM_CAP_ASYNC_PAGE_FLIP 0x7 +#define DRM_CAP_ATOMIC 0xa #define DRM_PRIME_CAP_IMPORT 0x1 #define DRM_PRIME_CAP_EXPORT 0x2 diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index a2ab88a..66f856f 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -507,4 +507,20 @@ 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_ALLOW_MODESET 0x0400 + +struct drm_mode_atomic { + __u32 flags; + __u32 count_objs; + __u64 objs_ptr; + __u64 count_props_ptr; + __u64 props_ptr; + __u64 prop_values_ptr; + __u64 reserved; + __u64 user_data; +}; + #endif diff --git a/xf86drmMode.c b/xf86drmMode.c index 1333da4..30b94b8 100644 --- a/xf86drmMode.c +++ b/xf86drmMode.c @@ -40,6 +40,7 @@ #include #include #include +#include #ifdef HAVE_CONFIG_H #include "config.h" @@ -1147,3 +1148,188 @@ int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop); } + +typedef struct _drmModeAtomicReqItem drmModeAtomicReqItem, *drmModeAtomicReqItemPtr; + +struct _drmModeAtomicReqItem { + uint32_t object_id; + uint32_t property_id; + uint64_t value; + drmModeAtomicReqItemPtr next; +}; + +struct _drmModeAtomicReq { + unsigned int count_objs; + unsigned int count_props; + drmModeAtomicReqItem list; +}; + +drmModeAtomicReqPtr drmModeAtomicAlloc(void) +{ + drmModeAtomicReqPtr req; + + req = drmMalloc(sizeof *req); + if (!req) + return NULL; + + req->list.next = NULL; + req->count_props = 0; + req->count_objs = 0; + + return req; +} + +int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value) +{ + drmModeAtomicReqItemPtr prev = &req->list; + bool new_obj = false; + + /* keep it sorted by object_id and property_id */ + while (prev->next) { + if (prev->next->object_id > object_id) + break; + + if (prev->next->object_id == object_id && + prev->next->property_id >= property_id) + break; + + prev = prev->next; + } + + if ((prev == &req->list || prev->object_id != object_id) && + (!prev->next || prev->next->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) { + drmModeAtomicReqItemPtr item = prev->next; + item->value = value; + } else { + drmModeAtomicReqItemPtr item; + + item = drmMalloc(sizeof *item); + if (!item) + return -1; + + item->object_id = object_id; + item->property_id = property_id; + item->value = value; + + item->next = prev->next; + prev->next = item; + + req->count_props++; + } + + if (new_obj) + req->count_objs++; + + return 0; +} + +void drmModeAtomicFree(drmModeAtomicReqPtr req) +{ + drmModeAtomicReqItemPtr item; + + if (!req) + return; + + item = req->list.next; + + while (item) { + drmModeAtomicReqItemPtr next = item->next; + + drmFree(item); + + item = next; + } + + drmFree(req); +} + +int drmModeAtomicCommit(int fd, drmModeAtomicReqPtr req, uint32_t flags, + void *user_data) +{ + drmModeAtomicReqItemPtr item; + uint32_t *objs_ptr = NULL; + uint32_t *count_props_ptr = NULL; + uint32_t *props_ptr = NULL; + uint64_t *prop_values_ptr = NULL; + struct drm_mode_atomic atomic = { 0 }; + unsigned int obj_idx = 0; + unsigned int prop_idx = 0; + int ret = -1; + + if (!req) + return -1; + + objs_ptr = drmMalloc(req->count_objs * sizeof objs_ptr[0]); + if (!objs_ptr) { + errno = ENOMEM; + goto out; + } + + count_props_ptr = drmMalloc(req->count_objs * sizeof count_props_ptr[0]); + if (!count_props_ptr) { + errno = ENOMEM; + goto out; + } + + props_ptr = drmMalloc(req->count_props * sizeof props_ptr[0]); + if (!props_ptr) { + errno = ENOMEM; + goto out; + } + + prop_values_ptr = drmMalloc(req->count_props * sizeof prop_values_ptr[0]); + if (!prop_values_ptr) { + errno = ENOMEM; + goto out; + } + + item = req->list.next; + + while (item) { + int count_props = 0; + drmModeAtomicReqItemPtr 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++; + + count_props++; + + next = next->next; + } + + count_props_ptr[obj_idx++] = count_props; + + item = next; + } + + atomic.count_objs = req->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.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..3ba2333 100644 --- a/xf86drmMode.h +++ b/xf86drmMode.h @@ -484,6 +484,20 @@ extern int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type, uint32_t property_id, uint64_t value); + +typedef struct _drmModeAtomicReq drmModeAtomicReq, *drmModeAtomicReqPtr; + +extern drmModeAtomicReqPtr drmModeAtomicAlloc(void); +extern int drmModeAtomicAddProperty(drmModeAtomicReqPtr req, + uint32_t object_id, + uint32_t property_id, + uint64_t value); +extern int drmModeAtomicCommit(int fd, + drmModeAtomicReqPtr req, + uint32_t flags, + void *user_data); +extern void drmModeAtomicFree(drmModeAtomicReqPtr req); + #if defined(__cplusplus) || defined(c_plusplus) } #endif