PowerVR SGX 530 does NOT support Depth Textures

If you download the PowerVR SDK for the TI OMAP3430 which is used in the N900, you will find a nice shadow mapping example which uses the OES_depth_texture extension. You can even run this example using the included emulator using the SGX 530 profile.

However if you try to run your code on the actual device you will soon find out that it does NOT support OES_depth_texture. This is quite surprising as the device supports OES_texture_float and OES_depth24, so depth_texture should be not too hard to implement.

But the situation is the same on the iPhone 3GS, which uses the same hardware. This leads me to believe that this is not just a driver limitation.

However here is a workaround using a ordinary RGBA texture and byte packing:

const highp vec4 packFactors = vec4(256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0);
const highp vec4 cutoffMask  = vec4(0.0, 1.0/256.0, 1.0/256.0, 1.0/256.0);

void main() {
    highp vec4 packedVal = vec4(fract(packFactors*gl_FragCoord.z));
    gl_FragColor = packedVal - packedVal.xxyz*cutoffMask;
}

the packFactors vector basically contains the 3 necessary byte wise shifts to the left. The call to fract() cuts off anythig which is to the left of the byte we want to save and subtracting packedVal.xxyz*cutoffMask cuts off anything to the right of the byte.

The cutting is necessary as we are dealing with floating-point here and we dont know how the hardware selects the value that should go in.

The future of the radeon OSS driver is bright

recently I had to switch to the gallium based r300g driver to get GLSL support, which I need for a project. And I must say I am quite impressed. It exposes all extensions necessary for OpenGL 2.1 and already seems quite stable. Although some extensions are not implemented properly yet like NPOT as they need special workarounds I think this will eventually become the most feature complete driver for radeon hardware.

But although currently compiz works as do most of the OpenGL programs, I would not reccomend using r300g for production use as it is still really slow. I know glxgears is not a benchmark, but these numbers represent the impression I got quite well

  • 8200 frames in 5s (no kms + classic mesa)
  • 5140 frames in 5s (kms + classic mesa)
  • 2431 frames in 5s (kms + gallium)

But as r300g exposes GLSL and the adobe flash player uses that if available, HD flash movies seem smoother now. And considering that using gallium not only provides better OpenGL, but eventually also VDPAU, OpenVG, OpenCL etc. the r300g driver does a good job already. And remember all AMD cards starting from r300 will get this stuff – I hope you now see why open source drivers are important πŸ˜‰

GLUT for C++ and OpenGL ES

did you ever try to use GLUT with C++? Do you remember the pain of having to make you member function static, so they can be used as a callback? Maybe you also want to create a OpenGL ES2 context if you develop for mobile devices. But although the latest freeglut supports OpenGL3 contexts, you are still out of luck using GLUT here. But there is rescue:

#include <QGLWidget>

class View : public QGLWidget {
public:
 View();  // glutInit
protected:
 void initializeGL();
 void paintGL(); // glutDisplayFunc
 void resizeGL(int width, int height); // glutReshapeFunc
 void keyPressEvent(QKeyEvent *event); // glutKeyboardFunc
};

and thats it. Works with OpenGL2 and OpenGL ES2 and integrates nicely with the Object Oriented approach. As Qt is LGPL today you can also use it in closed source projects and as you see, you can easily migrate from GLUT without changing all your code πŸ™‚

E-Mail backup in 2009

Are you still one of those using POP to pull E-Mails and save them locally? Are you then using some kind copy to back-up the local mails? At least so did I until recently… But welcome to 2009!

Today the serious e-mail providers also offer IMAP access and pulling e-mails from other servers using POP. Furthermore you get about 7GB(at gmail at least) of online storage and you can configure IMAP to maintain a full local copy. (hint: default of Thunderbird 3)

So instead of fiddling with some local back-ups you can just let gmail pull and save your mail in one place. Then you can clone all your mail locally with thunderbird and you have a reasonable backup. (also recommended for offline usage)

But what to do with your mail collection from the last years? Luckily IMAP has also push support, so you can upload them to gmail and maybe to a bunch of other email providers if you feel safer. πŸ™‚

