HDMI stereo 3D & KMS

October 2nd, 2013 3 comments

If everything goes according to plan, KMS in linux 3.13 should have stereo 3D support. Should one be interested in scanning out a stereo frame buffer to a 3D capable HDMI sink, here’s a rough description of how those modes are exposed to user space and how to use them.

A reader not well acquainted with the DRM sub-system and its mode setting API (Aka Kernel Mode Setting, KMS) could start by watching the first part of Laurent Pinchart’s Anatomy of an Embedded KMS Driver or read David Herrmann’s heavily documented mode setting example code.

Stereo modes work by sending a left eye and right eye picture per frame to the monitor. It’s then up to the monitor to use those 2 pictures to display a 3D frame and the technology there varies.

There are different ways to organise the 2 pictures inside a bigger frame buffer. For HDMI, those layouts are described in the HDMI 1.4 specification. Provided you give them your contact details, it’s possible to download the stereo 3D part of the HDMI 1.4 spec from hdmi.org.

As one inevitably knows, modes supported by a monitor can be retrieved out of the KMS connector object in the form of drmModeModeInfo structures (when using libdrm, it’s also possible to write your own wrappers around the KMS ioctls, should you want to):

typedef struct _drmModeModeInfo {
    uint32_t clock;
    uint16_t hdisplay, hsync_start, hsync_end, htotal, hskew;
    uint16_t vdisplay, vsync_start, vsync_end, vtotal, vscan;

    uint32_t vrefresh;

    uint32_t flags;
    uint32_t type;
    char name[...];
} drmModeModeInfo, *drmModeModeInfoPtr;

To keep existing software blissfully unaware of those modes, a DRM client interested in having stereo modes listed starts by telling the kernel to expose them:

drmSetClientCap(drm_fd, DRM_CLIENT_CAP_STEREO_3D, 1);

Stereo modes use the flags field to advertise which layout the mode requires:

uint32_t layout = mode->flags & DRM_MODE_FLAG_3D_MASK;

This will give you a non zero value when the mode is a stereo mode, value among:

DRM_MODE_FLAG_3D_FRAME_PACKING
DRM_MODE_FLAG_3D_FIELD_ALTERNATIVE
DRM_MODE_FLAG_3D_LINE_ALTERNATIVE
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_FULL
DRM_MODE_FLAG_3D_L_DEPTH
DRM_MODE_FLAG_3D_L_DEPTH_GFX_GFX_DEPTH
DRM_MODE_FLAG_3D_TOP_AND_BOTTOM
DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF

User space is then responsible for choosing which stereo mode to use and to prepare a buffer that matches the size and left/right placement requirements of that layout. For instance, when choosing Side by Side (half), the frame buffer is the same size as its 2D equivalent (that is hdisplay x vdisplay) with the left and right images sub-sampled by 2 horizontally:

sbsh

Side by Side (half)

Other modes need a bigger buffer than hdisplay x vdisplay. This is the case with frame packing, where each eye has the the full 2D resolution, separated by the number of vblank lines:

Frame Packing

Frame Packing

Of course, anything can be used to draw into the stereo frame buffer, including OpenGL. Further work should enable Mesa to directly render into such buffers, say with the EGL/gbm winsys for a wayland compositor to use. Of course, fun profit would the last step:

PS3_3D2

A 720p frame packing buffer from the game WipeOut

Behind the scene, the kernel’s job is to parse the EDID to discover which stereo modes the HDMI sink supports and, once user-space instructs to use a stereo mode, to send infoframes (metadata sent during the vblank interval) with the information about which 3D mode is being sent.

A good place to start for anyone wanting to use this API is testdisplay, part of the Intel GPU tools test suite. testdisplay can list the available modes with:

$ sudo ./tests/testdisplay -3 -i
[...]
  name refresh (Hz) hdisp hss hse htot vdisp vss vse vtot flags type clock
[0]  1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 0x5 0x48 148500
[1]  1920x1080 60 1920 2008 2052 2200 1080 1084 1089 1125 0x5 0x40 148352
[2]  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 0x15 0x40 74250
[3]  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 0x20015 0x40 74250 (3D:SBSH)
[4]  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 0x15 0x40 74176
[5]  1920x1080i 60 1920 2008 2052 2200 1080 1084 1094 1125 0x20015 0x40 74176 (3D:SBSH)
[6]  1920x1080 50 1920 2448 2492 2640 1080 1084 1089 1125 0x5 0x40 148500
[7]  1920x1080i 50 1920 2448 2492 2640 1080 1084 1094 1125 0x15 0x40 74250
[8]  1920x1080i 50 1920 2448 2492 2640 1080 1084 1094 1125 0x20015 0x40 74250 (3D:SBSH)
[9]  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 0x5 0x40 74250
[10]  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 0x1c005 0x40 74250 (3D:TB)
[11]  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 0x4005 0x40 74250 (3D:FP)
[...]

