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>
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;
}
`}
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
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
# 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
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
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)
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
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; `}
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+# 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
--- /dev/null
+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
--- /dev/null
+<?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>
--- /dev/null
+[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
--- /dev/null
+# 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
--- /dev/null
+# 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
# 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
--- /dev/null
+# 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
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
end
import android::aware
+intrude import c
in "C Header" `{
#include <GLES2/gl2.h>
# 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
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_*`
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
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
#
# 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);
`}
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);
# 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
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
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
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("\}")
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("\}")
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
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