#include "viewerFB.h"
#include "fb.h"
#include <stdio.h>
#if 0
#include <asm/ps3fb.h>
#endif


#define default_sdl_flag SDL_INIT_TIMER | SDL_INIT_JOYSTICK

ViewerFB::ViewerFB() {}
ViewerFB::~ViewerFB() {}

#if defined(__linux__)

#define DEVICE_NAME "/dev/fb0"
#define DIV_BYTE 8


ScreenInfo get_fbdev_addr(void)
{
	ScreenInfo info;
	int fd_framebuffer ;
	struct fb_var_screeninfo vinfo;
	struct fb_fix_screeninfo finfo;
	long int screensize ;
	//long int location;
	char *fbptr ;
	char tmp[DIV_BYTE*10];

	//int x , y ;
	int xres,yres,vbpp,line_len;
	//unsigned short tcolor ;

	/* 読み書き用にファイルを開く */
	fd_framebuffer = open( DEVICE_NAME , O_RDWR);
	if ( !fd_framebuffer ) {
	    send_current_error_msg("Framebuffer device open error !");
	    exit(1);
	}
	send_current_information("The framebuffer device was opened !");
	
	/* 固定スクリーン情報取得 */
	if ( ioctl( fd_framebuffer , FBIOGET_FSCREENINFO , &finfo ) ) {
	    send_current_error_msg("Fixed information not gotton !");
	    exit(2);
	}

	/* 変動スクリーン情報取得 */
	if ( ioctl( fd_framebuffer , FBIOGET_VSCREENINFO , &vinfo ) ) {
		send_current_error_msg("Variable information not gotton !");
		exit(3);
	}
	xres = vinfo.xres ;
	yres = vinfo.yres ;
	vbpp = vinfo.bits_per_pixel ;
	line_len = finfo.line_length ;
	sprintf( tmp , "%d(pixel)x%d(line), %dbpp(bits per pixel)",xres,yres,vbpp);
	send_current_information( tmp );

	/* バイト単位でのスクリーンのサイズを計算 */
	screensize = xres * yres * vbpp / DIV_BYTE ;

	/* デバイスをメモリにマップする */
	fbptr = (char *)mmap(0,screensize,PROT_READ | PROT_WRITE,MAP_SHARED,fd_framebuffer,0);
	if ( (int)fbptr == -1 ) {
		send_current_error_msg("Don't get framebuffer device to memory !");
		exit(4);
	}
	send_current_information("The framebuffer device was mapped !");

#if 0
    // Take control of frame buffer from kernel
    ioctl(fd_framebuffer, PS3FB_IOCTL_ON, 0);
    int field_ndx = 0;
    ioctl(fd_framebuffer , PS3FB_IOCTL_FSEL,  &field_ndx );
#endif


	printf("fb: 0x%x \n", (unsigned int)fbptr);
	info.xres = xres;
        info.yres = yres; 
        info.vbpp = vbpp;
        info.line_len = line_len;
	info.fbptr[0] = (uint32_t *)fbptr;
      
	return info;
	//munmap(fbptr,screensize);
	//close(fd_framebuffer);
	//return 0;
}

void send_current_error_msg(const char *ptr)
{
    fprintf( stderr , "%s\n" , ptr );
}

void send_current_information(const char *ptr)
{
    fprintf( stdout , "%s\n" , ptr );
}

#else /* !defined(__linux__) */
ScreenInfo get_fbdev_addr(void) { 
    ScreenInfo tmp = {0,0,0,0};
    return tmp;
}
#endif /* defined(__linux__) */


Uint32 *
ViewerFB::video_init(TaskManager *manager, int bpp, int width, int height)
{
    Uint32 sdl_flag = default_sdl_flag |  SDL_INIT_VIDEO;

    if (SDL_Init(sdl_flag) < 0) {
	fprintf(stderr,"Couldn't initialize SDL: %s\n",SDL_GetError());
	exit(1);
    }

    screen_info = get_fbdev_addr();
    Uint32 *pixels = screen_info.fbptr[0];

    if (pixels == 0) {
	fprintf(stderr, "Cannot get frame buffer!\n");
    	pixels = (new Uint32[width*height*32/8]);
    }
    this->width = screen_info.xres;
    this->height = screen_info.yres;
    this->bpp = screen_info.vbpp;

    return pixels;
}

void
ViewerFB::clean_pixels()
{
}

void
ViewerFB::clear_screen()
{
}


void
ViewerFB::free_device()
{
}


