Writing an OpenGL ES Application using Qt on the TI Sitara AM3517 EVM



As the line between embedded and general-use devices has blurred, the demand for complex graphical applications on smaller devices has increased. The mobile gaming industry has exploded over the past few years, and most developers have moved beyond Snake and Sudoku. This has led to an increase in dedicated 3D hardware on mobile platforms.

This tutorial will cover creating a platform and application that includes the Qt UI Framework and accelerated OpenGL/ES graphics. In this tutorial we will:

  • Install a Pre-built Starting Point from the TimeSys Web Factory.
  • Install the TimeStorm integrated development environment (IDE).
  • Use TimeStorm IDE to build and run a demo application.
  • Use TimeStorm IDE to customize the demo application.

The tutorial will provide a brief introduction to building and executing an OpenGL application in Qt, but is not intended to teach the OpenGL standard itself.

Qt Overview

Qt (pronounced "cute") is a programming framework that is primarily geared towards graphical applications. It forms the basis of a number of projects, including the KDE desktop and the Meego platform. It is implemented in C++, although hooks for other languages do exist. The code is ostensibly platform-independent, although it must be re-compiled for different architectures. One advantage of this property is that a Qt application compiled on a host platform should look and feel the same as one built and run on the target system. This allows you to do most of your development and testing before even powering-up the target device.

Besides basic graphical elements, Qt also provides a number of modules that may be used to interface with more general Linux systems. The Phonon multimedia framework interacts with gstreamer for use in audio/video applications. Qt also provides libraries that can use accelerated 2D/3D libraries, such as OpenGL ES and OpenVG. Qt contains an implementation of the Webkit browser engine, as well. Qt is designed to give the developer a common interface to a wide variety of systems regardless of the operating system or platform.

The Timesys Factory will automatically configure Qt for your platform based on your package selection. For instance, if you include the tslib package in your build, Qt will include support for touchscreens. Selecting 3D libraries on certain platforms will enable OpenGL in Qt (if supported). The Factory's internal logic helps to make Qt configuration relatively simple.

OpenGL Overview

The Open Graphics Library (OpenGL) was designed in the early 90's to address the PC industry's move towards dedicated graphics hardware. Its purpose is to provide a common API for the various 2D and 3D hardware accelerators available from the different vendors. At that time, most of the similar APIs were proprietary and required licenses to use. In response to this, Silicon Graphics created OpenGL, which is completely open. It is currently maintained by a non-profit group, Khronos (www.khronos.org). While the API itself is open, the implementations are typically proprietary. This division allows anybody to implement the OpenGL standard, and thus take advantage of the large number of applications written against it. At the same time, it allows traditional software companies to fill the holes that open source software has not filled.

However, since embedded devices are typically both space- and power-constrained, a full-fledged graphical library would be much too resource intensive. To address this need, the OpenGL standard was expanded to include a new, stripped down specification for embedded systems called OpenGL ES.

OpenGL and OpenGL ES implementations provide the tools to create powerful graphical applications. At its most basic level, it converts high-level objects, such as lines, points, curves, and polygons, into raw pixel data that can be understood by the display hardware. Depending on the graphics accelerator and OpenGL implementation, some amount of this conversion is done in hardware, and some in software.


  • PC running a recent linux distribution
  • TI Sitara AM3517 EVM board
  • LinuxLink Desktop Edition

Some additional cables will be required for your board, see the Getting Started Guide for the board for more information.

Creating the platform

The first step is to create a base platform to install on the board that contains all necessary packages for building your application.

Using a Pre-built Starting Point

The easiest way to get started is to use a Pre-built Starting Point. Timesys has already created a Starting Point that contains the necessary packages to build and run the program in this tutorial. To download the Starting Point:

  • Open https://linuxlink.timesys.com in your browser
  • Login to LinuxLink
  • Click Download BSP/SDK in the top navigation area.
  • If you have a subscription for multiple processors, choose the TI-AM3517 processor
  • Under Pre-Built Starting Points section, click AM3517EVM Qt/Multimedia Starting Point.
  • Download am3517_evm-development-environment.sh
  • At a linux command prompt run:
    • chmod +x am3517_evm-development-environment.sh
    • ./am3517_evm-development-environment.sh

The console-based install program will start. After accepting the TimeSys EULA, you will be prompted for an install location. The default location is within your home directory. The installer will automatically create a sub-directory named am3517_evm . This directory will be referred to as <install_dir> in later sections of the document. Be aware that if another Starting Point or custom build for am3517_evm has already been installed, the installer will automatically move the old installation to prevent overlap.

