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

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.

For more information please leave a note in the comments.

Git link: https://github.com/degoossez/InverseOpenCL

OpenCL is a trademark of Apple Inc. used under license to the Khronos Group Inc. 
Comments
  1. AlexI says:

    I downloaded the code and I am struggling to run the example. Can you please tell me how should I proceed?

    • degoossez says:

      You have to give me more information. Do you get error codes? What are you exactly struggling with?

      • AlexI says:

        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!

      • degoossez says:

        No problem, could you post your error code for other people who have the same problem?

      • AlexI says:

        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!

  2. 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.

  3. aravind says:

    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

  4. […] 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/ […]

  5. ashokbugude says:

    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)

  6. Tushar Soni says:

    Thanks for OpenCL tutorials. These blogs like yours help a lot to us newbie programmers.

Leave a comment