diff --git a/3rdparty/android/android_native_app_glue_impl.d b/3rdparty/android/android_native_app_glue_impl.d index 0dcaac15..dd1d0b2d 100644 --- a/3rdparty/android/android_native_app_glue_impl.d +++ b/3rdparty/android/android_native_app_glue_impl.d @@ -32,7 +32,7 @@ import core.stdc.errno; import core.sys.posix.sys.resource; import core.sys.posix.unistd; -import android_native_app_glue; +import android.android_native_app_glue; import android.log; void LOGI(S...)(string fmt, S args) { diff --git a/android/dlangui_source_files.mk b/android/dlangui_source_files.mk old mode 100755 new mode 100644 index d68d4efc..2f310d69 --- a/android/dlangui_source_files.mk +++ b/android/dlangui_source_files.mk @@ -1,9 +1,8 @@ -MY_DIR=$(dirname $(readlink -f $0)) -DLANGUI_DIR=$(dirname $MY_DIR) -echo $DLANGUI_DIR +#MY_DIR=$(dirname $(readlink -f $0)) +#DLANGUI_DIR=$(dirname $MY_DIR) +#echo "DLANGUI DIR: $DLANGUI_DIR" DLANGUI_SOURCES="\ -$DLANGUI_DIR/src/dlangui/core/logger.d \ $DLANGUI_DIR/src/dlangui/platforms/common/startup.d \ $DLANGUI_DIR/src/dlangui/platforms/common/platform.d \ $DLANGUI_DIR/src/dlangui/dialogs/filedlg.d \ @@ -113,25 +112,9 @@ $DLANGUI_DIR/3rdparty/dimage/png.d \ $DLANGUI_DIR/3rdparty/dimage/huffman.d \ $DLANGUI_DIR/3rdparty/dimage/compound.d \ $DLANGUI_DIR/3rdparty/GLES2/gl2.d \ -$DLANGUI_DIR/3rdparty/android_native_app_glue.d \ $DLANGUI_DIR/3rdparty/GLES/gl.d \ $DLANGUI_DIR/3rdparty/EGL/eglplatform.d \ $DLANGUI_DIR/3rdparty/EGL/egl.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/ext.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/functions.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/glx.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/cgl.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/deprecatedConstants.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/gl3.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/types.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/internal.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/wglext.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/wgl.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/glxext.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/arb.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/deprecatedFunctions.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/constants.d \ -$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/gl.d \ $DLANGUI_DIR/deps/DerelictFT/source/derelict/freetype/functions.d \ $DLANGUI_DIR/deps/DerelictFT/source/derelict/freetype/ft.d \ $DLANGUI_DIR/deps/DerelictFT/source/derelict/freetype/types.d \ @@ -143,7 +126,7 @@ $DLANGUI_DIR/deps/DerelictUtil/source/derelict/util/loader.d \ $DLANGUI_DIR/deps/DerelictUtil/source/derelict/util/xtypes.d \ " -echo $DLANGUI_SOURCES +#echo $DLANGUI_SOURCES DLANGUI_SOURCE_PATHS="\ -I$DLANGUI_DIR/src \ @@ -162,5 +145,21 @@ DLANGUI_IMPORT_PATHS="\ -J$DLANGUI_DIR/views/res/shaders \ " -echo "Import paths: $DLANGUI_IMPORT_PATHS" -echo "Source paths: $DLANGUI_SOURCE_PATHS" +#echo "Import paths: $DLANGUI_IMPORT_PATHS" +#echo "Source paths: $DLANGUI_SOURCE_PATHS" + +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/ext.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/functions.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/glx.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/cgl.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/deprecatedConstants.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/gl3.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/types.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/internal.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/wglext.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/wgl.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/glxext.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/arb.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/deprecatedFunctions.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/constants.d \ +#$DLANGUI_DIR/deps/DerelictGL3/source/derelict/opengl3/gl.d \ diff --git a/examples/android/AndroidManifest.xml b/examples/android/AndroidManifest.xml new file mode 100644 index 00000000..2477af8e --- /dev/null +++ b/examples/android/AndroidManifest.xml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/examples/android/android_app.mk b/examples/android/android_app.mk new file mode 100644 index 00000000..530ef26a --- /dev/null +++ b/examples/android/android_app.mk @@ -0,0 +1,12 @@ +# List application source files here + +# application library name ("app" -> libapp.so) +LOCAL_MODULE=native-activity + +# applicatino source files +LOCAL_SRC_FILES="\ +jni/main.d \ +" + +# Additional libraries to link +LOCAL_LDLIBS="" diff --git a/examples/android/android_build_config.mk b/examples/android/android_build_config.mk new file mode 100644 index 00000000..602e2fb3 --- /dev/null +++ b/examples/android/android_build_config.mk @@ -0,0 +1,12 @@ +#!/bin/sh + +#========================================================================= +# Modify this file to specify DLANGUI, Android NDK, SDK and LDC2 locations. + +MY_DIR=$(dirname $(readlink -f $0)) +# relative path: ../../ +export DLANGUI_DIR=$(dirname $(dirname $MY_DIR)) +export NDK=$HOME/android-ndk-r11c +export SDK=$HOME/android-sdk-linux +export LDC=$HOME/ldc2-android-arm-0.17.0-alpha2-linux-x86_64 +export NDK_ARCH=x86_64 diff --git a/examples/android/build_apk.sh b/examples/android/build_apk.sh new file mode 100755 index 00000000..6bfc2b84 --- /dev/null +++ b/examples/android/build_apk.sh @@ -0,0 +1,70 @@ +#!/bin/sh +# load settings for paths +. ./android_build_config.mk + +echo "DlangUI Build for Android native app" +echo "====================================" +echo "DLANGUI_DIR: $DLANGUI_DIR" +echo "NDK: $NDK" +echo "SDK: $SDK" +echo "LDC: $LDC" + +# dlangui sources +. $DLANGUI_DIR/android/dlangui_source_files.mk + +# application sources +. ./android_app.mk + +echo "\nLOCAL_MODULE: $LOCAL_MODULE" +#echo "DLANGUI SOURCES: $DLANGUI_SOURCES" + +LDC_PARAMS="-mtriple=armv7-none-linux-androideabi -relocation-model=pic " +export LD=$NDK/toolchains/llvm/prebuilt/linux-$NDK_ARCH/bin/llvm-link +export CC=$NDK/toolchains/llvm/prebuilt/linux-$NDK_ARCH/bin/clang + +SOURCES="$LOCAL_SRC_FILES $DLANGUI_SOURCES" +SOURCE_PATHS="-I./jni $DLANGUI_SOURCE_PATHS $DLANGUI_IMPORT_PATHS" + +TARGET="libs/armeabi-v7a/lib$LOCAL_MODULE.so" +OBJFILE="build/armeabi-v7a/lib$LOCAL_MODULE.o" + +LIBS="\ +-L$NDK/platforms/android-19/arch-arm/usr/lib \ +$LDC/lib/libphobos2-ldc.a $LDC/lib/libdruntime-ldc.a \ +-lgcc \ +-llog -landroid -lEGL -lGLESv3 -lGLESv1_CM -lc -lm \ +$LOCAL_LDLIBS \ +" + +LINK_OPTIONS="\ +-Wl,-soname,libnative-activity.so \ +--sysroot=$NDK/platforms/android-9/arch-arm \ +-gcc-toolchain $NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-$NDK_ARCH \ +-no-canonical-prefixes \ +-target armv7-none-linux-androideabi \ +-Wl,--fix-cortex-a8 \ +-Wl,--no-undefined \ +-Wl,-z,noexecstack \ +-fuse-ld=bfd \ +-Wl,-z,relro \ +-Wl,-z,now \ +-mthumb \ +" + +mkdir -p libs/armeabi-v7a/ +mkdir -p build/armeabi-v7a/ + +#========================================================= +echo "\nCompiling $OBJFILE\n" +$LDC/bin/ldc2 $LDC_PARAMS $SOURCE_PATHS $SOURCES -c -singleobj -of=$OBJFILE || exit 1 + +#========================================================= +echo "\n\nLinking $TARGET\n" +$CC $OBJFILE $LIBS $LINK_OPTIONS -o $TARGET || exit 1 + +echo "Library is linked ok\n" + +echo "Building APK" + +$SDK/tools/android update project -p . -s --target 1 +ant debug diff --git a/examples/android/deploy_apk.sh b/examples/android/deploy_apk.sh new file mode 100755 index 00000000..6e318dbf --- /dev/null +++ b/examples/android/deploy_apk.sh @@ -0,0 +1,5 @@ +#!/bin/sh +export SDK=/home/lve/android-sdk-linux + +$SDK/platform-tools/adb install -r bin/NativeActivity-debug.apk + diff --git a/examples/android/jni/main.d b/examples/android/jni/main.d new file mode 100644 index 00000000..37a72fb2 --- /dev/null +++ b/examples/android/jni/main.d @@ -0,0 +1,308 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +import core.stdc.stdlib : malloc; +import core.stdc.string : memset; + +import EGL.eglplatform : EGLint; +import EGL.egl, GLES.gl; + +import android.input, android.looper : ALooper_pollAll; +import android.native_window : ANativeWindow_setBuffersGeometry; +import android.sensor, android.log, android.android_native_app_glue; + +int LOGI(const(char)* fmt, float x, float y, float z) { return __android_log_print(android_LogPriority.ANDROID_LOG_INFO, "native-activity", fmt, x, y, z); } +int LOGW(const(char)* warning) { return __android_log_print(android_LogPriority.ANDROID_LOG_WARN, "native-activity", warning); } + +/** + * Our saved state data. + */ +struct saved_state { + float angle; + float x; + float y; +} + +/** + * Shared state for our app. + */ +struct engine { + android_app* app; + + ASensorManager* sensorManager; + const(ASensor)* accelerometerSensor; + ASensorEventQueue* sensorEventQueue; + + int animating; + EGLDisplay display; + EGLSurface surface; + EGLContext context; + int width; + int height; + 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; +} + +/** + * 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; + } +} + +void main(){} +/** + * This is the main entry point of a native application that is using + * android_native_app_glue. It runs in its own thread, with its own + * event loop for receiving input events and doing other things. + */ +extern (C) void android_main(android_app* state) { + engine engine; + + // Make sure glue isn't stripped. + app_dummy(); + + memset(&engine, 0, engine.sizeof); + state.userData = &engine; + state.onAppCmd = &engine_handle_cmd; + state.onInputEvent = &engine_handle_input; + engine.app = state; + + // Prepare to monitor accelerometer + engine.sensorManager = ASensorManager_getInstance(); + engine.accelerometerSensor = ASensorManager_getDefaultSensor(engine.sensorManager, + ASENSOR_TYPE_ACCELEROMETER); + engine.sensorEventQueue = ASensorManager_createEventQueue(engine.sensorManager, + state.looper, LOOPER_ID_USER, null, null); + + if (state.savedState != null) { + // We are starting with a previous saved state; restore from it. + engine.state = *cast(saved_state*)state.savedState; + } + + // loop waiting for stuff to do. + + while (1) { + // Read all pending events. + int ident; + int events; + android_poll_source* source; + + // If not animating, we will block forever waiting for events. + // If animating, we loop until all events are read, then continue + // to draw the next frame of animation. + while ((ident=ALooper_pollAll(engine.animating ? 0 : -1, null, &events, + cast(void**)&source)) >= 0) { + + // Process this event. + if (source != null) { + source.process(state, source); + } + + // If a sensor has data, process it now. + if (ident == LOOPER_ID_USER) { + if (engine.accelerometerSensor != null) { + ASensorEvent event; + while (ASensorEventQueue_getEvents(engine.sensorEventQueue, + &event, 1) > 0) { + LOGI("accelerometer: x=%f y=%f z=%f", + event.acceleration.x, event.acceleration.y, + event.acceleration.z); + } + } + } + + // Check if we are exiting. + if (state.destroyRequested != 0) { + engine_term_display(&engine); + return; + } + } + + if (engine.animating) { + // Done with events; draw next animation frame. + engine.state.angle += .01f; + if (engine.state.angle > 1) { + engine.state.angle = 0; + } + + // Drawing is throttled to the screen update rate, so there + // is no need to do timing here. + engine_draw_frame(&engine); + } + } +} diff --git a/src/dlangui/core/files.d b/src/dlangui/core/files.d index 995877e1..fe02d754 100644 --- a/src/dlangui/core/files.d +++ b/src/dlangui/core/files.d @@ -243,7 +243,9 @@ private: version (Posix) { res ~= RootEntry(RootEntryType.ROOT, "/", "File System"d); } - version(linux) { + version(Android) { + // do nothing + } else version(linux) { import std.string : fromStringz; mntent ent; @@ -582,8 +584,8 @@ bool listDirectory(in string dir, in bool includeDirs, in bool includeFiles, in files ~= e; } } - dirs.sort!((a,b) => filenameCmp!(std.path.CaseSensitive.no)(a,b) < 0); - files.sort!((a,b) => filenameCmp!(std.path.CaseSensitive.no)(a,b) < 0); + dirs.sort!((a,b) => filenameCmp!(std.path.CaseSensitive.no)(a.name,b.name) < 0); + files.sort!((a,b) => filenameCmp!(std.path.CaseSensitive.no)(a.name,b.name) < 0); if (includeDirs) foreach(DirEntry e; dirs) entries ~= e; diff --git a/src/dlangui/graphics/glsupport.d b/src/dlangui/graphics/glsupport.d index 70856a60..53f889f7 100644 --- a/src/dlangui/graphics/glsupport.d +++ b/src/dlangui/graphics/glsupport.d @@ -30,12 +30,19 @@ import std.conv; import std.string; import std.array; -public import derelict.opengl3.types; -public import derelict.opengl3.gl3; -public import derelict.opengl3.gl; +version (Android) { + public import EGL.eglplatform : EGLint; + public import EGL.egl, GLES3.gl3; + public import GLES.gl : glEnableClientState, glLightfv, glColor4f, GL_ALPHA_TEST, GL_VERTEX_ARRAY, + GL_COLOR_ARRAY, glVertexPointer, glColorPointer, glDisableClientState, + GL_TEXTURE_COORD_ARRAY, glTexCoordPointer, glColorPointer, glMatrixMode, + glLoadMatrixf, glLoadIdentity, GL_PROJECTION, GL_MODELVIEW; -import dlangui.graphics.scene.mesh; -import dlangui.graphics.scene.effect; + +} else { + public import derelict.opengl3.types; + public import derelict.opengl3.gl3; + public import derelict.opengl3.gl; derelict.util.exception.ShouldThrow gl3MissingSymFunc( string symName ) { import std.algorithm : equal; @@ -55,6 +62,12 @@ derelict.util.exception.ShouldThrow gl3MissingSymFunc( string symName ) { } +} + +import dlangui.graphics.scene.mesh; +import dlangui.graphics.scene.effect; + + /** * Convenient wrapper around glGetError() * Using: checkgl!glFunction(funcParams); @@ -182,7 +195,7 @@ class GLProgram : dlangui.graphics.scene.mesh.GraphicsEffect { } bool compile() { - glslversion = std.string.fromStringz(glGetString(GL_SHADING_LANGUAGE_VERSION)).dup; + glslversion = std.string.fromStringz(cast(const char *)glGetString(GL_SHADING_LANGUAGE_VERSION)).dup; glslversionString.length = 0; glslversionInt = 0; @@ -660,38 +673,42 @@ bool initGLSupport(bool legacy = false) { import dlangui.platforms.common.platform : setOpenglEnabled; if (_glSupport && _glSupport.valid) return true; - static bool DERELICT_GL3_RELOADED; - static bool gl3ReloadedOk; - static bool glReloadedOk; - if (!DERELICT_GL3_RELOADED) { - DERELICT_GL3_RELOADED = true; - try { - Log.v("Reloading DerelictGL3"); - import derelict.opengl3.gl3; - DerelictGL3.missingSymbolCallback = &gl3MissingSymFunc; - DerelictGL3.reload(); - gl3ReloadedOk = true; - } catch (Exception e) { - Log.e("Derelict exception while reloading DerelictGL3", e); + version(Android) { + + } else { + static bool DERELICT_GL3_RELOADED; + static bool gl3ReloadedOk; + static bool glReloadedOk; + if (!DERELICT_GL3_RELOADED) { + DERELICT_GL3_RELOADED = true; + try { + Log.v("Reloading DerelictGL3"); + import derelict.opengl3.gl3; + DerelictGL3.missingSymbolCallback = &gl3MissingSymFunc; + DerelictGL3.reload(); + gl3ReloadedOk = true; + } catch (Exception e) { + Log.e("Derelict exception while reloading DerelictGL3", e); + } + try { + Log.v("Reloading DerelictGL"); + import derelict.opengl3.gl; + DerelictGL.missingSymbolCallback = &gl3MissingSymFunc; + DerelictGL.reload(); + glReloadedOk = true; + } catch (Exception e) { + Log.e("Derelict exception while reloading DerelictGL", e); + } } - try { - Log.v("Reloading DerelictGL"); - import derelict.opengl3.gl; - DerelictGL.missingSymbolCallback = &gl3MissingSymFunc; - DerelictGL.reload(); - glReloadedOk = true; - } catch (Exception e) { - Log.e("Derelict exception while reloading DerelictGL", e); + if (!gl3ReloadedOk && !glReloadedOk) { + Log.e("Neither DerelictGL3 nor DerelictGL were reloaded successfully"); + return false; } + if (!gl3ReloadedOk) + legacy = true; + else if (!glReloadedOk) + legacy = false; } - if (!gl3ReloadedOk && !glReloadedOk) { - Log.e("Neither DerelictGL3 nor DerelictGL were reloaded successfully"); - return false; - } - if (!gl3ReloadedOk) - legacy = true; - else if (!glReloadedOk) - legacy = false; if (!_glSupport) { _glSupport = new GLSupport(legacy); if (_glSupport.valid || _glSupport.initShaders()) { @@ -731,10 +748,13 @@ final class GLSupport { @property bool legacyMode() { return _legacyMode; } this(bool legacy = false) { - if (legacy && !glLightfv) { - Log.w("GLSupport legacy API is not supported"); - legacy = false; - } + version (Android) { + } else { + if (legacy && !glLightfv) { + Log.w("GLSupport legacy API is not supported"); + legacy = false; + } + } _legacyMode = legacy; } @@ -1222,9 +1242,15 @@ class GLVertexBuffer : VertexBuffer { protected GLuint _vao; this() { - assertgl!glGenBuffers(1, &_vertexBuffer); - assertgl!glGenBuffers(1, &_indexBuffer); - assertgl!glGenVertexArrays(1, &_vao); + version (Android) { + checkgl!glGenBuffers(1, &_vertexBuffer); + checkgl!glGenBuffers(1, &_indexBuffer); + checkgl!glGenVertexArrays(1, &_vao); + } else { + assertgl!glGenBuffers(1, &_vertexBuffer); + assertgl!glGenBuffers(1, &_indexBuffer); + assertgl!glGenVertexArrays(1, &_vao); + } } ~this() {