IOS Support for Kivy

Kivy has now added official support for IOS platform. You can now package your Kivy application for the Ipad (and other iOS devices, testers needed).

The current instructions are available here: http://kivy.org/docs/guide/packaging-ios.html

For the full story on the multiple Apple limitations we are working with, i want to share the hardest part for Python integration: Apple’s prohibition on using dlopen() to load dynamic libraries.
In a typical case, a compiled Python library’s extension is a “.so”, and the “.so” is dlopen() at import.

That being said, as we did for the python-for-android project published in January, we are redirecting the compilation object to create static libraries. Theses libraries are included in the final application binary. But it’s not enough: we must also tell to Python to look for the library entry point in the application binary, instead of dlopen(). So in the python dynload loader:

return (dl_funcptr) dlsym(RTLD_MAIN_ONLY, funcname)

This way, Python will always look at the application binary, and never need to use dlopen().

If you are worried that Apple would reject a Python-based application, or even using Kivy altogether, we have tested it for you: the game that won the Kivy contest has been packaged for IOS, submitted to Apple… and accepted. You can found Deflectouch on iTunes (source code).

Anyway, Kivy is now officially supporting 5 platforms: Windows, Linux, MacOSX, Android and IOS!

Enjoy :)

Kivy programming contest #1 is over!

During January, we hosted a contest for promoting the Kivy framework. The goal was simple: create a game using Kivy, without external non-pure python dependencies. All the entries have been submitted on our sponsor Github (and thanks to NotionInk), under a compatible OSS licence. The contest registered 21 entries, and 11 submissions was valid.

Our winners are:

  1. Deflectouch, from Cyril Stoller
  2. FishLife, from Zogg
  3. memoryKivy, from Niavlys
  4. Centripetal, from Dilon Cower
  5. Flingy, from Andy Wilson

In term of numbers, everything is growing:

  • 19919 unique visitors for the website (vs 9772 in December)
  • +56 subscribers on the mailing list (192 in total)
  • 229 messages on kivy-users (vs 94 in December)
  • 23 pull requests (vs 6 in December)

That was a great event so far, with a perfect timing: Kivy have now 1 year old! (first release was 1st February 2011).

Introducing “Python for Android”

I’m glad to share a new project called Python for Android. The goal of this project is to package your python application into an APK.

https://github.com/kivy/python-for-android

The project is under the umbrella of Kivy organization, but is not designed to be limited to Kivy only. Read the documentation to correctly install the NDK/SDK Android, and set the needed environment variables.

The packaging is done in 4 steps:
1. Ensure you have Android SDK/NDK downloaded and correctly installed
2. Ensure you have some environment set
3. Create a Python distribution containing the selected modules
4. Use that distribution to build an APK of your Python application

Creating the python distribution is as simple as that:

# create a simple distribution with python + PIL + Kivy
./distribute.sh -m "pil kivy"

# create a distribution with python + openssl + pil + kivy
./distribute.sh -m "openssl pil kivy"

A directory dist/default will be created, including the result of the whole arm compilation.
Available libraries as for today: jpeg pil png sdl sqlite3 pygame kivy android libxml2 libxslt lxml ffmpeg openssl.

The second step is a little bit harder, since you need to provide more information for Android:

cd dist/default
./build.py --package org.test.touchtracer --name touchtracer \
--version 1.0 --dir ~/code/kivy/examples/demo/touchtracer debug installd

# --package: java name of your application
# --name: title of your application
# --version: version of your application
# --dir: location of your application containing the main.py

Then you’ll get a nicely bin/touchtracer-1.0-debug.apk

Pro:

  • A blacklist.txt file that can be used to exclude files in the final APK
  • Reusable distribution for other applications
  • Modular recipes architecture
  • Be able to build independents python distributions

Cons:

  • You need a main.py file that will be used for starting your application
  • Only one java bootstrap available, using OpenGL ES 2.0.
  • Only Kivy toolkit is working. I’m sure that other people can enhance it to add other toolkit recipes. But for example, pygame is not gonna to work because the android project is OpenGL ES 2.0: pygame drawing will not work.

I hope you’ll like it :)

We would like to thank Renpy / PGS4A for its initial pygame for android project

Kivy programming contest #1

