The following two patches are the rework of the patch series sent two weeks ago [1] that add libdrm support for render node manipulation. All notes described in [1] apply. A new option to render_node_add utility has been added to specify the number of planes and plane IDs are supposed to be the last in the ID list.
Regards, -- Ilija
----
[1] http://lists.freedesktop.org/archives/dri-devel/2012-March/020782.html
Implement the user-space side of drm_render_node_create and drm_render_node_remove ioctls. The new functions are drmCreateRenderNode and drmRemoveRenderNode.
v2: - add planes
Signed-off-by: Ilija Hadzic ihadzic@research.bell-labs.com --- include/drm/drm.h | 2 + include/drm/drm_mode.h | 17 ++++++++++++++ xf86drm.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++ xf86drm.h | 6 +++++ 4 files changed, 83 insertions(+), 0 deletions(-)
diff --git a/include/drm/drm.h b/include/drm/drm.h index 753d2fc..7d82130 100644 --- a/include/drm/drm.h +++ b/include/drm/drm.h @@ -650,6 +650,8 @@ struct drm_prime_handle { #define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink) #define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open) #define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap) +#define DRM_IOCTL_RENDER_NODE_CREATE DRM_IOWR(0x0d, struct drm_render_node_create) +#define DRM_IOCTL_RENDER_NODE_REMOVE DRM_IOWR(0x0e, struct drm_render_node_remove)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique) #define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth) diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h index f36c61a..5e719fd 100644 --- a/include/drm/drm_mode.h +++ b/include/drm/drm_mode.h @@ -437,4 +437,21 @@ struct drm_mode_destroy_dumb { __u32 handle; };
+/* + * render node create and remove functions + * if crtc/encoders/connectors all == 0 then gpgpu node + */ +struct drm_render_node_create { + __u32 node_minor_id; + __u32 num_crtc; + __u32 num_encoder; + __u32 num_connector; + __u32 num_plane; + __u64 id_list_ptr; +}; + +struct drm_render_node_remove { + __u32 node_minor_id; +}; + #endif diff --git a/xf86drm.c b/xf86drm.c index 7def2b3..eb813e0 100644 --- a/xf86drm.c +++ b/xf86drm.c @@ -2552,3 +2552,61 @@ char *drmGetDeviceNameFromFd(int fd) out: return strdup(name); } + +/** + * Create a new render node. + * + * \param fd file descriptor. + * \param minor pointer where to put the minor of the new node. + * \param num_crtc number of CRTCs to assign to the new node. + * \param num_encoder number of encoders to assign to the new node. + * \param num_connector number of connectors to assign to the new node. + * \param id_list list of CRTC/encoder/connector IDs. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * Issues an ioctl to the kernel to create a new render node + * and popluates the variable pointed by *minor with the new minor + * device number. + */ +int drmCreateRenderNode(int fd, int *minor, + int num_crtc, int num_encoder, + int num_connector, int num_plane, + uint32_t *id_list) +{ + struct drm_render_node_create node; + int r; + + node.num_crtc = num_crtc; + node.num_encoder = num_encoder; + node.num_connector = num_connector; + node.num_plane = num_plane; + node.id_list_ptr = (uint64_t)(unsigned long)id_list; + r = drmIoctl(fd, DRM_IOCTL_RENDER_NODE_CREATE, &node); + if (!r) + *minor = node.node_minor_id; + return r; +} + +/** + * Remove the render node. + * + * \param fd file descriptor. + * \param minor minor device number to remove. + * + * \return zero on success, or a negative value on failure. + * + * \internal + * Issues an ioctl to the kernel to remove a new render node + * identified by the file descriptor and the minor device number. + */ +int drmRemoveRenderNode(int fd, int minor) +{ + struct drm_render_node_remove node; + int r; + + node.node_minor_id = minor; + r = drmIoctl(fd, DRM_IOCTL_RENDER_NODE_REMOVE, &node); + return r; +} diff --git a/xf86drm.h b/xf86drm.h index 76eb94e..0658a85 100644 --- a/xf86drm.h +++ b/xf86drm.h @@ -701,6 +701,12 @@ extern void drmMsg(const char *format, ...); extern int drmSetMaster(int fd); extern int drmDropMaster(int fd);
+extern int drmCreateRenderNode(int fd, int *minor, + int num_crtc, int num_encoder, + int num_connector, int num_plane, + uint32_t *id_list); +extern int drmRemoveRenderNode(int fd, int minor); + #define DRM_EVENT_CONTEXT_VERSION 2
typedef struct _drmEventContext {
Add two simple programs (render_node_add and render_node_rm) that can be used to add and remove render nodes from a shell command or a script.
v2: - add planes
Signed-off-by: Ilija Hadzic ihadzic@research.bell-labs.com --- .gitignore | 2 + configure.ac | 1 + tests/Makefile.am | 2 +- tests/render_nodes/Makefile.am | 16 ++++ tests/render_nodes/render_node_add.c | 158 ++++++++++++++++++++++++++++++++++ tests/render_nodes/render_node_rm.c | 88 +++++++++++++++++++ 6 files changed, 266 insertions(+), 1 deletions(-) create mode 100644 tests/render_nodes/Makefile.am create mode 100644 tests/render_nodes/render_node_add.c create mode 100644 tests/render_nodes/render_node_rm.c
diff --git a/.gitignore b/.gitignore index 243457e..3d2afe8 100644 --- a/.gitignore +++ b/.gitignore @@ -76,3 +76,5 @@ tests/modeprint/modeprint tests/modetest/modetest tests/kmstest/kmstest tests/vbltest/vbltest +tests/render_nodes/render_node_add +tests/render_nodes/render_node_rm diff --git a/configure.ac b/configure.ac index 1ba7eba..797a4bf 100644 --- a/configure.ac +++ b/configure.ac @@ -308,6 +308,7 @@ AC_CONFIG_FILES([ tests/kmstest/Makefile tests/radeon/Makefile tests/vbltest/Makefile + tests/render_nodes/Makefile include/Makefile include/drm/Makefile libdrm.pc]) diff --git a/tests/Makefile.am b/tests/Makefile.am index a3a59bd..f916a38 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -10,7 +10,7 @@ check_PROGRAMS = \ dristat \ drmstat
-SUBDIRS = modeprint +SUBDIRS = modeprint render_nodes
if HAVE_LIBKMS SUBDIRS += kmstest modetest diff --git a/tests/render_nodes/Makefile.am b/tests/render_nodes/Makefile.am new file mode 100644 index 0000000..133d792 --- /dev/null +++ b/tests/render_nodes/Makefile.am @@ -0,0 +1,16 @@ +AM_CFLAGS = \ + -I$(top_srcdir)/include/drm \ + -I$(top_srcdir) + +noinst_PROGRAMS = \ + render_node_add render_node_rm + +render_node_add_SOURCES = \ + render_node_add.c +render_node_add_LDADD = \ + $(top_builddir)/libdrm.la + +render_node_rm_SOURCES = \ + render_node_rm.c +render_node_rm_LDADD = \ + $(top_builddir)/libdrm.la diff --git a/tests/render_nodes/render_node_add.c b/tests/render_nodes/render_node_add.c new file mode 100644 index 0000000..ec64247 --- /dev/null +++ b/tests/render_nodes/render_node_add.c @@ -0,0 +1,158 @@ +/* + * Copyright 2012 Alcatel-Lucent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ilija Hadzic ihadzic@research.bell-labs.com + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <string.h> +#include <xf86drm.h> + +#include "config.h" + +void print_usage() +{ + fprintf(stderr, "Render Node Add\n"); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\trender_node_add -? | [-n control_node_path] " + "[-c num_crtc] [-e num_encoders] [-p num_connectors] " + "[-o num_planes] [-l id_list]\n"); +} + +int parse_id_list(char *in_list, uint32_t *out_list, int list_size) +{ + int i; + char *list_elem; + + if (!in_list) + return 0; + list_elem = strtok(in_list, ","); + out_list[0] = strtol(list_elem, NULL, 0); + for (i = 1; list_elem && i < list_size; i++) { + list_elem = strtok(NULL, ","); + if (!list_elem) + break; + out_list[i] = strtol(list_elem, NULL, 0); + } + return 0; +} + +int main(int argc, char **argv) +{ + int r; + int i; + int minor; + int fd; + int num_crtc, num_encoder, num_connector, num_plane; + uint32_t *id_list; + char *id_list_arg; + char *control_node; + int id_list_size; + + num_crtc = 0; + num_encoder = 0; + num_connector = 0; + num_plane = 0; + id_list = NULL; + id_list_arg = NULL; + control_node = NULL; + while ((r = getopt(argc, argv, "n:c:e:p:o:l:?")) != -1) { + switch (r) { + case 'n': + control_node = optarg; + break; + case 'c': + num_crtc = strtol(optarg, NULL, 0); + if (num_crtc < 0) + num_crtc = 0; + break; + case 'e': + num_encoder = strtol(optarg, NULL, 0); + if (num_encoder < 0) + num_encoder = 0; + break; + case 'p': + num_connector = strtol(optarg, NULL, 0); + if (num_connector < 0) + num_connector = 0; + break; + case 'o': + num_plane = strtol(optarg, NULL, 0); + if (num_plane < 0) + num_plane = 0; + break; + case 'l': + id_list_arg = optarg; + break; + case '?': + default: + print_usage(); + return 0; + } + } + id_list_size = num_crtc + num_encoder + num_connector + num_plane; + if (id_list_size) { + int s; + + id_list = calloc(id_list_size, sizeof(uint32_t)); + if (!id_list) { + perror(argv[0]); + exit(EXIT_FAILURE); + } + s = parse_id_list(id_list_arg, id_list, id_list_size); + if (s) { + fprintf(stderr, "id_list parse error\n"); + free(id_list); + exit(EXIT_FAILURE); + } + } + if (!control_node) + control_node = "/dev/dri/controlD64"; + printf("control_node = %s\n", control_node); + fd = open(control_node, 0); + if (fd == -1) { + perror(argv[0]); + exit(EXIT_FAILURE); + } + printf("id_list = "); + for (i = 0; i < id_list_size; i++) + printf("%d ", id_list[i]); + printf("\n"); + r = drmCreateRenderNode(fd, &minor, num_crtc, num_encoder, + num_connector, num_plane, id_list); + if (r) { + free(id_list); + close(fd); + perror(argv[0]); + exit(EXIT_FAILURE); + } + printf("minor = %d\n", minor); + free(id_list); + close(fd); + return 0; +} diff --git a/tests/render_nodes/render_node_rm.c b/tests/render_nodes/render_node_rm.c new file mode 100644 index 0000000..f300a03 --- /dev/null +++ b/tests/render_nodes/render_node_rm.c @@ -0,0 +1,88 @@ +/* + * Copyright 2012 Alcatel-Lucent, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Authors: + * Ilija Hadzic ihadzic@research.bell-labs.com + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <xf86drm.h> + +#include "config.h" + +void print_usage() +{ + fprintf(stderr, "Render Node Remove\n"); + fprintf(stderr, "Usage:\n"); + fprintf(stderr, "\trender_node_rm -? | "); + fprintf(stderr, "[-n control_node_path] -m <minor>\n"); +} + +int main(int argc, char **argv) +{ + int r; + char *control_node; + int minor; + int fd; + + control_node = NULL; + minor = -1; + while ((r = getopt(argc, argv, "n:m:?")) != -1) { + switch (r) { + case 'n': + control_node = optarg; + break; + case 'm': + minor = strtol(optarg, NULL, 0); + break; + case '?': + default: + print_usage(); + return 0; + } + } + if (minor < 0) { + fprintf(stderr, "missing or invalid minor number\n"); + exit(EXIT_FAILURE); + } + if (!control_node) + control_node = "/dev/dri/controlD64"; + printf("control_node = %s\n", control_node); + fd = open(control_node, 0); + if (fd == -1) { + perror(argv[0]); + exit(EXIT_FAILURE); + } + printf("minor = %d\n", minor); + r = drmRemoveRenderNode(fd, minor); + close(fd); + if (r) { + perror(argv[0]); + exit(EXIT_FAILURE); + } + return 0; +}
dri-devel@lists.freedesktop.org