From fe94d0b33508560f7b42dacd457f9eedcaf1a210 Mon Sep 17 00:00:00 2001 From: Claudio Ciccani Date: Wed, 31 May 2006 17:05:11 +0000 Subject: [PATCH] Added some example progs using DirectFBGL. --- progs/directfb/Makefile | 36 ++ progs/directfb/df_gears.c | 480 ++++++++++++++++ progs/directfb/df_morph3d.c | 1013 +++++++++++++++++++++++++++++++++ progs/directfb/df_reflect.c | 489 ++++++++++++++++ progs/directfb/multi_window.c | 240 ++++++++ 5 files changed, 2258 insertions(+) create mode 100644 progs/directfb/Makefile create mode 100644 progs/directfb/df_gears.c create mode 100644 progs/directfb/df_morph3d.c create mode 100644 progs/directfb/df_reflect.c create mode 100644 progs/directfb/multi_window.c diff --git a/progs/directfb/Makefile b/progs/directfb/Makefile new file mode 100644 index 00000000000..a541c8ff9aa --- /dev/null +++ b/progs/directfb/Makefile @@ -0,0 +1,36 @@ +# progs/directfb/Makefile + +TOP = ../.. +include $(TOP)/configs/current + + +INCDIR = $(TOP)/include -I$(TOP)/progs + +LIB_DEP = $(LIB_DIR)/$(GL_LIB_NAME) $(LIB_DIR)/$(GLU_LIB_NAME) + +CFLAGS += $(shell pkg-config --cflags directfb) +APP_LIB_DEPS += $(shell pkg-config --libs directfb) + +PROGS = df_gears \ + df_reflect \ + df_morph3d \ + multi_window + +##### RULES ##### + +.SUFFIXES: +.SUFFIXES: .c + +.c: $(LIB_DEP) + $(CC) -I$(INCDIR) $(CFLAGS) $< $(APP_LIB_DEPS) -o $@ + + +##### TARGETS ##### + +default: $(PROGS) + + +clean: + -rm -f $(PROGS) + -rm -f *.o *~ + diff --git a/progs/directfb/df_gears.c b/progs/directfb/df_gears.c new file mode 100644 index 00000000000..27df900115f --- /dev/null +++ b/progs/directfb/df_gears.c @@ -0,0 +1,480 @@ +/* + (c) Copyright 2001 convergence integrated media GmbH. + All rights reserved. + + Written by Denis Oliver Kropp and + Andreas Hundt . + + 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 +#include +#include +#include + +#include + +#include +#include + + +/* 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); +} + + +#ifndef M_PI +#define M_PI 3.14159265 +#endif + +/** + + Draw a gear wheel. You'll probably want to call this function when + building a display list since we do a lot of trig here. + + Input: inner_radius - radius of hole at center + outer_radius - radius at center of teeth + width - width of gear + teeth - number of teeth + tooth_depth - depth of tooth + + **/ + +static void +gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width, + GLint teeth, GLfloat tooth_depth) +{ + GLint i; + GLfloat r0, r1, r2; + GLfloat angle, da; + GLfloat u, v, len; + + r0 = inner_radius; + r1 = outer_radius - tooth_depth / 2.0; + r2 = outer_radius + tooth_depth / 2.0; + + da = 2.0 * M_PI / teeth / 4.0; + + glShadeModel(GL_FLAT); + + glNormal3f(0.0, 0.0, 1.0); + + /* draw front face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + if (i < teeth) { + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); + } + } + glEnd(); + + /* draw front sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); + } + glEnd(); + + glNormal3f(0.0, 0.0, -1.0); + + /* draw back face */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + if (i < teeth) { + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + } + } + glEnd(); + + /* draw back sides of teeth */ + glBegin(GL_QUADS); + da = 2.0 * M_PI / teeth / 4.0; + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + } + glEnd(); + + /* draw outward faces of teeth */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i < teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + + glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5); + glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5); + u = r2 * cos(angle + da) - r1 * cos(angle); + v = r2 * sin(angle + da) - r1 * sin(angle); + len = sqrt(u * u + v * v); + u /= len; + v /= len; + glNormal3f(v, -u, 0.0); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5); + glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5); + glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5); + u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da); + v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da); + glNormal3f(v, -u, 0.0); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5); + glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5); + glNormal3f(cos(angle), sin(angle), 0.0); + } + + glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5); + glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5); + + glEnd(); + + glShadeModel(GL_SMOOTH); + + /* draw inside radius cylinder */ + glBegin(GL_QUAD_STRIP); + for (i = 0; i <= teeth; i++) { + angle = i * 2.0 * M_PI / teeth; + glNormal3f(-cos(angle), -sin(angle), 0.0); + glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5); + glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5); + } + glEnd(); + +} + +static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0; +static GLfloat inc_rotx = 0, inc_roty = 0, inc_rotz = 0; +static GLint gear1, gear2, gear3; +static GLfloat angle = 0.0; + +static void +draw(void) +{ + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + glPushMatrix(); + glRotatef(view_rotx, 1.0, 0.0, 0.0); + glRotatef(view_roty, 0.0, 1.0, 0.0); + glRotatef(view_rotz, 0.0, 0.0, 1.0); + + glPushMatrix(); + glTranslatef(-3.0, -2.0, 0.0); + glRotatef(angle, 0.0, 0.0, 1.0); + glCallList(gear1); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(3.1, -2.0, 0.0); + glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0); + glCallList(gear2); + glPopMatrix(); + + glPushMatrix(); + glTranslatef(-3.1, 4.2, 0.0); + glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0); + glCallList(gear3); + glPopMatrix(); + + glPopMatrix(); +} + +/* new window size or exposure */ +static void +reshape(int width, int height) +{ + GLfloat h = (GLfloat) height / (GLfloat) width; + + glViewport(0, 0, (GLint) width, (GLint) height); + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glFrustum(-1.0, 1.0, -h, h, 5.0, 60.0); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); +} + +static void +init(int argc, char *argv[]) +{ + static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; + static GLfloat red[4] = {0.8, 0.1, 0.0, 1.0}; + static GLfloat green[4] = {0.0, 0.8, 0.2, 1.0}; + static GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; + GLint i; + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + /* make the gears */ + gear1 = glGenLists(1); + glNewList(gear1, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red); + gear(1.0, 4.0, 1.0, 20, 0.7); + glEndList(); + + gear2 = glGenLists(1); + glNewList(gear2, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green); + gear(0.5, 2.0, 2.0, 10, 0.7); + glEndList(); + + gear3 = glGenLists(1); + glNewList(gear3, GL_COMPILE); + glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue); + gear(1.3, 2.0, 0.5, 10, 0.7); + glEndList(); + + glEnable(GL_NORMALIZE); + + for ( i=1; iCreateInputEventBuffer( dfb, DICAPS_KEYS | DICAPS_AXES, + 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 = 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 )); + primary->Flip( primary, NULL, 0 ); + + /* 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(argc, argv); + 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]; + + snprintf(buf, 64, "%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, 0 ); + Frames++; + + + t = get_millis(); + if (t - T0 >= 2000) { + 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 (evt.key_symbol) { + case DIKS_ESCAPE: + quit = 1; + break; + case DIKS_CURSOR_UP: + inc_rotx = 5.0; + break; + case DIKS_CURSOR_DOWN: + inc_rotx = -5.0; + break; + case DIKS_CURSOR_LEFT: + inc_roty = 5.0; + break; + case DIKS_CURSOR_RIGHT: + inc_roty = -5.0; + break; + case DIKS_PAGE_UP: + inc_rotz = 5.0; + break; + case DIKS_PAGE_DOWN: + inc_rotz = -5.0; + break; + default: + ; + } + break; + case DIET_KEYRELEASE: + switch (evt.key_symbol) { + case DIKS_CURSOR_UP: + inc_rotx = 0; + break; + case DIKS_CURSOR_DOWN: + inc_rotx = 0; + break; + case DIKS_CURSOR_LEFT: + inc_roty = 0; + break; + case DIKS_CURSOR_RIGHT: + inc_roty = 0; + break; + case DIKS_PAGE_UP: + inc_rotz = 0; + break; + case DIKS_PAGE_DOWN: + inc_rotz = 0; + break; + default: + ; + } + break; + case DIET_AXISMOTION: + if (evt.flags & DIEF_AXISREL) { + switch (evt.axis) { + case DIAI_X: + view_roty += evt.axisrel / 2.0; + break; + case DIAI_Y: + view_rotx += evt.axisrel / 2.0; + break; + case DIAI_Z: + view_rotz += evt.axisrel / 2.0; + break; + default: + ; + } + } + break; + default: + ; + } + } + + angle += 2.0; + + view_rotx += inc_rotx; + view_roty += inc_roty; + view_rotz += inc_rotz; + } + + /* 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; +} + diff --git a/progs/directfb/df_morph3d.c b/progs/directfb/df_morph3d.c new file mode 100644 index 00000000000..f7f143447f4 --- /dev/null +++ b/progs/directfb/df_morph3d.c @@ -0,0 +1,1013 @@ +/* + (c) Copyright 2001 convergence integrated media GmbH. + All rights reserved. + + Written by Denis Oliver Kropp and + Andreas Hundt . + + 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. +*/ + +/*- + * morph3d.c - Shows 3D morphing objects + * + * Converted to GLUT by brianp on 1/1/98 + * + * This program was inspired on a WindowsNT(R)'s screen saver. It was written + * from scratch and it was not based on any other source code. + * + * Porting it to xlock (the final objective of this code since the moment I + * decided to create it) was possible by comparing the original Mesa's gear + * demo with it's ported version, so thanks for Danny Sung for his indirect + * help (look at gear.c in xlock source tree). NOTE: At the moment this code + * was sent to Brian Paul for package inclusion, the XLock Version was not + * available. In fact, I'll wait it to appear on the next Mesa release (If you + * are reading this, it means THIS release) to send it for xlock package + * inclusion). It will probably there be a GLUT version too. + * + * Thanks goes also to Brian Paul for making it possible and inexpensive + * to use OpenGL at home. + * + * Since I'm not a native english speaker, my apologies for any gramatical + * mistake. + * + * My e-mail addresses are + * + * vianna@cat.cbpf.br + * and + * marcelo@venus.rdc.puc-rio.br + * + * Marcelo F. Vianna (Feb-13-1997) + */ + +/* +This document is VERY incomplete, but tries to describe the mathematics used +in the program. At this moment it just describes how the polyhedra are +generated. On futhurer versions, this document will be probabbly improved. + +Since I'm not a native english speaker, my apologies for any gramatical +mistake. + +Marcelo Fernandes Vianna +- Undergraduate in Computer Engeneering at Catholic Pontifical University +- of Rio de Janeiro (PUC-Rio) Brasil. +- e-mail: vianna@cat.cbpf.br or marcelo@venus.rdc.puc-rio.br +- Feb-13-1997 + +POLYHEDRA GENERATION + +For the purpose of this program it's not sufficient to know the polyhedra +vertexes coordinates. Since the morphing algorithm applies a nonlinear +transformation over the surfaces (faces) of the polyhedron, each face has +to be divided into smaller ones. The morphing algorithm needs to transform +each vertex of these smaller faces individually. It's a very time consoming +task. + +In order to reduce calculation overload, and since all the macro faces of +the polyhedron are transformed by the same way, the generation is made by +creating only one face of the polyhedron, morphing it and then rotating it +around the polyhedron center. + +What we need to know is the face radius of the polyhedron (the radius of +the inscribed sphere) and the angle between the center of two adjacent +faces using the center of the sphere as the angle's vertex. + +The face radius of the regular polyhedra are known values which I decided +to not waste my time calculating. Following is a table of face radius for +the regular polyhedra with edge length = 1: + + TETRAHEDRON : 1/(2*sqrt(2))/sqrt(3) + CUBE : 1/2 + OCTAHEDRON : 1/sqrt(6) + DODECAHEDRON : T^2 * sqrt((T+2)/5) / 2 -> where T=(sqrt(5)+1)/2 + ICOSAHEDRON : (3*sqrt(3)+sqrt(15))/12 + +I've not found any reference about the mentioned angles, so I needed to +calculate them, not a trivial task until I figured out how :) +Curiously these angles are the same for the tetrahedron and octahedron. +A way to obtain this value is inscribing the tetrahedron inside the cube +by matching their vertexes. So you'll notice that the remaining unmatched +vertexes are in the same straight line starting in the cube/tetrahedron +center and crossing the center of each tetrahedron's face. At this point +it's easy to obtain the bigger angle of the isosceles triangle formed by +the center of the cube and two opposite vertexes on the same cube face. +The edges of this triangle have the following lenghts: sqrt(2) for the base +and sqrt(3)/2 for the other two other edges. So the angle we want is: + +-----------------------------------------------------------+ + | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees | + +-----------------------------------------------------------+ +For the cube this angle is obvious, but just for formality it can be +easily obtained because we also know it's isosceles edge lenghts: +sqrt(2)/2 for the base and 1/2 for the other two edges. So the angle we +want is: + +-----------------------------------------------------------+ + | 2*ARCSIN((sqrt(2)/2)/1) = 90.000000000000000000 degrees | + +-----------------------------------------------------------+ +For the octahedron we use the same idea used for the tetrahedron, but now +we inscribe the cube inside the octahedron so that all cubes's vertexes +matches excatly the center of each octahedron's face. It's now clear that +this angle is the same of the thetrahedron one: + +-----------------------------------------------------------+ + | 2*ARCSIN(sqrt(2)/sqrt(3)) = 109.47122063449069174 degrees | + +-----------------------------------------------------------+ +For the dodecahedron it's a little bit harder because it's only relationship +with the cube is useless to us. So we need to solve the problem by another +way. The concept of Face radius also exists on 2D polygons with the name +Edge radius: + Edge Radius For Pentagon (ERp) + ERp = (1/2)/TAN(36 degrees) * VRp = 0.6881909602355867905 + (VRp is the pentagon's vertex radio). + Face Radius For Dodecahedron + FRd = T^2 * sqrt((T+2)/5) / 2 = 1.1135163644116068404 +Why we need ERp? Well, ERp and FRd segments forms a 90 degrees angle, +completing this triangle, the lesser angle is a half of the angle we are +looking for, so this angle is: + +-----------------------------------------------------------+ + | 2*ARCTAN(ERp/FRd) = 63.434948822922009981 degrees | + +-----------------------------------------------------------+ +For the icosahedron we can use the same method used for dodecahedron (well +the method used for dodecahedron may be used for all regular polyhedra) + Edge Radius For Triangle (this one is well known: 1/3 of the triangle height) + ERt = sin(60)/3 = sqrt(3)/6 = 0.2886751345948128655 + Face Radius For Icosahedron + FRi= (3*sqrt(3)+sqrt(15))/12 = 0.7557613140761707538 +So the angle is: + +-----------------------------------------------------------+ + | 2*ARCTAN(ERt/FRi) = 41.810314895778596167 degrees | + +-----------------------------------------------------------+ + +*/ + + +#include +#include +#include +#include +#include + +#include + +#include +#include + + +/* 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 Scale 0.3 + +#define VectMul(X1,Y1,Z1,X2,Y2,Z2) (Y1)*(Z2)-(Z1)*(Y2),(Z1)*(X2)-(X1)*(Z2),(X1)*(Y2)-(Y1)*(X2) +#define sqr(A) ((A)*(A)) + +/* Increasing this values produces better image quality, the price is speed. */ +/* Very low values produces erroneous/incorrect plotting */ +#define tetradivisions 23 +#define cubedivisions 20 +#define octadivisions 21 +#define dodecadivisions 10 +#define icodivisions 15 + +#define tetraangle 109.47122063449069174 +#define cubeangle 90.000000000000000000 +#define octaangle 109.47122063449069174 +#define dodecaangle 63.434948822922009981 +#define icoangle 41.810314895778596167 + +#ifndef Pi +#define Pi 3.1415926535897932385 +#endif +#define SQRT2 1.4142135623730951455 +#define SQRT3 1.7320508075688771932 +#define SQRT5 2.2360679774997898051 +#define SQRT6 2.4494897427831778813 +#define SQRT15 3.8729833462074170214 +#define cossec36_2 0.8506508083520399322 +#define cos72 0.3090169943749474241 +#define sin72 0.9510565162951535721 +#define cos36 0.8090169943749474241 +#define sin36 0.5877852522924731292 + +/*************************************************************************/ + +static int mono=0; +static int smooth=1; +static GLint WindH, WindW; +static GLfloat step=0; +static GLfloat seno; +static int object; +static int edgedivisions; +static void (*draw_object)( void ); +static float Magnitude; +static float *MaterialColor[20]; + +static float front_shininess[] = {60.0}; +static float front_specular[] = { 0.7, 0.7, 0.7, 1.0 }; +static float ambient[] = { 0.0, 0.0, 0.0, 1.0 }; +static float diffuse[] = { 1.0, 1.0, 1.0, 1.0 }; +static float position0[] = { 1.0, 1.0, 1.0, 0.0 }; +static float position1[] = {-1.0,-1.0, 1.0, 0.0 }; +static float lmodel_ambient[] = { 0.5, 0.5, 0.5, 1.0 }; +static float lmodel_twoside[] = {GL_TRUE}; + +static float MaterialRed[] = { 0.7, 0.0, 0.0, 1.0 }; +static float MaterialGreen[] = { 0.1, 0.5, 0.2, 1.0 }; +static float MaterialBlue[] = { 0.0, 0.0, 0.7, 1.0 }; +static float MaterialCyan[] = { 0.2, 0.5, 0.7, 1.0 }; +static float MaterialYellow[] = { 0.7, 0.7, 0.0, 1.0 }; +static float MaterialMagenta[] = { 0.6, 0.2, 0.5, 1.0 }; +static float MaterialWhite[] = { 0.7, 0.7, 0.7, 1.0 }; +static float MaterialGray[] = { 0.2, 0.2, 0.2, 1.0 }; + +#define TRIANGLE(Edge, Amp, Divisions, Z) \ +{ \ + GLfloat Xf,Yf,Xa,Yb,Xf2,Yf2; \ + GLfloat Factor,Factor1,Factor2; \ + GLfloat VertX,VertY,VertZ,NeiAX,NeiAY,NeiAZ,NeiBX,NeiBY,NeiBZ; \ + GLfloat Ax,Ay,Bx; \ + int Ri,Ti; \ + GLfloat Vr=(Edge)*SQRT3/3; \ + GLfloat AmpVr2=(Amp)/sqr(Vr); \ + GLfloat Zf=(Edge)*(Z); \ + \ + Ax=(Edge)*(+0.5/(Divisions)), Ay=(Edge)*(-SQRT3/(2*Divisions)); \ + Bx=(Edge)*(-0.5/(Divisions)); \ + \ + for (Ri=1; Ri<=(Divisions); Ri++) { \ + glBegin(GL_TRIANGLE_STRIP); \ + for (Ti=0; TiFlip( primary, NULL, 0 ); + + glLightfv(GL_LIGHT0, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT0, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT0, GL_POSITION, position0); + glLightfv(GL_LIGHT1, GL_AMBIENT, ambient); + glLightfv(GL_LIGHT1, GL_DIFFUSE, diffuse); + glLightfv(GL_LIGHT1, GL_POSITION, position1); + glLightModelfv(GL_LIGHT_MODEL_AMBIENT, lmodel_ambient); + glLightModelfv(GL_LIGHT_MODEL_TWO_SIDE, lmodel_twoside); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_LIGHT1); + glEnable(GL_DEPTH_TEST); + glEnable(GL_NORMALIZE); + + glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, front_shininess); + glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, front_specular); + + glHint(GL_FOG_HINT, GL_FASTEST); + glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); + glHint(GL_POLYGON_SMOOTH_HINT, GL_FASTEST); + + pinit(); +} + +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_KEYS, 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 = 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; + + primary->Clear( primary, 0, 0, 0, 0 ); + + 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, 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 (evt.key_symbol) { + case DIKS_ESCAPE: + quit = 1; + break; + case DIKS_1: object=1; break; + case DIKS_2: object=2; break; + case DIKS_3: object=3; break; + case DIKS_4: object=4; break; + case DIKS_5: object=5; break; + case DIKS_SPACE: mono^=1; break; + case DIKS_ENTER: smooth^=1; break; + default: + ; + } + pinit(); + break; + default: + ; + } + } + } + + /* 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; +} + diff --git a/progs/directfb/df_reflect.c b/progs/directfb/df_reflect.c new file mode 100644 index 00000000000..ce4d12f749f --- /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 and + Andreas Hundt . + + 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 +#include +#include +#include + +#include + +#include +#include + +#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; +} + diff --git a/progs/directfb/multi_window.c b/progs/directfb/multi_window.c new file mode 100644 index 00000000000..9bb0e4be8ef --- /dev/null +++ b/progs/directfb/multi_window.c @@ -0,0 +1,240 @@ +/* + (c) Copyright 2001 convergence integrated media GmbH. + All rights reserved. + + Written by Denis Oliver Kropp and + Andreas Hundt . + + 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 +#include +#include +#include + +#include +#include + +#include +#include + + +typedef struct { + IDirectFBWindow *window; + IDirectFBSurface *surface; + IDirectFBGL *gl; + + int width; + int height; + + unsigned long last_time; + int frames; + float fps; +} Context; + +static const GLfloat blue[4] = {0.2, 0.2, 1.0, 1.0}; + +static IDirectFB *dfb; +static IDirectFBDisplayLayer *layer; +static IDirectFBFont *font; +static IDirectFBEventBuffer *events = NULL; + +/* macro for a safe call to DirectFB functions */ +#define DFBCHECK(x...) \ + do { \ + ret = x; \ + if (ret != DFB_OK) { \ + fprintf( stderr, "%s <%d>:\n\t", __FILE__, __LINE__ ); \ + DirectFBErrorFatal( #x, ret ); \ + } \ + } while (0) + + +static inline unsigned long get_millis() +{ + struct timeval tv; + + gettimeofday (&tv, NULL); + return (tv.tv_sec * 1000 + tv.tv_usec / 1000); +} + + +static void +setup( Context *context ) +{ + GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0}; + + context->surface->GetSize( context->surface, + &context->width, &context->height ); + + context->gl->Lock( context->gl ); + + glLightfv(GL_LIGHT0, GL_POSITION, pos); + glEnable(GL_CULL_FACE); + glEnable(GL_LIGHTING); + glEnable(GL_LIGHT0); + glEnable(GL_DEPTH_TEST); + + glViewport(0, 0, context->width, context->height); + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(70.0, context->width / (float) context->height, 1.0, 80.0); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glTranslatef(0.0, 0.0, -40.0); + + context->gl->Unlock( context->gl ); +} + +static void +update( Context *context ) +{ + unsigned long t; + IDirectFBSurface *surface = context->surface; + static __u8 r = 0, g = 0, b = 0; + + + context->gl->Lock( context->gl ); + + glClearColor( r++/255.0, g++/255.0, b++/255.0, 1.0 ); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + context->gl->Unlock( context->gl ); + + if (context->fps) { + char buf[16]; + + snprintf(buf, sizeof(buf), "%.1f FPS\n", context->fps); + + surface->SetColor( surface, 0xff, 0x00, 0x00, 0xff ); + surface->DrawString( surface, buf, -1, + context->width - 5, 5, DSTF_TOPRIGHT ); + } + + surface->Flip( surface, NULL, 0 ); + + context->frames++; + + t = get_millis(); + if (t - context->last_time >= 2000) { + float seconds = (t - context->last_time) / 1000.0f; + + context->fps = context->frames / seconds; + + context->last_time = t; + context->frames = 0; + } +} + +int +main( int argc, char *argv[] ) +{ + DFBResult ret; + int i; + int quit = 0; + const int num = 2; + Context contexts[num]; + + DFBCHECK(DirectFBInit( &argc, &argv )); + + /* create the super interface */ + DFBCHECK(DirectFBCreate( &dfb )); + + DFBCHECK(dfb->GetDisplayLayer( dfb, DLID_PRIMARY, &layer )); + + /* create the default font */ + DFBCHECK(dfb->CreateFont( dfb, NULL, NULL, &font )); + + for (i=0; iCreateWindow( layer, &desc, &window )); + DFBCHECK(window->GetSurface( window, &surface )); + DFBCHECK(surface->GetGL( surface, &gl )); + + contexts[i].window = window; + contexts[i].surface = surface; + contexts[i].gl = gl; + + contexts[i].last_time = get_millis(); + contexts[i].frames = 0; + contexts[i].fps = 0; + + setup( &contexts[i] ); + + if (events) + DFBCHECK(window->AttachEventBuffer( window, events )); + else + DFBCHECK(window->CreateEventBuffer( window, &events )); + + DFBCHECK(surface->SetFont( surface, font )); + + window->SetOpacity( window, 0xff ); + } + + while (!quit) { + DFBWindowEvent evt; + + for (i=0; iGetEvent( events, DFB_EVENT(&evt) ) == DFB_OK) { + switch (evt.type) { + case DWET_KEYDOWN: + switch (evt.key_symbol) { + case DIKS_ESCAPE: + quit = 1; + break; + + default: + break; + } + break; + + default: + break; + } + } + } + + events->Release( events ); + + for (i=0; iRelease( contexts[i].gl ); + contexts[i].surface->Release( contexts[i].surface ); + contexts[i].window->Release( contexts[i].window ); + } + + font->Release( font ); + layer->Release( layer ); + dfb->Release( dfb ); + + return 0; +} + -- 2.30.2