Kivy, an open source project for building cross platform applications and user interfaces, is announcing its 1st programming contest. The contest will start with the publication of official rules on January 1st. Registrations will be accepted through January 25th, and submissions will be accepted through January 31st. Prizes include Nvidia Tegra 2 android tablets from NotionInk, One-year “bronze” plans and t-shirts.

The goal of the contest is to encourage interested developers to learn more about Kivy, which is a cross platform Application and User Interface software library for the python programming language. Kivy applications run on Linux, Windows, OSX, Android (and iOS). The framework supports most inputs protocols and devices like WM_Touch, WM_Pen, Mac OS X Trackpad and Magic Mouse, single/multi touch screens, Mtdev, Linux Kernel HID, TUIO, and uses pure hardware accelerated rendering to enable developers to really take user interfaces to a new level.

The contest is sponsored by NotionInk, an indian company that designs tablets PCs, and Github, a web-based hosting service for software developments projects.

Join the contest at : http://kivy.org/#contest

Kivy 1.0.8 released ! What’s next ?

101 days after 1.0.7, Kivy 1.0.8 have been released (changelog).

This release include:

  • New widgets: Virtual Keyboard, Accordion, ProgressBar
  • Video support on android – Python bindings for ffmpeg have been done and are available on github. Theses are focused to be usable on android within Kivy project, but any help to clean and make the code more crossplatform is welcome !
  • Scroll wheel support in scrollview
  • + 1.6x more performance on Kivy langage
  • Support for GIF image + set of images in Zip files
  • Bezier and stipple lines in graphics instructions
  • … and lot of improvements and fixes !

A documentation translation project have been started (thanks for Sphinx for generating gettext translations automatically from python autodoc). Help us at: http://translation.kivy.org/.

And now, where to go ?

The roadmap is not written, since what we do is mostly depending of our interests / jobs / contributions.
But community is growing fast ! I see $N multistroke recognizer, GSOC integration (better macosx integration), iOS port, better android packaging, unit test, better desktop integration, widget theming support, 3D graphics instructions…

If you still hesitating about using Kivy… just look at the frontpage for the current awesome projects made by the community. And they are lot of others projects going to be released during the next month ! We are also glad to see some big companies to use Kivy as the base for building their products.
If you have also cool project going on, don’t hesitate to share :)

To finish, here is a video from Cyril that playing on Icarus Touch, an instrument that use Kivy for his UI. Awesome work !

Texture compression, why does it matter ?

We all care about cash, time, life, love, and if you’re doing computer graphics, you might care about the memory consumption of your graphics card. Why ? For the same reason when you running out of cash :)

I’ll explain why does it matter to compress texture, and compare available possibilities. My personnal goal is to be able to load a lot of FULL HD pictures on tablet, for a museum project. The analysis is focused on DXT1 compression and size. I’m looking forward to ETC1 and will update that blog post with the result in the future.

What are we dealing with

If you are doing an application that display lot of hd pictures, that’s matter. We’ll start from this simple math statement: a full HD picture is 1980×1020 with 4 channels (RGBA). Whatever if your pictures is in PNG, or JPEG, your graphics card is not able to understand it, and will store it in its memory decompressed. So this image will eat:

1920 x 1080 x 4 = 8294400 bytes = 7.91MB
1920 x 1080 x 4 + mipmaps = 10769252 bytes = 10.27MB

In theory. Because it might be more if your graphics card doesn’t support NPOT texture. If not, usually, the texture will be resized to the closest POT texture available, mean for us: 2048 x 2048. Then the size for POT will be:

2048 x 2048 x 4 = 16777216 bytes = 16MB
2048 x 2048 x 4 + mipmaps = 22369620 bytes = 21MB

Compressions types

They are plenty types of compression availables. The most common are S3TC (including DXT1, DXT3, DXT5) from Savage3 originally, LATC from Nvidia, PVRTC from PowerVR, ETC1 from Ericsson…

Not all of them are available everywhere, and it’s depending a lot from your hardware. Here is a list of tablet / vendor / texture compression available. (only tablet, not desktop computer.) Thanks to this stackoverflow thread about supported OpenGL ES 2.0 extensions on Android devices

