Merge: Prepare Android projects to be compiled in release mode for F-Droid
authorJean Privat <jean@pryen.org>
Tue, 15 Sep 2015 13:27:16 +0000 (09:27 -0400)
committerJean Privat <jean@pryen.org>
Tue, 15 Sep 2015 13:27:16 +0000 (09:27 -0400)
This PR prepares the Android projects to be compiled in release mode by Jenkins (or a cron) for F-Droid. It adds the `android-release` rule to all Android projects and it vectorizes the fonts in the logos to get the desired result when the font is not installed.

At this point, the release APK file is written over the debug one, this should not be such a big problem as we usually use both separately.

@privat To prepare to compile in release mode on the server you can follow the instructions at the end of http://nitlanguage.org/catalog/android.html , it's pretty much a single command to generate a keystore. We'll have to find a way to manage the key to the keystore... For the TSA server, we could use http://tsa.safecreative.org/ but it's limited to 5 timestamps per days so we would need to choose our requests.

Pull-Request: #1710
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
Reviewed-by: Jean Privat <jean@pryen.org>

25 files changed:
contrib/friendz/res/raw/music.ogg [new file with mode: 0644]
lib/android/audio.nit
lib/android/native_app_glue.nit
lib/c.nit
lib/egl.nit
lib/gamnit/display.nit [new file with mode: 0644]
lib/gamnit/display_android.nit [new file with mode: 0644]
lib/gamnit/display_linux.nit [new file with mode: 0644]
lib/gamnit/egl.nit [new file with mode: 0644]
lib/gamnit/examples/triangle/Makefile [new file with mode: 0644]
lib/gamnit/examples/triangle/art/icon.svg [new file with mode: 0644]
lib/gamnit/examples/triangle/bin/.gitignore [new file with mode: 0644]
lib/gamnit/examples/triangle/package.ini [new file with mode: 0644]
lib/gamnit/examples/triangle/res/.gitignore [new file with mode: 0644]
lib/gamnit/examples/triangle/src/portable_triangle.nit [new file with mode: 0644]
lib/gamnit/examples/triangle/src/standalone_triangle.nit [new file with mode: 0644]
lib/gamnit/gamnit.nit
lib/gamnit/gamnit_android.nit [new file with mode: 0644]
lib/glesv2/examples/opengles2_hello_triangle.nit
lib/glesv2/glesv2.nit
lib/linux/linux.nit
lib/mnit/linux/linux_app.nit
src/compiler/compiler_ffi/compiler_ffi.nit
src/platform/android.nit
tests/sav/Darwin/todo