To test a specific mode:

$ sudo ./tests/testdisplay -3 -o 17,10
  1920x1080 24 1920 2558 2602 2750 1080 1084 1089 1125 0x1c005 0x40 74250 (3D:TB)

To cycle through all the supported stereo modes:

$ sudo ./tests/testdisplay -3

testdisplay uses cairo to compose the final frame buffer from two separate left and right test images.

Categories: Kernel

Working on more than one line with sed’s ‘N’ command

June 3rd, 2013 No comments

Yesterday I was asked to help solving a small sed problem. Considering that file (don’t look too closely on the engineering of the defined elements):

<root>
  <key>key0</key>
  <string>value0</string>
  <key>key1</key>
  <string>value1</string>
  <key>key2</key>
  <string>value2</string>
</root>

The problem was: How to change value1 to VALUE!. The problem here is that you can’t blindly execute a s command matching <string>.*</string>.

Sed maintains a buffer called the “pattern space” and processes commands on this buffer. From the GNU sed manual:

sed operates by performing the following cycle on each line of input: first, sed reads one line from the input stream, removes any trailing newline, and places it in the pattern space. Then commands are executed; each command can have an address associated to it: addresses are a kind of condition code, and a command is only executed if the condition is verified before the command is to be executed.

When the end of the script [(list of sed commands)] is reached, unless the -n option is in use, the contents of pattern space are printed out to the output stream, adding back the trailing newline if it was removed.3 Then the next cycle starts for the next input line.

So the idea is to first, use a /pattern/ address to select the the right <key> line, append the next line to the pattern space (with the N command) and finally run a s command on the buffer now containing both lines:

  <key>key1</key>
  <string>value1</string>

And so we end up with:

$ cat input 
<root>
  <key>key0</key>
  <string>value0</string>
  <key>key1</key>
  <string>value1</string>
  <key>key2</key>
  <string>value2</string>
</root>
$ sed -e '/<key>key1<\/key>/{N;s#<string>.*<\/string>#<string>VALUE!<\/string#;}' < input 
<root>
  <key>key0</key>
  <string>value0</string>
  <key>key1</key>
  <string>VALUE!</string
  <key>key2</key>
  <string>value2</string>
</root>
Categories: misc, Unix

A git pre-commit hook to check the year of copyright notices

January 13th, 2013 1 comment

Like every year, touching a source file means you also need to update the year of the copyright notice you should have at the top of the file. I always end up forgetting about them, this is where a git pre-commit hook would be ultra-useful, so I wrote one:

#
# Check if copyright statements include the current year
#
files=`git diff --cached --name-only`
year=`date +"%Y"`

for f in $files; do
    head -10 $f | grep -i copyright 2>&1 1>/dev/null || continue
    
    if ! grep -i -e "copyright.*$year" $f 2>&1 1>/dev/null; then
        missing_copyright_files="$missing_copyright_files $f"
    fi
done

if [ -n "$missing_copyright_files" ]; then
    echo "$year is missing in the copyright notice of the following files:"
    for f in $missing_copyright_files; do
        echo "    $f"
    done 
    exit 1
fi

Hope this helps!

Categories: Uncategorized

Extracting part of files with sed

April 10th, 2012 1 comment

For reference for my future self, a few handy sed commands. Let’s consider this file:

$ cat test-sed
First line
Second line
--
Another line
Last line

We can extract the lines from the start of the file to the marker by deleting the rest:

$ sed '/--/,$d' test-sed 
First line
Second line

a,b is the range the command, here d(elete), applies to. a and b can be, among others, line numbers, regular expressions or $ for end of the file. We can also extract the lines from the marker to the end of the file with:

$ sed -n '/--/,$p' test-sed 
--
Another line
Last line

This one is slightly more complicated. By default sed spits all the lines it receives as input, '-n' is there to tell sed not to do that. The rest of the expression is to p(rint) the lines between -- and the end of the file.

That’s all folks!

Categories: Unix

A simple autotool template

September 17th, 2011 2 comments

Every now and then, you feel a big urge to start hacking on a small thingy and need to create Makefiles for it. Turns out that the autotools won’t be that intrusive when we are talking about small programs and you get do a reasonable job with a few lines, first the configure.ac file:

