Android原生(Native)C开发之四:SDL移植笔记
2011-06-15 01:40
477 查看
SDL(Simple DirectMedia Layer)是一套开放源码的跨平台多媒体开发库,使用C语言写成。SDL提供了多种图像、声音、键盘等的实现,可配置性与移植性非常高,开发者可以开发出跨多个平台(Linux、Windows、Mac OS X、Symbian、Widnows Mobiel等嵌入式系统,当然也包括今天要移植的平台:Android)的应用,目前SDL多用于开发游戏、模拟器、媒体播放器等多媒体应用。
目前,SDL的稳定版本是 1.2.13,1.3还在开发中,可以通过SVN得到最新的代码,本次移植以 1.2.13为准,没有测试 1.3版的源码。请从 SDL 的官方网站下载 1.2.13 的源码,文件名为:SDL-1.2.13.zip,并解压,将得到一个 SDL-1.2.13 目录。
在Native编译SDL之前,要先装 Code Sourcery公司的arm交叉编译器,如果是用Windows操作系统,则一定要装 Cygwin(一个在windows上模拟linux的软件),因为在编译时要用到一些 linux命令,具体的步骤请参见:Port SDL/TinySDGL to android with native C,或自已在网上搜一些资料。
因为SDL是用纯C写的一套类库,所以移植性非常好,官方支持的系统有:Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX,非官方支持的有:AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS, and OS/2,而且网上也有人将SDL移植到很多其他嵌入式系统,甚至有人将SDL移植到 Moto A1200,如此强大的可移植性,其架构真是值得好好学习。
现在切入正题,如何为Android量身定做一个 SDL,下面就从视频,音频,输入事件,定时器(video,audio,events[key,mouse],timer),多线程等几个方面来分析:
1.首先讲视频方面,Android是一个定制的Linux操作系统,Linux显示要么用 X11,要么用framebuffer技术,很显然Android并没有集成 X11(也许Android的软件界面是基于X11的?!),那只有唯一的选择:framebuffer!
打开$SDL/src/video目录,可以发现SDL支持多达30多种的视频显示技术,其中包括我们想要的fbcon及directfb,directfb我没有做测试,也许显示效果会比linux自带的fbcon好,有兴趣的朋友可以试一下,成功了别忘了告诉我;
2.再来谈音频,记得一个广告词:没有声音,再好的戏也出不来!可见音频对多媒体应用的重要性。
这次用的是OSS的driver,但用的是dsp及dma的实现,但在打开Android指定的音频文件 /dev/eac 时有误,所以音频这一块只是能编译通过,不能正常运行,正在考虑用ALSA (Advanced Linux Sound Architecture) 替代;
关于OSS大家可以参看IBM的文章: OSS--跨平台的音频接口简介,写得比较详细。
3.输入事件(键盘,鼠标)中的键盘事件不需要任何更改,就能正常处理,用的设备文件是 /dev/tty0,
但鼠标事件却不能正常处理,加上DEBUG_MOUSE发现用的是PS2的鼠标,但其实Android用的不是PS2的鼠标,用的应该是触摸屏(TouchScreen)鼠标,设备文件是 /dev/input/event0,详情请参见本人的blog: Android原生(Native)C开发之三:鼠标事件篇(捕鼠记),经过改动后,基本能实现鼠标的处理;
4.定时器用的是unix的实现;
5.多线程用的是pthread的实现,unix系统都是用pthread来实现多线程的,在 ln demo时别忘了加 -lpthread;
6.加载动态库用的是unix 的 dl库,同样,在ln demo时别忘了加 -ldl。
SDL提供了一个最小化的Makefile:Makefile.minimal,所有的实现都是 dummy,就是一个空的实现,编译能通过,但运行时什么都不能做,根据上面的分析,将 Makefile.minimal 的内容改成如下:
最后将$SDL/include/SDL_config_minimal.h的内容改成如下:
注意黑体部分,其实就是打开一些宏定义,将SDL的实现一一打开。
改完了这些以后,还需要改一些代码,主要是video方面的,因为Android Linux的framebuffer设备文件与标准Linux不同,Linux的fb设备文件一般是 /dev/fb0,但Android的设备文件是 /dev/graphics/fb0,打开 $SDL/src/video/fbcon/SDL_fbvideo.c,将191、499行的 "/dev/fb0" 替换成 "/dev/graphics/fb0",保存即可。
再修改 $SDL/src/thread/pthread/SDL_sysmutex.c,将第30行改成: #define FAKE_RECURSIVE_MUTEX 1,就是在后面加一个“1”子,这可能是编译器的一个bug,define默认应该就是“1”的。
现在可以开始编译libSDL.a了,在cygwin或Linux下,进入SDL目录,输入:
make -f Makefile.minimal
视情况面定,一般几分钟后能顺利编译 Android版的 SDL,编译成功后,就需要编译几个SDL的test demo来测试一下 SDL的性能。
进入 test目录,复制 Makefile.in 文件,并改名为 Makefile,将前面一点内容改为:
并将所有的 @MATHLIB@ 替换成 $(MATHLIB),保存后,先编译一个testsprite demo,在命令行输入:
make testsprite
编译成功后,启动Android模拟器,将编译出来的testsprite及icon.bmp上传至一个目录,如 /dev/sample,命令如下:
最后进入 android 的shell: adb shell,再进入 /dev/sample目录,执行testsprite demo即可:
可以根据模拟器的设置调整 width 及 height,因为程序默认的是 640x480的,初始化时会失败,如果一切正常的话,模拟器就会出现很多***的笑脸!按任意键退出,在本人机器上能达到 60 FPS左右,效果图如下:
其他的 demo有兴趣的朋友可以自己编译测试。
http://blog.sina.com.cn/s/blog_4a0a39c30100b1n1.html
目前,SDL的稳定版本是 1.2.13,1.3还在开发中,可以通过SVN得到最新的代码,本次移植以 1.2.13为准,没有测试 1.3版的源码。请从 SDL 的官方网站下载 1.2.13 的源码,文件名为:SDL-1.2.13.zip,并解压,将得到一个 SDL-1.2.13 目录。
在Native编译SDL之前,要先装 Code Sourcery公司的arm交叉编译器,如果是用Windows操作系统,则一定要装 Cygwin(一个在windows上模拟linux的软件),因为在编译时要用到一些 linux命令,具体的步骤请参见:Port SDL/TinySDGL to android with native C,或自已在网上搜一些资料。
因为SDL是用纯C写的一套类库,所以移植性非常好,官方支持的系统有:Linux, Windows, Windows CE, BeOS, MacOS, Mac OS X, FreeBSD, NetBSD, OpenBSD, BSD/OS, Solaris, IRIX, and QNX,非官方支持的有:AmigaOS, Dreamcast, Atari, AIX, OSF/Tru64, RISC OS, SymbianOS, and OS/2,而且网上也有人将SDL移植到很多其他嵌入式系统,甚至有人将SDL移植到 Moto A1200,如此强大的可移植性,其架构真是值得好好学习。
现在切入正题,如何为Android量身定做一个 SDL,下面就从视频,音频,输入事件,定时器(video,audio,events[key,mouse],timer),多线程等几个方面来分析:
1.首先讲视频方面,Android是一个定制的Linux操作系统,Linux显示要么用 X11,要么用framebuffer技术,很显然Android并没有集成 X11(也许Android的软件界面是基于X11的?!),那只有唯一的选择:framebuffer!
打开$SDL/src/video目录,可以发现SDL支持多达30多种的视频显示技术,其中包括我们想要的fbcon及directfb,directfb我没有做测试,也许显示效果会比linux自带的fbcon好,有兴趣的朋友可以试一下,成功了别忘了告诉我;
2.再来谈音频,记得一个广告词:没有声音,再好的戏也出不来!可见音频对多媒体应用的重要性。
这次用的是OSS的driver,但用的是dsp及dma的实现,但在打开Android指定的音频文件 /dev/eac 时有误,所以音频这一块只是能编译通过,不能正常运行,正在考虑用ALSA (Advanced Linux Sound Architecture) 替代;
关于OSS大家可以参看IBM的文章: OSS--跨平台的音频接口简介,写得比较详细。
3.输入事件(键盘,鼠标)中的键盘事件不需要任何更改,就能正常处理,用的设备文件是 /dev/tty0,
但鼠标事件却不能正常处理,加上DEBUG_MOUSE发现用的是PS2的鼠标,但其实Android用的不是PS2的鼠标,用的应该是触摸屏(TouchScreen)鼠标,设备文件是 /dev/input/event0,详情请参见本人的blog: Android原生(Native)C开发之三:鼠标事件篇(捕鼠记),经过改动后,基本能实现鼠标的处理;
4.定时器用的是unix的实现;
5.多线程用的是pthread的实现,unix系统都是用pthread来实现多线程的,在 ln demo时别忘了加 -lpthread;
6.加载动态库用的是unix 的 dl库,同样,在ln demo时别忘了加 -ldl。
SDL提供了一个最小化的Makefile:Makefile.minimal,所有的实现都是 dummy,就是一个空的实现,编译能通过,但运行时什么都不能做,根据上面的分析,将 Makefile.minimal 的内容改成如下:
# Makefile to build the SDL library INCLUDE = -I./include CFLAGS = -g -s -O2 $(INCLUDE) CC = arm-none-linux-gnueabi-gcc AR = arm-none-linux-gnueabi-ar RANLIB = arm-none-linux-gnueabi-ranlib CONFIG_H = include/SDL_config.h TARGET = libSDL.a SOURCES = / src/*.c / src/audio/*.c / src/cdrom/*.c / src/cpuinfo/*.c / src/events/*.c / src/file/*.c / src/joystick/*.c / src/stdlib/*.c / src/thread/*.c / src/timer/*.c / src/video/*.c / src/audio/dsp/*.c / src/audio/dma/*.c / src/video/fbcon/*.c / src/joystick/dummy/*.c / src/cdrom/dummy/*.c / src/thread/pthread/*.c / src/timer/unix/*.c / src/loadso/dlopen/*.c / OBJECTS = $(shell echo $(SOURCES) | sed -e 's,/.c,/.o,g') all: $(TARGET) $(TARGET): $(CONFIG_H) $(OBJECTS) $(AR) crv $@ $^ $(RANLIB) $@ $(CONFIG_H): cp $(CONFIG_H).default $(CONFIG_H) clean: rm -f $(TARGET) $(OBJECTS) |
#ifndef _SDL_config_minimal_h #define _SDL_config_minimal_h #include "SDL_platform.h" #include <stdarg.h> typedef signed char int8_t; typedef unsigned char uint8_t; typedef signed short int16_t; typedef unsigned short uint16_t; typedef signed int int32_t; typedef unsigned int uint32_t; typedef unsigned int size_t; //typedef unsigned long uintptr_t; #define H***E_LIBC 1 #ifdef H***E_LIBC #define H***E_ALLOCA_H 1 #define H***E_SYS_TYPES_H 1 #define H***E_STDIO_H 1 #define STDC_HEADERS 1 #define H***E_STDLIB_H 1 #define H***E_STDARG_H 1 #define H***E_MALLOC_H 1 #define H***E_MEMORY_H 1 //#define H***E_STRING_H 1 //#define H***E_STRINGS_H 1 #define H***E_INTTYPES_H 1 #define H***E_STDINT_H 1 #define H***E_CTYPE_H 1 #define H***E_MATH_H 1 //#define H***E_ICONV_H 1 #define H***E_SIGNAL_H 1 #define H***E_ALTIVEC_H 1 #define H***E_MALLOC 1 #define H***E_CALLOC 1 #define H***E_REALLOC 1 #define H***E_FREE 1 #define H***E_ALLOCA 1 #define H***E_GETENV 1 #define H***E_PUTENV 1 #define H***E_UNSETENV 1 #define H***E_QSORT 1 #define H***E_ABS 1 //#define H***E_BCOPY 1 //#define H***E_MEMSET 1 //#define H***E_MEMCPY 1 //#define H***E_MEMMOVE 1 //#define H***E_MEMCMP 1 //#define H***E_STRLEN 1 //#define H***E_STRLCPY 1 //#define H***E_STRLCAT 1 //#define H***E_STRDUP 1 #define H***E__STRREV 1 #define H***E__STRUPR 1 #define H***E__STRLWR 1 //#define H***E_INDEX 1 #define H***E_RINDEX 1 //#define H***E_STRCHR 1 #define H***E_STRRCHR 1 #define H***E_STRSTR 1 #define H***E_ITOA 1 #define H***E__LTOA 1 #define H***E__UITOA 1 #define H***E__ULTOA 1 #define H***E_STRTOL 1 #define H***E_STRTOUL 1 #define H***E__I64TOA 1 #define H***E__UI64TOA 1 #define H***E_STRTOLL 1 #define H***E_STRTOULL 1 #define H***E_STRTOD 1 #define H***E_ATOI 1 #define H***E_ATOF 1 #define H***E_STRCMP 1 #define H***E_STRNCMP 1 #define H***E__STRICMP 1 #define H***E_STRCASECMP 1 #define H***E__STRNICMP 1 #define H***E_STRNCASECMP 1 #define H***E_SSCANF 1 #define H***E_SNPRINTF 1 #define H***E_VSNPRINTF 1 //#define H***E_ICONV #define H***E_SIGACTION 1 #define H***E_SETJMP 1 #define H***E_NANOSLEEP 1 //#define H***E_CLOCK_GETTIME 1 #define H***E_DLVSYM 1 #define H***E_GETPAGESIZE 1 #define H***E_MPROTECT 1 #else #include <stdarg.h> #endif //#define H***E_STDIO_H 1 //#define H***E_STDINT_H 1 //#define SDL_INPUT_TSLIB 1 //touch screen input #define SDL_AUDIO_DRIVER_OSS 1 // SDL_AUDIO_DRIVER_DUMMY #define SDL_CDROM_DISABLED 1 #define SDL_JOYSTICK_DISABLED 1 #define SDL_LOADSO_DLOPEN 1 //SDL_LOADSO_DISABLED 1 //#undef #define SDL_THREAD_PTHREAD 1 //SDL_THREADS_DISABLED //SDL_TIMERS_DISABLED #define SDL_TIMER_UNIX 1 // SDL_VIDEO_DRIVER_DUMMY #define SDL_VIDEO_DRIVER_FBCON 1 #endif |
改完了这些以后,还需要改一些代码,主要是video方面的,因为Android Linux的framebuffer设备文件与标准Linux不同,Linux的fb设备文件一般是 /dev/fb0,但Android的设备文件是 /dev/graphics/fb0,打开 $SDL/src/video/fbcon/SDL_fbvideo.c,将191、499行的 "/dev/fb0" 替换成 "/dev/graphics/fb0",保存即可。
再修改 $SDL/src/thread/pthread/SDL_sysmutex.c,将第30行改成: #define FAKE_RECURSIVE_MUTEX 1,就是在后面加一个“1”子,这可能是编译器的一个bug,define默认应该就是“1”的。
现在可以开始编译libSDL.a了,在cygwin或Linux下,进入SDL目录,输入:
make -f Makefile.minimal
视情况面定,一般几分钟后能顺利编译 Android版的 SDL,编译成功后,就需要编译几个SDL的test demo来测试一下 SDL的性能。
进入 test目录,复制 Makefile.in 文件,并改名为 Makefile,将前面一点内容改为:
# Makefile to build the SDL tests srcdir = . INCLUDE = -I../include CC = arm-none-linux-gnueabi-gcc EXE = CFLAGS = -g -s -O2 $(INCLUDE) -static LIBS = -L.. -lSDL -lpthread MATHLIB = -lm |
make testsprite
编译成功后,启动Android模拟器,将编译出来的testsprite及icon.bmp上传至一个目录,如 /dev/sample,命令如下:
adb push testspirte /dev/sample/testsprite adb push icon.bmp /dev/sample/icon.bmp |
#cd /dev/sample #chmod 755 testsprite #./testsprite -width 320 -height 480 -bpp 32 |
其他的 demo有兴趣的朋友可以自己编译测试。
http://blog.sina.com.cn/s/blog_4a0a39c30100b1n1.html
相关文章推荐
- Android原生(Native)C开发之四:SDL移植笔记
- Android原生(Native)C开发之四:SDL移植笔记
- Android原生(Native)C开发之四:SDL移植笔记
- Android原生(Native)C开发之五:zlib移植笔记
- Android原生(Native)C开发之七:libjpeg移植笔记
- 【React Native开发】React Native移植原生Android项目(4)
- 【React Native开发】React Native移植原生Android项目(Mac用)
- 【React Native开发】React Native移植原生Android项目(4)
- Android 原生开发、H5、React-Native使用利弊和场景技术分享
- [置顶] React-Native开发之原生模块封装(Android)升级版
- XX程序媛学习笔记--Cordova(PhoneGap)Android Native混合开发值传递
- React Native移植原生Android
- React Native 原生模块开发笔记 (Android/iOS)
- 从Native到Web(六), emscripten学习笔记: SDL游戏移植尝试
- 零基础学习SDL开发之移植SDL2.0到Android
- 转载:&nbsp;Android原生(Native)C开发之…
- Android原生(Native)C开发之七:libjpeg移植笔记
- Android原生(Native)C开发:编译选项小结
- Android Native 代码NDK开发学习笔记
- 2.android 原生应用和React native 结合开发.环境搭建