2013-04-15

RetroArch on ODROID-U2 (with hardware acceleration, yes!)

ODROID-U2

I have tried to run decent console emulation on Raspberry Pi, without success.

So I recently got my hands on an ODROID-U2 (that comes with a respectable more powerful hardware) and that can potentially carry out my console emulation and preservation dreams.

In the below pictures you can see it shily coming out of the box:

A small package to rule them all

Better use a fan if you want to overclock this little beast!


















This development board comes with 4 ARM Cortex A9 CPUs and the Mali 400 GPU (more about this later); when choosing a development board you should really pay attention to the planned shelf life, the expected community size and the GPU driver support. There's really nothing else that will matter more for you than the open source/closed source drivers.

In these regards the vendor, Hardkernel, gets my kudos as I see they are working hard to deliver the best to the community that's aggregating around ODROID (but keep in mind that it's not yet very big right now, so weaponize yourself for all cases!).

As far as I understood the driver is partly closed-source, for longer term dreams (full open source Mali400 driver) you could check out the Lima project, although nothing usable is available at time of writing.

I was expecting some geeky adventures to achieve my goal, and I wasn't disappointed. In the last few days I had to learn all my way through forums, IRC, blog posts and generally fragmented and incomplete information - but finally after a few strong machete cuts I have been able to see the light!

Do-it-yourself

I didn't want to release the result of my efforts as Debian packages or complete SD images (update: I did!), so I will provide you with a walkthrough and the necessary steps.
The reasons are:
  • possible licensing concerns, it is not fully clear to me if I am entitled to release these (for example the vendor-provided drivers);
  • releasing concerns, once you release something you should take care to mantain it;
  • philosophy: if you are using a development board you should really get in touch with all the layers to better understand how things work.

I used this blog post as starting point and also other resources here and there; in this blog post I am focusing only on SD card booting and ODROID-U2 specifically.
Although I didn't follow it originally, you might also want to read the official post about ODROID-U2 and then come back for the other steps about Xorg configuration and RetroArch.

Update 7 May 2013: I released neagix' excellent (and unofficial) Debian Wheezy for Development&Emulation (with X11 hardware acceleration). I advise to use the image as information in this post might be obsolete.

Prerequisites

In the following steps I aim to provide an aid at getting a fully functional RetroArch on ODROID-U2.

If you can use debian apt-get/aptitude and SSH you should be able to follow it. Also you might want to use Google in case of some strange error that is not covered by this tutorial.

This is not a from-scratch tutorial for complete newbies, so please don't expect so.

Update 25-April-2013: the more advanced cores will not exhibit a great performance, but you should be fine with emulation of 16bit (and less) consoles

Step 1 - booting the device


Insert the microSD in a Linux PC, then check with dmesg|tail what is the dev node. On my PC it was /dev/mmcblk0. Please take note of the root device, not the partition device (that would be /dev/mmcblk0p1 and so on).

Now download a prepared ODROID-U2 Ubuntu image and flash it to the microSD card.


wget http://www.mdrjr.net/odroid/mirror/ODROID-U2/Ubuntu/odroidu2_20121231-linaro-ubuntu-desktop-uSD.zip
7z x odroidu2_20121231-linaro-ubuntu-desktop-uSD.zip
sudo dd if=odroidu2_20121231-linaro-ubuntu-desktop-uSD.img of=/dev/mmcblk0 bs=24M

Update 14 July 2013: use instead the odroid-wheezy-retro image, instructions here

At this point I advice to eject/insert the microSD card, then run the following:

sudo resize2fs /dev/mmcblk0p2

This will resize the linux partition to the maximum available space on your SD card.

Before proceeding to next step you might want to mount the /dev/mmcblk0p2 partition and change some files there for easier initial setup (like wired network, for example).

And now...ready for the show! Put the SD card back in the ODROID device and boot your device.

Step 2 - First boot operations

The first time you boot you should connect through SSH to your device, default users have the following usernames/passwords:

root / root
user / user

As first operation change those passwords, and possibly you might want to use usermod to rename 'user' to something else.

After that re-generate the SSH keys:

