[Piglit] [PATCH] framework: support for creating dma buffers through libdrm (v4)

Chad Versace chad.versace at linux.intel.com
Tue May 14 18:37:41 PDT 2013


From: Topi Pohjolainen <topi.pohjolainen at intel.com>

In order to test EXT_image_dma_buf_import one needs the capability
of creating driver specific buffers. By probing the environment for
drm libraries one can decide for which drivers the support is to
be built.

v2 (first five according to Chad's advice):
   - replace manual search for drm with 'pkg_check_modules()'
   - move BATCH_SZ into intel specific part
   - use ARRAY_SIZE
   - fix faulty check for mem-allocation (drm_buf vs. buf)
   - define the opaque type piglit_dma_buf declared in platform
     independent interface instead of introducing new local type
     (piglit_drm_dma_buf)
   - use 'drm_intel_bo_subdata()' instead of mapping the buffers
     for CPU
   - also set the support for GBM in addition to X11

v3:
   - fix a type (does -> doesn't)
   - exclude intel driver entry points when the driver is not
     present

v4: [chadv]
    - Fix tests to work as non-root user. Get DRM authentication before
      calling intel_bufmgr_gem_init().

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---

This patch now makes X a requirement to run these tests. However, the tests
are now actually runnable as non-root. In a follow-up series, we should
generalize the test so that it works on any system where i915 is present: X11,
Wayland, or Android.

My philosophy here is to get the test working first, then make it
cross-platform later.

 tests/util/CMakeLists.txt                          |  34 +++
 .../util/piglit-framework-gl/piglit_drm_dma_buf.c  | 266 +++++++++++++++++++++
 .../util/piglit-framework-gl/piglit_drm_dma_buf.h  |  37 +++
 .../piglit-framework-gl/piglit_gbm_framework.c     |   5 +
 .../piglit-framework-gl/piglit_x11_framework.c     |   5 +
 5 files changed, 347 insertions(+)
 create mode 100644 tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
 create mode 100644 tests/util/piglit-framework-gl/piglit_drm_dma_buf.h

diff --git a/tests/util/CMakeLists.txt b/tests/util/CMakeLists.txt
index cbcf050..479a23e 100644
--- a/tests/util/CMakeLists.txt
+++ b/tests/util/CMakeLists.txt
@@ -51,6 +51,40 @@ set(UTIL_GL_LIBS
 	)
 
 if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+	pkg_check_modules(LIBDRM QUIET libdrm)
+	pkg_check_modules(LIBDRM_INTEL QUIET libdrm_intel)
+	pkg_check_modules(XCB_DRI2 QUIET xcb-dri2)
+
+	# One needs to have at least one hardware driver present, otherwise
+	# there is no point compiling just the dispatcher.
+        #
+        # xcb-dri2 is used to gain DRM authentication.
+        if(LIBDRM_FOUND AND LIBDRM_INTEL_FOUND AND XCB_DRI2_FOUND)
+		add_definitions(-DHAVE_LIBDRM)
+
+		list(APPEND UTIL_GL_SOURCES
+			piglit-framework-gl/piglit_drm_dma_buf.c
+		)
+
+		list(APPEND UTIL_GL_LIBS
+			${LIBDRM_LDFLAGS}
+			${XCB_DRI2_LDFLAGS}
+		)
+
+		list(APPEND UTIL_GL_INCLUDES
+			${LIBDRM_INCLUDE_DIRS}
+			${XCB_DRI2_INCLUDE_DIRS}
+		)
+
+		if(LIBDRM_INTEL_FOUND)
+			add_definitions(-DHAVE_LIBDRM_INTEL)
+
+			list(APPEND UTIL_GL_LIBS
+				${LIBDRM_INTEL_LDFLAGS}
+			)
+		endif()
+	endif()
+
 	set(UTIL_GL_LIBS
 		${UTIL_GL_LIBS}
 		${X11_X11_LIB}
diff --git a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
new file mode 100644
index 0000000..0fcce01
--- /dev/null
+++ b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+
+#include "piglit-util-gl-common.h"
+#include "piglit_drm_dma_buf.h"
+#ifdef HAVE_LIBDRM_INTEL
+#include <libdrm/intel_bufmgr.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <xf86drm.h>
+#include <xcb/dri2.h>
+#include <drm.h>
+
+static const char *drm_device_filename = "/dev/dri/card0";
+
+#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
+
+struct piglit_dma_buf {
+	unsigned w;
+	unsigned h;
+	unsigned stride;
+	int fd;
+	void *priv;
+};
+
+struct piglit_drm_driver {
+	const char *name;
+
+	int
+	(*create)(unsigned w, unsigned h, unsigned cpp,
+		  const unsigned char *src_data, unsigned src_stride,
+		  struct piglit_dma_buf *buf);
+
+	int
+	(*export)(struct piglit_dma_buf *buf);
+
+	void
+	(*destroy)(struct piglit_dma_buf *buf);
+};
+
+static int
+piglit_drm_device_get(void)
+{
+	static int fd = 0;
+
+	if (fd)
+		return fd;
+
+	fd = open(drm_device_filename, O_RDWR);
+
+	return fd;
+}
+
+static int
+piglit_drm_x11_authenticate(void)
+{
+	drm_magic_t magic;
+	xcb_connection_t *conn;
+	int screen;
+	xcb_screen_iterator_t screen_iter;
+	xcb_dri2_authenticate_cookie_t auth_cookie;
+	xcb_dri2_authenticate_reply_t *auth_reply;
+	int ret = 0;
+
+	conn = xcb_connect(NULL, &screen);
+	if (!conn) {
+		printf("piglit: failed to connect to X server for DRI2 "
+		       "authentication\n");
+		return -1;
+	}
+
+	ret = drmGetMagic(piglit_drm_device_get(), &magic);
+	if (ret) {
+		printf("piglit: failed to get DRM magic\n");
+		return -1;
+	}
+
+	screen_iter = xcb_setup_roots_iterator(xcb_get_setup(conn));
+	auth_cookie = xcb_dri2_authenticate_unchecked(conn,
+	                                              screen_iter.data->root,
+	                                              magic);
+	auth_reply = xcb_dri2_authenticate_reply(conn, auth_cookie, NULL);
+
+	if (auth_reply == NULL || !auth_reply->authenticated) {
+		printf("piglit: failed to authenticate with DRI2\n");
+		return -1;
+	}
+	free(auth_reply);
+
+	return 0;
+}
+
+#ifdef HAVE_LIBDRM_INTEL
+static drm_intel_bufmgr *
+piglit_intel_bufmgr_get(void)
+{
+	static const unsigned batch_sz = 8192 * sizeof(uint32_t);
+	static drm_intel_bufmgr *mgr = NULL;
+
+	if (mgr)
+		return mgr;
+
+	if (!piglit_drm_device_get())
+		return NULL;
+
+	if (piglit_drm_x11_authenticate() < 0)
+		return NULL;
+
+	mgr = intel_bufmgr_gem_init(piglit_drm_device_get(), batch_sz);
+
+	return mgr;
+}
+
+static int
+piglit_intel_buf_create(unsigned w, unsigned h, unsigned cpp,
+			const unsigned char *src_data, unsigned src_stride,
+			struct piglit_dma_buf *buf)
+{
+	unsigned i;
+	drm_intel_bo *bo;
+	unsigned stride = ALIGN(w * cpp, 4);
+	drm_intel_bufmgr *mgr = piglit_intel_bufmgr_get();
+
+	if (!mgr || src_stride > stride || h % 2)
+		return -1;
+
+	bo = drm_intel_bo_alloc(mgr, "piglit_dma_buf", h * stride, 4096);
+	if (!bo)
+		return -1;
+
+	for (i = 0; i < h; ++i) {
+		if (drm_intel_bo_subdata(bo, i * stride, src_stride,
+			src_data + i * src_stride)) {
+			drm_intel_bo_unreference(bo);
+			return -1;
+		}
+	}
+
+	buf->w = w;
+	buf->h = h;
+	buf->stride = stride;
+	buf->priv = bo;
+
+	return 0;
+}
+
+static int
+piglit_intel_buf_export(struct piglit_dma_buf *buf)
+{
+	if (drm_intel_bo_gem_export_to_prime((drm_intel_bo *)buf->priv,
+					&buf->fd)) {
+		drm_intel_bo_unreference((drm_intel_bo *)buf->priv);
+		return -1;
+	}
+
+	return 0;
+}
+
+static void
+piglit_intel_buf_destroy(struct piglit_dma_buf *buf)
+{
+	drm_intel_bo_unreference((drm_intel_bo *)buf->priv);
+}
+#endif /* HAVE_LIBDRM_INTEL */
+
+/**
+ * The framework makes sure one doesn't try to compile without any hardware
+ * support.
+ */
+static const struct piglit_drm_driver piglit_drm_drivers[] = {
+#ifdef HAVE_LIBDRM_INTEL
+	{ "i915", piglit_intel_buf_create, piglit_intel_buf_export,
+	   piglit_intel_buf_destroy }
+#endif /* HAVE_LIBDRM_INTEL */
+};
+
+static const struct piglit_drm_driver *
+piglit_drm_get_driver(void)
+{
+	unsigned i;
+	drmVersionPtr version;
+	int fd = piglit_drm_device_get();
+
+	if (!fd)
+		return NULL;
+
+	version = drmGetVersion(fd);
+	if (!version || !version->name)
+		return NULL;
+
+	for (i = 0; i < ARRAY_SIZE(piglit_drm_drivers); ++i) {
+		if (strcmp(piglit_drm_drivers[i].name, version->name) == 0)
+			return &piglit_drm_drivers[i];
+	}
+
+	return NULL;
+}
+
+enum piglit_result
+piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
+			const void *src_data, unsigned src_stride,
+			struct piglit_dma_buf **buf, int *fd,
+			unsigned *stride, unsigned *offset)
+{
+	struct piglit_dma_buf *drm_buf;
+	const struct piglit_drm_driver *drv = piglit_drm_get_driver();
+
+	if (!drv)
+		return PIGLIT_SKIP;
+
+	drm_buf = calloc(sizeof(struct piglit_dma_buf), 1);
+	if (!drm_buf)
+		return PIGLIT_FAIL;
+
+	if (drv->create(w, h, cpp, src_data, src_stride, drm_buf)) {
+		free(drm_buf);
+		return PIGLIT_FAIL;
+	}
+
+	if (drv->export(drm_buf)) {
+		free(drm_buf);
+		return PIGLIT_FAIL;
+	}
+
+	*buf = drm_buf;
+	*fd = drm_buf->fd;
+	*stride = drm_buf->stride;
+	*offset = 0;
+
+	return PIGLIT_PASS;
+}
+
+void
+piglit_drm_destroy_dma_buf(struct piglit_dma_buf *buf)
+{
+	const struct piglit_drm_driver *drv = piglit_drm_get_driver();
+
+	if (!drv)
+		return;
+
+	drv->destroy(buf);
+	free(buf);
+}
diff --git a/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h
new file mode 100644
index 0000000..2c72eca
--- /dev/null
+++ b/tests/util/piglit-framework-gl/piglit_drm_dma_buf.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ */
+#ifndef PIGLIT_DRM_DMA_BUF_H
+#define PIGLIT_DRM_DMA_BUF_H
+
+struct piglit_dma_buf;
+
+enum piglit_result
+piglit_drm_create_dma_buf(unsigned w, unsigned h, unsigned cpp,
+			  const void *src_data, unsigned src_stride,
+			  struct piglit_dma_buf **buf, int *fd,
+			  unsigned *stride, unsigned *offset);
+
+void
+piglit_drm_destroy_dma_buf(struct piglit_dma_buf *buf);
+
+#endif /* PIGLIT_DRM_DMA_BUF_H */
diff --git a/tests/util/piglit-framework-gl/piglit_gbm_framework.c b/tests/util/piglit-framework-gl/piglit_gbm_framework.c
index 4df3861..67ca21f 100644
--- a/tests/util/piglit-framework-gl/piglit_gbm_framework.c
+++ b/tests/util/piglit-framework-gl/piglit_gbm_framework.c
@@ -27,6 +27,7 @@
 
 #include "piglit-util-gl-common.h"
 #include "piglit_gbm_framework.h"
+#include "piglit_drm_dma_buf.h"
 
 static void
 enter_event_loop(struct piglit_winsys_framework *winsys_fw)
@@ -69,6 +70,10 @@ piglit_gbm_framework_create(const struct piglit_gl_test_config *test_config)
 	winsys_fw->show_window = show_window;
 	winsys_fw->enter_event_loop = enter_event_loop;
 	gl_fw->destroy = destroy;
+#ifdef HAVE_LIBDRM
+	gl_fw->create_dma_buf = piglit_drm_create_dma_buf;
+	gl_fw->destroy_dma_buf = piglit_drm_destroy_dma_buf;
+#endif
 
 	return gl_fw;
 
diff --git a/tests/util/piglit-framework-gl/piglit_x11_framework.c b/tests/util/piglit-framework-gl/piglit_x11_framework.c
index dafd370..6cbc122 100644
--- a/tests/util/piglit-framework-gl/piglit_x11_framework.c
+++ b/tests/util/piglit-framework-gl/piglit_x11_framework.c
@@ -57,6 +57,7 @@
 
 #include "piglit_gl_framework.h"
 #include "piglit_x11_framework.h"
+#include "piglit_drm_dma_buf.h"
 
 struct piglit_x11_framework {
 	struct piglit_winsys_framework winsys_fw;
@@ -215,6 +216,10 @@ piglit_x11_framework_create(const struct piglit_gl_test_config *test_config,
 	winsys_fw->show_window = show_window;
 	winsys_fw->enter_event_loop = enter_event_loop;
 	gl_fw->destroy = destroy;
+#ifdef HAVE_LIBDRM
+	gl_fw->create_dma_buf = piglit_drm_create_dma_buf;
+	gl_fw->destroy_dma_buf = piglit_drm_destroy_dma_buf;
+#endif
 
 	return gl_fw;
 
-- 
1.8.1.4



More information about the Piglit mailing list