Android with OpenCL tutorial
System information:
– Ubuntu 13.10 64 bit
– Eclipse: Android SDK tools 22.3 , SDK platform tools 19.0.1 , Android build-tools 19.0.2 , Android NDK r9c
– To work with this tutorial you should have already setup your android SDK. If you don’t know how to setup the android SDK follow this link: http://developer.android.com/sdk/installing/bundle.html
– This tutorial is for Odroid but can be used for any other platform if you change the right .so file. (Will be explained later)
Step 1: setup Android NDK
- Download the NDK from: http://developer.android.com/tools/sdk/ndk/index.html
- I unzipped it in the adt-bundle
- Create a new android project and call it InverseFilter
- Take all the default settings
- Go to Window -> Preferences -> Android -> NDK
- Browse to android-ndk-r9c. Example: /home/dries/AndroidDev/adt-bundle-linux-x86_64-20131030/android-ndk-r9c
- Click apply and ok
Step 2: configure Android NDK for your project
- Right click on your project folder. Choose android tools -> add native support (! the bottom one !) and click finish.
- The file you just created is going to be your own .so file with the functions in it we will create later in the tutorial.
- Now you should see a JNI folder in your project with a InverseFilter.cpp and an Android.mk file in it.
- Now go to project -> properties -> C/C++ build -> build variables -> add
- Name: NDKROOT
- Value: your android-ndk-r9c folder you also added to NDK in step 1.
- Click Ok
- Go to C/C++ build and uncheck Use default build path. Change the build path to ${NDKROOT}/ndk-build
- Make sure you did not end the NDKROOT value on / !
- Click apply
- In the JNI folder, create an Application.mk file. This is the make file. And add the following text to it:
APP_STL := stlport_static
APP_CPPFLAGS := -fexceptions
APP_OPTIM := debug
APP_ABI := armeabi-v7a
APP_PLATFORM := android-14
- This is where it gets hardware specific: now you will have to copy the right .so file from your Android device.
- Example: on a device with a PowerVR GPU you will have to search for libPVROCL.so.
- On this site you can see that your device is supported or not: http://www.khronos.org/conformance/adopters/conformant-products
- Look for your processor or GPU on the website
- More information can be found here: http://streamcomputing.eu/blog/2013-09-05/mobile-processor-opencl-drivers-q3-2013/
- This tutorial is created on an Odroid XU with a PowerVR GPU
- Change the Android.mk file to (the line in bold is the line that has to be edited platform specific.
LOCAL_PATH := $(call my-dir)
LOCAL_PATH_EXT := $(call my-dir)/../external/
include $(CLEAR_VARS)
LOCAL_MODULE := InverseFilter
LOCAL_CFLAGS += -DANDROID_CL
LOCAL_CFLAGS += -O3 -ffast-math
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../include
LOCAL_SRC_FILES := InverseFilter.cpp
#LOCAL_LDFLAGS += -ljnigraphics
LOCAL_LDLIBS := -llog -ljnigraphics
LOCAL_LDLIBS += $(LOCAL_PATH)/../external/libPVROCL.so
LOCAL_ARM_MODE := arm
include $(BUILD_SHARED_LIBRARY)
- If you work with the Odroid XU you must create a /external/ directory in your project directory and copy the libPVROCL.so from the Odroid XU into this directory
- To make use of the opencl functions you need the opencl headers. You can find those headers in my git link in the folder “include/CL” . I advice you to copy the include folder directly into your own project.
Step 3: create an opencl kernel
- Create a file in the assets folder named inverse.cl
- This file will be your kernel function for opencl. This is the function the will be placed in the command queue for your GPU.
- You can find my inverse.cl kernel on git (link below).
Step 4: creating a very simple opencl program
In the next steps I will explain code parts. The source code can be downloaded below with GIT or in a zip file. The code takes a picture from it’s sources and creates the inverse of the image and shows it below the original picture.
MainActivity.java file:
- This try catch function attempts to load the library “/system/vendor/lib/libPVROCL.so”. This is system specific. It has to point to the location on your device where the opencl library is located. It also loads the library with your InverseFilter functions in. This is the .so file you created when you added the NDK support to your project. Note that you may not add lib before it. When the .so file is named libInverseFilter.so you have to give InverseFilter as argument.
static {
try {
System.load(“/system/vendor/lib/libPVROCL.so”);
System.loadLibrary(“InverseFilter”);
}
catch (UnsatisfiedLinkError e) {
sfoundLibrary = false;
}
}
- The private void copyFile(final String f) function copy’s the kernel given as parameter to /data/data/application.name/app_execdir/
- The next three lines connects cpp functions to the java code
private native void initOpenCL (String kernelName);
private native void nativeInverseOpenCL (
Bitmap inputBitmap,
Bitmap outputBitmap
);
private native void shutdownOpenCL ();
- The other code is self explaining and will be explained by comments in the code itself.
The inversefilter.cpp file
- The loadProgram function copy’s the .cl kernel into a string so the string can be build as a program
- opencl_error_to_str makes the error codes more readable for humans
- Java_com_example_InverseFilter_MainActivity_initOpenCL is a function that can be called from the Java code. This function calls the initOpenCL code that sets up the opencl environment.
- Java_com_example_InverseFilter_MainActivity_shutdownOpenCL can also be called from Java and cleans up all the opencl data.
- nativeInverseOpenCL is going to put the kernel in the queue and is going to execute it.
I downloaded the code and I am struggling to run the example. Can you please tell me how should I proceed?
You have to give me more information. Do you get error codes? What are you exactly struggling with?
Hello, sorry, I finally managed to run the code. The problem was that I didn’t have the OpenCL PVR library on the board. Now it’s working as expected. Thank you!
No problem, could you post your error code for other people who have the same problem?
Hello,
The error I was getting was this:
“I/DEBUG (15742): BEFORE runOpencl
W/dalvikvm(15742): No implementation found for native Lcom/example/inversefilter/MainActivity;.initOpenCL:(Ljava/lang/String;)V”
Thank you!
Finding out which devices support for OpenCL on Android ?
It is a great initiative to build up OpenCL knowledge on Android. To even further support this we created an app that creates a list of all Android devices that support OpenCL. It detects and tests the OpenCL implementation. The big difference is that it does not just display the data, but it also posts the results directly to a cloud database. With the app you can directly search through the data. This enables the community/developer to easily pick a OpenCL capable device and see what the penetration is of OpenCL on Android. At the moment list is already interesting to browse through !
https://play.google.com/store/apps/details?id=com.maxtrium.opencldevicetest
Hope that you are willing to use this app and build an accurate list more quickly. Thanks for testing and contributing.
Hello
Ur tutorial is very useful.
In the Android.mk file what all changes i hv to make for my specific target.
Also what changes i should make to the LOCAL_PATH := $(call my-dir) i mean which directory i should call?
Thanks
[…] I have searched a lot on google but I am unable to find a good documentation about integrating OpenCl with Android. I referred this link: https://aplacetogeek.wordpress.com/android-with-opencl-tutorial/ […]
I get below error
05-15 11:28:56.854: E/AndroidRuntime(28539): java.lang.UnsatisfiedLinkError: No implementation found for void com.example.inversefilter.MainActivity.initOpenCL(java.lang.String) (tried Java_com_example_inversefilter_MainActivity_initOpenCL and Java_com_example_inversefilter_MainActivity_initOpenCL__Ljava_lang_String_2)
Thanks for OpenCL tutorials. These blogs like yours help a lot to us newbie programmers.