[Piglit] [v2 2/3] framework: gbm: support for creating external buffers

Topi Pohjolainen topi.pohjolainen at intel.com
Fri Mar 8 01:29:21 PST 2013


Getting direct access to the gbm device through the waffle display
and creating the buffer is rather straightforward thing to do.
Writing to the buffer using CPU, however, requires priviledges for
the underlying gem-ioctl.

v2:
  - support for NV12 formatted buffers in addition to YV12

Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 .../piglit-framework-gl/piglit_gbm_framework.c     |  108 ++++++++++++++++++++
 1 file changed, 108 insertions(+)

diff --git a/tests/util/piglit-framework-gl/piglit_gbm_framework.c b/tests/util/piglit-framework-gl/piglit_gbm_framework.c
index 4df3861..2af081b 100644
--- a/tests/util/piglit-framework-gl/piglit_gbm_framework.c
+++ b/tests/util/piglit-framework-gl/piglit_gbm_framework.c
@@ -24,10 +24,18 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <waffle.h>
+#include <waffle_gbm.h>
+#include <gbm.h>
+#include <libdrm/drm.h>
+#include <libdrm/i915_drm.h>
+#include <sys/ioctl.h>
 
 #include "piglit-util-gl-common.h"
 #include "piglit_gbm_framework.h"
 
+#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
+
 static void
 enter_event_loop(struct piglit_winsys_framework *winsys_fw)
 {
@@ -51,6 +59,102 @@ destroy(struct piglit_gl_framework *gl_fw)
 	free(winsys_fw);
 }
 
+static void *
+map(struct gbm_device *gbm, struct gbm_bo *bo, unsigned n_bytes)
+{
+        int res;
+        struct drm_i915_gem_mmap mmap_arg;
+
+        mmap_arg.handle = gbm_bo_get_handle(bo).u32;
+        mmap_arg.offset = 0;
+        mmap_arg.size = n_bytes;
+
+        res = ioctl(gbm_device_get_fd(gbm), DRM_IOCTL_I915_GEM_MMAP, &mmap_arg);
+
+        if (res)
+                return 0;
+
+        return (void *)(uintptr_t)mmap_arg.addr_ptr;
+}
+
+/* At the time of writing this, GBM did not have any alignment
+ * restrictions on height or width.
+ */
+static void *
+create_ext_420_buffer(struct piglit_gl_framework *gl_fw,
+		      unsigned w, unsigned h, bool swap_vu,
+		      const void *y, const void *u, const void *v)
+{
+	struct waffle_gbm_display *native = waffle_display_get_native(
+		piglit_wfl_framework(gl_fw)->display)->gbm;
+	struct gbm_bo *bo = gbm_bo_create(native->gbm_device, w, h,
+				swap_vu ? GBM_FORMAT_YVU420 : GBM_FORMAT_YUV420,
+				GBM_BO_USE_RENDERING);
+	unsigned char *p;
+	unsigned y_off = 0;
+	unsigned u_off = ALIGN(w * h, 4096);
+	unsigned v_off = u_off + ALIGN((w / 2) * (h / 2), 4096);
+	unsigned total = v_off + ALIGN((w / 2) * (h / 2), 4096);
+
+	if (!bo)
+		return NULL;
+
+	p = (unsigned char *)map(native->gbm_device, bo, total);
+
+	if (!p) {
+		gbm_bo_destroy(bo);
+		return NULL;
+	}
+
+	memcpy(p + y_off, y, w * h);
+
+	if (swap_vu) {
+		memcpy(p + u_off, v, (w / 2) * (h / 2));
+		memcpy(p + v_off, u, (w / 2) * (h / 2));
+	} else {
+		memcpy(p + u_off, u, (w / 2) * (h / 2));
+		memcpy(p + v_off, v, (w / 2) * (h / 2));
+	}
+
+	return bo;
+}
+
+static void *
+create_ext_nv12_buffer(struct piglit_gl_framework *gl_fw,
+		       unsigned w, unsigned h, const void *y, const void *uv)
+{
+	struct waffle_gbm_display *native = waffle_display_get_native(
+		piglit_wfl_framework(gl_fw)->display)->gbm;
+	struct gbm_bo *bo = gbm_bo_create(native->gbm_device, w, h,
+				GBM_FORMAT_NV12, GBM_BO_USE_RENDERING);
+	unsigned char *p;
+	unsigned y_off = 0;
+	unsigned uv_off = ALIGN(w * h, 4096);
+	unsigned total = uv_off + ALIGN(w * (h / 2), 4096);
+
+	if (!bo)
+		return NULL;
+
+	p = (unsigned char *)map(native->gbm_device, bo, total);
+
+	if (!p) {
+		gbm_bo_destroy(bo);
+		return NULL;
+	}
+
+	memcpy(p + y_off, y, w * h);
+	memcpy(p + uv_off, uv, w * (h / 2));
+
+	return bo;
+}
+
+static void
+destroy_ext_buffer(struct piglit_gl_framework *gl_fw, void *buf)
+{
+	(void)gl_fw;
+	gbm_bo_destroy((struct gbm_bo *)buf);
+}
+
 struct piglit_gl_framework*
 piglit_gbm_framework_create(const struct piglit_gl_test_config *test_config)
 {
@@ -70,6 +174,10 @@ piglit_gbm_framework_create(const struct piglit_gl_test_config *test_config)
 	winsys_fw->enter_event_loop = enter_event_loop;
 	gl_fw->destroy = destroy;
 
+	gl_fw->create_external_420_buffer = create_ext_420_buffer;
+	gl_fw->create_external_nv12_buffer = create_ext_nv12_buffer;
+	gl_fw->destroy_external_buffer = destroy_ext_buffer;
+
 	return gl_fw;
 
 fail:
-- 
1.7.9.5



More information about the Piglit mailing list