/*
 * Copyright 2017 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <getopt.h>

#include "bs_drm.h"

#define BUFFERS 2
#define NUM_FRAMES 0x40

struct framebuffer {
	struct gbm_bo *bo;
	uint32_t id;
};

struct context {
	int display_fd;
	uint32_t crtc_id;

	struct framebuffer fbs[BUFFERS];
	struct bs_mapper *mapper;

	int vgem_device_fd;
};

struct disabled_features {
	char psr_prev_val[1];
};

const char psr_path[] = "/sys/module/i915/parameters/enable_psr";

static void disable_psr(struct disabled_features *dis_feat)
{
	int psr_fd = open(psr_path, O_RDWR);

	if (psr_fd < 0)
		return;

	if (read(psr_fd, dis_feat->psr_prev_val, 1) == -1) {
		bs_debug_error("failed to read psr value");
	} else {
		printf("previous enable_psr value: %c\n", dis_feat->psr_prev_val[0]);
	}
	if (strncmp(dis_feat->psr_prev_val, "1", 1) == 0) {
		if (write(psr_fd, "0", 1) == -1) {
			bs_debug_error("failed to disable psr");
		} else {
			printf("disabled psr\n");
		}
	}

	close(psr_fd);
}

static void restore_psr(struct disabled_features *dis_feat)
{
	if (strncmp(dis_feat->psr_prev_val, "1", 1) == 0) {
		int psr_fd = open(psr_path, O_WRONLY);

		if (psr_fd < 0)
			return;

		if (write(psr_fd, "1", 1) == -1) {
			bs_debug_error("failed to re-enable psr");
		} else {
			printf("re-enabled psr\n");
		}

		close(psr_fd);
	}
}

static void do_fixes(struct disabled_features *dis_feat)
{
	disable_psr(dis_feat);
}

static void restore_features(struct disabled_features *dis_feat)
{
	restore_psr(dis_feat);
}

#define STEP_SKIP 0
#define STEP_MMAP 1
#define STEP_FAULT 2
#define STEP_FLIP 3
#define STEP_DRAW 4

static void show_sequence(const int *sequence)
{
	int sequence_subindex;
	printf("starting sequence: ");
	for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
		switch (sequence[sequence_subindex]) {
			case STEP_SKIP:
				break;
			case STEP_MMAP:
				printf("mmap ");
				break;
			case STEP_FAULT:
				printf("fault ");
				break;
			case STEP_FLIP:
				printf("flip ");
				break;
			case STEP_DRAW:
				printf("draw ");
				break;
			default:
				bs_debug_error("<unknown step %d> (aborting!)",
					       sequence[sequence_subindex]);
				abort();
				break;
		}
	}
	printf("\n");
}

static void draw(struct context *ctx)
{
	// Run the drawing routine with the key driver events in different
	// sequences.
	const int sequences[4][4] = {
		{ STEP_MMAP, STEP_FAULT, STEP_FLIP, STEP_DRAW },
		{ STEP_MMAP, STEP_FLIP, STEP_DRAW, STEP_SKIP },
		{ STEP_MMAP, STEP_DRAW, STEP_FLIP, STEP_SKIP },
		{ STEP_FLIP, STEP_MMAP, STEP_DRAW, STEP_SKIP },
	};

	int sequence_index = 0;
	int sequence_subindex = 0;

	int fb_idx = 1;

	for (sequence_index = 0; sequence_index < 4; sequence_index++) {
		show_sequence(sequences[sequence_index]);
		for (int frame_index = 0; frame_index < NUM_FRAMES; frame_index += 2) {
			struct framebuffer *fb = &ctx->fbs[fb_idx];
			uint32_t bo_stride;
			size_t bo_size = gbm_bo_get_plane_size(fb->bo, 0);
			const uint32_t width = gbm_bo_get_width(fb->bo);
			const uint32_t height = gbm_bo_get_height(fb->bo);
			uint32_t *bo_ptr = NULL;
			volatile uint32_t *ptr = NULL;
			void *map_data;

			for (sequence_subindex = 0; sequence_subindex < 4; sequence_subindex++) {
				switch (sequences[sequence_index][sequence_subindex]) {
					case STEP_MMAP:
						bo_ptr = bs_mapper_map(ctx->mapper, fb->bo, 0,
								       &map_data, &bo_stride);
						if (bo_ptr == MAP_FAILED)
							bs_debug_error("failed to mmap gbm bo");

						ptr = bo_ptr;
						break;

					case STEP_FAULT:
						*ptr = 1234567;
						break;

					case STEP_FLIP:
						drmModePageFlip(ctx->display_fd, ctx->crtc_id,
								ctx->fbs[fb_idx].id, 0, NULL);
						break;

					case STEP_DRAW:
						for (ptr = bo_ptr;
						     ptr < bo_ptr + (bo_size / sizeof(*bo_ptr));
						     ptr++) {
							int y = ((void *)ptr - (void *)bo_ptr) /
								bo_stride;
							int x = ((void *)ptr - (void *)bo_ptr -
								 bo_stride * y) /
								sizeof(*ptr);
							x -= frame_index * (width / NUM_FRAMES);
							y -= frame_index * (height / NUM_FRAMES);
							*ptr = 0xff000000;
							if (x * x + y * y <
							    frame_index * frame_index)
								*ptr |= (frame_index % 0x100) << 8;
							else
								*ptr |= 0xff |
									(sequence_index * 64 << 16);
						}
						break;

					case STEP_SKIP:
					default:
						break;
				}
			}

			bs_mapper_unmap(ctx->mapper, fb->bo, map_data);

			usleep(1e6 / 120); /* 120 Hz */

			fb_idx = fb_idx ^ 1;
		}
	}
}

