[PATCH] Add simple g2dtest

Joonyoung Shim jy0922.shim at samsung.com
Thu Mar 15 23:13:45 PDT 2012


This can test only solid color fill.

Signed-off-by: Joonyoung Shim <jy0922.shim at samsung.com>
---
 configure.ac              |    1 +
 include/drm/exynos_drm.h  |  185 ++++++++++++++
 tests/Makefile.am         |    2 +-
 tests/g2dtest/Makefile.am |   16 ++
 tests/g2dtest/g2d.h       |   64 +++++
 tests/g2dtest/g2d_reg.h   |  108 ++++++++
 tests/g2dtest/g2dtest.c   |  612 +++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 987 insertions(+), 1 deletions(-)
 create mode 100644 include/drm/exynos_drm.h
 create mode 100644 tests/g2dtest/Makefile.am
 create mode 100644 tests/g2dtest/g2d.h
 create mode 100644 tests/g2dtest/g2d_reg.h
 create mode 100644 tests/g2dtest/g2dtest.c

diff --git a/configure.ac b/configure.ac
index 71a596c..1b51b65 100644
--- a/configure.ac
+++ b/configure.ac
@@ -297,6 +297,7 @@ AC_CONFIG_FILES([
 	tests/kmstest/Makefile
 	tests/radeon/Makefile
 	tests/vbltest/Makefile
+	tests/g2dtest/Makefile
 	include/Makefile
 	include/drm/Makefile
 	libdrm.pc])
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
new file mode 100644
index 0000000..701dbd9
--- /dev/null
+++ b/include/drm/exynos_drm.h
@@ -0,0 +1,185 @@
+/* exynos_drm.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *	Inki Dae <inki.dae at samsung.com>
+ *	Joonyoung Shim <jy0922.shim at samsung.com>
+ *	Seung-Woo Kim <sw0312.kim at samsung.com>
+ *
+ * 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
+ * VA LINUX SYSTEMS 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.
+ */
+
+#ifndef _EXYNOS_DRM_H_
+#define _EXYNOS_DRM_H_
+
+#include "drm.h"
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ *	- this size value would be page-aligned internally.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ *	- this handle will be set by gem module of kernel side.
+ */
+struct drm_exynos_gem_create {
+	uint64_t size;
+	unsigned int flags;
+	unsigned int handle;
+};
+
+/**
+ * A structure for getting buffer offset.
+ *
+ * @handle: a pointer to gem object created.
+ * @pad: just padding to be 64-bit aligned.
+ * @offset: relatived offset value of the memory region allocated.
+ *	- this value should be set by user.
+ */
+struct drm_exynos_gem_map_off {
+	unsigned int handle;
+	unsigned int pad;
+	uint64_t offset;
+};
+
+/**
+ * A structure for mapping buffer.
+ *
+ * @handle: a handle to gem object created.
+ * @size: memory size to be mapped.
+ * @mapped: having user virtual address mmaped.
+ *	- this variable would be filled by exynos gem module
+ *	of kernel side with user virtual address which is allocated
+ *	by do_mmap().
+ */
+struct drm_exynos_gem_mmap {
+	unsigned int handle;
+	unsigned int size;
+	uint64_t mapped;
+};
+
+/**
+ * A structure for user connection request of virtual display.
+ *
+ * @connection: indicate whether doing connetion or not by user.
+ * @extensions: if this value is 1 then the vidi driver would need additional
+ *	128bytes edid data.
+ * @pad: just padding to be 64-bit aligned.
+ * @edid: the edid data pointer from user side.
+ */
+struct drm_exynos_vidi_connection {
+	unsigned int connection;
+	unsigned int extensions;
+	unsigned int pad;
+	void *edid;
+};
+
+struct drm_exynos_plane_set_zpos {
+	__u32 crtc_id;
+	__u32 plane_id;
+	__s32 zpos;
+	__u32 pad;
+};
+
+/* memory type definitions. */
+enum e_drm_exynos_gem_mem_type {
+	/* Physically Non-Continuous memory. */
+	EXYNOS_BO_NONCONTIG	= 1 << 0
+};
+
+struct drm_exynos_g2d_get_ver {
+	__u32	major;
+	__u32	minor;
+};
+
+struct drm_exynos_g2d_cmd {
+	__u32	offset;
+	__u32	data;
+};
+
+enum drm_exynos_g2d_event_type {
+	G2D_EVENT_NOT,
+	G2D_EVENT_NONSTOP,
+	G2D_EVENT_STOP,		/* not yet */
+};
+
+struct drm_exynos_g2d_set_cmdlist {
+	struct drm_exynos_g2d_cmd		*cmd;
+	struct drm_exynos_g2d_cmd		*cmd_gem;
+	__u32					cmd_nr;
+	__u32					cmd_gem_nr;
+
+	/* for g2d event */
+	__u64					event_type;
+	__u64					user_data;
+};
+
+struct drm_exynos_g2d_exec {
+	__u64					async;
+};
+
+#define DRM_EXYNOS_GEM_CREATE		0x00
+#define DRM_EXYNOS_GEM_MAP_OFFSET	0x01
+#define DRM_EXYNOS_GEM_MMAP		0x02
+/* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
+#define DRM_EXYNOS_PLANE_SET_ZPOS	0x06
+#define DRM_EXYNOS_VIDI_CONNECTION	0x07
+
+/* G2D */
+#define DRM_EXYNOS_G2D_GET_VER		0x20
+#define DRM_EXYNOS_G2D_SET_CMDLIST	0x21
+#define DRM_EXYNOS_G2D_EXEC		0x22
+
+#define DRM_IOCTL_EXYNOS_GEM_CREATE		DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
+
+#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET	DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off)
+
+#define DRM_IOCTL_EXYNOS_GEM_MMAP	DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
+
+#define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS	DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos)
+
+#define DRM_IOCTL_EXYNOS_VIDI_CONNECTION	DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection)
+
+#define DRM_IOCTL_EXYNOS_G2D_GET_VER		DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_G2D_GET_VER, struct drm_exynos_g2d_get_ver)
+#define DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST	DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_G2D_SET_CMDLIST, struct drm_exynos_g2d_set_cmdlist)
+#define DRM_IOCTL_EXYNOS_G2D_EXEC		DRM_IOWR(DRM_COMMAND_BASE + \
+		DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
+
+/* EXYNOS specific events */
+#define DRM_EXYNOS_G2D_EVENT		0x80000000
+
+struct drm_exynos_g2d_event {
+	struct drm_event	base;
+	__u64			user_data;
+	__u32			tv_sec;
+	__u32			tv_usec;
+	__u32			cmdlist_no;
+	__u32			reserved;
+};
+
+#endif
diff --git a/tests/Makefile.am b/tests/Makefile.am
index a3a59bd..58a4d36 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -13,7 +13,7 @@ check_PROGRAMS = \
 SUBDIRS = modeprint
 
 if HAVE_LIBKMS