YouAmp 0.6 has grown

After several betas the final release of YouAmp 0.6 is almost there. You can find the current versions in the launchpad PPA for Ubuntu and in maemo-extras for N8x0.

YouAmp DesktopYouAmp Maemo

the new features are:

  • Playlists
  • Automatic Cover Download
  • Adding Files from anywhere, not just the music library (just drag and drop in Desktop version)
  • you can pay for YouAmp now

I would like to emphasise the last feature: make me a millionaire! No seriously – if you like YouAmp consider a small donation > 0,30€ (otherwise everything goes to paypal) which will help developing the program in my free-time. πŸ˜‰

As I did not get into the Developers programme for the N900, I also accept unused discount codes – in case you would like to see YouAmp on the N900.

First serious YouAmp release for Desktop

YouAmp is yet another music player for Linux. But it is different than the other players as it is written by me! Here is a screenshot

youamp-0.6

if you are convinced by these outstanding features you can give it a try here. Do not be afraid if nothing happens on first startup as it will index your whole home directory which takes a while.

Basically this re-implements Tracker for music files – and indeed one of the features of this release is that I throw away Tracker. Although the Tracker devs never get tired of praising the cool new features they are implementing, their last stable release Tracker 0.6 is an unusable piece of crap. But I am actually looking forward to try out Tracker 0.7 once it gets an stable release for using it with YouAmp.

For those waiting for playlist in YouAmp on maemo: this release means they are not far away. The main purpose of the last release on maemo was basically to sync the code with the desktop version. Now it only needs some polish and UI love, so it works well on the small screen.

ARToolkitPlus 2.1.3

I just released ARToolkitPlus 2.1.3 based on the new development on launchpad. While the last official release 2.1.1 was back in 2006 and the intermediate release 2.1.2 just contained some build fixes, this version is actually useful.

It has the following features/ fixes:

  • build fixes with GCC 4.4
  • allow build with -std=c++0x
  • allow system-wide installation (allows packaging)
  • add debian packaging information

therefore you can find some ARToolkitPlus packages in my PPA now.

In case you wonder about the differences between ARToolkit and ARToolkitPlus or you are searching for more documentation, I also set up an FAQ.

OpenGL on the N900

some people already got enthusiastic because they heard that the N900 – nokias latest Linux phone supports OpenGL. Playing games like Frets On Fire on your phone as soon as you got one was a common expectation. But this will not be possible – at least not as easy as you might think.

OpenGL does not always mean OpenGL. There is OpenGL1, OpenGL2, OpenGL3, OpenGL ES1 and last but not least OpenGL ES2. While all contain OpenGL in the name and are somewhat similiar they are not compatible with each other. Basically only GL2 is compatible with GL1 programs. As soon as the deprecated stuff will be removed from GL3, GL2 programs wont run any more. Generally GLES is also not compatible with GL – but programs written in GL2 are very similar to GLES1 and programs written in GL3 are likewise similar to GLES2. So porting between this two pairs is easily possible. The problem is that Quake3 was written with GL1 and the N900 only supports GLES2. This means that basically the whole renderer of the game has to be rewritten.

Another problem is that FretsOnFire uses SDL1.2 for input/ output handling and context creation(through pygame). But SDL1.2 uses GL1 for context creation so you cant use that. Luckily there is SDL1.3 which also supports GLES2 but it is not available on the N900 yet.

So in order to get an existing game running on the N900 one would have to rewrite the engine using the GLES2/GL3 model and replace any librariesΒ  (SDL1.2, GLUT) with direct calls to EGL for context creation and Xlib to get the window . The port of Quake3 to Maemo shows that this is possible – but it will usually take more time than a simple recompile.

HD movies with crappy Open Source drivers

do you want to watch a HD film on your Ubuntu Box? Most likely this will be a choppy experience unless you have a NVidia card with VDPAU decoding support. With ordinary open source radeon or intel drivers, your CPU wont get any help with decoding and thus the decoding will be most likely be not fast enough.

