Commit a64fc29c authored by Sam Lantinga's avatar Sam Lantinga

Merged Paul's Google Summer of Code work from SDL-gsoc2010_android

parents 238acbd5 0d3fdb86
# Makefile to build the SDL library
include ./android/config.cfg #get ANDROID_NDK
TOOLS_PATH=$(ANDROID_NDK)/build/prebuilt/linux-x86/arm-eabi-4.2.1/bin
ANDROID_INCLUDES = -I$(ANDROID_NDK)/build/platforms/android-4/common/include \
-I$(ANDROID_NDK)/build/platforms/android-4/arch-arm/usr/include
INCLUDE = -I./include
CFLAGS = -g -O2 $(INCLUDE) $(ANDROID_INCLUDES) -DANDROID -DANDROID_NDK -static
AR = $(TOOLS_PATH)/arm-eabi-ar
RANLIB = $(TOOLS_PATH)/arm-eabi-ranlib
CC = $(TOOLS_PATH)/arm-eabi-gcc
CONFIG_H = include/SDL_config.h
TARGET = libSDL.a
SOURCES = \
src/*.c \
src/audio/*.c \
src/cpuinfo/*.c \
src/events/*.c \
src/file/*.c \
src/joystick/*.c \
src/haptic/*.c \
src/stdlib/*.c \
src/thread/*.c \
src/timer/*.c \
src/video/*.c \
src/power/*.c \
src/audio/android/*.c \
src/video/android/*.c \
src/joystick/android/*.c \
src/haptic/dummy/*.c \
src/atomic/dummy/*.c \
src/thread/pthread/*.c \
src/timer/unix/*.c \
src/loadso/dummy/*.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)
================================================================================
Simple DirectMedia Layer for Android
================================================================================
Requirements: Android NDK r4 or later
================================================================================
How the port works
================================================================================
- Android applications are Java-based, optionally with parts written in C
- As SDL apps are C-based, we use a small Java shim that uses JNI to talk to
the SDL library
- This means that your application C code must be placed inside an android
Java project, along with some C support code that communicates with Java
- This eventually produces a standard Android .apk package
================================================================================
Building an app
================================================================================
Instructions:
1. Edit android/config.cfg to point to the location of the NDK
2. Run 'make -f Makefile.android'. If all goes well, libsdl.a should be created
3. Place your application source files in android/project/jni
4. Edit the Android.mk to include your source files
5. Run 'ndk-build' (a script provided by the NDK). This compiles the C source
6. Run 'ant' in android/testproject. This compiles the .java and eventually
creates a .apk with the C source embedded
7. 'ant install' will push the apk to the device or emulator (if connected)
================================================================================
Known issues
================================================================================
- SDL audio (although it's mostly written, just not working properly yet)
- TODO. I'm sure there's a bunch more stuff I haven't thought of
ANDROID_NDK=/home/paul/Projects/gsoc/sdk/android-ndk-r4
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.libsdl.app"
android:versionCode="1"
android:versionName="1.0">
<application android:label="@string/app_name" android:icon="@drawable/icon">
<activity android:name="SDLActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
# This file is used to override default values used by the Ant build system.
#
# This file must be checked in Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
<?xml version="1.0" encoding="UTF-8"?>
<project name="SDLApp" default="help">
<!-- The local.properties file is created and updated by the 'android' tool.
It contains the path to the SDK. It should *NOT* be checked in in Version
Control Systems. -->
<property file="local.properties" />
<!-- The build.properties file can be created by you and is never touched
by the 'android' tool. This is the place to change some of the default property values
used by the Ant rules.
Here are some properties you may want to change/update:
application.package
the name of your application package as defined in the manifest. Used by the
'uninstall' rule.
source.dir
the name of the source directory. Default is 'src'.
out.dir
the name of the output directory. Default is 'bin'.
Properties related to the SDK location or the project target should be updated
using the 'android' tool with the 'update' action.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems.
-->
<property file="build.properties" />
<!-- The default.properties file is created and updated by the 'android' tool, as well
as ADT.
This file is an integral part of the build system for your application and
should be checked in in Version Control Systems. -->
<property file="default.properties" />
<!-- Custom Android task to deal with the project target, and import the proper rules.
This requires ant 1.6.0 or above. -->
<path id="android.antlibs">
<pathelement path="${sdk.dir}/tools/lib/anttasks.jar" />
<pathelement path="${sdk.dir}/tools/lib/sdklib.jar" />
<pathelement path="${sdk.dir}/tools/lib/androidprefs.jar" />
<pathelement path="${sdk.dir}/tools/lib/apkbuilder.jar" />
<pathelement path="${sdk.dir}/tools/lib/jarutils.jar" />
</path>
<taskdef name="setup"
classname="com.android.ant.SetupTask"
classpathref="android.antlibs" />
<!-- Execute the Android Setup task that will setup some properties specific to the target,
and import the build rules files.
The rules file is imported from
<SDK>/platforms/<target_platform>/templates/android_rules.xml
To customize some build steps for your project:
- copy the content of the main node <project> from android_rules.xml
- paste it in this build.xml below the <setup /> task.
- disable the import by changing the setup task below to <setup import="false" />
This will ensure that the properties are setup correctly but that your customized
build steps are used.
-->
<setup />
</project>
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must be checked in Version Control Systems.
#
# To customize properties used by the Ant build system use,
# "build.properties", and override values to adapt the script to your
# project structure.
# Project target.
target=android-7
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sdlapp
SDL := ../../../
LOCAL_CFLAGS := -DANDROID_NDK \
-DDISABLE_IMPORTGL \
-I$(SDL)/include
LOCAL_SRC_FILES := \
android-support.cpp \
lesson05.c \
LOCAL_LDLIBS := -lGLESv1_CM -ldl -llog -lSDL -lgcc -L$(SDL)
include $(BUILD_SHARED_LIBRARY)
/*******************************************************************************
This file links the Java side of Android with libsdl
*******************************************************************************/
#include <jni.h>
#include <sys/time.h>
#include <time.h>
#include <android/log.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <pthread.h>
#define DEBUG
/*******************************************************************************
Globals
*******************************************************************************/
static long _getTime(void){
struct timeval now;
gettimeofday(&now, NULL);
return (long)(now.tv_sec*1000 + now.tv_usec/1000);
}
JNIEnv* mEnv = NULL;
JNIEnv* mAudioThreadEnv = NULL; //See the note below for why this is necessary
JavaVM* mVM = NULL;
//Main activity
jclass mActivityInstance;
//method signatures
jmethodID midCreateGLContext;
jmethodID midFlipBuffers;
jmethodID midEnableFeature;
jmethodID midUpdateAudio;
extern "C" int SDL_main();
extern "C" int Android_OnKeyDown(int keycode);
extern "C" int Android_OnKeyUp(int keycode);
extern "C" void Android_SetScreenResolution(int width, int height);
extern "C" void Android_OnResize(int width, int height, int format);
extern "C" int SDL_SendQuit();
extern "C" void Android_EnableFeature(int featureid, bool enabled);
//If we're not the active app, don't try to render
bool bRenderingEnabled = false;
//Feature IDs
static const int FEATURE_AUDIO = 1;
static const int FEATURE_ACCEL = 2;
//Accelerometer data storage
float fLastAccelerometer[3];
/*******************************************************************************
Functions called by JNI
*******************************************************************************/
//Library init
extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved){
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
return result;
}
mEnv = env;
__android_log_print(ANDROID_LOG_INFO, "SDL", "JNI: OnLoad");
jclass cls = mEnv->FindClass ("org/libsdl/app/SDLActivity");
mActivityInstance = cls;
midCreateGLContext = mEnv->GetStaticMethodID(cls,"createGLContext","()V");
midFlipBuffers = mEnv->GetStaticMethodID(cls,"flipBuffers","()V");
midEnableFeature = mEnv->GetStaticMethodID(cls,"enableFeature","(II)V");
midUpdateAudio = mEnv->GetStaticMethodID(cls,"updateAudio","([B)V");
if(!midCreateGLContext || !midFlipBuffers || !midEnableFeature ||
!midUpdateAudio){
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Bad mids\n");
}else{
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Good mids\n");
#endif
}
return JNI_VERSION_1_4;
}
//Start up the SDL app
extern "C" void Java_org_libsdl_app_SDLActivity_nativeInit( JNIEnv* env,
jobject obj ){
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native Init");
mEnv = env;
bRenderingEnabled = true;
Android_EnableFeature(FEATURE_ACCEL, true);
SDL_main();
}
//Keydown
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(JNIEnv* env,
jobject obj, jint keycode){
int r = Android_OnKeyDown(keycode);
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key down %d, %d\n", keycode, r);
#endif
}
//Keyup
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(JNIEnv* env,
jobject obj, jint keycode){
int r = Android_OnKeyUp(keycode);
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native key up %d, %d\n", keycode, r);
#endif
}
//Touch
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeTouch(JNIEnv* env,
jobject obj, jint action, jfloat x, jfloat y, jfloat p){
#ifdef DEBUG
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: native touch event %d @ %f/%f, pressure %f\n",
action, x, y, p);
#endif
//TODO: Pass this off to the SDL multitouch stuff
}
//Quit
extern "C" void Java_org_libsdl_app_SDLActivity_nativeQuit( JNIEnv* env,
jobject obj ){
//Stop rendering as we're no longer in the foreground
bRenderingEnabled = false;
//Inject a SDL_QUIT event
int r = SDL_SendQuit();
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Native quit %d", r);
}
//Screen size
extern "C" void Java_org_libsdl_app_SDLActivity_nativeSetScreenSize(
JNIEnv* env, jobject obj, jint width, jint height){
__android_log_print(ANDROID_LOG_INFO, "SDL",
"SDL: Set screen size on init: %d/%d\n", width, height);
Android_SetScreenResolution(width, height);
}
//Resize
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeResize(
JNIEnv* env, jobject obj, jint width,
jint height, jint format){
Android_OnResize(width, height, format);
}
extern "C" void Java_org_libsdl_app_SDLActivity_onNativeAccel(
JNIEnv* env, jobject obj,
jfloat x, jfloat y, jfloat z){
fLastAccelerometer[0] = x;
fLastAccelerometer[1] = y;
fLastAccelerometer[2] = z;
}
/*******************************************************************************
Functions called by SDL into Java
*******************************************************************************/
extern "C" void Android_CreateContext(){
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: sdl_create_context()\n");
bRenderingEnabled = true;
mEnv->CallStaticVoidMethod(mActivityInstance, midCreateGLContext );
}
extern "C" void Android_Render(){
if(!bRenderingEnabled){
return;
}
//When we get here, we've accumulated a full frame
mEnv->CallStaticVoidMethod(mActivityInstance, midFlipBuffers );
}
extern "C" void Android_EnableFeature(int featureid, bool enabled){
mEnv->CallStaticVoidMethod(mActivityInstance, midEnableFeature,
featureid, (int)enabled);
}
extern "C" void Android_UpdateAudioBuffer(unsigned char *buf, int len){
//Annoyingly we can't just call into Java from any thread. Because the audio
//callback is dispatched from the SDL audio thread (that wasn't made from
//java, we have to do some magic here to let the JVM know about the thread.
//Because everything it touches on the Java side is static anyway, it's
//not a big deal, just annoying.
if(!mAudioThreadEnv){
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: Need to set up audio thread env\n");
mVM->AttachCurrentThread(&mAudioThreadEnv, NULL);
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: ok\n");
}
jbyteArray arr = mAudioThreadEnv->NewByteArray(len);
//blah. We probably should rework this so we avoid the copy.
mAudioThreadEnv->SetByteArrayRegion(arr, 0, len, (jbyte *)buf);
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: copied\n");
mAudioThreadEnv->CallStaticVoidMethod( mActivityInstance,
midUpdateAudio, arr );
__android_log_print(ANDROID_LOG_INFO, "SDL", "SDL: invoked\n");
}
/*
* This code was created by Jeff Molofee '99
* (ported to Linux/SDL by Ti Leggett '01)
*
* If you've found this code useful, please let me know.
*
* Visit Jeff at http://nehe.gamedev.net/
*
* or for port-specific comments, questions, bugreports etc.
* email to leggett@eecs.tulane.edu
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <signal.h>
#include <android/log.h>
#ifdef ANDROID
#include <GLES/gl.h>
#else
#include <GL/gl.h>
#include <GL/glu.h>
#endif
#include "SDL.h"
/* screen width, height, and bit depth */
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 430
#define SCREEN_BPP 16
/* Define our booleans */
#define TRUE 1
#define FALSE 0
/* This is our SDL surface */
SDL_Surface *surface;
int rotation = 0;
/**************************************
gluperspective implementation
**************************************/
void gluPerspective(double fovy, double aspect, double zNear, double zFar){
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
double xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
glFrustumf(xmin, xmax, ymin, ymax, zNear, zFar);
}
/**************************************
glulookat implementation
**************************************/
void gluLookAt(GLfloat eyex, GLfloat eyey, GLfloat eyez,
GLfloat centerx, GLfloat centery, GLfloat centerz,
GLfloat upx, GLfloat upy, GLfloat upz)
{
GLfloat m[16];
GLfloat x[3], y[3], z[3];
GLfloat mag;
/* Make rotation matrix */
/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) { /* mpichler, 19950515 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;
/* X vector = Y cross Z */
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];
/* Recompute Y = Z cross X */
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];
/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#define M(row,col) m[col*4+row]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);
/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);
}
/* function to release/destroy our resources and restoring the old desktop */
void Quit( int returnCode )
{
/* clean up the window */
SDL_Quit( );
/* and exit appropriately */
exit( returnCode );
}
/* function to reset our viewport after a window resize */
int resizeWindow( int width, int height )
{
/* Height / width ration */
GLfloat ratio;
/* Protect against a divide by zero */
if ( height == 0 )
height = 1;
ratio = ( GLfloat )width / ( GLfloat )height;
/* Setup our viewport. */
glViewport( 0, 0, ( GLsizei )width, ( GLsizei )height );
/* change to the projection matrix and set our viewing volume. */
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
/* Set our perspective */
gluPerspective( 45.0f, ratio, 0.1f, 100.0f );
/* Make sure we're chaning the model view and not the projection */
glMatrixMode( GL_MODELVIEW );
/* Reset The View */
glLoadIdentity( );
return( TRUE );
}
/* function to handle key press events */
void handleKeyPress( SDL_keysym *keysym )
{
switch ( keysym->sym )
{
case SDLK_ESCAPE:
/* ESC key was pressed */
Quit( 0 );
break;
case SDLK_F1:
/* F1 key was pressed
* this toggles fullscreen mode
*/
SDL_WM_ToggleFullScreen( surface );
break;
case SDLK_LEFT:
rotation -= 30;
break;
case SDLK_RIGHT:
rotation += 30;
break;
default:
break;
}
__android_log_print(ANDROID_LOG_INFO, "SDL","Keycode: %d, %d, %d\n", keysym->sym, SDLK_LEFT, SDLK_RIGHT);
return;
}
/* general OpenGL initialization function */
int initGL( GLvoid )
{
/* Enable smooth shading */
glShadeModel( GL_SMOOTH );
/* Set the background black */
glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
/* Depth buffer setup */
//glClearDepth( 1.0f );
/* Enables Depth Testing */
glEnable( GL_DEPTH_TEST );
/* The Type Of Depth Test To Do */
glDepthFunc( GL_LEQUAL );
/* Really Nice Perspective Calculations */
glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
return( TRUE );
}
/* Here goes our drawing code */
int drawGLScene( GLvoid )
{
static int Frames = 0;
static int T0 = 0;
glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
glClearColorx(0,0,0,255);
glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, (float)SCREEN_WIDTH / SCREEN_HEIGHT, 0.5f, 150);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
//Camera
gluLookAt(0,0,5, 0,0,0, 0,1,0);
//Draw a triangle
//glRotatef(iRot, 0, 1, 0);
glRotatef( rotation, 0.0f, 1.0f, 0.0f );
glEnableClientState (GL_VERTEX_ARRAY);
glEnableClientState (GL_COLOR_ARRAY);
/* Rotate The Triangle On The Y axis ( NEW ) */
//glRotatef( Frames % 360, 0.0f, 1.0f, 0.0f );
/* GLES variant of drawing a triangle */
const GLfloat triVertices[][9] = {
{ /* Front Triangle */
0.0f, 1.0f, 0.0f, /* Top Of Triangle */
-1.0f, -1.0f, 1.0f, /* Left Of Triangle */
1.0f, -1.0f, 1.0f /* Right Of Triangle */
}, { /* Right Triangle */
0.0f, 1.0f, 0.0f, /* Top Of Triangle */
1.0f, -1.0f, 1.0f, /* Left Of Triangle */
1.0f, -1.0f, -1.0f /* Right Of Triangle */
}, { /* Back Triangle */
0.0f, 1.0f, 0.0f, /* Top Of Triangle */
1.0f, -1.0f, -1.0f, /* Left Of Triangle */
-1.0f, -1.0f, -1.0f /* Right Of Triangle */
}, { /* Left Triangle */
0.0f, 1.0f, 0.0f, /* Top Of Triangle */
-1.0f, -1.0f, -1.0f, /* Left Of Triangle */
-1.0f, -1.0f, 1.0f /* Right Of Triangle */
}
};
/* unlike GL, GLES does not support RGB. We have to use RGBA instead */
const GLfloat triColors[][12] = {
{ /* Front triangle */
1.0f, 0.0f, 0.0f, 1.0f, /* Red */
0.0f, 1.0f, 0.0f, 1.0f, /* Green */
0.0f, 0.0f, 1.0f, 1.0f /* Blue */
}, { /* Right triangle */
1.0f, 0.0f, 0.0f, 1.0f, /* Red */
0.0f, 0.0f, 1.0f, 1.0f, /* Blue */
0.0f, 1.0f, 0.0f, 1.0f /* Green */
}, { /* Back triangle */
1.0f, 0.0f, 0.0f, 1.0f, /* Red */
0.0f, 1.0f, 0.0f, 1.0f, /* Green */
0.0f, 0.0f, 1.0f, 1.0f /* Blue */
}, { /* Left triangle */
1.0f, 0.0f, 0.0f, 1.0f, /* Red */
0.0f, 0.0f, 1.0f, 1.0f, /* Blue */
0.0f, 1.0f, 0.0f, 1.0f /* Green */
}
};
glEnableClientState(GL_COLOR_ARRAY);
int tri=0;
/* Loop through all Triangles */
for(tri=0;tri<sizeof(triVertices)/(9*sizeof(GLfloat));tri++)
{
glVertexPointer(3, GL_FLOAT, 0, triVertices[tri]);
glColorPointer(4, GL_FLOAT, 0, triColors[tri]);
glDrawArrays(GL_TRIANGLE_STRIP, 0, 3);
}
//__android_log_print(ANDROID_LOG_INFO, "SDL", "render %d", Frames++);
/* Draw it to the screen */
SDL_GL_SwapBuffers( );
/* Gather our frames per second */
Frames++;
{
GLint t = SDL_GetTicks();
if (t - T0 >= 5000) {
GLfloat seconds = (t - T0) / 1000.0;
GLfloat fps = Frames / seconds;
__android_log_print(ANDROID_LOG_INFO, "SDL","%d frames in %g seconds = %g FPS\n", Frames, seconds, fps);
T0 = t;
Frames = 0;
}
}
rotation++;
return( TRUE );
}
struct
{
SDL_AudioSpec spec;
Uint8 *sound; /* Pointer to wave data */
Uint32 soundlen; /* Length of wave data */
int soundpos; /* Current play position */
} wave;
void SDLCALL
fillerup(void *unused, Uint8 * stream, int len)
{
__android_log_print(ANDROID_LOG_INFO, "SDL","FILLERUP\n");
Uint8 *waveptr;
int waveleft;
/* Set up the pointers */
waveptr = wave.sound + wave.soundpos;
waveleft = wave.soundlen - wave.soundpos;
/* Go! */
while (waveleft <= len) {
SDL_memcpy(stream, waveptr, waveleft);
stream += waveleft;
len -= waveleft;
waveptr = wave.sound;
waveleft = wave.soundlen;
wave.soundpos = 0;
}
SDL_memcpy(stream, waveptr, len);
wave.soundpos += len;
}
void testAudio(){
const char *file = "/sdcard/sample.wav";
/* Load the SDL library */
if (SDL_Init(SDL_INIT_AUDIO) < 0) {
__android_log_print(ANDROID_LOG_INFO, "SDL","Couldn't initialize SDL Audio: %s\n", SDL_GetError());
return;
}else{
__android_log_print(ANDROID_LOG_INFO, "SDL","Init audio ok\n");
}
/* Load the wave file into memory */
if (SDL_LoadWAV(file, &wave.spec, &wave.sound, &wave.soundlen) == NULL) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't load %s: %s\n", file, SDL_GetError());
return;
}
wave.spec.callback = fillerup;
__android_log_print(ANDROID_LOG_INFO, "SDL","Loaded: %d\n", wave.soundlen);
/* Initialize fillerup() variables */
if (SDL_OpenAudio(&wave.spec, NULL) < 0) {
__android_log_print(ANDROID_LOG_INFO, "SDL", "Couldn't open audio: %s\n", SDL_GetError());
SDL_FreeWAV(wave.sound);
return;
}
__android_log_print(ANDROID_LOG_INFO, "SDL","Using audio driver: %s\n", SDL_GetCurrentAudioDriver());
/* Let the audio run */
SDL_PauseAudio(0);
__android_log_print(ANDROID_LOG_INFO, "SDL","Playing\n");
while (SDL_GetAudioStatus() == SDL_AUDIO_PLAYING){
//__android_log_print(ANDROID_LOG_INFO, "SDL","Still playing\n");
SDL_Delay(100);
}
__android_log_print(ANDROID_LOG_INFO, "SDL","Closing down\n");
/* Clean up on signal */
SDL_CloseAudio();
SDL_FreeWAV(wave.sound);
}
int SDL_main( int argc, char **argv )
{
__android_log_print(ANDROID_LOG_INFO, "SDL","entry\n");
/* Flags to pass to SDL_SetVideoMode */
int videoFlags;
/* main loop variable */
int done = FALSE;
/* used to collect events */
SDL_Event event;
/* this holds some info about our display */
const SDL_VideoInfo *videoInfo;
/* whether or not the window is active */
int isActive = TRUE;
/* initialize SDL */
if ( SDL_Init( SDL_INIT_VIDEO ) < 0 )
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "Video initialization failed: %s\n",
SDL_GetError( ) );
Quit( 1 );
}
/* Fetch the video info */
videoInfo = SDL_GetVideoInfo( );
if ( !videoInfo )
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "Video query failed: %s\n",
SDL_GetError( ) );
Quit( 1 );
}
/* the flags to pass to SDL_SetVideoMode */
videoFlags = SDL_OPENGL; /* Enable OpenGL in SDL */
videoFlags |= SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
videoFlags |= SDL_HWPALETTE; /* Store the palette in hardware */
videoFlags |= SDL_RESIZABLE; /* Enable window resizing */
/* This checks to see if surfaces can be stored in memory */
if ( videoInfo->hw_available )
videoFlags |= SDL_HWSURFACE;
else
videoFlags |= SDL_SWSURFACE;
/* This checks if hardware blits can be done */
if ( videoInfo->blit_hw )
videoFlags |= SDL_HWACCEL;
/* Sets up OpenGL double buffering */
SDL_GL_SetAttribute( SDL_GL_DOUBLEBUFFER, 1 );
/* get a SDL surface */
surface = SDL_SetVideoMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,
videoFlags );
/* Verify there is a surface */
if ( !surface )
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "Video mode set failed: %s\n", SDL_GetError( ) );
Quit( 1 );
}
__android_log_print(ANDROID_LOG_INFO, "SDL","Made a video mode!\n");
/* initialize OpenGL */
initGL( );
/* resize the initial window */
resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
//testAudio();
/* wait for events */
while ( !done )
{
/* handle the events in the queue */
while ( SDL_PollEvent( &event ) )
{
switch( event.type )
{
case SDL_ACTIVEEVENT:
/* Something's happend with our focus
* If we lost focus or we are iconified, we
* shouldn't draw the screen
*/
if ( event.active.gain == 0 )
isActive = FALSE;
else
isActive = TRUE;
break;
case SDL_VIDEORESIZE:
/* handle resize event */
surface = SDL_SetVideoMode( event.resize.w,
event.resize.h,
16, videoFlags );
if ( !surface )
{
__android_log_print(ANDROID_LOG_INFO, "SDL","Could not get a surface after resize: %s\n", SDL_GetError( ) );
Quit( 1 );
}
resizeWindow( event.resize.w, event.resize.h );
break;
case SDL_KEYDOWN:
/* handle key presses */
handleKeyPress( &event.key.keysym );
break;
case SDL_QUIT:
/* handle quit requests */
done = TRUE;
__android_log_print(ANDROID_LOG_INFO, "SDL","App is shutting down\n");
break;
default:
break;
}
}
/* draw the scene */
if ( isActive )
drawGLScene( );
}
/* clean ourselves up and exit */
Quit( 0 );
/* Should never get here */
return( 0 );
}
# This file is automatically generated by Android Tools.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked in Version Control Systems,
# as it contains information specific to your local configuration.
# location of the SDK. This is only used by Ant
# For customization when using a Version Control System, please read the
# header note.
sdk.dir=/home/paul/Projects/gsoc/sdk/android-sdk-linux_86
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, SDLActivity"
/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">SDLActivity</string>
</resources>
package org.libsdl.app;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.*;
import android.app.*;
import android.content.*;
import android.view.*;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
import java.lang.*;
/**
SDL Activity
*/
public class SDLActivity extends Activity {
//Main components
private static SDLActivity mSingleton;
private static SDLSurface mSurface;
//Audio
private static AudioTrack mAudioTrack;
private static boolean bAudioIsEnabled;
//Sensors
private static boolean bAccelIsEnabled;
//feature IDs. Must match up on the C side as well.
private static int FEATURE_AUDIO = 1;
private static int FEATURE_ACCEL = 2;
//Load the .so
static {
System.loadLibrary("sdlapp");
}
//Setup
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//So we can call stuff from static callbacks
mSingleton = this;
//Set up the surface
mSurface = new SDLSurface(getApplication());
setContentView(mSurface);
SurfaceHolder holder = mSurface.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
}
//Audio
public static boolean initAudio(){
//blah. Hardcoded things are bad. FIXME when we have more sound stuff
//working properly.
mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
11025,
AudioFormat.CHANNEL_CONFIGURATION_MONO,
AudioFormat.ENCODING_PCM_8BIT,
2048,
AudioTrack.MODE_STREAM);
bAudioIsEnabled = true;
return true;
}
//Accel
public static boolean initAccel(){
mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
bAccelIsEnabled = true;
return true;
}
public static boolean closeAccel(){
mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
bAccelIsEnabled = false;
return true;
}
//Events
protected void onPause() {
super.onPause();
}
protected void onResume() {
super.onResume();
}
//C functions we call
public static native void nativeInit();
public static native void nativeQuit();
public static native void nativeSetScreenSize(int width, int height);
public static native void onNativeKeyDown(int keycode);
public static native void onNativeKeyUp(int keycode);
public static native void onNativeTouch(int action, float x,
float y, float p);
public static native void onNativeResize(int x, int y, int format);
public static native void onNativeAccel(float x, float y, float z);
//Java functions called from C
private static void createGLContext(){
mSurface.initEGL();
}
public static void flipBuffers(){
mSurface.flipEGL();
}
public static void updateAudio(byte [] buf){
if(mAudioTrack == null){
return;
}
mAudioTrack.write(buf, 0, buf.length);
mAudioTrack.play();
Log.v("SDL","Played some audio");
}
public static void enableFeature(int featureid, int enabled){
Log.v("SDL","Feature " + featureid + " = " + enabled);
//Yuck. This is all horribly inelegent. If it gets to more than a few
//'features' I'll rip this out and make something nicer, I promise :)
if(featureid == FEATURE_AUDIO){
if(enabled == 1){
initAudio();
}else{
//We don't have one of these yet...
//closeAudio();
}
}
else if(featureid == FEATURE_ACCEL){
if(enabled == 1){
initAccel();
}else{
closeAccel();
}
}
}
}
/**
Simple nativeInit() runnable
*/
class SDLRunner implements Runnable{
public void run(){
//SDLActivity.initAudio();
//Runs SDL_main()
SDLActivity.nativeInit();
Log.v("SDL","SDL thread terminated");
}
}
/**
SDLSurface. This is what we draw on, so we need to know when it's created
in order to do anything useful.
Because of this, that's where we set up the SDL thread
*/
class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
//This is what SDL runs in. It invokes SDL_main(), eventually
private Thread mSDLThread;
//EGL private objects
private EGLContext mEGLContext;
private EGLSurface mEGLSurface;
private EGLDisplay mEGLDisplay;
//Sensors
private static SensorManager mSensorManager;
//Startup
public SDLSurface(Context context) {
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
setOnTouchListener(this);
mSensorManager = (SensorManager)context.getSystemService("sensor");
}
//Called when we have a valid drawing surface
public void surfaceCreated(SurfaceHolder holder) {
Log.v("SDL","Surface created");
int width = getWidth();
int height = getHeight();
//Set the width and height variables in C before we start SDL so we have
//it available on init
SDLActivity.nativeSetScreenSize(width, height);
//Now start up the C app thread
mSDLThread = new Thread(new SDLRunner(), "SDLThread");
mSDLThread.start();
}
//Called when we lose the surface
public void surfaceDestroyed(SurfaceHolder holder) {
Log.v("SDL","Surface destroyed");
SDLActivity.nativeQuit();
//Now wait for the SDL thread to quit
try{
mSDLThread.wait();
}catch(Exception e){
Log.v("SDL","Problem stopping thread: " + e);
}
}
//Called when the surface is resized
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
Log.v("SDL","Surface resized");
SDLActivity.onNativeResize(width, height, format);
}
//unused
public void onDraw(Canvas canvas) {}
//EGL functions
public boolean initEGL(){
Log.v("SDL","Starting up");
try{
EGL10 egl = (EGL10)EGLContext.getEGL();
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
egl.eglInitialize(dpy, version);
int[] configSpec = {
//EGL10.EGL_DEPTH_SIZE, 16,
EGL10.EGL_NONE
};
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
egl.eglChooseConfig(dpy, configSpec, configs, 1, num_config);
EGLConfig config = configs[0];
EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, null);
EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null);
egl.eglMakeCurrent(dpy, surface, surface, ctx);
mEGLContext = ctx;
mEGLDisplay = dpy;
mEGLSurface = surface;
}catch(Exception e){
Log.v("SDL", e + "");
for(StackTraceElement s : e.getStackTrace()){
Log.v("SDL", s.toString());
}
}
Log.v("SDL","Done making!");
return true;
}
//EGL buffer flip
public void flipEGL(){
try{
EGL10 egl = (EGL10)EGLContext.getEGL();
GL10 gl = (GL10)mEGLContext.getGL();
egl.eglWaitNative(EGL10.EGL_NATIVE_RENDERABLE, null);
//drawing here
egl.eglWaitGL();
egl.eglSwapBuffers(mEGLDisplay, mEGLSurface);
}catch(Exception e){
Log.v("SDL", "flipEGL(): " + e);
for(StackTraceElement s : e.getStackTrace()){
Log.v("SDL", s.toString());
}
}
}
//Key events
public boolean onKey(View v, int keyCode, KeyEvent event){
if(event.getAction() == KeyEvent.ACTION_DOWN){
SDLActivity.onNativeKeyDown(keyCode);
return true;
}
else if(event.getAction() == KeyEvent.ACTION_UP){
SDLActivity.onNativeKeyUp(keyCode);
return true;
}
return false;
}
//Touch events
public boolean onTouch(View v, MotionEvent event){
int action = event.getAction();
float x = event.getX();
float y = event.getY();
float p = event.getPressure();
//TODO: Anything else we need to pass?
SDLActivity.onNativeTouch(action, x, y, p);
return true;
}
//Sensor events
public void enableSensor(int sensortype, boolean enabled){
//TODO: This uses getDefaultSensor - what if we have >1 accels?
if(enabled){
mSensorManager.registerListener(this,
mSensorManager.getDefaultSensor(sensortype),
SensorManager.SENSOR_DELAY_GAME, null);
}else{
mSensorManager.unregisterListener(this,
mSensorManager.getDefaultSensor(sensortype));
}
}
public void onAccuracyChanged(Sensor sensor, int accuracy){
//TODO
}
public void onSensorChanged(SensorEvent event){
if(event.sensor.getType() == Sensor.TYPE_ACCELEROMETER){
SDLActivity.onNativeAccel( event.values[0],
event.values[1],
event.values[2] );
}
}
}
#!/bin/bash
ANDROID_NDK="/home/paul/Projects/gsoc/sdk/android-ndk-r4"
TOOLS_PATH="$ANDROID_NDK/build/prebuilt/linux-x86/arm-eabi-4.2.1/bin"
export PATH=$TOOLS_PATH:$PATH
CC="arm-eabi-gcc"
#cflags
ACC_C=" -I$ANDROID_NDK/build/platforms/android-8/common/include \
-I$ANDROID_NDK/build/platforms/android-8/arch-arm/usr/include \
-DANDROID -DANDROID_NDK -c"
$CC $CFLAGS $ACC_C $@
#!/bin/bash
ANDROID_NDK="/home/paul/Projects/gsoc/sdk/android-ndk-r4"
TOOLS_PATH="$ANDROID_NDK/build/prebuilt/linux-x86/arm-eabi-4.2.1/bin"
ADDITIONAL_LIBS=`dirname "$0"`/android_libs/
export PATH=$TOOLS_PATH:$PATH
LD="arm-eabi-ld"
#ldflags
ACC_L=" -rpath-link=$ANDROID_NDK/build/platforms/android-8/arch-arm/usr/lib/ \
-dynamic-linker=/system/bin/linker \
-lc -nostdlib \
$ANDROID_NDK/build/platforms/android-8/arch-arm/usr/lib/crtbegin_static.o \
-L$ANDROID_NDK/build/platforms/android-8/arch-arm/usr/lib/ \
-L$ANDROID_NDK/build/prebuilt/linux-x86/arm-eabi-4.2.1/lib/gcc/arm-eabi/4.2.1 \
-L$ADDITIONAL_LIBS "
$LD $ACC_L $LDFLAGS $@ -lgcc
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#ifndef _SDL_config_android_h
#define _SDL_config_android_h
#include "SDL_platform.h"
/**
* \file SDL_config_android.h
*
* This is a configuration that can be used to build SDL for Android
*/
#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;
*/
#define HAVE_ALLOCA_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_STDIO_H 1
#define STDC_HEADERS 1
#define HAVE_STRING_H 1
#define HAVE_INTTYPES_H 1
#define HAVE_STDINT_H 1
#define HAVE_CTYPE_H 1
#define HAVE_MATH_H 1
#define HAVE_SIGNAL_H 1
/* C library functions */
#define HAVE_MALLOC 1
#define HAVE_CALLOC 1
#define HAVE_REALLOC 1
#define HAVE_FREE 1
#define HAVE_ALLOCA 1
#define HAVE_GETENV 1
#define HAVE_SETENV 1
#define HAVE_PUTENV 1
#define HAVE_SETENV 1
#define HAVE_UNSETENV 1
#define HAVE_QSORT 1
#define HAVE_ABS 1
#define HAVE_BCOPY 1
#define HAVE_MEMSET 1
#define HAVE_MEMCPY 1
#define HAVE_MEMMOVE 1
#define HAVE_MEMCMP 1
#define HAVE_STRLEN 1
#define HAVE_STRLCPY 1
#define HAVE_STRLCAT 1
#define HAVE_STRDUP 1
#define HAVE_STRCHR 1
#define HAVE_STRRCHR 1
#define HAVE_STRSTR 1
#define HAVE_STRTOL 1
#define HAVE_STRTOUL 1
#define HAVE_STRTOLL 1
#define HAVE_STRTOULL 1
#define HAVE_STRTOD 1
#define HAVE_ATOI 1
#define HAVE_ATOF 1
#define HAVE_STRCMP 1
#define HAVE_STRNCMP 1
#define HAVE_STRCASECMP 1
#define HAVE_STRNCASECMP 1
#define HAVE_SSCANF 1
#define HAVE_SNPRINTF 1
#define HAVE_VSNPRINTF 1
#define HAVE_CEIL 1
#define HAVE_COPYSIGN 1
#define HAVE_COS 1
#define HAVE_COSF 1
#define HAVE_FABS 1
#define HAVE_FLOOR 1
#define HAVE_LOG 1
#define HAVE_POW 1
#define HAVE_SCALBN 1
#define HAVE_SIN 1
#define HAVE_SINF 1
#define HAVE_SQRT 1
#define HAVE_SIGACTION 1
#define HAVE_SETJMP 1
#define HAVE_NANOSLEEP 1
#define HAVE_SYSCONF 1
#define SIZEOF_VOIDP 4
typedef unsigned int size_t;
//typedef unsigned long uintptr_t;
#define SDL_AUDIO_DRIVER_ANDROID 1
#define SDL_CDROM_DISABLED 1
#define SDL_HAPTIC_DISABLED 1
#define SDL_JOYSTICK_ANDROID 1
#define SDL_LOADSO_DISABLED 1
/* Enable various threading systems */
#define SDL_THREAD_PTHREAD 1
#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
/* Enable various timer systems */
#define SDL_TIMER_UNIX 1
#define SDL_VIDEO_DRIVER_ANDROID 1
#define HAVE_STDIO_H 1
#define HAVE_SYS_TYPES_H 1
#define HAVE_M_PI 1
#define SDL_VIDEO_RENDER_OGL_ES 1
#endif /* _SDL_config_minimal_h */
...@@ -65,6 +65,11 @@ ...@@ -65,6 +65,11 @@
#undef __LINUX__ #undef __LINUX__
#define __LINUX__ 1 #define __LINUX__ 1
#endif #endif
#if defined(ANDROID)
#undef __ANDROID__
#undef __LINUX__ /*do we need to do this?*/
#define __ANDROID__ 1
#endif
#if defined(__APPLE__) #if defined(__APPLE__)
/* lets us know what version of Mac OS X we're compiling on */ /* lets us know what version of Mac OS X we're compiling on */
......
...@@ -174,9 +174,10 @@ SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2); ...@@ -174,9 +174,10 @@ SDL_COMPILE_TIME_ASSERT(uint16, sizeof(Uint16) == 2);
SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2); SDL_COMPILE_TIME_ASSERT(sint16, sizeof(Sint16) == 2);
SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4); SDL_COMPILE_TIME_ASSERT(uint32, sizeof(Uint32) == 4);
SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4); SDL_COMPILE_TIME_ASSERT(sint32, sizeof(Sint32) == 4);
#ifndef __NINTENDODS__ /* TODO: figure out why the following happens: #if !defined(__NINTENDODS__) && !defined(__ANDROID__)
include/SDL_stdinc.h:150: error: size of array 'SDL_dummy_uint64' is negative /* TODO: figure out why the following happens:
include/SDL_stdinc.h:151: error: size of array 'SDL_dummy_sint64' is negative */ include/SDL_stdinc.h:150: error: size of array 'SDL_dummy_uint64' is negative
include/SDL_stdinc.h:151: error: size of array 'SDL_dummy_sint64' is negative */
SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8); SDL_COMPILE_TIME_ASSERT(uint64, sizeof(Uint64) == 8);
SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
#endif #endif
...@@ -195,7 +196,8 @@ SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8); ...@@ -195,7 +196,8 @@ SDL_COMPILE_TIME_ASSERT(sint64, sizeof(Sint64) == 8);
/** \cond */ /** \cond */
#ifndef DOXYGEN_SHOULD_IGNORE_THIS #ifndef DOXYGEN_SHOULD_IGNORE_THIS
#ifndef __NINTENDODS__ /* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */ #if !defined(__NINTENDODS__) && !defined(__ANDROID__)
/* TODO: include/SDL_stdinc.h:174: error: size of array 'SDL_dummy_enum' is negative */
typedef enum typedef enum
{ {
DUMMY_ENUM_VALUE DUMMY_ENUM_VALUE
......
...@@ -639,18 +639,29 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags) ...@@ -639,18 +639,29 @@ SDL_SetVideoMode(int width, int height, int bpp, Uint32 flags)
/* If we're in OpenGL mode, just create a stub surface and we're done! */ /* If we're in OpenGL mode, just create a stub surface and we're done! */
if (flags & SDL_OPENGL) { if (flags & SDL_OPENGL) {
printf("1\n");
SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow); SDL_VideoContext = SDL_GL_CreateContext(SDL_VideoWindow);
if (!SDL_VideoContext) { if (!SDL_VideoContext) {
return NULL; return NULL;
} }
printf("2\n");
if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) { if (SDL_GL_MakeCurrent(SDL_VideoWindow, SDL_VideoContext) < 0) {
return NULL; return NULL;
} }
printf("3\n");
SDL_VideoSurface = SDL_VideoSurface =
SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0); SDL_CreateRGBSurfaceFrom(NULL, width, height, bpp, 0, 0, 0, 0, 0);
if (!SDL_VideoSurface) { if (!SDL_VideoSurface) {
return NULL; return NULL;
} }
printf("4\n");
SDL_VideoSurface->flags |= surface_flags; SDL_VideoSurface->flags |= surface_flags;
SDL_PublicSurface = SDL_VideoSurface; SDL_PublicSurface = SDL_VideoSurface;
return SDL_PublicSurface; return SDL_PublicSurface;
......
...@@ -69,6 +69,7 @@ extern AudioBootStrap MMEAUDIO_bootstrap; ...@@ -69,6 +69,7 @@ extern AudioBootStrap MMEAUDIO_bootstrap;
extern AudioBootStrap DART_bootstrap; extern AudioBootStrap DART_bootstrap;
extern AudioBootStrap NDSAUD_bootstrap; extern AudioBootStrap NDSAUD_bootstrap;
extern AudioBootStrap FUSIONSOUND_bootstrap; extern AudioBootStrap FUSIONSOUND_bootstrap;
extern AudioBootStrap ANDROIDAUD_bootstrap;
/* Available audio drivers */ /* Available audio drivers */
...@@ -136,6 +137,9 @@ static const AudioBootStrap *const bootstrap[] = { ...@@ -136,6 +137,9 @@ static const AudioBootStrap *const bootstrap[] = {
#endif #endif
#if SDL_AUDIO_DRIVER_FUSIONSOUND #if SDL_AUDIO_DRIVER_FUSIONSOUND
&FUSIONSOUND_bootstrap, &FUSIONSOUND_bootstrap,
#endif
#if SDL_AUDIO_DRIVER_ANDROID
&ANDROIDAUD_bootstrap,
#endif #endif
NULL NULL
}; };
...@@ -318,6 +322,8 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream) ...@@ -318,6 +322,8 @@ SDL_StreamDeinit(SDL_AudioStreamer * stream)
} }
#include <android/log.h>
/* The general mixing thread function */ /* The general mixing thread function */
int SDLCALL int SDLCALL
SDL_RunAudio(void *devicep) SDL_RunAudio(void *devicep)
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
This file written by Ryan C. Gordon (icculus@icculus.org)
*/
#include "SDL_config.h"
/* Output audio to Android */
#include "SDL_audio.h"
#include "../SDL_audio_c.h"
#include "SDL_androidaudio.h"
extern void Android_UpdateAudioBuffer(unsigned char *buf, int len);
#include <android/log.h>
static int
AndroidAUD_OpenDevice(_THIS, const char *devname, int iscapture)
{
SDL_AudioFormat test_format = SDL_FirstAudioFormat(this->spec.format);
int valid_datatype = 0;
//TODO: Sample rates etc
__android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Open\n");
this->hidden = SDL_malloc(sizeof(*(this->hidden)));
if (!this->hidden) {
SDL_OutOfMemory();
return 0;
}
SDL_memset(this->hidden, 0, (sizeof *this->hidden));
while ((!valid_datatype) && (test_format)) {
this->spec.format = test_format;
switch (test_format) {
case AUDIO_S8:
/*case AUDIO_S16LSB: */
valid_datatype = 1;
break;
default:
test_format = SDL_NextAudioFormat();
break;
}
}
return 1;
}
static void
AndroidAUD_PlayDevice(_THIS)
{
__android_log_print(ANDROID_LOG_INFO, "SDL", "AndroidAudio Play\n");
//playGenericSound(this->hidden->mixbuf, this->hidden->mixlen);
#if 0
// sound->rate = 22050; /* sample rate = 22050Hz */
// sound->vol = 127; /* volume [0..127] for [min..max] */
// sound->pan = 64; /* balance [0..127] for [left..right] */
// sound->format = 0; /* 0 for 16-bit, 1 for 8-bit */
// playSound(sound);
#endif
}
static Uint8 *
AndroidAUD_GetDeviceBuf(_THIS)
{
//__android_log_print(ANDROID_LOG_INFO, "SDL", "****** get device buf\n");
// sound->data = this->hidden->mixbuf;/* pointer to raw audio data */
// sound->len = this->hidden->mixlen; /* size of raw data pointed to above */
Android_UpdateAudioBuffer(this->hidden->mixbuf, this->hidden->mixlen);
return this->hidden->mixbuf; /* is this right? */
}
static void
AndroidAUD_WaitDevice(_THIS)
{
/* stub */
__android_log_print(ANDROID_LOG_INFO, "SDL", "****** wait device buf\n");
}
static void
AndroidAUD_CloseDevice(_THIS)
{
/* stub */
__android_log_print(ANDROID_LOG_INFO, "SDL", "****** close device buf\n");
}
static int
AndroidAUD_Init(SDL_AudioDriverImpl * impl)
{
/* Set the function pointers */
impl->OpenDevice = AndroidAUD_OpenDevice;
impl->PlayDevice = AndroidAUD_PlayDevice;
impl->WaitDevice = AndroidAUD_WaitDevice;
impl->GetDeviceBuf = AndroidAUD_GetDeviceBuf;
impl->CloseDevice = AndroidAUD_CloseDevice;
/* and the capabilities */
impl->HasCaptureSupport = 0; //TODO
impl->OnlyHasDefaultOutputDevice = 1;
impl->OnlyHasDefaultInputDevice = 1;
__android_log_print(ANDROID_LOG_INFO, "SDL","Audio init\n");
return 1; /* this audio target is available. */
}
AudioBootStrap ANDROIDAUD_bootstrap = {
"android", "SDL Android audio driver", AndroidAUD_Init, 0 /*1? */
};
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef _SDL_androidaudio_h
#define _SDL_androidaudio_h
#include "../SDL_sysaudio.h"
/* Hidden "this" pointer for the audio functions */
#define _THIS SDL_AudioDevice *this
struct SDL_PrivateAudioData
{
/* The file descriptor for the audio device */
Uint8 *mixbuf;
Uint32 mixlen;
Uint32 write_delay;
Uint32 initial_calls;
};
#endif /* _SDL_androidaudio_h */
/* vi: set ts=4 sw=4 expandtab: */
...@@ -92,11 +92,13 @@ SDL_Unlock_EventThread(void) ...@@ -92,11 +92,13 @@ SDL_Unlock_EventThread(void)
static __inline__ SDL_bool static __inline__ SDL_bool
SDL_ShouldPollJoystick() SDL_ShouldPollJoystick()
{ {
#if !SDL_JOYSTICK_DISABLED
if (SDL_numjoysticks && if (SDL_numjoysticks &&
(!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] || (!SDL_disabled_events[SDL_JOYAXISMOTION >> 8] ||
SDL_JoystickEventState(SDL_QUERY))) { SDL_JoystickEventState(SDL_QUERY))) {
return SDL_TRUE; return SDL_TRUE;
} }
#endif
return SDL_FALSE; return SDL_FALSE;
} }
......
...@@ -729,7 +729,7 @@ SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode) ...@@ -729,7 +729,7 @@ SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
break; break;
default: default:
/* Invalid state -- bail */ /* Invalid state -- bail */
return 0; return 2;
} }
/* Drop events that don't change state */ /* Drop events that don't change state */
...@@ -738,14 +738,14 @@ SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode) ...@@ -738,14 +738,14 @@ SDL_SendKeyboardKey(Uint8 state, SDL_scancode scancode)
#if 0 #if 0
printf("Keyboard event didn't change state - dropped!\n"); printf("Keyboard event didn't change state - dropped!\n");
#endif #endif
return 0; return 3;
} }
/* Update internal keyboard state */ /* Update internal keyboard state */
keyboard->keystate[scancode] = state; keyboard->keystate[scancode] = state;
/* Post the event, if desired */ /* Post the event, if desired */
posted = 0; posted = 4;
if (SDL_GetEventState(type) == SDL_ENABLE) { if (SDL_GetEventState(type) == SDL_ENABLE) {
SDL_Event event; SDL_Event event;
event.key.type = type; event.key.type = type;
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifdef SDL_JOYSTICK_ANDROID
/* This is the system specific header for the SDL joystick API */
#include <stdio.h> /* For the definition of NULL */
#include "SDL_error.h"
#include "SDL_events.h"
#include "SDL_joystick.h"
#include "../SDL_sysjoystick.h"
#include "../SDL_joystick_c.h"
extern float fLastAccelerometer[3];
const char *accelerometerName = "Android accelerometer";
/* Function to scan the system for joysticks.
* This function should set SDL_numjoysticks to the number of available
* joysticks. Joystick 0 should be the system default joystick.
* It should return 0, or -1 on an unrecoverable fatal error.
*/
int
SDL_SYS_JoystickInit(void)
{
SDL_numjoysticks = 1;
return (1);
}
/* Function to get the device-dependent name of a joystick */
const char *
SDL_SYS_JoystickName(int index)
{
if (!index)
return accelerometerName;
SDL_SetError("No joystick available with that index");
return (NULL);
}
/* Function to open a joystick for use.
The joystick to open is specified by the index field of the joystick.
This should fill the nbuttons and naxes fields of the joystick structure.
It returns 0, or -1 if there is an error.
*/
int
SDL_SYS_JoystickOpen(SDL_Joystick * joystick)
{
joystick->nbuttons = 0;
joystick->nhats = 0;
joystick->nballs = 0;
joystick->naxes = 3;
joystick->name = accelerometerName;
return 0;
}
/* Function to update the state of a joystick - called as a device poll.
* This function shouldn't update the joystick structure directly,
* but instead should call SDL_PrivateJoystick*() to deliver events
* and update joystick device state.
*/
void
SDL_SYS_JoystickUpdate(SDL_Joystick * joystick)
{
int i=0;
for(i=0;i<3;i++){
SDL_PrivateJoystickAxis(joystick, i, fLastAccelerometer[i]);
}
}
/* Function to close a joystick after use */
void
SDL_SYS_JoystickClose(SDL_Joystick * joystick)
{
}
/* Function to perform any system-specific joystick related cleanup */
void
SDL_SYS_JoystickQuit(void)
{
}
#endif /* SDL_JOYSTICK_NDS */
...@@ -417,6 +417,9 @@ extern VideoBootStrap NDS_bootstrap; ...@@ -417,6 +417,9 @@ extern VideoBootStrap NDS_bootstrap;
#if SDL_VIDEO_DRIVER_PANDORA #if SDL_VIDEO_DRIVER_PANDORA
extern VideoBootStrap PND_bootstrap; extern VideoBootStrap PND_bootstrap;
#endif #endif
#if SDL_VIDEO_DRIVER_ANDROID
extern VideoBootStrap Android_bootstrap;
#endif
#define SDL_CurrentDisplay (&_this->displays[_this->current_display]) #define SDL_CurrentDisplay (&_this->displays[_this->current_display])
#define SDL_CurrentRenderer (SDL_CurrentDisplay->current_renderer) #define SDL_CurrentRenderer (SDL_CurrentDisplay->current_renderer)
......
...@@ -96,6 +96,9 @@ static VideoBootStrap *bootstrap[] = { ...@@ -96,6 +96,9 @@ static VideoBootStrap *bootstrap[] = {
#endif #endif
#if SDL_VIDEO_DRIVER_PANDORA #if SDL_VIDEO_DRIVER_PANDORA
&PND_bootstrap, &PND_bootstrap,
#endif
#if SDL_VIDEO_DRIVER_ANDROID
&Android_bootstrap,
#endif #endif
NULL NULL
}; };
......
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Being a null driver, there's no event stream. We just define stubs for
most of the API. */
#include <stdio.h>
#include <stdlib.h>
#include "../../events/SDL_sysevents.h"
#include "../../events/SDL_events_c.h"
#include "SDL_androidevents.h"
void Android_InitEvents(){
SDL_Keyboard keyboard;
SDL_zero(keyboard);
SDL_AddKeyboard(&keyboard, -1);
SDLKey keymap[SDL_NUM_SCANCODES];
/* Add default scancode to key mapping */
SDL_GetDefaultKeymap(keymap);
SDL_SetKeymap(0, 0, keymap, SDL_NUM_SCANCODES);
}
void
Android_PumpEvents(_THIS)
{
//scanKeys();
/* TODO: defer click-age */
/*
if (keysDown() & KEY_TOUCH) {
SDL_SendMouseButton(0, SDL_PRESSED, 0);
} else if (keysUp() & KEY_TOUCH) {
SDL_SendMouseButton(0, SDL_RELEASED, 0);
}
if (keysHeld() & KEY_TOUCH) {
touchPosition t = touchReadXY();
SDL_SendMouseMotion(0, 0, t.px, t.py, 1);
}
*/
}
void Android_OnResize(int width, int height, int format){
}
int
Android_OnKeyDown(int keycode){
return SDL_SendKeyboardKey(0, SDL_PRESSED, (SDL_scancode)keycode);
}
int
Android_OnKeyUp(int keycode){
return SDL_SendKeyboardKey(0, SDL_RELEASED, (SDL_scancode)keycode);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_androidvideo.h"
extern void Android_PumpEvents(_THIS);
extern void Android_InitEvents();
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Android SDL video driver implementation
*/
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "SDL_androidvideo.h"
#include "SDL_androidevents.h"
#include "SDL_androidrender.h"
#include <android/log.h>
#include <pthread.h>
/*
These things are in the JNI android support
*/
extern void Android_CreateContext();
extern void Android_Render();
/* GL functions */
int Android_GL_LoadLibrary(_THIS, const char *path){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_LoadLibrary\n");
return 0;
}
void *Android_GL_GetProcAddress(_THIS, const char *proc){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_GetProcAddress\n");
return 0;
}
void Android_GL_UnloadLibrary(_THIS){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_UnloadLibrary\n");
}
/*
int *Android_GL_GetVisual(_THIS, Display * display, int screen){
__android_log_print(ANDROID_LOG_INFO, "SDL","[STUB] GL_GetVisual\n");
return 0;
}
*/
SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window){
Android_CreateContext();
return 1;
}
int Android_GL_MakeCurrent(_THIS, SDL_Window * window,
SDL_GLContext context){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_MakeCurrent\n");
return 0;
}
int Android_GL_SetSwapInterval(_THIS, int interval){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_SetSwapInterval\n");
return 0;
}
int Android_GL_GetSwapInterval(_THIS){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_GetSwapInterval\n");
return 0;
}
void Android_GL_SwapWindow(_THIS, SDL_Window * window){
Android_Render();
}
void Android_GL_DeleteContext(_THIS, SDL_GLContext context){
__android_log_print(ANDROID_LOG_INFO, "SDL", "[STUB] GL_DeleteContext\n");
}
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#include "SDL_video.h"
#include "../SDL_sysvideo.h"
#include "../SDL_yuv_sw_c.h"
#include "../SDL_renderer_sw.h"
/* SDL surface based renderer implementation */
static SDL_Renderer *Android_CreateRenderer(SDL_Window * window,
Uint32 flags);
static int Android_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int Android_RenderDrawLines(SDL_Renderer * renderer,
const SDL_Point * points, int count);
static int Android_RenderDrawRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int Android_RenderFillRects(SDL_Renderer * renderer,
const SDL_Rect ** rects, int count);
static int Android_RenderCopy(SDL_Renderer * renderer,
SDL_Texture * texture,
const SDL_Rect * srcrect,
const SDL_Rect * dstrect);
static int Android_RenderReadPixels(SDL_Renderer * renderer,
const SDL_Rect * rect,
Uint32 format,
void * pixels, int pitch);
static int Android_RenderWritePixels(SDL_Renderer * renderer,
const SDL_Rect * rect,
Uint32 format,
const void * pixels, int pitch);
static void Android_RenderPresent(SDL_Renderer * renderer);
static void Android_DestroyRenderer(SDL_Renderer * renderer);
SDL_RenderDriver Android_RenderDriver = {
Android_CreateRenderer,
{
"dummy",
(SDL_RENDERER_SINGLEBUFFER | SDL_RENDERER_PRESENTCOPY |
SDL_RENDERER_PRESENTFLIP2 | SDL_RENDERER_PRESENTFLIP3 |
SDL_RENDERER_PRESENTDISCARD),
}
};
typedef struct
{
int current_screen;
SDL_Surface *screens[3];
} Android_RenderData;
SDL_Renderer *
Android_CreateRenderer(SDL_Window * window, Uint32 flags)
{
SDL_VideoDisplay *display = window->display;
SDL_DisplayMode *displayMode = &display->current_mode;
SDL_Renderer *renderer;
Android_RenderData *data;
int i, n;
int bpp;
Uint32 Rmask, Gmask, Bmask, Amask;
if (!SDL_PixelFormatEnumToMasks
(displayMode->format, &bpp, &Rmask, &Gmask, &Bmask, &Amask)) {
SDL_SetError("Unknown display format");
return NULL;
}
renderer = (SDL_Renderer *) SDL_calloc(1, sizeof(*renderer));
if (!renderer) {
SDL_OutOfMemory();
return NULL;
}
data = (Android_RenderData *) SDL_malloc(sizeof(*data));
if (!data) {
Android_DestroyRenderer(renderer);
SDL_OutOfMemory();
return NULL;
}
SDL_zerop(data);
renderer->RenderDrawPoints = Android_RenderDrawPoints;
renderer->RenderDrawLines = Android_RenderDrawLines;
renderer->RenderDrawRects = Android_RenderDrawRects;
renderer->RenderFillRects = Android_RenderFillRects;
renderer->RenderCopy = Android_RenderCopy;
renderer->RenderReadPixels = Android_RenderReadPixels;
renderer->RenderWritePixels = Android_RenderWritePixels;
renderer->RenderPresent = Android_RenderPresent;
renderer->DestroyRenderer = Android_DestroyRenderer;
renderer->info.name = Android_RenderDriver.info.name;
renderer->info.flags = 0;
renderer->window = window;
renderer->driverdata = data;
Setup_SoftwareRenderer(renderer);
if (flags & SDL_RENDERER_PRESENTFLIP2) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP2;
n = 2;
} else if (flags & SDL_RENDERER_PRESENTFLIP3) {
renderer->info.flags |= SDL_RENDERER_PRESENTFLIP3;
n = 3;
} else {
renderer->info.flags |= SDL_RENDERER_PRESENTCOPY;
n = 1;
}
for (i = 0; i < n; ++i) {
data->screens[i] =
SDL_CreateRGBSurface(0, window->w, window->h, bpp, Rmask, Gmask,
Bmask, Amask);
if (!data->screens[i]) {
Android_DestroyRenderer(renderer);
return NULL;
}
SDL_SetSurfacePalette(data->screens[i], display->palette);
}
data->current_screen = 0;
return renderer;
}
static int
Android_RenderDrawPoints(SDL_Renderer * renderer,
const SDL_Point * points, int count)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Surface *target = data->screens[data->current_screen];
if (renderer->blendMode == SDL_BLENDMODE_NONE ||
renderer->blendMode == SDL_BLENDMODE_MASK) {
Uint32 color = SDL_MapRGBA(target->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
return SDL_DrawPoints(target, points, count, color);
} else {
return SDL_BlendPoints(target, points, count, renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
}
static int
Android_RenderDrawLines(SDL_Renderer * renderer,
const SDL_Point * points, int count)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Surface *target = data->screens[data->current_screen];
if (renderer->blendMode == SDL_BLENDMODE_NONE ||
renderer->blendMode == SDL_BLENDMODE_MASK) {
Uint32 color = SDL_MapRGBA(target->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
return SDL_DrawLines(target, points, count, color);
} else {
return SDL_BlendLines(target, points, count, renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
}
static int
Android_RenderDrawRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
int count)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Surface *target = data->screens[data->current_screen];
if (renderer->blendMode == SDL_BLENDMODE_NONE ||
renderer->blendMode == SDL_BLENDMODE_MASK) {
Uint32 color = SDL_MapRGBA(target->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
return SDL_DrawRects(target, rects, count, color);
} else {
return SDL_BlendRects(target, rects, count,
renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
}
static int
Android_RenderFillRects(SDL_Renderer * renderer, const SDL_Rect ** rects,
int count)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Surface *target = data->screens[data->current_screen];
if (renderer->blendMode == SDL_BLENDMODE_NONE ||
renderer->blendMode == SDL_BLENDMODE_MASK) {
Uint32 color = SDL_MapRGBA(target->format,
renderer->r, renderer->g, renderer->b,
renderer->a);
return SDL_FillRects(target, rects, count, color);
} else {
return SDL_BlendFillRects(target, rects, count,
renderer->blendMode,
renderer->r, renderer->g, renderer->b,
renderer->a);
}
}
static int
Android_RenderCopy(SDL_Renderer * renderer, SDL_Texture * texture,
const SDL_Rect * srcrect, const SDL_Rect * dstrect)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
if (SDL_ISPIXELFORMAT_FOURCC(texture->format)) {
SDL_Surface *target = data->screens[data->current_screen];
void *pixels =
(Uint8 *) target->pixels + dstrect->y * target->pitch +
dstrect->x * target->format->BytesPerPixel;
return SDL_SW_CopyYUVToRGB((SDL_SW_YUVTexture *) texture->driverdata,
srcrect, display->current_mode.format,
dstrect->w, dstrect->h, pixels,
target->pitch);
} else {
SDL_Surface *surface = (SDL_Surface *) texture->driverdata;
SDL_Surface *target = data->screens[data->current_screen];
SDL_Rect real_srcrect = *srcrect;
SDL_Rect real_dstrect = *dstrect;
return SDL_LowerBlit(surface, &real_srcrect, target, &real_dstrect);
}
}
static int
Android_RenderReadPixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, void * pixels, int pitch)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
SDL_Surface *screen = data->screens[data->current_screen];
Uint32 screen_format = display->current_mode.format;
Uint8 *screen_pixels = (Uint8 *) screen->pixels +
rect->y * screen->pitch +
rect->x * screen->format->BytesPerPixel;
int screen_pitch = screen->pitch;
return SDL_ConvertPixels(rect->w, rect->h,
screen_format, screen_pixels, screen_pitch,
format, pixels, pitch);
}
static int
Android_RenderWritePixels(SDL_Renderer * renderer, const SDL_Rect * rect,
Uint32 format, const void * pixels, int pitch)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
SDL_Window *window = renderer->window;
SDL_VideoDisplay *display = window->display;
SDL_Surface *screen = data->screens[data->current_screen];
Uint32 screen_format = display->current_mode.format;
Uint8 *screen_pixels = (Uint8 *) screen->pixels +
rect->y * screen->pitch +
rect->x * screen->format->BytesPerPixel;
int screen_pitch = screen->pitch;
return SDL_ConvertPixels(rect->w, rect->h,
format, pixels, pitch,
screen_format, screen_pixels, screen_pitch);
}
static void
Android_RenderPresent(SDL_Renderer * renderer)
{
static int frame_number;
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
/* Send the data to the display */
if (SDL_getenv("SDL_VIDEO_DUMMY_SAVE_FRAMES")) {
char file[128];
SDL_snprintf(file, sizeof(file), "SDL_window%d-%8.8d.bmp",
renderer->window->id, ++frame_number);
SDL_SaveBMP(data->screens[data->current_screen], file);
}
/* Update the flipping chain, if any */
if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP2) {
data->current_screen = (data->current_screen + 1) % 2;
} else if (renderer->info.flags & SDL_RENDERER_PRESENTFLIP3) {
data->current_screen = (data->current_screen + 1) % 3;
}
}
static void
Android_DestroyRenderer(SDL_Renderer * renderer)
{
Android_RenderData *data =
(Android_RenderData *) renderer->driverdata;
int i;
if (data) {
for (i = 0; i < SDL_arraysize(data->screens); ++i) {
if (data->screens[i]) {
SDL_FreeSurface(data->screens[i]);
}
}
SDL_free(data);
}
SDL_free(renderer);
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* SDL surface based renderer implementation */
extern SDL_RenderDriver Android_RenderDriver;
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
/* Android SDL video driver implementation
*/
#include "SDL_video.h"
#include "SDL_mouse.h"
#include "../SDL_sysvideo.h"
#include "../SDL_pixels_c.h"
#include "../../events/SDL_events_c.h"
#include "SDL_androidvideo.h"
#include "SDL_androidevents.h"
#include "SDL_androidrender.h"
#define ANDROID_VID_DRIVER_NAME "Android"
/* Initialization/Query functions */
static int Android_VideoInit(_THIS);
static int Android_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode);
static void Android_VideoQuit(_THIS);
/* GL functions (SDL_androidgl.c) */
extern int Android_GL_LoadLibrary(_THIS, const char *path);
extern void *Android_GL_GetProcAddress(_THIS, const char *proc);
extern void Android_GL_UnloadLibrary(_THIS);
//extern int *Android_GL_GetVisual(_THIS, Display * display, int screen);
extern SDL_GLContext Android_GL_CreateContext(_THIS, SDL_Window * window);
extern int Android_GL_MakeCurrent(_THIS, SDL_Window * window,
SDL_GLContext context);
extern int Android_GL_SetSwapInterval(_THIS, int interval);
extern int Android_GL_GetSwapInterval(_THIS);
extern void Android_GL_SwapWindow(_THIS, SDL_Window * window);
extern void Android_GL_DeleteContext(_THIS, SDL_GLContext context);
/* Android driver bootstrap functions */
//These are filled in with real values in Android_SetScreenResolution on
//init (before SDL_Main())
static int iScreenWidth = 320;
static int iScreenHeight = 240;
static int
Android_Available(void)
{
return 1;
}
static void
Android_DeleteDevice(SDL_VideoDevice * device)
{
SDL_free(device);
}
static SDL_VideoDevice *
Android_CreateDevice(int devindex)
{
printf("Creating video device\n");
SDL_VideoDevice *device;
/* Initialize all variables that we clean on shutdown */
device = (SDL_VideoDevice *) SDL_calloc(1, sizeof(SDL_VideoDevice));
if (!device) {
SDL_OutOfMemory();
if (device) {
SDL_free(device);
}
return (0);
}
/* Set the function pointers */
device->VideoInit = Android_VideoInit;
device->VideoQuit = Android_VideoQuit;
device->SetDisplayMode = Android_SetDisplayMode;
device->PumpEvents = Android_PumpEvents;
device->free = Android_DeleteDevice;
/* GL pointers */
device->GL_LoadLibrary = Android_GL_LoadLibrary;
device->GL_GetProcAddress = Android_GL_GetProcAddress;
device->GL_UnloadLibrary = Android_GL_UnloadLibrary;
device->GL_CreateContext = Android_GL_CreateContext;
device->GL_MakeCurrent = Android_GL_MakeCurrent;
device->GL_SetSwapInterval = Android_GL_SetSwapInterval;
device->GL_GetSwapInterval = Android_GL_GetSwapInterval;
device->GL_SwapWindow = Android_GL_SwapWindow;
device->GL_DeleteContext = Android_GL_DeleteContext;
return device;
}
VideoBootStrap Android_bootstrap = {
ANDROID_VID_DRIVER_NAME, "SDL Android video driver",
Android_Available, Android_CreateDevice
};
int
Android_VideoInit(_THIS)
{
SDL_DisplayMode mode;
/* Use a fake 32-bpp desktop mode */
mode.format = SDL_PIXELFORMAT_RGB888;
mode.w = iScreenWidth;
mode.h = iScreenHeight;
mode.refresh_rate = 0;
mode.driverdata = NULL;
if (SDL_AddBasicVideoDisplay(&mode) < 0) {
return -1;
}
SDL_AddRenderDriver(&_this->displays[0], &Android_RenderDriver);
SDL_zero(mode);
SDL_AddDisplayMode(&_this->displays[0], &mode);
Android_InitEvents();
/* We're done! */
return 0;
}
static int
Android_SetDisplayMode(_THIS, SDL_VideoDisplay * display, SDL_DisplayMode * mode)
{
return 0;
}
void
Android_VideoQuit(_THIS)
{
}
void Android_SetScreenResolution(int width, int height){
iScreenWidth = width;
iScreenHeight = height;
}
/* vi: set ts=4 sw=4 expandtab: */
/*
SDL - Simple DirectMedia Layer
Copyright (C) 1997-2010 Sam Lantinga
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 St, Fifth Floor, Boston, MA 02110-1301 USA
Sam Lantinga
slouken@libsdl.org
*/
#include "SDL_config.h"
#ifndef _SDL_androidvideo_h
#define _SDL_androidvideo_h
#include "../SDL_sysvideo.h"
#endif /* _SDL_ndsvideo_h */
/* vi: set ts=4 sw=4 expandtab: */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment