summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'main.c')
-rw-r--r--main.c446
1 files changed, 446 insertions, 0 deletions
diff --git a/main.c b/main.c
new file mode 100644
index 0000000..afe1e51
--- /dev/null
+++ b/main.c
@@ -0,0 +1,446 @@
+/****************************************************************************
+** Authors: Matteo Muratori, Michele Fabbri.
+**
+** Official website: http://www.amanithvg.com
+**
+** Copyright (C) 2004-2009 Mazatech S.r.l. All rights reserved.
+**
+** This file is part of AmanithVG library.
+** Khronos and OpenVG are trademarks of The Khronos Group Inc.
+** OpenGL is a registered trademark and OpenGL ES is a trademark of
+** Silicon Graphics, Inc.
+**
+** This file is distributed under the terms of Mazatech End-User License
+** Agreement for Evaluation Purposes only as defined by Mazatech S.r.l. of
+** Italy and appearing in the file LICENSE.TXT included in the packaging
+** of this file.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+** For any informations, please contact info@mazatech.com
+**
+****************************************************************************/
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <X11/keysym.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+#include <EGL/egl.h>
+#include "tiger.h"
+
+//#define RENDERING_ON_VGIMAGE
+
+// X11 variables
+static Display *display;
+static Window window;
+static Atom atom_DELWIN;
+static Atom atom_PROTOCOLS;
+// EGL variables
+static EGLDisplay eglDisplay = EGL_NO_DISPLAY;
+static EGLConfig eglConfigWindow = 0;
+static EGLSurface eglWindowSurface = EGL_NO_SURFACE;
+static EGLContext eglContext = EGL_NO_CONTEXT;
+#if defined(RENDERING_ON_VGIMAGE)
+#include <VG/openvg.h>
+static EGLSurface eglPbufferSurface = EGL_NO_SURFACE;
+static EGLConfig eglConfigPbuffer = 0;
+static VGImage destImg = VG_INVALID_HANDLE;
+#endif
+// user input variables
+static unsigned int time0, time1, framesCount;
+static unsigned int done;
+
+static struct app *App = NULL;
+
+#define xy_method(name) static void name(int x, int y) { App->name(x,y); }
+#define void_method(name) static void name(void) { App->name(); }
+
+xy_method(initApp)
+void_method(killApp)
+xy_method(drawScene)
+xy_method(mouseLeftButtonDown)
+xy_method(mouseLeftButtonUp)
+xy_method(mouseRightButtonDown)
+xy_method(mouseRightButtonUp)
+xy_method(mouseMove)
+void_method(changeQuality)
+void_method(toggleAnimation)
+void_method(resetParameters)
+
+static void keyFunction(Display *dpy, Window wnd, const KeySym key) {
+
+ (void)dpy;
+ (void)wnd;
+
+ if (key == XK_b)
+ toggleAnimation();
+ else
+ if (key == XK_q)
+ changeQuality();
+ else
+ if (key == XK_r)
+ resetParameters();
+ else
+ if (key == XK_F1) {
+ }
+ else
+ if (key == XK_F2) {
+ }
+ else
+ if (key == XK_Escape)
+ done = 1;
+}
+
+static void processEvent(Display *dpy, Window wnd, XEvent *ev) {
+
+ switch (ev->type) {
+
+ case KeyPress:
+ keyFunction(dpy, wnd, XLookupKeysym(&ev->xkey, 0));
+ break;
+
+ case ButtonPress:
+ if (ev->xbutton.button == Button1)
+ mouseLeftButtonDown(ev->xbutton.x, ev->xbutton.y);
+ else
+ if (ev->xbutton.button == Button2 || ev->xbutton.button == Button3)
+ mouseRightButtonDown(ev->xbutton.x, ev->xbutton.y);
+ break;
+
+ case ButtonRelease:
+ if (ev->xbutton.button == Button1)
+ mouseLeftButtonUp(ev->xbutton.x, ev->xbutton.y);
+ else
+ if (ev->xbutton.button == Button2 || ev->xbutton.button == Button3)
+ mouseRightButtonUp(ev->xbutton.x, ev->xbutton.y);
+ break;
+
+ case MotionNotify:
+ mouseMove(ev->xmotion.x, ev->xmotion.y);
+ break;
+
+ case ConfigureNotify:
+ resetParameters();
+ break;
+
+ case ClientMessage:
+ if ((((XClientMessageEvent *)ev)->message_type == atom_PROTOCOLS) && (((XClientMessageEvent *)ev)->data.l[0] == (long)atom_DELWIN))
+ done = 1;
+ break;
+ }
+}
+
+static void processEvents(Display *dpy, Window wnd) {
+
+ XEvent event;
+ int i;
+
+ // check for incoming events
+ XFlush(dpy);
+
+ i = XPending(dpy);
+ if (i > 0) {
+ // get the next event in queue
+ XNextEvent(dpy, &event);
+ processEvent(dpy, wnd, &event);
+ i--;
+ for (; i > 0; --i)
+ XNextEvent(dpy, &event);
+ }
+}
+
+static Window createWindow(Display *dpy, const char *title, const unsigned int width, const unsigned int height) {
+
+ Window wnd;
+ int screen, screenDepth, screenWidth, screenHeight;
+ Visual *screenVisual;
+ XSetWindowAttributes windowAttributes;
+ XSizeHints windowSizeHints;
+
+ // get the default screen associated with the previously opened display
+ screen = DefaultScreen(display);
+ // get the default visual
+ screenVisual = DefaultVisual(display, screen);
+ // get screen bitdepth
+ screenDepth = DefaultDepth(display, screen);
+ // run only on a 32bpp display
+ if (screenDepth != 24 && screenDepth != 32)
+ return None;
+
+ // initialize window's attribute structure
+ windowAttributes.border_pixel = BlackPixel(display, screen);
+ windowAttributes.background_pixel = 0xCCCCCCCC;
+ windowAttributes.backing_store = NotUseful;
+ // get screen dimensions
+ screenWidth = DisplayWidth(display, screen);
+ screenHeight = DisplayHeight(display, screen);
+
+ // create the window centered on the screen
+ if (width == 0 || height == 0)
+ wnd = XCreateWindow(dpy, DefaultRootWindow(dpy), screenWidth / 4, screenHeight / 4, screenWidth / 2, screenHeight / 2, 0, screenDepth, InputOutput, screenVisual, CWBackPixel | CWBorderPixel | CWBackingStore, &windowAttributes);
+ else
+ wnd = XCreateWindow(dpy, DefaultRootWindow(dpy), (screenWidth - width) / 2, (screenHeight - height) / 2, width, height, 0, screenDepth, InputOutput, screenVisual, CWBackPixel | CWBorderPixel | CWBackingStore, &windowAttributes);
+ // check for errors
+ if (wnd == None)
+ return None;
+ // set the window's name
+ XStoreName(dpy, wnd, title);
+ // tell the server to report mouse and key-related events
+ XSelectInput(dpy, wnd, KeyPressMask | KeyReleaseMask | ButtonPressMask | Button1MotionMask | Button2MotionMask | Button3MotionMask | StructureNotifyMask);
+ // initialize window's sizehint definition structure
+ windowSizeHints.flags = PPosition | PMinSize | PMaxSize;
+ windowSizeHints.x = 0;
+ windowSizeHints.y = 0;
+ windowSizeHints.min_width = 1;
+ windowSizeHints.max_width = screenWidth;
+ windowSizeHints.min_height = 1;
+ windowSizeHints.max_height = screenHeight;
+ // set the window's sizehint
+ XSetWMNormalHints(dpy, wnd, &windowSizeHints);
+ // clear the window
+ XClearWindow(dpy, wnd);
+ // put the window on top of the others
+ XMapRaised(dpy, wnd);
+ // clear event queue
+ XFlush(dpy);
+
+ atom_DELWIN = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+ atom_PROTOCOLS = XInternAtom(dpy, "WM_PROTOCOLS", False);
+ XChangeProperty(dpy, wnd, atom_PROTOCOLS, XA_ATOM, 32, PropModeReplace, (unsigned char *)&atom_DELWIN, 1);
+ return wnd;
+}
+
+static void killWindow(Display *dpy, Window wnd) {
+
+ // close the window
+ XDestroyWindow(dpy, wnd);
+ // close the display
+ XCloseDisplay(dpy);
+}
+
+static unsigned int getTimeMS(void) {
+
+ struct timeval tp;
+ struct timezone tzp;
+
+ gettimeofday(&tp, &tzp);
+ return (unsigned int)((tp.tv_sec * 1000) + (tp.tv_usec / 1000));
+}
+
+static void updateTitle(Display *dpy, Window wnd) {
+
+ // print frame rate every second
+ time1 = getTimeMS();
+ if (time1 - time0 > 1000) {
+
+ char title[64];
+ float fps = ((float)framesCount * 1000.0f / (float)(time1 - time0));
+
+ sprintf(title, "AmanithVG tiger - Press F1 for help - FPS: %6.2f", fps);
+ XStoreName(dpy, wnd, title);
+ framesCount = 0;
+ time0 = time1;
+ }
+}
+
+static void messageDialog(const char *title, const char *message) {
+
+ fprintf(stderr, "%s: %s\n", title, message);
+}
+
+static unsigned int testEGLError(const char *msg) {
+
+ EGLint err = eglGetError();
+
+ if (err != EGL_SUCCESS) {
+
+ char errStr[64];
+
+ sprintf(errStr, "%s failed (%d)", msg, err);
+ messageDialog("EGL error", errStr);
+ return 0;
+ }
+ return 1;
+}
+
+static void destroyEGL(void) {
+
+ eglMakeCurrent(eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (eglWindowSurface != EGL_NO_SURFACE)
+ eglDestroySurface(eglDisplay, eglWindowSurface);
+#if defined(RENDERING_ON_VGIMAGE)
+ if (eglPbufferSurface != EGL_NO_SURFACE)
+ eglDestroySurface(eglDisplay, eglPbufferSurface);
+#endif
+ if (eglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(eglDisplay, eglContext);
+
+ eglTerminate(eglDisplay);
+}
+
+static unsigned int initEGL(Display *dpy, Window wnd) {
+
+ EGLint iMajorVersion, iMinorVersion;
+ int iConfigs;
+
+ EGLint attribListWindow[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_NONE
+ };
+
+#if defined(RENDERING_ON_VGIMAGE)
+ EGLint attribListPbuffer[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_NONE
+ };
+#endif
+
+ // get the default display
+ eglDisplay = eglGetDisplay((NativeDisplayType)dpy);
+ if (eglDisplay == EGL_NO_DISPLAY)
+ goto cleanup;
+
+ // initialize EGL
+ if (!eglInitialize(eglDisplay, &iMajorVersion, &iMinorVersion)) {
+ messageDialog("EGL error", "eglInitialize failed.");
+ goto cleanup;
+ }
+
+ // make OpenVG the current API
+ eglBindAPI(EGL_OPENVG_API);
+
+ // find a config that matches all requirements for the window surface
+ if (!eglChooseConfig(eglDisplay, attribListWindow, &eglConfigWindow, 1, &iConfigs) || (iConfigs != 1)) {
+ messageDialog("EGL error", "eglChooseConfig failed for window.");
+ goto cleanup;
+ }
+
+#if defined(RENDERING_ON_VGIMAGE)
+ // find a config that matches all requirements for the pbuffer surface
+ if (!eglChooseConfig(eglDisplay, attribListPbuffer, &eglConfigPbuffer, 1, &iConfigs) || (iConfigs != 1)) {
+ messageDialog("EGL error", "eglChooseConfig failed for pbuffer.");
+ goto cleanup;
+ }
+#endif
+
+ // create a window surface
+ eglWindowSurface = eglCreateWindowSurface(eglDisplay, eglConfigWindow, (NativeWindowType)wnd, NULL);
+ if (!testEGLError("eglCreateWindowSurface"))
+ goto cleanup;
+
+ // create a context
+ eglContext = eglCreateContext(eglDisplay, eglConfigWindow, EGL_NO_CONTEXT, NULL);
+ if (!testEGLError("eglCreateContext"))
+ goto cleanup;
+
+ // bind the context to the current thread and use our window surface for drawing and reading
+ eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
+ if (!testEGLError("eglMakeCurrent"))
+ goto cleanup;
+
+#if defined(RENDERING_ON_VGIMAGE)
+{
+ EGLint surfaceWidth, surfaceHeight;
+
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH, &surfaceWidth);
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT, &surfaceHeight);
+
+ destImg = vgCreateImage(VG_sARGB_8888_PRE, surfaceWidth, surfaceHeight, VG_IMAGE_QUALITY_BETTER);
+ eglPbufferSurface = eglCreatePbufferFromClientBuffer(eglDisplay, EGL_OPENVG_IMAGE, (EGLClientBuffer)destImg, eglConfigPbuffer, NULL);
+ if (!testEGLError("eglCreatePbufferFromClientBuffer"))
+ goto cleanup;
+}
+#endif
+
+ return 1;
+
+cleanup:
+ destroyEGL();
+ return 0;
+}
+
+int main(void) {
+
+ EGLint surfaceWidth, surfaceHeight;
+
+ App = &vg_tiger_app;
+ if (getenv("USECAIRO"))
+ App = &cairo_tiger_app;
+
+ // open the default display
+ display = XOpenDisplay(NULL);
+ if (display == NULL) {
+ messageDialog("Error", "Unable to open display.\n");
+ return EXIT_FAILURE;
+ }
+
+ // create the window
+ window = createWindow(display, "AmanithVG tiger - Press F1 for help - FPS: ", 480, 640);
+ if (window == None) {
+ messageDialog("Error", "Unable to create the main window");
+ XCloseDisplay(display);
+ return EXIT_FAILURE;
+ }
+
+ // initialize EGL
+ if (!initEGL(display, window)) {
+ killWindow(display, window);
+ return EXIT_FAILURE;
+ }
+
+ // init application
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH, &surfaceWidth);
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT, &surfaceHeight);
+ initApp(surfaceWidth, surfaceHeight);
+ // start frame counter
+ time0 = getTimeMS();
+ framesCount = 0;
+
+ done = 0;
+ while (!done) {
+
+ processEvents(display, window);
+
+ #if defined(RENDERING_ON_VGIMAGE)
+ // get pbuffer surface dimensions
+ eglQuerySurface(eglDisplay, eglPbufferSurface, EGL_WIDTH, &surfaceWidth);
+ eglQuerySurface(eglDisplay, eglPbufferSurface, EGL_HEIGHT, &surfaceHeight);
+ // make the pbuffer surface current
+ eglMakeCurrent(eglDisplay, eglPbufferSurface, eglPbufferSurface, eglContext);
+ drawScene(surfaceWidth, surfaceHeight);
+ // make the window surface current
+ eglMakeCurrent(eglDisplay, eglWindowSurface, eglWindowSurface, eglContext);
+ // put the image
+ vgSetPixels(0, 0, destImg, 0, 0, surfaceWidth, surfaceHeight);
+ #else
+ // get window surface dimensions
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_WIDTH, &surfaceWidth);
+ eglQuerySurface(eglDisplay, eglWindowSurface, EGL_HEIGHT, &surfaceHeight);
+ drawScene(surfaceWidth, surfaceHeight);
+ #endif
+ //eglSwapBuffers(eglDisplay, eglWindowSurface);
+
+ // advance frames counter and update windiw title
+ framesCount++;
+ updateTitle(display, window);
+ }
+
+ killApp();
+ destroyEGL();
+ killWindow(display, window);
+ return EXIT_SUCCESS;
+}