/* Swfdec
 * Copyright (C) 2007 Benjamin Otte <otte@gnome.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 
 * Boston, MA  02110-1301  USA
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "swfdec_fb_drawing.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

#define FBDEV "/dev/mem"
#if 0
#define SHMEM_GNASH_PHY_START             (0x3A200000)
#else
#define SHMEM_GNASH_PHY_START             (0x36800000)
#endif

extern int emmaBlit( void *src, int sx, int sy, int sw, int sh, void *dst, int dx, int dy );

static int drawing_inited = 0;
static unsigned long shmem_start = SHMEM_GNASH_PHY_START;
static int fb = -1;
static unsigned char  *g_buffer = NULL;
static int g_maxw = 960;
static int g_maxh = 540;
static int g_stride = 960 * 4;

/**
 * :
 * @buffer: buffer address in/out
 * @maxw: max width in/out
 * @maxh: max height in/out
 * @stride: stride in/out
 *
 * init drawing.
 *
 * Returns: SUCC/FAIL
 **/
int swfdec_fb_drawing_init(unsigned char  ** buffer, int * maxw, int *maxh, int *stride)
{
    printf("drawing init!\n");
	if (drawing_inited)
		return 0;
	fb = open(FBDEV, O_RDWR);
	if(fb < 0)
	{
    	printf("Error opening %s: %m. Check kernel config\n", FBDEV);
    	printf("errno = %d, (%s)\n", errno, strerror(errno));
    	return -1;
	}
	g_maxw = *maxw = 960;
	g_maxh = *maxh = 540;
	g_stride = *stride = 960 * 4;
	g_buffer = *buffer = (unsigned char *)mmap(0, 0x00200000, (PROT_READ | PROT_WRITE), MAP_SHARED, fb, shmem_start + 0x00200000);
	if (*buffer == NULL)
	{
    	printf("Error mmap.\n");
    	printf("errno = %d, (%s)\n", errno, strerror(errno));
		close(fb);
		fb = -1;
    	return -1;
	}
	memset(*buffer, 0, *stride * *maxh);
	drawing_inited = 1;
    printf("drawing init ok, stride = %d!\n", *stride);
	return 0;
}

/**
 * :
 * @: 
 *
 * uninit drawing.
 *
 * Returns: SUCC/FAIL
 **/
int swfdec_fb_drawing_uninit(unsigned char  *buffer, int maxw, int maxh, int stride)
{
    printf("drawing uninit!\n");
	if (!drawing_inited)
		return 0;
	memset(buffer, 0, stride * maxh);
	swfdec_fb_drawing_blit(0, 0, maxw, maxh, 0, 0);
	munmap(buffer, 0x00200000);
	if (fb != -1)
	{
    	close(fb);
    	fb = -1;
	}
	drawing_inited = 0;
	printf("drawing uninit ok!\n");
	return 0;
}

/**
 * :
 * @sx: 
 * @sy: 
 * @sw: 
 * @sh: 
 * @dx: 
 * @dy: 
 *
 * blit.
 *
 * Returns: SUCC/FAIL
 **/
int swfdec_fb_drawing_blit(int sx, int sy, int sw, int sh, int dx, int dy)
{
	if (!drawing_inited)
		return -1;
	if (emmaBlit((void *)(shmem_start + 0x00200000),
            sx,
            sy,
            sw,
            sh,
            (void *)(shmem_start),
            dx,
            dy))
	{
#if 0
    	printf("emmaBlit ok!\n");
#endif
		return 0;
	}
	else
	{
    	printf("emmaBlit fail!\n");
		return -1;
	}
}

#ifndef DRAWING_NO_AUTO_UNINIT
/**
 * :
 * @: 
 *
 * ensure uninit.
 *
 * Returns: N/A
 **/
static void __attribute((destructor)) uninit(void) {
  swfdec_fb_drawing_uninit(g_buffer, g_maxw, g_maxh, g_stride);
}
#endif