diff --git a/contrib/friendz/res/raw/music.ogg b/contrib/friendz/res/raw/music.ogg
new file mode 100644 (file)
index 0000000..8dcfa3b
Binary files /dev/null and b/contrib/friendz/res/raw/music.ogg differ
index b729219..b361b4f 100644 (file)
@@ -138,7 +138,6 @@ private extern class NativeMediaPlayer in "Java" `{ android.media.MediaPlayer `}
                        self.setDataSource(fd, start_offset, length);
                        return 1;
                }catch(Exception e) {
-                       Log.e("Error loading the Media Player with a file descriptor", e.getMessage());
                        return 0;
                }
        `}
@@ -537,8 +536,8 @@ redef class Sound
        end
 
        redef fun play do
-               if self.error != null then return
                if not is_loaded then load
+               if self.error != null then return
                soundpool.play(soundpool_id)
        end
 
@@ -599,8 +598,8 @@ redef class Music
        end
 
        redef fun play do
-               if self.error != null then return
                if not is_loaded then load
+               if self.error != null then return
                media_player.start
        end
 
index 2202827..d99f5a9 100644 (file)
@@ -368,4 +368,13 @@ end
 
 # Android NDK's structure to control the native window for drawing
 extern class ANativeWindow `{ ANativeWindow* `}
+       # Change the format and size of the window buffers
+       #
+       # All arguments can be set to 0 to use the default devices values.
+       # `width` and `height` must both be set to 0 or have significant values.
+       #
+       # `format` is a value specified by EGL.
+       fun set_buffers_geometry(width, height, format: Int): Bool `{
+               return ANativeWindow_setBuffersGeometry(self, (int32_t)width, (int32_t)height, (int32_t)format);
+       `}
 end
index deb6765..a9b04e1 100644 (file)
--- a/lib/c.nit
+++ b/lib/c.nit
@@ -93,8 +93,8 @@ class CIntArray
                super size
        end
 
-       # Build from an `Array[Int]`
-       new from(array: Array[Int])
+       # Create from an `SequenceRead[Int]`
+       new from(array: SequenceRead[Int])
        do
                var carray = new CIntArray(array.length)
                for i in array.length.times do
@@ -129,7 +129,7 @@ class CByteArray
                super size
        end
 
-       # Build from a `SequenceRead[Byte]`
+       # Create from a `SequenceRead[Byte]`
        new from(array: SequenceRead[Byte])
        do
                var carray = new CByteArray(array.length)
@@ -166,8 +166,8 @@ class CNativeStringArray
                super size
        end
 
-       # Build from an `Array[NativeString]`
-       new from(array: Array[NativeString])
+       # Create from an `SequenceRead[NativeString]`
+       new from(array: SequenceRead[NativeString])
        do
                var carray = new CNativeStringArray(array.length)
                for i in array.length.times do
index 8934b7e..69df8e5 100644 (file)
@@ -454,3 +454,6 @@ end
 fun egl_bind_opengl_api: Bool `{ return eglBindAPI(EGL_OPENGL_API); `}
 fun egl_bind_opengl_es_api: Bool `{ return eglBindAPI(EGL_OPENGL_ES_API); `}
 fun egl_bind_openvg_api: Bool `{ return eglBindAPI(EGL_OPENVG_API); `}
+
+# Handle to the default display to use with EGL
+fun egl_default_display: Pointer `{ return EGL_DEFAULT_DISPLAY; `}
diff --git a/lib/gamnit/display.nit b/lib/gamnit/display.nit
new file mode 100644 (file)
index 0000000..94ece8a
--- /dev/null
@@ -0,0 +1,49 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# 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.
+
+# Abstract display services
+module display
+
+import ::glesv2
+
+import display_linux is conditional(linux)
+import display_android is conditional(android)
+
+# Should Gamnit be more verbose?
+fun debug_gamnit: Bool do return false
+
+# General display class, is sized and drawable
+class GamnitDisplay
+
+       # Width of the display, in pixels
+       fun width: Int is abstract
+
+       # Height of the display, in pixels
+       fun height: Int is abstract
+
+       # Prepare this display
+       #
+       # The implementation varies per platform.
+       fun setup is abstract
+
+       # Close this display and free underlying resources
+       #
+       # The implementation varies per platform.
+       fun close do end
+
+       # Flip the display buffers
+       #
+       # The implementation varies per platform.
+       fun flip do end
+end
diff --git a/lib/gamnit/display_android.nit b/lib/gamnit/display_android.nit
new file mode 100644 (file)
index 0000000..d0e5235
--- /dev/null
@@ -0,0 +1,47 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# 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.
+
+# Gamnit display implementation for Android
+#
+# Generated APK files require OpenGL ES 2.0.
+#
+# This modules uses `android::native_app_glue` and the Android NDK.
+module display_android is
+       android_manifest """<uses-feature android:glEsVersion="0x00020000"/>"""
+end
+
+import ::android
+
+private import gamnit::egl
+
+redef class GamnitDisplay
+
+       redef fun setup
+       do
+               var native_display = egl_default_display
+               var native_window = app.native_app_glue.window
+
+               setup_egl_display native_display
+
+               # We need 8 bits per color for selection by color
+               select_egl_config(8, 8, 8, 0, 8, 0, 0)
+
+               var format = egl_config.attribs(egl_display).native_visual_id
+               native_window.set_buffers_geometry(0, 0, format)
+
+               setup_egl_context native_window
+       end
+
+       redef fun close do close_egl
+end
diff --git a/lib/gamnit/display_linux.nit b/lib/gamnit/display_linux.nit
new file mode 100644 (file)
index 0000000..109ff51
--- /dev/null
@@ -0,0 +1,91 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# 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.
+
+# Gamnit display implementation for GNU/Linux using `egl`, `sdl` and `x11`
+module display_linux
+
+import sdl
+import x11
+
+import egl # local to gamnit
+import display
+
+redef class GamnitDisplay
+
+       # Actual width or desired width of the window, can be set before calling `setup`
+       fun width=(value: Int) do requested_width = value
+       private var requested_width = 1920
+
+       # Actual height or desired height of the window, can be set before calling `setup`
+       fun height=(value: Int) do requested_height = value
+       private var requested_height = 1080
+
+       # Setup SDL, X11, EGL in order
+       redef fun setup
+       do
+               if debug_gamnit then print "Setting up SDL"
+               self.sdl_display = setup_sdl(requested_width, requested_height)
+
+               if debug_gamnit then print "Setting up X11"
+               var x11_display = setup_x11
+               var window_handle = window_handle
+               setup_egl_display x11_display
+
+               if debug_gamnit then print "Setting up EGL context"
+               select_egl_config(8, 8, 8, 8, 8, 0, 0)
+               setup_egl_context window_handle
+       end
+
+       # Close EGL and SDL in reverse order of `setup` (nothing to do for X11)
+       redef fun close
+       do
+               close_egl
+               close_sdl
+       end
+
+       # ---
+       # SDL
+
+       # The SDL display managing the window and events
+       var sdl_display: SDLDisplay is noautoinit
+
+       # Setup the SDL display and lib
+       fun setup_sdl(window_width, window_height: Int): SDLDisplay
+       do
+               var sdl_display = new SDLDisplay(window_width, window_height)
+               assert not sdl_display.address_is_null else print "Opening SDL display failed"
+               return sdl_display
+       end
+
+       # Close the SDL display
+       fun close_sdl do sdl_display.destroy
+
+       # Get a native handle to the current SDL window
+       fun window_handle: Pointer
+       do
+               var sdl_wm_info = new SDLSystemWindowManagerInfo
+               return sdl_wm_info.x11_window_handle
+       end
+
+       # ---
+       # X11
+
+       # Get a native handle to the current X11 display
+       fun setup_x11: Pointer
+       do
+               var x11_display = x_open_default_display
+               assert not x11_display.address_is_null else print "Opening X11 display failed"
+               return x11_display
+       end
+end
diff --git a/lib/gamnit/egl.nit b/lib/gamnit/egl.nit
new file mode 100644 (file)
index 0000000..3fcb8c8
--- /dev/null
@@ -0,0 +1,115 @@
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# 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.
+
+# Use of EGL to implement Gamnit on GNU/Linux and Android
+module egl
+
+import ::egl
+
+import gamnit::display
+
+redef class GamnitDisplay
+
+       # The EGL display
+       var egl_display: EGLDisplay is noautoinit
+
+       # The EGL context
+       var egl_context: EGLContext is noautoinit
+
+       # The EGL surface for the window
+       var window_surface: EGLSurface is noautoinit
+
+       # The selected EGL configuration
+       var egl_config: EGLConfig is noautoinit
+
+       # Setup the EGL display for the given `x11_display`
+       protected fun setup_egl_display(x11_display: Pointer)
+       do
+               var egl_display = new EGLDisplay(x11_display)
+               assert egl_display.is_valid else print "new EGL display is not valid"
+
+               egl_display.initialize
+               assert egl_display.is_valid else print "EGL initialize error: {egl_display.error}"
+
+               self.egl_display = egl_display
+       end
+
+       # Select an EGL config
+       protected fun select_egl_config(blue, green, red, alpha, depth, stencil, sample: Int)
+       do
+               var config_chooser = new EGLConfigChooser
+               config_chooser.renderable_type_egl
+               config_chooser.surface_type_egl
+               config_chooser.blue_size = blue
+               config_chooser.green_size = green
+               config_chooser.red_size = red
+               if alpha > 0 then config_chooser.alpha_size = alpha
+               if depth > 0 then config_chooser.depth_size = depth
+               if stencil > 0 then config_chooser.stencil_size = stencil
+               if sample > 0 then config_chooser.sample_buffers = sample
+               config_chooser.close
+
+               var configs = config_chooser.choose(egl_display)
+               assert configs != null else print "Choosing EGL config failed: {egl_display.error}"
+               assert not configs.is_empty else print "Found no EGL config"
+
+               if debug_gamnit then
+                       print "EGL available configurations:"
+                       for config in configs do
+                               var attribs = config.attribs(egl_display)
+                               print "* Conformant to: {attribs.conformant}"
+                               print "  Caveats: {attribs.caveat}"
+                               print "  Size of RGBA: {attribs.red_size} {attribs.green_size} {attribs.blue_size} {attribs.alpha_size}"
+                               print "  Buffer, depth, stencil: {attribs.buffer_size} {attribs.depth_size} {attribs.stencil_size}"
+                       end
+               end
+
+               # We use the first one, it is recommended
+               self.egl_config = configs.first
+       end
+
+       # Setup the EGL context for the given `window_handle`
+       protected fun setup_egl_context(window_handle: Pointer)
+       do
+               var window_surface = egl_display.create_window_surface(egl_config, window_handle, [0])
+               assert window_surface.is_ok else print "Creating EGL window surface failed: {egl_display.error}"
+               self.window_surface = window_surface
+
+               egl_context = egl_display.create_context(egl_config)
+               assert egl_context.is_ok else print "Creating EGL context failed: {egl_display.error}"
+
+               var make_current_res = egl_display.make_current(window_surface, window_surface, egl_context)
+               assert make_current_res else print "Creating EGL make current failed: {egl_display.error}"
+
+               # TODO make the API selection configurable per platform
+               assert egl_bind_opengl_es_api else print "EGL bind API failed: {egl_display.error}"
+       end
+
+       redef fun width do return window_surface.attribs(egl_display).width
+
+       redef fun height do return window_surface.attribs(egl_display).height
+
+       # Close the EGL context
+       fun close_egl
+       do
+               egl_display.make_current(new EGLSurface.none, new EGLSurface.none, new EGLContext.none)
+               egl_display.destroy_context(egl_context)
+               egl_display.destroy_surface(window_surface)
+       end
+
+       redef fun flip
+       do
+               egl_display.swap_buffers(window_surface)
+       end
+end
diff --git a/lib/gamnit/examples/triangle/Makefile b/lib/gamnit/examples/triangle/Makefile
new file mode 100644 (file)
index 0000000..22172de
--- /dev/null
@@ -0,0 +1,21 @@
+NITC=../../../../bin/nitc
+NITLS=../../../../bin/nitls
+
+all: bin/standalone_triangle bin/triangle bin/triangle.apk
+
+bin/standalone_triangle: $(shell ${NITLS} -M src/standalone_triangle.nit linux) ${NITC}
+       ${NITC} src/standalone_triangle.nit -m linux -o $@
+
+bin/triangle: $(shell ${NITLS} -M src/portable_triangle.nit linux) ${NITC}
+       ${NITC} src/portable_triangle.nit -m linux -o $@
+
+check: bin/standalone_triangle bin/triangle
+       bin/standalone_triangle
+       bin/triangle
+
+android: bin/triangle.apk
+bin/triangle.apk: $(shell ${NITLS} -M src/portable_triangle.nit android) ${NITC} res/drawable-hdpi/icon.png
+       ${NITC} src/portable_triangle.nit -m android -o $@
+
+res/drawable-hdpi/icon.png: art/icon.svg
+       ../../../../contrib/inkscape_tools/bin/svg_to_icons --out res --android art/icon.svg
diff --git a/lib/gamnit/examples/triangle/art/icon.svg b/lib/gamnit/examples/triangle/art/icon.svg
new file mode 100644 (file)
index 0000000..26f7c04
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="512"
+   height="512"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.5 r10040"
+   sodipodi:docname="New document 1">
+  <defs
+     id="defs4" />
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="0.98994949"
+     inkscape:cx="292.54393"
+     inkscape:cy="311.81525"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:window-width="1279"
+     inkscape:window-height="1379"
+     inkscape:window-x="3840"
+     inkscape:window-y="27"
+     inkscape:window-maximized="0" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(0,-540.36218)">
+    <rect
+       style="fill:#ab00cf;fill-opacity:1;stroke:none"
+       id="rect2985"
+       width="512"
+       height="512"
+       x="0"
+       y="540.36218"
+       ry="69.507881"
+       rx="69.507881" />
+    <path
+       sodipodi:type="star"
+       style="fill:#ff001b;fill-opacity:1;stroke:none"
+       id="path3755"
+       sodipodi:sides="3"
+       sodipodi:cx="22.857143"
+       sodipodi:cy="-299.06638"
+       sodipodi:r1="235.13782"
+       sodipodi:r2="118.85303"
+       sodipodi:arg1="-1.5707963"
+       sodipodi:arg2="-0.52359875"
+       inkscape:flatsided="false"
+       inkscape:rounded="0"
+       inkscape:randomized="0"
+       d="m 22.85715,-534.20419 102.92974,175.7113 100.70557,176.99543 -203.63532,1.28411 -203.63532,-1.28412 100.705584,-176.99542 z"
+       inkscape:transform-center-y="-22.453664"
+       transform="translate(232.85714,1144.2857)" />
+  </g>
+</svg>
diff --git a/lib/gamnit/examples/triangle/bin/.gitignore b/lib/gamnit/examples/triangle/bin/.gitignore
new file mode 100644 (file)
index 0000000..72e8ffc
--- /dev/null
@@ -0,0 +1 @@
+*
diff --git a/lib/gamnit/examples/triangle/package.ini b/lib/gamnit/examples/triangle/package.ini
new file mode 100644 (file)
index 0000000..f673878
--- /dev/null
@@ -0,0 +1,11 @@
+[package]
+name=triangle
+tags=example
+maintainer=Alexis Laferrière <alexis.laf@xymus.net>
+license=Apache-2.0
+[upstream]
+browse=https://github.com/nitlang/nit/tree/master/lib/gamnit/examples/triangle/
+git=https://github.com/nitlang/nit.git
+git.directory=lib/gamnit/examples/triangle/
+homepage=http://nitlanguage.org
+issues=https://github.com/nitlang/nit/issues
diff --git a/lib/gamnit/examples/triangle/res/.gitignore b/lib/gamnit/examples/triangle/res/.gitignore
new file mode 100644 (file)
index 0000000..72e8ffc
--- /dev/null
@@ -0,0 +1 @@
+*
diff --git a/lib/gamnit/examples/triangle/src/portable_triangle.nit b/lib/gamnit/examples/triangle/src/portable_triangle.nit
new file mode 100644 (file)
index 0000000..ac8e0e6
--- /dev/null
@@ -0,0 +1,138 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+# Portable example of using Gamnit with custom calls to OpenGL ES 2.0
+#
+# References:
+# * The book OpenGL ES 2.0 Programming Guide
+# * https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c
+module portable_triangle is
+       app_name "gamnit Triangle"
+       app_namespace "org.nitlanguage.triangle"
+       app_version(1, 0, git_revision)
+end
+
+import gamnit
+
+redef class App
+
+       # Our only program for the graphic card
+       var program: GLProgram is noautoinit
+
+       # The only vertex sharder
+       var vertex_shader: GLVertexShader is noautoinit
+
+       # The only fragment sharder
+       var fragment_shader: GLFragmentShader is noautoinit
+
+       # Vertex data for the triangle
+       var vertex_array: VertexArray is noautoinit
+
+       redef fun on_create
+       do
+               super
+
+               var display = display
+               assert display != null
+
+               print "Width: {display.width}"
+               print "Height: {display.height}"
+
+               assert_no_gl_error
+               assert gl.shader_compiler else print "Cannot compile shaders"
+
+               # GL program
+               program = new GLProgram
+               if not program.is_ok then
+                       print "Program is not ok: {gl.error.to_s}\nLog:"
+                       print program.info_log
+                       abort
+               end
+               assert_no_gl_error
+
+               # Vertex shader
+               vertex_shader = new GLVertexShader
+               assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}"
+               vertex_shader.source = """
+               attribute vec4 vPosition;
+               void main()
+               {
+                 gl_Position = vPosition;
+               }
+               """@glsl_vertex_shader.to_cstring
+               vertex_shader.compile
+               assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
+               assert_no_gl_error
+
+               # Fragment shader
+               fragment_shader = new GLFragmentShader
+               assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}"
+               fragment_shader.source = """
+               precision mediump float;
+               void main()
+               {
+                       gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+               }
+               """@glsl_fragment_shader.to_cstring
+               fragment_shader.compile
+               assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
+               assert_no_gl_error
+
+               # Attach to program
+               program.attach_shader vertex_shader
+               program.attach_shader fragment_shader
+               program.bind_attrib_location(0, "vPosition")
+               program.link
+               assert program.is_linked else print "Linking failed: {program.info_log}"
+               assert_no_gl_error
+
+               # Draw!
+               var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
+               vertex_array = new VertexArray(0, 3, vertices)
+               vertex_array.attrib_pointer
+       end
+
+       redef fun frame_core
+       do
+               var display = display
+               if display != null then
+                       gl.clear_color(0.5, 0.0, 0.5, 1.0)
+
+                       assert_no_gl_error
+                       gl.viewport(0, 0, display.width, display.height)
+                       gl.clear((new GLBuffer).color)
+                       program.use
+                       vertex_array.enable
+
+                       glDrawArrays(new GLDrawMode.triangles, 0, 3)
+
+                       display.flip
+               end
+       end
+
+       redef fun on_stop
+       do
+               # Clean up
+               program.delete
+               vertex_shader.delete
+               fragment_shader.delete
+
+               # Close gamnit
+               var display = display
+               if display != null then display.close
+       end
+end
+
+if "NIT_TESTING".environ == "true" then exit(0)
+super
diff --git a/lib/gamnit/examples/triangle/src/standalone_triangle.nit b/lib/gamnit/examples/triangle/src/standalone_triangle.nit
new file mode 100644 (file)
index 0000000..04e14db
--- /dev/null
@@ -0,0 +1,112 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+# Example of using `GamnitDisplay` to setup a screen for custom calls to OpenGL ES 2.0
+#
+# This example does not support the lifecycle of mobile platforms, as such it only works on desktop computers.
+#
+# References:
+# * The book OpenGL ES 2.0 Programming Guide
+# * https://code.google.com/p/opengles-book-samples/source/browse/trunk/LinuxX11/Chapter_2/Hello_Triangle/Hello_Triangle.c
+module standalone_triangle
+
+import app
+import gamnit::display
+
+if "NIT_TESTING".environ == "true" then exit(0)
+
+# Setup gamnit
+var display = new GamnitDisplay
+display.setup
+
+var width = display.width
+var height = display.height
+print "Width: {width}"
+print "Height: {height}"
+
+# Custom calls to OpenGL ES 2.0
+assert_no_gl_error
+assert gl.shader_compiler else print "Cannot compile shaders"
+
+# GL program
+print gl.error.to_s
+var program = new GLProgram
+if not program.is_ok then
+       print "Program is not ok: {gl.error.to_s}\nLog:"
+       print program.info_log
+       abort
+end
+assert_no_gl_error
+
+# Vertex shader
+var vertex_shader = new GLVertexShader
+assert vertex_shader.is_ok else print "Vertex shader is not ok: {gl.error}"
+vertex_shader.source = """
+attribute vec4 vPosition;
+void main()
+{
+  gl_Position = vPosition;
+}
+"""@glsl_vertex_shader.to_cstring
+vertex_shader.compile
+assert vertex_shader.is_compiled else print "Vertex shader compilation failed with: {vertex_shader.info_log} {program.info_log}"
+assert_no_gl_error
+
+# Fragment shader
+var fragment_shader = new GLFragmentShader
+assert fragment_shader.is_ok else print "Fragment shader is not ok: {gl.error}"
+fragment_shader.source = """
+precision mediump float;
+void main()
+{
+       gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
+}
+"""@glsl_fragment_shader.to_cstring
+fragment_shader.compile
+assert fragment_shader.is_compiled else print "Fragment shader compilation failed with: {fragment_shader.info_log}"
+assert_no_gl_error
+
+# Attach to program
+program.attach_shader vertex_shader
+program.attach_shader fragment_shader
+program.bind_attrib_location(0, "vPosition")
+program.link
+assert program.is_linked else print "Linking failed: {program.info_log}"
+assert_no_gl_error
+
+# Draw!
+var vertices = [0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0]
+var vertex_array = new VertexArray(0, 3, vertices)
+vertex_array.attrib_pointer
+gl.clear_color(0.5, 0.0, 0.5, 1.0)
+for i in [0..1000[ do
+       printn "."
+       assert_no_gl_error
+       gl.viewport(0, 0, width, height)
+       gl.clear((new GLBuffer).color)
+       program.use
+       vertex_array.enable
+
+       glDrawArrays(new GLDrawMode.triangles, 0, 3)
+
+       display.flip
+end
+
+# Clean up
+program.delete
+vertex_shader.delete
+fragment_shader.delete
+
+# Close gamnit
+display.close
index 2fa5b8e..43ec95c 100644 (file)
 
 # Game and multimedia framework for Nit
 module gamnit
+
+import app
+
+import display
+
+import gamnit_android is conditional(android)
+
+redef class App
+
+       # Main `GamnitDisplay` initialized by `on_create`
+       var display: nullable GamnitDisplay = null
+
+       redef fun on_create
+       do
+               super
+
+               var display = new GamnitDisplay
+               display.setup
+               self.display = display
+       end
+
+       # Core of the frame logic, executed only when the display is visible
+       #
+       # This method should be redefined by user modules to customize the behavior of the game.
+       protected fun frame_core do end
+
+       # Full frame logic, executed even if the display is not visible
+       #
+       # This method wraps `frame_core` and other services to be executed in the main app loop.
+       #
+       # To customize the behavior on each turn, it is preferable to redefined `frame_core`.
+       # Still, `frame_full` can be redefined with care for more control.
+       protected fun frame_full
+       do
+               var display = display
+               if display != null then frame_core
+
+               feed_events
+       end
+
+       redef fun run
+       do
+               # TODO manage exit condition
+               loop frame_full
+       end
+
+       # Loop on available events and feed them back to the app
+       #
+       # The implementation varies per platform.
+       private fun feed_events do end
+end
diff --git a/lib/gamnit/gamnit_android.nit b/lib/gamnit/gamnit_android.nit
new file mode 100644 (file)
index 0000000..647c741
--- /dev/null
@@ -0,0 +1,24 @@
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# 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.
+
+# Support services for Gamnit on Android
+module gamnit_android
+
+import android
+
+intrude import gamnit
+
+redef class App
+       redef fun feed_events do app.poll_looper 0
+end
index 48d49ab..3a1e1c5 100644 (file)
@@ -168,7 +168,7 @@ for i in [0..10000[ do
        gl.clear((new GLBuffer).color)
        program.use
        vertex_array.enable
-       vertex_array.draw_arrays_triangles
+       glDrawArrays(new GLDrawMode.triangles, 0, 3)
        egl_display.swap_buffers(surface)
 end
 
index 4e71e1f..9c3e1d7 100644 (file)
@@ -37,6 +37,7 @@ module glesv2 is
 end
 
 import android::aware
+intrude import c
 
 in "C Header" `{
        #include <GLES2/gl2.h>
@@ -296,38 +297,106 @@ class VertexArray
        # Number of data per vertex
        var count: Int
 
-       protected var glfloat_array: GLfloatArray
+       protected var glfloat_array: NativeGLfloatArray
 
        init(index, count: Int, array: Array[Float])
        do
                self.index = index
                self.count = count
-               self.glfloat_array = new GLfloatArray(array)
+               self.glfloat_array = new NativeGLfloatArray(array.length)
+               for k in [0..array.length[ do
+                       glfloat_array[k] = array[k]
+               end
        end
 
        fun attrib_pointer do attrib_pointer_intern(index, count, glfloat_array)
-       private fun attrib_pointer_intern(index, count: Int, array: GLfloatArray) `{
+       private fun attrib_pointer_intern(index, count: Int, array: NativeGLfloatArray) `{
                glVertexAttribPointer(index, count, GL_FLOAT, GL_FALSE, 0, array);
        `}
 
-       fun enable do enable_intern(index)
-       private fun enable_intern(index: Int) `{ glEnableVertexAttribArray(index); `}
+       # Enable this vertex attribute array
+       fun enable do glEnableVertexAttribArray(index)
 
-       fun draw_arrays_triangles do draw_arrays_triangles_intern(index, count)
-       private fun draw_arrays_triangles_intern(index, count: Int) `{
-               glDrawArrays(GL_TRIANGLES, index, count);
-       `}
+       # Disable this vertex attribute array
+       fun disable do glDisableVertexAttribArray(index)
 end
 
+# Enable the generic vertex attribute array at `index`
+fun glEnableVertexAttribArray(index: Int) `{ glEnableVertexAttribArray(index); `}
+
+# Disable the generic vertex attribute array at `index`
+fun glDisableVertexAttribArray(index: Int) `{ glDisableVertexAttribArray(index); `}
+
+# Render primitives from array data
+fun glDrawArrays(mode: GLDrawMode, from, count: Int) `{ glDrawArrays(mode, from, count); `}
+
+# Define an array of generic vertex attribute data
+fun glVertexAttribPointer(index, size: Int, typ: GLDataType, normalized: Bool, stride: Int, array: NativeGLfloatArray) `{
+       glVertexAttribPointer(index, size, typ, normalized, stride, array);
+`}
+
+# Specify the value of a generic vertex attribute
+fun glVertexAttrib1f(index: Int, x: Float) `{ glVertexAttrib1f(index, x); `}
+
+# Specify the value of a generic vertex attribute
+fun glVertexAttrib2f(index: Int, x, y: Float) `{ glVertexAttrib2f(index, x, y); `}
+
+# Specify the value of a generic vertex attribute
+fun glVertexAttrib3f(index: Int, x, y, z: Float) `{ glVertexAttrib3f(index, x, y, z); `}
+
+# Specify the value of a generic vertex attribute
+fun glVertexAttrib4f(index: Int, x, y, z, w: Float) `{ glVertexAttrib4f(index, x, y, z, w); `}
+
+# Specify the value of a uniform variable for the current program object
+fun glUniform1i(index, x: Int) `{ glUniform1i(index, x); `}
+
+# Specify the value of a uniform variable for the current program object
+fun glUniform2i(index, x, y: Int) `{ glUniform2i(index, x, y); `}
+
+# Specify the value of a uniform variable for the current program object
+fun glUniform3i(index, x, y, z: Int) `{ glUniform3i(index, x, y, z); `}
+
+# Specify the value of a uniform variable for the current program object
+fun glUniform4i(index, x, y, z, w: Int) `{ glUniform4i(index, x, y, z, w); `}
+
+# TODO glUniform*f
+
 # Low level array of `Float`
-extern class GLfloatArray `{GLfloat *`}
-       new (array: Array[Float]) import Array[Float].length, Array[Float].[] `{
-               int i;
-               int len = Array_of_Float_length(array);
-               GLfloat *vertex_array = malloc(sizeof(GLfloat)*len);
-               for (i = 0; i < len; i ++) vertex_array[i] = Array_of_Float__index(array, i);
-               return vertex_array;
-       `}
+class GLfloatArray
+       super CArray[Float]
+       redef type NATIVE: NativeGLfloatArray
+
+       init do native_array = new NativeGLfloatArray(length)
+
+       # Create with the content of `array`
+       new from(array: Array[Float])
+       do
+               var arr = new GLfloatArray(array.length)
+               arr.fill_from array
+               return arr
+       end
+
+       # Fill with the content of `array`
+       fun fill_from(array: Array[Float])
+       do
+               assert length >= array.length
+               for k in [0..array.length[ do
+                       self[k] = array[k]
+               end
+       end
+end
+
+# An array of `GLfloat` in C (`GLfloat*`)
+extern class NativeGLfloatArray `{ GLfloat* `}
+       super NativeCArray
+       redef type E: Float
+
+       new(size: Int) `{ return calloc(size, sizeof(GLfloat)); `}
+
+       redef fun [](index) `{ return self[index]; `}
+       redef fun []=(index, val) `{ self[index] = val; `}
+
+       redef fun +(offset) `{ return self + offset; `}
 end
 
 # General type for OpenGL enumerations
@@ -375,30 +444,47 @@ do
        end
 end
 
-# Texture minifying function
-#
-# Used by: `GLES::tex_parameter_min_filter`
-extern class GLTextureMinFilter
-       super GLEnum
+# Does `name` corresponds to a texture?
+fun glIsTexture(name: Int): Bool `{ return glIsTexture(name); `}
 
-       new nearest `{ return GL_NEAREST; `}
-       new linear `{ return GL_LINEAR; `}
-end
+# Bind the named `texture` to a `target`
+fun glBindTexture(target: GLTextureTarget, texture: Int) `{ glBindTexture(target, texture); `}
 
-# Texture magnification function
-#
-# Used by: `GLES::tex_parameter_mag_filter`
-extern class GLTextureMagFilter
+# Set pixel storage modes
+fun glPixelStorei(parameter: GLPack, val: Int) `{ glPixelStorei(parameter, val); `}
+
+# Symbolic name of the parameter to be set with `glPixelStorei`
+extern class GLPack
        super GLEnum
+end
+
+# Parameter to specify the alignment requirements for the start of each pixel row in memory
+fun gl_PACK_ALIGNEMENT: GLPack `{ return GL_PACK_ALIGNMENT; `}
+
+# Parameter to specify the alignment requirements for the start of each pixel row in memory
+fun gl_UNPACK_ALIGNEMENT: GLPack `{ return GL_UNPACK_ALIGNMENT; `}
+
+# TODO GL_PACK_ROW_LENGTH, GL_PACK_IMAGE_HEIGHT, GL_PACK_SKIP_PIXELS, GL_PACK_SKIP_ROWS, GL_PACK_SKIP_IMAGES
+# GL_UNPACK_ROW_LENGTH, GL_UNPACK_IMAGE_HEIGHT, GL_UNPACK_SKIP_PIXELS, GL_UNPACK_SKIP_ROWS, GL_UNPACK_SKIP_IMAGES
 
-       new nearest `{ return GL_NEAREST; `}
-       new linear `{ return GL_LINEAR; `}
-       new nearest_mipmap_nearest `{ return GL_NEAREST_MIPMAP_NEAREST; `}
-       new linear_mipmap_nearest `{ return GL_LINEAR_MIPMAP_NEAREST; `}
-       new nearest_mipmap_linear `{ return GL_NEAREST_MIPMAP_LINEAR; `}
-       new linear_mipmap_linear `{ return GL_LINEAR_MIPMAP_LINEAR; `}
+# Specify a two-dimensional texture image
+fun glTexImage2D(target: GLTextureTarget, level, internalformat, width, height, border: Int,
+                 format: GLPixelFormat, typ: GLPixelType, data: NativeCByteArray) `{
+       glTexImage2D(target, level, internalformat, width, height, border, format, typ, data);
+`}
+
+# Texture minifying and magnifying function
+extern class GLTextureFilter
+       super GLEnum
 end
 
+fun gl_NEAREST: GLTextureFilter `{ return GL_NEAREST; `}
+fun gl_LINEAR: GLTextureFilter `{ return GL_LINEAR; `}
+fun gl_NEAREST_MIPMAP_NEAREST: GLTextureFilter `{ return GL_NEAREST_MIPMAP_NEAREST; `}
+fun gl_LINEAR_MIPMAP_NEAREST: GLTextureFilter `{ return GL_LINEAR_MIPMAP_NEAREST; `}
+fun gl_NEAREST_MIPMAP_NINEAR: GLTextureFilter `{ return GL_NEAREST_MIPMAP_LINEAR; `}
+fun gl_LINEAR_MIPMAP_LINEAR: GLTextureFilter `{ return GL_LINEAR_MIPMAP_LINEAR; `}
+
 # Wrap parameter of a texture
 #
 # Used by: `tex_parameter_wrap_*`
@@ -411,15 +497,19 @@ extern class GLTextureWrap
 end
 
 # Target texture
-#
-# Used by: `tex_parameter_*`
 extern class GLTextureTarget
        super GLEnum
-
-       new flat `{ return GL_TEXTURE_2D; `}
-       new cube_map `{ return GL_TEXTURE_CUBE_MAP; `}
 end
 
+# Two-dimensional texture
+fun gl_TEXTURE_2D: GLTextureTarget `{ return GL_TEXTURE_2D; `}
+
+# Cube map texture
+fun gl_TEXTURE_CUBE_MAP: GLTextureTarget `{ return GL_TEXTURE_CUBE_MAP; `}
+
+# TODO GL_TEXTURE_CUBE_MAP_POSITIVE_X, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
+# GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
+
 # A server-side capability
 class GLCap
 
@@ -439,6 +529,52 @@ class GLCap
        redef fun hash do return val
        redef fun ==(o) do return o != null and is_same_type(o) and o.hash == self.hash
 end
+
+# Attach a renderbuffer object to a framebuffer object
+fun glFramebufferRenderbuffer(target: GLFramebufferTarget, attachment: GLAttachment,
+                              renderbuffertarget: GLRenderbufferTarget, renderbuffer: Int) `{
+       glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+`}
+
+# Establish data storage, `format` and dimensions of the `target` renderbuffer object's image
+fun glRenderbufferStorage(target: GLRenderbufferTarget, format: GLRenderbufferFormat, width, height: Int) `{
+       glRenderbufferStorage(GL_RENDERBUFFER, format, width, height);
+`}
+
+# Format for a renderbuffer
+extern class GLRenderbufferFormat
+       super GLEnum
+end
+
+# 4 red, 4 green, 4 blue, 4 alpha bits format
+fun gl_RGBA4: GLRenderbufferFormat `{ return GL_RGBA4; `}
+
+# 5 red, 6 green, 5 blue bits format
+fun gl_RGB565: GLRenderbufferFormat `{ return GL_RGB565; `}
+
+# 5 red, 5 green, 5 blue, 1 alpha bits format
+fun gl_RGB_A1: GLRenderbufferFormat `{ return GL_RGB5_A1; `}
+
+# 16 depth bits format
+fun gl_DEPTH_COMPNENT16: GLRenderbufferFormat `{ return GL_DEPTH_COMPONENT16; `}
+
+# 8 stencil bits format
+fun gl_STENCIL_INDEX8: GLRenderbufferFormat `{ return GL_STENCIL_INDEX8; `}
+
+# Renderbuffer attachment point to a framebuffer
+extern class GLAttachment
+       super GLEnum
+end
+
+# First color attachment point
+fun gl_COLOR_ATTACHMENT0: GLAttachment `{ return GL_COLOR_ATTACHMENT0; `}
+
+# Depth attachment point
+fun gl_DEPTH_ATTACHMENT: GLAttachment `{ return GL_DEPTH_ATTACHMENT; `}
+
+# Stencil attachment
+fun gl_STENCIL_ATTACHMENT: GLAttachment `{ return GL_STENCIL_ATTACHMENT; `}
+
 redef class Sys
        private var gles = new GLES is lazy
 end
@@ -544,20 +680,20 @@ class GLES
        #
        # Foreign: glReadPixel
        fun read_pixels(x, y, width, height: Int, format: GLPixelFormat, typ: GLPixelType, data: Pointer) `{
-               glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, data);
+               glReadPixels(x, y, width, height, format, typ, data);
        `}
 
        # Set the texture minifying function
        #
        # Foreign: glTexParameter with GL_TEXTURE_MIN_FILTER
-       fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureMinFilter) `{
+       fun tex_parameter_min_filter(target: GLTextureTarget, value: GLTextureFilter) `{
                glTexParameteri(target, GL_TEXTURE_MIN_FILTER, value);
        `}
 
        # Set the texture magnification function
        #
        # Foreign: glTexParameter with GL_TEXTURE_MAG_FILTER
-       fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureMagFilter) `{
+       fun tex_parameter_mag_filter(target: GLTextureTarget, value: GLTextureFilter) `{
                glTexParameteri(target, GL_TEXTURE_MAG_FILTER, value);
        `}
 
@@ -619,6 +755,23 @@ fun glHint(target: GLHintTarget, mode: GLHintMode) `{
        glHint(target, mode);
 `}
 
+# Generate and fill set of mipmaps for the texture object `target`
+fun glGenerateMipmap(target: GLTextureTarget) `{ glGenerateMipmap(target); `}
+
+# Bind the named `buffer` object
+fun glBindBuffer(target: GLArrayBuffer, buffer: Int) `{ glBindBuffer(target, buffer); `}
+
+# Target to which bind the buffer with `glBindBuffer`
+extern class GLArrayBuffer
+       super GLEnum
+end
+
+# Array buffer target
+fun gl_ARRAY_BUFFER: GLArrayBuffer `{ return GL_ARRAY_BUFFER; `}
+
+# Element array buffer
+fun gl_ELEMENT_ARRAY_BUFFER: GLArrayBuffer `{ return GL_ELEMENT_ARRAY_BUFFER; `}
+
 # Completeness status of a framebuffer object
 fun glCheckFramebufferStatus(target: GLFramebufferTarget): GLFramebufferStatus `{
        return glCheckFramebufferStatus(target);
@@ -686,6 +839,12 @@ fun gl_NICEST: GLHintMode `{ return GL_NICEST; `}
 # No preference
 fun gl_DONT_CARE: GLHintMode `{ return GL_DONT_CARE; `}
 
+# Attach a level of a texture object as a logical buffer to the currently bound framebuffer object
+fun glFramebufferTexture2D(target: GLFramebufferTarget, attachment: GLAttachment,
+                           texture_target: GLTextureTarget,  texture, level: Int) `{
+       glFramebufferTexture2D(target, attachment, texture_target, texture, level);
+`}
+
 # Entry point to OpenGL server-side capabilities
 class GLCapabilities
 
index 8b90102..04a0c5d 100644 (file)
 module linux
 
 import app
+
+redef class App
+       redef fun setup
+       do
+               super
+
+               on_create
+               on_restore_state
+               on_start
+               on_resume
+       end
+
+       redef fun run
+       do
+               super
+
+               on_pause
+               on_save_state
+               on_stop
+               on_destroy
+       end
+end
index 938bfd8..7bc03a0 100644 (file)
@@ -35,21 +35,6 @@ redef class App
                display = new Opengles1Display
 
                super
-
-               on_create
-               on_restore_state
-               on_start
-               on_resume
-       end
-
-       redef fun run
-       do
-               super
-
-               on_pause
-               on_save_state
-               on_stop
-               on_destroy
        end
 
        redef fun generate_input
index edf0a16..79c2f14 100644 (file)
@@ -280,7 +280,7 @@ redef class MExplicitCast
 
                        var from_var = nitni_visitor.var_from_c("from", from)
                        from_var = nitni_visitor.box_extern(from_var, from)
-                       var recv_var = nitni_visitor.type_test(from_var, to, "FFI isa")
+                       var recv_var = nitni_visitor.type_test(from_var, to, "isa")
                        nitni_visitor.add("return {recv_var};")
 
                        nitni_visitor.add("\}")
@@ -316,7 +316,7 @@ redef class MExplicitCast
                        from_var = nitni_visitor.box_extern(from_var, from)
 
                        ## test type
-                       var check = nitni_visitor.type_test(from_var, to, "FFI cast")
+                       var check = nitni_visitor.type_test(from_var, to, "as")
                        nitni_visitor.add("if (!{check}) \{")
                        nitni_visitor.add_abort("FFI cast failed")
                        nitni_visitor.add("\}")
index 72c219f..1a6f458 100644 (file)
@@ -337,11 +337,16 @@ $(call import-module,android/native_app_glue)
                        var tsa_server= "TSA_SERVER".environ
 
                        if key_alias.is_empty then
-                               toolcontext.error(null,
-                                       "Error: the environment variable `KEY_ALIAS` must be set to use the `--release` option on Android projects.")
+                               toolcontext.warning(null, "key-alias",
+                                       "Warning: the environment variable `KEY_ALIAS` is not set, the APK file will not be signed.")
+
+                               # Just move the unsigned APK to outname
+                               args = ["mv", apk_path, outname]
+                               toolcontext.exec_and_check(args, "Android project error")
                                return
                        end
 
+                       # We have a key_alias, try to sign the APK
                        args = ["jarsigner", "-sigalg", "MD5withRSA", "-digestalg", "SHA1", apk_path, key_alias]
 
                        ## Use a custom keystore
index c3eac84..5a6669c 100644 (file)
@@ -1,4 +1,5 @@
 fatal error: 'endian.h' file not found
 Error: package `glesv1_cm` unknown by `pkg-config`, make sure the development package is be installed
 Error: package `glesv2` unknown by `pkg-config`, make sure the development package is be installed
+Error: package `egl` unknown by `pkg-config`, make sure the development package is be installed
 fatal error: 'libintl.h' file not found