iPod Linux framebuffer support.
--ryan. Date: Sun, 19 Jun 2005 15:53:22 -0700 From: Joshua Oreman <oremanj@gmail.com> To: sdl@libsdl.org Subject: [SDL] [PATCH] iPod framebuffer video driver Hi SDL-list, I've been working on a port of SDL to iPodLinux (http://www.ipodlinux.org). I've created a patch for both the standard 2-bit iPod screen (using an unchangeable palette) and the 16-bit iPod photo. The patch is attached, against version 1.2.8. I've created two pages on the iPodLinux wiki about this patch: http://www.ipodlinux.org/Building_SDL and http://www.ipodlinux.org/SDL_Programming. See those pages if you're curious. Comments? Questions? Is this something that might be able to get into SDL 1.2.9? Thanks for your feedback! -- Josh --HG-- extra : convert_revision : svn%3Ac70aab31-4412-0410-b14c-859654838e24/trunk%401143
This commit is contained in:
parent
45d84e2337
commit
ecbe9ec648
9 changed files with 797 additions and 1 deletions
27
configure.in
27
configure.in
|
@ -549,6 +549,20 @@ CheckNASM()
|
|||
fi
|
||||
}
|
||||
|
||||
dnl Do the iPod thing
|
||||
CheckIPod()
|
||||
{
|
||||
AC_ARG_ENABLE(ipod,
|
||||
[ --enable-ipod configure SDL to work with iPodLinux [default=yes on arm-elf]],
|
||||
, enable_ipod=yes)
|
||||
|
||||
if test x$enable_ipod = xyes; then
|
||||
CFLAGS="$CFLAGS -DENABLE_IPOD -DIPOD"
|
||||
VIDEO_SUBDIRS="$VIDEO_SUBDIRS ipod"
|
||||
VIDEO_DRIVERS="$VIDEO_DRIVERS ipod/libvideo_ipod.la"
|
||||
fi
|
||||
}
|
||||
|
||||
dnl Find the nanox include and library directories
|
||||
CheckNANOX()
|
||||
{
|
||||
|
@ -1306,7 +1320,7 @@ CheckPTHREAD()
|
|||
pthread_lib="-lpthread"
|
||||
;;
|
||||
esac
|
||||
if test x$enable_threads = xyes -a x$enable_pthreads = xyes; then
|
||||
if test x$enable_threads = xyes -a x$enable_pthreads = xyes -a x$enable_ipod != xyes; then
|
||||
# Save the original compiler flags and libraries
|
||||
ac_save_cflags="$CFLAGS"; ac_save_libs="$LIBS"
|
||||
# Add the pthread compiler flags and libraries
|
||||
|
@ -1932,6 +1946,15 @@ CheckRPATH()
|
|||
}
|
||||
|
||||
case "$target" in
|
||||
arm-*-elf*)
|
||||
ARCH=linux
|
||||
CheckDummyVideo
|
||||
CheckIPod
|
||||
# Set up files for the timer library
|
||||
if test x$enable_timers = xyes; then
|
||||
COPY_ARCH_SRC(src/timer, linux, SDL_systimer.c)
|
||||
fi
|
||||
;;
|
||||
*-*-linux*|*-*-gnu*|*-*-k*bsd*-gnu)
|
||||
case "$target" in
|
||||
*-*-linux*) ARCH=linux ;;
|
||||
|
@ -2810,6 +2833,7 @@ AM_CONDITIONAL(TARGET_MACOS, test $ARCH = macos)
|
|||
AM_CONDITIONAL(TARGET_MACOSX, test $ARCH = macosx)
|
||||
AM_CONDITIONAL(TARGET_QNX, test $ARCH = qnx)
|
||||
AM_CONDITIONAL(TARGET_MINT, test $ARCH = mint)
|
||||
AM_CONDITIONAL(TARGET_IPOD, test x$enable_ipod = xyes)
|
||||
|
||||
# More automake conditionals
|
||||
AM_CONDITIONAL(USE_DIRECTX, test x$use_directx = xyes)
|
||||
|
@ -2989,6 +3013,7 @@ src/video/epoc/Makefile
|
|||
src/video/fbcon/Makefile
|
||||
src/video/gem/Makefile
|
||||
src/video/ggi/Makefile
|
||||
src/video/ipod/Makefile
|
||||
src/video/maccommon/Makefile
|
||||
src/video/macdsp/Makefile
|
||||
src/video/macrom/Makefile
|
||||
|
|
|
@ -181,7 +181,9 @@ static void SDL_StopEventThread(void)
|
|||
SDL_EventThread = NULL;
|
||||
SDL_DestroyMutex(SDL_EventLock.lock);
|
||||
}
|
||||
#ifndef IPOD
|
||||
SDL_DestroyMutex(SDL_EventQ.lock);
|
||||
#endif
|
||||
}
|
||||
|
||||
Uint32 SDL_EventThreadID(void)
|
||||
|
|
|
@ -37,6 +37,10 @@ static char rcsid =
|
|||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
|
||||
#ifdef IPOD /* iPod doesn't support threading at all */
|
||||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
|
||||
#ifdef macintosh /* MacOS 7/8 don't support preemptive multi-tasking */
|
||||
#define CANT_THREAD_EVENTS
|
||||
#endif
|
||||
|
|
|
@ -74,7 +74,9 @@ void SDL_CursorQuit(void)
|
|||
int SDL_CursorInit(Uint32 multithreaded)
|
||||
{
|
||||
/* We don't have mouse focus, and the cursor isn't drawn yet */
|
||||
#ifndef IPOD
|
||||
SDL_cursorstate = CURSOR_VISIBLE;
|
||||
#endif
|
||||
|
||||
/* Create the default cursor */
|
||||
if ( SDL_defcursor == NULL ) {
|
||||
|
|
|
@ -341,6 +341,9 @@ extern VideoBootStrap DGA_bootstrap;
|
|||
#ifdef ENABLE_NANOX
|
||||
extern VideoBootStrap NX_bootstrap;
|
||||
#endif
|
||||
#ifdef ENABLE_IPOD
|
||||
extern VideoBootStrap iPod_bootstrap;
|
||||
#endif
|
||||
#ifdef ENABLE_FBCON
|
||||
extern VideoBootStrap FBCON_bootstrap;
|
||||
#endif
|
||||
|
|
|
@ -57,6 +57,9 @@ static VideoBootStrap *bootstrap[] = {
|
|||
#ifdef ENABLE_NANOX
|
||||
&NX_bootstrap,
|
||||
#endif
|
||||
#ifdef ENABLE_IPOD
|
||||
&iPod_bootstrap,
|
||||
#endif
|
||||
#ifdef ENABLE_QTOPIA
|
||||
&Qtopia_bootstrap,
|
||||
#endif
|
||||
|
|
5
src/video/ipod/Makefile.am
Normal file
5
src/video/ipod/Makefile.am
Normal file
|
@ -0,0 +1,5 @@
|
|||
|
||||
## Makefile.am for SDL using the iPod framebuffer driver
|
||||
|
||||
noinst_LTLIBRARIES = libvideo_ipod.la
|
||||
libvideo_ipod_la_SOURCES = SDL_ipodvideo.c SDL_ipodvideo.h
|
710
src/video/ipod/SDL_ipodvideo.c
Normal file
710
src/video/ipod/SDL_ipodvideo.c
Normal file
|
@ -0,0 +1,710 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <linux/vt.h>
|
||||
#include <linux/kd.h>
|
||||
#include <linux/keyboard.h>
|
||||
#include <linux/fb.h>
|
||||
|
||||
#include "SDL.h"
|
||||
#include "SDL_error.h"
|
||||
#include "SDL_video.h"
|
||||
#include "SDL_mouse.h"
|
||||
#include "SDL_sysvideo.h"
|
||||
#include "SDL_pixels_c.h"
|
||||
#include "SDL_events_c.h"
|
||||
#include "SDL_sysevents.h"
|
||||
#include "SDL_ipodvideo.h"
|
||||
|
||||
#define _THIS SDL_VideoDevice *this
|
||||
|
||||
static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat);
|
||||
static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags);
|
||||
static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
|
||||
static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors);
|
||||
static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects);
|
||||
static void iPod_VideoQuit (_THIS);
|
||||
static void iPod_PumpEvents (_THIS);
|
||||
|
||||
static long iPod_GetGeneration();
|
||||
|
||||
static int initd = 0;
|
||||
static int kbfd = -1;
|
||||
static int fbfd = -1;
|
||||
static int oldvt = -1;
|
||||
static int curvt = -1;
|
||||
static int old_kbmode = -1;
|
||||
static long generation = 0;
|
||||
static struct termios old_termios, cur_termios;
|
||||
|
||||
FILE *dbgout;
|
||||
|
||||
#define LCD_DATA 0x10
|
||||
#define LCD_CMD 0x08
|
||||
#define IPOD_OLD_LCD_BASE 0xc0001000
|
||||
#define IPOD_OLD_LCD_RTC 0xcf001110
|
||||
#define IPOD_NEW_LCD_BASE 0x70003000
|
||||
#define IPOD_NEW_LCD_RTC 0x60005010
|
||||
|
||||
static unsigned long lcd_base, lcd_rtc, lcd_width, lcd_height;
|
||||
|
||||
static long iPod_GetGeneration()
|
||||
{
|
||||
int i;
|
||||
char cpuinfo[256];
|
||||
char *ptr;
|
||||
FILE *file;
|
||||
|
||||
if ((file = fopen("/proc/cpuinfo", "r")) != NULL) {
|
||||
while (fgets(cpuinfo, sizeof(cpuinfo), file) != NULL)
|
||||
if (strncmp(cpuinfo, "Revision", 8) == 0)
|
||||
break;
|
||||
fclose(file);
|
||||
}
|
||||
for (i = 0; !isspace(cpuinfo[i]); i++);
|
||||
for (; isspace(cpuinfo[i]); i++);
|
||||
ptr = cpuinfo + i + 2;
|
||||
|
||||
return strtol(ptr, NULL, 10);
|
||||
}
|
||||
|
||||
static int iPod_Available()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void iPod_DeleteDevice (SDL_VideoDevice *device)
|
||||
{
|
||||
free (device->hidden);
|
||||
free (device);
|
||||
}
|
||||
|
||||
void iPod_InitOSKeymap (_THIS) {}
|
||||
|
||||
static SDL_VideoDevice *iPod_CreateDevice (int devindex)
|
||||
{
|
||||
SDL_VideoDevice *this;
|
||||
|
||||
this = (SDL_VideoDevice *)malloc (sizeof(SDL_VideoDevice));
|
||||
if (this) {
|
||||
memset (this, 0, sizeof *this);
|
||||
this->hidden = (struct SDL_PrivateVideoData *) malloc (sizeof(struct SDL_PrivateVideoData));
|
||||
}
|
||||
if (!this || !this->hidden) {
|
||||
SDL_OutOfMemory();
|
||||
if (this)
|
||||
free (this);
|
||||
return 0;
|
||||
}
|
||||
memset (this->hidden, 0, sizeof(struct SDL_PrivateVideoData));
|
||||
|
||||
generation = iPod_GetGeneration();
|
||||
|
||||
this->VideoInit = iPod_VideoInit;
|
||||
this->ListModes = iPod_ListModes;
|
||||
this->SetVideoMode = iPod_SetVideoMode;
|
||||
this->SetColors = iPod_SetColors;
|
||||
this->UpdateRects = iPod_UpdateRects;
|
||||
this->VideoQuit = iPod_VideoQuit;
|
||||
this->AllocHWSurface = 0;
|
||||
this->CheckHWBlit = 0;
|
||||
this->FillHWRect = 0;
|
||||
this->SetHWColorKey = 0;
|
||||
this->SetHWAlpha = 0;
|
||||
this->LockHWSurface = 0;
|
||||
this->UnlockHWSurface = 0;
|
||||
this->FlipHWSurface = 0;
|
||||
this->FreeHWSurface = 0;
|
||||
this->SetCaption = 0;
|
||||
this->SetIcon = 0;
|
||||
this->IconifyWindow = 0;
|
||||
this->GrabInput = 0;
|
||||
this->GetWMInfo = 0;
|
||||
this->InitOSKeymap = iPod_InitOSKeymap;
|
||||
this->PumpEvents = iPod_PumpEvents;
|
||||
this->free = iPod_DeleteDevice;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
VideoBootStrap iPod_bootstrap = {
|
||||
"ipod", "iPod Framebuffer Driver",
|
||||
iPod_Available, iPod_CreateDevice
|
||||
};
|
||||
|
||||
//--//
|
||||
|
||||
static int iPod_VideoInit (_THIS, SDL_PixelFormat *vformat)
|
||||
{
|
||||
if (!initd) {
|
||||
/*** Code adapted/copied from SDL fbcon driver. ***/
|
||||
|
||||
static const char * const tty0[] = { "/dev/tty0", "/dev/vc/0", 0 };
|
||||
static const char * const vcs[] = { "/dev/vc/%d", "/dev/tty%d", 0 };
|
||||
int i, tty0_fd;
|
||||
|
||||
dbgout = fdopen (open ("/etc/sdlpod.log", O_WRONLY | O_SYNC | O_APPEND), "a");
|
||||
if (dbgout) {
|
||||
setbuf (dbgout, 0);
|
||||
fprintf (dbgout, "--> Started SDL <--\n");
|
||||
}
|
||||
|
||||
// Try to query for a free VT
|
||||
tty0_fd = -1;
|
||||
for ( i=0; tty0[i] && (tty0_fd < 0); ++i ) {
|
||||
tty0_fd = open(tty0[i], O_WRONLY, 0);
|
||||
}
|
||||
if ( tty0_fd < 0 ) {
|
||||
tty0_fd = dup(0); /* Maybe stdin is a VT? */
|
||||
}
|
||||
ioctl(tty0_fd, VT_OPENQRY, &curvt);
|
||||
close(tty0_fd);
|
||||
|
||||
tty0_fd = open("/dev/tty", O_RDWR, 0);
|
||||
if ( tty0_fd >= 0 ) {
|
||||
ioctl(tty0_fd, TIOCNOTTY, 0);
|
||||
close(tty0_fd);
|
||||
}
|
||||
|
||||
if ( (geteuid() == 0) && (curvt > 0) ) {
|
||||
for ( i=0; vcs[i] && (kbfd < 0); ++i ) {
|
||||
char vtpath[12];
|
||||
|
||||
sprintf(vtpath, vcs[i], curvt);
|
||||
kbfd = open(vtpath, O_RDWR);
|
||||
}
|
||||
}
|
||||
if ( kbfd < 0 ) {
|
||||
if (dbgout) fprintf (dbgout, "Couldn't open any VC\n");
|
||||
return -1;
|
||||
}
|
||||
if (dbgout) fprintf (stderr, "Current VT: %d\n", curvt);
|
||||
|
||||
if (kbfd >= 0) {
|
||||
/* Switch to the correct virtual terminal */
|
||||
if ( curvt > 0 ) {
|
||||
struct vt_stat vtstate;
|
||||
|
||||
if ( ioctl(kbfd, VT_GETSTATE, &vtstate) == 0 ) {
|
||||
oldvt = vtstate.v_active;
|
||||
}
|
||||
if ( ioctl(kbfd, VT_ACTIVATE, curvt) == 0 ) {
|
||||
if (dbgout) fprintf (dbgout, "Waiting for switch to this VT... ");
|
||||
ioctl(kbfd, VT_WAITACTIVE, curvt);
|
||||
if (dbgout) fprintf (dbgout, "done!\n");
|
||||
}
|
||||
}
|
||||
|
||||
// Set terminal input mode
|
||||
if (tcgetattr (kbfd, &old_termios) < 0) {
|
||||
if (dbgout) fprintf (dbgout, "Can't get termios\n");
|
||||
return -1;
|
||||
}
|
||||
cur_termios = old_termios;
|
||||
// cur_termios.c_iflag &= ~(ICRNL | INPCK | ISTRIP | IXON);
|
||||
// cur_termios.c_iflag |= (BRKINT);
|
||||
// cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG | IEXTEN);
|
||||
// cur_termios.c_oflag &= ~(OPOST);
|
||||
// cur_termios.c_oflag |= (ONOCR | ONLRET);
|
||||
cur_termios.c_lflag &= ~(ICANON | ECHO | ISIG);
|
||||
cur_termios.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
|
||||
cur_termios.c_cc[VMIN] = 0;
|
||||
cur_termios.c_cc[VTIME] = 0;
|
||||
|
||||
if (tcsetattr (kbfd, TCSAFLUSH, &cur_termios) < 0) {
|
||||
if (dbgout) fprintf (dbgout, "Can't set termios\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl (kbfd, KDSKBMODE, K_MEDIUMRAW) < 0) {
|
||||
if (dbgout) fprintf (dbgout, "Can't set medium-raw mode\n");
|
||||
return -1;
|
||||
}
|
||||
if (ioctl (kbfd, KDSETMODE, KD_GRAPHICS) < 0) {
|
||||
if (dbgout) fprintf (dbgout, "Can't set graphics\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// Open the framebuffer
|
||||
if ((fbfd = open ("/dev/fb0", O_RDWR)) < 0) {
|
||||
if (dbgout) fprintf (dbgout, "Can't open framebuffer\n");
|
||||
return -1;
|
||||
} else {
|
||||
struct fb_var_screeninfo vinfo;
|
||||
|
||||
if (dbgout) fprintf (dbgout, "Generation: %ld\n", generation);
|
||||
|
||||
if (generation >= 40000) {
|
||||
lcd_base = IPOD_NEW_LCD_BASE;
|
||||
} else {
|
||||
lcd_base = IPOD_OLD_LCD_BASE;
|
||||
}
|
||||
|
||||
ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo);
|
||||
close (fbfd);
|
||||
|
||||
if (lcd_base == IPOD_OLD_LCD_BASE)
|
||||
lcd_rtc = IPOD_OLD_LCD_RTC;
|
||||
else if (lcd_base == IPOD_NEW_LCD_BASE)
|
||||
lcd_rtc = IPOD_NEW_LCD_RTC;
|
||||
else {
|
||||
SDL_SetError ("Unknown iPod version");
|
||||
return -1;
|
||||
}
|
||||
|
||||
lcd_width = vinfo.xres;
|
||||
lcd_height = vinfo.yres;
|
||||
|
||||
if (dbgout) fprintf (dbgout, "LCD is %dx%d\n", lcd_width, lcd_height);
|
||||
}
|
||||
|
||||
fcntl (kbfd, F_SETFL, O_RDWR | O_NONBLOCK);
|
||||
|
||||
if ((generation >= 60000) && (generation < 70000)) {
|
||||
vformat->BitsPerPixel = 16;
|
||||
vformat->Rmask = 0xF800;
|
||||
vformat->Gmask = 0x07E0;
|
||||
vformat->Bmask = 0x001F;
|
||||
} else {
|
||||
vformat->BitsPerPixel = 8;
|
||||
vformat->Rmask = vformat->Gmask = vformat->Bmask = 0;
|
||||
}
|
||||
|
||||
initd = 1;
|
||||
if (dbgout) fprintf (dbgout, "Initialized.\n\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SDL_Rect **iPod_ListModes (_THIS, SDL_PixelFormat *format, Uint32 flags)
|
||||
{
|
||||
int width, height, fd;
|
||||
static SDL_Rect r;
|
||||
static SDL_Rect *rs[2] = { &r, 0 };
|
||||
|
||||
if ((fd = open ("/dev/fb0", O_RDWR)) < 0) {
|
||||
return 0;
|
||||
} else {
|
||||
struct fb_var_screeninfo vinfo;
|
||||
|
||||
ioctl (fbfd, FBIOGET_VSCREENINFO, &vinfo);
|
||||
close (fbfd);
|
||||
|
||||
width = vinfo.xres;
|
||||
height = vinfo.yres;
|
||||
}
|
||||
r.x = r.y = 0;
|
||||
r.w = width;
|
||||
r.h = height;
|
||||
return rs;
|
||||
}
|
||||
|
||||
|
||||
static SDL_Surface *iPod_SetVideoMode (_THIS, SDL_Surface *current, int width, int height, int bpp,
|
||||
Uint32 flags)
|
||||
{
|
||||
Uint32 Rmask, Gmask, Bmask;
|
||||
if (bpp > 8) {
|
||||
Rmask = 0xF800;
|
||||
Gmask = 0x07E0;
|
||||
Bmask = 0x001F;
|
||||
} else {
|
||||
Rmask = Gmask = Bmask = 0;
|
||||
}
|
||||
|
||||
if (this->hidden->buffer) free (this->hidden->buffer);
|
||||
this->hidden->buffer = malloc (width * height * (bpp / 8));
|
||||
if (!this->hidden->buffer) {
|
||||
SDL_SetError ("Couldn't allocate buffer for requested mode");
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset (this->hidden->buffer, 0, width * height * (bpp / 8));
|
||||
|
||||
if (!SDL_ReallocFormat (current, bpp, Rmask, Gmask, Bmask, 0)) {
|
||||
SDL_SetError ("Couldn't allocate new pixel format");
|
||||
free (this->hidden->buffer);
|
||||
this->hidden->buffer = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bpp <= 8) {
|
||||
int i, j;
|
||||
for (i = 0; i < 256; i += 4) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
current->format->palette->colors[i+j].r = 85 * j;
|
||||
current->format->palette->colors[i+j].g = 85 * j;
|
||||
current->format->palette->colors[i+j].b = 85 * j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current->flags = flags & SDL_FULLSCREEN;
|
||||
this->hidden->w = current->w = width;
|
||||
this->hidden->h = current->h = height;
|
||||
current->pitch = current->w * (bpp / 8);
|
||||
current->pixels = this->hidden->buffer;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
static int iPod_SetColors (_THIS, int firstcolor, int ncolors, SDL_Color *colors)
|
||||
{
|
||||
if (SDL_VideoSurface && SDL_VideoSurface->format && SDL_VideoSurface->format->palette) {
|
||||
int i, j;
|
||||
for (i = 0; i < 256; i += 4) {
|
||||
for (j = 0; j < 4; j++) {
|
||||
SDL_VideoSurface->format->palette->colors[i+j].r = 85 * j;
|
||||
SDL_VideoSurface->format->palette->colors[i+j].g = 85 * j;
|
||||
SDL_VideoSurface->format->palette->colors[i+j].b = 85 * j;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void iPod_VideoQuit (_THIS)
|
||||
{
|
||||
ioctl (kbfd, KDSETMODE, KD_TEXT);
|
||||
tcsetattr (kbfd, TCSAFLUSH, &old_termios);
|
||||
old_kbmode = -1;
|
||||
|
||||
if (oldvt > 0)
|
||||
ioctl (kbfd, VT_ACTIVATE, oldvt);
|
||||
|
||||
if (kbfd > 0)
|
||||
close (kbfd);
|
||||
|
||||
if (dbgout) {
|
||||
fprintf (dbgout, "<-- Ended SDL -->\n");
|
||||
fclose (dbgout);
|
||||
}
|
||||
|
||||
kbfd = -1;
|
||||
}
|
||||
|
||||
static char iPod_SC_keymap[] = {
|
||||
0, /* 0 - no key */
|
||||
'[' - 0x40, /* ESC (Ctrl+[) */
|
||||
'1', '2', '3', '4', '5', '6', '7', '8', '9',
|
||||
'-', '=',
|
||||
'\b', '\t', /* Backspace, Tab (Ctrl+H,Ctrl+I) */
|
||||
'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']',
|
||||
'\n', 0, /* Enter, Left CTRL */
|
||||
'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`',
|
||||
0, '\\', /* left shift, backslash */
|
||||
'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/',
|
||||
0, '*', 0, ' ', 0, /* right shift, KP mul, left alt, space, capslock */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* F1-10 */
|
||||
0, 0, /* numlock, scrollock */
|
||||
'7', '8', '9', '-', '4', '5', '6', '+', '1', '2', '3', '0', '.', /* numeric keypad */
|
||||
0, 0, /* padding */
|
||||
0, 0, 0, /* "less" (?), F11, F12 */
|
||||
0, 0, 0, 0, 0, 0, 0, /* padding */
|
||||
'\n', 0, '/', 0, 0, /* KP enter, Rctrl, Ctrl, KP div, PrtSc, RAlt */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, /* Break, Home, Up, PgUp, Left, Right, End, Down, PgDn */
|
||||
0, 0, /* Ins, Del */
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* padding */
|
||||
0, 0, /* RWin, LWin */
|
||||
0 /* no key */
|
||||
};
|
||||
|
||||
|
||||
static void iPod_keyboard()
|
||||
{
|
||||
unsigned char keybuf[128];
|
||||
int i, nread;
|
||||
SDL_keysym keysym;
|
||||
SDL_Event ev;
|
||||
|
||||
keysym.mod = 0;
|
||||
keysym.scancode = 0xff;
|
||||
memset (&ev, 0, sizeof(SDL_Event));
|
||||
|
||||
nread = read (kbfd, keybuf, 128);
|
||||
for (i = 0; i < nread; i++) {
|
||||
char ascii = iPod_SC_keymap[keybuf[i] & 0x7f];
|
||||
|
||||
if (dbgout) fprintf (dbgout, "Key! %02x is %c %s", keybuf[i], ascii, (keybuf[i] & 0x80)? "up" : "down");
|
||||
|
||||
keysym.sym = keysym.unicode = ascii;
|
||||
ev.type = (keybuf[i] & 0x80)? SDL_KEYUP : SDL_KEYDOWN;
|
||||
ev.key.state = 0;
|
||||
ev.key.keysym = keysym;
|
||||
SDL_PushEvent (&ev);
|
||||
}
|
||||
}
|
||||
|
||||
static void iPod_PumpEvents (_THIS)
|
||||
{
|
||||
fd_set fdset;
|
||||
int max_fd = 0;
|
||||
static struct timeval zero;
|
||||
int posted;
|
||||
|
||||
do {
|
||||
posted = 0;
|
||||
|
||||
FD_ZERO (&fdset);
|
||||
if (kbfd >= 0) {
|
||||
FD_SET (kbfd, &fdset);
|
||||
max_fd = kbfd;
|
||||
}
|
||||
if (dbgout) fprintf (dbgout, "Selecting");
|
||||
if (select (max_fd + 1, &fdset, 0, 0, &zero) > 0) {
|
||||
if (dbgout) fprintf (dbgout, " -> match!\n");
|
||||
iPod_keyboard();
|
||||
posted++;
|
||||
}
|
||||
if (dbgout) fprintf (dbgout, "\n");
|
||||
} while (posted);
|
||||
}
|
||||
|
||||
// enough space for 160x128x2
|
||||
static char ipod_scr[160 * (128/4)];
|
||||
|
||||
#define outl(datum,addr) (*(volatile unsigned long *)(addr) = (datum))
|
||||
#define inl(addr) (*(volatile unsigned long *)(addr))
|
||||
|
||||
/*** The following LCD code is taken from Linux kernel uclinux-2.4.24-uc0-ipod2,
|
||||
file arch/armnommu/mach-ipod/fb.c. A few modifications have been made. ***/
|
||||
|
||||
/* get current usec counter */
|
||||
static int M_timer_get_current(void)
|
||||
{
|
||||
return inl(lcd_rtc);
|
||||
}
|
||||
|
||||
/* check if number of useconds has past */
|
||||
static int M_timer_check(int clock_start, int usecs)
|
||||
{
|
||||
unsigned long clock;
|
||||
clock = inl(lcd_rtc);
|
||||
|
||||
if ( (clock - clock_start) >= usecs ) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for LCD with timeout */
|
||||
static void M_lcd_wait_write(void)
|
||||
{
|
||||
if ( (inl(lcd_base) & 0x8000) != 0 ) {
|
||||
int start = M_timer_get_current();
|
||||
|
||||
do {
|
||||
if ( (inl(lcd_base) & (unsigned int)0x8000) == 0 )
|
||||
break;
|
||||
} while ( M_timer_check(start, 1000) == 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* send LCD data */
|
||||
static void M_lcd_send_data(int data_lo, int data_hi)
|
||||
{
|
||||
M_lcd_wait_write();
|
||||
|
||||
outl(data_lo, lcd_base + LCD_DATA);
|
||||
|
||||
M_lcd_wait_write();
|
||||
|
||||
outl(data_hi, lcd_base + LCD_DATA);
|
||||
|
||||
}
|
||||
|
||||
/* send LCD command */
|
||||
static void
|
||||
M_lcd_prepare_cmd(int cmd)
|
||||
{
|
||||
M_lcd_wait_write();
|
||||
|
||||
outl(0x0, lcd_base + LCD_CMD);
|
||||
|
||||
M_lcd_wait_write();
|
||||
|
||||
outl(cmd, lcd_base + LCD_CMD);
|
||||
|
||||
}
|
||||
|
||||
/* send LCD command and data */
|
||||
static void M_lcd_cmd_and_data(int cmd, int data_lo, int data_hi)
|
||||
{
|
||||
M_lcd_prepare_cmd(cmd);
|
||||
|
||||
M_lcd_send_data(data_lo, data_hi);
|
||||
}
|
||||
|
||||
// Copied from uW
|
||||
static void M_update_display(int sx, int sy, int mx, int my)
|
||||
{
|
||||
int y;
|
||||
unsigned short cursor_pos;
|
||||
|
||||
sx >>= 3;
|
||||
mx >>= 3;
|
||||
|
||||
cursor_pos = sx + (sy << 5);
|
||||
|
||||
for ( y = sy; y <= my; y++ ) {
|
||||
unsigned char *img_data;
|
||||
int x;
|
||||
|
||||
/* move the cursor */
|
||||
M_lcd_cmd_and_data(0x11, cursor_pos >> 8, cursor_pos & 0xff);
|
||||
|
||||
/* setup for printing */
|
||||
M_lcd_prepare_cmd(0x12);
|
||||
|
||||
img_data = ipod_scr + (sx << 1) + (y * (lcd_width/4));
|
||||
|
||||
/* loops up to 160 times */
|
||||
for ( x = sx; x <= mx; x++ ) {
|
||||
/* display eight pixels */
|
||||
M_lcd_send_data(*(img_data + 1), *img_data);
|
||||
|
||||
img_data += 2;
|
||||
}
|
||||
|
||||
/* update cursor pos counter */
|
||||
cursor_pos += 0x20;
|
||||
}
|
||||
}
|
||||
|
||||
/* get current usec counter */
|
||||
static int C_timer_get_current(void)
|
||||
{
|
||||
return inl(0x60005010);
|
||||
}
|
||||
|
||||
/* check if number of useconds has past */
|
||||
static int C_timer_check(int clock_start, int usecs)
|
||||
{
|
||||
unsigned long clock;
|
||||
clock = inl(0x60005010);
|
||||
|
||||
if ( (clock - clock_start) >= usecs ) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* wait for LCD with timeout */
|
||||
static void C_lcd_wait_write(void)
|
||||
{
|
||||
if ((inl(0x70008A0C) & 0x80000000) != 0) {
|
||||
int start = C_timer_get_current();
|
||||
|
||||
do {
|
||||
if ((inl(0x70008A0C) & 0x80000000) == 0)
|
||||
break;
|
||||
} while (C_timer_check(start, 1000) == 0);
|
||||
}
|
||||
}
|
||||
static void C_lcd_cmd_data(int cmd, int data)
|
||||
{
|
||||
C_lcd_wait_write();
|
||||
outl(cmd | 0x80000000, 0x70008A0C);
|
||||
|
||||
C_lcd_wait_write();
|
||||
outl(data | 0x80000000, 0x70008A0C);
|
||||
}
|
||||
|
||||
static void C_update_display(int sx, int sy, int mx, int my)
|
||||
{
|
||||
int height = (my - sy) + 1;
|
||||
int width = (mx - sx) + 1;
|
||||
|
||||
char *addr = SDL_VideoSurface->pixels;
|
||||
|
||||
if (width & 1) width++;
|
||||
|
||||
/* start X and Y */
|
||||
C_lcd_cmd_data(0x12, (sy & 0xff));
|
||||
C_lcd_cmd_data(0x13, (((SDL_VideoSurface->w - 1) - sx) & 0xff));
|
||||
|
||||
/* max X and Y */
|
||||
C_lcd_cmd_data(0x15, (((sy + height) - 1) & 0xff));
|
||||
C_lcd_cmd_data(0x16, (((((SDL_VideoSurface->w - 1) - sx) - width) + 1) & 0xff));
|
||||
|
||||
addr += sx + sy * SDL_VideoSurface->pitch;
|
||||
|
||||
while (height > 0) {
|
||||
int h, x, y, pixels_to_write;
|
||||
|
||||
pixels_to_write = (width * height) * 2;
|
||||
|
||||
/* calculate how much we can do in one go */
|
||||
h = height;
|
||||
if (pixels_to_write > 64000) {
|
||||
h = (64000/2) / width;
|
||||
pixels_to_write = (width * h) * 2;
|
||||
}
|
||||
|
||||
outl(0x10000080, 0x70008A20);
|
||||
outl((pixels_to_write - 1) | 0xC0010000, 0x70008A24);
|
||||
outl(0x34000000, 0x70008A20);
|
||||
|
||||
/* for each row */
|
||||
for (x = 0; x < h; x++)
|
||||
{
|
||||
/* for each column */
|
||||
for (y = 0; y < width; y += 2) {
|
||||
unsigned two_pixels;
|
||||
|
||||
two_pixels = addr[0] | (addr[1] << 16);
|
||||
addr += 2;
|
||||
|
||||
while ((inl(0x70008A20) & 0x1000000) == 0);
|
||||
|
||||
/* output 2 pixels */
|
||||
outl(two_pixels, 0x70008B00);
|
||||
}
|
||||
|
||||
addr += SDL_VideoSurface->w - width;
|
||||
}
|
||||
|
||||
while ((inl(0x70008A20) & 0x4000000) == 0);
|
||||
|
||||
outl(0x0, 0x70008A24);
|
||||
|
||||
height = height - h;
|
||||
}
|
||||
}
|
||||
|
||||
// Should work with photo. However, I don't have one, so I'm not sure.
|
||||
static void iPod_UpdateRects (_THIS, int nrects, SDL_Rect *rects)
|
||||
{
|
||||
if (SDL_VideoSurface->format->BitsPerPixel == 16) {
|
||||
C_update_display (0, 0, lcd_width, lcd_height);
|
||||
} else {
|
||||
int i, y, x;
|
||||
for (i = 0; i < nrects; i++) {
|
||||
SDL_Rect *r = rects + i;
|
||||
if (!r) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (y = r->y; (y < r->y + r->h) && y < lcd_height; y++) {
|
||||
for (x = r->x; (x < r->x + r->w) && x < lcd_width; x++) {
|
||||
ipod_scr[y*(lcd_width/4) + x/4] &= ~(3 << (2 * (x%4)));
|
||||
ipod_scr[y*(lcd_width/4) + x/4] |=
|
||||
(((Uint8*)(SDL_VideoSurface->pixels))[ y*SDL_VideoSurface->pitch + x ] & 3) << (2 * (x%4));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
M_update_display (0, 0, lcd_width, lcd_height);
|
||||
}
|
||||
}
|
42
src/video/ipod/SDL_ipodvideo.h
Normal file
42
src/video/ipod/SDL_ipodvideo.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
SDL - Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2004 Sam Lantinga
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Sam Lantinga
|
||||
slouken@libsdl.org
|
||||
*/
|
||||
|
||||
/* iPod SDL framebuffer driver
|
||||
* Joshua Oreman
|
||||
* Main header file
|
||||
*/
|
||||
|
||||
#ifdef SAVE_RCSID
|
||||
static char rcsid =
|
||||
"@(#) $Id$";
|
||||
#endif
|
||||
|
||||
#ifndef _SDL_ipodvideo_h
|
||||
#define _SDL_ipodvideo_h
|
||||
|
||||
struct SDL_PrivateVideoData {
|
||||
char *buffer;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
Loading…
Add table
Add a link
Reference in a new issue