Add the gears from glxgears.
authorKristian Høgsberg <krh@redhat.com>
Mon, 3 Nov 2008 20:31:30 +0000 (15:31 -0500)
committerKristian Høgsberg <krh@redhat.com>
Thu, 6 Nov 2008 15:53:03 +0000 (10:53 -0500)
Makefile
gears.c [new file with mode: 0644]
gears.h [new file with mode: 0644]
window.c

index a335cb1..a533f61 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,13 +1,16 @@
 CFLAGS +=  -Wall -g $(shell pkg-config --cflags libffi libdrm)
 LDLIBS += $(shell pkg-config --libs libffi libdrm)
 
+EAGLE_CFLAGS = -I../eagle
+EAGLE_LDLIBS = -L../eagle -leagle
+
 clients = flower pointer background window
 
 all : wayland $(clients)
 
 wayland_objs = wayland.o event-loop.o connection.o hash.o input.o egl-compositor.o
-wayland : CFLAGS += -I../eagle
-wayland : LDLIBS += -L../eagle -leagle -ldl
+wayland : CFLAGS += $(EAGLE_CFLAGS)
+wayland : LDLIBS += $(EAGLE_LDLIBS)
 
 wayland : $(wayland_objs)
        gcc -o $@ $(LDLIBS) $(wayland_objs)
@@ -20,7 +23,7 @@ libwayland.so : $(libwayland_objs)
 flower_objs = flower.o
 pointer_objs = pointer.o
 background_objs = background.o
-window_objs = window.o
+window_objs = window.o gears.o
 
 $(clients) : CFLAGS += $(shell pkg-config --cflags cairo)
 $(clients) : LDLIBS += $(shell pkg-config --libs cairo gdk-pixbuf-2.0) -lrt
@@ -28,6 +31,9 @@ $(clients) : LDLIBS += $(shell pkg-config --libs cairo gdk-pixbuf-2.0) -lrt
 background : CFLAGS += $(shell pkg-config --cflags gdk-pixbuf-2.0)
 background : LDLIBS += $(shell pkg-config --libs gdk-pixbuf-2.0)
 
+window : CFLAGS += $(EAGLE_CFLAGS)
+window : LDLIBS += $(EAGLE_LDLIBS)
+
 define client_template
 $(1): $$($(1)_objs) libwayland.so
 endef
diff --git a/gears.c b/gears.c
new file mode 100644 (file)
index 0000000..db79d4d
--- /dev/null
+++ b/gears.c
@@ -0,0 +1,207 @@
+#include <stdlib.h>
+#include <math.h>
+#include <GL/gl.h>
+#include "gears.h"
+
+struct gears {
+       GLint gear1, gear2, gear3;
+};
+
+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();
+}
+
+struct gears *
+gears_create(void)
+{
+       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};
+       static GLfloat pos[4] = {5.0, 5.0, 10.0, 0.0};
+       struct gears *gears;
+
+       gears = malloc(sizeof *gears);
+       /* make the gears */
+       gears->gear1 = glGenLists(1);
+       glNewList(gears->gear1, GL_COMPILE);
+       glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
+       gear(1.0, 4.0, 1.0, 20, 0.7);
+       glEndList();
+
+       gears->gear2 = glGenLists(1);
+       glNewList(gears->gear2, GL_COMPILE);
+       glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
+       gear(0.5, 2.0, 2.0, 10, 0.7);
+       glEndList();
+
+       gears->gear3 = glGenLists(1);
+       glNewList(gears->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);
+
+       glMatrixMode(GL_PROJECTION);
+       glLoadIdentity();
+       glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 200.0);
+       glMatrixMode(GL_MODELVIEW);
+
+       glLightfv(GL_LIGHT0, GL_POSITION, pos);
+       glEnable(GL_CULL_FACE);
+       glEnable(GL_LIGHTING);
+       glEnable(GL_LIGHT0);
+       glEnable(GL_DEPTH_TEST);
+
+       return gears;
+}
+
+void
+gears_draw(struct gears *gears, GLfloat angle)
+{
+       GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
+
+       glPushMatrix();
+
+       glTranslatef(0.0, 0.0, -50);
+
+       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(gears->gear1);
+       glPopMatrix();
+
+       glPushMatrix();
+       glTranslatef(3.1, -2.0, 0.0);
+       glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
+       glCallList(gears->gear2);
+       glPopMatrix();
+
+
+       glPushMatrix();
+       glTranslatef(-3.1, 4.2, 0.0);
+       glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
+       glCallList(gears->gear3);
+       glPopMatrix();
+
+       glPopMatrix();
+
+       glFlush();
+}
diff --git a/gears.h b/gears.h
new file mode 100644 (file)
index 0000000..76b8d63
--- /dev/null
+++ b/gears.h
@@ -0,0 +1,10 @@
+#ifndef _GEARS_H_
+#define _GEARS_H_
+
+struct gears;
+
+struct gears *gears_create(void);
+
+void gears_draw(struct gears *gears, GLfloat angle);
+
+#endif
index 0067488..7db8c2c 100644 (file)
--- a/window.c
+++ b/window.c
 #include <time.h>
 #include <cairo.h>
 