sudo rm /etc/ssh/*_key /etc/ssh/*.pub
sudo dpkg-reconfigure openssh-server

Modify /etc/rc.local by adding these lines before the last exit 0 line (reported for reference):

cpufreq-set -g ondemand -d 200Mhz
chown .video /dev/ump
chown .video /dev/mali
chmod 0660 /dev/ump
chmod 0660 /dev/mali


Install now cpufrequtils package if you are not going to do Step 3.

Also make sure that your user is in the following groups:
user adm cdrom sudo audio dip video plugdev lpadmin pulse

Step 3 - Trimming down the installation (optional)

In this optional step (that is also untested!) I explain how to remove a lot of packages that come by default installed with Linaro Ubuntu, you can skip it if you prefer to customize it by yourself.

Download odroid-u2-slim-package-selections.txt and then restore the selections by running:

sudo apt-get install dselect
sudo dpkg --clear-selections
sudo dpkg --set-selections < odroid-u2-slim-package-selections.txt
sudo apt-get -y update
sudo apt-get dselect-upgrade

A lot of packages will be removed and you should get XFCE installed in place of Unity (although I advise using LXDE).

When you have finished, please run:

sudo dpkg-reconfigure -a

To go through all necessary configuration steps.

Please note that the display manager will also not work! So don't expect any output on HDMI yet. Real men/women use terminal ;)

Step 4 - Getting the bare metal hardware (acceleration)!

It is necessary to update the kernel to use proper Mali400 hardware-accelerated GPU drivers.

We will use the 13th February release:

wget http://dn.odroid.com/Ubuntu_U2/20130213/linux-3.0.63-odroidu2_20130213.tar.gz
tar xvfz linux-3.0.63-odroidu2_20130213.tar.gz
cd linux-3.0.63-odroidu2_20130213
rm fstab
sudo ./install.sh


At this point a reboot is necessary to make the new kernel effective, I will ask you for such reboot at a later step.

Now we will install the vendor-provided mali400 drivers:

wget http://dn.odroid.com/MALI400_R3P2/20130222/mali_packages.tar.gz
tar xvfz mali_packages.tar.gz
cd mali_packages
sudo dpkg -i mali400_2.1-13_armhf.deb mali400-dev_2.1-13_armhf.deb xf86-video-mali_1.0.1-7_armhf.deb
sudo rm -rf /usr/lib/arm-linux-gnueabihf/mesa-egl /usr/share/X11/xorg.conf.d/99-hkl_mali.conf


Please note that we are removing 2 objects here:
  • mesa-egl, because would prevent you from getting the Mali EGL acceleration
  • 99-hkl_mali.conf, that is the default Mali configuration and consitutes just a source of confusion (it always overrides your xorg.conf)

Step 5 - Build your own xf86-video-mali (optional)

This step is optional e.g. you don't need it, I am keeping it here for reference.
Install xorg-dev, xutils-dev, automake, autoconf and libtool, then download the sources from ARM website (I've used release of 11 March 2013 called Linux EXA/DRI2 and X11 Display Drivers r3p2-01rel1), then enter the proper directory and run the following script build.sh:

#!/bin/bash
set -e
ODFLAGS="-DUMP_LOCK_ENABLED=1 -mfpu=neon -mfloat-abi=hard"

autoreconf -rfi
CFLAGS="$ODFLAGS" ./configure --prefix=/usr
CFLAGS="$ODFLAGS" ASFLAGS="-mfpu=neon -mfloat-abi=hard" make -j5

This will quickly deliver an usable xf86-video-mali that you can use in conjunction with the mali400 driver package from step 4.

NOTE: on some older versions of autoconf you can only do autoconf -fi

Step 6 - Starting XFCE4

If you have not before, reconfigure X11 to allow any user:

sudo dpkg reconfigure x11-common

Make sure that "Anybody" is selected and save.

Now let's setup /etc/X11/xorg.conf:

Section "Device"
        Identifier "Mali-Fbdev"
        Driver  "mali"
        Option  "fbdev"           "/dev/fb6"
        Option  "DRI2"            "true"

        Option  "DRI2_PAGE_FLIP"  "false"
        Option  "DRI2_WAIT_VSYNC" "false"

        Option  "UMP_CACHED"      "true"
        Option  "UMP_LOCK"        "false"
EndSection

Section "Screen"
        Identifier   "Mali-Screen"
        Device       "Mali-Fbdev"

EndSection

Section "DRI"
        Mode 0666
EndSection


Please note the DRI2_PAGE_FLIP setting above, set to disabled. If you enable it your applications performance will start to thrash after a couple of minutes. For example RetroArch had a constantly falling down FPS because of this. I have also experienced instant crashes (SEGFAULT) with fullscreen applications using it.
Update 13 July 2013: The segfault was due to using the setting "DefaultDepth 16", and DRI2_PAGE_FLIP does no more show a negative behaviour, actually a positive one - so feel free to enable it. VSYNC can be enabled but it's not effective, see also this post

Update 05 May 2013: I have provided with a more recent version of xorg.conf here in this post, that adds only turning off DPMS

Now we're ready again. Reboot the system (and check that you are running kernel 3.0.63 through uname -a), then run:

startxfce4

XFCE4 will display in all its glory. Your Xorg.0.log will contain:

(EE) AIGLX error: dlopen of /usr/lib/arm-linux-gnueabihf/dri/Mali DRI2_dri.so failed (/usr/lib/arm-linux-gnueabihf/dri/Mali DRI2_dri.so: cannot open shared object file: No such file or directory)
(EE) AIGLX: reverting to software rendering
(II) AIGLX: Screen 0 is not DRI capable
(II) AIGLX: Loaded and initialized swrast
(II) GLX: Initialized DRISWRAST GL provider for screen 0

You can completely disregard the above as hardware acceleration will instead work, and we are now going to verify it.

Bit depth

By specifying a DefaultDepth of 24 you will get a segfault right after the GET_UMP_SECURE_ID_BUF1 line in the log.

Update 18 April 2013: libv has personally sent a patch to mdrjr so that HDMI output up to 32bit will be supported, stay tuned! :)
Update 21 April 2013: by recompiling the 3.0 kernel (provided by Hardkernel) with CONFIG_VIDEO_EXYNOS_24_FORCE=y you can use HDMI in 24 bit mode, many thanks to libv for the patch

Step 7 - Rotating horses and crates!

Now it's time to see hardware acceleration in action.

You can use 3 programs to check the status of hadware acceleration on your ODROID:
  • glxgears, a classic tool to test GLX
  • es2gears, for ES2 testing
  • glmark2-es2, that is actually a benchmark and you will score 92 if everything went right
If your hardware acceleration is enabled you will see FPS above 100 in all of them (although not in all glmark2-es2 tests).

If you verify hardware acceleration to be working, feel free to continue to step 7.

Step 8 - Time for RetroArch

Unfortunately I have not been able to use KMS with Mali 400, I think it's not supported, but I managed to use RetroArch in accelerated X11.

Let's download and compile RetroArch:

git clone https://github.com/Themaister/RetroArch.git
mv RetroArch retroarch 
cd retroarch
CFLAGS="-mfpu=neon -mfloat-abi=hard" ./configure --enable-x11 --enable-gles --enable-alsa --disable-oss --disable-jack --disable-pulse --disable-kms --disable-vg
ASFLAGS="-mfpu=neon -mfloat-abi=hard" make -j5


If you get gcc errors about virtual memory exhausted or other weird corruptions, try to set the governor to userspace for the length of compilation operations.

At this point you should have a compiled retroarch binary, we are ready for Step 8.

NOTE: I have only a small patch, you might want to use it in you have an error there (compiling with VG support):
diff --git a/gfx/vg.c b/gfx/vg.c
index c5b92e0..bbfc3a8 100644
--- a/gfx/vg.c
+++ b/gfx/vg.c
@@ -99,7 +99,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
    RARCH_LOG("Detecting screen resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight);

    vg->driver->swap_interval(video->vsync ? 1 : 0);
-   vg->driver->update_window_title(true);
+   vg->driver->update_window_title();

    vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565;
    vg->mKeepAspect = video->force_aspect;
@@ -387,7 +387,7 @@ static bool vg_frame(void *data, const void *frame, unsigned width, unsigned hei
    if (msg && vg->mFontsOn)
       vg_draw_message(vg, msg);

-   vg->driver->update_window_title(false);
+   vg->driver->update_window_title();

    RARCH_PERFORMANCE_STOP(vg_fr);
    vg->driver->swap_buffers();


Step 9 - We need a core


RetroArch cannot do anything if you have no cores. Let's build snes9x-next.

git clone https://github.com/libretro/snes9x-next.git
cd snes9x-next
mv snes9x-next libretro-snes9x-next
make -j5 -f Makefile.libretro


Now you will have snes9x_next_libretro.so, take note of the path to this file by copying the output of:

ls $PWD/snes9x_next_libretro.so

Now let's go back into retroarch's working directory and run RetroArch:

DISPLAY=:0 ./retroarch -L /your/complete/path/snes9x_next_libretro.so SNES9X\ Demo\ V1.16\ \(PD\).smc

If you are typing this into an XFCE terminal, then you can omit the DISPLAY=:0 part.

Now you should see the ROM being emulated with FPS count on the window title bar.
You can install the other cores manually (one by one) or by using the libretro-super scripts.

Step 10 - Packing up together


It is advised to use different CPU settings when running retroarch; for this reason I use a script similar to this snes9x.sh:

#!/bin/bash
sudo cpufreq-set -g ondemand --min 1.6Ghz
DISPLAY=:0 ./retroarch -L /your/complete/path/snes9x_next_libretro.so $@
sudo cpufreq-set -g ondemand --min 200Mhz

This script will effectively change the minimum frequency when you are using RetroArch, and then restore it back when you exit (unless you use Ctrl+C, so don't!).

You can even use a higher minimum frequency if you experience slowdowns, however please pay attention that a fan might be needed when overclocking! Please refer to official ODROID information regarding this.

Step 11

SNES9X Demo ROM (Public Domain)

Enjoy it! :)

Conclusions


I think that ODROID-U2 has a lot of potential, I plan to do other interesting things in future with this development board.

Please let me know your feedback if there are errors or possibility of improvements by using the official ODROID forums discussion thread.

18 comments:

  1. What is the resulting Color Depth on X11? Can you post your glxinfo?

    ReplyDelete
  2. It's 16bit, if I enable DefaultDepth 24 I get a segfault :(

    ReplyDelete
    Replies
    1. Yeah, this is the problem... Current drivers are doing only 16 bit and there are rumors here and there that this is a hardware limitation for HDMI.
      Same time the Android on the same hardware doing perfectly well with more colors, so something smells fishy here.

      Delete
    2. You mean that apparently only way to get 24bit colour depth is to use the LCD port (not available on U2)?

      Delete
    3. Yup, now it is so.
      First:
      http://com.odroid.com/sigong/prev_forum/t2525n-compatibility-between-ubuntu-u2-and-x2-versions.html
      Second:
      http://forum.odroid.com/viewtopic.php?f=10&t=982&p=5471

      Delete
    4. yes, mdrjr is working on it...I am going to test kernel 3.8 to help him out

      Delete
  3. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. I saw you removed the comment :)
      Can't find that model you mentioned. I am also not very experienced with ODROID, as you can see I recently received it.
      I think what I would do in your shoes is to ask specifically to the vendors, and make the most precise questions you can!

      In my case I did some checks before ordering and so far it turned out matching my expectations quite well (there is still to see what will happen in future e.g. regarding driver support)

      Delete
  4. Also please note that your link to odroid-u2-slim-package-selections.txt is a link nowhere.

    ReplyDelete
    Replies
    1. fixed. actually I am planning to put all these files on github for ease of access

      Delete
  5. Hi!

    at which subdirectories' level I must execute build.sh script? I got autoreconf: command not found... you can see here below:

    linaro@linaro-ubuntu-desktop:~/Downloads/DX910-SW-99003-r3p2-01rel1/x11/xf86-video-mali-0.0.1/src$ sudo ./build.sh
    ./build.sh: line 4: autoreconf: command not found


    thanx!

    ReplyDelete
  6. 1. I said to use the forums :)
    2. that step is optional, you don't need it
    3. when you have a missing command on Debian, look for the package that contains it. Google is your friend

    ReplyDelete
  7. So tried to use parts of your tutorial that would benefit me (steps 1 - 8). When I got to step 3 (I know it is untested), found some issues. I would follow step 3 - 6, reboot the system, but then the board would not display on HDMI. The fan also did not power up, however, I did notice that I could ssh into the board. I did this twice, once from a previously setup image that had been running other applications, and a second time with a clean image through your description. Both times, still black screen with no power on fan.

    I did confirm that the kernel seemed to have been upgraded. Any ideas?

    ReplyDelete
  8. At step 6 it is required to run 'startxfce4', that should start Xorg and output through HDMI

    Regarding the fan: I have no idea

    ReplyDelete
  9. You aren't kidding when you say you have to find your own info on it and piece it all together. I got one about two weeks ago and had the stock android and then CM10.1 on it, but something screwed up and now I can't boot to the recovery no matter what so it's proving to be a real challenge to get a current Android version to run (I can get old builds to run via the dd command since they're image files, but that's about it).

    ReplyDelete
    Replies
    1. Yes, I had the same feeling. Information is fragmentary and sometimes contradictory. That's also why I wanted to document how I got it running with hardware acceleration; unfortunately when documentation is not good enough you can be misled by vague statements, even if you have some experience.

      However I have no experience with Android, I completely skipped trying it - although I might give it a try in future.

      Delete
  10. This comment has been removed by a blog administrator.

    ReplyDelete
    Replies
    1. Sorry Robert didn't want to delete your comment! I am still getting used to Blogspot :\

      It's not an Xubuntu-specific issue, please try with the SNES9X public domain ROM

      Delete