# autoconf
AC_PREREQ(2.59)
AC_INIT([fart], [0.0.1], [damien.lespiau@gmail.com])
AC_CONFIG_MACRO_DIR([build])
AC_CONFIG_AUX_DIR([build])
AC_CONFIG_SRCDIR([fart.c])
AC_CONFIG_HEADERS([config.h])

# automake
AM_INIT_AUTOMAKE([1.11 -Wall foreign no-define])
AM_SILENT_RULES([yes])

# Check for programs
AC_PROG_CC

# Check for header files
AC_HEADER_STDC

AS_COMPILER_FLAGS([WARNING_CFLAGS],
		  ["-Wall -Wshadow -Wcast-align -Wno-uninitialized
		   -Wno-strict-aliasing -Wempty-body -Wformat -Wformat-security
		   -Winit-self -Wdeclaration-after-statement -Wvla
		   -Wpointer-arith"])

PKG_CHECK_MODULES([GLIB], [glib-2.0 >= 2.24])

AC_OUTPUT([
  Makefile
])

and then Makefile.am:

ACLOCAL_AMFLAGS = -I build ${ACLOCAL_FLAGS}

bin_PROGRAMS = fart

fart_SOURCES =	fart.c
fart_CFLAGS  = $(WARNING_CFLAGS) $(GLIB_CFLAGS)
fart_LDADD   = $(GLIB_LIBS)

After that, it’s just a matter of running autoreconf

$ autoreconf -i

and you are all set!

So, what do you get for this amount of lines?

  • The usual set of automake targets, handy! (“make tags” is so under used!) and bonus features (out of tree builds, extra rules to reconfigure/rebuild the Makefiles on changes in configure.ac/Makefile.an, …)
  • Trying to make the autoconf/automake discreet (putting auxiliary files out of the way, silence mode, automake for non GNU projects)
  • Some decent warning flags (tweak to your liking!)
  • autoreconf cooperating with aclocal thanks to ACLOCAL_AMFLAGS and coping with non standard locations for system m4 macros

I’ll maintain a git tree to help bootstrap my next small hacks, feel free to use it as well!

Categories: misc

Clutter on Android: first results

May 31st, 2011 17 comments

With the release of Android 2.3, there’s a decent way to integrate native applications with the NativeActivity class, an EGL library, and some C API to expose events, main loop, etc. So? how about porting Clutter to it now that it looks actually feasible? After a few days of work, the first results are there, quite promising!

There’s still a fairly large number of items in my TODO before being happy with the state of this work, the most prominent items are:

  • Get a clean up pass done to have something upstreamable, this includes finishing the event integration (it receives events but not yet forward them to Clutter),
  • Come up with a plan to manage the application life cycle and handle the case when Android destroys the EGL surface that you were using (probably by having the app save a state, and properly tear down Clutter).,
  • While you probably have the droid font installed in /system/fonts, this is not part of the advertised NDK interface. The safest choice is to embed the font you want to use with your application. Unfortunately fontconfig + freetype + pango + compressed assets in your Android package don’t work really well together. Maybe solve it at the Pango level with a custom “direct” fontmap implementation that would let you register fonts from files easily?
  • What to do with text entries? show soft keyboard? Mx or Clutter problem? what happens to the GL surface in that case?
  • Better test the GMainLoop/ALooper main loop integration (esp. adding and removing file descriptors),
  • All the libraries that Clutter depends on are linked into a big .so (which is the Android NDK application). It results in a big .so (~5 MB, ~1.7 MB compressed in the .apk). That size can be dramatically reduced, sometimes at the expense of changes that will break the current API/ABI, but hell, you’ll be statically linking anyway,
  • Provide “prebuilt libraries”, ie. pre-compiled libraries that makes it easy to just use Clutter to build applications.
Categories: Android, Clutter

A simple transition effect with Clutter

May 10th, 2011 1 comment

When doing something with graphics, your first need an idea (granted, as with pretty much everything else). In this case, a simple transition that I’ve seen somewhere a long time ago and I wanted to reproduce with Clutter.

The code is available in a branch of a media explorer I’m currently working on. A few bullet points to follow the code:

  • As the effect needs a “screenshot” of a Clutter scene to play with. You first need to create a subclass of ClutterOffscreenEffect as it does the work of redirecting the painting of a subtree of actors in an offscreen buffer that you can  reuse to texture the rectangles you’ll be animating in the effect. This subclass has a “progress” property to control the animation.
  • Then actually compute the coordinates of the grid cells both in screen space and in texture space. To be able to use cogl_rectangles_with_texture_coords(), to try limit the number of GL calls (and/or by the Cogl journal and to ease the animation of the cells fading out, I decided to store the diagonals of the rectangle in a 1D array so that the following grid:

a 5x5 grid with one color per diagonal line

is stored as:

A 1D array with all the diagonals of the grid

  • ::paint_target()looks at the “progress” property, animate those grid cells accordingly and draw them. priv->rects is the array storing the initial rectangles, priv->animated_rects the animated ones and priv->chunks stores the start and duration of each diagonal animation along with a (index, length) tuple that references the diagonal rectangles in priv->rects and priv->animated_rects.

Some more details:

  • in the ::paint_target() function, you can special case when the progress is 0.0 (paint the whole FBO instead of the textured grid) and 1.0 (don’t do anything),
  • Clutter does not currently allow to just rerun the effect when you animate a property of an offscreen effect for instance. This means that when animating the “progress” property on the effect, it queues a redraw on the actor that end up in the offscreen to trigger the effect ::paint_target() again. A branch from Neil allows to queue a “rerun” on the effect to avoid having to do that,
  • The code has some limitations right now (ie, n_colums must be equal to n_rows) but easily fixable. Once done, it makes sense to try to push the effect to Mx.
Categories: Clutter

The GStreamer conference from a Clutter point of view

November 16th, 2010 No comments

Two weeks ago I attended the first GStreamer conference, and it was great. I won’t talk about the 1.0 plan that seems to take shape and looks really good but just what stroke me the most: Happy Clutter Stories and an Tale To Be Told to your manager.

Let’s move on the Clutter stories. You had a surprising number of people mixing GStreamer and Clutter, two talks especially:

  • Florent Thiery founder of Ubicast talked about one of their products: a portable recording system with quite a bit of bling (records the slides, movement detection with OpenCV, RoI, …). The system was used to record the talks on the main track. Now, what was of particular interest for me is that the UI to control the system is entirely written with Clutter and python. They have built a whole toolkit on top of Clutter, in python, called candies/touchwizard and written their UI with it, cooool.
  • A very impressive talk from the Tanberg (now Cisco) guys about their Movi software, video conferencing at its finest. It uses GStreamer extensively and Clutter for its UI (on Windows!). They said that about 150,000 copies of Movi are deployed in the wild. Patches from Ole André Vadla Ravnås and Haakon Sporsheim have been flowing to Clutter and Clutter-gst (win32 support).

As a side note, Fluendo talked about their Open Source, Intel founded, GStreamer codecs for Intel CE3100/CE4100. This platform specificities are supported natively by Clutter (./configure –with-flavour=cex100) using the native EGL winsys called “GDL” and evdev events coming from the kernel. More on this later :p

A very interesting point about those success stories is that the companies and engineers working with open source software to build their applications, sometimes with parts heavily covered by patents, while contributing back to the ecosystem that allowed to build those applications in the first place. Contributing is done at many levels: directly patches but also feedback on the libraries/platform (eg. input for GStreamer 1.0). And guess what? It works! To me, that’s exactly how the GNOME platform should be used to build proprietary applications: build on top and contribute back to consolidate the libraries. I’d go as far as saying that contributing upstream is the best way to share code inside the same big corporation. Such companies are always very bad a cooperating between divisions.

Categories: Clutter, GNOME

g_object_notify_by_pspec()

September 28th, 2010 No comments

Now that GLib 2.26.0 is out, it’s time to talk about a little patch to GObject I’ve written (well, the original idea was born while looking at it with Neil): add a new g_object_notify_by_pspec() symbol to GObject. As shown in the bug it can improve the notification of GObject properties by 10-15% (the test case tested was without any handler connected to the notify signal).

If you can depend on GLib 2.26, consider using it!

Categories: GNOME

Learning how to draw

June 3rd, 2010 6 comments

 I can’t draw. I’ve never been able to. Yet, for some reason, I decided to give it a serious try, buy a book to guide me in that journey (listening to an advice from pippin, yeah I know, crazy). The first step was, like a pilgrim walking to a sacred place, to go and buy some art supplies, which turned out to be a really enjoyable experience.

The first thing you have to do is a snapshot of your skills before reading more of the book to be able to do a “before/after” comparison. I thought it was quite hard, but was surprised that the result was all right, by my low standards anyway. You have to do 3 drawings: a self-portrait, looking at yourself in a mirror, a person/character drawn from memory without a visual help and your hand.

The next exercise is there to make you realize that you’ll have to forget everything you know and re-learn how to see to draw. It’s about copying drawings upside down, copying it curve by curve without associating any meaning to what you are doing. The result is quite surprising as you can see on the left. Now it’s a matter to learn how to do that without resorting to the upside down trick.

It’s only the beginning of a long journey, so many things can go wrong, but worth giving it a try!

Categories: drawing