1d722e3fbSopenharmony_ci/*
2d722e3fbSopenharmony_ci * Copyright (C) 2013 Samsung Electronics Co.Ltd
3d722e3fbSopenharmony_ci * Authors:
4d722e3fbSopenharmony_ci *	Inki Dae <inki.dae@samsung.com>
5d722e3fbSopenharmony_ci *
6d722e3fbSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7d722e3fbSopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8d722e3fbSopenharmony_ci * to deal in the Software without restriction, including without limitation
9d722e3fbSopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10d722e3fbSopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11d722e3fbSopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12d722e3fbSopenharmony_ci *
13d722e3fbSopenharmony_ci * The above copyright notice and this permission notice (including the next
14d722e3fbSopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
15d722e3fbSopenharmony_ci * Software.
16d722e3fbSopenharmony_ci *
17d722e3fbSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18d722e3fbSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19d722e3fbSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20d722e3fbSopenharmony_ci * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21d722e3fbSopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22d722e3fbSopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23d722e3fbSopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
24d722e3fbSopenharmony_ci */
25d722e3fbSopenharmony_ci
26d722e3fbSopenharmony_ci#include <stdlib.h>
27d722e3fbSopenharmony_ci#include <stdio.h>
28d722e3fbSopenharmony_ci#include <string.h>
29d722e3fbSopenharmony_ci#include <errno.h>
30d722e3fbSopenharmony_ci#include <time.h>
31d722e3fbSopenharmony_ci#include <unistd.h>
32d722e3fbSopenharmony_ci
33d722e3fbSopenharmony_ci#include <sys/mman.h>
34d722e3fbSopenharmony_ci#include <linux/stddef.h>
35d722e3fbSopenharmony_ci
36d722e3fbSopenharmony_ci#include <xf86drm.h>
37d722e3fbSopenharmony_ci#include <xf86drmMode.h>
38d722e3fbSopenharmony_ci#include <drm_fourcc.h>
39d722e3fbSopenharmony_ci
40d722e3fbSopenharmony_ci#include "exynos_drm.h"
41d722e3fbSopenharmony_ci#include "exynos_drmif.h"
42d722e3fbSopenharmony_ci#include "exynos_fimg2d.h"
43d722e3fbSopenharmony_ci
44d722e3fbSopenharmony_ci#define DRM_MODULE_NAME		"exynos"
45d722e3fbSopenharmony_ci
46d722e3fbSopenharmony_cistatic unsigned int screen_width, screen_height;
47d722e3fbSopenharmony_ci
48d722e3fbSopenharmony_cistruct connector {
49d722e3fbSopenharmony_ci	uint32_t id;
50d722e3fbSopenharmony_ci	char mode_str[64];
51d722e3fbSopenharmony_ci	drmModeModeInfo *mode;
52d722e3fbSopenharmony_ci	drmModeEncoder *encoder;
53d722e3fbSopenharmony_ci	int crtc;
54d722e3fbSopenharmony_ci};
55d722e3fbSopenharmony_ci
56d722e3fbSopenharmony_cistatic void connector_find_mode(int fd, struct connector *c,
57d722e3fbSopenharmony_ci				drmModeRes *resources)
58d722e3fbSopenharmony_ci{
59d722e3fbSopenharmony_ci	drmModeConnector *connector;
60d722e3fbSopenharmony_ci	int i, j;
61d722e3fbSopenharmony_ci
62d722e3fbSopenharmony_ci	/* First, find the connector & mode */
63d722e3fbSopenharmony_ci	c->mode = NULL;
64d722e3fbSopenharmony_ci	for (i = 0; i < resources->count_connectors; i++) {
65d722e3fbSopenharmony_ci		connector = drmModeGetConnector(fd, resources->connectors[i]);
66d722e3fbSopenharmony_ci
67d722e3fbSopenharmony_ci		if (!connector) {
68d722e3fbSopenharmony_ci			fprintf(stderr, "could not get connector %i: %s\n",
69d722e3fbSopenharmony_ci				resources->connectors[i], strerror(errno));
70d722e3fbSopenharmony_ci			continue;
71d722e3fbSopenharmony_ci		}
72d722e3fbSopenharmony_ci
73d722e3fbSopenharmony_ci		if (!connector->count_modes) {
74d722e3fbSopenharmony_ci			drmModeFreeConnector(connector);
75d722e3fbSopenharmony_ci			continue;
76d722e3fbSopenharmony_ci		}
77d722e3fbSopenharmony_ci
78d722e3fbSopenharmony_ci		if (connector->connector_id != c->id) {
79d722e3fbSopenharmony_ci			drmModeFreeConnector(connector);
80d722e3fbSopenharmony_ci			continue;
81d722e3fbSopenharmony_ci		}
82d722e3fbSopenharmony_ci
83d722e3fbSopenharmony_ci		for (j = 0; j < connector->count_modes; j++) {
84d722e3fbSopenharmony_ci			c->mode = &connector->modes[j];
85d722e3fbSopenharmony_ci			if (!strcmp(c->mode->name, c->mode_str))
86d722e3fbSopenharmony_ci				break;
87d722e3fbSopenharmony_ci		}
88d722e3fbSopenharmony_ci
89d722e3fbSopenharmony_ci		/* Found it, break out */
90d722e3fbSopenharmony_ci		if (c->mode)
91d722e3fbSopenharmony_ci			break;
92d722e3fbSopenharmony_ci
93d722e3fbSopenharmony_ci		drmModeFreeConnector(connector);
94d722e3fbSopenharmony_ci	}
95d722e3fbSopenharmony_ci
96d722e3fbSopenharmony_ci	if (!c->mode) {
97d722e3fbSopenharmony_ci		fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
98d722e3fbSopenharmony_ci		return;
99d722e3fbSopenharmony_ci	}
100d722e3fbSopenharmony_ci
101d722e3fbSopenharmony_ci	/* Now get the encoder */
102d722e3fbSopenharmony_ci	for (i = 0; i < resources->count_encoders; i++) {
103d722e3fbSopenharmony_ci		c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
104d722e3fbSopenharmony_ci
105d722e3fbSopenharmony_ci		if (!c->encoder) {
106d722e3fbSopenharmony_ci			fprintf(stderr, "could not get encoder %i: %s\n",
107d722e3fbSopenharmony_ci				resources->encoders[i], strerror(errno));
108d722e3fbSopenharmony_ci			continue;
109d722e3fbSopenharmony_ci		}
110d722e3fbSopenharmony_ci
111d722e3fbSopenharmony_ci		if (c->encoder->encoder_id  == connector->encoder_id)
112d722e3fbSopenharmony_ci			break;
113d722e3fbSopenharmony_ci
114d722e3fbSopenharmony_ci		drmModeFreeEncoder(c->encoder);
115d722e3fbSopenharmony_ci	}
116d722e3fbSopenharmony_ci
117d722e3fbSopenharmony_ci	if (c->crtc == -1)
118d722e3fbSopenharmony_ci		c->crtc = c->encoder->crtc_id;
119d722e3fbSopenharmony_ci}
120d722e3fbSopenharmony_ci
121d722e3fbSopenharmony_cistatic int drm_set_crtc(struct exynos_device *dev, struct connector *c,
122d722e3fbSopenharmony_ci			unsigned int fb_id)
123d722e3fbSopenharmony_ci{
124d722e3fbSopenharmony_ci	int ret;
125d722e3fbSopenharmony_ci
126d722e3fbSopenharmony_ci	ret = drmModeSetCrtc(dev->fd, c->crtc,
127d722e3fbSopenharmony_ci			fb_id, 0, 0, &c->id, 1, c->mode);
128d722e3fbSopenharmony_ci	if (ret)
129d722e3fbSopenharmony_ci		drmMsg("failed to set mode: %s\n", strerror(errno));
130d722e3fbSopenharmony_ci
131d722e3fbSopenharmony_ci	return ret;
132d722e3fbSopenharmony_ci}
133d722e3fbSopenharmony_ci
134d722e3fbSopenharmony_cistatic struct exynos_bo *exynos_create_buffer(struct exynos_device *dev,
135d722e3fbSopenharmony_ci						unsigned long size,
136d722e3fbSopenharmony_ci						unsigned int flags)
137d722e3fbSopenharmony_ci{
138d722e3fbSopenharmony_ci	struct exynos_bo *bo;
139d722e3fbSopenharmony_ci
140d722e3fbSopenharmony_ci	bo = exynos_bo_create(dev, size, flags);
141d722e3fbSopenharmony_ci	if (!bo)
142d722e3fbSopenharmony_ci		return bo;
143d722e3fbSopenharmony_ci
144d722e3fbSopenharmony_ci	if (!exynos_bo_map(bo)) {
145d722e3fbSopenharmony_ci		exynos_bo_destroy(bo);
146d722e3fbSopenharmony_ci		return NULL;
147d722e3fbSopenharmony_ci	}
148d722e3fbSopenharmony_ci
149d722e3fbSopenharmony_ci	return bo;
150d722e3fbSopenharmony_ci}
151d722e3fbSopenharmony_ci
152d722e3fbSopenharmony_ci/* Allocate buffer and fill it with checkerboard pattern, where the tiles *
153d722e3fbSopenharmony_ci * have a random color. The caller has to free the buffer.                */
154d722e3fbSopenharmony_cistatic void *create_checkerboard_pattern(unsigned int num_tiles_x,
155d722e3fbSopenharmony_ci						unsigned int num_tiles_y, unsigned int tile_size)
156d722e3fbSopenharmony_ci{
157d722e3fbSopenharmony_ci	unsigned int *buf;
158d722e3fbSopenharmony_ci	unsigned int x, y, i, j;
159d722e3fbSopenharmony_ci	const unsigned int stride = num_tiles_x * tile_size;
160d722e3fbSopenharmony_ci
161d722e3fbSopenharmony_ci	if (posix_memalign((void*)&buf, 64, num_tiles_y * tile_size * stride * 4) != 0)
162d722e3fbSopenharmony_ci		return NULL;
163d722e3fbSopenharmony_ci
164d722e3fbSopenharmony_ci	for (x = 0; x < num_tiles_x; ++x) {
165d722e3fbSopenharmony_ci		for (y = 0; y < num_tiles_y; ++y) {
166d722e3fbSopenharmony_ci			const unsigned int color = 0xff000000 + (random() & 0xffffff);
167d722e3fbSopenharmony_ci
168d722e3fbSopenharmony_ci			for (i = 0; i < tile_size; ++i) {
169d722e3fbSopenharmony_ci				for (j = 0; j < tile_size; ++j) {
170d722e3fbSopenharmony_ci					buf[x * tile_size + y * stride * tile_size + i + j * stride] = color;
171d722e3fbSopenharmony_ci				}
172d722e3fbSopenharmony_ci			}
173d722e3fbSopenharmony_ci		}
174d722e3fbSopenharmony_ci	}
175d722e3fbSopenharmony_ci
176d722e3fbSopenharmony_ci	return buf;
177d722e3fbSopenharmony_ci}
178d722e3fbSopenharmony_ci
179d722e3fbSopenharmony_cistatic void exynos_destroy_buffer(struct exynos_bo *bo)
180d722e3fbSopenharmony_ci{
181d722e3fbSopenharmony_ci	exynos_bo_destroy(bo);
182d722e3fbSopenharmony_ci}
183d722e3fbSopenharmony_ci
184d722e3fbSopenharmony_cistatic void wait_for_user_input(int last)
185d722e3fbSopenharmony_ci{
186d722e3fbSopenharmony_ci	printf("press <ENTER> to %s\n", last ? "exit test application" :
187d722e3fbSopenharmony_ci			"skip to next test");
188d722e3fbSopenharmony_ci
189d722e3fbSopenharmony_ci	getchar();
190d722e3fbSopenharmony_ci}
191d722e3fbSopenharmony_ci
192d722e3fbSopenharmony_cistatic int g2d_solid_fill_test(struct exynos_device *dev, struct exynos_bo *dst)
193d722e3fbSopenharmony_ci{
194d722e3fbSopenharmony_ci	struct g2d_context *ctx;
195d722e3fbSopenharmony_ci	struct g2d_image img = {0};
196d722e3fbSopenharmony_ci	unsigned int count, img_w, img_h;
197d722e3fbSopenharmony_ci	int ret = 0;
198d722e3fbSopenharmony_ci
199d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
200d722e3fbSopenharmony_ci	if (!ctx)
201d722e3fbSopenharmony_ci		return -EFAULT;
202d722e3fbSopenharmony_ci
203d722e3fbSopenharmony_ci	img.bo[0] = dst->handle;
204d722e3fbSopenharmony_ci
205d722e3fbSopenharmony_ci	printf("solid fill test.\n");
206d722e3fbSopenharmony_ci
207d722e3fbSopenharmony_ci	srand(time(NULL));
208d722e3fbSopenharmony_ci	img_w = screen_width;
209d722e3fbSopenharmony_ci	img_h = screen_height;
210d722e3fbSopenharmony_ci
211d722e3fbSopenharmony_ci	for (count = 0; count < 2; count++) {
212d722e3fbSopenharmony_ci		unsigned int x, y, w, h;
213d722e3fbSopenharmony_ci
214d722e3fbSopenharmony_ci		x = rand() % (img_w / 2);
215d722e3fbSopenharmony_ci		y = rand() % (img_h / 2);
216d722e3fbSopenharmony_ci		w = rand() % (img_w - x);
217d722e3fbSopenharmony_ci		h = rand() % (img_h - y);
218d722e3fbSopenharmony_ci
219d722e3fbSopenharmony_ci		img.width = img_w;
220d722e3fbSopenharmony_ci		img.height = img_h;
221d722e3fbSopenharmony_ci		img.stride = img.width * 4;
222d722e3fbSopenharmony_ci		img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
223d722e3fbSopenharmony_ci		img.color = 0xff000000 + (random() & 0xffffff);
224d722e3fbSopenharmony_ci
225d722e3fbSopenharmony_ci		ret = g2d_solid_fill(ctx, &img, x, y, w, h);
226d722e3fbSopenharmony_ci		if (ret < 0)
227d722e3fbSopenharmony_ci			goto err_fini;
228d722e3fbSopenharmony_ci
229d722e3fbSopenharmony_ci		ret = g2d_exec(ctx);
230d722e3fbSopenharmony_ci		if (ret < 0)
231d722e3fbSopenharmony_ci			break;
232d722e3fbSopenharmony_ci	}
233d722e3fbSopenharmony_ci
234d722e3fbSopenharmony_cierr_fini:
235d722e3fbSopenharmony_ci	g2d_fini(ctx);
236d722e3fbSopenharmony_ci
237d722e3fbSopenharmony_ci	return ret;
238d722e3fbSopenharmony_ci}
239d722e3fbSopenharmony_ci
240d722e3fbSopenharmony_cistatic int g2d_copy_test(struct exynos_device *dev, struct exynos_bo *src,
241d722e3fbSopenharmony_ci				struct exynos_bo *dst,
242d722e3fbSopenharmony_ci				enum e_g2d_buf_type type)
243d722e3fbSopenharmony_ci{
244d722e3fbSopenharmony_ci	struct g2d_context *ctx;
245d722e3fbSopenharmony_ci	struct g2d_image src_img = {0}, dst_img = {0};
246d722e3fbSopenharmony_ci	unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
247d722e3fbSopenharmony_ci	unsigned long userptr, size;
248d722e3fbSopenharmony_ci	int ret;
249d722e3fbSopenharmony_ci
250d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
251d722e3fbSopenharmony_ci	if (!ctx)
252d722e3fbSopenharmony_ci		return -EFAULT;
253d722e3fbSopenharmony_ci
254d722e3fbSopenharmony_ci	dst_img.bo[0] = dst->handle;
255d722e3fbSopenharmony_ci
256d722e3fbSopenharmony_ci	src_x = 0;
257d722e3fbSopenharmony_ci	src_y = 0;
258d722e3fbSopenharmony_ci	dst_x = 0;
259d722e3fbSopenharmony_ci	dst_y = 0;
260d722e3fbSopenharmony_ci	img_w = screen_width;
261d722e3fbSopenharmony_ci	img_h = screen_height;
262d722e3fbSopenharmony_ci
263d722e3fbSopenharmony_ci	switch (type) {
264d722e3fbSopenharmony_ci	case G2D_IMGBUF_GEM:
265d722e3fbSopenharmony_ci		src_img.bo[0] = src->handle;
266d722e3fbSopenharmony_ci		break;
267d722e3fbSopenharmony_ci	case G2D_IMGBUF_USERPTR:
268d722e3fbSopenharmony_ci		size = img_w * img_h * 4;
269d722e3fbSopenharmony_ci
270d722e3fbSopenharmony_ci		userptr = (unsigned long)malloc(size);
271d722e3fbSopenharmony_ci		if (!userptr) {
272d722e3fbSopenharmony_ci			fprintf(stderr, "failed to allocate userptr.\n");
273d722e3fbSopenharmony_ci			ret = -EFAULT;
274d722e3fbSopenharmony_ci			goto fail;
275d722e3fbSopenharmony_ci		}
276d722e3fbSopenharmony_ci
277d722e3fbSopenharmony_ci		src_img.user_ptr[0].userptr = userptr;
278d722e3fbSopenharmony_ci		src_img.user_ptr[0].size = size;
279d722e3fbSopenharmony_ci		break;
280d722e3fbSopenharmony_ci	case G2D_IMGBUF_COLOR:
281d722e3fbSopenharmony_ci	default:
282d722e3fbSopenharmony_ci		ret = -EFAULT;
283d722e3fbSopenharmony_ci		goto fail;
284d722e3fbSopenharmony_ci	}
285d722e3fbSopenharmony_ci
286d722e3fbSopenharmony_ci	printf("copy test with %s.\n",
287d722e3fbSopenharmony_ci			type == G2D_IMGBUF_GEM ? "gem" : "userptr");
288d722e3fbSopenharmony_ci
289d722e3fbSopenharmony_ci	src_img.width = img_w;
290d722e3fbSopenharmony_ci	src_img.height = img_h;
291d722e3fbSopenharmony_ci	src_img.stride = src_img.width * 4;
292d722e3fbSopenharmony_ci	src_img.buf_type = type;
293d722e3fbSopenharmony_ci	src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
294d722e3fbSopenharmony_ci	src_img.color = 0xffff0000;
295d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
296d722e3fbSopenharmony_ci	if (ret < 0)
297d722e3fbSopenharmony_ci		goto err_free_userptr;
298d722e3fbSopenharmony_ci
299d722e3fbSopenharmony_ci	dst_img.width = img_w;
300d722e3fbSopenharmony_ci	dst_img.height = img_h;
301d722e3fbSopenharmony_ci	dst_img.stride = dst_img.width * 4;
302d722e3fbSopenharmony_ci	dst_img.buf_type = G2D_IMGBUF_GEM;
303d722e3fbSopenharmony_ci	dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
304d722e3fbSopenharmony_ci
305d722e3fbSopenharmony_ci	ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y,
306d722e3fbSopenharmony_ci			img_w - 4, img_h - 4);
307d722e3fbSopenharmony_ci	if (ret < 0)
308d722e3fbSopenharmony_ci		goto err_free_userptr;
309d722e3fbSopenharmony_ci
310d722e3fbSopenharmony_ci	g2d_exec(ctx);
311d722e3fbSopenharmony_ci
312d722e3fbSopenharmony_cierr_free_userptr:
313d722e3fbSopenharmony_ci	if (type == G2D_IMGBUF_USERPTR)
314d722e3fbSopenharmony_ci		if (userptr)
315d722e3fbSopenharmony_ci			free((void *)userptr);
316d722e3fbSopenharmony_ci
317d722e3fbSopenharmony_cifail:
318d722e3fbSopenharmony_ci	g2d_fini(ctx);
319d722e3fbSopenharmony_ci
320d722e3fbSopenharmony_ci	return ret;
321d722e3fbSopenharmony_ci}
322d722e3fbSopenharmony_ci
323d722e3fbSopenharmony_cistatic int g2d_move_test(struct exynos_device *dev,
324d722e3fbSopenharmony_ci				struct exynos_bo *tmp,
325d722e3fbSopenharmony_ci				struct exynos_bo *buf,
326d722e3fbSopenharmony_ci				enum e_g2d_buf_type type)
327d722e3fbSopenharmony_ci{
328d722e3fbSopenharmony_ci	struct g2d_context *ctx;
329d722e3fbSopenharmony_ci	struct g2d_image img = {0}, tmp_img = {0};
330d722e3fbSopenharmony_ci	unsigned int img_w, img_h, count;
331d722e3fbSopenharmony_ci	int cur_x, cur_y;
332d722e3fbSopenharmony_ci	void *checkerboard;
333d722e3fbSopenharmony_ci	int ret;
334d722e3fbSopenharmony_ci
335d722e3fbSopenharmony_ci	static const struct g2d_step {
336d722e3fbSopenharmony_ci		int x, y;
337d722e3fbSopenharmony_ci	} steps[] = {
338d722e3fbSopenharmony_ci		{ 1,  0}, { 0,  1},
339d722e3fbSopenharmony_ci		{-1,  0}, { 0, -1},
340d722e3fbSopenharmony_ci		{ 1,  1}, {-1, -1},
341d722e3fbSopenharmony_ci		{ 1, -1}, {-1,  1},
342d722e3fbSopenharmony_ci		{ 2,  1}, { 1,  2},
343d722e3fbSopenharmony_ci		{-2, -1}, {-1, -2},
344d722e3fbSopenharmony_ci		{ 2, -1}, { 1, -2},
345d722e3fbSopenharmony_ci		{-2,  1}, {-1,  2}
346d722e3fbSopenharmony_ci	};
347d722e3fbSopenharmony_ci	static const unsigned int num_steps =
348d722e3fbSopenharmony_ci		sizeof(steps) / sizeof(struct g2d_step);
349d722e3fbSopenharmony_ci
350d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
351d722e3fbSopenharmony_ci	if (!ctx)
352d722e3fbSopenharmony_ci		return -EFAULT;
353d722e3fbSopenharmony_ci
354d722e3fbSopenharmony_ci	img.bo[0] = buf->handle;
355d722e3fbSopenharmony_ci
356d722e3fbSopenharmony_ci	/* create pattern of half the screen size */
357d722e3fbSopenharmony_ci	checkerboard = create_checkerboard_pattern(screen_width / 64, screen_height / 64, 32);
358d722e3fbSopenharmony_ci	if (!checkerboard) {
359d722e3fbSopenharmony_ci		ret = -EFAULT;
360d722e3fbSopenharmony_ci		goto fail;
361d722e3fbSopenharmony_ci	}
362d722e3fbSopenharmony_ci
363d722e3fbSopenharmony_ci	img_w = (screen_width / 64) * 32;
364d722e3fbSopenharmony_ci	img_h = (screen_height / 64) * 32;
365d722e3fbSopenharmony_ci
366d722e3fbSopenharmony_ci	switch (type) {
367d722e3fbSopenharmony_ci	case G2D_IMGBUF_GEM:
368d722e3fbSopenharmony_ci		memcpy(tmp->vaddr, checkerboard, img_w * img_h * 4);
369d722e3fbSopenharmony_ci		tmp_img.bo[0] = tmp->handle;
370d722e3fbSopenharmony_ci		break;
371d722e3fbSopenharmony_ci	case G2D_IMGBUF_USERPTR:
372d722e3fbSopenharmony_ci		tmp_img.user_ptr[0].userptr = (unsigned long)checkerboard;
373d722e3fbSopenharmony_ci		tmp_img.user_ptr[0].size = img_w * img_h * 4;
374d722e3fbSopenharmony_ci		break;
375d722e3fbSopenharmony_ci	case G2D_IMGBUF_COLOR:
376d722e3fbSopenharmony_ci	default:
377d722e3fbSopenharmony_ci		ret = -EFAULT;
378d722e3fbSopenharmony_ci		goto fail;
379d722e3fbSopenharmony_ci	}
380d722e3fbSopenharmony_ci
381d722e3fbSopenharmony_ci	/* solid fill framebuffer with white color */
382d722e3fbSopenharmony_ci	img.width = screen_width;
383d722e3fbSopenharmony_ci	img.height = screen_height;
384d722e3fbSopenharmony_ci	img.stride = screen_width * 4;
385d722e3fbSopenharmony_ci	img.buf_type = G2D_IMGBUF_GEM;
386d722e3fbSopenharmony_ci	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
387d722e3fbSopenharmony_ci	img.color = 0xffffffff;
388d722e3fbSopenharmony_ci
389d722e3fbSopenharmony_ci	/* put checkerboard pattern in the center of the framebuffer */
390d722e3fbSopenharmony_ci	cur_x = (screen_width - img_w) / 2;
391d722e3fbSopenharmony_ci	cur_y = (screen_height - img_h) / 2;
392d722e3fbSopenharmony_ci	tmp_img.width = img_w;
393d722e3fbSopenharmony_ci	tmp_img.height = img_h;
394d722e3fbSopenharmony_ci	tmp_img.stride = img_w * 4;
395d722e3fbSopenharmony_ci	tmp_img.buf_type = type;
396d722e3fbSopenharmony_ci	tmp_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
397d722e3fbSopenharmony_ci
398d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &img, 0, 0, screen_width, screen_height) ||
399d722e3fbSopenharmony_ci		g2d_copy(ctx, &tmp_img, &img, 0, 0, cur_x, cur_y, img_w, img_h);
400d722e3fbSopenharmony_ci
401d722e3fbSopenharmony_ci	if (!ret)
402d722e3fbSopenharmony_ci		ret = g2d_exec(ctx);
403d722e3fbSopenharmony_ci	if (ret < 0)
404d722e3fbSopenharmony_ci			goto fail;
405d722e3fbSopenharmony_ci
406d722e3fbSopenharmony_ci	printf("move test with %s.\n",
407d722e3fbSopenharmony_ci			type == G2D_IMGBUF_GEM ? "gem" : "userptr");
408d722e3fbSopenharmony_ci
409d722e3fbSopenharmony_ci	srand(time(NULL));
410d722e3fbSopenharmony_ci	for (count = 0; count < 256; ++count) {
411d722e3fbSopenharmony_ci		const struct g2d_step *s;
412d722e3fbSopenharmony_ci
413d722e3fbSopenharmony_ci		/* select step and validate it */
414d722e3fbSopenharmony_ci		while (1) {
415d722e3fbSopenharmony_ci			s = &steps[random() % num_steps];
416d722e3fbSopenharmony_ci
417d722e3fbSopenharmony_ci			if (cur_x + s->x < 0 || cur_y + s->y < 0 ||
418d722e3fbSopenharmony_ci				cur_x + img_w + s->x >= screen_width ||
419d722e3fbSopenharmony_ci				cur_y + img_h + s->y >= screen_height)
420d722e3fbSopenharmony_ci				continue;
421d722e3fbSopenharmony_ci			else
422d722e3fbSopenharmony_ci				break;
423d722e3fbSopenharmony_ci		}
424d722e3fbSopenharmony_ci
425d722e3fbSopenharmony_ci		ret = g2d_move(ctx, &img, cur_x, cur_y, cur_x + s->x, cur_y + s->y,
426d722e3fbSopenharmony_ci			img_w, img_h);
427d722e3fbSopenharmony_ci		if (!ret)
428d722e3fbSopenharmony_ci			ret = g2d_exec(ctx);
429d722e3fbSopenharmony_ci
430d722e3fbSopenharmony_ci		if (ret < 0)
431d722e3fbSopenharmony_ci			goto fail;
432d722e3fbSopenharmony_ci
433d722e3fbSopenharmony_ci		cur_x += s->x;
434d722e3fbSopenharmony_ci		cur_y += s->y;
435d722e3fbSopenharmony_ci
436d722e3fbSopenharmony_ci		usleep(100000);
437d722e3fbSopenharmony_ci	}
438d722e3fbSopenharmony_ci
439d722e3fbSopenharmony_cifail:
440d722e3fbSopenharmony_ci	g2d_fini(ctx);
441d722e3fbSopenharmony_ci
442d722e3fbSopenharmony_ci	free(checkerboard);
443d722e3fbSopenharmony_ci
444d722e3fbSopenharmony_ci	return ret;
445d722e3fbSopenharmony_ci}
446d722e3fbSopenharmony_ci
447d722e3fbSopenharmony_cistatic int g2d_copy_with_scale_test(struct exynos_device *dev,
448d722e3fbSopenharmony_ci					struct exynos_bo *src,
449d722e3fbSopenharmony_ci					struct exynos_bo *dst,
450d722e3fbSopenharmony_ci					enum e_g2d_buf_type type)
451d722e3fbSopenharmony_ci{
452d722e3fbSopenharmony_ci	struct g2d_context *ctx;
453d722e3fbSopenharmony_ci	struct g2d_image src_img = {0}, dst_img = {0};
454d722e3fbSopenharmony_ci	unsigned int src_x, src_y, img_w, img_h;
455d722e3fbSopenharmony_ci	unsigned long userptr, size;
456d722e3fbSopenharmony_ci	int ret;
457d722e3fbSopenharmony_ci
458d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
459d722e3fbSopenharmony_ci	if (!ctx)
460d722e3fbSopenharmony_ci		return -EFAULT;
461d722e3fbSopenharmony_ci
462d722e3fbSopenharmony_ci	dst_img.bo[0] = dst->handle;
463d722e3fbSopenharmony_ci
464d722e3fbSopenharmony_ci	src_x = 0;
465d722e3fbSopenharmony_ci	src_y = 0;
466d722e3fbSopenharmony_ci	img_w = screen_width;
467d722e3fbSopenharmony_ci	img_h = screen_height;
468d722e3fbSopenharmony_ci
469d722e3fbSopenharmony_ci	switch (type) {
470d722e3fbSopenharmony_ci	case G2D_IMGBUF_GEM:
471d722e3fbSopenharmony_ci		src_img.bo[0] = src->handle;
472d722e3fbSopenharmony_ci		break;
473d722e3fbSopenharmony_ci	case G2D_IMGBUF_USERPTR:
474d722e3fbSopenharmony_ci		size = img_w * img_h * 4;
475d722e3fbSopenharmony_ci
476d722e3fbSopenharmony_ci		userptr = (unsigned long)malloc(size);
477d722e3fbSopenharmony_ci		if (!userptr) {
478d722e3fbSopenharmony_ci			fprintf(stderr, "failed to allocate userptr.\n");
479d722e3fbSopenharmony_ci			ret = -EFAULT;
480d722e3fbSopenharmony_ci			goto fail;
481d722e3fbSopenharmony_ci		}
482d722e3fbSopenharmony_ci
483d722e3fbSopenharmony_ci		src_img.user_ptr[0].userptr = userptr;
484d722e3fbSopenharmony_ci		src_img.user_ptr[0].size = size;
485d722e3fbSopenharmony_ci		break;
486d722e3fbSopenharmony_ci	case G2D_IMGBUF_COLOR:
487d722e3fbSopenharmony_ci	default:
488d722e3fbSopenharmony_ci		ret = -EFAULT;
489d722e3fbSopenharmony_ci		goto fail;
490d722e3fbSopenharmony_ci	}
491d722e3fbSopenharmony_ci
492d722e3fbSopenharmony_ci	printf("copy and scale test with %s.\n",
493d722e3fbSopenharmony_ci			type == G2D_IMGBUF_GEM ? "gem" : "userptr");
494d722e3fbSopenharmony_ci
495d722e3fbSopenharmony_ci	src_img.width = img_w;
496d722e3fbSopenharmony_ci	src_img.height = img_h;
497d722e3fbSopenharmony_ci	src_img.stride = src_img.width * 4;
498d722e3fbSopenharmony_ci	src_img.buf_type = type;
499d722e3fbSopenharmony_ci	src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
500d722e3fbSopenharmony_ci	src_img.color = 0xffffffff;
501d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w ,  img_h);
502d722e3fbSopenharmony_ci	if (ret < 0)
503d722e3fbSopenharmony_ci		goto err_free_userptr;
504d722e3fbSopenharmony_ci
505d722e3fbSopenharmony_ci	src_img.color = 0xff00ff00;
506d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &src_img, 5, 5, 100, 100);
507d722e3fbSopenharmony_ci	if (ret < 0)
508d722e3fbSopenharmony_ci		goto err_free_userptr;
509d722e3fbSopenharmony_ci
510d722e3fbSopenharmony_ci	dst_img.width = img_w;
511d722e3fbSopenharmony_ci	dst_img.height = img_h;
512d722e3fbSopenharmony_ci	dst_img.buf_type = G2D_IMGBUF_GEM;
513d722e3fbSopenharmony_ci	dst_img.stride = dst_img.width * 4;
514d722e3fbSopenharmony_ci	dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
515d722e3fbSopenharmony_ci
516d722e3fbSopenharmony_ci	ret = g2d_copy_with_scale(ctx, &src_img, &dst_img, 5, 5, 100, 100,
517d722e3fbSopenharmony_ci					100, 100, 200, 200, 0);
518d722e3fbSopenharmony_ci	if (ret < 0)
519d722e3fbSopenharmony_ci		goto err_free_userptr;
520d722e3fbSopenharmony_ci
521d722e3fbSopenharmony_ci	g2d_exec(ctx);
522d722e3fbSopenharmony_ci
523d722e3fbSopenharmony_cierr_free_userptr:
524d722e3fbSopenharmony_ci	if (type == G2D_IMGBUF_USERPTR)
525d722e3fbSopenharmony_ci		if (userptr)
526d722e3fbSopenharmony_ci			free((void *)userptr);
527d722e3fbSopenharmony_ci
528d722e3fbSopenharmony_cifail:
529d722e3fbSopenharmony_ci	g2d_fini(ctx);
530d722e3fbSopenharmony_ci
531d722e3fbSopenharmony_ci	return ret;
532d722e3fbSopenharmony_ci}
533d722e3fbSopenharmony_ci
534d722e3fbSopenharmony_ci#ifdef EXYNOS_G2D_USERPTR_TEST
535d722e3fbSopenharmony_cistatic int g2d_blend_test(struct exynos_device *dev,
536d722e3fbSopenharmony_ci					struct exynos_bo *src,
537d722e3fbSopenharmony_ci					struct exynos_bo *dst,
538d722e3fbSopenharmony_ci					enum e_g2d_buf_type type)
539d722e3fbSopenharmony_ci{
540d722e3fbSopenharmony_ci	struct g2d_context *ctx;
541d722e3fbSopenharmony_ci	struct g2d_image src_img = {0}, dst_img = {0};
542d722e3fbSopenharmony_ci	unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
543d722e3fbSopenharmony_ci	unsigned long userptr, size;
544d722e3fbSopenharmony_ci	int ret;
545d722e3fbSopenharmony_ci
546d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
547d722e3fbSopenharmony_ci	if (!ctx)
548d722e3fbSopenharmony_ci		return -EFAULT;
549d722e3fbSopenharmony_ci
550d722e3fbSopenharmony_ci	dst_img.bo[0] = dst->handle;
551d722e3fbSopenharmony_ci
552d722e3fbSopenharmony_ci	src_x = 0;
553d722e3fbSopenharmony_ci	src_y = 0;
554d722e3fbSopenharmony_ci	dst_x = 0;
555d722e3fbSopenharmony_ci	dst_y = 0;
556d722e3fbSopenharmony_ci	img_w = screen_width;
557d722e3fbSopenharmony_ci	img_h = screen_height;
558d722e3fbSopenharmony_ci
559d722e3fbSopenharmony_ci	switch (type) {
560d722e3fbSopenharmony_ci	case G2D_IMGBUF_GEM:
561d722e3fbSopenharmony_ci		src_img.bo[0] = src->handle;
562d722e3fbSopenharmony_ci		break;
563d722e3fbSopenharmony_ci	case G2D_IMGBUF_USERPTR:
564d722e3fbSopenharmony_ci		size = img_w * img_h * 4;
565d722e3fbSopenharmony_ci
566d722e3fbSopenharmony_ci		userptr = (unsigned long)malloc(size);
567d722e3fbSopenharmony_ci		if (!userptr) {
568d722e3fbSopenharmony_ci			fprintf(stderr, "failed to allocate userptr.\n");
569d722e3fbSopenharmony_ci			ret = -EFAULT;
570d722e3fbSopenharmony_ci			goto fail;
571d722e3fbSopenharmony_ci		}
572d722e3fbSopenharmony_ci
573d722e3fbSopenharmony_ci		src_img.user_ptr[0].userptr = userptr;
574d722e3fbSopenharmony_ci		src_img.user_ptr[0].size = size;
575d722e3fbSopenharmony_ci		break;
576d722e3fbSopenharmony_ci	case G2D_IMGBUF_COLOR:
577d722e3fbSopenharmony_ci	default:
578d722e3fbSopenharmony_ci		ret = -EFAULT;
579d722e3fbSopenharmony_ci		goto fail;
580d722e3fbSopenharmony_ci	}
581d722e3fbSopenharmony_ci
582d722e3fbSopenharmony_ci	printf("blend test with %s.\n",
583d722e3fbSopenharmony_ci			type == G2D_IMGBUF_GEM ? "gem" : "userptr");
584d722e3fbSopenharmony_ci
585d722e3fbSopenharmony_ci	src_img.width = img_w;
586d722e3fbSopenharmony_ci	src_img.height = img_h;
587d722e3fbSopenharmony_ci	src_img.stride = src_img.width * 4;
588d722e3fbSopenharmony_ci	src_img.buf_type = type;
589d722e3fbSopenharmony_ci	src_img.select_mode = G2D_SELECT_MODE_NORMAL;
590d722e3fbSopenharmony_ci	src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
591d722e3fbSopenharmony_ci	src_img.color = 0xffffffff;
592d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &src_img, src_x, src_y, img_w, img_h);
593d722e3fbSopenharmony_ci	if (ret < 0)
594d722e3fbSopenharmony_ci		goto err_free_userptr;
595d722e3fbSopenharmony_ci
596d722e3fbSopenharmony_ci	src_img.color = 0x770000ff;
597d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &src_img, 5, 5, 200, 200);
598d722e3fbSopenharmony_ci	if (ret < 0)
599d722e3fbSopenharmony_ci		goto err_free_userptr;
600d722e3fbSopenharmony_ci
601d722e3fbSopenharmony_ci	dst_img.width = img_w;
602d722e3fbSopenharmony_ci	dst_img.height = img_h;
603d722e3fbSopenharmony_ci	dst_img.stride = dst_img.width * 4;
604d722e3fbSopenharmony_ci	dst_img.buf_type = G2D_IMGBUF_GEM;
605d722e3fbSopenharmony_ci	dst_img.select_mode = G2D_SELECT_MODE_NORMAL;
606d722e3fbSopenharmony_ci	dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
607d722e3fbSopenharmony_ci	dst_img.color = 0xffffffff;
608d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &dst_img, dst_x, dst_y, img_w, img_h);
609d722e3fbSopenharmony_ci	if (ret < 0)
610d722e3fbSopenharmony_ci		goto err_free_userptr;
611d722e3fbSopenharmony_ci
612d722e3fbSopenharmony_ci	dst_img.color = 0x77ff0000;
613d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &dst_img, 105, 105, 200, 200);
614d722e3fbSopenharmony_ci	if (ret < 0)
615d722e3fbSopenharmony_ci		goto err_free_userptr;
616d722e3fbSopenharmony_ci
617d722e3fbSopenharmony_ci	ret = g2d_blend(ctx, &src_img, &dst_img, 5, 5, 105, 105, 200, 200,
618d722e3fbSopenharmony_ci			G2D_OP_OVER);
619d722e3fbSopenharmony_ci	if (ret < 0)
620d722e3fbSopenharmony_ci		goto err_free_userptr;
621d722e3fbSopenharmony_ci
622d722e3fbSopenharmony_ci	g2d_exec(ctx);
623d722e3fbSopenharmony_ci
624d722e3fbSopenharmony_cierr_free_userptr:
625d722e3fbSopenharmony_ci	if (type == G2D_IMGBUF_USERPTR)
626d722e3fbSopenharmony_ci		if (userptr)
627d722e3fbSopenharmony_ci			free((void *)userptr);
628d722e3fbSopenharmony_ci
629d722e3fbSopenharmony_cifail:
630d722e3fbSopenharmony_ci	g2d_fini(ctx);
631d722e3fbSopenharmony_ci
632d722e3fbSopenharmony_ci	return ret;
633d722e3fbSopenharmony_ci}
634d722e3fbSopenharmony_ci#endif
635d722e3fbSopenharmony_ci
636d722e3fbSopenharmony_cistatic int g2d_checkerboard_test(struct exynos_device *dev,
637d722e3fbSopenharmony_ci					struct exynos_bo *src,
638d722e3fbSopenharmony_ci					struct exynos_bo *dst,
639d722e3fbSopenharmony_ci					enum e_g2d_buf_type type)
640d722e3fbSopenharmony_ci{
641d722e3fbSopenharmony_ci	struct g2d_context *ctx;
642d722e3fbSopenharmony_ci	struct g2d_image src_img = {0}, dst_img = {0};
643d722e3fbSopenharmony_ci	unsigned int src_x, src_y, dst_x, dst_y, img_w, img_h;
644d722e3fbSopenharmony_ci	void *checkerboard = NULL;
645d722e3fbSopenharmony_ci	int ret;
646d722e3fbSopenharmony_ci
647d722e3fbSopenharmony_ci	ctx = g2d_init(dev->fd);
648d722e3fbSopenharmony_ci	if (!ctx)
649d722e3fbSopenharmony_ci		return -EFAULT;
650d722e3fbSopenharmony_ci
651d722e3fbSopenharmony_ci	dst_img.bo[0] = dst->handle;
652d722e3fbSopenharmony_ci
653d722e3fbSopenharmony_ci	src_x = 0;
654d722e3fbSopenharmony_ci	src_y = 0;
655d722e3fbSopenharmony_ci	dst_x = 0;
656d722e3fbSopenharmony_ci	dst_y = 0;
657d722e3fbSopenharmony_ci
658d722e3fbSopenharmony_ci	checkerboard = create_checkerboard_pattern(screen_width / 32, screen_height / 32, 32);
659d722e3fbSopenharmony_ci	if (!checkerboard) {
660d722e3fbSopenharmony_ci		ret = -EFAULT;
661d722e3fbSopenharmony_ci		goto fail;
662d722e3fbSopenharmony_ci	}
663d722e3fbSopenharmony_ci
664d722e3fbSopenharmony_ci	img_w = screen_width - (screen_width % 32);
665d722e3fbSopenharmony_ci	img_h = screen_height - (screen_height % 32);
666d722e3fbSopenharmony_ci
667d722e3fbSopenharmony_ci	switch (type) {
668d722e3fbSopenharmony_ci	case G2D_IMGBUF_GEM:
669d722e3fbSopenharmony_ci		memcpy(src->vaddr, checkerboard, img_w * img_h * 4);
670d722e3fbSopenharmony_ci		src_img.bo[0] = src->handle;
671d722e3fbSopenharmony_ci		break;
672d722e3fbSopenharmony_ci	case G2D_IMGBUF_USERPTR:
673d722e3fbSopenharmony_ci		src_img.user_ptr[0].userptr = (unsigned long)checkerboard;
674d722e3fbSopenharmony_ci		src_img.user_ptr[0].size = img_w * img_h * 4;
675d722e3fbSopenharmony_ci		break;
676d722e3fbSopenharmony_ci	case G2D_IMGBUF_COLOR:
677d722e3fbSopenharmony_ci	default:
678d722e3fbSopenharmony_ci		ret = -EFAULT;
679d722e3fbSopenharmony_ci		goto fail;
680d722e3fbSopenharmony_ci	}
681d722e3fbSopenharmony_ci
682d722e3fbSopenharmony_ci	printf("checkerboard test with %s.\n",
683d722e3fbSopenharmony_ci			type == G2D_IMGBUF_GEM ? "gem" : "userptr");
684d722e3fbSopenharmony_ci
685d722e3fbSopenharmony_ci	src_img.width = img_w;
686d722e3fbSopenharmony_ci	src_img.height = img_h;
687d722e3fbSopenharmony_ci	src_img.stride = src_img.width * 4;
688d722e3fbSopenharmony_ci	src_img.buf_type = type;
689d722e3fbSopenharmony_ci	src_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
690d722e3fbSopenharmony_ci
691d722e3fbSopenharmony_ci	dst_img.width = screen_width;
692d722e3fbSopenharmony_ci	dst_img.height = screen_height;
693d722e3fbSopenharmony_ci	dst_img.stride = dst_img.width * 4;
694d722e3fbSopenharmony_ci	dst_img.buf_type = G2D_IMGBUF_GEM;
695d722e3fbSopenharmony_ci	dst_img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
696d722e3fbSopenharmony_ci	src_img.color = 0xff000000;
697d722e3fbSopenharmony_ci	ret = g2d_solid_fill(ctx, &dst_img, src_x, src_y, screen_width, screen_height);
698d722e3fbSopenharmony_ci	if (ret < 0)
699d722e3fbSopenharmony_ci		goto fail;
700d722e3fbSopenharmony_ci
701d722e3fbSopenharmony_ci	ret = g2d_copy(ctx, &src_img, &dst_img, src_x, src_y, dst_x, dst_y,
702d722e3fbSopenharmony_ci			img_w, img_h);
703d722e3fbSopenharmony_ci	if (ret < 0)
704d722e3fbSopenharmony_ci		goto fail;
705d722e3fbSopenharmony_ci
706d722e3fbSopenharmony_ci	g2d_exec(ctx);
707d722e3fbSopenharmony_ci
708d722e3fbSopenharmony_cifail:
709d722e3fbSopenharmony_ci	free(checkerboard);
710d722e3fbSopenharmony_ci	g2d_fini(ctx);
711d722e3fbSopenharmony_ci
712d722e3fbSopenharmony_ci	return ret;
713d722e3fbSopenharmony_ci}
714d722e3fbSopenharmony_ci
715d722e3fbSopenharmony_cistatic void usage(char *name)
716d722e3fbSopenharmony_ci{
717d722e3fbSopenharmony_ci	fprintf(stderr, "usage: %s [-s]\n", name);
718d722e3fbSopenharmony_ci	fprintf(stderr, "-s <connector_id>@<crtc_id>:<mode>\n");
719d722e3fbSopenharmony_ci	exit(0);
720d722e3fbSopenharmony_ci}
721d722e3fbSopenharmony_ci
722d722e3fbSopenharmony_ciextern char *optarg;
723d722e3fbSopenharmony_cistatic const char optstr[] = "s:";
724d722e3fbSopenharmony_ci
725d722e3fbSopenharmony_ciint main(int argc, char **argv)
726d722e3fbSopenharmony_ci{
727d722e3fbSopenharmony_ci	struct exynos_device *dev;
728d722e3fbSopenharmony_ci	struct exynos_bo *bo, *src;
729d722e3fbSopenharmony_ci	struct connector con;
730d722e3fbSopenharmony_ci	unsigned int fb_id;
731d722e3fbSopenharmony_ci	uint32_t handles[4] = {0}, pitches[4] = {0}, offsets[4] = {0};
732d722e3fbSopenharmony_ci	drmModeRes *resources;
733d722e3fbSopenharmony_ci	int ret, fd, c;
734d722e3fbSopenharmony_ci
735d722e3fbSopenharmony_ci	memset(&con, 0, sizeof(struct connector));
736d722e3fbSopenharmony_ci
737d722e3fbSopenharmony_ci	if (argc != 3) {
738d722e3fbSopenharmony_ci		usage(argv[0]);
739d722e3fbSopenharmony_ci		return -EINVAL;
740d722e3fbSopenharmony_ci	}
741d722e3fbSopenharmony_ci
742d722e3fbSopenharmony_ci	while ((c = getopt(argc, argv, optstr)) != -1) {
743d722e3fbSopenharmony_ci		switch (c) {
744d722e3fbSopenharmony_ci		case 's':
745d722e3fbSopenharmony_ci			con.crtc = -1;
746d722e3fbSopenharmony_ci			if (sscanf(optarg, "%d:0x%64s",
747d722e3fbSopenharmony_ci						&con.id,
748d722e3fbSopenharmony_ci						con.mode_str) != 2 &&
749d722e3fbSopenharmony_ci					sscanf(optarg, "%d@%d:%64s",
750d722e3fbSopenharmony_ci						&con.id,
751d722e3fbSopenharmony_ci						&con.crtc,
752d722e3fbSopenharmony_ci						con.mode_str) != 3)
753d722e3fbSopenharmony_ci				usage(argv[0]);
754d722e3fbSopenharmony_ci			break;
755d722e3fbSopenharmony_ci		default:
756d722e3fbSopenharmony_ci			usage(argv[0]);
757d722e3fbSopenharmony_ci			break;
758d722e3fbSopenharmony_ci		}
759d722e3fbSopenharmony_ci	}
760d722e3fbSopenharmony_ci
761d722e3fbSopenharmony_ci	fd = drmOpen(DRM_MODULE_NAME, NULL);
762d722e3fbSopenharmony_ci	if (fd < 0) {
763d722e3fbSopenharmony_ci		fprintf(stderr, "failed to open.\n");
764d722e3fbSopenharmony_ci		return fd;
765d722e3fbSopenharmony_ci	}
766d722e3fbSopenharmony_ci
767d722e3fbSopenharmony_ci	dev = exynos_device_create(fd);
768d722e3fbSopenharmony_ci	if (!dev) {
769d722e3fbSopenharmony_ci		ret = -EFAULT;
770d722e3fbSopenharmony_ci		goto err_drm_close;
771d722e3fbSopenharmony_ci	}
772d722e3fbSopenharmony_ci
773d722e3fbSopenharmony_ci	resources = drmModeGetResources(dev->fd);
774d722e3fbSopenharmony_ci	if (!resources) {
775d722e3fbSopenharmony_ci		fprintf(stderr, "drmModeGetResources failed: %s\n",
776d722e3fbSopenharmony_ci				strerror(errno));
777d722e3fbSopenharmony_ci		ret = -EFAULT;
778d722e3fbSopenharmony_ci		goto err_dev_destory;
779d722e3fbSopenharmony_ci	}
780d722e3fbSopenharmony_ci
781d722e3fbSopenharmony_ci	connector_find_mode(dev->fd, &con, resources);
782d722e3fbSopenharmony_ci	drmModeFreeResources(resources);
783d722e3fbSopenharmony_ci
784d722e3fbSopenharmony_ci	if (!con.mode) {
785d722e3fbSopenharmony_ci		fprintf(stderr, "failed to find usable connector\n");
786d722e3fbSopenharmony_ci		ret = -EFAULT;
787d722e3fbSopenharmony_ci		goto err_dev_destory;
788d722e3fbSopenharmony_ci	}
789d722e3fbSopenharmony_ci
790d722e3fbSopenharmony_ci	screen_width = con.mode->hdisplay;
791d722e3fbSopenharmony_ci	screen_height = con.mode->vdisplay;
792d722e3fbSopenharmony_ci
793d722e3fbSopenharmony_ci	if (screen_width == 0 || screen_height == 0) {
794d722e3fbSopenharmony_ci		fprintf(stderr, "failed to find sane resolution on connector\n");
795d722e3fbSopenharmony_ci		ret = -EFAULT;
796d722e3fbSopenharmony_ci		goto err_dev_destory;
797d722e3fbSopenharmony_ci	}
798d722e3fbSopenharmony_ci
799d722e3fbSopenharmony_ci	printf("screen width = %d, screen height = %d\n", screen_width,
800d722e3fbSopenharmony_ci			screen_height);
801d722e3fbSopenharmony_ci
802d722e3fbSopenharmony_ci	bo = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
803d722e3fbSopenharmony_ci	if (!bo) {
804d722e3fbSopenharmony_ci		ret = -EFAULT;
805d722e3fbSopenharmony_ci		goto err_dev_destory;
806d722e3fbSopenharmony_ci	}
807d722e3fbSopenharmony_ci
808d722e3fbSopenharmony_ci	handles[0] = bo->handle;
809d722e3fbSopenharmony_ci	pitches[0] = screen_width * 4;
810d722e3fbSopenharmony_ci	offsets[0] = 0;
811d722e3fbSopenharmony_ci
812d722e3fbSopenharmony_ci	ret = drmModeAddFB2(dev->fd, screen_width, screen_height,
813d722e3fbSopenharmony_ci				DRM_FORMAT_XRGB8888, handles,
814d722e3fbSopenharmony_ci				pitches, offsets, &fb_id, 0);
815d722e3fbSopenharmony_ci	if (ret < 0)
816d722e3fbSopenharmony_ci		goto err_destroy_buffer;
817d722e3fbSopenharmony_ci
818d722e3fbSopenharmony_ci	memset(bo->vaddr, 0xff, screen_width * screen_height * 4);
819d722e3fbSopenharmony_ci
820d722e3fbSopenharmony_ci	ret = drm_set_crtc(dev, &con, fb_id);
821d722e3fbSopenharmony_ci	if (ret < 0)
822d722e3fbSopenharmony_ci		goto err_rm_fb;
823d722e3fbSopenharmony_ci
824d722e3fbSopenharmony_ci	ret = g2d_solid_fill_test(dev, bo);
825d722e3fbSopenharmony_ci	if (ret < 0) {
826d722e3fbSopenharmony_ci		fprintf(stderr, "failed to solid fill operation.\n");
827d722e3fbSopenharmony_ci		goto err_rm_fb;
828d722e3fbSopenharmony_ci	}
829d722e3fbSopenharmony_ci
830d722e3fbSopenharmony_ci	wait_for_user_input(0);
831d722e3fbSopenharmony_ci
832d722e3fbSopenharmony_ci	src = exynos_create_buffer(dev, screen_width * screen_height * 4, 0);
833d722e3fbSopenharmony_ci	if (!src) {
834d722e3fbSopenharmony_ci		ret = -EFAULT;
835d722e3fbSopenharmony_ci		goto err_rm_fb;
836d722e3fbSopenharmony_ci	}
837d722e3fbSopenharmony_ci
838d722e3fbSopenharmony_ci	ret = g2d_copy_test(dev, src, bo, G2D_IMGBUF_GEM);
839d722e3fbSopenharmony_ci	if (ret < 0) {
840d722e3fbSopenharmony_ci		fprintf(stderr, "failed to test copy operation.\n");
841d722e3fbSopenharmony_ci		goto err_free_src;
842d722e3fbSopenharmony_ci	}
843d722e3fbSopenharmony_ci
844d722e3fbSopenharmony_ci	wait_for_user_input(0);
845d722e3fbSopenharmony_ci
846d722e3fbSopenharmony_ci	ret = g2d_move_test(dev, src, bo, G2D_IMGBUF_GEM);
847d722e3fbSopenharmony_ci	if (ret < 0) {
848d722e3fbSopenharmony_ci		fprintf(stderr, "failed to test move operation.\n");
849d722e3fbSopenharmony_ci		goto err_free_src;
850d722e3fbSopenharmony_ci	}
851d722e3fbSopenharmony_ci
852d722e3fbSopenharmony_ci	wait_for_user_input(0);
853d722e3fbSopenharmony_ci
854d722e3fbSopenharmony_ci	ret = g2d_copy_with_scale_test(dev, src, bo, G2D_IMGBUF_GEM);
855d722e3fbSopenharmony_ci	if (ret < 0) {
856d722e3fbSopenharmony_ci		fprintf(stderr, "failed to test copy and scale operation.\n");
857d722e3fbSopenharmony_ci		goto err_free_src;
858d722e3fbSopenharmony_ci	}
859d722e3fbSopenharmony_ci
860d722e3fbSopenharmony_ci	wait_for_user_input(0);
861d722e3fbSopenharmony_ci
862d722e3fbSopenharmony_ci	ret = g2d_checkerboard_test(dev, src, bo, G2D_IMGBUF_GEM);
863d722e3fbSopenharmony_ci	if (ret < 0) {
864d722e3fbSopenharmony_ci		fprintf(stderr, "failed to issue checkerboard test.\n");
865d722e3fbSopenharmony_ci		goto err_free_src;
866d722e3fbSopenharmony_ci	}
867d722e3fbSopenharmony_ci
868d722e3fbSopenharmony_ci	wait_for_user_input(1);
869d722e3fbSopenharmony_ci
870d722e3fbSopenharmony_ci	/*
871d722e3fbSopenharmony_ci	 * The blend test uses the userptr functionality of exynos-drm, which
872d722e3fbSopenharmony_ci	 * is currently not safe to use. If the kernel hasn't been build with
873d722e3fbSopenharmony_ci	 * exynos-iommu support, then the blend test is going to produce (kernel)
874d722e3fbSopenharmony_ci	 * memory corruption, eventually leading to a system crash.
875d722e3fbSopenharmony_ci	 *
876d722e3fbSopenharmony_ci	 * Disable the test for now, until the kernel code has been sanitized.
877d722e3fbSopenharmony_ci	 */
878d722e3fbSopenharmony_ci#ifdef EXYNOS_G2D_USERPTR_TEST
879d722e3fbSopenharmony_ci	ret  = g2d_blend_test(dev, src, bo, G2D_IMGBUF_USERPTR);
880d722e3fbSopenharmony_ci	if (ret < 0)
881d722e3fbSopenharmony_ci		fprintf(stderr, "failed to test blend operation.\n");
882d722e3fbSopenharmony_ci
883d722e3fbSopenharmony_ci	getchar();
884d722e3fbSopenharmony_ci#endif
885d722e3fbSopenharmony_ci
886d722e3fbSopenharmony_cierr_free_src:
887d722e3fbSopenharmony_ci	if (src)
888d722e3fbSopenharmony_ci		exynos_destroy_buffer(src);
889d722e3fbSopenharmony_ci
890d722e3fbSopenharmony_cierr_rm_fb:
891d722e3fbSopenharmony_ci	drmModeRmFB(dev->fd, fb_id);
892d722e3fbSopenharmony_ci
893d722e3fbSopenharmony_cierr_destroy_buffer:
894d722e3fbSopenharmony_ci	exynos_destroy_buffer(bo);
895d722e3fbSopenharmony_ci
896d722e3fbSopenharmony_cierr_dev_destory:
897d722e3fbSopenharmony_ci	exynos_device_destroy(dev);
898d722e3fbSopenharmony_ci
899d722e3fbSopenharmony_cierr_drm_close:
900d722e3fbSopenharmony_ci	drmClose(fd);
901d722e3fbSopenharmony_ci
902d722e3fbSopenharmony_ci	return ret;
903d722e3fbSopenharmony_ci}
904