Using a custom Factory build

It is also possible to use a custom platform built using either the Timesys Web Factory or Desktop Factory. For this tutorial, the platform must contain the following packages:

  • qt-embedded-linux
  • omap35x-graphics-sdk
  • tslib
  • glibc (required for graphics SDK)
  • dropbear (for TimeStorm remote access)
  • busybox (for basic system commands)
Note: It is possible to use sysvinit in combination with other packages instead of busybox to provide the basic system. Use the SystemV Init template in factory to replace busybox, if desired.

This document will assume that you installed the Pre-built Starting Point. If using a custom build, substitute the appropriate toolchain, RFS, and kernel image paths. For more information on using the Timesys Web Factory or Desktop Factory, see the Additional Information section at the end of this document.

Booting the platform

Follow the getting started guide to boot the kernel and RFS on the AM3517.


For the pre-built starting point the kernel image is <install_dir>/ uImage-2.6.32-ts-armv7l, and the RFS tar is <install_dir>/rootfs.tar.gz.

Set a root password on the board

Once the board is booted to a shell prompt, set the root password by typing "passwd". A password will be required for remote access from TimeStorm. This document will assume that you set the password to "password".

Installing TimeStorm with Qt integration

TimeStorm with Qt integration can be downloaded from https://linuxlink.timesys.com/ide. Be sure to get "TimeStorm for Qt". Unpack the archive into your home directory. You will need a license file for TimeStorm installed on your desktop computer. To generate and install a TimeStorm license, follow the instructions here: https://linuxlink.timesys.com/docs/manage_your_linuxlink_user_account#generate-license.

Starting TimeStorm

Before starting TimeStorm, you must export an environment variable that points to the location of the platform's qmake spec. Replace <install_dir> in the following with your actual installation directory.

export QMAKESPEC="<install_dir>/toolchain/share/mkspecs/qws/linux-timesys-g++/"

When TimeStorm starts for the first time, it will start with an empty workspace.

Adding Qt version to preferences

Once TimeStorm is started, you must add your Qt version under the preferences for TimeStorm. Select "Window->Preferences" in the TimeStorm menu and choose Qt in the Preference Dialog. Click the "Add..." button to add a new version. Name the version "Cross". Enter <install_dir>/toolchain/bin as "Bin Path" (replacing <install_dir> with your actual installation directory). "Include Path" will be filled in automatically. Click "Finish" to add this version.

Importing the demo project into TimeStorm

TimeSys provides the source for this demo in an archive that is available here: https://linuxlink.timesys.com/git?repo=timesys-omap35x-demos.git&view=refs&path=tags&h=master. Once you download the archive, unpack it using the command "tar xjf timesys-omap35x-demos-20101109.tar.bz2".

Choose "File->Import..." from the TimeStorm menu. Under the "Qt" folder, choose "Qt Project" and click "Next". The demo archive contains multiple demos. For this tutorial, browse to the file logo3d.pro within the logo3d directory that you extracted from the archive.

Building the demo project with TimeStorm

At this point you should be able to cross-build the demo source and produce an executable that can run on the target. Choose "Project->Build All" to build all projects in the workspace. A executable named " logo3d" will be created within the project.

Setting up TimeStorm to communicate with your board

Choose "Run->Hardware Targets" from the TimeStorm menu. If this menu item is not visible you may need to change the Workbench Perspective. In the upper right hand corner, click the icon to switch to the "C/C++ Perspective". The Hardware Targets menu item will be visible in this perspective. Once the target management dialog is open, click the "New" button to create a new target. Name the target "Demo". Change the download option to SCP. Enter the ip address of your target board. For the remaining fields enter Username: root, Password: password, Destination Directory: /root. Leave "Link to Execution" checked. Switch to the "Execute" tab and choose the SSH option. Now that your target is setup, click the "Check Link" button. A log will show the interaction with the board and indicate Pass or Fail for the test. Once the test has passed, close the Target Management dialog.

Launching the demo on your board

Choose "Run->Run As->C/C++ Remote Application" from the TimeStorm menu. This will create a new launch configuration. Fill out the launch configuration as follows. Once all tabs are filled out, click the "Run" button to launch the program.

Main Tab
Name: logo3d
Project: logo3d
C/C++ Application: logo3d

Arguments Tab
Project Arguments: -qws

Leave all other fields as default.

Remove all environment variables to start.

Add the following variables:

