/**********************************************************************
** Copyright (C) 2010 FreeC ORG. All rights reserved.
** Author: Carlson Lee.
**
** This file is part of FreeC.
**
** This file may be distributed and/or modified under the terms of the
** GNU General Public License version 2 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.
**
** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
** See http://freec.sourceforge.net
**
** Contact CarlsonLee_FreeC@hotmail.com if any conditions of this licensing are
** not clear to you.
**
**********************************************************************/
#include "config.h"
#include "typedef.h"
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
//#include <asm/page.h>
#include <sys/mman.h>
#include <directfb.h>
#include <asm/errno.h>
#include <pthread.h>
#include "errcode.h"
#include "cncui.h"
#include "disp.h"
#include "cncdisplay.h"
#include "cnctask.h"
static IDirectFB *dfb = NULL;
static IDirectFBSurface *primary = NULL;
static IDirectFBDisplayLayer *layer = NULL;
static IDirectFBSurface *imageSurface = NULL;
static IDirectFBEventBuffer *mouse_events = NULL;
static pthread_mutex_t mutex_display = PTHREAD_MUTEX_INITIALIZER;
static UINT8 *pCursorBuf = NULL;
static UINT8 *mouse_bg_data = NULL;
#define DFBCHECK(x...) /
{ /
DFBResult err = x; /
if (err != DFB_OK) /
{ /
printf("%s <%d>:/n/t", __FILE__, __LINE__ ); /
DirectFBErrorFatal( #x, err ); /
goto exit; /
} /
}
#define MOUSE_WIDTH 12
#define MOUSE_HEIGHT 20
/* init framebuffer*/
CNC_RET dispInit(void)
{
DFBSurfaceDescription dsc;
pthread_t key_thread_id;
if(dfb || primary || imageSurface)
return CERR_NONE;
DFBCHECK (DirectFBInit (0, 0));
DFBCHECK (DirectFBCreate (&dfb));
DFBCHECK (dfb->SetCooperativeLevel (dfb, DFSCL_FULLSCREEN));
dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc.caps = DSCAPS_PRIMARY;
dsc.width = SCREEN_WIDTH;
dsc.height = SCREEN_HEIGHT;
//#if BYTES_PER_PIXEL==3
// dsc.pixelformat = DSPF_RGB24 ;
//#elif BYTES_PER_PIXEL==4
dsc.pixelformat = DSPF_RGB32 ;
dfb->GetDisplayLayer(dfb, 0, &layer);
layer->EnableCursor(layer, 1);
//#endif
DFBCHECK (dfb->CreateSurface( dfb, &dsc, &primary ));
dsc.flags = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc.width = SCREEN_WIDTH;
dsc.height = SCREEN_HEIGHT;
//#if BYTES_PER_PIXEL==3
// dsc.pixelformat = DSPF_RGB24 ;
//#elif BYTES_PER_PIXEL==4
dsc.pixelformat = DSPF_RGB32 ;
//#endif
DFBCHECK(dfb->CreateSurface( dfb, &dsc, &imageSurface));
DFBCHECK(dfb->CreateInputEventBuffer( dfb, DICAPS_ALL,
DFB_FALSE, &mouse_events));
printf("pthread_create procKeyMsg /n");
if(0 != pthread_create(&key_thread_id,NULL,procKeyMsg,NULL))
{
printf("pthread_create procKeyMsg failed/n");
goto exit;
}
pCursorBuf = (UINT8*)malloc(4*60*BYTES_PER_PIXEL);
mouse_bg_data = (UINT8*)malloc(SCREEN_WIDTH*SCREEN_HEIGHT*4);
return CERR_NONE;
exit:
if(mouse_events)
mouse_events->Release( mouse_events );
if(imageSurface)
imageSurface->Release( imageSurface );
if(primary)
primary->Release( primary );
if(layer)
layer->Release( layer );
if(dfb)
dfb->Release( dfb );
return CERR_DISPLAY_INIT_FAIL;
}
void dispUninit()
{
if(mouse_events)
mouse_events->Release( mouse_events );
if(imageSurface)
imageSurface->Release( imageSurface );
if(primary)
primary->Release( primary );
if(layer)
layer->Release( layer );
if(dfb)
dfb->Release( dfb );
if(pCursorBuf)
{
free(pCursorBuf);
pCursorBuf = NULL;
}
if(mouse_bg_data)
{
free(mouse_bg_data);
mouse_bg_data = NULL;
}
mouse_events = NULL;
imageSurface = NULL;
primary = NULL;
dfb = NULL;
pthread_mutex_destroy(&mutex_display);
}
const unsigned char mouse_data[720] =
{
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF,
0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01,
0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xFF,
0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
static int old_mouse_x = MOUSE_WIDTH/2;
static int old_mouse_y = MOUSE_HEIGHT/2;
static int old_mouse_width = -1;
static int old_mouse_height = -1;
static BOOL gbMouseShow = FALSE;
void dispHideMouse()
{
gbMouseShow = FALSE;
}
static void dispUpdateMouse(int x, int y)
{
UINT8* display_buf = NULL;
int display_buf_len = 0;
DFBRectangle oldrect = {0,0,0,0};
int mouse_width = MOUSE_WIDTH;
int mouse_height = MOUSE_HEIGHT;
int i, j;
if(dfb==NULL || primary==NULL || imageSurface == NULL)
return;
if(x<0 || y<0 || x>=SCREEN_WIDTH || y>=SCREEN_HEIGHT)
return;
if(pthread_mutex_trylock(&mutex_display) == EBUSY)
return;
DFBCHECK(imageSurface->Lock(imageSurface, DSLF_WRITE, (void*)&display_buf, &display_buf_len));
//copy old mouse bg buffer to screen
if(old_mouse_x >=0 && old_mouse_y>=0 && old_mouse_width> 0 && old_mouse_height>0 && gbMouseShow)
{
if(old_mouse_x+MOUSE_WIDTH>SCREEN_WIDTH)
{
mouse_width = SCREEN_WIDTH - old_mouse_x;
}
if(old_mouse_y+MOUSE_HEIGHT>SCREEN_HEIGHT)
{
mouse_height = SCREEN_HEIGHT - old_mouse_y;
}
for(i=0; i<mouse_height; i++)
{
memcpy(display_buf+((old_mouse_y+i)*SCREEN_WIDTH+old_mouse_x)*BYTES_PER_PIXEL, mouse_bg_data+(i*MOUSE_WIDTH*BYTES_PER_PIXEL),mouse_width*BYTES_PER_PIXEL);
}
oldrect.x = old_mouse_x;
oldrect.y = old_mouse_y;
oldrect.w = mouse_width;
oldrect.h = mouse_height;
}
//copy new mouse bg to old mouse bg buffer
{
if(x+MOUSE_WIDTH>SCREEN_WIDTH)
{
mouse_width = SCREEN_WIDTH - x;
}
if(y+MOUSE_HEIGHT>SCREEN_HEIGHT)
{
mouse_height = SCREEN_HEIGHT - y;
}
for(i=0; i<mouse_height; i++)
{
memcpy(mouse_bg_data+(i*MOUSE_WIDTH*BYTES_PER_PIXEL), display_buf+((y+i)*SCREEN_WIDTH+x)*BYTES_PER_PIXEL, mouse_width*BYTES_PER_PIXEL);
}
gbMouseShow = TRUE;
}
//set mouse icon to new place
{
//unsigned char *pTmp = mouse_data;
if(x+MOUSE_WIDTH>SCREEN_WIDTH)
{
mouse_width = SCREEN_WIDTH - x;
}
if(y+MOUSE_HEIGHT>SCREEN_HEIGHT)
{
mouse_height = SCREEN_HEIGHT - y;
}
for(i=0; i<mouse_height; i++)
{
unsigned char* pTmp = (unsigned char*)mouse_data + i*MOUSE_WIDTH*3;
for(j=0; j<mouse_width; j++)
{
if(*pTmp != 0x00)
{
*(display_buf+((y+i)*SCREEN_WIDTH+x+j)*BYTES_PER_PIXEL) = *pTmp;
*(display_buf+((y+i)*SCREEN_WIDTH+x+j)*BYTES_PER_PIXEL+1) = *pTmp;
*(display_buf+((y+i)*SCREEN_WIDTH+x+j)*BYTES_PER_PIXEL+2) = *pTmp;
// *(display_buf+((y+i)*SCREEN_WIDTH+x+j)*BYTES_PER_PIXEL+3) = 0xFF;
}
pTmp+=3;
}
}
old_mouse_x = x;
old_mouse_y = y;
old_mouse_width = mouse_height;
old_mouse_height = mouse_width;
}
DFBCHECK(imageSurface->Unlock(imageSurface));
primary->Blit (primary, imageSurface, &oldrect, oldrect.x, oldrect.y);
oldrect.x = x;
oldrect.y = y;
oldrect.h = mouse_height;
oldrect.w = mouse_width;
primary->Blit (primary, imageSurface, &oldrect, oldrect.x, oldrect.y);
exit:
pthread_mutex_unlock(&mutex_display);
return;
}
int mouse_x = SCREEN_WIDTH/2;
int mouse_y = SCREEN_HEIGHT/2;
void* procKeyMsg(void* pParam)
{
DFBInputEvent evt;
mouse_events->WaitForEvent( mouse_events );
cncTask_SetKeyThreadExited(FALSE);
while (mouse_events->GetEvent( mouse_events, DFB_EVENT(&evt) ) == DFB_OK)
{
switch (evt.type)
{
case DIET_KEYRELEASE:
cncDisp_ProcMsg(UI_OPERATE_KEYUP, evt.key_symbol, 0);
break;
case DIET_KEYPRESS:
cncDisp_ProcMsg(UI_OPERATE_KEYDOWN, evt.key_symbol, 0);
break;
case DIET_BUTTONPRESS:
if(evt.buttons & DIBM_LEFT)
{
UINT32 lParam = ((mouse_y<<16)&0xFFFF0000)+mouse_x;
cncDisp_ProcMsg(UI_OPERATE_LBTN_DOWN, 0, lParam);
}
if(evt.buttons & DIBM_RIGHT)
{
cncTask_SetExit(TRUE);
}
break;
case DIET_BUTTONRELEASE:
if(evt.button == DIBI_LEFT)
{
UINT32 lParam = ((mouse_y<<16)&0xFFFF0000)+mouse_x;
cncDisp_ProcMsg(UI_OPERATE_LBTN_UP, 0, lParam);
}
break;
case DIET_AXISMOTION:
{
if (evt.flags & DIEF_AXISREL)
{
switch (evt.axis)
{
case DIAI_X:
mouse_x += evt.axisrel;
break;
case DIAI_Y:
mouse_y += evt.axisrel;
break;
default:
break;
}
}
if(mouse_x>=SCREEN_WIDTH)
{
mouse_x =SCREEN_WIDTH-1;
}
if(mouse_x<0)
{
mouse_x =0;
}
if(mouse_y>=SCREEN_HEIGHT)
{
mouse_y =SCREEN_HEIGHT-1;
}
if(mouse_y<0)
{
mouse_y =0;
}
dispUpdateMouse(mouse_x,mouse_y);
{
UINT32 lParam = ((mouse_y<<16)&0xFFFF0000)+mouse_x;
cncDisp_ProcMsg(UI_OPERATE_MOUSE_MOVE, 0, lParam);
}
}
default:
break;
}
if(cncTask_GetExit())
break;
mouse_events->WaitForEvent( mouse_events );
}
cncTask_SetKeyThreadExited(TRUE);
return NULL;
}
void dispUpdateScreen()
{
void* display_buf = NULL;
int display_buf_len = 0;
int i, j;
const DFBRectangle rect = {0,0, SCREEN_WIDTH, SCREEN_HEIGHT};
if(dfb==NULL || primary==NULL || imageSurface == NULL)
return;
if(pthread_mutex_trylock(&mutex_display) == EBUSY)
return;
disp_num++;
DFBCHECK(imageSurface->Lock(imageSurface, DSLF_WRITE, &display_buf, &display_buf_len));
printf("dispUpdateScreen = %d/n", disp_num);
if(!uiGetBuffer(display_buf))
{
DFBCHECK(imageSurface->Unlock(imageSurface));
pthread_mutex_unlock(&mutex_display);
return;
}
for(i=0; i<old_mouse_width; i++)
{
memcpy(mouse_bg_data+(i*MOUSE_WIDTH*BYTES_PER_PIXEL), display_buf+((old_mouse_y+i)*SCREEN_WIDTH+old_mouse_x)*BYTES_PER_PIXEL, old_mouse_width*BYTES_PER_PIXEL);
}
if(gbMouseShow)
{
old_mouse_width = MOUSE_WIDTH;
old_mouse_height = MOUSE_HEIGHT;
if(old_mouse_x+MOUSE_WIDTH>SCREEN_WIDTH)
{
old_mouse_width = SCREEN_WIDTH - old_mouse_x;
}
if(old_mouse_y+MOUSE_HEIGHT>SCREEN_HEIGHT)
{
old_mouse_height = SCREEN_HEIGHT - old_mouse_y;
}
for(i=0; i<old_mouse_height; i++)
{
unsigned char* pTmp = (unsigned char*)mouse_data + i*MOUSE_WIDTH*3;
for(j=0; j<old_mouse_width; j++)
{
if(*pTmp != 0x00)
{
*((UINT8*)display_buf+((old_mouse_y+i)*SCREEN_WIDTH+old_mouse_x+j)*BYTES_PER_PIXEL) = *pTmp;
*((UINT8*)display_buf+((old_mouse_y+i)*SCREEN_WIDTH+old_mouse_x+j)*BYTES_PER_PIXEL+1) = *pTmp;
*((UINT8*)display_buf+((old_mouse_y+i)*SCREEN_WIDTH+old_mouse_x+j)*BYTES_PER_PIXEL+2) = *pTmp;
}
pTmp+=3;
}
}
}
DFBCHECK(imageSurface->Unlock(imageSurface));
primary->Blit (primary, imageSurface, &rect, 0, 0);
exit:
pthread_mutex_unlock(&mutex_display);
return;
}