/*
 * Copyright (c) 2014 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 <drm_fourcc.h>
#include <errno.h>
#include <fcntl.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <time.h>
#include <unistd.h>

#include "util.h"
#include "fb.h"

static int fb_buffer_create(fb_t* fb,
			    int* pitch)
{
	struct drm_mode_create_dumb create_dumb;
	struct drm_mode_destroy_dumb destroy_dumb;
	int ret;

	memset(&create_dumb, 0, sizeof (create_dumb));
	create_dumb.bpp = 32;
	create_dumb.width = fb->drm->crtc->mode.hdisplay;
	create_dumb.height = fb->drm->crtc->mode.vdisplay;

	ret = drmIoctl(fb->drm->fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb);
	if (ret) {
		LOG(ERROR, "CREATE_DUMB failed");
		return ret;
	}

	fb->buffer_properties.size = create_dumb.size;
	fb->buffer_handle = create_dumb.handle;

	struct drm_mode_map_dumb map_dumb;
	map_dumb.handle = create_dumb.handle;
	ret = drmIoctl(fb->drm->fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb);
	if (ret) {
		LOG(ERROR, "MAP_DUMB failed");
		goto destroy_buffer;
	}

	fb->lock.map_offset = map_dumb.offset;

	uint32_t offset = 0;
	ret = drmModeAddFB2(fb->drm->fd, fb->drm->crtc->mode.hdisplay, fb->drm->crtc->mode.vdisplay,
			    DRM_FORMAT_XRGB8888, &create_dumb.handle,
			    &create_dumb.pitch, &offset, &fb->fb_id, 0);
	if (ret) {
		LOG(ERROR, "drmModeAddFB2 failed");
		goto destroy_buffer;
	}

	*pitch = create_dumb.pitch;

	return 0;

destroy_buffer:
	destroy_dumb.handle = create_dumb.handle;

	drmIoctl(fb->drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);

	return ret;
}

void fb_buffer_destroy(fb_t* fb)
{
	struct drm_mode_destroy_dumb destroy_dumb;

	if (fb->buffer_handle <= 0)
		return;

	drmModeRmFB(fb->drm->fd, fb->fb_id);
	fb->fb_id = 0;
	destroy_dumb.handle = fb->buffer_handle;
	drmIoctl(fb->drm->fd, DRM_IOCTL_MODE_DESTROY_DUMB, &destroy_dumb);
	fb->buffer_handle = 0;
	fb->lock.map = NULL;
	drm_delref(fb->drm);
	fb->drm = NULL;
}

static bool parse_edid_dtd(uint8_t* dtd, drmModeModeInfo* mode,
			   int32_t* hdisplay_size, int32_t* vdisplay_size) {
	int32_t clock;
	int32_t hactive, hbl, hso, hsw, hsize;
	int32_t vactive, vbl, vso, vsw, vsize;

	clock = ((int32_t)dtd[DTD_PCLK_HI] << 8) | dtd[DTD_PCLK_LO];
	if (!clock)
		return false;

	hactive = ((int32_t)(dtd[DTD_HABL_HI] & 0xf0) << 4) + dtd[DTD_HA_LO];
	vactive = ((int32_t)(dtd[DTD_VABL_HI] & 0xf0) << 4) + dtd[DTD_VA_LO];
	hbl = ((int32_t)(dtd[DTD_HABL_HI] & 0x0f) << 8) + dtd[DTD_HBL_LO];
	vbl = ((int32_t)(dtd[DTD_VABL_HI] & 0x0f) << 8) + dtd[DTD_VBL_LO];
	hso = ((int32_t)(dtd[DTD_HVSX_HI] & 0xc0) << 2) + dtd[DTD_HSO_LO];
	vso = ((int32_t)(dtd[DTD_HVSX_HI] & 0x0c) << 2) + (dtd[DTD_VSX_LO] >> 4);
	hsw = ((int32_t)(dtd[DTD_HVSX_HI] & 0x30) << 4) + dtd[DTD_HSW_LO];
	vsw = ((int32_t)(dtd[DTD_HVSX_HI] & 0x03) << 4) + (dtd[DTD_VSX_LO] & 0xf);
	hsize = ((int32_t)(dtd[DTD_HVSIZE_HI] & 0xf0) << 4) + dtd[DTD_HSIZE_LO];
	vsize = ((int32_t)(dtd[DTD_HVSIZE_HI] & 0x0f) << 8) + dtd[DTD_VSIZE_LO];

	mode->clock = clock * 10;
	mode->hdisplay = hactive;
	mode->vdisplay = vactive;
	mode->hsync_start = hactive + hso;
	mode->vsync_start = vactive + vso;
	mode->hsync_end = mode->hsync_start + hsw;
	mode->vsync_end = mode->vsync_start + vsw;
	mode->htotal = hactive + hbl;
	mode->vtotal = vactive + vbl;
	*hdisplay_size = hsize;
	*vdisplay_size = vsize;
	return true;
}

static bool parse_edid_dtd_display_size(drm_t* drm, int32_t* hsize_mm, int32_t* vsize_mm) {
	drmModeModeInfo* mode = &drm->crtc->mode;

	for (int i = 0; i < EDID_N_DTDS; i++) {
		uint8_t* dtd = (uint8_t*)&drm->edid[EDID_DTD_BASE + i * DTD_SIZE];
		drmModeModeInfo dtd_mode;
		int32_t hdisplay_size, vdisplay_size;
		if (!parse_edid_dtd(dtd, &dtd_mode, &hdisplay_size, &vdisplay_size) ||
				mode->clock != dtd_mode.clock ||
				mode->hdisplay != dtd_mode.hdisplay ||
				mode->vdisplay != dtd_mode.vdisplay ||
				mode->hsync_start != dtd_mode.hsync_start ||
				mode->vsync_start != dtd_mode.vsync_start ||
				mode->hsync_end != dtd_mode.hsync_end ||
				mode->vsync_end != dtd_mode.vsync_end ||
				mode->htotal != dtd_mode.htotal ||
				mode->vtotal != dtd_mode.vtotal)
			continue;
		*hsize_mm = hdisplay_size;
		*vsize_mm = vdisplay_size;
		return true;
	}
	return false;
}

int fb_buffer_init(fb_t* fb)
{
	int32_t width, height, pitch;
	int32_t hsize_mm, vsize_mm;
	int r;

	/* some reasonable defaults */
	fb->buffer_properties.width = 640;
	fb->buffer_properties.height = 480;
	fb->buffer_properties.pitch = 640 * 4;
	fb->buffer_properties.scaling = 1;

	fb->drm = drm_addref();

	if (!fb->drm) {
		LOG(WARNING, "No monitor available, running headless!");
		return -ENODEV;
	}

	width = fb->drm->crtc->mode.hdisplay;
	height = fb->drm->crtc->mode.vdisplay;

	r = fb_buffer_create(fb, &pitch);
	if (r < 0) {
		LOG(ERROR, "fb_buffer_create failed");
		return r;
	}

	fb->buffer_properties.width = width;
	fb->buffer_properties.height = height;
	fb->buffer_properties.pitch = pitch;

	hsize_mm = fb->drm->main_monitor_connector->mmWidth;
	vsize_mm = fb->drm->main_monitor_connector->mmHeight;
	if (drm_read_edid(fb->drm))
		parse_edid_dtd_display_size(fb->drm, &hsize_mm, &vsize_mm);

	if (hsize_mm) {
		int dots_per_cm = width * 10 / hsize_mm;
		if (dots_per_cm > 133)
			fb->buffer_properties.scaling = 4;
		else if (dots_per_cm > 100)
			fb->buffer_properties.scaling = 3;
		else if (dots_per_cm > 67)
			fb->buffer_properties.scaling = 2;
	}

	return 0;
}