static const struct option longopts[] = {
	{ "help", no_argument, NULL, 'h' },
	{ "dma-buf", no_argument, NULL, 'b' },
	{ "gem", no_argument, NULL, 'g' },
	{ "dumb", no_argument, NULL, 'd' },
	{ "vgem", no_argument, NULL, 'v' },
	{ "scanout", no_argument, NULL, 's' },
	{ 0, 0, 0, 0 },
};

static void print_help(const char *argv0)
{
	printf("Usage: %s [OPTIONS]\n", argv0);
	printf(" -h, --help     Print help.\n");
	printf(" -b, --dma-buf  Use dma-buf mmap (by default).\n");
	printf(" -g, --gem      Use GEM map.\n");
	printf(" -d, --dumb     Use dump map.\n");
	printf(" -v, --vgem     Use vgem dump map.\n");
	printf(" -s, --scanout  Use buffer optimized for scanout.\n");
}

int main(int argc, char **argv)
{
	struct context ctx = { 0 };
	struct disabled_features dis_feat = { 0 };

	do_fixes(&dis_feat);

	ctx.display_fd = bs_drm_open_main_display();
	if (ctx.display_fd < 0) {
		bs_debug_error("failed to open card for display");
		return 1;
	}

	struct gbm_device *gbm = gbm_create_device(ctx.display_fd);
	if (!gbm) {
		bs_debug_error("failed to create gbm device");
		return 1;
	}

	int c;
	uint32_t flags = GBM_BO_USE_SCANOUT;
	while ((c = getopt_long(argc, argv, "bgdvsh", longopts, NULL)) != -1) {
		switch (c) {
			case 'b':
				ctx.mapper = bs_mapper_dma_buf_new();
				flags |= GBM_BO_USE_LINEAR;
				printf("started dma-buf mmap.\n");
				break;
			case 'g':
				ctx.mapper = bs_mapper_gem_new();
				flags |= GBM_BO_USE_SW_READ_OFTEN | GBM_BO_USE_SW_WRITE_OFTEN;
				printf("started GEM map.\n");
				break;
			case 'd':
				ctx.mapper = bs_mapper_dumb_new(gbm_device_get_fd(gbm));
				flags |= GBM_BO_USE_LINEAR;
				printf("started dumb map.\n");
				break;
			case 'v':
				ctx.vgem_device_fd = bs_drm_open_vgem();
				ctx.mapper = bs_mapper_dumb_new(ctx.vgem_device_fd);
				printf("started vgem map.\n");
				break;
			case 's':
				flags = GBM_BO_USE_SCANOUT;
				break;
			case 'h':
			default:
				print_help(argv[0]);
				return 1;
		}
	}

	// Use dma-buf mmap by default, in case any arguments aren't selected.
	if (!ctx.mapper) {
		ctx.mapper = bs_mapper_dma_buf_new();
		flags |= GBM_BO_USE_LINEAR;
		printf("started dma-buf mmap.\n");
	}

	if (ctx.mapper == NULL) {
		bs_debug_error("failed to create mapper object");
		return 1;
	}

	struct bs_drm_pipe pipe = { 0 };
	if (!bs_drm_pipe_make(ctx.display_fd, &pipe)) {
		bs_debug_error("failed to make pipe");
		return 1;
	}

	drmModeConnector *connector = drmModeGetConnector(ctx.display_fd, pipe.connector_id);
	drmModeModeInfo *mode = &connector->modes[0];
	ctx.crtc_id = pipe.crtc_id;

	printf("display size: %ux%u\n", mode->hdisplay, mode->vdisplay);

	for (size_t fb_index = 0; fb_index < BUFFERS; ++fb_index) {
		struct framebuffer *fb = &ctx.fbs[fb_index];
		fb->bo =
		    gbm_bo_create(gbm, mode->hdisplay, mode->vdisplay, GBM_FORMAT_XRGB8888, flags);

		if (!fb->bo) {
			bs_debug_error("failed to create buffer object");
			return 1;
		}

		fb->id = bs_drm_fb_create_gbm(fb->bo);
		if (fb->id == 0) {
			bs_debug_error("failed to create fb");
			return 1;
		}
	}

	if (drmModeSetCrtc(ctx.display_fd, pipe.crtc_id, ctx.fbs[0].id, 0, 0, &pipe.connector_id, 1,
			   mode)) {
		bs_debug_error("failed to set CRTC");
		return 1;
	}

	draw(&ctx);

	restore_features(&dis_feat);

	return 0;
}