Debugger Tab
This tab is not required for run mode. If you want to use this launch configuration for debugging, you must choose an appropriate Toolchain to use as the debugger. See the TimeStorm manual for more information on managing TimeStorm toolchains.

Source Tab
No changes required.

Target Tab
Choose the "Demo" target in the drop-down.

Download Files Tab
The default of downloading the target program to the current directory (.) is good. No changes required.

Common Tab
No changes required.

Relaunching the demo

Once the launch configuration is setup, it can be re-used for each subsequent launch. Recently launched configurations are available under "Run->Run History". The dialog to create new configurations and edit/launch existing ones is available under "Run->Run Configurations". You will need to exit the previous launch of the demo before you can launch it again. Using the options you can quickly re-build and re-launch your project after any changes to test the out on the board. On each launch, the executable file will be re-downloaded so the latest changes can be tested.

Customizing the demo

At this point, you've been able to build the demo project and launch it on the board. The following sections will step through a simple modification to the logo3d program. We will add new menu, that has items to stop and start the rotation of the 3D model.

Editing the UI

We will add a new menu and two new menu items to stop and start the rotation of the rendering. First, let's add the menu items themselves. Open the logo3d.ui file (double click it in Project Explorer view). This will bring up the QT Designer Editor. The designer will show the user interface for the demo. Click the "Type Here" text in the menu bar within the UI editor. Once selected, type "Run" and hit enter to create a new menu named Run. When the Run menu is selected, you can click the "Type Here" entry within the menu to add items to the menu. Add "Go" and "Stop" menu items. Save the logo3d.ui file. Next time the demo is re-built and launched, it will include this new menu.

Add declarations to glwidget.h

Open the glwidget.h header file. This is the header for the main area of the demo that includes the 3d rendering. Under public slots, add two new methods stop() and go().

public slots:
    void stop(); /* add this line */
    void go();   /* and this line */
    void setScaling(int scale);
    void setLogo();

In addition, add a boolean private member, "running".

    bool running; /* add this line */
    GLuint  m_uiTexture;
    qreal   m_fAngle;
    qreal   m_fScale;

Add implementations to glwidget.cpp

Open the glwidget.cpp source file. In the GLWidget constructor, set the initial value of running to true.

GLWidget::GLWidget(QWidget *parent)
    : QGLWidget(parent)
    /* Initial state of widget */
    logoOn = true;
    frames = 0;
    m_showBubbles = true;
    ortho = false;
    running = true; /* add this line */

Implement the two new public methods to toggle the running member.

/* These are both entirely new methods. */
void GLWidget::stop() {
    running = false;

void GLWidget::go() {
    running = true;

Now edit the end of the paintGL() method to hold the angle steady when running == false.

/* enclose changing the angle in an if block */
if (running) {

    /* Change the rotation for the next frame. */
    m_fAngle += 1.0f;

Linking the UI to the implementation

Now we have two new menu items and we have code to implement them. The next step is to connect the two together. Qt includes a method connect(...) for just this purpose. The other menus are already being connected in the constructor for MainWindow. Open mainwindow.cpp in the editor and scroll to the MainWindow constructor to view the following lines:

/* Connect the actions in the menus to the approprate methods. */
QObject::connect(ui.actionShow_3D_Logo, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(setLogo()));
QObject::connect(ui.actionShow_2D_Texture, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(setTexture()));
QObject::connect(ui.actionShow_Bubbles, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(showBubbles(bool)));
QObject::connect(ui.slider, SIGNAL(valueChanged(int)),
    ui.glwidget, SLOT(setScaling(int)));
QObject::connect(ui.actionPerspective, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(viewPerspective()));
QObject::connect(ui.actionOrthographic, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(viewOrtho()));

We need to connected the "triggered" signal of the menu to the new slots we created. To do this, add the following lines to the MainWindow constructor:

QObject::connect(ui.actionGo, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(go()));
QObject::connect(ui.actionStop, SIGNAL(triggered(bool)),
    ui.glwidget, SLOT(stop()));

As we can see, the "ui" class has an automatically generated member for each of the menu items we added. To learn more about signals and slots in Qt, see the Qt Framework Documentation.

Rebuild and relaunch

Now we've made all of our changes. Pick "Project->Build All" to rebuild the executable with the changes. Once it has built successfully, re-launch the demo using "Run->Run History" menu item. You must exit the demo on the board before re-launching. Once launched, the demo will have a new menu allowing you to stop and start the rotation of the 3D model.

Additional Information