Tablette Vendor DXT1 S3TC LATC PVRTC ETC1 3DC ATC
(desktop computer) GeForce GTX 560 NVIDIA X X X
Motorola Xoom NVIDIA X X X X
Nexus One Qualcom X X X
Toshiba Folio NVIDIA X X X X
LGE Tablet NVIDIA X X X X
Galaxy Tab PowerVR X X
Acer Stream Qualcomm X X X
Desire Z Qualcomm X X X
Spica Samsumg X X
HTC Desire Qualcomm X X X
VegaTab NVIDIA X X X X
Nexus S PowerVR X X
HTC Desire HD Qualcomm X X X
HTC Legend Qualcomm X X X
Samsung Corby Qualcomm X X X
Droid 2 PowerVR X X
Galaxy S PowerVR X X
Milestone PowerVR X X

We are seeing that ETC1 is standard compression for OpenGL ES 2, unfortunately, it will not work on desktop.
PVRTC is specific to PowerVR device: it’s a standard on Ipad/Iphone.

Using DXT1

If you use DXT1, you need a POT image. DXT1 doesn’t work on NPOT.

To convert any image to DXT1 without any tool, you must know that your graphics card is capable of doing it, using specials opengl functions. But i wanted to precalculate them.
Nvidia texture tools contains tools for converting them, but you need an Nvidia card. For all others, you might want to look at Libsquish. It’s designed to compress in software a raw image to DXTn.
The result will be not a DXT1 “file”, because DXT1 is the compression format. The result will be stored in a DDS file, that we’ll see later about it.

If you want to be able to use libssquish in Python, you might want to apply my patch available on their issue tracker

For DXT1, the size of the file is not depending of the image content:

DXT1 2048x2048 RGBA = 2097152 bytes = 2MB

That’s already a big improvement. DXTn is able to store mipmaps of the texture too. For this size, the calculation is:

DXT1 2048x2048 RGBA + mipmap = 2795520 bytes = 2.73MB

Comparaison table

Type Resolution File size GPU size Images in a 256MB GPU Images in a 512MB GPU
Raw RGBA image (POT) 2048 x 2048 - 16384KB 16 32
PNG image (NPOT) 1920 x 1080 4373KB 8040KB 32 65
PNG Image in reduced POT resolution 1024 x 1024 1268KB 4096KB 64 128
DXT1 without mipmap 2048 x 2048 2048KB 2048KB 128 256
DXT1 without mipmap, reduced 1024 x 1024 512KB 512KB 512 1024
DXT1 with mipmap 2048 x 2048 2730KB 2730KB 96 192
DXT1 with mipmap, reduced 1024 x 1024 682KB 682KB 384 768

As soon as we use compression, what we see is:

  1. The file size is the same as GPU size
  2. Even with POT texture compared to NPOT dxt1, we can still store 4x more images in GPU

And with Kivy ?

DXT1 itself is the compression format, but you cannot actually use it like that. You need to store the result is a formatted file. DDS.

Kivy is already able to read DDS files. But you must ensure that your graphics card is supporting DXT1 or S3TC. Look at gl_has_capability() function in Kivy then.

Kivy at EuroPython – Lightning explanation


For all the guys that was interested about Kivy lightning talk at EuroPython 2011, due to some incomprehension about what is Kivy, here is a lightning explanation to make it clear.

Kivy is a Python framework designed for creating of Natural Users Interfaces. The framework containing abstraction for loading image, video, audio. It have a complete new approach about input events, and widgets. For example, you can use lot of widgets at the _same_ time, something not really possible in classical framework (qt, gtk…): try to touch on a button while selecting something in a list. This is not only about multitouch for one user, but also for multi users. Kivy graphics engine is in OpenGL ES2, and all the widgets are using it.

If you write an application in top of Kivy, you can deploy it on Linux, MacOSX, Windows and Android. Without changing anything in your code. Because it’s in Python.

The presentation tool i’ve used is PreseMT. It have been made by Christopher and Me. And it’s an application built using Kivy. A version of this tool is already published on Android Market.
PreseMT have been written in one week, and use lot of Kivy features. But it’s still not finished, and we are missing lot of features, like the ability to export the presentation in a “good” format. We have plan to make an export in HTML5, that will support animation too.

Feel free to follow me on @mathieuvirbel !

Recording OpenGL output to H264 video