-SUBDIRS += kmstest modetest
+SUBDIRS += kmstest modetest g2dtest
 endif
 
 if HAVE_RADEON
diff --git a/tests/g2dtest/Makefile.am b/tests/g2dtest/Makefile.am
new file mode 100644
index 0000000..17d78cf
--- /dev/null
+++ b/tests/g2dtest/Makefile.am
@@ -0,0 +1,16 @@
+AM_CFLAGS = \
+	-I$(top_srcdir)/include/drm \
+	-I$(top_srcdir)/libkms/ \
+	-I$(top_srcdir) \
+	$(CAIRO_CFLAGS)
+
+noinst_PROGRAMS = \
+	g2dtest
+
+g2dtest_SOURCES = \
+	g2dtest.c
+
+g2dtest_LDADD = \
+	$(top_builddir)/libdrm.la \
+	$(top_builddir)/libkms/libkms.la \
+	$(CAIRO_LIBS)
diff --git a/tests/g2dtest/g2d.h b/tests/g2dtest/g2d.h
new file mode 100644
index 0000000..1a62880
--- /dev/null
+++ b/tests/g2dtest/g2d.h
@@ -0,0 +1,64 @@
+#ifndef _G2D_H_
+#define _G2D_H_
+
+#include "g2d_reg.h"
+
+typedef enum {
+	G2D_SELECT_MODE_NORMAL = (0 << 0),
+	G2D_SELECT_MODE_FGCOLOR = (1 << 0),
+	G2D_SELECT_MODE_BGCOLOR = (2 << 0),
+	G2D_SELECT_MODE_MAX = (3 << 0),
+} G2dSelectMode;
+
+typedef enum {
+	/* COLOR FORMAT */
+	G2D_COLOR_FMT_XRGB8888,
+	G2D_COLOR_FMT_ARGB8888,
+	G2D_COLOR_FMT_RGB565,
+	G2D_COLOR_FMT_XRGB1555,
+	G2D_COLOR_FMT_ARGB1555,
+	G2D_COLOR_FMT_XRGB4444,
+	G2D_COLOR_FMT_ARGB4444,
+	G2D_COLOR_FMT_PRGB888,
+	G2D_COLOR_FMT_YCbCr444,
+	G2D_COLOR_FMT_YCbCr422,
+	G2D_COLOR_FMT_YCbCr420 = 10,
+	G2D_COLOR_FMT_A8,                       /* alpha 8bit */
+	G2D_COLOR_FMT_L8,                       /* Luminance 8bit: gray color */
+	G2D_COLOR_FMT_A1,                       /* alpha 1bit */
+	G2D_COLOR_FMT_A4,                       /* alpha 4bit */
+	G2D_COLOR_FMT_MASK = (15 << 0),		/* VER4.1 */
+
+	/* COLOR ORDER */
+	G2D_ORDER_AXRGB = (0 << 4),			/* VER4.1 */
+	G2D_ORDER_RGBAX = (1 << 4),			/* VER4.1 */
+	G2D_ORDER_AXBGR = (2 << 4),			/* VER4.1 */
+	G2D_ORDER_BGRAX = (3 << 4),			/* VER4.1 */
+	G2D_ORDER_MASK = (3 << 4),			/* VER4.1 */
+
+	/* Number of YCbCr plane */
+	G2D_YCbCr_1PLANE = (0 << 8),			/* VER4.1 */
+	G2D_YCbCr_2PLANE = (1 << 8),			/* VER4.1 */
+	G2D_YCbCr_PLANE_MASK = (3 << 8),		/* VER4.1 */
+
+	/* Order in YCbCr */
+	G2D_YCbCr_ORDER_CrY1CbY0 = (0 << 12),		/* VER4.1 */
+	G2D_YCbCr_ORDER_CbY1CrY0 = (1 << 12),		/* VER4.1 */
+	G2D_YCbCr_ORDER_Y1CrY0Cb = (2 << 12),		/* VER4.1 */
+	G2D_YCbCr_ORDER_Y1CbY0Cr = (3 << 12),		/* VER4.1 */
+	G2D_YCbCr_ORDER_MASK = (3 < 12),		/* VER4.1 */
+
+	/* CSC */
+	G2D_CSC_601 = (0 << 16),			/* VER4.1 */
+	G2D_CSC_709 = (1 << 16),			/* VER4.1 */
+	G2D_CSC_MASK = (1 << 16),			/* VER4.1 */
+
+	/* Valid value range of YCbCr */
+	G2D_YCbCr_RANGE_NARROW = (0 << 17),		/* VER4.1 */
+	G2D_YCbCr_RANGE_WIDE = (1 << 17),		/* VER4.1 */
+	G2D_YCbCr_RANGE_MASK= (1 << 17),		/* VER4.1 */
+
+	G2D_COLOR_MODE_MASK = 0xFFFFFFFF
+} G2dColorMode;
+
+#endif /* _G2D_H_ */
diff --git a/tests/g2dtest/g2d_reg.h b/tests/g2dtest/g2d_reg.h
new file mode 100644
index 0000000..b991681
--- /dev/null
+++ b/tests/g2dtest/g2d_reg.h
@@ -0,0 +1,108 @@
+#ifndef _G2D_REG_H_
+#define _G2D_REG_H_
+
+/* Registers */
+/* GEBERAL REGISTER */
+#define SOFT_RESET_REG			(0x0000)
+#define INTEN_REG			(0x0004)
+#define INTC_PEND_REG			(0x000c)
+#define FIFO_STAT_REG			(0x0010)
+#define AXI_MODE_REG			(0x001C)
+#define DMA_SFR_BASE_ADDR_REG		(0x0080)
+#define DMA_COMMAND_REG			(0x0084)
+#define DMA_EXE_LIST_NUM_REG		(0x0088)
+#define DMA_STATUS_REG			(0x008C)
+#define DMA_HOLD_CMD_REG		(0x0090)
+
+/* COMMAND REGISTER */
+#define BITBLT_START_REG		(0x0100)
+#define BITBLT_COMMAND_REG		(0x0104)
+#define BLEND_FUNCTION_REG		(0x0108)	/* VER4.1 */
+#define ROUND_MODE_REG			(0x010C)	/* VER4.1 */
+
+/* PARAMETER SETTING REGISTER */
+
+/*	ROTATE and DIRECTION	*/
+#define ROTATE_REG			(0x0200)
+#define SRC_MASK_DIRECT_REG		(0x0204)
+#define DST_PAT_DIRECT_REG		(0x0208)
+
+/*	SOURCE	*/
+#define SRC_SELECT_REG			(0x0300)
+#define SRC_BASE_ADDR_REG		(0x0304)
+#define SRC_STRIDE_REG			(0x0308)
+#define SRC_COLOR_MODE_REG		(0x030c)
+#define SRC_LEFT_TOP_REG		(0x0310)
+#define SRC_RIGHT_BOTTOM_REG		(0x0314)
+#define SRC_PLANE2_BASE_ADDR_REG	(0x0318)	/* VER4.1 */
+#define SRC_REPEAT_MODE_REG		(0x031C)
+#define SRC_PAD_VALUE_REG		(0x0320)
+#define SRC_A8_RGB_EXT_REG		(0x0324)
+#define SRC_SCALE_CTRL_REG		(0x0328)
+#define SRC_XSCALE_REG			(0x032C)
+#define SRC_YSCALE_REG			(0x0330)
+
+/*	DESTINATION	*/
+#define DST_SELECT_REG			(0x0400)
+#define DST_BASE_ADDR_REG		(0x0404)
+#define DST_STRIDE_REG			(0x0408)
+#define DST_COLOR_MODE_REG		(0x040C)
+#define DST_LEFT_TOP_REG		(0x0410)
+#define DST_RIGHT_BOTTOM_REG		(0x0414)
+#define DST_PLANE2_BASE_ADDR_REG	(0x0418)	/* VER4.1 */
+#define DST_A8_RGB_EXT_REG		(0x041C)
+
+/*	PATTERN	*/
+#define PAT_BASE_ADDR_REG		(0x0500)
+#define PAT_SIZE_REG			(0x0504)
+#define PAT_COLOR_MODE_REG		(0x0508)
+#define PAT_OFFSET_REG			(0x050C)
+#define PAT_STRIDE_REG			(0x0510)
+
+/*	MASK	*/
+#define MASK_BASE_ADDR_REG		(0x0520)
+#define MASK_STRIDE_REG			(0x0524)
+#define MASK_LEFT_TOP_REG		(0x0528)	/* VER4.1 */
+#define MASK_RIGHT_BOTTOM_REG		(0x052C)	/* VER4.1 */
+#define MASK_MODE_REG			(0x0530)	/* VER4.1 */
+#define MASK_REPEAT_MODE_REG		(0x0534)
+#define MASK_PAD_VALUE_REG		(0x0538)
+#define MASK_SCALE_CTRL_REG		(0x053C)
+#define MASK_XSCALE_REG			(0x0540)
+#define MASK_YSCALE_REG			(0x0544)
+
+/* CLIPPING WINDOW */
+#define CW_LT_REG			(0x0600)
+#define CW_RB_REG			(0x0604)
+
+/* ROP & ALPHA SETTING */
+#define THIRD_OPERAND_REG		(0x0610)
+#define ROP4_REG			(0x0614)
+#define ALPHA_REG			(0x0618)
+
+/* COLOR SETTING */
+#define FG_COLOR_REG			(0x0700)
+#define BG_COLOR_REG			(0x0704)
+#define BS_COLOR_REG			(0x0708)
+#define SF_COLOR_REG			(0x070C)	/* VER4.1 */
+
+/* COLOR KEY */
+#define SRC_COLORKEY_CTRL_REG		(0x0710)
+#define SRC_COLORKEY_DR_MIN_REG		(0x0714)
+#define SRC_COLORKEY_DR_MAX_REG		(0x0718)
+#define DST_COLORKEY_CTRL_REG		(0x071C)
+#define DST_COLORKEY_DR_MIN_REG		(0x0720)
+#define DST_COLORKEY_DR_MAX_REG		(0x0724)
+/*	YCbCr src Color Key	*/
+#define YCbCr_SRC_COLORKEY_CTRL_REG	(0x0728)	/* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MIN_REG	(0x072C)	/* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MAX_REG	(0x0730)	/* VER4.1 */
+/*	YCbCr dst Color Key	*/
+#define YCbCr_DST_COLORKEY_CTRL_REG	(0x0734)	/* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MIN_REG	(0x0738)	/* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MAX_REG	(0x073C)	/* VER4.1 */
+
+/* bits of BITBLT_COMMAND_REG */
+#define	G2D_FAST_SOLID_COLOR_FILL	(1 << 28)
+
+#endif /* _G2D_REG_H_ */
diff --git a/tests/g2dtest/g2dtest.c b/tests/g2dtest/g2dtest.c
new file mode 100644
index 0000000..4521cd4
--- /dev/null
+++ b/tests/g2dtest/g2dtest.c
@@ -0,0 +1,612 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "exynos_drm.h"
+#include "drm_fourcc.h"
+#include "g2d.h"
+
+#define DRM_MODULE_NAME		"exynos-drm"
+
+struct connector {
+	uint32_t id;
+	char mode_str[64];
+	drmModeModeInfo *mode;
+	drmModeEncoder *encoder;
+	int crtc;
+	int plane_zpos;
+	unsigned int fb_id[2], current_fb_id;
+	struct timeval start;
+
+	int swap_count;
+};
+
+struct drm_buffer {
+	struct drm_exynos_gem_create	gem;
+	struct drm_exynos_gem_mmap	gem_mmap;
+};
+
+struct drm_fb {
+	uint32_t			id;
+	struct drm_buffer		drm_buffer;
+};
+
+struct drm_desc {
+	int				fd;
+	struct connector		connector;
+	int				plane_id[5];
+	int				width;
+	int				height;
+};
+
+enum format {
+	FMT_RGB565,
+	FMT_RGB888,
+	FMT_NV12M,
+};
+
+static void connector_find_mode(int fd, struct connector *c,
+				drmModeRes *resources)
+{
+	drmModeConnector *connector;
+	int i, j;
+
+	/* First, find the connector & mode */
+	c->mode = NULL;
+	for (i = 0; i < resources->count_connectors; i++) {
+		connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+		if (!connector) {
+			fprintf(stderr, "could not get connector %i: %s\n",
+				resources->connectors[i], strerror(errno));
+			drmModeFreeConnector(connector);
+			continue;
+		}
+
+		if (!connector->count_modes) {
+			drmModeFreeConnector(connector);
+			continue;
+		}
+
+		if (connector->connector_id != c->id) {
+			drmModeFreeConnector(connector);
+			continue;
+		}
+
+		for (j = 0; j < connector->count_modes; j++) {
+			c->mode = &connector->modes[j];
+			if (!strcmp(c->mode->name, c->mode_str))
+				break;
+		}
+
+		/* Found it, break out */
+		if (c->mode)
+			break;
+
+		drmModeFreeConnector(connector);
+	}
+
+	if (!c->mode) {
+		fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
+		return;
+	}
+
+	/* Now get the encoder */
+	for (i = 0; i < resources->count_encoders; i++) {
+		c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+		if (!c->encoder) {
+			fprintf(stderr, "could not get encoder %i: %s\n",
+				resources->encoders[i], strerror(errno));
+			drmModeFreeEncoder(c->encoder);
+			continue;
+		}
+
+		if (c->encoder->encoder_id  == connector->encoder_id)
+			break;
+
+		drmModeFreeEncoder(c->encoder);
+	}
+
+	if (c->crtc == -1)
+		c->crtc = c->encoder->crtc_id;
+}
+
+static int connector_find_plane(int fd, unsigned int *plane_id)
+{
+	drmModePlaneRes *plane_resources;
+	drmModePlane *ovr;
+	int i;
+
+	plane_resources = drmModeGetPlaneResources(fd);
+	if (!plane_resources) {
+		fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
+			strerror(errno));
+		return -1;
+	}
+
+	for (i = 0; i < plane_resources->count_planes; i++) {
+		plane_id[i] = 0;
+
+		ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
+		if (!ovr) {
+			fprintf(stderr, "drmModeGetPlane failed: %s\n",
+				strerror(errno));
+			continue;
+		}
+
+		if (ovr->possible_crtcs & (1 << 0))
+			plane_id[i] = ovr->plane_id;
+		drmModeFreePlane(ovr);
+	}
+
+	return 0;
+}
+
+static int exynos_g2d_get_ver(int fd, struct drm_exynos_g2d_get_ver *ver)
+{
+	int ret;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_GET_VER, ver);
+	if (ret < 0) {
+		fprintf(stderr, "failed to get version: %s\n", strerror(-ret));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int exynos_g2d_set_cmdlist(int fd,
+				  struct drm_exynos_g2d_set_cmdlist *cmdlist)
+{
+	int ret;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST, cmdlist);
+	if (ret < 0) {
+		fprintf(stderr, "failed to set cmdlist: %s\n", strerror(-ret));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int exynos_g2d_exec(int fd, int async)
+{
+	struct drm_exynos_g2d_exec exec;
+	int ret;
+
+	exec.async = async;
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_EXEC, &exec);
+	if (ret < 0) {
+		fprintf(stderr, "failed to execute: %s\n", strerror(-ret));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int exynos_plane_set_zpos(int fd, unsigned int plane_id, int zpos)
+{
+	struct drm_exynos_plane_set_zpos zpos_req;
+	int ret;
+
+	zpos_req.plane_id = plane_id;
+	zpos_req.zpos = zpos;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS, &zpos_req);
+	if (ret < 0) {
+		fprintf(stderr, "failed to set plane zpos: %s\n",
+				strerror(-ret));
+		return ret;
+	}
+
+	return 0;
+}
+
+static int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem)
+{
+	int ret;
+
+	if (!gem)
+		return -EINVAL;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, gem);
+	if (ret < 0)
+		perror("ioctl failed\n");
+
+	return ret;
+}
+
+static int exynos_gem_map_offset(int fd, struct drm_exynos_gem_map_off *map_off)
+{
+	int ret;
+
+	if (!map_off)
+		return -EINVAL;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET, map_off);
+	if (ret < 0)
+		perror("ioctl failed\n");
+
+	return ret;
+}
+
+static int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
+{
+	int ret;
+
+	if (!in_mmap)
+		return -EINVAL;
+
+	ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MMAP, in_mmap);
+	if (ret < 0)
+		perror("ioctl failed\n");
+
+	return ret;
+}
+
+static int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
+{
+	int ret;
+
+	if (!gem_close)
+		return -EINVAL;
+
+	ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, gem_close);
+	if (ret < 0)
+		perror("ioctl failed\n");
+
+	return ret;
+}
+
+static struct drm_desc *drm_alloc_desc(void)
+{
+	struct drm_desc *drm_desc;
+
+	drm_desc = malloc(sizeof(struct drm_desc));
+	if (!drm_desc) {
+		perror("memory alloc error\n");
+		return NULL;
+	}
+	memset(drm_desc, 0, sizeof(struct drm_desc));
+
+	return drm_desc;
+}
+
+static int drm_open(struct drm_desc *drm_desc)
+{
+	if (!drm_desc) {
+		fprintf(stderr, "drm_desc is NULL\n");
+		return -EINVAL;
+	}
+
+	drm_desc->fd = drmOpen(DRM_MODULE_NAME, NULL);
+	if (drm_desc->fd < 0) {
+		printf("Failed to open %s module\n", DRM_MODULE_NAME);
+		return drm_desc->fd;
+	}
+
+	return 0;
+}
+
+static int drm_create_buffer(struct drm_desc *drm_desc, struct drm_fb *drm_fb,
+			     int width, int height)
+{
+	struct drm_buffer *drm_buffer;
+	unsigned int num_planes;
+	unsigned long size;
+	int i;
+	int ret;
+
+	if (!drm_desc)
+		return -EINVAL;
+
+	size = width * height * 4;
+
+	drm_buffer = &drm_fb->drm_buffer;
+
+	{
+		struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+		struct drm_exynos_gem_mmap *gem_mmap = &drm_buffer->gem_mmap;
+
+		memset(gem, 0, sizeof(struct drm_exynos_gem_create));
+		gem->size = size;
+
+		ret = exynos_gem_create(drm_desc->fd, gem);
+		if (ret < 0) {
+			printf("failed to create gem\n");
+			goto err_gem;
+		}
+
+		gem_mmap->handle = gem->handle;
+		gem_mmap->size = gem->size;
+		ret = exynos_gem_mmap(drm_desc->fd, gem_mmap);
+		if (ret < 0) {
+			printf("failed to mmap gem directly\n");
+			goto err_gem;
+		}
+
+		/* init gem buffer */
+		memset((void *)(unsigned long)gem_mmap->mapped, 0,
+				gem_mmap->size);
+	}
+
+	return 0;
+
+err_gem:
+	{
+		struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+		struct drm_gem_close gem_close;
+
+		gem_close.handle = gem->handle;
+		exynos_gem_close(drm_desc->fd, &gem_close);
+	}
+
+	return ret;
+}
+
+static int drm_create_fb(struct drm_desc *drm_desc, struct drm_fb *drm_fb,
+			 int width, int height)
+{
+	unsigned int pixel_format;
+	unsigned int num_planes;
+	unsigned int pitch;
+	int i;
+	int j;
+	int ret;
+
+	if (!drm_desc)
+		return -EINVAL;
+
+	drm_desc->width = width;
+	drm_desc->height = height;
+
+	pixel_format = DRM_FORMAT_RGBA8888;
+	num_planes = 1;
+	pitch = width * 4;
+
+	{
+		uint32_t bo[4] = {0,};
+		uint32_t pitches[4] = {0,};
+		uint32_t offset[4] = {0,};
+
+		ret = drm_create_buffer(drm_desc, drm_fb, width, height);
+		if (ret < 0)
+			goto err;
+
+		for (j = 0; j < num_planes; j++) {
+			struct drm_buffer *drm_buffer = &drm_fb->drm_buffer;
+			struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+
+			bo[j] = gem->handle;
+			pitches[j] = pitch;
+		}
+
+		ret = drmModeAddFB2(drm_desc->fd, width, height, pixel_format,
+				bo, pitches, offset, &drm_fb->id,
+				0);
+		if (ret < 0) {
+			perror("failed to add fb\n");
+			goto err;
+		}
+	}
+
+	return 0;
+
+err:
+	/* TODO: free buffer */
+	return ret;
+}
+
+static int drm_set_crtc(struct drm_desc *drm_desc, struct connector *c,
+			struct drm_fb *drm_fb)
+{
+	drmModeRes *resources;
+	int ret;
+
+	memcpy(&drm_desc->connector, c, sizeof(struct connector));
+
+	resources = drmModeGetResources(drm_desc->fd);
+	if (!resources) {
+		fprintf(stderr, "drmModeGetResources failed: %s\n",
+			strerror(errno));
+		ret = -EFAULT;
+		goto err;
+	}
+
+	connector_find_mode(drm_desc->fd, &drm_desc->connector, resources);
+	drmModeFreeResources(resources);
+
+	ret = drmModeSetCrtc(drm_desc->fd, drm_desc->connector.crtc,
+			drm_fb->id, 0, 0,
+			&drm_desc->connector.id, 1,
+			drm_desc->connector.mode);
+	if (ret) {
+		fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
+		goto err;
+	}
+
+	return 0;
+
+err:
+	/* TODO */
+	return ret;
+}
+
+static inline void set_cmd(struct drm_exynos_g2d_cmd *cmd,
+				      __u32 offset, __u32 data)
+{
+	cmd->offset = offset;
+	cmd->data = data;
+}
+
+static int exynos_g2d_test_solid_fill(struct drm_desc *drm_desc, int x, int y,
+				      int color, int gem_handle)
+{
+	struct drm_exynos_g2d_set_cmdlist cmdlist;
+	struct drm_exynos_g2d_cmd cmd[20];
+	struct drm_exynos_g2d_cmd cmd_gem[5];
+	int nr = 0;
+	int gem_nr = 0;
+	int ret;
+
+	memset(&cmdlist, 0, sizeof(struct drm_exynos_g2d_set_cmdlist));
+	memset(cmd, 0, sizeof(struct drm_exynos_g2d_cmd) * 20);
+	memset(cmd_gem, 0, sizeof(struct drm_exynos_g2d_cmd) * 5);
+
+	cmdlist.cmd = cmd;
+	cmdlist.cmd_gem = cmd_gem;
+
+	set_cmd(&cmd[nr++], BITBLT_COMMAND_REG, G2D_FAST_SOLID_COLOR_FILL);
+	/* [14:10] R, [9:5] G, [4:0] B */
+	set_cmd(&cmd[nr++], SF_COLOR_REG, color);
+
+	/* DST */
+	set_cmd(&cmd[nr++], DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+	set_cmd(&cmd_gem[gem_nr++], DST_BASE_ADDR_REG, gem_handle);
+	set_cmd(&cmd[nr++], DST_STRIDE_REG, 720 * 4);
+	set_cmd(&cmd[nr++], DST_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 |
+						G2D_ORDER_AXRGB);
+	set_cmd(&cmd[nr++], DST_LEFT_TOP_REG, (0 << 16) | 0);
+	set_cmd(&cmd[nr++], DST_RIGHT_BOTTOM_REG, (y << 16) | x);
+	set_cmd(&cmd[nr++], DST_PLANE2_BASE_ADDR_REG, 0);
+	set_cmd(&cmd[nr++], DST_A8_RGB_EXT_REG, 0);
+
+	cmdlist.cmd_nr = nr;
+	cmdlist.cmd_gem_nr = gem_nr;
+
+	cmdlist.event_type = G2D_EVENT_NONSTOP;
+	cmdlist.user_data = 1234;
+
+	ret = exynos_g2d_set_cmdlist(drm_desc->fd, &cmdlist);
+	if (ret < 0)
+		return ret;
+}
+
+static int exynos_g2d_event(int fd)
+{
+	char buffer[1024];
+	int len, i;
+	struct drm_event *e;
+	struct drm_exynos_g2d_event *g2d_event;
+
+	len = read(fd, buffer, sizeof buffer);
+	if (len == 0)
+		return 0;
+	if (len < sizeof *e)
+		return -1;
+
+	i = 0;
+	while (i < len) {
+		e = (struct drm_event *) &buffer[i];
+		switch (e->type) {
+		case DRM_EXYNOS_G2D_EVENT:
+			g2d_event = (struct drm_exynos_g2d_event *) e;
+			printf("cmdlist_no: %d\n", g2d_event->cmdlist_no);
+			printf("user_data: %lld\n", g2d_event->user_data);
+			break;
+		default:
+			break;
+		}
+		i += e->length;
+	}
+
+	return 0;
+}
+
+int main(int argc, char **argv)
+{
+	struct connector con_args;
+	struct drm_desc *drm_desc;
+	struct drm_fb drm_fb;
+	struct drm_exynos_g2d_get_ver ver;
+	int x, y;
+	int ret;
+
+	/* default set of connector */
+	memset(&con_args, 0, sizeof(struct connector));
+	con_args.id = 12;
+	con_args.crtc = 3;
+	con_args.plane_zpos = -1;
+	strcpy(con_args.mode_str, "720x1280");
+	x = 720;
+	y = 1280;
+
+	drm_desc = drm_alloc_desc();
+	if (!drm_desc) {
+		ret = -1;
+		goto err_free;
+	}
+
+	ret = drm_open(drm_desc);
+	if (ret < 0)
+		goto err_free;
+
+	/* check version */
+	ret = exynos_g2d_get_ver(drm_desc->fd, &ver);
+	if (ret < 0)
+		return ret;
+
+	if (ver.major != 4 || ver.minor != 1) {
+		fprintf(stderr, "version(%d.%d) mismatch\n", ver.major, ver.minor);
+		return -1;
+	}
+	printf("g2d hw version: %d.%d\n", ver.major, ver.minor);
+
+	ret = drm_create_fb(drm_desc, &drm_fb, x, y);
+	if (ret < 0)
+		goto err_drm_close;
+
+	ret = drm_set_crtc(drm_desc, &con_args, &drm_fb);
+	if (ret < 0)
+		goto err;
+
+	getchar();
+
+	ret = exynos_g2d_test_solid_fill(drm_desc, x, y, 0x1f,
+					 drm_fb.drm_buffer.gem.handle);
+	if (ret < 0)
+		goto err;
+
+	ret = exynos_g2d_exec(drm_desc->fd, 1);
+	if (ret < 0)
+		return ret;
+
+	while (1) {
+		struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+		fd_set fds;
+		int ret;
+
+		FD_ZERO(&fds);
+		FD_SET(0, &fds);
+		FD_SET(drm_desc->fd, &fds);
+		ret = select(drm_desc->fd + 1, &fds, NULL, NULL, &timeout);
+
+		if (ret <= 0) {
+			fprintf(stderr, "select timed out or error (ret %d)\n",
+				ret);
+			continue;
+		} else if (FD_ISSET(0, &fds)) {
+			break;
+		}
+
+		exynos_g2d_event(drm_desc->fd);
+	}
+
+	getchar();
+
+	/* TODO */
+
+err:
+	/* TODO */
+err_drm_close:
+	drmClose(drm_desc->fd);
+err_free:
+	if (drm_desc)
+		free(drm_desc);
+
+	return ret;
+}
-- 
1.7.5.4


--------------040707050107050602080100--


More information about the dri-devel mailing list