android support refactoring #119

This commit is contained in:
Vadim Lopatin 2016-04-20 15:47:30 +03:00
parent 2325d3e4df
commit e633218cb5
1 changed files with 174 additions and 159 deletions

View File

@ -99,7 +99,7 @@ class AndroidPlatform : Platform {
this(android_app* state) {
_appstate = state;
memset(&_engine, 0, engine.sizeof);
state.userData = &_engine;
state.userData = cast(void*)this;
state.onAppCmd = &engine_handle_cmd;
state.onInputEvent = &engine_handle_input;
_engine.app = state;
@ -119,7 +119,174 @@ class AndroidPlatform : Platform {
}
~this() {
engine_term_display(&_engine);
engine_term_display();
}
/**
* Initialize an EGL context for the current display.
*/
int engine_init_display() {
// initialize OpenGL ES and EGL
/*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const(EGLint)[9] attribs = [
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
];
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, null, null);
/* Here, the application chooses the configuration it desires. In this
* sample, we have a very simplified selection process, where we pick
* the first EGLConfig that matches our criteria */
eglChooseConfig(display, attribs.ptr, &config, 1, &numConfigs);
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(_engine.app.window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, _engine.app.window, null);
context = eglCreateContext(display, config, null, null);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
_engine.display = display;
_engine.context = context;
_engine.surface = surface;
_engine.width = w;
_engine.height = h;
_engine.state.angle = 0;
// Initialize GL state.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
//glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
return 0;
}
/**
* Just the current frame in the display.
*/
void engine_draw_frame() {
if (_engine.display == null) {
// No display.
return;
}
// Just fill the screen with a color.
glClearColor(_engine.state.x/_engine.width, _engine.state.angle,
_engine.state.y/_engine.height, 1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(_engine.display, _engine.surface);
}
/**
* Tear down the EGL context currently associated with the display.
*/
void engine_term_display() {
if (_engine.display != EGL_NO_DISPLAY) {
eglMakeCurrent(_engine.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (_engine.context != EGL_NO_CONTEXT) {
eglDestroyContext(_engine.display, _engine.context);
}
if (_engine.surface != EGL_NO_SURFACE) {
eglDestroySurface(_engine.display, _engine.surface);
}
eglTerminate(_engine.display);
}
_engine.animating = 0;
_engine.display = EGL_NO_DISPLAY;
_engine.context = EGL_NO_CONTEXT;
_engine.surface = EGL_NO_SURFACE;
}
/**
* Process the next input event.
*/
int handle_input(AInputEvent* event) {
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
_engine.animating = 1;
_engine.state.x = AMotionEvent_getX(event, 0);
_engine.state.y = AMotionEvent_getY(event, 0);
return 1;
}
return 0;
}
/**
* Process the next main command.
*/
void handle_cmd(int cmd) {
switch (cmd) {
case APP_CMD_SAVE_STATE:
// The system has asked us to save our current state. Do so.
_engine.app.savedState = malloc(saved_state.sizeof);
*(cast(saved_state*)_engine.app.savedState) = _engine.state;
_engine.app.savedStateSize = saved_state.sizeof;
break;
case APP_CMD_INIT_WINDOW:
// The window is being shown, get it ready.
if (_engine.app.window != null) {
engine_init_display();
engine_draw_frame();
}
break;
case APP_CMD_TERM_WINDOW:
// The window is being hidden or closed, clean it up.
engine_term_display();
break;
case APP_CMD_GAINED_FOCUS:
// When our app gains focus, we start monitoring the accelerometer.
if (_engine.accelerometerSensor != null) {
ASensorEventQueue_enableSensor(_engine.sensorEventQueue,
_engine.accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(_engine.sensorEventQueue,
_engine.accelerometerSensor, (1000L/60)*1000);
}
break;
case APP_CMD_LOST_FOCUS:
// When our app loses focus, we stop monitoring the accelerometer.
// This is to avoid consuming battery while not being used.
if (_engine.accelerometerSensor != null) {
ASensorEventQueue_disableSensor(_engine.sensorEventQueue,
_engine.accelerometerSensor);
}
// Also stop animating.
_engine.animating = 0;
engine_draw_frame();
break;
default:
break;
}
}
/**
@ -207,7 +374,7 @@ class AndroidPlatform : Platform {
// Drawing is throttled to the screen update rate, so there
// is no need to do timing here.
engine_draw_frame(&_engine);
engine_draw_frame();
}
}
}
@ -264,172 +431,20 @@ struct engine {
saved_state state;
}
/**
* Initialize an EGL context for the current display.
*/
int engine_init_display(engine* engine) {
// initialize OpenGL ES and EGL
/*
* Here specify the attributes of the desired configuration.
* Below, we select an EGLConfig with at least 8 bits per color
* component compatible with on-screen windows
*/
const(EGLint)[9] attribs = [
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_BLUE_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_RED_SIZE, 8,
EGL_NONE
];
EGLint w, h, dummy, format;
EGLint numConfigs;
EGLConfig config;
EGLSurface surface;
EGLContext context;
EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
eglInitialize(display, null, null);
/* Here, the application chooses the configuration it desires. In this
* sample, we have a very simplified selection process, where we pick
* the first EGLConfig that matches our criteria */
eglChooseConfig(display, attribs.ptr, &config, 1, &numConfigs);
/* EGL_NATIVE_VISUAL_ID is an attribute of the EGLConfig that is
* guaranteed to be accepted by ANativeWindow_setBuffersGeometry().
* As soon as we picked a EGLConfig, we can safely reconfigure the
* ANativeWindow buffers to match, using EGL_NATIVE_VISUAL_ID. */
eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(engine.app.window, 0, 0, format);
surface = eglCreateWindowSurface(display, config, engine.app.window, null);
context = eglCreateContext(display, config, null, null);
if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
LOGW("Unable to eglMakeCurrent");
return -1;
}
eglQuerySurface(display, surface, EGL_WIDTH, &w);
eglQuerySurface(display, surface, EGL_HEIGHT, &h);
engine.display = display;
engine.context = context;
engine.surface = surface;
engine.width = w;
engine.height = h;
engine.state.angle = 0;
// Initialize GL state.
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
glEnable(GL_CULL_FACE);
//glShadeModel(GL_SMOOTH);
glDisable(GL_DEPTH_TEST);
return 0;
}
/**
* Just the current frame in the display.
*/
void engine_draw_frame(engine* engine) {
if (engine.display == null) {
// No display.
return;
}
// Just fill the screen with a color.
glClearColor(engine.state.x/engine.width, engine.state.angle,
engine.state.y/engine.height, 1);
glClear(GL_COLOR_BUFFER_BIT);
eglSwapBuffers(engine.display, engine.surface);
}
/**
* Tear down the EGL context currently associated with the display.
*/
void engine_term_display(engine* engine) {
if (engine.display != EGL_NO_DISPLAY) {
eglMakeCurrent(engine.display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (engine.context != EGL_NO_CONTEXT) {
eglDestroyContext(engine.display, engine.context);
}
if (engine.surface != EGL_NO_SURFACE) {
eglDestroySurface(engine.display, engine.surface);
}
eglTerminate(engine.display);
}
engine.animating = 0;
engine.display = EGL_NO_DISPLAY;
engine.context = EGL_NO_CONTEXT;
engine.surface = EGL_NO_SURFACE;
}
/**
* Process the next input event.
*/
extern(C) int engine_handle_input(android_app* app, AInputEvent* event) {
engine* engine = cast(engine*)app.userData;
if (AInputEvent_getType(event) == AINPUT_EVENT_TYPE_MOTION) {
engine.animating = 1;
engine.state.x = AMotionEvent_getX(event, 0);
engine.state.y = AMotionEvent_getY(event, 0);
return 1;
}
return 0;
AndroidPlatform p = cast(AndroidPlatform)app.userData;
return p.handle_input(event);
}
/**
* Process the next main command.
*/
extern(C) void engine_handle_cmd(android_app* app, int cmd) {
engine* engine = cast(engine*)app.userData;
switch (cmd) {
case APP_CMD_SAVE_STATE:
// The system has asked us to save our current state. Do so.
engine.app.savedState = malloc(saved_state.sizeof);
*(cast(saved_state*)engine.app.savedState) = engine.state;
engine.app.savedStateSize = saved_state.sizeof;
break;
case APP_CMD_INIT_WINDOW:
// The window is being shown, get it ready.
if (engine.app.window != null) {
engine_init_display(engine);
engine_draw_frame(engine);
}
break;
case APP_CMD_TERM_WINDOW:
// The window is being hidden or closed, clean it up.
engine_term_display(engine);
break;
case APP_CMD_GAINED_FOCUS:
// When our app gains focus, we start monitoring the accelerometer.
if (engine.accelerometerSensor != null) {
ASensorEventQueue_enableSensor(engine.sensorEventQueue,
engine.accelerometerSensor);
// We'd like to get 60 events per second (in us).
ASensorEventQueue_setEventRate(engine.sensorEventQueue,
engine.accelerometerSensor, (1000L/60)*1000);
}
break;
case APP_CMD_LOST_FOCUS:
// When our app loses focus, we stop monitoring the accelerometer.
// This is to avoid consuming battery while not being used.
if (engine.accelerometerSensor != null) {
ASensorEventQueue_disableSensor(engine.sensorEventQueue,
engine.accelerometerSensor);
}
// Also stop animating.
engine.animating = 0;
engine_draw_frame(engine);
break;
default:
break;
}
AndroidPlatform p = cast(AndroidPlatform)app.userData;
p.handle_cmd(cmd);
}
void main(){}