/*
 *   Creation Date: <2002/10/23 20:26:40 samuel>
 *   Time-stamp: <2004/01/07 19:39:15 samuel>
 *
 *     <video_common.c>
 *
 *     Shared video routines
 *
 *   Copyright (C) 2002, 2003, 2004 Samuel Rydh (samuel@ibrium.se)
 *
 *   This program is free software; you can redistribute it and/or
 *   modify it under the terms of the GNU General Public License
 *   as published by the Free Software Foundation
 *
 */

#include "config.h"
#include "libc/vsprintf.h"
#include "libopenbios/bindings.h"
#include "libopenbios/fontdata.h"
#include "libopenbios/ofmem.h"
#include "libopenbios/video.h"
#include "packages/video.h"
#include "drivers/vga.h"
#define NO_QEMU_PROTOS
#include "arch/common/fw_cfg.h"

struct video_info video;

unsigned long
video_get_color( int col_ind )
{
	unsigned long col;
	if( !VIDEO_DICT_VALUE(video.ih) || col_ind < 0 || col_ind > 255 )
		return 0;
	if( VIDEO_DICT_VALUE(video.depth) == 8 )
		return col_ind;
	col = video.pal[col_ind];
	if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 )
		return col;
	if( VIDEO_DICT_VALUE(video.depth) == 15 )
		return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f);
	return 0;
}

/* ( fbaddr maskaddr width height fgcolor bgcolor -- ) */

void
video_mask_blit(void)
{
	ucell bgcolor = POP();
	ucell fgcolor = POP();
	ucell height = POP();
	ucell width = POP();
	unsigned char *mask = (unsigned char *)POP();
	unsigned char *fbaddr = (unsigned char *)POP();

	ucell color;
	unsigned char *dst, *rowdst;
	int x, y, m, b, d, depthbytes;

	fgcolor = video_get_color(fgcolor);
	bgcolor = video_get_color(bgcolor);
	d = VIDEO_DICT_VALUE(video.depth);
	depthbytes = (d + 1) >> 3;

	dst = fbaddr;
	for( y = 0; y < height; y++) {
		rowdst = dst;
		for( x = 0; x < (width + 1) >> 3; x++ ) {
			for (b = 0; b < 8; b++) {
				m = (1 << (7 - b));

				if (*mask & m) {
					color = fgcolor;
				} else {
					color = bgcolor;
				}

				if( d >= 24 )
					*((uint32_t*)dst) = color;
				else if( d >= 15 )
					*((uint16_t*)dst) = color;
				else
					*dst = color;

				dst += depthbytes;
			}
			mask++;
		}
		dst = rowdst;
		dst += VIDEO_DICT_VALUE(video.rb);
	}
}

/* ( x y w h fgcolor bgcolor -- ) */

void
video_invert_rect( void )
{
	ucell bgcolor = POP();
	ucell fgcolor = POP();
	int h = POP();
	int w = POP();
	int y = POP();
	int x = POP();
	char *pp;

	bgcolor = video_get_color(bgcolor);
	fgcolor = video_get_color(fgcolor);

	if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
		x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
		return;

	pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
	for( ; h--; pp += *(video.rb) ) {
		int ww = w;
		if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
			uint32_t *p = (uint32_t*)pp + x;
			while( ww-- ) {
				if (*p == fgcolor) {
					*p++ = bgcolor;
				} else if (*p == bgcolor) {
					*p++ = fgcolor;
				}
			}
		} else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
			uint16_t *p = (uint16_t*)pp + x;
			while( ww-- ) {
				if (*p == (uint16_t)fgcolor) {
					*p++ = bgcolor;
				} else if (*p == (uint16_t)bgcolor) {
					*p++ = fgcolor;
				}
			}
		} else {
			char *p = (char *)(pp + x);

			while( ww-- ) {
				if (*p == (char)fgcolor) {
					*p++ = bgcolor;
				} else if (*p == (char)bgcolor) {
					*p++ = fgcolor;
				}
			}
		}
	}
}

/* ( color_ind x y width height -- ) (?) */
void
video_fill_rect(void)
{
	int h = POP();
	int w = POP();
	int y = POP();
	int x = POP();
	int col_ind = POP();

	char *pp;
	unsigned long col = video_get_color(col_ind);

        if (!VIDEO_DICT_VALUE(video.ih) || x < 0 || y < 0 || w <= 0 || h <= 0 ||
            x + w > VIDEO_DICT_VALUE(video.w) || y + h > VIDEO_DICT_VALUE(video.h))
		return;

	pp = (char*)VIDEO_DICT_VALUE(video.mvirt) + VIDEO_DICT_VALUE(video.rb) * y;
	for( ; h--; pp += VIDEO_DICT_VALUE(video.rb) ) {
		int ww = w;
		if( VIDEO_DICT_VALUE(video.depth) == 24 || VIDEO_DICT_VALUE(video.depth) == 32 ) {
			uint32_t *p = (uint32_t*)pp + x;
			while( ww-- )
				*p++ = col;
		} else if( VIDEO_DICT_VALUE(video.depth) == 16 || VIDEO_DICT_VALUE(video.depth) == 15 ) {
			uint16_t *p = (uint16_t*)pp + x;
			while( ww-- )
				*p++ = col;
		} else {
                        char *p = (char *)(pp + x);

			while( ww-- )
				*p++ = col;
		}
	}
}

void setup_video()
{
	/* Make everything inside the video_info structure point to the
	   values in the Forth dictionary. Hence everything is always in
	   sync. */
	phandle_t options;
	char buf[10];

	feval("['] display-ih cell+");
	video.ih = cell2pointer(POP());

	feval("['] frame-buffer-adr cell+");
	video.mvirt = cell2pointer(POP());
	feval("['] openbios-video-width cell+");
	video.w = cell2pointer(POP());
	feval("['] openbios-video-height cell+");
	video.h = cell2pointer(POP());
	feval("['] depth-bits cell+");
	video.depth = cell2pointer(POP());
	feval("['] line-bytes cell+");
	video.rb = cell2pointer(POP());
	feval("['] color-palette cell+");
	video.pal = cell2pointer(POP());

	/* Set global variables ready for fb8-install */
	PUSH( pointer2cell(video_mask_blit) );
	fword("is-noname-cfunc");
	feval("to fb8-blitmask");
	PUSH( pointer2cell(video_fill_rect) );
	fword("is-noname-cfunc");
	feval("to fb8-fillrect");
	PUSH( pointer2cell(video_invert_rect) );
	fword("is-noname-cfunc");
	feval("to fb8-invertrect");

	/* Static information */
	PUSH((ucell)fontdata);
	feval("to (romfont)");
	PUSH(FONT_HEIGHT);
	feval("to (romfont-height)");
	PUSH(FONT_WIDTH);
	feval("to (romfont-width)");

	/* Initialise the structure */
	VIDEO_DICT_VALUE(video.w) = VGA_DEFAULT_WIDTH;
	VIDEO_DICT_VALUE(video.h) = VGA_DEFAULT_HEIGHT;
	VIDEO_DICT_VALUE(video.depth) = VGA_DEFAULT_DEPTH;
	VIDEO_DICT_VALUE(video.rb) = VGA_DEFAULT_LINEBYTES;

#if defined(CONFIG_QEMU) && (defined(CONFIG_PPC) || defined(CONFIG_SPARC32) || defined(CONFIG_SPARC64))
	/* If running from QEMU, grab the parameters from the firmware interface */
	int w, h, d;

	w = fw_cfg_read_i16(FW_CFG_ARCH_WIDTH);
        h = fw_cfg_read_i16(FW_CFG_ARCH_HEIGHT);
        d = fw_cfg_read_i16(FW_CFG_ARCH_DEPTH);
	if (w && h && d) {
		VIDEO_DICT_VALUE(video.w) = w;
		VIDEO_DICT_VALUE(video.h) = h;
		VIDEO_DICT_VALUE(video.depth) = d;
		VIDEO_DICT_VALUE(video.rb) = (w * ((d + 7) / 8));
	}
#endif

	/* Setup screen-#rows/screen-#columns */
	options = find_dev("/options");
	snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.w) / FONT_WIDTH);
	set_property(options, "screen-#columns", buf, strlen(buf) + 1);
	snprintf(buf, sizeof(buf), FMT_ucell, VIDEO_DICT_VALUE(video.h) / FONT_HEIGHT);
	set_property(options, "screen-#rows", buf, strlen(buf) + 1);
}
