158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi/*
258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * Copyright (C) 2015 - Tobias Jakobi
358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi *
458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * This is free software: you can redistribute it and/or modify
558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * it under the terms of the GNU General Public License as published
658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * by the Free Software Foundation, either version 2 of the License,
758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * or (at your option) any later version.
858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi *
958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * It is distributed in the hope that it will be useful, but
1058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * WITHOUT ANY WARRANTY; without even the implied warranty of
1158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * GNU General Public License for more details.
1358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * You should have received a copy of the GNU General Public License
1458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * along with it. If not, see <http://www.gnu.org/licenses/>.
1558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi */
1658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
1758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <unistd.h>
1858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <poll.h>
1958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
2058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <stdlib.h>
2158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <stdio.h>
2258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <time.h>
2358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <getopt.h>
2458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
2558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <pthread.h>
2658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
2758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include <xf86drm.h>
2858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
2958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include "exynos_drm.h"
3058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include "exynos_drmif.h"
3158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi#include "exynos_fimg2d.h"
3258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
3358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistruct g2d_job {
3458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned int id;
3558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned int busy;
3658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi};
3758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
3858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistruct exynos_evhandler {
3958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct pollfd fds;
4058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct exynos_event_context evctx;
4158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi};
4258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
4358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistruct threaddata {
4458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned int stop;
4558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct exynos_device *dev;
4658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct exynos_evhandler evhandler;
4758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi};
4858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
4958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic void g2d_event_handler(int fd, unsigned int cmdlist_no, unsigned int tv_sec,
5058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi							unsigned int tv_usec, void *user_data)
5158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
5258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct g2d_job *job = user_data;
5358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
5458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "info: g2d job (id = %u, cmdlist number = %u) finished!\n",
5558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			job->id, cmdlist_no);
5658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
5758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	job->busy = 0;
5858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
5958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
6058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic void setup_g2d_event_handler(struct exynos_evhandler *evhandler, int fd)
6158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
6258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	evhandler->fds.fd = fd;
6358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	evhandler->fds.events = POLLIN;
6458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	evhandler->evctx.base.version = 2;
6558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	evhandler->evctx.version = 1;
6658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	evhandler->evctx.g2d_event_handler = g2d_event_handler;
6758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
6858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
6958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic void* threadfunc(void *arg) {
7058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	const int timeout = 0;
7158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct threaddata *data;
7258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
7358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	data = arg;
7458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
7558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	while (1) {
7658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (data->stop) break;
7758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
7858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		usleep(500);
7958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
8058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		data->evhandler.fds.revents = 0;
8158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
8258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (poll(&data->evhandler.fds, 1, timeout) < 0)
8358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			continue;
8458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
8558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (data->evhandler.fds.revents & (POLLHUP | POLLERR))
8658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			continue;
8758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
8858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (data->evhandler.fds.revents & POLLIN)
8958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			exynos_handle_event(data->dev, &data->evhandler.evctx);
9058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
9158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
9258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	pthread_exit(0);
9358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
9458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
9558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi/*
9658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * We need to wait until all G2D jobs are finished, otherwise we
9758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * potentially remove a BO which the engine still operates on.
9858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * This results in the following kernel message:
9958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * [drm:exynos_drm_gem_put_dma_addr] *ERROR* failed to lookup gem object.
10058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * Also any subsequent BO allocations fail then with:
10158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi * [drm:exynos_drm_alloc_buf] *ERROR* failed to allocate buffer.
10258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi */
10358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic void wait_all_jobs(struct g2d_job* jobs, unsigned num_jobs)
10458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
10558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned i;
10658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
10758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	for (i = 0; i < num_jobs; ++i) {
10858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		while (jobs[i].busy)
10958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			usleep(500);
11058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
11158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
11258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
11358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
11458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic struct g2d_job* free_job(struct g2d_job* jobs, unsigned num_jobs)
11558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
11658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned i;
11758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
11858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	for (i = 0; i < num_jobs; ++i) {
11958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (jobs[i].busy == 0)
12058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			return &jobs[i];
12158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
12258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
12358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	return NULL;
12458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
12558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
12658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic int g2d_work(struct g2d_context *ctx, struct g2d_image *img,
12758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi					unsigned num_jobs, unsigned iterations)
12858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
12958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct g2d_job *jobs = calloc(num_jobs, sizeof(struct g2d_job));
13058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	int ret;
13158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned i;
13258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
13358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	/* setup job ids */
13458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	for (i = 0; i < num_jobs; ++i)
13558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		jobs[i].id = i;
13658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
13758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	for (i = 0; i < iterations; ++i) {
13858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		unsigned x, y, w, h;
13958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
14058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		struct g2d_job *j = NULL;
14158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
14258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		while (1) {
14358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			j = free_job(jobs, num_jobs);
14458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
14558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			if (j)
14658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				break;
14758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			else
14858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				usleep(500);
14958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		}
15058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
15158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		x = rand() % img->width;
15258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		y = rand() % img->height;
15358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
15458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (x == (img->width - 1))
15558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			x -= 1;
15658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (y == (img->height - 1))
15758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			y -= 1;
15858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
15958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		w = rand() % (img->width - x);
16058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		h = rand() % (img->height - y);
16158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
16258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (w == 0) w = 1;
16358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (h == 0) h = 1;
16458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
16558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		img->color = rand();
16658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
16758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		j->busy = 1;
16858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		g2d_config_event(ctx, j);
16958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
17058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = g2d_solid_fill(ctx, img, x, y, w, h);
17158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
17258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (ret == 0)
17358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			g2d_exec(ctx);
17458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
17558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		if (ret != 0) {
17658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			fprintf(stderr, "error: iteration %u (x = %u, x = %u, x = %u, x = %u) failed\n",
17758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi					i, x, y, w, h);
17858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
17958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		}
18058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
18158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
18258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	wait_all_jobs(jobs, num_jobs);
18358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	free(jobs);
18458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
18558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	return 0;
18658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
18758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
18858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobistatic void usage(const char *name)
18958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
19058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "usage: %s [-ijwh]\n\n", name);
19158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
19258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "\t-i <number of iterations>\n");
19358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "\t-j <number of G2D jobs> (default = 4)\n\n");
19458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
19558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "\t-w <buffer width> (default = 4096)\n");
19658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fprintf(stderr, "\t-h <buffer height> (default = 4096)\n");
19758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
19858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	exit(0);
19958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
20058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
20158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobiint main(int argc, char **argv)
20258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi{
20358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	int fd, ret, c, parsefail;
20458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
20558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	pthread_t event_thread;
20658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct threaddata event_data = {0};
20758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
20858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct exynos_device *dev;
20958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct g2d_context *ctx;
21058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct exynos_bo *bo;
21158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
21258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	struct g2d_image img = {0};
21358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
21458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned int iters = 0, njobs = 4;
21558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	unsigned int bufw = 4096, bufh = 4096;
21658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
21758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	ret = 0;
21858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	parsefail = 0;
21958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
22058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	while ((c = getopt(argc, argv, "i:j:w:h:")) != -1) {
22158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		switch (c) {
22258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		case 'i':
22358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			if (sscanf(optarg, "%u", &iters) != 1)
22458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				parsefail = 1;
22558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
22658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		case 'j':
22758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			if (sscanf(optarg, "%u", &njobs) != 1)
22858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				parsefail = 1;
22958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
23058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		case 'w':
23158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			if (sscanf(optarg, "%u", &bufw) != 1)
23258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				parsefail = 1;
23358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
23458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		case 'h':
23558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			if (sscanf(optarg, "%u", &bufh) != 1)
23658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi				parsefail = 1;
23758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
23858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		default:
23958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			parsefail = 1;
24058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi			break;
24158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		}
24258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
24358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
24458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (parsefail || (argc == 1) || (iters == 0))
24558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		usage(argv[0]);
24658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
24758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (bufw > 4096 || bufh > 4096) {
24858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: buffer width/height should be less than 4096.\n");
24958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -1;
25058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
25158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto out;
25258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
25358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
25458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (bufw == 0 || bufh == 0) {
25558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: buffer width/height should be non-zero.\n");
25658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -1;
25758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
25858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto out;
25958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
26058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
26158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	fd = drmOpen("exynos", NULL);
26258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (fd < 0) {
26358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: failed to open drm\n");
26458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -1;
26558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
26658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto out;
26758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
26858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
26958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	dev = exynos_device_create(fd);
27058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (dev == NULL) {
27158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: failed to create device\n");
27258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -2;
27358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
27458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto fail;
27558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
27658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
27758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	ctx = g2d_init(fd);
27858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (ctx == NULL) {
27958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: failed to init G2D\n");
28058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -3;
28158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
28258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto g2d_fail;
28358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
28458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
28558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	bo = exynos_bo_create(dev, bufw * bufh * 4, 0);
28658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (bo == NULL) {
28758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: failed to create bo\n");
28858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		ret = -4;
28958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
29058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		goto bo_fail;
29158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	}
29258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
29358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	/* setup g2d image object */
29458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.width = bufw;
29558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.height = bufh;
29658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.stride = bufw * 4;
29758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.color_mode = G2D_COLOR_FMT_ARGB8888 | G2D_ORDER_AXRGB;
29858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.buf_type = G2D_IMGBUF_GEM;
29958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	img.bo[0] = bo->handle;
30058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
30158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	event_data.dev = dev;
30258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	setup_g2d_event_handler(&event_data.evhandler, fd);
30358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
30458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	pthread_create(&event_thread, NULL, threadfunc, &event_data);
30558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
30658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	ret = g2d_work(ctx, &img, njobs, iters);
30758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	if (ret != 0)
30858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi		fprintf(stderr, "error: g2d_work failed\n");
30958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
31058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	event_data.stop = 1;
31158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	pthread_join(event_thread, NULL);
31258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
31358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	exynos_bo_destroy(bo);
31458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
31558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobibo_fail:
31658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	g2d_fini(ctx);
31758a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
31858a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobig2d_fail:
31958a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	exynos_device_destroy(dev);
32058a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
32158a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobifail:
32258a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	drmClose(fd);
32358a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi
32458a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobiout:
32558a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi	return ret;
32658a39f6ba113073432dc0cd0ae702aba332c81b7Tobias Jakobi}
327