Added some example progs using DirectFBGL.
diff --git a/progs/directfb/df_reflect.c b/progs/directfb/df_reflect.c
new file mode 100644
index 0000000..ce4d12f
--- /dev/null
+++ b/progs/directfb/df_reflect.c
@@ -0,0 +1,489 @@
+/*
+   (c) Copyright 2001  convergence integrated media GmbH.
+   All rights reserved.
+
+   Written by Denis Oliver Kropp <dok@convergence.de> and
+              Andreas Hundt <andi@convergence.de>.
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the
+   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#include <directfb.h>
+
+#include <GL/glu.h>
+#include <GL/directfbgl.h>
+
+#include "util/showbuffer.c"
+#include "util/readtex.c"
+
+
+/* the super interface */
+IDirectFB *dfb;
+
+/* the primary surface (surface of primary layer) */
+IDirectFBSurface *primary;
+
+/* the GL context */
+IDirectFBGL *primary_gl;
+
+/* our font */
+IDirectFBFont *font;
+
+/* event buffer */
+IDirectFBEventBuffer *events;
+
+/* macro for a safe call to DirectFB functions */
+#define DFBCHECK(x...) \
+        {                                                                      \
+           err = x;                                                            \
+           if (err != DFB_OK) {                                                \
+              fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ );           \
+              DirectFBErrorFatal( #x, err );                                   \
+           }                                                                   \
+        }
+
+static int screen_width, screen_height;
+
+static unsigned long T0 = 0;
+static GLint Frames = 0;
+static GLfloat fps = 0;
+
+static inline unsigned long get_millis()
+{
+  struct timeval tv;
+
+  gettimeofday (&tv, NULL);
+  return (tv.tv_sec * 1000 + tv.tv_usec / 1000);
+}
+
+/*******************************/
+
+#define DEG2RAD (3.14159/180.0)
+
+#define TABLE_TEXTURE "../images/tile.rgb"
+
+static GLint ImgWidth, ImgHeight;
+static GLenum ImgFormat;
+static GLubyte *Image = NULL;
+
+#define MAX_OBJECTS 2
+static GLint table_list;
+static GLint objects_list[MAX_OBJECTS];
+
+static GLfloat xrot, yrot;
+static GLfloat spin;
+
+static GLint Width = 400, Height = 300;
+static GLenum ShowBuffer = GL_NONE;
+
+
+static void make_table( void )
+{
+   static GLfloat table_mat[] = { 1.0, 1.0, 1.0, 0.6 };
+   static GLfloat gray[] = { 0.4, 0.4, 0.4, 1.0 };
+
+   table_list = glGenLists(1);
+   glNewList( table_list, GL_COMPILE );
+
+   /* load table's texture */
+   glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, table_mat );
+/*   glMaterialfv( GL_FRONT, GL_EMISSION, gray );*/
+   glMaterialfv( GL_FRONT, GL_DIFFUSE, table_mat );
+   glMaterialfv( GL_FRONT, GL_AMBIENT, gray );
+
+   /* draw textured square for the table */
+   glPushMatrix();
+   glScalef( 4.0, 4.0, 4.0 );
+   glBegin( GL_POLYGON );
+   glNormal3f( 0.0, 1.0, 0.0 );
+   glTexCoord2f( 0.0, 0.0 );   glVertex3f( -1.0, 0.0,  1.0 );
+   glTexCoord2f( 1.0, 0.0 );   glVertex3f(  1.0, 0.0,  1.0 );
+   glTexCoord2f( 1.0, 1.0 );   glVertex3f(  1.0, 0.0, -1.0 );
+   glTexCoord2f( 0.0, 1.0 );   glVertex3f( -1.0, 0.0, -1.0 );
+   glEnd();
+   glPopMatrix();
+
+   glDisable( GL_TEXTURE_2D );
+
+   glEndList();
+}
+
+
+static void make_objects( void )
+{
+   GLUquadricObj *q;
+
+   static GLfloat cyan[] = { 0.0, 1.0, 1.0, 1.0 };
+   static GLfloat green[] = { 0.2, 1.0, 0.2, 1.0 };
+   static GLfloat black[] = { 0.0, 0.0, 0.0, 0.0 };
+
+   q = gluNewQuadric();
+   gluQuadricDrawStyle( q, GLU_FILL );
+   gluQuadricNormals( q, GLU_SMOOTH );
+
+   objects_list[0] = glGenLists(1);
+   glNewList( objects_list[0], GL_COMPILE );
+   glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, cyan );
+   glMaterialfv( GL_FRONT, GL_EMISSION, black );
+   gluCylinder( q, 0.5, 0.5,  1.0, 15, 1 );
+   glEndList();
+
+   objects_list[1] = glGenLists(1);
+   glNewList( objects_list[1], GL_COMPILE );
+   glMaterialfv( GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green );
+   glMaterialfv( GL_FRONT, GL_EMISSION, black );
+   gluCylinder( q, 1.5, 0.0,  2.5, 15, 1 );
+   glEndList();
+}
+
+
+static void init( void )
+{
+   make_table();
+   make_objects();
+
+   Image = LoadRGBImage( TABLE_TEXTURE, &ImgWidth, &ImgHeight, &ImgFormat );
+   if (!Image) {
+      printf("Couldn't read %s\n", TABLE_TEXTURE);
+      exit(0);
+   }
+
+   gluBuild2DMipmaps(GL_TEXTURE_2D, 3, ImgWidth, ImgHeight,
+                     ImgFormat, GL_UNSIGNED_BYTE, Image);
+
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
+   glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
+
+   xrot = 30.0;
+   yrot = 50.0;
+   spin = 0.0;
+
+   glShadeModel( GL_FLAT );
+
+   glEnable( GL_LIGHT0 );
+   glEnable( GL_LIGHTING );
+
+   glClearColor( 0.5, 0.5, 0.9, 0.0 );
+
+   glEnable( GL_NORMALIZE );
+}
+
+
+
+static void reshape(int w, int h)
+{
+   GLfloat yAspect = 2.5;
+   GLfloat xAspect = yAspect * (float) w / (float) h;
+   Width = w;
+   Height = h;
+   glViewport(0, 0, w, h);
+   glMatrixMode(GL_PROJECTION);
+   glLoadIdentity();
+   glFrustum( -xAspect, xAspect, -yAspect, yAspect, 10.0, 30.0 );
+   glMatrixMode(GL_MODELVIEW);
+   glLoadIdentity();
+}
+
+
+
+static void draw_objects( GLfloat eyex, GLfloat eyey, GLfloat eyez )
+{
+   (void) eyex;
+   (void) eyey;
+   (void) eyez;
+#ifndef USE_ZBUFFER
+   if (eyex<0.5) {
+#endif
+       glPushMatrix();
+       glTranslatef( 1.0, 1.5, 0.0 );
+       glRotatef( spin, 1.0, 0.5, 0.0 );
+       glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+       glCallList( objects_list[0] );
+       glPopMatrix();
+    
+       glPushMatrix();
+       glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
+       glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+       glRotatef( spin, 1.0, 0.5, 0.0 );
+       glScalef( 0.5, 0.5, 0.5 );
+       glCallList( objects_list[1] );
+       glPopMatrix();
+#ifndef USE_ZBUFFER
+   }
+   else {   
+       glPushMatrix();
+       glTranslatef( -1.0, 0.85+3.0*fabs( cos(0.01*spin) ), 0.0 );
+       glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+       glRotatef( spin, 1.0, 0.5, 0.0 );
+       glScalef( 0.5, 0.5, 0.5 );
+       glCallList( objects_list[1] );
+       glPopMatrix();
+
+       glPushMatrix();
+       glTranslatef( 1.0, 1.5, 0.0 );
+       glRotatef( spin, 1.0, 0.5, 0.0 );
+       glRotatef( 0.5*spin, 0.0, 0.5, 1.0 );
+       glCallList( objects_list[0] );
+       glPopMatrix();
+   }
+#endif
+}
+
+
+
+static void draw_table( void )
+{
+   glCallList( table_list );
+}
+
+
+
+static void draw( void )
+{
+   static GLfloat light_pos[] = { 0.0, 20.0, 0.0, 1.0 };
+   GLfloat dist = 20.0;
+   GLfloat eyex, eyey, eyez;
+
+   glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+
+
+   eyex = dist * cos(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
+   eyez = dist * sin(yrot*DEG2RAD) * cos(xrot*DEG2RAD);
+   eyey = dist * sin(xrot*DEG2RAD);
+
+   /* view from top */
+   glPushMatrix();
+   gluLookAt( eyex, eyey, eyez, 0.0, 0.0, 0.0,  0.0, 1.0, 0.0 );
+
+   glLightfv( GL_LIGHT0, GL_POSITION, light_pos );
+
+   /* draw table into stencil planes */
+   glDisable( GL_DEPTH_TEST );
+   glEnable( GL_STENCIL_TEST );
+   glStencilFunc( GL_ALWAYS, 1, 0xffffffff );
+   glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );
+   glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );
+   draw_table();
+   glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );
+
+   glEnable( GL_DEPTH_TEST );
+
+   /* render view from below (reflected viewport) */
+   /* only draw where stencil==1 */
+   if (eyey>0.0) {
+      glPushMatrix();
+
+      glStencilFunc( GL_EQUAL, 1, 0xffffffff );  /* draw if ==1 */
+      glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );
+      glScalef( 1.0, -1.0, 1.0 );
+
+      /* Reposition light in reflected space. */
+      glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
+
+      draw_objects(eyex, eyey, eyez);
+      glPopMatrix();
+
+      /* Restore light's original unreflected position. */
+      glLightfv(GL_LIGHT0, GL_POSITION, light_pos);
+   }
+
+   glDisable( GL_STENCIL_TEST );
+
+   glEnable( GL_BLEND );
+   glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
+
+   glEnable( GL_TEXTURE_2D );
+   draw_table();
+   glDisable( GL_TEXTURE_2D );
+   glDisable( GL_BLEND );
+
+   /* view from top */
+   glPushMatrix();
+
+   draw_objects(eyex, eyey, eyez);
+
+   glPopMatrix();
+
+   glPopMatrix();
+
+   if (ShowBuffer == GL_DEPTH) {
+      ShowDepthBuffer(Width, Height, 1.0, 0.0);
+   }
+   else if (ShowBuffer == GL_STENCIL) {
+      ShowStencilBuffer(Width, Height, 255.0, 0.0);
+   }
+   else if (ShowBuffer == GL_ALPHA) {
+      ShowAlphaBuffer(Width, Height);
+   }
+}
+
+/*******************************/
+
+int main( int argc, char *argv[] )
+{
+     int quit = 0;
+     DFBResult err;
+     DFBSurfaceDescription dsc;
+
+     DFBCHECK(DirectFBInit( &argc, &argv ));
+
+     /* create the super interface */
+     DFBCHECK(DirectFBCreate( &dfb ));
+
+     /* create an event buffer for all devices with these caps */
+     DFBCHECK(dfb->CreateInputEventBuffer( dfb, DICAPS_ALL, DFB_FALSE, &events ));
+
+     /* set our cooperative level to DFSCL_FULLSCREEN
+        for exclusive access to the primary layer */
+     dfb->SetCooperativeLevel( dfb, DFSCL_FULLSCREEN );
+
+     /* get the primary surface, i.e. the surface of the
+        primary layer we have exclusive access to */
+     dsc.flags = DSDESC_CAPS;
+     dsc.caps  = (DFBSurfaceCapabilities)(DSCAPS_PRIMARY | DSCAPS_DOUBLE);
+
+     DFBCHECK(dfb->CreateSurface( dfb, &dsc, &primary ));
+
+     /* get the size of the surface and fill it */
+     DFBCHECK(primary->GetSize( primary, &screen_width, &screen_height ));
+     DFBCHECK(primary->FillRectangle( primary, 0, 0,
+                                      screen_width, screen_height ));
+
+     /* create the default font and set it */
+     DFBCHECK(dfb->CreateFont( dfb, NULL, NULL, &font ));
+     DFBCHECK(primary->SetFont( primary, font ));
+
+     /* get the GL context */
+     DFBCHECK(primary->GetGL( primary, &primary_gl ));
+
+     DFBCHECK(primary_gl->Lock( primary_gl ));
+     
+     init();
+     reshape(screen_width, screen_height);
+
+     DFBCHECK(primary_gl->Unlock( primary_gl ));
+     
+     T0 = get_millis();
+
+     while (!quit) {
+          DFBInputEvent evt;
+          unsigned long t;
+
+          DFBCHECK(primary_gl->Lock( primary_gl ));
+          
+          draw();
+
+          DFBCHECK(primary_gl->Unlock( primary_gl ));
+          
+          if (fps) {
+               char buf[64];
+
+               sprintf(buf, "%4.1f FPS\n", fps);
+               primary->SetColor( primary, 0xff, 0, 0, 0xff );
+               primary->DrawString( primary, buf, -1, screen_width - 5, 5, DSTF_TOPRIGHT );
+          }
+
+          primary->Flip( primary, NULL, (DFBSurfaceFlipFlags)0 );
+          Frames++;
+
+
+          t = get_millis();
+          if (t - T0 >= 1000) {
+               GLfloat seconds = (t - T0) / 1000.0;
+
+               fps = Frames / seconds;
+
+               T0 = t;
+               Frames = 0;
+          }
+
+
+          while (events->GetEvent( events, DFB_EVENT(&evt) ) == DFB_OK) {
+               switch (evt.type) {
+                    case DIET_KEYPRESS:
+                         switch (DFB_LOWER_CASE(evt.key_symbol)) {
+                              case DIKS_ESCAPE:
+                                   quit = 1;
+                                   break;
+                              case DIKS_CURSOR_UP:
+                                   xrot += 3.0;
+                                   if ( xrot > 85 )
+                                      xrot = 85;
+                                   break;
+                              case DIKS_CURSOR_DOWN:
+                                   xrot -= 3.0;
+                                   if ( xrot < 5 )
+                                      xrot = 5;
+                                   break;
+                              case DIKS_CURSOR_LEFT:
+                                   yrot += 3.0;
+                                   break;
+                              case DIKS_CURSOR_RIGHT:
+                                   yrot -= 3.0;
+                                   break;
+                              case DIKS_SMALL_D:
+                                   ShowBuffer = GL_DEPTH;
+                                   break;
+                              case DIKS_SMALL_S:
+                                   ShowBuffer = GL_STENCIL;
+                                   break;
+                              case DIKS_SMALL_A:
+                                   ShowBuffer = GL_ALPHA;
+                                   break;
+                              default:
+                                   ShowBuffer = GL_NONE;
+                         }
+                         break;
+                    case DIET_AXISMOTION:
+                         if (evt.flags & DIEF_AXISREL) {
+                              switch (evt.axis) {
+                                   case DIAI_X:
+                                        yrot += evt.axisrel / 2.0;
+                                        break;
+                                   case DIAI_Y:
+                                        xrot += evt.axisrel / 2.0;
+                                        break;
+                                   default:
+                                        ;
+                              }
+                         }
+                         break;
+                    default:
+                         ;
+               }
+          }
+
+          spin += 2.0;
+          yrot += 3.0;
+     }
+
+     /* release our interfaces to shutdown DirectFB */
+     primary_gl->Release( primary_gl );
+     primary->Release( primary );
+     font->Release( font );
+     events->Release( events );
+     dfb->Release( dfb );
+
+     return 0;
+}
+