diff -urN gnash/backend/Renderer_ovg.cpp gnash-ovg/backend/Renderer_ovg.cpp
--- gnash/backend/Renderer_ovg.cpp	1970-01-01 08:00:00.000000000 +0800
+++ gnash-ovg/backend/Renderer_ovg.cpp	2010-06-29 16:04:03.488969183 +0800
@@ -0,0 +1,1230 @@
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+///
+/// Author: Visor <cutevisor@gmail.com>
+///
+
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <cstring>
+#include <cmath>
+
+#include "swf/ShapeRecord.h"
+#include "gnash.h"
+#include "RGBA.h"
+#include "GnashImage.h"
+#include "GnashNumeric.h"
+#include "log.h"
+#include "utility.h"
+#include "Range2d.h"
+
+#include "Renderer_ovg.h"
+#include "Matrix.h"
+
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+
+#include <sys/time.h>
+
+#define GNASH_IMAGE_QUALITY     VG_IMAGE_QUALITY_FASTER
+#define GNASH_RENDER_QUALITY    VG_RENDERING_QUALITY_FASTER
+
+#define  MAX_POINTS (4096)
+
+/// \file Renderer_ovg.cpp
+/// \brief The OpenVG renderer and related code.
+///
+
+namespace gnash {
+
+static int tex_size;
+
+typedef std::vector<Path> PathVec;
+typedef std::vector<geometry::Range2d<int> > ClipBounds;
+
+class eglScopeMatrix : public boost::noncopyable
+{
+public:
+  eglScopeMatrix(const SWFMatrix& m)
+  {
+    vgGetMatrix(orig_mat);
+
+    float mat[9];
+    memset(mat, 0, sizeof(mat));
+    mat[0] = m.sx  / 65536.0f;
+    mat[1] = m.shx / 65536.0f;
+    mat[3] = m.shy / 65536.0f;
+    mat[4] = m.sy  / 65536.0f;
+    mat[6] = m.tx;
+    mat[7] = m.ty;
+    vgMultMatrix(mat);
+  }
+  
+  ~eglScopeMatrix()
+  {
+    vgLoadMatrix(orig_mat);
+  }
+private:
+  VGfloat orig_mat[9];
+};
+
+#define MAX_SEG  (256)
+
+inline void startpath(VGPath path, const int x, const int y)
+{
+  VGubyte     gseg[1];
+  VGfloat     gdata[2];
+  
+  gseg[0] = VG_MOVE_TO;
+  gdata[0] = x;
+  gdata[1] = y;
+  vgAppendPathData (path, 1, gseg, gdata);
+}
+
+inline void closepath(VGPath path)
+{
+  VGubyte     gseg[1];
+  VGfloat     gdata[2];
+  
+  gseg[0] = VG_CLOSE_PATH;
+  vgAppendPathData (path, 1, gseg, gdata);
+}
+
+inline void preparepath(VGPath path, const std::vector<Edge>& edges,
+        const float& anchor_x, const float& anchor_y)
+{
+  VGubyte     gseg[MAX_SEG];
+  VGfloat     gdata[MAX_SEG*3*2];
+  int         scount = 0;
+  int         dcount = 0; 
+
+  point start(anchor_x, anchor_y);
+  point anchor(anchor_x, anchor_y);
+  
+  for (std::vector<Edge>::const_iterator it = edges.begin(), end = edges.end();
+        it != end; ++it) {
+      const Edge& the_edge = *it;
+      
+      point target(the_edge.ap.x, the_edge.ap.y);
+
+      if (the_edge.straight()) {
+        gseg[scount++]  = VG_LINE_TO;
+        gdata[dcount++] = target.x;
+        gdata[dcount++] = target.y;
+      } else {
+        gseg[scount++]  = VG_QUAD_TO;
+        gdata[dcount++] = the_edge.cp.x;
+        gdata[dcount++] = the_edge.cp.y;
+        gdata[dcount++] = target.x;
+        gdata[dcount++] = target.y; 
+      }
+      if (scount >= MAX_SEG-2) {
+          vgAppendPathData(path, scount, gseg, gdata);
+          scount = 0;
+          dcount = 0;
+      }
+      anchor = target;
+  }
+  
+  if (scount > 0)
+      vgAppendPathData (path, scount, gseg, gdata);
+}
+
+// Use the image class copy constructor; it's not important any more
+// what kind of image it is.
+bitmap_info_ovg::bitmap_info_ovg(GnashImage* img, VGImageFormat pixelformat, VGPaint paint) 
+:
+    _img(img),
+    _pixel_format(pixelformat),
+    _paint(paint)
+{
+    _width = _img->width();
+    _height = _img->height();
+  
+    if (_pixel_format == VG_sARGB_8888)
+        _image = vgCreateImage(VG_sARGB_8888, _width, _height, GNASH_IMAGE_QUALITY);    
+    
+    vgImageSubData(_image, _img->data(), _width * 4, VG_sARGB_8888,
+                   0, 0, _width, _height);
+    
+    tex_size += _width * _height * 4;
+    log_debug("Add Texture size:%d (%d x %d x %dbpp)", _width * _height * 4, _width, _height, 4);
+    log_debug("Current Texture size: %d", tex_size);
+}   
+    
+bitmap_info_ovg::~bitmap_info_ovg()
+{
+    tex_size -= _width * _height * 4;
+    log_debug("Remove Texture size:%d (%d x %d x %dbpp)", _width * _height * 4, _width, _height, 4);
+    log_debug("Current Texture size: %d", tex_size);
+
+    vgDestroyImage(_image);
+}
+
+void
+bitmap_info_ovg::apply(const gnash::SWFMatrix& bitmap_matrix,
+                       bitmap_wrap_mode wrap_mode) const
+{
+    gnash::SWFMatrix mat;
+    VGfloat     vmat[9];
+    
+    mat = bitmap_matrix;
+
+    vgSetParameteri (_paint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+    vgPaintPattern (_paint, _image);
+    
+    mat.invert();
+    memset(vmat, 0, sizeof(vmat));
+    vmat[0] = mat.sx  / 65536.0f;
+    vmat[1] = mat.shx / 65536.0f;
+    vmat[3] = mat.shy / 65536.0f;
+    vmat[4] = mat.sy  / 65536.0f;
+    vmat[6] = mat.tx;
+    vmat[7] = mat.ty;
+
+    
+    vgSeti (VG_MATRIX_MODE, VG_MATRIX_FILL_PAINT_TO_USER);
+    vgLoadMatrix (vmat);
+    vgSeti (VG_MATRIX_MODE, VG_MATRIX_STROKE_PAINT_TO_USER);
+    vgLoadMatrix (vmat);
+    vgSeti (VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+
+    if (wrap_mode == WRAP_CLAMP) {  
+        vgSetParameteri (_paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_PAD);
+    } else {
+        vgSetParameteri (_paint, VG_PAINT_PATTERN_TILING_MODE, VG_TILE_REPEAT);
+    }
+}
+
+template<typename C, typename T, typename R, typename A>
+void 
+for_each(C& container, R (T::*pmf)(const A&),const A& arg)
+{
+    std::for_each(container.begin(), container.end(),
+                  boost::bind(pmf, _1, boost::ref(arg)));
+}
+
+class DSOEXPORT Renderer_ovg : public Renderer_ovg_base
+{
+public: 
+    Renderer_ovg()
+        : m_display_width(0.0),
+          m_display_height(0.0),
+          _drawing_mask(false)
+    {
+        set_scale(1.0f, 1.0f);
+        m_fillpaint = vgCreatePaint();
+        m_strokepaint = vgCreatePaint();
+        
+        vgSetPaint (m_fillpaint,   VG_FILL_PATH);
+        vgSetPaint (m_strokepaint, VG_STROKE_PATH);
+    }
+  
+    void init(float x, float y)
+    {
+        m_display_width = x;
+        m_display_height = y;
+        // Turn on alpha blending.
+        vgSeti (VG_BLEND_MODE, VG_BLEND_SRC_OVER);
+        
+        vgSeti(VG_RENDERING_QUALITY, GNASH_RENDER_QUALITY);
+        vgSetf(VG_STROKE_LINE_WIDTH, 20.0f);
+    
+        VGfloat clearColor[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
+        vgSetfv( VG_CLEAR_COLOR, 4, clearColor );
+        
+        m_mask = vgCreateMaskLayer(x, y);
+    }
+  
+    ~Renderer_ovg()
+    {
+        vgDestroyPaint(m_fillpaint);
+        vgDestroyPaint(m_strokepaint);
+        vgDestroyMaskLayer(m_mask);
+    }
+
+    virtual BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im)
+    {
+        // OpenVG don't support 24bit RGB, need translate colorspace
+        switch (im->type())
+        {
+            case GNASH_IMAGE_RGBA:   
+                return new bitmap_info_ovg(im.get(), VG_sARGB_8888, m_fillpaint);
+            default:
+                std::abort();
+        }
+    }
+
+  // Since we store drawing operations in display lists, we take special care
+  // to store video frame operations in their own display list, lest they be
+  // anti-aliased with the rest of the drawing. Since display lists cannot be
+  // concatenated this means we'll add up with several display lists for normal
+  // drawing operations.
+  virtual void drawVideoFrame(GnashImage* frame, const SWFMatrix* m,
+          const rect* bounds, bool /*smooth*/)
+  {
+    log_unimpl("drawVideoFrame");  
+  }
+  
+  inline void world_to_pixel(int& x, int& y,
+    float world_x, float world_y)
+  {
+    // negative pixels seems ok here... we don't
+    // clip to valid range, use world_to_pixel(rect&)
+    // and Intersect() against valid range instead.
+    point p(world_x, world_y);
+    stage_matrix.transform(p);
+    x = (int)p.x;
+    y = (int)p.y;
+  }
+
+  geometry::Range2d<int> world_to_pixel(const rect& wb)
+  {
+    using namespace gnash::geometry;
+
+    if ( wb.is_null() ) return Range2d<int>(nullRange);
+    if ( wb.is_world() ) return Range2d<int>(worldRange);
+
+    int xmin, ymin, xmax, ymax;
+
+    world_to_pixel(xmin, ymin, wb.get_x_min(), wb.get_y_min());
+    world_to_pixel(xmax, ymax, wb.get_x_max(), wb.get_y_max());
+
+    return Range2d<int>(xmin, ymin, xmax, ymax);
+  }
+
+  geometry::Range2d<int> world_to_pixel(const geometry::Range2d<float>& wb)
+  {
+    if (wb.isNull() || wb.isWorld()) return wb;
+
+    int xmin, ymin, xmax, ymax;
+
+    world_to_pixel(xmin, ymin, wb.getMinX(), wb.getMinY());
+    world_to_pixel(xmax, ymax, wb.getMaxX(), wb.getMaxY());
+
+    return geometry::Range2d<int>(xmin, ymin, xmax, ymax);
+  }
+
+  point
+  pixel_to_world(int x, int y)
+  {
+    point p(x, y);
+    SWFMatrix mat = stage_matrix;
+    mat.invert().transform(p);
+    return p;
+  };
+
+  virtual void  begin_display(
+    const rgba& bg_color,
+    int viewport_x0, int viewport_y0,
+    int viewport_width, int viewport_height,
+    float x0, float x1, float y0, float y1)
+  {
+    vgSeti (VG_MASKING, VG_FALSE);
+
+    float mat[9];
+    memset(mat, 0, sizeof(mat));
+    mat[0] = (float)m_display_width / float(x1 - x0);  // scale sx
+    mat[1] = 0; // shx
+    mat[3] = 0; // shy
+    mat[4] = -((float)m_display_height / float(y1 - y0)); // scale sy
+    mat[6] = 0;   // shift tx
+    mat[7] = m_display_height;   // shift ty
+
+    vgSeti (VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+    vgLoadMatrix (mat);
+  }
+  
+  virtual void
+  end_display()
+  {
+  }
+  
+  /// Draw a line-strip directly, using a thin, solid line. 
+  //
+  /// Can be used to draw empty boxes and cursors.
+  virtual void drawLine(const std::vector<point>& coords, const rgba& fill,
+                  const SWFMatrix& mat)
+  {
+    VGubyte     gseg[MAX_SEG];
+    VGfloat     gdata[MAX_SEG*3*2];
+    int         scount = 0;
+    int         dcount = 0;
+    
+    if (coords.empty()) return;
+
+    eglScopeMatrix scope_mat(mat);
+
+    VGfloat color[] = {
+        fill.m_r / 255.0f,
+        fill.m_g / 255.0f,
+        fill.m_b / 255.0f,
+        1.0f
+    };
+    VGPath      vg_path;
+    vg_path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                            VG_PATH_DATATYPE_F,
+                            1, 0, 0, 0,
+                            VG_PATH_CAPABILITY_ALL);
+    vgSetf (VG_FILL_RULE, VG_EVEN_ODD );
+    vgSetParameteri (m_strokepaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+    vgSetParameterfv (m_strokepaint, VG_PAINT_COLOR, 4, color);
+    
+    std::vector<point>::const_iterator  it = coords.begin();
+    std::vector<point>::const_iterator end = coords.end();
+    
+    gseg[scount++] = VG_MOVE_TO;
+    gdata[dcount++] = (float)(*it).x;
+    gdata[dcount++] = (float)(*it).y;
+    ++it;            
+
+    for (; it != end; ++it)
+    {
+        gseg[scount++] = VG_LINE_TO;
+        gdata[dcount++] = (float)(*it).x;
+        gdata[dcount++] = (float)(*it).y;
+        if (scount >= MAX_SEG-1) {
+            vgAppendPathData(vg_path, scount, gseg, gdata);
+            scount = 0;
+            dcount = 0;
+        }
+    }
+
+    if (scount > 0)
+        vgAppendPathData(vg_path, scount, gseg, gdata);
+
+    vgSetf (VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
+    vgSetf (VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
+    vgSetf (VG_STROKE_LINE_WIDTH, 20.0f);
+
+    vgDrawPath (vg_path, VG_STROKE_PATH);
+    vgDestroyPath(vg_path);
+  }
+
+  virtual void  draw_poly(const point* corners, size_t corner_count, 
+    const rgba& fill, const rgba& outline, const SWFMatrix& mat, bool masked)
+  {
+    VGubyte     gseg[MAX_SEG];
+    VGfloat     gdata[MAX_SEG*3*2];
+    int         scount = 0;
+    int         dcount = 0;
+    
+    if (corner_count < 1) {
+      return;
+    }
+
+    unsigned int i;
+    
+    eglScopeMatrix scope_mat(mat);
+    
+    VGfloat color[] = {
+        fill.m_r / 255.0f,
+        fill.m_g / 255.0f,
+        fill.m_b / 255.0f,
+        fill.m_a / 255.0f
+    };
+    VGPath      vg_path;
+    vg_path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                            VG_PATH_DATATYPE_F,
+                            1, 0, 0, 0,
+                            VG_PATH_CAPABILITY_ALL);
+    vgSetf (VG_FILL_RULE, VG_NON_ZERO );
+
+    vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+    vgSetParameterfv (m_fillpaint, VG_PAINT_COLOR, 4, color);
+
+    const point *ptr = corners;
+    gseg[scount++] = VG_MOVE_TO;
+    gdata[dcount++] = (float)ptr->x;
+    gdata[dcount++] = (float)ptr->y;
+    ptr++;
+
+    for (i = 1; i < corner_count; i++)
+    {
+        gseg[scount++] = VG_LINE_TO;
+        gdata[dcount++] = (float)ptr->x;
+        gdata[dcount++] = (float)ptr->y;
+        ptr++;
+        if (scount >= MAX_SEG-2) {
+            vgAppendPathData(vg_path, scount, gseg, gdata);
+            scount = 0;
+            dcount = 0;
+        }
+    }
+    gseg[scount++] = VG_CLOSE_PATH;
+    vgAppendPathData (vg_path, scount, gseg, gdata);
+
+    vgDrawPath (vg_path, VG_FILL_PATH);
+    vgDestroyPath(vg_path);
+  }
+
+  virtual void  set_antialiased(bool enable)
+  {
+    log_unimpl("set_antialiased");
+  }
+    
+  virtual void begin_submit_mask()
+  {
+    PathVec mask;
+    _masks.push_back(mask);
+    
+    _drawing_mask = true;
+    
+  }
+  
+  virtual void end_submit_mask()
+  {
+
+    _drawing_mask = false;
+    
+    apply_mask();
+    
+  }
+
+  /// Apply the current mask; nesting is supported.
+  ///
+  /// This method marks the stencil buffer by incrementing every stencil pixel
+  /// by one every time a solid from one of the current masks is drawn. When
+  /// all the mask solids are drawn, we change the stencil operation to permit
+  /// only drawing where all masks have drawn, in other words, where all masks
+  /// intersect, or in even other words, where the stencil pixel buffer equals
+  /// the number of masks.
+  void apply_mask()
+  {
+  
+    if (_masks.empty()) {
+      return;
+    }
+
+    float mat[9];
+    float omat[9];
+    
+    vgSeti (VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE);
+    vgGetMatrix (omat);
+    
+    memset(mat, 0, sizeof(mat));
+    mat[0] =  stage_matrix.get_x_scale(); // scale sx
+    mat[1] =  0.0f; // shx
+    mat[3] =  0.0f; // shy
+    mat[4] =  -stage_matrix.get_x_scale(); // scale sy
+    mat[6] =  0;    // shift tx
+    mat[7] =  m_display_height;   // shift ty
+    vgLoadMatrix(mat);
+    
+    vgMask(m_mask, VG_FILL_MASK, 0, 0, m_display_width, m_display_height);
+
+    // Call add_paths for each mask.
+    std::for_each(_masks.begin(), _masks.end(),
+        boost::bind(&Renderer_ovg::add_paths, this, _1));    
+    vgSeti(VG_MASKING, VG_TRUE);      
+    vgLoadMatrix (omat);
+  }
+  
+  void
+  add_paths(const PathVec& path_vec)
+  {
+
+    cxform dummy_cx;
+    
+    fill_style coloring;
+    coloring.setSolid(rgba(0,255,0,255));
+            
+    draw_submask(path_vec, SWFMatrix(), dummy_cx, coloring);
+    
+  }
+  
+  virtual void disable_mask()
+  {
+  
+    _masks.pop_back();
+    
+    if (_masks.empty()) {
+      vgSeti (VG_MASKING, VG_FALSE);
+    } else {
+      apply_mask();
+    }
+            
+  }
+
+  Path reverse_path(const Path& cur_path)
+  {
+    const Edge& cur_end = cur_path.m_edges.back();    
+        
+    float prev_cx = cur_end.cp.x;
+    float prev_cy = cur_end.cp.y;        
+                
+    Path newpath(cur_end.ap.x, cur_end.ap.y, cur_path.m_fill1, cur_path.m_fill0, cur_path.m_line, cur_path.m_new_shape);
+    
+    float prev_ax = cur_end.ap.x;
+    float prev_ay = cur_end.ap.y; 
+
+    for (std::vector<Edge>::const_reverse_iterator it = cur_path.m_edges.rbegin()+1, end = cur_path.m_edges.rend();
+         it != end; ++it) {
+      const Edge& cur_edge = *it;
+
+      if (prev_ax == prev_cx && prev_ay == prev_cy) {
+        prev_cx = cur_edge.ap.x;
+        prev_cy = cur_edge.ap.y;      
+      }
+
+      Edge newedge(prev_cx, prev_cy, cur_edge.ap.x, cur_edge.ap.y); 
+          
+      newpath.m_edges.push_back(newedge);
+          
+      prev_cx = cur_edge.cp.x;
+      prev_cy = cur_edge.cp.y;
+      prev_ax = cur_edge.ap.x;
+      prev_ay = cur_edge.ap.y;
+           
+    }
+        
+    Edge newlastedge(prev_cx, prev_cy, cur_path.ap.x, cur_path.ap.y);    
+    newpath.m_edges.push_back(newlastedge);
+        
+    return newpath;
+  }
+  
+  const Path* find_connecting_path(const Path& to_connect,
+                                   std::list<const Path*> path_refs)
+  {
+        
+    float target_x = to_connect.m_edges.back().ap.x;
+    float target_y = to_connect.m_edges.back().ap.y;
+
+    if (target_x == to_connect.ap.x &&
+        target_y == to_connect.ap.y) {
+      return NULL;
+    }
+  
+    for (std::list<const Path*>::const_iterator it = path_refs.begin(), end = path_refs.end();
+         it != end; ++it) {
+      const Path* cur_path = *it;
+      
+      if (cur_path == &to_connect) {
+      
+        continue;
+      
+      }
+      
+            
+      if (cur_path->ap.x == target_x && cur_path->ap.y == target_y) {
+ 
+        if (cur_path->m_fill1 != to_connect.m_fill1) {
+          continue;
+        }
+        return cur_path;
+      }
+    }
+  
+  
+    return NULL;  
+  }
+  
+  PathVec normalize_paths(const PathVec &paths)
+  {
+    PathVec normalized;
+  
+    for (PathVec::const_iterator it = paths.begin(), end = paths.end();
+         it != end; ++it) 
+    {
+      const Path& cur_path = *it;
+      
+      if (cur_path.m_edges.empty()) {
+        continue;
+      
+      } else if (cur_path.m_fill0 && cur_path.m_fill1) {     
+        
+        // Two fill styles; duplicate and then reverse the left-filled one.
+        normalized.push_back(cur_path);
+        normalized.back().m_fill0 = 0; 
+     
+        Path newpath = reverse_path(cur_path);
+        newpath.m_fill0 = 0;        
+           
+        normalized.push_back(newpath);       
+
+      } else if (cur_path.m_fill0) {
+        // Left fill style.
+        Path newpath = reverse_path(cur_path);
+        newpath.m_fill0 = 0;
+           
+        normalized.push_back(newpath);
+      } else if (cur_path.m_fill1) {
+        // Right fill style.
+        normalized.push_back(cur_path);
+      } else {
+        // No fill styles; copy without modifying.
+        normalized.push_back(cur_path);
+      }
+
+    }
+    
+    return normalized;
+  }
+  
+  
+  /// Analyzes a set of paths to detect real presence of fills and/or outlines
+  /// TODO: This should be something the character tells us and should be 
+  /// cached. 
+  void analyze_paths(const PathVec &paths, bool& have_shape,
+    bool& have_outline) 
+  {
+    have_shape=false;
+    have_outline=false;
+    
+    int pcount = paths.size();
+    
+    for (int pno=0; pno<pcount; pno++) {
+    
+      const Path &the_path = paths[pno];
+    
+      if ((the_path.m_fill0>0) || (the_path.m_fill1>0)) {
+        have_shape=true;
+        if (have_outline) return; // have both
+      }
+    
+      if (the_path.m_line>0) {
+        have_outline=true;
+        if (have_shape) return; // have both
+      }
+    
+    }    
+  }
+
+  void apply_fill_style(const fill_style& style, const SWFMatrix& mat, const cxform& cx)
+  {
+      int fill_type = style.get_type();
+      
+      switch (fill_type) {
+
+        case SWF::FILL_LINEAR_GRADIENT:
+        case SWF::FILL_RADIAL_GRADIENT:
+        case SWF::FILL_FOCAL_GRADIENT:
+        {
+          const bitmap_info_ovg* binfo = static_cast<const bitmap_info_ovg*>(
+                      style.need_gradient_bitmap(*this));       
+
+          binfo->apply(style.getGradientMatrix(), bitmap_info_ovg::WRAP_CLAMP); 
+          vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+          break;
+        }        
+        case SWF::FILL_TILED_BITMAP_HARD:
+        case SWF::FILL_TILED_BITMAP:
+        {
+          const bitmap_info_ovg* binfo = static_cast<const bitmap_info_ovg*>(
+                    style.get_bitmap_info(*this));
+
+          binfo->apply(style.getBitmapMatrix(), bitmap_info_ovg::WRAP_REPEAT);
+          vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+          break;
+        }
+                
+        case SWF::FILL_CLIPPED_BITMAP:
+        case SWF::FILL_CLIPPED_BITMAP_HARD:
+        {     
+          const bitmap_info_ovg* binfo = dynamic_cast<const bitmap_info_ovg*>(
+                  style.get_bitmap_info(*this));
+          
+          binfo->apply(style.getBitmapMatrix(), bitmap_info_ovg::WRAP_CLAMP);
+          vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_PATTERN);
+          break;
+        } 
+
+        case SWF::FILL_SOLID:
+        {
+            rgba c = cx.transform(style.get_color());
+            VGfloat color[] = {
+                c.m_r / 255.0f,
+                c.m_g / 255.0f,
+                c.m_b / 255.0f,
+                c.m_a / 255.0f
+            };
+
+            vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+            vgSetParameterfv (m_fillpaint, VG_PAINT_COLOR, 4, color);
+        }
+        
+      } // switch
+  }
+  
+  bool apply_line_style(const line_style& style, const cxform& cx, const SWFMatrix& mat)
+  {
+    
+    bool rv = true;
+    
+    switch(style.joinStyle()) {
+        case JOIN_ROUND:
+            vgSetf (VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
+            break;
+        case JOIN_BEVEL:
+            vgSetf (VG_STROKE_JOIN_STYLE, VG_JOIN_BEVEL);
+            break;
+        case JOIN_MITER:
+            vgSetf (VG_STROKE_JOIN_STYLE, VG_JOIN_MITER);
+            break;
+        default:
+          log_unimpl("join style");
+    }
+
+    switch(style.startCapStyle()) {
+        case CAP_ROUND:
+            vgSetf (VG_STROKE_CAP_STYLE, VG_CAP_ROUND);
+            break;
+        case CAP_NONE:
+            vgSetf (VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
+            break;
+        case CAP_SQUARE:
+            vgSetf (VG_STROKE_CAP_STYLE, VG_CAP_SQUARE);
+            break;
+        default:
+            log_unimpl("cap style");
+    }
+
+    vgSetf (VG_STROKE_MITER_LIMIT, style.miterLimitFactor());
+
+    float width = style.getThickness();
+    
+    if (!width)
+    {
+      vgSetf(VG_STROKE_LINE_WIDTH, 20.0f);
+      rv = false; // Don't draw rounded lines.
+    }
+    else if ( (!style.scaleThicknessVertically()) && (!style.scaleThicknessHorizontally()) )
+    {
+      vgSetf(VG_STROKE_LINE_WIDTH, width);
+    }
+    else
+    {
+      if ( (!style.scaleThicknessVertically()) || (!style.scaleThicknessHorizontally()) )
+      {
+         LOG_ONCE( log_unimpl(_("Unidirectionally scaled strokes in OGL renderer")) );
+      }
+      
+      float stroke_scale = fabsf(mat.get_x_scale()) + fabsf(mat.get_y_scale());
+      stroke_scale /= 2.0f;
+      stroke_scale *= (stage_matrix.get_x_scale() + stage_matrix.get_y_scale()) / 2.0f;
+      width *= stroke_scale;
+
+      if (width < 20.0f)
+          width = 20.0f;
+
+      vgSetf(VG_STROKE_LINE_WIDTH, width);
+    }
+
+    rgba c = cx.transform(style.get_color());
+    VGfloat color[] = {
+        c.m_r / 255.0f,
+        c.m_g / 255.0f,
+        c.m_b / 255.0f,
+        c.m_a / 255.0f
+    };
+    
+
+    vgSetParameteri (m_strokepaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+    vgSetParameterfv (m_strokepaint, VG_PAINT_COLOR, 4, color);
+
+    return rv;
+  }
+ 
+  
+  typedef std::vector<const Path*> PathPtrVec;
+  
+  void
+  draw_outlines(const PathVec& path_vec, const SWFMatrix& mat,
+                const cxform& cx, const std::vector<line_style>& line_styles)
+  {
+      for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+           it != end; ++it) 
+      {
+    
+          const Path& cur_path = *it;
+        
+          if (!cur_path.m_line) {
+              continue;
+          }
+        
+          VGPath      vpath;
+          vpath = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                                VG_PATH_DATATYPE_F,
+                                1, 0, 0, 0,
+                                VG_PATH_CAPABILITY_ALL);
+          vgSetf (VG_FILL_RULE, VG_EVEN_ODD );
+          startpath(vpath, cur_path.ap.x, cur_path.ap.y);
+          preparepath(vpath, cur_path.m_edges, cur_path.ap.x,
+                                               cur_path.ap.y);
+        
+          apply_line_style(line_styles[cur_path.m_line-1], cx, mat);
+          vgDrawPath (vpath, VG_STROKE_PATH);
+          vgDestroyPath(vpath);
+      }
+  }
+
+  std::list<PathPtrVec> get_contours(const PathPtrVec &paths)
+  {
+    std::list<const Path*> path_refs;
+    std::list<PathPtrVec> contours;
+    
+    for (PathPtrVec::const_iterator it = paths.begin(), end = paths.end();
+         it != end; ++it) {
+      const Path* cur_path = *it;
+      path_refs.push_back(cur_path);
+    }
+        
+    for (std::list<const Path*>::const_iterator it = path_refs.begin(), end = path_refs.end();
+         it != end; ++it) {
+      const Path* cur_path = *it;
+      
+      if (cur_path->m_edges.empty()) {
+        continue;
+      }
+      
+      if (!cur_path->m_fill0 && !cur_path->m_fill1) {
+        continue;
+      }
+      
+      PathPtrVec contour;
+            
+      contour.push_back(cur_path);
+        
+      const Path* connector = find_connecting_path(*cur_path, path_refs);
+
+      while (connector) {       
+        contour.push_back(connector);
+
+        const Path* tmp = connector;
+        connector = find_connecting_path(*connector, std::list<const Path*>(boost::next(it), end));
+  
+        // make sure we don't iterate over the connecting path in the for loop.
+        path_refs.remove(tmp);
+        
+      } 
+      
+      contours.push_back(contour);   
+    }
+    
+    return contours;
+  }
+
+  
+  void draw_mask(const PathVec& path_vec)
+  { 
+   
+    for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+         it != end; ++it) {
+      const Path& cur_path = *it;
+      
+      if (cur_path.m_fill0 || cur_path.m_fill1) {
+        _masks.back().push_back(cur_path);
+        _masks.back().back().m_line = 0;    
+      }
+    }  
+
+  }
+  
+  PathPtrVec
+  paths_by_style(const PathVec& path_vec, unsigned int style)
+  {
+    PathPtrVec paths;
+    for (PathVec::const_iterator it = path_vec.begin(), end = path_vec.end();
+         it != end; ++it) {
+      const Path& cur_path = *it;
+      
+      if (cur_path.m_fill0 == style) {
+        paths.push_back(&cur_path);
+      }
+      
+      if (cur_path.m_fill1 == style) {
+        paths.push_back(&cur_path);
+      }
+      
+    }
+    return paths;
+  }
+  
+  
+  std::vector<PathVec::const_iterator>
+  find_subshapes(const PathVec& path_vec)
+  {
+    std::vector<PathVec::const_iterator> subshapes;
+    
+    PathVec::const_iterator it = path_vec.begin(),
+                            end = path_vec.end();
+                            
+    subshapes.push_back(it);
+    ++it;
+
+    for (;it != end; ++it) {
+      const Path& cur_path = *it;
+    
+      if (cur_path.m_new_shape) {
+        subshapes.push_back(it); 
+      } 
+    }
+
+    if (subshapes.back() != end) {
+      subshapes.push_back(end);
+    }
+    
+    return subshapes;
+  }
+  
+  /// Takes a path and translates it using the given SWFMatrix.
+  void
+  apply_matrix_to_paths(std::vector<Path>& paths, const SWFMatrix& mat)
+  {  
+    std::for_each(paths.begin(), paths.end(),
+                  boost::bind(&Path::transform, _1, boost::ref(mat)));
+  }  
+
+  void
+  draw_subshape(const PathVec& path_vec,
+    const SWFMatrix& mat,
+    const cxform& cx,
+    const std::vector<fill_style>& fill_styles,
+    const std::vector<line_style>& line_styles)
+  {
+      PathVec normalized = normalize_paths(path_vec);
+
+      for (size_t i = 0; i < fill_styles.size(); ++i) 
+      {
+          PathPtrVec paths = paths_by_style(normalized, i+1);
+      
+          if (!paths.size()) {
+              continue;
+          }
+      
+          std::list<PathPtrVec> contours = get_contours(paths);
+      
+          apply_fill_style(fill_styles[i], mat, cx);
+      
+          VGPath      vg_path;
+          vg_path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                                  VG_PATH_DATATYPE_F,
+                                  1, 0, 0, 0,
+                                  VG_PATH_CAPABILITY_ALL);              
+          vgSetf (VG_FILL_RULE, VG_EVEN_ODD );                                  
+
+          for (std::list<PathPtrVec>::const_iterator iter = contours.begin(),
+               final = contours.end(); iter != final; ++iter)
+          {
+              const PathPtrVec& refs = *iter;
+
+              startpath(vg_path, (*(refs[0])).ap.x, (*(refs[0])).ap.y);
+                                        
+              for (PathPtrVec::const_iterator it = refs.begin(), end = refs.end();
+                   it != end; ++it)
+              {
+                  const Path& cur_path = *(*it);
+                  if (!cur_path.m_fill0 && !cur_path.m_fill1)
+                      continue;
+                  preparepath(vg_path, cur_path.m_edges, cur_path.ap.x,
+                                                         cur_path.ap.y);
+              }
+              closepath(vg_path);
+          }
+          vgDrawPath (vg_path, VG_FILL_PATH);
+          vgDestroyPath(vg_path);
+
+      
+      }
+    
+      draw_outlines(normalized, mat, cx, line_styles);
+
+
+  }
+
+  void
+  draw_submask(const PathVec& path_vec,
+    const SWFMatrix& mat,
+    const cxform& cx,
+    const fill_style& f_style)
+  {
+
+      PathVec normalized = normalize_paths(path_vec);
+
+      PathPtrVec paths = paths_by_style(normalized, 1);
+
+      std::list<PathPtrVec> contours = get_contours(paths);
+
+      VGfloat color[] = {1.0f, 1.0f, 1.0f, 1.0f};
+
+      vgSetParameteri (m_fillpaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
+      vgSetParameterfv (m_fillpaint, VG_PAINT_COLOR, 4, color);
+
+            
+      VGPath      vg_path;
+      vg_path = vgCreatePath (VG_PATH_FORMAT_STANDARD,
+                              VG_PATH_DATATYPE_F,
+                              1, 0, 0, 0,
+                              VG_PATH_CAPABILITY_ALL);
+      vgSetf (VG_FILL_RULE, VG_EVEN_ODD );
+
+      for (std::list<PathPtrVec>::const_iterator iter = contours.begin(),
+           final = contours.end(); iter != final; ++iter)
+      {
+          const PathPtrVec& refs = *iter;
+          startpath(vg_path, (*(refs[0])).ap.x, (*(refs[0])).ap.y);
+          for (PathPtrVec::const_iterator it = refs.begin(), end = refs.end();
+               it != end; ++it)
+          {
+              const Path& cur_path = *(*it);
+              preparepath(vg_path, cur_path.m_edges, cur_path.ap.x,
+                                                     cur_path.ap.y);
+          }
+          closepath(vg_path);
+      }
+
+      vgRenderToMask(vg_path, VG_FILL_PATH, VG_INTERSECT_MASK);
+      vgDestroyPath(vg_path);
+  }
+
+// Drawing procedure:
+// 1. Separate paths by subshape.
+// 2. Separate subshapes by fill style.
+// 3. For every subshape/fill style combo:
+//  a. Separate contours: find closed shapes by connecting ends.
+//  b. Apply fill style.
+//  c. Feed the contours in the tesselator. (Render.)
+//  d. Draw outlines for every path in the subshape with a line style.
+//
+// 4. ...
+// 5. Profit!
+
+  virtual void
+  drawShape(const SWF::ShapeRecord& shape, const cxform& cx,
+          const SWFMatrix& mat)
+  {
+
+    const PathVec& path_vec = shape.paths();
+
+    if (!path_vec.size()) {
+      // No paths. Nothing to draw...
+        return;
+    }
+    if (_drawing_mask) {
+      PathVec scaled_path_vec = path_vec;
+      apply_matrix_to_paths(scaled_path_vec, mat);
+      draw_mask(scaled_path_vec); 
+      return;
+    }    
+
+    bool have_shape, have_outline;
+    
+    analyze_paths(path_vec, have_shape, have_outline);
+    
+    if (!have_shape && !have_outline) {
+      return;
+    }    
+    
+    eglScopeMatrix scope_mat(mat);
+
+    std::vector<PathVec::const_iterator> subshapes = find_subshapes(path_vec);
+    
+    const std::vector<fill_style>& fill_styles = shape.fillStyles();
+    const std::vector<line_style>& line_styles = shape.lineStyles();
+    
+    for (size_t i = 0; i < subshapes.size()-1; ++i) {
+      PathVec subshape_paths;
+      
+      if (subshapes[i] != subshapes[i+1]) {
+        subshape_paths = PathVec(subshapes[i], subshapes[i+1]);
+      } else {
+        subshape_paths.push_back(*subshapes[i]);
+      }
+      
+      draw_subshape(subshape_paths, mat, cx, fill_styles,
+                    line_styles);
+    }
+  }
+
+  virtual void drawGlyph(const SWF::ShapeRecord& rec, const rgba& c,
+         const SWFMatrix& mat)
+  {
+
+    if (_drawing_mask) abort();
+
+    if (rec.getBounds().is_null()) {
+        return;
+    }
+    
+    cxform dummy_cx;
+    std::vector<fill_style> glyph_fs;
+    
+    fill_style coloring;
+    coloring.setSolid(c);
+    
+    glyph_fs.push_back(coloring);
+    
+    std::vector<line_style> dummy_ls;
+    
+    eglScopeMatrix scope_mat(mat);
+    
+    draw_subshape(rec.paths(), mat, dummy_cx, glyph_fs, dummy_ls);
+
+  }
+
+  virtual void set_scale(float xscale, float yscale) {
+    _xscale = xscale;
+    _yscale = yscale;
+    stage_matrix.set_identity();
+    stage_matrix.set_scale(xscale/20.0f, yscale/20.0f);
+  }
+
+  virtual void set_invalidated_regions(const InvalidatedRanges& ranges)
+  {
+  }
+
+
+private:
+  
+    float _xscale;
+    float _yscale;
+    float _width; // Width of the movie, in world coordinates.
+    float _height;
+  
+    // Output size.
+    float m_display_width;
+    float m_display_height;
+  
+    std::vector<PathVec> _masks;
+    bool _drawing_mask;
+  
+    gnash::SWFMatrix stage_matrix;  // conversion from TWIPS to pixels
+    
+    VGPaint     m_fillpaint;
+    VGPaint     m_strokepaint;
+    
+    VGMaskLayer m_mask;
+}; // class Renderer_ovg
+  
+Renderer_ovg_base* create_Renderer_ovg()
+// Factory.
+{
+  Renderer_ovg_base* renderer = new Renderer_ovg();
+  return renderer;
+}
+  
+  
+  
+} // namespace gnash
+
+
+
diff -urN gnash/backend/Renderer_ovg.h gnash-ovg/backend/Renderer_ovg.h
--- gnash/backend/Renderer_ovg.h	1970-01-01 08:00:00.000000000 +0800
+++ gnash-ovg/backend/Renderer_ovg.h	2010-06-29 16:04:12.827232732 +0800
@@ -0,0 +1,106 @@
+// 
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// 
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+// 
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+
+///
+/// Author: Visor <cutevisor@gmail.com>
+///
+
+
+#ifndef GNASH_RENDER_HANDLER_OVG_H
+#define GNASH_RENDER_HANDLER_OVG_H
+
+#include <EGL/egl.h>
+#include <VG/openvg.h>
+#include <VG/vgu.h>
+#include <VG/vgext.h>
+
+#include "Renderer.h"
+#include "Geometry.h"
+#include "BitmapInfo.h"
+
+namespace gnash {
+
+typedef std::vector<const Path*> PathRefs;
+
+struct eglVertex {
+  eglVertex(float x, float y)
+    : _x(x), _y(y)
+  {
+  }
+  
+  eglVertex(const point& p)
+    : _x(p.x), _y(p.y)
+  {
+  }
+
+  VGfloat _x;
+  VGfloat _y;
+};
+
+typedef std::map<const Path*, VGPath > PathPointMap;
+
+class bitmap_info_ovg : public BitmapInfo
+{
+  public:
+  
+    /// Set line and fill styles for mesh & line_strip rendering.
+    enum bitmap_wrap_mode
+    {
+      WRAP_REPEAT,
+      WRAP_CLAMP
+    };
+    
+    bitmap_info_ovg(GnashImage* img, VGImageFormat pixelformat, VGPaint paint);
+    ~bitmap_info_ovg();
+
+    void apply(const gnash::SWFMatrix& bitmap_matrix,
+               bitmap_wrap_mode wrap_mode) const;
+
+    int _width;
+    int _height;
+
+  private:
+    
+    mutable GnashImage *_img;
+    VGImageFormat   _pixel_format;
+    mutable VGImage _image;
+    VGPaint         _paint;
+};
+
+class Renderer_ovg_base : public Renderer
+{
+public:
+
+  Renderer_ovg_base() { }
+
+  // virtual classes should have virtual destructors
+  virtual ~Renderer_ovg_base() {}
+
+  // these methods need to be accessed from outside:
+  virtual void init(float x, float y)=0;
+  
+};
+
+DSOEXPORT Renderer_ovg_base* create_Renderer_ovg();
+
+
+
+} // namespace gnash
+
+
+#endif // __RENDER_HANDLER_OVG_H__
+
diff -urN gnash/gui/egl.cpp gnash-ovg/gui/egl.cpp
--- gnash/gui/egl.cpp	1970-01-01 08:00:00.000000000 +0800
+++ gnash-ovg/gui/egl.cpp	2010-06-29 16:03:36.654626551 +0800
@@ -0,0 +1,1378 @@
+//
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+// -----------------------------------------------------------------------------
+   
+/// \page egl_input EGL GUI input devices
+///
+/// The framebuffer GUI supports various input devices through the modern
+/// Linux Input Subsystem (/dev/input/event*). Both standard mice and 
+/// touchscreen devices are supported.
+///
+/// Make sure the USE_INPUT_EVENTS macro is defined in fbsup.h so that
+/// the events system is enabled for the EGL GUI (this may be configurable
+/// at runtime sometime).
+///
+/// Since there can be multiple input devices in /dev/input/ you have to
+/// specify which device to use using the 
+///  POINTING_DEVICE environment variable for the mouse and
+///  KEYBOARD_DEVICE environment variable for the keyboard
+
+///
+/// Author: Visor <cutevisor@gmail.com>
+///
+   
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <fcntl.h>
+#include <cerrno>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <linux/fb.h>
+#include <linux/kd.h>
+#include "GnashSystemIOHeaders.h"
+#include <csignal>
+#include <cstdlib> // getenv
+
+#include "gnash.h"
+#include "gui.h"
+#include "eglsup.h"
+#include "log.h"
+#include "movie_root.h"
+#include "RunResources.h"
+
+#include "Renderer.h"
+#ifdef  RENDERER_GLES
+#include "Renderer_gles.h"
+#endif
+#ifdef  RENDERER_OVG
+#include "Renderer_ovg.h"
+#endif
+#include "GnashSleep.h" // for gnashSleep
+
+#include <linux/input.h>    // for /dev/input/event*
+
+#include <EGL/egl.h>
+
+#ifdef  RENDERER_GLES
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#endif
+
+#ifdef  RENDERER_OVG
+#include <VG/openvg.h>
+#include <VG/vgu.h>
+#endif
+
+//#define DEBUG_SHOW_FPS  // prints number of frames per second to STDOUT
+
+#ifdef DEBUG_SHOW_FPS
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+#endif
+
+// workaround until fatal_error() is implemented
+// that is not silent without -v switch
+//
+// The do { } while (0) strangeness here is the only general way to get a
+// compound statement that is lexically equivalent to a single one. Example:
+//   #define foo() { this(); that(); }
+//   if (a) foo();
+//   else bar();
+// would become
+//   if (a) { this(); that() ; } ; else bar()
+// which is a syntax error.
+
+#define fatal_error(args ...) \
+  do { fprintf(stderr, args); putc('\n', stderr); } while(0)
+
+//--
+
+namespace gnash
+{
+
+static EGLint const attrib32_list[] = {
+    EGL_RED_SIZE, 8,
+    EGL_GREEN_SIZE,8,
+    EGL_BLUE_SIZE, 8,
+    EGL_ALPHA_SIZE,8,
+#ifdef  RENDERER_GLES    
+    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+#ifdef  RENDERER_OVG
+    EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+    EGL_DEPTH_SIZE,0,
+    EGL_STENCIL_SIZE, 0,
+#endif
+    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+    EGL_NONE
+};
+
+static EGLint const attrib16_list[] = {
+    EGL_RED_SIZE, 5,
+    EGL_GREEN_SIZE,6,
+    EGL_BLUE_SIZE, 5,
+    EGL_ALPHA_SIZE,0,
+#ifdef  RENDERER_GLES    
+    EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+#ifdef  RENDERER_OVG
+    EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+    EGL_DEPTH_SIZE,0,
+    EGL_STENCIL_SIZE, 0,
+#endif
+    EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+    EGL_SAMPLE_BUFFERS, EGL_FALSE,
+    EGL_NONE
+};
+
+const EGLint window_attrib_list[] = {   EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
+                                        EGL_COLORSPACE, EGL_COLORSPACE_sRGB,
+                                        EGL_NONE };
+
+
+//---------------
+#ifdef DEBUG_SHOW_FPS
+double fps_timer=0;
+int fps_counter=0;
+void profile() {
+  int fd;
+  double uptime, idletime;
+  char buffer[20];
+  int readcount;
+
+  fd = open("/proc/uptime", O_RDONLY);
+  if (fd<0) return;
+  readcount = read(fd, buffer, sizeof(buffer)-1);
+  buffer[readcount]=0;
+  sscanf(buffer, "%lf %lf", &uptime, &idletime);
+  close(fd);
+  
+  fps_counter++;
+
+  if (fps_counter<2) {
+    fps_timer = uptime;
+    return;    
+  }
+  
+  printf("FPS: %.3f (%.2f)\n", fps_counter/(uptime-fps_timer), uptime-fps_timer);
+  
+}
+#endif
+//---------------
+
+int terminate_request = false;  // global scope to avoid GUI access
+
+/// Called on CTRL-C and alike
+void terminate_signal(int /*signo*/) {
+  terminate_request = true;
+}
+
+void user_signal(int /*signo*/) {
+}
+
+static unsigned int   fb_bpp;
+static unsigned int   fb_width;
+static unsigned int   fb_height;
+
+//---------------
+
+EGLGui::EGLGui(unsigned long xid, float scale, bool loop, RunResources& r)
+  : Gui(xid, scale, loop, r)
+{
+    fb_fd = -1;
+    fbmem = NULL;
+    m_pixmap = NULL;
+    
+#ifdef  USE_MOUSE
+    input_fd = -1;
+#endif
+
+    m_EGLXDisplay = EGL_NO_DISPLAY;
+    m_EGLXSurface = EGL_NO_SURFACE;
+    m_EGLXContext = EGL_NO_CONTEXT;
+    m_EGLXwin_native = NULL;
+  
+    signal(SIGINT,  terminate_signal);
+    signal(SIGTERM, terminate_signal);
+    signal(SIGUSR1, user_signal);
+    signal(SIGUSR2, user_signal);
+
+}
+
+EGLGui::~EGLGui()
+{
+    if (m_EGLXDisplay != EGL_NO_DISPLAY)
+    {  
+        eglMakeCurrent(m_EGLXDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+        if (m_EGLXContext != EGL_NO_CONTEXT)
+            eglDestroyContext(m_EGLXDisplay, m_EGLXContext);
+
+        if (m_EGLXSurface != EGL_NO_SURFACE)
+            eglDestroySurface(m_EGLXDisplay, m_EGLXSurface);
+
+        if (m_EGLXwin_native)
+            free(m_EGLXwin_native);
+
+        eglTerminate(m_EGLXDisplay);
+    }
+    
+    if (fb_fd > 0)
+        close(fb_fd);
+
+#ifdef  USE_MOUSE
+    if (input_fd >= 0)
+        close(input_fd);
+#endif
+
+    if (m_pixmap)
+        free(m_pixmap);
+}
+
+bool EGLGui::init(int /*argc*/, char *** /*argv*/)
+{
+#ifdef  USE_MOUSE
+    // Initialize mouse (don't abort if no mouse found)
+    if (!init_mouse()) {
+        // just report to the user, keep on going...
+        log_debug(_("You won't have any pointing input device, sorry."));
+    }
+#endif
+
+#ifdef  USE_KEYBOARD
+    // Initialize keyboard (still not critical)
+    if (!init_keyboard()) {   
+        log_debug(_("You won't have any keyboard input device, sorry."));
+    }
+#endif
+
+    // Open the framebuffer device
+    fb_fd = open("/dev/fb1", O_RDWR);
+    if (fb_fd<0) {
+        fatal_error("Could not open framebuffer device: %s", strerror(errno));
+        return false;
+    }
+    
+    // Load framebuffer properties
+    ioctl(fb_fd, FBIOGET_VSCREENINFO, &var_screeninfo);
+    ioctl(fb_fd, FBIOGET_FSCREENINFO, &fix_screeninfo);
+    log_debug(_("Framebuffer device uses %d bytes of memory."),
+        fix_screeninfo.smem_len);
+    log_debug(_("Video mode: %dx%d with %d bits per pixel."),
+        var_screeninfo.xres, var_screeninfo.yres, var_screeninfo.bits_per_pixel);
+
+    fbmem = (unsigned char *)
+        mmap(0, fix_screeninfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED /* MAP_PRIVATE*/, fb_fd, 0);
+
+    m_rowsize = var_screeninfo.xres * ((var_screeninfo.bits_per_pixel+7)/8);
+
+    fb_width = var_screeninfo.xres;
+    fb_height = var_screeninfo.yres;
+    fb_bpp = (var_screeninfo.bits_per_pixel+7)/8;
+
+    // Ok, now initialize EGL
+    return initialize_renderer();
+}
+
+bool EGLGui::initialize_renderer() {
+    int _width    = var_screeninfo.xres;
+    int _height   = var_screeninfo.yres;
+    int _bpp      = var_screeninfo.bits_per_pixel;
+    
+#ifdef  RENDERER_GLES    
+    Renderer_gles_base* handler;
+#endif
+#ifdef  RENDERER_OVG
+    Renderer_ovg_base* handler;
+#endif
+  
+    m_stage_width = _width;
+    m_stage_height = _height;
+  
+    _validbounds.setTo(0, 0, _width-1, _height-1);
+    
+    // choose apropriate pixel format
+  
+    log_debug(_("red channel: %d / %d"), var_screeninfo.red.offset, 
+        var_screeninfo.red.length);
+    log_debug(_("green channel: %d / %d"), var_screeninfo.green.offset, 
+        var_screeninfo.green.length);
+    log_debug(_("blue channel: %d / %d"), var_screeninfo.blue.offset, 
+        var_screeninfo.blue.length);
+    log_debug(_("Total bits per pixel: %d"), var_screeninfo.bits_per_pixel);
+
+
+    EGLConfig *configs = NULL;
+    int i;
+
+    EGLint major, minor;
+    /* see egl_config.c for a list of supported configs, this looks for
+    a 5650 (rgba) config, supporting OpenGL ES and windowed surfaces  */
+
+    /* step1 - get a display */
+    m_EGLXDisplay = eglGetDisplay( EGL_DEFAULT_DISPLAY );
+    if ( EGL_NO_DISPLAY == m_EGLXDisplay )
+    {
+        printf( "eglGetDisplay() failed (error 0x%x)\n", eglGetError() );
+        return false;
+    }
+
+    if ( EGL_FALSE == eglInitialize( m_EGLXDisplay, &major, &minor ) )
+    {
+        printf( "eglInitialize() failed (error 0x%x)\n", eglGetError() );
+        return false;
+    }
+    if ( EGL_FALSE == eglGetConfigs(m_EGLXDisplay, NULL, 0, &max_num_config) )
+    {
+        printf( "eglGetConfigs() failed to retrive the number of configs (error 0x%x)\n", eglGetError() );
+        return false;
+    }
+    if(max_num_config <= 0)
+    {
+        printf( "No EGLconfigs found\n" );
+        return false;
+    }
+    configs = (EGLConfig *)malloc( sizeof( EGLConfig) * max_num_config );
+    if ( NULL == configs )
+    {
+        printf( "Out of memory\n" );
+        return false;
+    }
+
+    /* step2 - bind to the wanted client API */
+#ifdef  RENDERER_GLES
+    if( EGL_FALSE == eglBindAPI( EGL_OPENGL_ES_API ) )
+    {
+        printf( "eglBindAPI() failed to retrive the number of configs (error 0x%x)\n", eglGetError() );
+        return 1;
+    }
+#endif
+#ifdef  RENDERER_OVG
+    if( EGL_FALSE == eglBindAPI( EGL_OPENVG_API ) )
+    {
+        printf( "eglBindAPI() failed to retrive the number of configs (error 0x%x)\n", eglGetError() );
+        return 1;
+    }
+#endif
+
+    /* step3 - find a suitable config */
+    if (_bpp == 32)
+    {
+        if ( EGL_FALSE == eglChooseConfig( m_EGLXDisplay, attrib32_list, configs, max_num_config, &m_EGLXNumOfConfigs ) )
+        {
+            printf( "eglChooseConfig() failed (error 0x%x)\n", eglGetError() );
+            free( configs );
+            return false;
+        }
+    }
+    else
+    {
+        if ( EGL_FALSE == eglChooseConfig( m_EGLXDisplay, attrib16_list, configs, max_num_config, &m_EGLXNumOfConfigs ) )
+        {
+            printf( "eglChooseConfig() failed (error 0x%x)\n", eglGetError() );
+            free( configs );
+            return false;
+        }
+    }
+    if ( 0 == m_EGLXNumOfConfigs )
+    {
+        printf( "eglChooseConfig() was unable to find a suitable config\n" );
+        free( configs );
+        return false;
+    }
+    /*Use this to explicitly check that the EGL config has the expected color depths */
+    for ( i=0; i<m_EGLXNumOfConfigs; i++ )
+    {
+        EGLint value;
+        if (_bpp == 32)
+        {
+        
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_RED_SIZE, &value );
+            if ( 8 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_GREEN_SIZE, &value );
+            if ( 8 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_BLUE_SIZE, &value );
+            if ( 8 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_ALPHA_SIZE, &value );
+            if ( 8 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_SAMPLES, &value );
+            if ( 4 != value ) continue;
+        }
+        else if (_bpp == 16)
+        {
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_RED_SIZE, &value );
+            if ( 5 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_GREEN_SIZE, &value );
+            if ( 6 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_BLUE_SIZE, &value );
+            if ( 5 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_ALPHA_SIZE, &value );
+            if ( 0 != value ) continue;
+            eglGetConfigAttrib( m_EGLXDisplay, configs[i], EGL_SAMPLES, &value );
+#ifdef  RENDERER_GLES            
+            if ( 4 != value ) continue;
+#endif
+#ifdef  RENDERER_OVG
+            if ( 0 != value ) continue;
+#endif
+        }
+        else
+             continue;
+        m_EGLXConfig = configs[i];
+        break;
+    }
+
+    /* step4 - create a window surface  */
+    m_EGLXwin_native = (fbdev_window *)malloc( sizeof( fbdev_window ) );
+    m_EGLXwin_native->width = _width;
+    m_EGLXwin_native->height = _height;
+    m_nativeWindow = (EGLNativeWindowType)m_EGLXwin_native;
+
+#ifdef  RENDERER_GLES
+    m_EGLXSurface = eglCreateWindowSurface( m_EGLXDisplay, m_EGLXConfig, m_nativeWindow, NULL );
+#endif
+#ifdef  RENDERER_OVG
+    m_EGLXSurface = eglCreateWindowSurface( m_EGLXDisplay, m_EGLXConfig, m_nativeWindow, window_attrib_list);
+#endif
+
+    if ( EGL_NO_SURFACE == m_EGLXSurface )
+    {
+        printf( "eglCreateWindowSurface failed (error 0x%x\n", eglGetError() );
+        free( configs );
+        return false;
+    }
+
+    /* step5 - create a context */
+    m_EGLXContext = eglCreateContext( m_EGLXDisplay, m_EGLXConfig, EGL_NO_CONTEXT, NULL );
+    if ( EGL_NO_CONTEXT == m_EGLXContext )
+    {
+        printf( "eglCreateContext failed (error 0x%x)\n", eglGetError() );
+        free( configs );
+        return false;
+    }
+    /* step6 - make the context and surface current */
+    if ( EGL_FALSE == eglMakeCurrent( m_EGLXDisplay, m_EGLXSurface, m_EGLXSurface, m_EGLXContext ) )
+    {
+        printf( "eglMakeCurrent failed (error 0x%x)\n", eglGetError() );
+        free( configs );
+        return false;
+    }       /* begin user code */
+
+    eglSwapInterval(m_EGLXDisplay, 0);
+    
+    free( configs );
+  
+    printf("Gnash EGL Frame width %d height %d bpp %d \n", _width, _height, _bpp);
+
+#ifdef  RENDERER_GLES
+    handler = create_Renderer_gles();
+#endif
+#ifdef  RENDERER_OVG
+    handler = create_Renderer_ovg();
+#endif
+
+    assert(handler!=NULL);
+    _renderer.reset(handler);
+
+    _runResources.setRenderer(boost::shared_ptr<Renderer>(_renderer));
+    
+    handler->init(_width, _height);
+  
+    return true;
+}
+
+bool EGLGui::run()
+{
+    struct timeval tv;
+
+    double start_timer;
+  
+    if (!gettimeofday(&tv, NULL))
+        start_timer = (double)tv.tv_sec + (double)tv.tv_usec / 1000000.0;
+    else
+        start_timer = 0.0;
+  
+    // let the GUI recompute the x/y scale factors to best fit the whole screen
+    resize_view(_validbounds.width(), _validbounds.height());
+
+    while (!terminate_request) {
+  
+        // wait the "heartbeat" inteval
+        gnashSleep(_interval * 10);
+        // TODO: Do we need to check the real time slept or is it OK when we woke
+        // up early because of some Linux signal sent to our process (and thus
+        // "advance" faster than the "heartbeat" interval)? - Udo
+  
+        // check input devices
+#ifdef  USE_MOUSE
+        check_mouse();
+#endif
+#ifdef  USE_KEYBOARD
+        check_keyboard();
+#endif
+        // advance movie  
+        Gui::advance_movie(this);
+    }
+  
+    return true;
+}
+
+
+void EGLGui::renderBuffer()
+{
+    if ( _drawbounds.size() == 0 ) return; // nothing to do..
+
+    eglSwapBuffers(m_EGLXDisplay, m_EGLXSurface);
+}
+
+bool EGLGui::createWindow(const char* /*title*/, int /*width*/, int /*height*/)
+{
+    // Framebuffer has no windows... :-)
+
+    return true;
+}
+
+bool EGLGui::createMenu()
+{
+    // no menu support! 
+    return true;
+}
+
+bool EGLGui::setupEvents()
+{
+    // events currently not supported!
+    return true;
+}
+
+void EGLGui::setInterval(unsigned int interval)
+{
+    _interval = interval;
+}
+
+void EGLGui::setTimeout(unsigned int /*timeout*/)
+{
+
+}
+
+void EGLGui::setFullscreen()
+{
+    // EGL GUI always runs fullscreen; ignore...
+}
+
+void EGLGui::unsetFullscreen()
+{
+    // EGL GUI always runs fullscreen; ignore...
+}
+
+void EGLGui::showMenu(bool /*show*/)
+{
+    log_unimpl(_("This GUI does not yet support menus"));
+}
+
+bool EGLGui::showMouse(bool /*show*/)
+{
+    log_unimpl(_("This GUI does not yet support a mouse pointer"));
+    // Should return true if the pointer was visible before call,
+    // otherwise false;
+    return true;
+}
+
+
+int EGLGui::valid_x(int x) {
+    if (x<0) x=0;
+    if (x>=m_stage_width) x=m_stage_width-1;
+    return x;
+}
+
+int EGLGui::valid_y(int y) {
+    if (y<0) y=0;
+    if (y>=m_stage_height) y=m_stage_height-1;
+    return y;
+}
+
+void EGLGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
+{
+    _renderer->set_invalidated_regions(ranges);
+
+    _drawbounds.clear();
+    
+    for (unsigned int rno=0; rno<ranges.size(); rno++) 
+    {
+  
+        geometry::Range2d<int> bounds = Intersection(
+            _renderer->world_to_pixel(ranges.getRange(rno)),
+            _validbounds);
+      
+        // it may happen that a particular range is out of the screen, which 
+        // will lead to bounds==null. 
+        if (bounds.isNull()) continue; 
+    
+        _drawbounds.push_back(bounds);
+      
+    }
+  
+}
+
+#ifdef  USE_MOUSE
+void EGLGui::read_mouse_data()
+{
+  if (input_fd<0) return;   // no mouse available
+  
+  int count;  
+  
+  unsigned char *ptr;
+  
+  ptr = mouse_buf + mouse_buf_size;
+  
+  count = read(input_fd, mouse_buf + mouse_buf_size, 
+    sizeof(mouse_buf) - mouse_buf_size);
+    
+  if (count<=0) return;
+  
+  mouse_buf_size += count;
+}
+
+#ifdef USE_MOUSE_PS2    
+bool EGLGui::mouse_command(unsigned char cmd, unsigned char *buf, int count) {
+  int n;
+  
+  // flush input buffer
+  char trash[16];
+  do {
+    n = read(input_fd, trash, sizeof trash);
+    if (n>0) 
+      log_debug(_("mouse_command: discarded %d bytes from input buffer"), n);
+  } while (n>0);
+  
+  // send command
+  write(input_fd, &cmd, 1);
+  
+  // read response (if any)
+  while (count>0) {
+    gnashSleep(250*1000); // 250 ms inter-char timeout (simple method)
+    // TODO: use select() instead
+    
+    n = read(input_fd, buf, count);
+    if (n<=0) return false;
+    count-=n;
+    buf+=n;
+  }
+  
+  return true;
+  
+} //command()
+#endif
+
+#ifdef USE_MOUSE_PS2    
+bool EGLGui::init_mouse() 
+{
+
+  // see http://www.computer-engineering.org/ps2mouse/
+  
+
+  // Try to open mouse device, be error tolerant (FD is kept open all the time)
+  input_fd = open(MOUSE_DEVICE, O_RDWR);
+  
+  if (input_fd<0) {
+    log_debug(_("Could not open " MOUSE_DEVICE ": %s"), strerror(errno));    
+    return false;
+  }
+  
+  unsigned char buf[10], byte;
+
+  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
+    log_error("Could not set non-blocking mode for mouse device: %s", strerror(errno));
+    close(input_fd);
+    input_fd=-1;
+    return false; 
+  }
+  
+  // Clear input buffer
+  while ( read(input_fd, buf, sizeof buf) > 0 ) { }
+  
+  // Reset mouse
+  if ((!mouse_command(0xFF, buf, 3)) || (buf[0]!=0xFA)) {
+    log_debug(_("Mouse reset failed"));
+    close(input_fd);
+    input_fd=-1;
+    return false; 
+  }
+  
+  // Get Device ID (not crucial, debug only)
+  if ((!mouse_command(0xF2, buf, 2)) || (buf[0]!=0xFA)) {
+    log_debug(_("WARNING: Could not detect mouse device ID"));
+  } else {
+    unsigned char devid = buf[1];
+    if (devid!=0)
+      log_debug(_("WARNING: Non-standard mouse device ID %d"), devid);
+  }
+  
+  // Enable mouse data reporting
+  if ((!mouse_command(0xF4, &byte, 1)) || (byte!=0xFA)) {
+    log_debug(_("Could not activate Data Reporting mode for mouse"));
+    close(input_fd);
+    input_fd=-1;
+    return false; 
+  }
+  
+  
+  log_debug(_("Mouse enabled."));
+      
+  mouse_x = 0;
+  mouse_y = 0;
+  mouse_btn = 0;
+  
+  return true;
+}
+#endif
+
+#ifdef USE_MOUSE_PS2    
+bool EGLGui::check_mouse() 
+{
+  if (input_fd<0) return false;   // no mouse available
+  
+  int i;
+  int xmove, ymove, btn, btn_changed;
+  
+  read_mouse_data();
+  
+  // resync
+  int pos = -1;
+  for (i=0; i<mouse_buf_size; i++)
+  if (mouse_buf[i] & 8) { // bit 3 must be high for the first byte
+    pos = i;
+    break;    
+  }
+  if (pos<0) return false; // no sync or no data
+  
+  if (pos>0) {
+    // remove garbage:
+    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+    mouse_buf_size -= pos;
+  }
+  
+  
+  if (mouse_buf_size >= 3) {
+  
+    xmove = mouse_buf[1];
+    ymove = mouse_buf[2];
+    btn = mouse_buf[0] & 1;
+    
+    if (mouse_buf[0] & 0x10) xmove = -(256-xmove);
+    if (mouse_buf[0] & 0x20) ymove = -(256-ymove);
+    
+    ymove *= -1; // vertical movement is upside-down
+    
+    log_debug(_("x/y %d/%d btn %d"), xmove, ymove, btn);
+
+    // movement    
+    mouse_x += xmove;
+    mouse_y += ymove;
+    
+    if (mouse_x<0) mouse_x=0;
+    if (mouse_y<0) mouse_y=0;
+    if (mouse_x>m_stage_width) mouse_x=m_stage_width;
+    if (mouse_y>m_stage_height) mouse_y=m_stage_height;
+    
+    //log_debug(_("mouse @ %d / %d, btn %d"), mouse_x, mouse_y, mouse_btn);
+    
+    notify_mouse_moved(mouse_x, mouse_y);
+    
+    // button
+    if (btn != mouse_btn) {
+      mouse_btn = btn;
+      
+      notify_mouse_clicked(btn, 1);  // mark=??
+      //log_debug(_("mouse click! %d"), btn);
+    }    
+
+    // remove from buffer
+    pos=3;
+    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+    mouse_buf_size -= pos;  
+    
+    return true;
+  
+  }
+  
+}
+#endif
+
+#ifdef USE_MOUSE_ETT    
+bool EGLGui::init_mouse()
+{
+  // Try to open mouse device, be error tolerant (FD is kept open all the time)
+  input_fd = open(MOUSE_DEVICE, O_RDWR);
+  
+  if (input_fd<0) {
+    log_debug(_("Could not open " MOUSE_DEVICE ": %s"), strerror(errno));    
+    return false;
+  }
+  
+  unsigned char buf[10];
+
+  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
+    log_error("Could not set non-blocking mode for touchpad device: %s", strerror(errno));
+    close(input_fd);
+    input_fd=-1;
+    return false; 
+  }
+  
+  // Clear input buffer
+  while ( read(input_fd, buf, sizeof buf) > 0 ) { }
+  
+  mouse_buf_size=0;
+  
+  log_debug(_("Touchpad enabled."));
+  return true;
+} 
+#endif
+
+#ifdef USE_MOUSE_ETT    
+bool EGLGui::check_mouse() 
+{
+  bool activity = false;
+  
+  if (input_fd<0) return false;   // no mouse available
+  
+  read_mouse_data();
+  
+  // resync
+  int pos = -1;
+  int i;
+  for (i=0; i<mouse_buf_size; i++)
+  if (mouse_buf[i] & 0x80) { 
+    pos = i;
+    break;    
+  }
+  if (pos<0) return false; // no sync or no data
+  
+  if (pos>0) {
+    //printf("touchscreen: removing %d bytes garbage!\n", pos);  
+    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+    mouse_buf_size -= pos;
+  }
+    
+  // packet complete?
+  while (mouse_buf_size > 4) {
+    /*
+    eTurboTouch version??
+    mouse_btn = ((mouse_buf[0] >> 4) & 1);
+    mouse_x = (mouse_buf[1] << 4) | (mouse_buf[2] >> 3);
+    mouse_y = (mouse_buf[3] << 4) | (mouse_buf[4] >> 3);
+    */
+
+    int new_btn = (mouse_buf[0] & 1);
+    int new_x = (mouse_buf[1] << 7) | (mouse_buf[2]);
+    int new_y = (mouse_buf[3] << 7) | (mouse_buf[4]);
+    
+    /*
+    printf("touchscreen: %02x %02x %02x %02x %02x | status %d, pos: %d/%d\n",
+      mouse_buf[0], mouse_buf[1], mouse_buf[2], mouse_buf[3], mouse_buf[4],   
+      new_btn, new_x, new_y);
+    */
+    
+    
+    new_x = (int)(((double)new_x - 355) / (1702 - 355) * 1536 + 256);
+    new_y = (int)(((double)new_y - 482) / (1771 - 482) * 1536 + 256);
+    
+    
+    new_x = new_x * m_stage_width / 2048;
+    new_y = (2048-new_y) * m_stage_height / 2048;
+    
+    if ((new_x!=mouse_x) || (new_y!=mouse_y)) {
+      mouse_x = new_x;
+      mouse_y = new_y;
+      notify_mouse_moved(mouse_x, mouse_y);
+      activity = true;
+    }
+    
+    if (new_btn != mouse_btn) {
+      mouse_btn = new_btn;      
+      notify_mouse_clicked(mouse_btn, 1);  // mask=?
+      activity = true;
+    }
+    
+    // remove from buffer
+    pos=5;
+    memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+    mouse_buf_size -= pos;    
+  }
+  
+  return activity;
+  
+}
+#endif
+
+#ifdef USE_INPUT_EVENTS   
+bool EGLGui::init_mouse()
+{
+  std::string dev;
+
+  char* devname = std::getenv("POINTING_DEVICE");
+  if (devname) dev = devname;
+  else dev = "/dev/input/event0";
+
+  // Try to open mouse device, be error tolerant (FD is kept open all the time)
+  input_fd = open(dev.c_str(), O_RDONLY);
+  
+  if (input_fd<0) {
+    log_debug(_("Could not open %s: %s"), dev.c_str(), strerror(errno));    
+    return false;
+  }
+  
+  log_debug(_("Pointing device %s open"), dev.c_str());
+  
+  if (fcntl(input_fd, F_SETFL, fcntl(input_fd, F_GETFL) | O_NONBLOCK)<0) {
+    log_error(_("Could not set non-blocking mode for pointing device: %s"), strerror(errno));
+    close(input_fd);
+    input_fd=-1;
+    return false; 
+  }
+  
+  return true;
+
+} //init_mouse
+
+void EGLGui::apply_ts_calibration(float* cx, float* cy, int rawx, int rawy) {
+
+  /*
+  <UdoG>:
+  This is a *very* simple method to translate raw touchscreen coordinates to
+  the screen coordinates. We simply to linear interpolation between two points.
+  Note this won't work well when the touchscreen is not perfectly aligned to
+  the screen (ie. slightly rotated). Standard touchscreen calibration uses
+  5 calibration points (or even 25). If someone can give me the formula, tell
+  me! I'm too lazy right now to do the math myself... ;)  
+  
+  And sorry for the quick-and-dirty implementation! I'm in a hurry...
+  */
+
+  float ref1x = m_stage_width  / 5 * 1;
+  float ref1y = m_stage_height / 5 * 1;
+  float ref2x = m_stage_width  / 5 * 4;
+  float ref2y = m_stage_height / 5 * 4;
+  
+  static float cal1x = 2048/5*1;   // very approximative default values
+  static float cal1y = 2048/5*4;
+  static float cal2x = 2048/5*4;
+  static float cal2y = 2048/5*1;
+  
+  static bool initialized=false; // woohooo.. better don't look at this code...
+  if (!initialized) {
+    initialized=true;
+    
+    char* settings = std::getenv("TSCALIB");
+    
+    if (settings) {
+    
+      // expected format: 
+      // 491,1635,1581,646      (cal1x,cal1y,cal2x,cal2y; all integers)
+
+      char buffer[1024];      
+      char* p1;
+      char* p2;
+      bool ok = false;
+      
+      snprintf(buffer, sizeof buffer, "%s", settings);
+      p1 = buffer;
+      
+      do {
+        // cal1x        
+        p2 = strchr(p1, ',');
+        if (!p2) continue; // stop here
+        *p2 = 0;
+        cal1x = atoi(p1);        
+        p1=p2+1;
+        
+        // cal1y        
+        p2 = strchr(p1, ',');
+        if (!p2) continue; // stop here
+        *p2 = 0;
+        cal1y = atoi(p1);        
+        p1=p2+1;
+        
+        // cal2x        
+        p2 = strchr(p1, ',');
+        if (!p2) continue; // stop here
+        *p2 = 0;
+        cal2x = atoi(p1);        
+        p1=p2+1;
+        
+        // cal2y        
+        cal2y = atoi(p1);
+        
+        ok = true;        
+        
+      } while (0);
+      
+      if (!ok)
+        log_debug(_("WARNING: Error parsing calibration data!"));
+      
+      log_debug(_("Using touchscreen calibration data: %.0f / %.0f / %.0f / %.0f"),
+        cal1x, cal1y, cal2x, cal2y);
+    
+    } else {
+      log_debug(_("WARNING: No touchscreen calibration settings found. "
+        "The mouse pointer most probably won't work precisely. Set "
+        "TSCALIB environment variable with correct values for better results"));
+    }
+    
+  } //!initialized
+
+
+  // real duty: 
+  *cx = (rawx-cal1x) / (cal2x-cal1x) * (ref2x-ref1x) + ref1x;
+  *cy = (rawy-cal1y) / (cal2y-cal1y) * (ref2y-ref1y) + ref1y;
+}
+
+bool EGLGui::check_mouse()
+{
+  bool activity = false;
+  
+  if (input_fd < 0) return false;
+
+  struct input_event ev;  // time,type,code,value
+  
+  static int new_mouse_x = 0; // all uncalibrated!
+  static int new_mouse_y = 0;
+  static int new_mouse_btn = 0;
+  
+  int notify_x=0;     // coordinate to be sent via notify_mouse_moved()
+  int notify_y=0;
+  bool move_pending = false;  // true: notify_mouse_moved() should be called
+  
+  // this is necessary for our quick'n'dirty touchscreen calibration: 
+  static int coordinatedebug = std::getenv("DUMP_RAW")!=NULL;
+  
+  // The while loop is limited because the kernel tends to send us hundreds
+  // of events while the touchscreen is touched. We don't loose any 
+  // information if we stop reading because the kernel will stop
+  // sending redundant information.
+  int loops=0;  
+  
+  // Assuming we will never read less than one full struct...  
+  
+  while ((loops++ < 100) && (read(input_fd, &ev, sizeof ev) == (sizeof ev))) {
+  
+    if (ev.type == EV_SYN) {    // synchronize (apply information)
+    
+      if ((new_mouse_x != mouse_x) || (new_mouse_y != mouse_y)) {
+      
+        mouse_x = new_mouse_x;
+        mouse_y = new_mouse_y;
+        
+        float cx, cy;
+        
+        if (std::getenv("TSCALIB"))  // ONLY convert when requested
+          apply_ts_calibration(&cx, &cy, mouse_x, mouse_y);
+        else
+          { cx=mouse_x; cy=mouse_y; }
+              
+        // Don't call notify_mouse_moved() here because this would lead to
+        // lots of calls, especially for touchscreens. Instead we save the
+        // coordinate and call notify_mouse_moved() only once.
+        notify_x = cx;
+        notify_y = cy;
+        move_pending = true;        
+      }
+      
+      if (new_mouse_btn != mouse_btn) {
+      
+        if (move_pending) {
+          notify_mouse_moved(notify_x, notify_y);
+          activity = true;
+          move_pending = false;
+        }
+      
+        mouse_btn = new_mouse_btn;
+        notify_mouse_clicked(mouse_btn, 1);  // mark=??
+        activity = true;
+      }
+
+      if (coordinatedebug)
+        printf("% 5d / % 5d / % 5d\n", mouse_x, mouse_y, mouse_btn);
+      
+    }
+  
+    if (ev.type == EV_KEY) {    // button down/up
+    
+      // don't care which button, we support only one...
+      new_mouse_btn = ev.value;      
+      
+    }
+      
+    if (ev.type == EV_ABS) {    // absolute coordinate
+      if (ev.code == ABS_X) new_mouse_x = ev.value;
+      if (ev.code == ABS_Y) new_mouse_y = ev.value;
+    }
+    
+    if (ev.type == EV_REL) {    // relative movement
+      if (ev.code == REL_X) new_mouse_x += ev.value;
+      if (ev.code == REL_Y) new_mouse_y += ev.value;
+      
+      if (new_mouse_x < 0) new_mouse_x=0;
+      if (new_mouse_y < 0) new_mouse_y=0;
+      
+      if (new_mouse_x > m_stage_width ) new_mouse_x = m_stage_width;
+      if (new_mouse_y > m_stage_height) new_mouse_y = m_stage_height;
+    }      
+  
+  } 
+  
+  if (move_pending) {
+    notify_mouse_moved(notify_x, notify_y);
+    activity = true;
+  }
+  
+  return activity;
+ 
+} //check_mouse
+#endif
+
+#endif //USE_MOUSE
+
+#ifdef  USE_KEYBOARD
+bool EGLGui::init_keyboard() 
+{
+  std::string dev;
+
+  char* devname = std::getenv("KEYBOARD_DEVICE");
+  if (devname) dev = devname;
+  else dev = "/dev/input/event0";
+
+  // Try to open keyboard device, be error tolerant (FD is kept open all the time)
+  keyb_fd = open(dev.c_str(), O_RDONLY);
+  
+  if (keyb_fd<0) {
+    log_debug(_("Could not open %s: %s"), dev.c_str(), strerror(errno));    
+    return false;
+  }
+  
+  log_debug(_("Keyboard device %s open"), dev.c_str());
+  
+  if (fcntl(keyb_fd, F_SETFL, fcntl(keyb_fd, F_GETFL) | O_NONBLOCK)<0) {
+    log_error(_("Could not set non-blocking mode for keyboard device: %s"), strerror(errno));
+    close(keyb_fd);
+    keyb_fd=-1;
+    return false; 
+  }
+  
+  return true;
+}
+
+gnash::key::code EGLGui::scancode_to_gnash_key(int code, bool shift) {
+ 
+  // NOTE: Scancodes are mostly keyboard oriented (ie. Q, W, E, R, T, ...)
+  // while Gnash codes are mostly ASCII-oriented (A, B, C, D, ...) so no
+  // direct conversion is possible.
+  
+  // TODO: This is a very *incomplete* list and I also dislike this method
+  // very much because it depends on the keyboard layout (ie. pressing "Z"
+  // on a german keyboard will print "Y" instead). So we need some 
+  // alternative...
+  
+  switch (code) {
+  
+    case KEY_1      : return !shift ? gnash::key::_1 : gnash::key::EXCLAM;
+    case KEY_2      : return !shift ? gnash::key::_2 : gnash::key::DOUBLE_QUOTE; 
+    case KEY_3      : return !shift ? gnash::key::_3 : gnash::key::HASH; 
+    case KEY_4      : return !shift ? gnash::key::_4 : gnash::key::DOLLAR; 
+    case KEY_5      : return !shift ? gnash::key::_5 : gnash::key::PERCENT; 
+    case KEY_6      : return !shift ? gnash::key::_6 : gnash::key::AMPERSAND; 
+    case KEY_7      : return !shift ? gnash::key::_7 : gnash::key::SINGLE_QUOTE; 
+    case KEY_8      : return !shift ? gnash::key::_8 : gnash::key::PAREN_LEFT; 
+    case KEY_9      : return !shift ? gnash::key::_9 : gnash::key::PAREN_RIGHT; 
+    case KEY_0      : return !shift ? gnash::key::_0 : gnash::key::ASTERISK;
+                            
+    case KEY_A      : return shift ? gnash::key::A : gnash::key::a;
+    case KEY_B      : return shift ? gnash::key::B : gnash::key::b;
+    case KEY_C      : return shift ? gnash::key::C : gnash::key::c;
+    case KEY_D      : return shift ? gnash::key::D : gnash::key::d;
+    case KEY_E      : return shift ? gnash::key::E : gnash::key::e;
+    case KEY_F      : return shift ? gnash::key::F : gnash::key::f;
+    case KEY_G      : return shift ? gnash::key::G : gnash::key::g;
+    case KEY_H      : return shift ? gnash::key::H : gnash::key::h;
+    case KEY_I      : return shift ? gnash::key::I : gnash::key::i;
+    case KEY_J      : return shift ? gnash::key::J : gnash::key::j;
+    case KEY_K      : return shift ? gnash::key::K : gnash::key::k;
+    case KEY_L      : return shift ? gnash::key::L : gnash::key::l;
+    case KEY_M      : return shift ? gnash::key::M : gnash::key::m;
+    case KEY_N      : return shift ? gnash::key::N : gnash::key::n;
+    case KEY_O      : return shift ? gnash::key::O : gnash::key::o;
+    case KEY_P      : return shift ? gnash::key::P : gnash::key::p;
+    case KEY_Q      : return shift ? gnash::key::Q : gnash::key::q;
+    case KEY_R      : return shift ? gnash::key::R : gnash::key::r;
+    case KEY_S      : return shift ? gnash::key::S : gnash::key::s;
+    case KEY_T      : return shift ? gnash::key::T : gnash::key::t;
+    case KEY_U      : return shift ? gnash::key::U : gnash::key::u;
+    case KEY_V      : return shift ? gnash::key::V : gnash::key::v;
+    case KEY_W      : return shift ? gnash::key::W : gnash::key::w;
+    case KEY_X      : return shift ? gnash::key::X : gnash::key::x;
+    case KEY_Y      : return shift ? gnash::key::Y : gnash::key::y;
+    case KEY_Z      : return shift ? gnash::key::Z : gnash::key::z;
+
+    case KEY_F1     : return gnash::key::F1; 
+    case KEY_F2     : return gnash::key::F2; 
+    case KEY_F3     : return gnash::key::F3; 
+    case KEY_F4     : return gnash::key::F4; 
+    case KEY_F5     : return gnash::key::F5; 
+    case KEY_F6     : return gnash::key::F6; 
+    case KEY_F7     : return gnash::key::F7; 
+    case KEY_F8     : return gnash::key::F8; 
+    case KEY_F9     : return gnash::key::F9;
+    case KEY_F10    : return gnash::key::F10;
+    case KEY_F11    : return gnash::key::F11;
+    case KEY_F12    : return gnash::key::F12;
+    
+    case KEY_KP0    : return gnash::key::KP_0; 
+    case KEY_KP1    : return gnash::key::KP_1; 
+    case KEY_KP2    : return gnash::key::KP_2; 
+    case KEY_KP3    : return gnash::key::KP_3; 
+    case KEY_KP4    : return gnash::key::KP_4; 
+    case KEY_KP5    : return gnash::key::KP_5; 
+    case KEY_KP6    : return gnash::key::KP_6; 
+    case KEY_KP7    : return gnash::key::KP_7; 
+    case KEY_KP8    : return gnash::key::KP_8; 
+    case KEY_KP9    : return gnash::key::KP_9;
+
+    case KEY_KPMINUS       : return gnash::key::KP_SUBTRACT;
+    case KEY_KPPLUS        : return gnash::key::KP_ADD;
+    case KEY_KPDOT         : return gnash::key::KP_DECIMAL;
+    case KEY_KPASTERISK    : return gnash::key::KP_MULITPLY;  // typo in GnashKey.h
+    case KEY_KPENTER       : return gnash::key::KP_ENTER;
+    
+    case KEY_ESC           : return gnash::key::ESCAPE;
+    case KEY_MINUS         : return gnash::key::MINUS;
+    case KEY_EQUAL         : return gnash::key::EQUALS;
+    case KEY_BACKSPACE     : return gnash::key::BACKSPACE;
+    case KEY_TAB           : return gnash::key::TAB;
+    case KEY_LEFTBRACE     : return gnash::key::LEFT_BRACE;
+    case KEY_RIGHTBRACE    : return gnash::key::RIGHT_BRACE;
+    case KEY_ENTER         : return gnash::key::ENTER;
+    case KEY_LEFTCTRL      : return gnash::key::CONTROL;
+    case KEY_SEMICOLON     : return gnash::key::SEMICOLON;
+    //case KEY_APOSTROPHE    : return gnash::key::APOSTROPHE;  
+    //case KEY_GRAVE         : return gnash::key::GRAVE;
+    case KEY_LEFTSHIFT     : return gnash::key::SHIFT;
+    case KEY_BACKSLASH     : return gnash::key::BACKSLASH;
+    case KEY_COMMA         : return gnash::key::COMMA;
+    case KEY_SLASH         : return gnash::key::SLASH;
+    case KEY_RIGHTSHIFT    : return gnash::key::SHIFT;
+    case KEY_LEFTALT       : return gnash::key::ALT;
+    case KEY_SPACE         : return gnash::key::SPACE;
+    case KEY_CAPSLOCK      : return gnash::key::CAPSLOCK;
+    case KEY_NUMLOCK       : return gnash::key::NUM_LOCK;
+    //case KEY_SCROLLLOCK    : return gnash::key::SCROLLLOCK;
+    
+    case KEY_UP            : return gnash::key::UP;
+    case KEY_DOWN          : return gnash::key::DOWN;
+    case KEY_LEFT          : return gnash::key::LEFT;
+    case KEY_RIGHT         : return gnash::key::RIGHT;
+    case KEY_PAGEUP        : return gnash::key::PGUP;
+    case KEY_PAGEDOWN      : return gnash::key::PGDN;
+    case KEY_INSERT        : return gnash::key::INSERT;
+    case KEY_DELETE        : return gnash::key::DELETEKEY;
+    case KEY_HOME          : return gnash::key::HOME;
+    case KEY_END           : return gnash::key::END;
+    
+  }
+  
+  return gnash::key::INVALID;  
+}
+
+bool EGLGui::check_keyboard()
+{
+  bool activity = false;
+  
+  if (keyb_fd < 0) return false;
+
+  struct input_event ev;  // time,type,code,value
+
+  
+  while (read(keyb_fd, &ev, sizeof ev) == (sizeof ev)) {
+  
+    if (ev.type == EV_KEY) {
+    
+      // code == scan code of the key (KEY_xxxx defines in input.h)
+      
+      // value == 0  key has been released
+      // value == 1  key has been pressed
+      // value == 2  repeated key reporting (while holding the key) 
+
+      if (ev.code==KEY_LEFTSHIFT) 
+        keyb_lshift = ev.value;
+      else
+      if (ev.code==KEY_RIGHTSHIFT) 
+        keyb_rshift = ev.value;
+      else
+      if (ev.code==KEY_LEFTCTRL) 
+        keyb_lctrl = ev.value;
+      else
+      if (ev.code==KEY_RIGHTCTRL) 
+        keyb_rctrl = ev.value;
+      else
+      if (ev.code==KEY_LEFTALT) 
+        keyb_lalt = ev.value;
+      else
+      if (ev.code==KEY_RIGHTALT) 
+        keyb_ralt = ev.value;
+      else {
+      
+        gnash::key::code  c = scancode_to_gnash_key(ev.code, 
+          keyb_lshift || keyb_rshift);
+      
+        // build modifier
+      
+        int modifier = gnash::key::GNASH_MOD_NONE;
+        
+        if (keyb_lshift || keyb_rshift)
+          modifier = modifier | gnash::key::GNASH_MOD_SHIFT;
+
+        if (keyb_lctrl || keyb_rctrl)
+          modifier = modifier | gnash::key::GNASH_MOD_CONTROL;
+
+        if (keyb_lalt || keyb_ralt)
+          modifier = modifier | gnash::key::GNASH_MOD_ALT;
+          
+          
+        // send event
+        if (c != gnash::key::INVALID) {
+          Gui::notify_key_event(c, modifier, ev.value);
+          activity=true;
+        }
+              
+      } //if normal key
+
+    } //if EV_KEY      
+  
+  } //while
+  
+  return activity;
+
+}
+#endif // USE_KEYBOARD
+
+// end of namespace gnash
+}
diff -urN gnash/gui/eglsup.h gnash-ovg/gui/eglsup.h
--- gnash/gui/eglsup.h	1970-01-01 08:00:00.000000000 +0800
+++ gnash-ovg/gui/eglsup.h	2010-06-29 16:03:52.926508535 +0800
@@ -0,0 +1,218 @@
+//
+//   Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program 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 General Public License for more details.
+// 
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+///
+/// Author: Visor <cutevisor@gmail.com>
+///
+
+
+#ifndef __EGLSUP_H__
+#define __EGLSUP_H__
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <vector>
+
+#include "gui.h"
+#include <linux/fb.h>
+
+#include <EGL/egl.h>
+
+#ifdef  RENDERER_OVG
+#include <VG/openvg.h>
+#include <VG/vgu.h>
+#endif
+
+#ifdef  RENDERER_GLES
+#include <GLES/gl.h>
+#include <GLES/glext.h>
+#endif
+//#define PIXELFORMAT_LUT8
+#define CMAP_SIZE (256*2)
+
+//#define USE_MOUSE
+//#define USE_KEYBOARD
+
+// Define this to read from /dev/input/mice (any PS/2 compatbile mouse or
+// emulated by the Kernel) 
+//#define USE_MOUSE_PS2
+
+// Define this to read from /dev/input/event0 (new generic input subsystem)
+#define USE_INPUT_EVENTS
+
+// Define this to support eTurboTouch / eGalax touchscreens. When reading from
+// a serial device, it must be initialized (stty) externally. 
+//#define USE_MOUSE_ETT
+
+#ifdef USE_MOUSE_PS2
+#define MOUSE_DEVICE "/dev/input/mice"
+#endif
+
+#ifdef USE_MOUSE_ETT
+#define MOUSE_DEVICE "/dev/usb/tkpanel0"
+#endif
+
+namespace gnash
+{
+
+
+/// A Framebuffer-based GUI for Gnash.
+/// ----------------------------------
+///
+/// This is a simple "GUI" that works with any framebuffer device (/dev/fb0).
+/// No window system is required, it will run straigt from a console. 
+///
+/// The current version requires that your system boots in graphics mode (that
+/// is, with a framebuffer driver - like vesafb - and most probably the 
+/// virtual console enabled). Which graphics mode Gnash runs in depends on the 
+/// mode your machine boots in and can be choosen using the kernel command line.
+/// With other words: Gnash does not change the graphics mode.
+/// Refer to the framebuffer docs for more information.
+///
+/// The fb gui now also supports pointing devices like mice or touchscreens, but
+/// it is not required. It works with /dev/input/mice so any PS/2 compatible 
+/// mouse should do. Your kernel can emulate the "mice" device for other devices
+/// (like touchscreens and tablets) so this method is very flexible.
+///
+/// There is currently no visible mouse pointer built in, which is fine for 
+/// touchscreens but will make it difficult for standard mice. This will be 
+/// fixed in near time.
+//
+/// Supported graphics modes:
+///
+///   Resolution: any
+///
+///   Pixel formats:
+///     16 bit: R5/G6/B5
+///     32 bit: R8/G8/B8/A8, B8/G8/R8/A8
+///
+///
+/// Supported input devices:
+///
+///   any PS/2 compatible mouse (may be emulated by the kernel) talking 
+///   to /dev/input/mice
+
+
+class EGLGui : public Gui
+{
+private:
+    EGLConfig   m_EGLXConfig;
+    EGLContext  m_EGLXContext;
+    EGLSurface  m_EGLXSurface;
+    EGLDisplay  m_EGLXDisplay;
+    EGLint      m_EGLXNumOfConfigs;
+    EGLNativeWindowType  m_nativeWindow;
+    fbdev_window* m_EGLXwin_native;
+    EGLint      max_num_config;
+    fbdev_pixmap* m_pixmap;
+
+    std::vector< geometry::Range2d<int> > _drawbounds;
+
+    int m_stage_width;
+    int m_stage_height;
+    unsigned m_rowsize;
+
+    int            fb_fd;
+    unsigned char *fbmem;
+
+#ifdef  USE_MOUSE
+  	int input_fd; /// file descriptor for /dev/input/mice
+  	int mouse_x, mouse_y, mouse_btn;
+  	unsigned char mouse_buf[256];
+  	int mouse_buf_size;
+#endif
+
+#ifdef  USE_KEYBOARD
+  	int keyb_fd; /// file descriptor for /dev/input/event* (keyboard)
+
+  	// Keyboard SHIFT/CTRL/ALT states (left + right)
+  	bool keyb_lshift, keyb_rshift, keyb_lctrl, keyb_rctrl, keyb_lalt, keyb_ralt;
+#endif
+
+    struct fb_var_screeninfo var_screeninfo;
+  	struct fb_fix_screeninfo fix_screeninfo;
+
+  	bool initialize_renderer();
+  	
+
+#ifdef  USE_MOUSE
+
+#ifdef USE_MOUSE_PS2  	
+  	/// Sends a command to the mouse and waits for the response
+  	bool mouse_command(unsigned char cmd, unsigned char *buf, int count);
+#endif
+
+    /// Fills the mouse data input buffer with fresh data
+    void read_mouse_data();  	
+  	
+  	/// Initializes mouse routines
+  	bool init_mouse();
+  	
+  	/// Checks for and processes any mouse activity. Returns true on activity.
+  	bool check_mouse();
+#endif
+
+#ifdef  USE_KEYBOARD
+  	/// Initializes keyboard routines 
+  	bool init_keyboard();
+  	  	
+  	/// Translates a scancode from the Linux Input Subsystem to a Gnash key code 
+    gnash::key::code scancode_to_gnash_key(int code, bool shift);
+  	
+  	/// Checks for and processes any keyboard activity. Returns true on activity.
+  	bool check_keyboard();
+#endif
+  	
+#ifdef USE_INPUT_EVENTS  	
+    /// Applies builtin touchscreen calibration
+  	void apply_ts_calibration(float* cx, float* cy, int rawx, int rawy);
+#endif
+  	
+  	int valid_x(int x);
+  	int valid_y(int y);
+  	
+  	void cleanup();
+  	  	
+public:
+	EGLGui(unsigned long xid, float scale, bool loop, RunResources& r);
+    virtual ~EGLGui();
+    virtual bool init(int argc, char ***argv);
+    virtual bool createWindow(const char* title, int width, int height);
+    virtual bool run();
+    virtual bool createMenu();
+    virtual bool setupEvents();
+    virtual void renderBuffer();
+    virtual void setInterval(unsigned int interval);
+    virtual void setTimeout(unsigned int timeout);
+    
+    virtual void setFullscreen();
+    virtual void unsetFullscreen();
+    
+    virtual void showMenu(bool show);
+    virtual bool showMouse(bool show);
+    
+    virtual void setInvalidatedRegions(const InvalidatedRanges& ranges);
+    virtual bool want_multiple_regions() { return true; }
+};
+
+// end of namespace gnash
+}
+
+#endif
+