But the good news is that you dont have to wait until next christmas, when the Gallium based open source drivers will probably be able to offer video decoding acceleration. In case you have a multi-core system you probably dont need any GPU based acceleration at all, since your CPU is basically fast enough, but is just not programmed properly. Currently ffmpeg(the library which does the decoding) only uses one core of your quad-core CPU ideling the other 3 while your video is stuttering.

Luckily there is a branch of ffmpeg which uses all 4 cores called ffmpeg-mt and there is also a special version of mplayer(mplayer-mt) available in this PPA which uses this ffmpeg branch. If you use this you most likely will be able to watch HD movies now – but the proper fix would be patching the system ffmpeg library so totem, VLC et. al. would benefit from it as well…

Developing OpenGL 3 when all you have is OpenGL 1.5

As you probably should know by now there was a big cleanup with OpenGL 3.1, when the functions deprecated with OpenGL 3.0 were removed. This means that the immediate mode is gone as well as all fixed function options, which results in a more flexible and Object Oriented API.

But this also means that programs written with OpenGL3.1+ are fundamentally different than those written with OpenGL 2 and before. So if you develop a new application it makes sense to stick to the OpenGL3 model. The problem is that the current Linux open source drivers are stuck to at most OpenGL 1.5 support due to missing GLSL support. But what if you want to develop a OpenGL3 compatible renderer today?

This post will cover how to create a renderer based on the OpenGL3 model, but only using OpenGL 1.5 constructs. If you want to know more about the OpenGL3 model, read here.

The core of OpenGL3 probably is that you feed arbitary data into vertex/ fragment shaders which do something useful with them, instead of specifying directly what to do. These shaders are written in GLSL, which is a sort of a C dialect. But as I said there is no GLSL with OpenGL 1.5, so we will have to use vertex/ fragment programs. They do basically the same as shaders, but are written in assembly.

Luckily one can compile GLSL Shaders to vertex/ fragment programs using Nvidias CG so we obviosly need the nvidia-cg-toolkit. Vertex/ Fragment programs are also loaded differently, so while for a vertex shader you do

unsigned int prog = glCreateProgram();
unsigned int id = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(id, 1, (char**)&progStr.c_str(), NULL);
glCompileShader(id);
glAttachShader(prog, id);
glLinkProgram(prog);

you do for a vertex program

unsigned int id;
glGenProgramsARB(1, &id);
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, id);
glProgramStringARB(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
 progStr.length(), progStr.c_str());

The pushing of data into the shader is also handled differently. For GLSL Shader:

// we bind the uniform variable "matPMV" from the vertex shader
int loc = glGetUniformLocation(prog, "matPMV");
glUniformMatrix4fv(loc, 1, GL_FALSE, matPMV);

// bind the attribute "vertexPos" in the shader
#define VERTEX_ATTR 0
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindAttribLocation(prog, VERTEX_ATTR, "vertexPos");
glEnableVertexAttribArrayARB(VERTEX_ATTR);
glVertexAttribPointerARB(VERTEX_ATTR, 3, GL_FLOAT, false, 0, 0);

for a vertex program

// we have no uniforms here yet
// this binds the C0..C3 to the model view matrix
glBindProgramARB(GL_VERTEX_PROGRAM_ARB, id);
glProgramLocalParameters4fvEXT(GL_VERTEX_PROGRAM_ARB, 0, 4, matPMV);

// attributes work almost the same
#define VERTEX_ATTR 0
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glEnableVertexAttribArrayARB(VERTEX_ATTR);
glVertexAttribPointerARB(VERTEX_ATTR, 3, GL_FLOAT, false, 0, 0);

but since we could specify the variable name in the code, we have to do it in the Shader:

uniform mat4 matPMV : C0;
attribute vec4 vertexPos : ATTR0;

the ordinary GLSL Vertex shader would just read

uniform mat4 matPMV;
attribute vec4 vertexPos;

But wait, I said there is no shader support in OpenGL 1.5. Right – this is where cgc comes into play. You have to compile your shader manually with it into a vertex program, which you finally load. The command for this is:

cgc -oglsl -profile arbvp1 vertexShader.cg -o vertexProg.vp

As you can see, the differences are pretty small using this technique, so you can start developing using the Open Source drivers now πŸ™‚