+#include <GL/gl.h>
+#include <eagle.h>
+
 #include "wayland-client.h"
+#include "gears.h"
 
 static const char gem_device[] = "/dev/dri/card0";
 static const char socket_name[] = "\0wayland";
 
+static void die(const char *msg)
+{
+       fprintf(stderr, "%s", msg);
+       exit(EXIT_FAILURE);
+}
+
 static uint32_t name_cairo_surface(int fd, cairo_surface_t *surface)
 {
        struct drm_i915_gem_create create;
@@ -75,6 +85,11 @@ struct window {
        uint32_t name;
        int fd;
        int need_redraw;
+
+       EGLDisplay display;
+       EGLContext context;
+       EGLConfig config;
+       EGLSurface egl_surface;
 };
 
 static void *
@@ -82,7 +97,7 @@ draw_window(struct window *window)
 {
        cairo_surface_t *surface;
        cairo_t *cr;
-       int border = 2, radius = 5;
+       int border = 2, radius = 5, h;
        int margin = (border + 1) / 2;
        cairo_text_extents_t extents;
        const static char title[] = "Wayland First Post";
@@ -108,8 +123,9 @@ draw_window(struct window *window)
        cairo_set_source_rgba(cr, 0, 0, 0, 1);
        cairo_set_font_size(cr, 14);
        cairo_text_extents(cr, title, &extents);
-       cairo_move_to(cr, margin, margin + radius + extents.height + 10);
-       cairo_line_to(cr, margin + window->width, margin + radius + extents.height + 10);
+       h = margin + radius + extents.height + 10;
+       cairo_move_to(cr, margin, h);
+       cairo_line_to(cr, margin + window->width, h);
        cairo_stroke(cr);
 
        cairo_move_to(cr, (window->width - extents.width) / 2, 10 - extents.y_bearing);
@@ -129,6 +145,24 @@ draw_window(struct window *window)
                       window->x, window->y,
                       window->width, window->height);
 
+       if (window->egl_surface != EGL_NO_SURFACE)
+               eglDestroySurface(window->display, window->egl_surface);
+
+       /* FIXME: We need to get the stride right here in a chipset
+        * independent way.  Maybe do it in name_cairo_surface(). */
+       window->egl_surface = eglCreatePixmapForName(window->display,
+                                                    window->config, window->name,
+                                                    window->width, window->height,
+                                                    window->stride, NULL);
+       if (surface == NULL)
+               die("failed to create surface\n");
+
+       if (!eglMakeCurrent(window->display,
+                           window->egl_surface, window->egl_surface, window->context))
+               die("failed to make context current\n");
+
+       glViewport(border, window->height - h - margin - 300, 300, 300);
+
        return surface;
 }
 
@@ -226,6 +260,30 @@ void event_handler(struct wl_display *display,
        }
 }
 
+static void
+init_egl(struct window *window)
+{
+       EGLint major, minor, count;
+       EGLConfig configs[64];
+
+       window->display = eglCreateDisplayNative("/dev/dri/card0", "i965");
+       if (window->display == NULL)
+               die("failed to create display\n");
+
+       if (!eglInitialize(window->display, &major, &minor))
+               die("failed to initialize display\n");
+
+       if (!eglGetConfigs(window->display, configs, 64, &count))
+               die("failed to get configs\n");
+
+       window->config = configs[24];
+       window->context = eglCreateContext(window->display, window->config, NULL, NULL);
+       if (window->context == NULL)
+               die("failed to create context\n");
+
+       window->egl_surface = EGL_NO_SURFACE;
+}
+
 int main(int argc, char *argv[])
 {
        struct wl_display *display;
@@ -234,6 +292,8 @@ int main(int argc, char *argv[])
        cairo_surface_t *s;
        struct pollfd p[1];
        struct window window;
+       struct gears *gears;
+       GLfloat angle = 0.0;
 
        fd = open(gem_device, O_RDWR);
        if (fd < 0) {
@@ -252,17 +312,23 @@ int main(int argc, char *argv[])
        window.surface = wl_display_create_surface(display);
        window.x = 200;
        window.y = 200;
-       window.width = 350;
-       window.height = 200;
+       window.width = 450;
+       window.height = 500;
        window.state = WINDOW_STABLE;
        window.fd = fd;
 
+       init_egl(&window);
+
        s = draw_window(&window);
 
        wl_display_set_event_handler(display, event_handler, &window);
 
-       while (ret = poll(p, 1, -1), ret >= 0) {
+       gears = gears_create();
+
+       while (ret = poll(p, 1, 20), ret >= 0) {
                mask = 0;
+               gears_draw(gears, angle);
+               angle += 1;
                if (p[0].revents & POLLIN)
                        mask |= WL_CONNECTION_READABLE;
                if (p[0].revents & POLLOUT)