Apitrace is a tool for recording all the gl commands in a trace file. The trace file can be replay in later time, and they got a nice gui for checking all the gl call every frame, with introspection. They have a glretrace software that replay a trace file. We can use it to get the output of everyframe and push it in a gstreamer pipeline to make a video.

Why not using gtkRecordMyDesktop or other screen capture ? Sometime, the overhead of capturing and encoding video on live take too much CPU. And the application start to slow down. I didn’t see any slowdown using apitrace, and the trace file is very small compared to video output or raw video output.

So first, compile apitrace with stdout support:

$ git clone git://github.com/tito/apitrace.git
$ cd apitrace
$ git checkout snapshot-stdout
$ mkdir build
$ cd build
$ cmake ..
$ make

Take any opengl application, and make a trace file. The trace file will have the name of the binary. In my case, python is an alias to python2.7: the trace file will be python2.7.trace.

$ LD_PRELOAD=./glxtrace.so python ~/code/kivy/examples/demo/pictures/main.py
# replay for fun now
$ ./glretrace python2.7.trace

To be able to make a video from the trace file, you need to know the size of the window, and the initial framerate. Here, my example is running at 800×600, 60fps:

$ ./glretrace -sr python2.7-trace | \
  gst-launch fdsrc ! \
  videoparse width=800 height=600 format=rgbx framerate=60 ! \
  videoflip method=5 ! videorate ! ffmpegcolorspace ! \
  video/x-raw-yuv,width=800,height=600,framerate=\(fraction\)30/1 \
   x264enc pass=quant ! avimux ! filesink location=output.avi

The final video will be saved in output.avi. You can check the video output here :

If you like my work, tip me!

Designing Configuration and Settings UI for Kivy

From 3 weeks now, i’m working on packaging kivy application, to create a installer/bundle/deb of a Kivy application. The reason is simple: as soon as you are doing an application, the user should not care about installing Kivy itself. In the same time, i’ve work on other projects that require to have their own configuration. From a long time, we always wanted to have some in-app settings for configure Kivy. Even Android have a “settings” button, we wanted to use it. :)

This is now possible.

Yes, it look like the honeycomb settings panel. Kind of. Well.

The configuration is automatically handled by the App class, and you can put your own token on it. The settings UI (that you’re seeing on the screen) is created from a JSON definitions. You can press F1 or the settings key on android to bring the settings panel, hook the on_config_change to know when a configuration token is changed from the settings ui, etc.

This is available in master, and will be published on next 1.0.7 version. If you are interested, please read and give feedback about the App documentation and the Settings documentation.

If you like my work, tip me!

NPOT textures support in OpenGL

If you already done OpenGL development, you should be aware of POT (Power of two) texture. Because of very old conventions, the texture size must be a power of two size. Not necessarily the same for width and height though : 256×256 is valid as 128×512.

The usual thing to do when you want to load an NPOT texture (like 23×61) is to:

  • take his closed POT size: 32×64
  • depending of the book you’re reading: blit/strech the 23×61 to the 32×64 texture
  • OR blit without stretch, and adjust texture coordinate (this is what kivy does right now.)

The downside part of this approach is that you’re lost a part of memory. Bad.

While ago, i remember to found the Rectangle texture support from NVidia. Aaah, finally, is it what we was waiting from a long time ? Erm, no. Their implementation have lot of downsides:

  • The usage of a specific texture target: GL_TEXTURE_RECTANGLE_NV
  • No mipmap support
  • The texture coordinates are not normalized from 0-1… but from 0-width/height of the image
  • Some wrap mode are not supported (GL_REPEAT for eg.)

But today… i discover that most graphics card are supporting rectangle texture. If the extension GL_ARB_texture_non_power_of_two (OES_texture_npot for OpenGL ES platform), you can finally ensure that loading NPOT texture will… just work as expected :

  • You can still use GL_TEXTURE_2D
  • Mipmapping are supported
  • Texture coordinates are from 0-1
  • All wrap mode are supported

A little note here, in OpenGL ES 2, they have a native support for NPOT texture, but with somes limitations related to mipmapping.

If you want to just load NPOT texture safely without using rectangle texture, just check the availability of theses extensions :

extensions = glGetString(GL_EXTENSIONS).split()
npot_support = ('OES_texture_npot' in extensions or \
                'GL_ARB_texture_non_power_of_two' in extensions)