fb_t* fb_init(void)
{
	fb_t* fb;

	fb = (fb_t*)calloc(1, sizeof(fb_t));
	if (!fb)
		return NULL;

	fb_buffer_init(fb);

	return fb;
}

void fb_close(fb_t* fb)
{
	if (!fb)
		return;

	fb_buffer_destroy(fb);

	free(fb);
}

int32_t fb_setmode(fb_t* fb)
{
	/* headless mode */
	if (!drm_valid(fb->drm))
		return 0;

	return drm_setmode(fb->drm, fb->fb_id);
}

uint32_t* fb_lock(fb_t* fb)
{
	if (fb->lock.count == 0 && fb->buffer_handle > 0) {
		fb->lock.map =
			mmap(0, fb->buffer_properties.size, PROT_READ | PROT_WRITE,
					MAP_SHARED, fb->drm->fd, fb->lock.map_offset);
		if (fb->lock.map == MAP_FAILED) {
			LOG(ERROR, "mmap failed");
			return NULL;
		}
	}
	fb->lock.count++;

	return fb->lock.map;
}

void fb_unlock(fb_t* fb)
{
	if (fb->lock.count > 0)
		fb->lock.count--;
	else
		LOG(ERROR, "fb locking unbalanced");

	if (fb->lock.count == 0 && fb->buffer_handle > 0) {
		int32_t ret;
		struct drm_clip_rect clip_rect = {
			0, 0, fb->buffer_properties.width, fb->buffer_properties.height
		};
		munmap(fb->lock.map, fb->buffer_properties.size);
		ret = drmModeDirtyFB(fb->drm->fd, fb->fb_id, &clip_rect, 1);
		if (ret)
			LOG(ERROR, "drmModeDirtyFB failed: %m");
	}
}

int32_t fb_getwidth(fb_t* fb)
{
	return fb->buffer_properties.width;
}

int32_t fb_getheight(fb_t* fb)
{
	return fb->buffer_properties.height;
}

int32_t fb_getpitch(fb_t* fb)
{
	return fb->buffer_properties.pitch;
}

int32_t fb_getscaling(fb_t* fb)
{
	return fb->buffer_properties.scaling;
}
