trinity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Tommi Rantala <tt.rantala@gmail.com>
To: davej@codemonkey.org.uk
Cc: trinity@vger.kernel.org, Tommi Rantala <tt.rantala@gmail.com>
Subject: [PATCH] DRM dumb buffer file descriptors
Date: Wed, 15 Apr 2015 22:39:20 +0300	[thread overview]
Message-ID: <1429126760-32714-1-git-send-email-tt.rantala@gmail.com> (raw)

Use the DRM_IOCTL_MODE_CREATE_DUMB ioctl to make "dumb" buffers; then use
the DRM_IOCTL_PRIME_HANDLE_TO_FD ioctl to get file descriptors.
---
 fd-drm.c          | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 fds.c             |   1 +
 include/drm_fds.h |   6 +++
 include/shm.h     |   2 +
 params.c          |   2 +-
 5 files changed, 153 insertions(+), 1 deletion(-)
 create mode 100644 fd-drm.c
 create mode 100644 include/drm_fds.h

diff --git a/fd-drm.c b/fd-drm.c
new file mode 100644
index 0000000..7772c6a
--- /dev/null
+++ b/fd-drm.c
@@ -0,0 +1,143 @@
+/* DRM FDs */
+
+#include "config.h"
+#include "fd.h"
+#include "log.h"
+#include "memfd.h"
+#include "net.h"
+#include "params.h"
+#include "pids.h"
+#include "random.h"
+#include "sanitise.h"
+#include "shm.h"
+#include "compat.h"
+#include "trinity.h"
+
+static unsigned fd_count;
+
+#ifdef USE_DRM
+
+#include <dirent.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <drm/drm.h>
+
+static int create_dumb(__unused__ int fd)
+{
+#if defined(DRM_IOCTL_MODE_CREATE_DUMB) && defined(DRM_IOCTL_PRIME_HANDLE_TO_FD)
+	struct drm_mode_create_dumb create;
+	struct drm_prime_handle handle_to_fd;
+
+	memset(&create, 0, sizeof(create));
+	create.height = 1 << RAND_RANGE(0, 10);
+	create.width = 1 << RAND_RANGE(0, 10);
+	create.bpp = 32;
+
+	if (ioctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &create) < 0) {
+		return -1;
+	}
+
+	memset(&handle_to_fd, 0, sizeof(handle_to_fd));
+	handle_to_fd.handle = create.handle;
+	if (RAND_BOOL())
+		handle_to_fd.flags = DRM_CLOEXEC;
+
+	if (ioctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &handle_to_fd) < 0) {
+		return -1;
+	}
+
+	return handle_to_fd.fd;
+#else
+	return -1;
+#endif
+}
+
+static int open_drm_fds(void)
+{
+	unsigned int i;
+	int fd, dfd;
+	DIR *dir;
+	struct dirent *entry;
+	char buf[128];
+
+	dir = opendir("/dev/dri/");
+	if (!dir)
+		goto done;
+
+	// Open all /dev/dri/*, and try to make FDs from each of them.
+	while (1) {
+		entry = readdir(dir);
+		if (!entry)
+			break;
+
+		if (strcmp(entry->d_name, ".") == 0 ||
+		    strcmp(entry->d_name, "..") == 0)
+			continue;
+
+		snprintf(buf, sizeof(buf), "/dev/dri/%s", entry->d_name);
+		buf[sizeof(buf)-1] = '\0';
+
+		fd = open(buf, O_RDWR);
+		if (fd < 0) {
+			continue;
+		}
+		shm->drm_fds[fd_count++] = fd;
+
+		if (fd_count >= MAX_DRM_FDS)
+			break;
+
+		dfd = create_dumb(fd);
+		if (dfd < 0) {
+			continue;
+		}
+		shm->drm_fds[fd_count++] = dfd;
+
+		if (fd_count >= MAX_DRM_FDS)
+			break;
+	}
+
+	if (dir)
+		closedir(dir);
+
+	for (i = 0; i < MAX_DRM_FDS; i++) {
+		if (shm->drm_fds[i] > 0) {
+			output(2, "fd[%d] = drm\n", shm->drm_fds[i]);
+		}
+	}
+
+done:
+	if (fd_count == 0)
+		drm_fd_provider.enabled = FALSE;
+
+	return TRUE;
+}
+
+#else
+
+static int open_drm_fds(void) { return TRUE; }
+
+#endif /* USE_DRM */
+
+static int get_rand_drm_fd(void)
+{
+	// We should not be called when fd_count is zero, but avoid div-by-zero
+	// just in case.
+	if (fd_count > 0)
+		return shm->drm_fds[rand() % fd_count];
+	else
+		return -1;
+}
+
+struct fd_provider drm_fd_provider = {
+	.name = "drm",
+	.enabled = TRUE,
+	.open = &open_drm_fds,
+	.get = &get_rand_drm_fd,
+};
diff --git a/fds.c b/fds.c
index fbb2bba..a3a70f9 100644
--- a/fds.c
+++ b/fds.c
@@ -56,6 +56,7 @@ void setup_fd_providers(void)
 	add_to_prov_list(&timerfd_fd_provider);
 	add_to_prov_list(&testfile_fd_provider);
 	add_to_prov_list(&memfd_fd_provider);
+	add_to_prov_list(&drm_fd_provider);
 
 	output(0, "Registered %d fd providers.\n", num_fd_providers);
 }
diff --git a/include/drm_fds.h b/include/drm_fds.h
new file mode 100644
index 0000000..3c70b33
--- /dev/null
+++ b/include/drm_fds.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include "fd.h"
+struct fd_provider drm_fd_provider;
+
+#define MAX_DRM_FDS 8
diff --git a/include/shm.h b/include/shm.h
index 16a5994..673ed1b 100644
--- a/include/shm.h
+++ b/include/shm.h
@@ -2,6 +2,7 @@
 
 #include "arch.h"
 #include "child.h"
+#include "drm_fds.h"
 #include "epoll.h"
 #include "eventfd.h"
 #include "exit.h"
@@ -61,6 +62,7 @@ struct shm_s {
 	int timerfd_fds[MAX_TIMERFD_FDS];
 	int testfile_fds[MAX_TESTFILE_FDS];
 	int memfd_fds[MAX_MEMFD_FDS];
+	int drm_fds[MAX_DRM_FDS];
 	struct socketinfo sockets[NR_SOCKET_FDS];
 	int current_fd;
 	unsigned int fd_lifetime;
diff --git a/params.c b/params.c
index 53861a5..96c737c 100644
--- a/params.c
+++ b/params.c
@@ -60,7 +60,7 @@ char server_addr[INET6_ADDRSTRLEN] = "\0";
 
 void enable_disable_fd_usage(void)
 {
-	outputerr(" --enable-fds/--disable-fds= {sockets,pipes,perf,epoll,eventfd,pseudo,timerfd,testfile,memfd}\n");
+	outputerr(" --enable-fds/--disable-fds= {sockets,pipes,perf,epoll,eventfd,pseudo,timerfd,testfile,memfd,drm}\n");
 }
 
 static void usage(void)
-- 
2.1.0

                 reply	other threads:[~2015-04-15 19:39 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1429126760-32714-1-git-send-email-tt.rantala@gmail.com \
    --to=tt.rantala@gmail.com \
    --cc=davej@codemonkey.org.uk \
    --cc=trinity@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).