[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] [SCM] Gnash branch, openvg, created. 25d315301e008059e614
From: |
Rob Savoye |
Subject: |
[Gnash-commit] [SCM] Gnash branch, openvg, created. 25d315301e008059e614f299bdd16bbb40d7ab73 |
Date: |
Tue, 17 Aug 2010 04:11:31 +0000 |
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "Gnash".
The branch, openvg has been created
at 25d315301e008059e614f299bdd16bbb40d7ab73 (commit)
- Log -----------------------------------------------------------------
http://git.savannah.gnu.org/cgit//commit/?id=25d315301e008059e614f299bdd16bbb40d7ab73
commit 25d315301e008059e614f299bdd16bbb40d7ab73
Author: Rob Savoye <address@hidden>
Date: Mon Aug 16 21:35:33 2010 -0600
copy files from old bzr branch to get around merge conflicts.
diff --git a/gui/fb/fb.cpp b/gui/fb/fb.cpp
index f3315ab..1a5c0a7 100644
--- a/gui/fb/fb.cpp
+++ b/gui/fb/fb.cpp
@@ -699,142 +699,6 @@ FBGui::enable_terminal()
} //command()
#endif
-#ifdef USE_MOUSE_PS2
-bool
-FBGui::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 FBGui::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;
- printf("clicked: %d\n", 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 FBGui::init_mouse()
{
diff --git a/gui/fb/fbsup.h b/gui/fb/fbsup.h
index 506a3bc..05ed5b1 100644
--- a/gui/fb/fbsup.h
+++ b/gui/fb/fbsup.h
@@ -31,17 +31,6 @@
#define PIXELFORMAT_LUT8
#define CMAP_SIZE (256*2)
-// 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
http://git.savannah.gnu.org/cgit//commit/?id=62e55ddc82c6384de5f45df0b1046716f8ae1ec9
commit 62e55ddc82c6384de5f45df0b1046716f8ae1ec9
Merge: c028bb7 78b457f
Author: Rob Savoye <address@hidden>
Date: Mon Aug 16 20:52:05 2010 -0600
merge master into older OpenVG bzr branch, which was imported into git.
diff --cc configure.ac
index 908755b,aab5c82..4eeb05a
--- a/configure.ac
+++ b/configure.ac
@@@ -743,14 -710,213 +710,208 @@@ operating system." >&
fi
fi
+ dnl We can use Xephyr or fbe to create a fake framebuffer instead of real
+ dnl video memory. This lets us test on a desktop machine.
+ AC_ARG_WITH(fakefb,
+ AC_HELP_STRING([--with-fakefb],
+ [specify a file to be mapped instead of a real framebuffer]),
+ with_fakefb=${withval})
+
+ fakefb=
+ if test x"${with_fakefb}" = xyes; then
+ dnl This is the default file name fbe uses.
+ fakefb=/tmp/fbe_buffer
+ else
+ if test x"${with_fakefb}" != x; then
+ fakefb=${with_fakefb}
+ fi
+ fi
+ FAKEFB=${fakefb}
+ AC_SUBST(FAKEFB)
+
+ if test x"${fakefb}" != x; then
+ AC_DEFINE(ENABLE_FAKE_FRAMEBUFFER, [1], [Enable using a file instead of a
real framebuffer])
+ fi
+
+
+ dnl --------------------------------------------------------
+ dnl Sound handler selection
+ dnl --------------------------------------------------------
+ add_sound=
+ build_sound_sdl=no
+ build_sound_ahi=no
+ build_sound_mkit=no
+ AC_ARG_ENABLE(sound,
+ AC_HELP_STRING([--enable-sound=[[sdl|ahi|mkit]]], [Use the specified sound
handler (default=sdl)]),
+ [case "${enableval}" in
+ sdl|SDL|Sdl)
+ build_sound_sdl=yes
+ add_sound="sdl"
+ ;;
+ ahi|AHI|Ahi)
+ build_sound_ahi=yes
+ add_sound="ahi"
+ ;;
+ mkit|MKIT|Mkit)
+ build_sound_mkit=yes
+ add_sound="mkit"
+ ;;
+ esac],
+ [if test x"${haiku}" = xyes; then
+ build_sound_mkit=yes
+ add_sound="mkit"
+ else
+ build_sound_sdl=yes
+ add_sound=sdl
+ fi]
+ )
+
+
+ dnl --------------------------------------------------------
+ dnl Media handler selection
+ dnl --------------------------------------------------------
-build_media_gst=no
++build_media_gst=yes
+ build_media_ffmpeg=no
+ AC_ARG_ENABLE(media,
+ AC_HELP_STRING([--enable-media=handler],
+ [Enable media handling support using the specified handler: gst, ffmpeg
or none (no sound) [[gst]] ]),
+
+ if test -n ${enableval}; then
+ enableval=`echo ${enableval} | tr '\054' ' ' `
+ fi
+ while test -n "${enableval}"; do
+ val=`echo ${enableval} | cut -d ' ' -f 1`
+ [case "${val}" in
+ GST|gst)
+ build_media_gst=yes
+ media_list="${media_list}gst "
+ ;;
+ FFMPEG|ffmpeg)
+ build_media_ffmpeg=yes
+ media_list="${media_list}ffmpeg "
+ ;;
+ no|NO|none)
+ media_list="none"
+ ;;
+ *)
+ AC_MSG_ERROR([bad value ${enableval} for --enable-media option])
+ ;;
+
+ esac]
+ enableval=`echo ${enableval} | cut -d ' ' -f 2-6`
+ if test "x$val" = "x$enableval"; then
+ break;
+ fi
+ done,
+ [if test x"${build_haiku}" = xyes; then
+ build_media_ffmpeg=yes
+ build_media_haiku=yes
+ media_list="ffmpeg haiku"
+ else
+ build_media_gst=yes
+ media_list="gst"
+ fi]
+ )
+
+ MEDIA_CONFIG="${media_list}"
+ AC_SUBST(MEDIA_CONFIG)
+
-dnl if no media handler is selected, default to Gstreamer.
-if test x"$build_media_ffmpeg" = x"no" -a x"$build_media_gst" = x"no"; then
- build_media_gst=yes
-fi
-
+ if test x"$build_media_ffmpeg" = x"yes"; then
+ GNASH_PATH_FFMPEG
+ fi
+
+ dnl -------------------------------
+ dnl Input Device selection
+ dnl -------------------------------
+
+ dnl Multiple input devices are supported. These can all work in
+ dnl varying combinations, so several may be listed. These are only
+ dnl required when using the Framebuffer, as without the X11 desktop,
+ dnl Gnash has to handle all these internally. This can get
+ dnl messy, as one might want to use a touchscreen with a normal mouse
+ dnl or keyboard attached.
+ dnl By default, don't build any of these, as they are only for the Framebuffer
+ dnl running without X11.
+ if test x"${build_fb}" = xyes; then
+ build_ps2mouse=yes
+ build_ps2keyboard=no
+ build_input_events=yes
+ build_tslib=yes
+ input_events="PS/2 Mouse, Input Devices, Touchscreen via Tslib"
+ else
+ build_ps2mouse=no
+ build_ps2keyboard=no
+ build_input_events=no
+ build_tslib=no
+ input_events=
+ fi
+ AC_ARG_ENABLE(input,
+ AC_HELP_STRING([--enable-input=], [Enable support for the specified input
devices for the framebuffer GUI
(default=ps2mouse|ps2keyboard|events|touchscreen)]),
+ [if test -n ${enableval}; then
+ enableval=`echo ${enableval} | tr '\054' ' ' `
+ fi
+ while test -n "${enableval}" ; do
+ val=`echo ${enableval} | cut -d ' ' -f 1`
+ case "${val}" in
+ ps2m*|PS2m*|m*|M*) dnl a PS/2 style mouse
+ build_ps2mouse=yes
+ input_events="${input_events}, PS/2 Mouse"
+ ;;
+ ps2k*|PS2K*|k*|K*) dnl a PS/2 style keyboard
+ build_ps2keyboard=yes
+ input_events="${input_events}, PS/2 Keyboard"
+ ;;
+ i*|I*|ev*|Ev*) dnl use the new Input Event, which supports both
+ input_events="${input_events}, Input Event Device"
+ build_input_events=yes
+ ;;
+ t*|T*) dnl use a touchscreen with tslib, which works like a mouse
+ build_tslib=yes
+ input_events="${input_events}, Touchscreen"
+ ;;
+ *) AC_MSG_ERROR([invalid input device list! ${enableval} given (accept:
ps2mouse|keyboard|events,touchscreen)])
+ ;;
+ esac
+ enableval=`echo ${enableval} | cut -d ' ' -f 2-6`
+ if test "x$val" = "x$enableval"; then
+ break;
+ fi
+ done],
+ )
+
+ if test x"${build_tslib}" = xyes; then
+ AC_DEFINE(USE_TSLIB, [1], [Use a tslib supported touchscreen])
+ GNASH_PKG_FIND(ts, [tslib.h], [Touchscreen library], ts_config)
+ fi
+ AM_CONDITIONAL(ENABLE_TSLIB, [test x${ac_cv_header_tslib_h} != xno])
+
+ if test x"${build_ps2mouse}" = xyes; then
+ AC_DEFINE(USE_MOUSE_PS2, [1], [Add support for a directly using a PS/2
Mouse])
+ fi
+ AM_CONDITIONAL(ENABLE_MOUSE, [test x"${build_ps2mouse}" = xyes])
+
+ if test x"${build_ps2keyboard}" = xyes; then
+ AC_DEFINE(USE_KEYBOARD_PS2, [1], [Add support for directly using a PS/2
Keyboard])
+ fi
+ if test x"${build_input_events}" = xyes; then
+ AC_DEFINE(USE_INPUT_EVENTS, [1], [Add support for a directly using Linux
Input Event Devices])
+ fi
+ AM_CONDITIONAL(ENABLE_INPUT_EVENTS, [test x"${build_input_events}" = xyes])
+ dnl this is enabled if we have any input devices at all
+ AM_CONDITIONAL(ENABLE_INPUT_DEVICES, [test x"${input_events}" != x])
+
+ dnl -------------------------------
+ dnl Renderer Selection
+ dnl -------------------------------
+ input_events=
dnl By default, we want to to build all renderers
- build_gles=no dnl OpenGL-ES 1.1 and 2.x
- build_ovg=yes dnl OpenVG
- build_ogl=yes dnl OpenGL
- build_agg=yes dnl AntiGrain
- build_cairo=yes dnl Cairo
- renderer_list="OpenGL OpenVG AGG Cairo"
- nrender=4
+ build_ovg=no
+ build_gles=no
+ build_ogl=yes
+ build_agg=yes
+ build_cairo=yes
+ renderer_list="OpenGL AGG Cairo"
+ nrender=3
AC_ARG_ENABLE(renderer,
AC_HELP_STRING([--enable-renderer=], [Enable support for the specified
renderers (ogl|gles|cairo|agg|all, default=all)]),
if test -n ${enableval}; then
diff --cc gui/fb/.#fbsup.h
index 0000000,0000000..1d9fded
new file mode 120000
--- /dev/null
+++ b/gui/fb/.#fbsup.h
@@@ -1,0 -1,0 +1,1 @@@
address@hidden:1281627622
http://git.savannah.gnu.org/cgit//commit/?id=c028bb7d68b8d36b42d642862e43b12d46773867
commit c028bb7d68b8d36b42d642862e43b12d46773867
Author: Rob Savoye <address@hidden>
Date: Sat Jul 24 10:43:34 2010 -0600
new files from branch, seperate the rendeer from the fb gui. Add OpenVG
support.
diff --git a/gui/fb/fb_glue_agg.cpp b/gui/fb/fb_glue_agg.cpp
new file mode 100644
index 0000000..c1b0486
--- /dev/null
+++ b/gui/fb/fb_glue_agg.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <cstring>
+#include <boost/cstdint.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "Renderer.h"
+#include "Renderer_agg.h"
+#include "fbsup.h"
+#include "fb_glue_agg.h"
+#include "RunResources.h"
+#include "log.h"
+
+namespace gnash {
+
+FBAggGlue::FBAggGlue(int fd)
+ : _fd(fd),
+ _rowsize(0)
+{
+ GNASH_REPORT_FUNCTION;
+
+ memset(&_var_screeninfo, 0, sizeof(struct fb_var_screeninfo));
+ memset(&_fix_screeninfo, 0, sizeof(struct fb_fix_screeninfo));
+}
+
+FBAggGlue::~FBAggGlue()
+{
+ GNASH_REPORT_FUNCTION;
+
+ // Close the memory
+ if (_fd) {
+ ::close(_fd);
+ }
+}
+
+void
+FBAggGlue::setInvalidatedRegions(const InvalidatedRanges &ranges)
+{
+ GNASH_REPORT_FUNCTION;
+
+}
+
+bool
+FBAggGlue::init (int argc, char ***argv)
+{
+ GNASH_REPORT_FUNCTION;
+
+ // Load framebuffer properties
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+ fakefb_ioctl(_fd, FBIOGET_VSCREENINFO, &_var_screeninfo);
+ fakefb_ioctl(_fd, FBIOGET_FSCREENINFO, &_fix_screeninfo);
+#else // ENABLE_FAKE_FRAMEBUFFER
+ ioctl(_fd, FBIOGET_VSCREENINFO, &_var_screeninfo);
+ ioctl(_fd, FBIOGET_FSCREENINFO, &_fix_screeninfo);
+#endif
+
+ 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);
+
+ // map framebuffer into memory
+ _fbmem.reset(static_cast<boost::uint8_t *>(mmap(0,
_fix_screeninfo.smem_len,
+ PROT_READ|PROT_WRITE, MAP_SHARED,
+ _fd, 0)));
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+ // allocate offscreen buffer
+ _buffer.reset(new boost::uint8_t[_fix_screeninfo.smem_len]);
+ memset(_buffer.get(), 0, _fix_screeninfo.smem_len);
+#endif
+
+#ifdef PIXELFORMAT_LUT8
+ // Set grayscale for 8 bit modes
+ if (_var_screeninfo.bits_per_pixel == 8) {
+ if (!set_grayscale_lut8())
+ return false;
+ }
+#endif
+
+ return true;
+}
+
+#define TO_16BIT(x) (x | (x<<8))
+
+bool
+FBAggGlue::set_grayscale_lut8()
+{
+ GNASH_REPORT_FUNCTION;
+
+ struct fb_cmap cmap;
+ int i;
+
+ log_debug(_("LUT8: Setting up colormap"));
+
+ cmap.start = 0;
+ cmap.len = 256;
+ cmap.red = new boost::uint16_t[CMAP_SIZE];
+ cmap.green = new boost::uint16_t[CMAP_SIZE];
+ cmap.blue = new boost::uint16_t[CMAP_SIZE];
+ cmap.transp = NULL;
+
+ for (i=0; i<256; i++) {
+
+ int r = i;
+ int g = i;
+ int b = i;
+
+ cmap.red[i] = TO_16BIT(r);
+ cmap.green[i] = TO_16BIT(g);
+ cmap.blue[i] = TO_16BIT(b);
+
+ }
+
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+ if (fakefb_ioctl(_fd, FBIOPUTCMAP, &cmap))
+#else
+ if (ioctl(_fd, FBIOPUTCMAP, &cmap))
+#endif
+ {
+ log_error(_("LUT8: Error setting colormap: %s"), strerror(errno));
+ return false;
+ }
+
+ return true;
+
+#undef TO_16BIT
+}
+
+Renderer *
+FBAggGlue::createRenderHandler()
+{
+ GNASH_REPORT_FUNCTION;
+
+ const int width = _var_screeninfo.xres;
+ const int height = _var_screeninfo.yres;
+ const int bpp = _var_screeninfo.bits_per_pixel;
+ const int size = _fix_screeninfo.smem_len;
+
+ // TODO: should recalculate!
+ boost::uint8_t *mem;
+ Renderer_agg_base *agg_handler;
+
+ agg_handler = NULL;
+
+ // _validbounds.setTo(0, 0, width - 1, height - 1);
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+ log_debug(_("Double buffering enabled"));
+ mem = _buffer;
+#else
+ log_debug(_("Double buffering disabled"));
+ mem = _fbmem.get();
+#endif
+
+ agg_handler = NULL;
+
+ // 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);
+
+ const char* pixelformat = agg_detect_pixel_format(
+ _var_screeninfo.red.offset, _var_screeninfo.red.length,
+ _var_screeninfo.green.offset, _var_screeninfo.green.length,
+ _var_screeninfo.blue.offset, _var_screeninfo.blue.length,
+ bpp
+ );
+
+ if (pixelformat) {
+ agg_handler = create_Renderer_agg(pixelformat);
+ } else {
+ log_error("The pixel format of your framebuffer could not be
detected.");
+ return false;
+ }
+
+ assert(agg_handler != NULL);
+
+ _rowsize = _var_screeninfo.xres_virtual*((bpp+7)/8);
+
+ agg_handler->init_buffer(mem, size, width, height, _rowsize);
+
+ return (Renderer *)agg_handler;
+}
+
+void
+FBAggGlue::render()
+{
+ // GNASH_REPORT_FUNCTION;
+
+ if ( _drawbounds.size() == 0 ) {
+ return; // nothing to do..
+ }
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+ // Size of a pixel in bytes
+ // NOTE: +7 to support 15 bpp
+ const unsigned int pixel_size = (var_screeninfo.bits_per_pixel+7)/8;
+
+ for (unsigned int bno=0; bno < _drawbounds.size(); bno++) {
+ geometry::Range2d<int>& bounds = _drawbounds[bno];
+
+ assert ( ! bounds.isWorld() );
+
+ // Size, in bytes, of a row that has to be copied
+ const unsigned int row_size = (bounds.width()+1) * pixel_size;
+
+ // copy each row
+ const int minx = bounds.getMinX();
+ const int maxy = bounds.getMaxY();
+
+ for (int y=bounds.getMinY(); y<=maxy; ++y) {
+ const unsigned int pixel_index = y * _rowsize + minx*pixel_size;
+ memcpy(&fbmem[pixel_index], &buffer[pixel_index], row_size);
+
+ }
+ }
+
+#endif
+
+#ifdef DEBUG_SHOW_FPS
+ profile();
+#endif
+}
+
+int
+FBAggGlue::width()
+{
+ return _var_screeninfo.xres_virtual;
+}
+
+int
+FBAggGlue::height()
+{
+ return _var_screeninfo.yres_virtual;
+}
+
+} // end of namespace gnash
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fb_glue_agg.h b/gui/fb/fb_glue_agg.h
new file mode 100644
index 0000000..6ce3e79
--- /dev/null
+++ b/gui/fb/fb_glue_agg.h
@@ -0,0 +1,78 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+
+#ifndef GNASH_FB_GLUE_AGG_H
+#define GNASH_FB_GLUE_AGG_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <boost/cstdint.hpp>
+#include <boost/shared_ptr.hpp>
+
+#include "fbsup.h"
+
+namespace gnash {
+
+class Renderer;
+
+class FBAggGlue: public FBGlue
+{
+public:
+ FBAggGlue(int fd);
+
+ // All of these virtuals are all defined in the base FBGlue class
+ virtual ~FBAggGlue();
+ virtual bool init(int argc, char ***argv);
+ virtual Renderer *createRenderHandler();
+ virtual void setInvalidatedRegions(const InvalidatedRanges &ranges);
+ virtual int width();
+ virtual int height();
+ virtual void render();
+
+ /// For 8 bit (palette / LUT) modes, sets a grayscale palette.
+ //
+ /// This GUI currently does not support palette modes.
+ //
+ bool set_grayscale_lut8();
+
+protected:
+ int _fd;
+ struct fb_var_screeninfo _var_screeninfo;
+ struct fb_fix_screeninfo _fix_screeninfo;
+ struct fb_cmap _cmap;
+
+ boost::shared_ptr<boost::uint8_t> _fbmem; // framebuffer memory
+#ifdef ENABLE_DOUBLE_BUFFERING
+ boost::shared_ptr<boost::uint8_t> _buffer; // offscreen buffer
+#endif
+ boost::uint32_t _rowsize;
+ std::vector< geometry::Range2d<int> > _drawbounds;
+
+ boost::shared_ptr<Renderer> _renderer;
+};
+
+} // end of gnash namespace
+
+#endif // GNASH_FB_GLUE_AGG_H
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fb_glue_gles.cpp b/gui/fb/fb_glue_gles.cpp
new file mode 100644
index 0000000..ea884e4
--- /dev/null
+++ b/gui/fb/fb_glue_gles.cpp
@@ -0,0 +1,181 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+// 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
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+// gles-1.0c for Linux
+#ifdef HAVE_GLES_GL_H
+# include <GLES/gl.h>
+#endif
+#ifdef HAVE_GLES_EGL_H
+#include <GLES/egl.h>
+#endif
+// Mali Developer Tools for ARM 1.x
+#ifdef HAVE_EGL_EGL_H
+# include <EGL/egl.h>
+# include <EGL/eglext.h>
+#endif
+// Mali Developer Tools for ARM 2.x and Android 2.1
+#ifdef HAVE_GLES2_GL2_H
+# include <GLES2/gl2.h>
+# include <GLES2/gl2ext.h>
+#endif
+
+#include "log.h"
+#include "fb_gles_glue.h"
+
+namespace gnash
+{
+
+bool
+FBglesGlue::init(int /*argc*/, char *** /*argv*/) {
+ EGLint majorVersion, minorVersion;
+ EGLint numOfConfigs = 0;
+ EGLint result;
+ const EGLint main_attrib_list[] = {
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_BUFFER_SIZE, 32,
+ EGL_DEPTH_SIZE, 16,
+ EGL_NONE
+ };
+
+ _display = eglGetDisplay((NativeDisplayType)0);
+ if (_display == EGL_NO_DISPLAY) {
+ return false;
+ }
+ log_trace("EGL: getDisplay ok");
+
+ result = eglInitialize(_display, &majorVersion, &minorVersion);
+ if (result == EGL_FALSE) {
+ return false;
+ }
+ log_trace("EGL: initialize ok");
+
+ result = eglChooseConfig(_display, main_attrib_list, &_config, 1,
+ &numOfConfigs);
+ if (result == EGL_FALSE || numOfConfigs != 1) {
+ return false;
+ }
+ log_trace("EGL: config ok");
+
+ _surface = eglCreateWindowSurface(_display, _config, (NativeWindowType)0,
+ NULL);
+ if (eglGetError () != EGL_SUCCESS) {
+ return false;
+ }
+ log_trace("EGL: surface ok");
+
+ _context = eglCreateContext(_display, _config, NULL, NULL);
+ if (eglGetError () != EGL_SUCCESS) {
+ return false;
+ }
+ log_trace("EGL: context ok");
+
+ eglMakeCurrent(_display, _surface, _surface, _context);
+ if (eglGetError () != EGL_SUCCESS) {
+ return false;
+ }
+ log_trace("EGL: current ok");
+
+ const EGLint pbuffer_config_list[] = {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
+ EGL_BUFFER_SIZE, 32,
+ EGL_DEPTH_SIZE, 0,
+ EGL_BIND_TO_TEXTURE_RGBA, EGL_TRUE,
+ EGL_CONFIG_CAVEAT, EGL_NONE,
+ EGL_NONE
+ };
+
+ result = eglChooseConfig(_display, pbuffer_config_list, &_pbuffer_config,
+ 1, &numOfConfigs);
+ if (result == EGL_FALSE || numOfConfigs == 0) {
+ return false;
+ }
+ log_trace("EGL: pbuffer config ok");
+
+ const EGLint pbuffer_attrib_list[] = {
+ EGL_WIDTH, PBUFFER_WIDTH,
+ EGL_HEIGHT, PBUFFER_HEIGHT,
+ EGL_TEXTURE_FORMAT, EGL_TEXTURE_RGBA,
+ EGL_TEXTURE_TARGET, EGL_TEXTURE_2D,
+ EGL_MIPMAP_TEXTURE, EGL_FALSE,
+ EGL_NONE
+ };
+
+ _pbuffer = eglCreatePbufferSurface(_display, _pbuffer_config,
+ pbuffer_attrib_list);
+ if (eglGetError () != EGL_SUCCESS) {
+ return false;
+ }
+ log_trace("EGL: pbuffer surface ok");
+
+ return true;
+}
+
+FBglesGlue::~FBglesGlue () {
+ eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(_display);
+}
+
+int
+FBglesGlue::width() {
+ EGLint result;
+ eglQuerySurface (_display, _surface, EGL_WIDTH, &result);
+ log_trace("EGL: width %d", result);
+ return result;
+}
+
+int
+FBglesGlue::height() {
+ EGLint result;
+ eglQuerySurface (_display, _surface, EGL_HEIGHT, &result);
+ log_trace("EGL: height %d", result);
+ return result;
+}
+
+void
+FBglesGlue::render() {
+ eglSwapBuffers(_display, _surface);
+}
+
+void
+FBglesGlue::render_to_pbuffer () {
+ if (_pbuffer != EGL_NO_SURFACE)
+ eglMakeCurrent(_display, _pbuffer, _pbuffer, _context);
+}
+
+void
+FBglesGlue::prepare_copy_from_pbuffer () {
+ if (_pbuffer != EGL_NO_SURFACE)
+ eglMakeCurrent(_display, _surface, _pbuffer, _context);
+}
+
+void
+FBglesGlue::render_to_display () {
+ if (_pbuffer != EGL_NO_SURFACE)
+ eglMakeCurrent(_display, _surface, _surface, _context);
+}
+
+} // namespace gnash
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fb_glue_gles.h b/gui/fb/fb_glue_gles.h
new file mode 100644
index 0000000..3962ea6
--- /dev/null
+++ b/gui/fb/fb_glue_gles.h
@@ -0,0 +1,93 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010
+// 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
+
+#ifndef FB_OGL_GLUE_H
+#define FB_OGL_GLUE_H
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+// gles-1.0c for Linux
+#ifdef HAVE_GLES_GL_H
+# include <GLES/gl.h>
+# endif
+#ifdef HAVE_GLES_EGL_H
+#include <GLES/egl.h>
+#endif
+// Mali Developer Tools for ARM 1.x
+#ifdef HAVE_EGL_EGL_H
+# include <EGL/egl.h>
+# include <EGL/eglext.h>
+#endif
+// Mali Developer Tools for ARM 2.x and Android 2.1
+#ifdef HAVE_GLES2_GL2_H
+# include <GLES2/gl2.h>
+# include <GLES2/gl2ext.h>
+#endif
+
+#include "ogl_glue.h"
+#include "fbsup.h"
+#include "render_handler_gles.h"
+
+namespace gnash
+{
+
+class FBglesGlue: public FBGlue, public OglGlue
+{
+public:
+ FBglesGlue() :
+ _surface (EGL_NO_SURFACE),
+ _pbuffer (EGL_NO_SURFACE) {}
+ virtual ~FBglesGlue();
+
+ virtual bool init(int /*argc*/, char *** /*argv*/);
+
+ virtual render_handler* createRenderHandler() {
+ //_render_handler = create_render_handler_ogl (true, this);
+ return _render_handler;
+ }
+
+ virtual void setInvalidatedRegions(const InvalidatedRanges& /* ranges */)
{}
+
+ virtual int width ();
+ virtual int height ();
+ virtual void render ();
+
+ virtual void render_to_pbuffer ();
+ virtual void prepare_copy_from_pbuffer ();
+ virtual void render_to_display ();
+
+private:
+ render_handler* _render_handler;
+ EGLDisplay _display;
+ EGLConfig _config;
+ EGLContext _context;
+ EGLSurface _surface;
+ EGLConfig _pbuffer_config;
+ EGLSurface _pbuffer;
+};
+
+} // namespace gnash
+
+#endif // FB_OGL_GLUE_H
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fb_glue_ovg.cpp b/gui/fb/fb_glue_ovg.cpp
new file mode 100644
index 0000000..4739b4a
--- /dev/null
+++ b/gui/fb/fb_glue_ovg.cpp
@@ -0,0 +1,30 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+namespace gnash {
+
+} // end of namespace gnash
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/gtk/gtk_glue_egl.h b/gui/gtk/gtk_glue_egl.h
new file mode 100644
index 0000000..2cb1888
--- /dev/null
+++ b/gui/gtk/gtk_glue_egl.h
@@ -0,0 +1,106 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+//
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include "gtk_glue.h"
+
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+#include <boost/scoped_array.hpp>
+#include "Renderer_ovg.h"
+
+#ifdef HAVE_VG_OPENVG_H
+#include <VG/openvg.h>
+#endif
+
+#ifdef HAVE_EGL_EGL_H
+# include <EGL/egl.h>
+#else
+# error "This file needs EGL, which is part of OpenGL-ES"
+#endif
+
+namespace gnash
+{
+
+class GtkEGLGlue : public GtkGlue
+{
+ public:
+ GtkEGLGlue();
+ ~GtkEGLGlue();
+
+ // Initialize EGL
+ bool init(int argc, char **argv[]);
+
+ // Prepare the drawing area
+ void prepDrawingArea(GtkWidget *drawing_area);
+
+ // Create the renderer
+ Renderer* createRenderHandler();
+
+ // Set the size of the rendering window
+ void setRenderHandlerSize(int width, int height);
+ void beforeRendering();
+
+ // Render the drawing area to the display
+ void render();
+ void render(int minx, int miny, int maxx, int maxy);
+
+ // Configure EGL
+ void configure(GtkWidget *const widget, GdkEventConfigure *const event);
+
+ // Utility methods not in the base class
+ /// Return a string with the error code as text, instead of a numeric value
+ const char *getErrorString(int error);
+ /// Check the requested EGl configuration against the current one
+ bool checkEGLConfig(EGLConfig config);
+ /// Query the system for all supported configs
+ int queryEGLConfig(EGLDisplay display);
+ void printEGLConfig(EGLConfig config);
+ void printEGLContext(EGLContext context);
+ void printEGLSurface(EGLSurface surface);
+
+ private:
+ // offscreenbuf is only used with ENABLE_EGL_OFFSCREEN
+ GdkImage *_offscreenbuf;
+ Renderer_ovg_base *_renderer;
+
+ EGLConfig _eglConfig;
+ EGLContext _eglContext;
+ EGLSurface _eglSurface;
+ EGLDisplay _eglDisplay;
+ EGLint _eglNumOfConfigs;
+ EGLNativeWindowType _nativeWindow;
+ EGLint _max_num_config;
+ unsigned int _bpp;
+ unsigned int _width;
+ unsigned int _height;
+};
+
+#define DUMP_CURRENT_SURFACE printEGLSurface(eglGetCurrentSurface(EGL_DRAW))
+#define DUMP_CURRENT_CONTEXT printEGLContext(eglGetCurrentContext())
+
+} // namespace gnash
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/librender/Renderer_ovg.cpp b/librender/Renderer_ovg.cpp
new file mode 100644
index 0000000..d592a35
--- /dev/null
+++ b/librender/Renderer_ovg.cpp
@@ -0,0 +1,1483 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 <address@hidden>
+///
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <sys/time.h>
+#include <cstring>
+#include <cmath>
+#include <boost/utility.hpp>
+#include <boost/bind.hpp>
+
+#include "gnash.h"
+#include "log.h"
+#include "RGBA.h"
+#include "smart_ptr.h"
+#include "GnashImage.h"
+#include "GnashNumeric.h"
+#include "log.h"
+#include "utility.h"
+#include "Range2d.h"
+#include "cxform.h"
+#include "Renderer_ovg.h"
+#include "Renderer_ovg_bitmap.h"
+#include "SWFMatrix.h"
+#include "swf/ShapeRecord.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 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)
+ {
+ GNASH_REPORT_FUNCTION;
+#if 0
+ static const VGubyte sqrCmds[5] = {VG_MOVE_TO_ABS, VG_HLINE_TO_ABS,
VG_VLINE_TO_ABS, VG_HLINE_TO_ABS, VG_CLOSE_PATH};
+ static const VGfloat sqrCoords[5] = {50.0f, 50.0f, 250.0f, 250.0f,
50.0f};
+ path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1, 0,
0, 0,
+ VG_PATH_CAPABILITY_APPEND_TO);
+ vgAppendPathData(path, 5, sqrCmds, sqrCoords);
+
+ fill = vgCreatePaint();
+ vgSetParameterfv(fill, VG_PAINT_COLOR, 4, color);
+ vgSetPaint(fill, VG_FILL_PATH);
+
+ vgSetfv(VG_CLEAR_COLOR, 4, white_color);
+ vgSetf(VG_STROKE_LINE_WIDTH, 10);
+ vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT);
+ vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_ROUND);
+ vgSetf(VG_STROKE_MITER_LIMIT, 4.0f);
+#else
+ 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 );
+
+#ifdef OPENVG_VERSION_1_1
+ m_mask = vgCreateMaskLayer(x, y);
+#endif
+#endif
+ log_debug("VG Vendor is %s, VG Version is %s, VG Renderer is %s",
+ vgGetString(VG_VENDOR), vgGetString(VG_VERSION),
+ vgGetString(VG_RENDERER));
+ log_debug("VG Extensions are: ", vgGetString(VG_EXTENSIONS));
+ printVGParams();
+ }
+
+ ~Renderer_ovg()
+ {
+ vgDestroyPaint(m_fillpaint);
+ vgDestroyPaint(m_strokepaint);
+#ifdef OPENVG_VERSION_1_1
+ vgDestroyMaskLayer(m_mask);
+#endif
+ }
+
+ // Given an image, returns a pointer to a bitmap_info class
+ // that can later be passed to fill_styleX_bitmap(), to set a
+ // bitmap fill style.
+ gnash::BitmapInfo* createBitmapInfo(std::auto_ptr<GnashImage> im)
+ {
+ GNASH_REPORT_FUNCTION;
+
+ // 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.
+ void drawVideoFrame(GnashImage* /* frame */, const SWFMatrix* /* m */,
+ const SWFRect* /* 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 SWFRect& 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;
+ };
+
+ 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)
+ {
+ // GNASH_REPORT_FUNCTION;
+
+ 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);
+ }
+
+ void end_display()
+ {
+ // GNASH_REPORT_FUNCTION;
+
+ }
+
+ /// Draw a line-strip directly, using a thin, solid line.
+ //
+ /// Can be used to draw empty boxes and cursors.
+ 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);
+ }
+
+ void drawPoly(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);
+ }
+
+ void set_antialiased(bool /* enable */)
+ {
+ log_unimpl("set_antialiased");
+ }
+
+ void begin_submit_mask()
+ {
+ PathVec mask;
+ _masks.push_back(mask);
+
+ _drawing_mask = true;
+
+ }
+
+ 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);
+
+#ifdef OPENVG_VERSION_1_1
+ vgMask(m_mask, VG_FILL_MASK, 0, 0, m_display_width, m_display_height);
FIXME
+#endif
+
+ // 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);
+ }
+
+ 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 LineStyle& 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<LineStyle>&
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<LineStyle>& 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);
+ }
+
+#ifdef OPENVG_VERSION_1_1
+ vgRenderToMask(vg_path, VG_FILL_PATH, VG_INTERSECT_MASK); FIXME
+#endif
+ 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.
+
+ 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<LineStyle>& 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);
+ }
+ }
+
+ 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<LineStyle> 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;
+
+#ifdef OPENVG_VERSION_1_1
+ VGMaskLayer m_mask;
+#endif
+}; // class Renderer_ovg
+
+Renderer_ovg_base *
+create_Renderer_ovg(const char */* pixelformat */)
+{
+ // Renderer_ovg_base* renderer = new Renderer_ovg();
+ // return renderer;
+}
+
+ // These methods are only for debugging and development
+void
+Renderer_ovg_base::printVGParams()
+{
+ // vgGetVectorSize();
+
+ std::string str;
+ switch(vgGeti(VG_MATRIX_MODE)) {
+ case VG_MATRIX_PATH_USER_TO_SURFACE:
+ str = "VG_MATRIX_PATH_USER_TO_SURFACE";
+ break;
+ case VG_MATRIX_IMAGE_USER_TO_SURFACE:
+ str = "VG_MATRIX_IMAGE_USER_TO_SURFACE";
+ break;
+ case VG_MATRIX_FILL_PAINT_TO_USER:
+ str = "VG_MATRIX_FILL_PAINT_TO_USER";
+ break;
+ case VG_MATRIX_STROKE_PAINT_TO_USER:
+ str = "VG_MATRIX_STROKE_PAINT_TO_USER";
+ break;
+ case VG_MATRIX_MODE_FORCE_SIZE:
+ str = "VG_MATRIX_MODE_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_MATRIX_MODE!");
+ }
+ log_debug("VG_MATRIX_MODE is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_FILL_RULE)) {
+ case VG_EVEN_ODD:
+ str = "VG_EVEN_ODD";
+ break;
+ case VG_NON_ZERO:
+ str = "VG_NON_ZERO";
+ break;
+ default:
+ log_error("unsupported VG_FILL_RULE!");
+ }
+ log_debug("VG_FILL_RULE is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_IMAGE_QUALITY)) {
+ case VG_IMAGE_QUALITY_NONANTIALIASED:
+ str = "VG_IMAGE_QUALITY_NONANTIALIASED";
+ break;
+ case VG_IMAGE_QUALITY_FASTER:
+ str = "VG_IMAGE_QUALITY_FASTER";
+ break;
+ case VG_IMAGE_QUALITY_BETTER:
+ str = "VG_IMAGE_QUALITY_BETTER";
+ break;
+ case VG_IMAGE_QUALITY_FORCE_SIZE:
+ str = "VG_IMAGE_QUALITY_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_IMAGE_QUALITY!");
+ }
+ log_debug("VG_IMAGE_QUALITY is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_RENDERING_QUALITY)) {
+ case VG_RENDERING_QUALITY_NONANTIALIASED:
+ str = "VG_RENDERING_QUALITY_NONANTIALIASED";
+ break;
+ case VG_RENDERING_QUALITY_FASTER:
+ str = "VG_RENDERING_QUALITY_FASTER";
+ break;
+ case VG_RENDERING_QUALITY_BETTER:
+ str = "VG_RENDERING_QUALITY_BETTER";
+ break;
+ case VG_RENDERING_QUALITY_FORCE_SIZE:
+ str = "VG_RENDERING_QUALITY_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_RENDERING_QUALITY!");
+ }
+ log_debug("VG_RENDERING_QUALITY is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_BLEND_MODE)) {
+ case VG_BLEND_SRC:
+ str = "VG_BLEND_SRC";
+ break;
+ case VG_BLEND_SRC_OVER:
+ str = "VG_BLEND_SRC_OVER";
+ break;
+ case VG_BLEND_DST_OVER:
+ str = "VG_BLEND_DST_OVER";
+ break;
+ case VG_BLEND_SRC_IN:
+ str = "VG_BLEND_SRC_IN";
+ break;
+ case VG_BLEND_DST_IN:
+ str = "VG_BLEND_DST_IN";
+ break;
+ case VG_BLEND_MULTIPLY:
+ str = "VG_BLEND_MULTIPLY";
+ break;
+ case VG_BLEND_SCREEN:
+ str = "VG_BLEND_SCREEN";
+ break;
+ case VG_BLEND_DARKEN:
+ str = "VG_BLEND_DARKEN";
+ break;
+ case VG_BLEND_LIGHTEN:
+ str = "VG_BLEND_LIGHTEN";
+ break;
+ case VG_BLEND_ADDITIVE:
+ str = "VG_BLEND_ADDITIVE";
+ break;
+ default:
+ log_error("unsupported VG_BLEND_MODE!");
+ }
+ log_debug("VG_BLEND_MODE is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_IMAGE_MODE)) {
+ case VG_DRAW_IMAGE_NORMAL:
+ str = "VG_DRAW_IMAGE_MULTIPLY";
+ break;
+ case VG_DRAW_IMAGE_MULTIPLY:
+ str = "VG_DRAW_IMAGE_MULTIPLY";
+ break;
+ case VG_DRAW_IMAGE_STENCIL:
+ str = "VG_DRAW_IMAGE_STENCIL";
+ break;
+ case VG_IMAGE_MODE_FORCE_SIZE:
+ str = "VG_IMAGE_MODE_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_IMAGE_MODE!");
+ }
+ log_debug("VG_IMAGE_MODE is %s", str);
+ str.clear();
+
+ log_debug("VG_STROKE_LINE_WIDTH is %d", vgGeti(VG_STROKE_LINE_WIDTH));
+ str.clear();
+
+ switch(vgGeti(VG_STROKE_CAP_STYLE)) {
+ case VG_CAP_BUTT:
+ str = "VG_CAP_BUTT";
+ break;
+ case VG_CAP_ROUND:
+ str = "VG_CAP_ROUND";
+ break;
+ case VG_CAP_SQUARE:
+ str = "VG_CAP_SQUARE";
+ break;
+ case VG_CAP_STYLE_FORCE_SIZE:
+ str = "VG_CAP_STYLE_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_STROKE_CAP_STYLE!");
+ }
+ log_debug("VG_STROKE_CAP_STYLE is %s", str);
+ str.clear();
+
+ switch(vgGeti(VG_STROKE_JOIN_STYLE)) {
+ case VG_JOIN_MITER:
+ str = "VG_JOIN_MITER";
+ break;
+ case VG_JOIN_ROUND:
+ str = "VG_JOIN_ROUND";
+ break;
+ case VG_JOIN_BEVEL:
+ str = "VG_JOIN_BEVEL";
+ break;
+ case VG_JOIN_STYLE_FORCE_SIZE:
+ str = "VG_JOIN_STYLE_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_STROKE_JOIN_STYLE!");
+ }
+ log_debug("VG_STROKE_JOIN_STYLE is %s", str);
+ str.clear();
+
+ log_debug("VG_STROKE_MITER_LIMIT is %d", vgGeti(VG_STROKE_MITER_LIMIT));
+ log_debug("VG_MASKING is %d", vgGeti(VG_MASKING));
+ log_debug("VG_SCISSORING is %d", vgGeti(VG_SCISSORING));
+ str.clear();
+
+ switch(vgGeti(VG_PIXEL_LAYOUT)) {
+ case VG_PIXEL_LAYOUT_UNKNOWN:
+ str = "VG_PIXEL_LAYOUT_UNKNOWN";
+ break;
+ case VG_PIXEL_LAYOUT_RGB_VERTICAL:
+ str = "VG_PIXEL_LAYOUT_RGB_VERTICAL";
+ break;
+ case VG_PIXEL_LAYOUT_BGR_VERTICAL:
+ str = "VG_PIXEL_LAYOUT_BGR_VERTICAL";
+ break;
+ case VG_PIXEL_LAYOUT_RGB_HORIZONTAL:
+ str = "VG_PIXEL_LAYOUT_RGB_HORIZONTAL";
+ break;
+ case VG_PIXEL_LAYOUT_BGR_HORIZONTAL:
+ str = "VG_PIXEL_LAYOUT_BGR_HORIZONTAL";
+ break;
+ case VG_PIXEL_LAYOUT_FORCE_SIZE:
+ str = "VG_PIXEL_LAYOUT_FORCE_SIZE";
+ break;
+ default:
+ log_error("unsupported VG_PIXEL_LAYOUT!");
+ }
+ log_debug("VG_PIXEL_LAYOUT is %s", str);
+
+ log_debug("VG_STROKE_DASH_PHASE_RESET is %s",
+ (vgGeti(VG_STROKE_DASH_PHASE_RESET) == true) ? "true" : "false");
+ log_debug("VG_FILTER_FORMAT_LINEAR is %s",
+ (vgGeti(VG_FILTER_FORMAT_LINEAR) == true) ? "true" : "false");
+ log_debug("VG_FILTER_FORMAT_PREMULTIPLIED is %s",
+ (vgGeti(VG_FILTER_FORMAT_PREMULTIPLIED) == true) ? "true" :
"false");
+ str.clear();
+
+ VGint value = vgGeti(VG_FILTER_CHANNEL_MASK);
+ if (value & VG_RED) {
+ str += " VG_RED";
+ }
+ if (value & VG_GREEN) {
+ str += " VG_GREEN";
+ }
+ if (value & VG_BLUE) {
+ str += " VG_BLUE";
+ }
+ if (value & VG_ALPHA) {
+ str += " VG_ALPHA";
+ }
+ log_debug("VG_FILTER_CHANNEL_MASK is %s", str);
+
+ log_debug("VG_MAX_IMAGE_WIDTH is %d", vgGeti(VG_MAX_IMAGE_WIDTH));
+ log_debug("VG_MAX_IMAGE_HEIGHT is %d", vgGeti(VG_MAX_IMAGE_HEIGHT));
+ log_debug("VG_MAX_IMAGE_PIXELS is %d", vgGeti(VG_MAX_IMAGE_PIXELS));
+ log_debug("VG_MAX_IMAGE_BYTES is %d", vgGeti(VG_MAX_IMAGE_BYTES));
+}
+
+void
+Renderer_ovg_base::printVGHardware()
+{
+
+}
+
+void
+Renderer_ovg_base::Renderer_ovg_base::printVGPath()
+{
+}
+
+} // namespace gnash
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/librender/Renderer_ovg.h b/librender/Renderer_ovg.h
new file mode 100644
index 0000000..e5ccd54
--- /dev/null
+++ b/librender/Renderer_ovg.h
@@ -0,0 +1,82 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 <address@hidden>
+///
+
+#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 "Geometry.h"
+#include "BitmapInfo.h"
+#include "Renderer.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 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;
+
+ // These methods are only for debugging and development
+ void printVGParams();
+ void printVGHardware();
+ void printVGPath();
+};
+
+DSOEXPORT Renderer_ovg_base* create_Renderer_ovg(const char *pixelformat);
+
+} // namespace gnash
+
+#endif // __RENDER_HANDLER_OVG_H__
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/librender/Renderer_ovg_bitmap.h b/librender/Renderer_ovg_bitmap.h
new file mode 100644
index 0000000..0a401a5
--- /dev/null
+++ b/librender/Renderer_ovg_bitmap.h
@@ -0,0 +1,70 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 <address@hidden>
+///
+
+#ifndef GNASH_RENDER_HANDLER_OVG_BITMAP_H
+#define GNASH_RENDER_HANDLER_OVG_BITMAP_H
+
+#include "Geometry.h"
+#include "BitmapInfo.h"
+#include "Renderer.h"
+
+namespace gnash {
+
+/// The class itself uses a template. Currently this is unnecessary and it may
+/// be removed but an older implementation required this method and it may be
+/// necessary again when the last missing parts of the renderer will be
+/// implemented. And when might that be? I don't think I'll wait.
+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;
+};
+
+} // namespace gnash
+
+#endif // __RENDER_HANDLER_OVG_BITMAP_H__
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
http://git.savannah.gnu.org/cgit//commit/?id=4a2363c0c92cec0eea20c3c6254c64db27d14fcc
commit 4a2363c0c92cec0eea20c3c6254c64db27d14fcc
Author: Rob Savoye <address@hidden>
Date: Sat Jul 24 10:42:43 2010 -0600
add double buffering and off screen rendering options from branch.
diff --git a/configure.ac b/configure.ac
index ad676f9..908755b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -272,6 +272,52 @@ fi
SOLDIR=${soldir}
AC_SUBST(SOLDIR)
+AC_ARG_ENABLE(doublebuf,
+ AC_HELP_STRING([--enable-doublebuf], [Enable support for double buffering
when rendering]),
+ [case "${enableval}" in
+ yes) doublebuf=yes ;;
+ no) doublebuf=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for enable-doublebuf option]) ;;
+ esac], doublebuf=no
+)
+AM_CONDITIONAL(ENABLE_DBUF, [test x"$doublebuf" = xyes])
+if test x$doublebuf = xyes; then
+ AC_DEFINE(ENABLE_DOUBLE_BUFFERING, [1], [Enable double buffering])
+fi
+
+dnl This enables rendering to an offscreen buffer, instead of directly to
window
+AC_ARG_ENABLE(offscreen,
+ AC_HELP_STRING([--enable-offscreen], [Enable support for rendering
offscreen]),
+ [case "${enableval}" in
+ yes) offscreen=yes ;;
+ no) offscreen=no ;;
+ *) AC_MSG_ERROR([bad value ${enableval} for enable-offscreen option]) ;;
+ esac], offscreen=yes
+)
+
+dnl We can use Xephyr or fbe to create a fake framebuffer instead of real
+dnl video memory. This lets us test on a desktop machine.
+AC_ARG_WITH(fakefb,
+AC_HELP_STRING([--with-fakefb],
+ [specify a file to be mapped instead of a real framebuffer]),
+ with_fakefb=${withval})
+
+fakefb=
+if test x"${with_fakefb}" = xyes; then
+ dnl This is the default file name fbe uses.
+ fakefb=/tmp/fbe_buffer
+else
+ if test x"${with_fakefb}" != x; then
+ fakefb=${with_fakefb}
+ fi
+fi
+FAKEFB=${fakefb}
+AC_SUBST(FAKEFB)
+
+if test x"${fakefb}" != x; then
+ AC_DEFINE(ENABLE_FAKE_FRAMEBUFFER, [1], [Enable using a file instead of a
real framebuffer])
+fi
+
AC_ARG_ENABLE(avm2,
AC_HELP_STRING([--enable-avm2], [Enable support for AS3]),
[case "${enableval}" in
@@ -698,13 +744,13 @@ operating system." >&3
fi
dnl By default, we want to to build all renderers
-build_ovg=no
-build_gles=no
-build_ogl=yes
-build_agg=yes
-build_cairo=yes
-renderer_list="OpenGL AGG Cairo"
-nrender=3
+build_gles=no dnl OpenGL-ES 1.1 and 2.x
+build_ovg=yes dnl OpenVG
+build_ogl=yes dnl OpenGL
+build_agg=yes dnl AntiGrain
+build_cairo=yes dnl Cairo
+renderer_list="OpenGL OpenVG AGG Cairo"
+nrender=4
AC_ARG_ENABLE(renderer,
AC_HELP_STRING([--enable-renderer=], [Enable support for the specified
renderers (ogl|gles|cairo|agg|all, default=all)]),
if test -n ${enableval}; then
@@ -757,7 +803,7 @@ AC_ARG_ENABLE(renderer,
;;
ovg|OVG|OpenVG|openvg)
renderer_list="${renderer_list} OpenVG"
- build_ogv=yes
+ build_ovg=yes
nrender=$((nrender+1))
;;
agg|AGG)
@@ -896,6 +942,18 @@ if test x$pixelformat = xall; then
fi
fi
+dnl For now, always enable offscreeen rendering for AGG, as that's how it
+dnl currently works.
+AC_DEFINE(ENABLE_AGG_OFFSCREEN, [1], [Enable offscreen rendering for AGG])
+dnl OpenVG uses EGL for the device layer, currently we only support
+dnl rendering directly to a window.
+if test x"${build_ovg}" = xyes; then
+ offscreen=no
+fi
+if test x"${build_ovg}" = xyes -a x"${offscreen}" = xyes; then
+ AC_DEFINE(ENABLE_EGL_OFFSCREEN, [1], [Enable offscreen rendering for EGL])
+fi
+
dnl --------------------------------------------------------
dnl Select media handler
dnl --------------------------------------------------------
@@ -1095,8 +1153,12 @@ AM_CONDITIONAL(ENABLE_SHARED, [test x"${enable_shared}"
= xyes])
AM_CONDITIONAL(ENABLE_STATIC, [test x"${enable_shared}" = xno])
dnl -- AM_CONDITIONAL(STATIC_GUI, test x"${dynamic_gui}" = xno -o
x"${enable_shared}" = xno)
+dnl DejaGnu is only used for testing.
AC_PATH_PROG(DEJAGNU, runtest)
+dnl These conditionals are triggers only when the selected Renderers
+dnl are chosen to be built, and not on whether they are actually
+dnl supported. So if configure fails, make will fail at build time.
AM_CONDITIONAL(BUILD_OVG_RENDERER, [ test x$build_ovg = xyes ])
AM_CONDITIONAL(BUILD_GLES_RENDERER, [ test x$build_gles = xyes ])
AM_CONDITIONAL(BUILD_OGL_RENDERER, [ test x$build_ogl = xyes])
@@ -1277,9 +1339,20 @@ fi
SECURITY_LIST="$security_list"
AC_SUBST(SECURITY_LIST)
+if test x"${build_agg}" = xyes; then
+ AC_DEFINE([RENDERER_AGG], [1], [Use AntiGrain renderer])
+fi
+
+if test x"${build_ovg}" = xyes; then
+ AC_DEFINE([RENDERER_OPENVG], [1], [Use OpenVG renderer])
+fi
+
+if test x"${build_gles}" = xyes; then
+ AC_DEFINE([RENDERER_GLES], [1], [Use the OpenGL-ES 1.1 renderer])
+fi
-if test x$build_agg = xyes; then
- AC_DEFINE([RENDERER_AGG], [], [Use AntiGrain renderer])
+if test x"${build_gles}" = xyes; then
+ AC_DEFINE([RENDERER_GLES2], [1], [Use the OpenGL-ES 2.x renderer])
fi
dnl For Haiku, we know the sysroot is in a non-standard place
@@ -2139,9 +2212,12 @@ if test x"${build_gles}" = xyes; then
GNASH_PATH_GLES
fi
-if test x"${build_ogv}" = xyes; then
+dnl The current version of OpenVG supported by most ARM platforms
+dnl is OpenVG 1.1. Mesa 7.8.x implements only OpenVG 1.0.1, so
+dnl some features like Masks and Fonts are missing on the desktop.
+if test x"${build_ovg}" = xyes; then
GNASH_PKG_FIND(EGL, [EGL/egl.h], [EGL library], eglGetDisplay)
- GNASH_PKG_FIND(OpenVG, [vg/openvg.h], [OpenVG library], vgDrawImage)
+ GNASH_PKG_FIND(OpenVG, [VG/openvg.h], [OpenVG library], vgDrawImage)
fi
if test x"${build_ogl}" = xyes; then
@@ -3829,6 +3905,13 @@ else
echo " DocBook document processing disabled (default)"
fi
+if test x"${offscreen}" = xyes; then
+ echo " Using offscreen rendering"
+fi
+if test x"${doublebuf}" = xyes; then
+ echo " Using double buffering when rendering"
+fi
+
if test -s $cwarn; then
echo ""
cat $cwarn
http://git.savannah.gnu.org/cgit//commit/?id=287c0d6c0db8f902b88a9d612bc96419e6a1ed65
commit 287c0d6c0db8f902b88a9d612bc96419e6a1ed65
Author: Rob Savoye <address@hidden>
Date: Sat Jul 24 10:42:03 2010 -0600
new files from branch, seperate the rendeer from the fb gui. Add OpenVG
support.
diff --git a/gui/fb/fb.am b/gui/fb/fb.am
index 544a1d3..84216e2 100644
--- a/gui/fb/fb.am
+++ b/gui/fb/fb.am
@@ -20,8 +20,11 @@
#
if BUILD_FB_GUI
bin_PROGRAMS += fb-gnash
-fb_gnash_SOURCES = $(GUI_SRCS) fb/gui_fb.cpp fb/fb.cpp fb/fbsup.h
-fb_gnash_CPPFLAGS = -DGUI_FB -DGUI_CONFIG=\"FB\" \
+fb_gnash_SOURCES = $(GUI_SRCS) \
+ fb/gui_fb.cpp \
+ fb/fb.cpp \
+ fb/fbsup.h
+fb_gnash_CPPFLAGS = -DGUI_FB -DGUI_CONFIG=\"FB\" -DFAKEFB=\"$(FAKEFB)\" \
$(AM_CPPFLAGS)
fb_gnash_LDFLAGS = $(LIBLTDL) -export-dynamic $(AM_LDFLAGS)
#fb_gnash_DEPENDENCIES = .configline
@@ -29,9 +32,26 @@ fb_gnash_LDADD = \
$(top_builddir)/librender/libgnashrender.la \
$(GNASH_LIBS)
+# Build support for AntiGrain.
if BUILD_AGG_RENDERER
+fb_gnash_SOURCES += fb/fb_glue_agg.cpp fb/fb_glue_agg.h
fb_gnash_CPPFLAGS += $(AGG_CFLAGS)
fb_gnash_LDADD += $(AGG_LIBS)
-endif # BUILD_AGG_RENDERER
-endif # BUILD_FB_GUI
+endif # BUILD_AGG_RENDERER
+
+# Build support for OpenVG.
+if BUILD_OVG_RENDERER
+fb_gnash_SOURCES += fb/fb_glue_ovg.cpp fb/fb_glue_ovg.h
+fb_gnash_CPPFLAGS += $(OPENVG_CFLAGS) $(EGL_CFLAGS)
+fb_gnash_LDADD += $(OPENVG_LIBS) $(EGL_LIBS)
+endif # BUILD_OVG_RENDERER
+
+# This supports only OpenGL-ES 1.1 with EGL support.
+if BUILD_GLES_RENDERER
+fb_gnash_SOURCES += fb/fb_glue_gles.cpp fb/fb_glue_gles.h
+fb_gnash_CPPFLAGS += $(GLES_CFLAGS)
+fb_gnash_LDADD += $(GLES__LIBS)
+endif # BUILD_OVG_RENDERER
+
+endif # BUILD_FB_GUI
diff --git a/gui/fb/fb.cpp b/gui/fb/fb.cpp
index a658ccc..f3315ab 100644
--- a/gui/fb/fb.cpp
+++ b/gui/fb/fb.cpp
@@ -74,29 +74,38 @@
#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 <linux/vt.h>
-#include "GnashSystemIOHeaders.h"
+#include <boost/shared_ptr.hpp>
+
+#include <boost/cstdint.hpp>
#include <csignal>
#include <cstdlib> // getenv
+#include "GnashSystemIOHeaders.h"
#include "gnash.h"
#include "gui.h"
#include "fbsup.h"
#include "log.h"
#include "movie_root.h"
#include "RunResources.h"
-
#include "Renderer.h"
-#include "Renderer_agg.h"
#include "GnashSleep.h" // for gnashSleep
-#include <linux/input.h> // for /dev/input/event*
+#ifdef RENDERER_AGG
+#include "fb_glue_agg.h"
+#endif
-//#define DEBUG_SHOW_FPS // prints number of frames per second to STDOUT
+#ifdef RENDERER_OPENVG
+#include "fb_glue_ovg.h"
+#endif
+
+#ifdef RENDERER_GLES
+#include "fb_glue_gles.h"
+#endif
+
+#include <linux/input.h> // for /dev/input/event*
#ifdef DEBUG_SHOW_FPS
# include <sys/types.h>
@@ -104,1370 +113,1395 @@
# 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)
-
-//--
-
+//#define DEBUG_SHOW_FPS // prints number of frames per second to STDOUT
namespace gnash
{
-
-//---------------
-#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);
-
+FBGlue::FBGlue ()
+{
+ GNASH_REPORT_FUNCTION;
+
+ /* do nothing */
}
-#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;
+FBGlue::~FBGlue ()
+{
+ GNASH_REPORT_FUNCTION;
+ /* do nothing */
}
+#ifdef DEBUG_SHOW_FPS
-//---------------
+double fps_timer = 0;
+int fps_counter = 0;
-FBGui::FBGui(unsigned long xid, float scale, bool loop, RunResources& r)
- : Gui(xid, scale, loop, r)
+void
+profile()
{
- fd = -1;
- fbmem = NULL;
- #ifdef DOUBLE_BUFFER
- buffer = NULL;
- #endif
-
- input_fd=-1;
-
- signal(SIGINT, terminate_signal);
- signal(SIGTERM, terminate_signal);
-}
-
-FBGui::~FBGui()
-{
-
- if (fd>0) {
- enable_terminal();
- log_debug(_("Closing framebuffer device"));
+ GNASH_REPORT_FUNCTION;
+
+ 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);
- }
-
- close(input_fd);
-
- #ifdef DOUBLE_BUFFER
- if (buffer) {
- log_debug(_("Free'ing offscreen buffer"));
- free(buffer);
- }
- #endif
+
+ fps_counter++;
+
+ if (fps_counter<2) {
+ fps_timer = uptime;
+ return;
+ }
+
+ log_debug("FPS: %.3f (%.2f)\n", fps_counter/(uptime-fps_timer),
uptime-fps_timer);
+
}
+#endif // DEBUG_SHOW_FPS
+int terminate_request=false; // global scope to avoid GUI access
-bool FBGui::set_grayscale_lut8()
+/// Called on CTRL-C and alike
+void
+terminate_signal(int /*signo*/)
{
- #define TO_16BIT(x) (x | (x<<8))
-
- struct fb_cmap cmap;
- int i;
-
- log_debug(_("LUT8: Setting up colormap"));
-
- cmap.start=0;
- cmap.len=256;
- cmap.red = (__u16*)malloc(CMAP_SIZE);
- cmap.green = (__u16*)malloc(CMAP_SIZE);
- cmap.blue = (__u16*)malloc(CMAP_SIZE);
- cmap.transp = NULL;
-
- for (i=0; i<256; i++) {
-
- int r = i;
- int g = i;
- int b = i;
-
- cmap.red[i] = TO_16BIT(r);
- cmap.green[i] = TO_16BIT(g);
- cmap.blue[i] = TO_16BIT(b);
-
- }
-
- if (ioctl(fd, FBIOPUTCMAP, &cmap)) {
- log_error(_("LUT8: Error setting colormap: %s"), strerror(errno));
- return false;
- }
-
- return true;
-
- #undef TO_16BIT
+ terminate_request = true;
}
-
-bool FBGui::init(int /*argc*/, char *** /*argv*/)
+FBGui::FBGui(unsigned long xid, float scale, bool loop, RunResources& r)
+ : Gui(xid, scale, loop, r),
+ _fd(-1),
+ original_vt(0),
+ original_kd(0),
+ own_vt(0),
+ m_stage_width(0),
+ m_stage_height(0),
+ input_fd(-1),
+ keyb_fd(0),
+ mouse_x(0),
+ mouse_y(0),
+ mouse_btn(0),
+ mouse_buf_size(0)
{
+ GNASH_REPORT_FUNCTION;
- // 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."));
- }
-
- // Initialize keyboard (still not critical)
- if (!init_keyboard()) {
- log_debug(_("You won't have any keyboard input device, sorry."));
- }
-
- // Open the framebuffer device
- fd = open("/dev/fb0", O_RDWR);
- if (fd<0) {
- fatal_error("Could not open framebuffer device: %s", strerror(errno));
- return false;
- }
-
- // Load framebuffer properties
- ioctl(fd, FBIOGET_VSCREENINFO, &var_screeninfo);
- ioctl(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);
-
- // map framebuffer into memory
- fbmem = (unsigned char *)
- mmap(0, fix_screeninfo.smem_len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-
-#ifdef DOUBLE_BUFFER
- // allocate offscreen buffer
- buffer = (unsigned char*)malloc(fix_screeninfo.smem_len);
- memset(buffer, 0, fix_screeninfo.smem_len);
-#endif
-
-#ifdef PIXELFORMAT_LUT8
- // Set grayscale for 8 bit modes
- if (var_screeninfo.bits_per_pixel==8) {
- if (!set_grayscale_lut8())
- return false;
- }
+ memset(mouse_buf, 0, 256);
+
+ signal(SIGINT, terminate_signal);
+ signal(SIGTERM, terminate_signal);
+}
+
+FBGui::~FBGui()
+{
+ GNASH_REPORT_FUNCTION;
+
+ if (_fd > 0) {
+ enable_terminal();
+ log_debug(_("Closing framebuffer device"));
+ close(_fd);
+ }
+
+ close(input_fd);
+
+#ifdef ENABLE_DOUBLE_BUFFERING
+ if (_buffer) {
+ log_debug(_("Free'ing offscreen buffer"));
+ delete[] _buffer;
+ }
#endif
-
- // Ok, now initialize AGG
- return initialize_renderer();
}
-
-bool FBGui::initialize_renderer() {
- const int width = var_screeninfo.xres;
- const int height = var_screeninfo.yres;
- const int bpp = var_screeninfo.bits_per_pixel;
- const int size = fix_screeninfo.smem_len;
-
- // TODO: should recalculate!
- unsigned char* mem;
- Renderer_agg_base* agg_handler;
-
- m_stage_width = width;
- m_stage_height = height;
-
- _validbounds.setTo(0, 0, width - 1, height - 1);
-
-#ifdef DOUBLE_BUFFER
- log_debug(_("Double buffering enabled"));
- mem = buffer;
+bool
+FBGui::init(int argc, char ***argv)
+{
+ GNASH_REPORT_FUNCTION;
+
+ // 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."));
+ }
+
+ // Initialize keyboard (still not critical)
+ if (!init_keyboard()) {
+ log_debug(_("You won't have any keyboard input device, sorry."));
+ }
+
+ // Open the framebuffer device
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+ _fd = open(FAKEFB, O_RDWR);
#else
- log_debug(_("Double buffering disabled"));
- mem = fbmem;
+ _fd = open("/dev/fb0", O_RDWR);
#endif
-
-
- agg_handler = NULL;
-
- // 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);
-
- const char* pixelformat = agg_detect_pixel_format(
- var_screeninfo.red.offset, var_screeninfo.red.length,
- var_screeninfo.green.offset, var_screeninfo.green.length,
- var_screeninfo.blue.offset, var_screeninfo.blue.length,
- bpp
- );
-
- if (pixelformat) {
- agg_handler = create_Renderer_agg(pixelformat);
- } else {
- fatal_error("The pixel format of your framebuffer could not be detected.");
- return false;
- }
-
- assert(agg_handler);
-
- _renderer.reset(agg_handler);
-
- _runResources.setRenderer(_renderer);
-
- m_rowsize = var_screeninfo.xres_virtual*((bpp+7)/8);
-
- agg_handler->init_buffer(mem, size, width, height, m_rowsize);
-
- disable_terminal();
+ if (_fd < 0) {
+ log_error("Could not open framebuffer device: %s", strerror(errno));
+ return false;
+ }
- return true;
-}
+#ifdef RENDERER_AGG
+ fb_glue = new FBAggGlue(_fd);
+#endif
+// #ifdef RENDERER_OPENVG
+// fb_glue = 0; // new FBOvgGlue(_fd);
+// #endif
+// #ifdef RENDERER_GLES
+// fb_glue = new FBglesGlue(_fd);
+// #endif
+
+ if (fb_glue == 0) {
+ log_error("No renderer created!");
+ return false;
+ } else if (!fb_glue->init(argc, argv)) {
+ return false;
+ }
-bool FBGui::run()
-{
- struct timeval tv;
+ m_stage_width = fb_glue->width();
+ m_stage_height = fb_glue->height();
+ _validbounds.setTo(0, 0, m_stage_width-1, m_stage_height-1);
- double start_timer;
-
- if (!gettimeofday(&tv, NULL))
- start_timer = static_cast<double>(tv.tv_sec) +
- static_cast<double>(tv.tv_usec) / 1000000.0;
- else
- start_timer = 0.0;
+ _renderer.reset(fb_glue->createRenderHandler());
+ _runResources.setRenderer(_renderer);
-
- // let the GUI recompute the x/y scale factors to best fit the whole screen
- resize_view(_validbounds.width(), _validbounds.height());
+ disable_terminal();
- while (!terminate_request) {
-
- // wait the "heartbeat" inteval
- gnashSleep(_interval * 1000);
- // 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
- check_mouse();
- check_keyboard();
-
- // advance movie
- Gui::advance_movie(this);
-
- }
-
- return true;
+ return true;
}
-
-void FBGui::renderBuffer()
+
+bool
+FBGui::run()
{
- if ( _drawbounds.size() == 0 ) return; // nothing to do..
-
-#ifdef DOUBLE_BUFFER
-
- // Size of a pixel in bytes
- // NOTE: +7 to support 15 bpp
- const unsigned int pixel_size = (var_screeninfo.bits_per_pixel+7)/8;
+ GNASH_REPORT_FUNCTION;
+ struct timeval tv;
+ double start_timer;
- for (unsigned int bno=0; bno < _drawbounds.size(); bno++) {
-
- geometry::Range2d<int>& bounds = _drawbounds[bno];
+ if (!gettimeofday(&tv, NULL))
+ start_timer = static_cast<double>(tv.tv_sec) +
+ static_cast<double>(tv.tv_usec) / 1000000.0;
+ else
+ start_timer = 0.0;
- assert ( ! bounds.isWorld() );
- // Size, in bytes, of a row that has to be copied
- const unsigned int row_size = (bounds.width()+1) * pixel_size;
-
- // copy each row
- const int minx = bounds.getMinX();
- const int maxy = bounds.getMaxY();
-
- for (int y=bounds.getMinY(); y<=maxy; ++y) {
+ // let the GUI recompute the x/y scale factors to best fit the whole screen
+ resize_view(_validbounds.width(), _validbounds.height());
- const unsigned int pixel_index = y * m_rowsize + minx*pixel_size;
-
- memcpy(&fbmem[pixel_index], &buffer[pixel_index], row_size);
-
+ while (!terminate_request) {
+
+ // wait the "heartbeat" inteval
+ gnashSleep(_interval * 1000);
+ // 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
+ check_mouse();
+ check_keyboard();
+
+ // advance movie
+ Gui::advance_movie(this);
+
}
- }
-
-#endif
-
-#ifdef DEBUG_SHOW_FPS
- profile();
-#endif
+
+ return true;
}
-bool FBGui::createWindow(const char* /*title*/, int /*width*/, int /*height*/,
- int /*xPosition*/, int /*yPosition*/)
+void FBGui::renderBuffer()
{
- // Framebuffer has no windows... :-)
-
- return true;
+ fb_glue->render();
}
-bool FBGui::createMenu()
+bool
+FBGui::createWindow(const char* /*title*/, int /*width*/, int /*height*/,
+ int /*xPosition*/, int /*yPosition*/)
{
- // no menu support!
- return true;
+ // Framebuffer has no windows... :-)
+
+ return true;
}
-bool FBGui::setupEvents()
+bool
+FBGui::createMenu()
{
- // events currently not supported!
- return true;
+ // no menu support!
+ return true;
}
-void FBGui::setInterval(unsigned int interval)
+bool
+FBGui::setupEvents()
{
- _interval = interval;
+ // events currently not supported!
+ return true;
}
-void FBGui::setTimeout(unsigned int /*timeout*/)
+void
+FBGui::setInterval(unsigned int interval)
{
+ _interval = interval;
+}
+void
+FBGui::setTimeout(unsigned int /*timeout*/)
+{
+
}
-void FBGui::setFullscreen()
+void
+FBGui::setFullscreen()
{
- // FB GUI always runs fullscreen; ignore...
+ // FB GUI always runs fullscreen; ignore...
}
-void FBGui::unsetFullscreen()
+void
+FBGui::unsetFullscreen()
{
- // FB GUI always runs fullscreen; ignore...
+ // FB GUI always runs fullscreen; ignore...
}
-void FBGui::showMenu(bool /*show*/)
+void
+FBGui::showMenu(bool /*show*/)
{
- log_unimpl(_("This GUI does not yet support menus"));
+ log_unimpl(_("This GUI does not yet support menus"));
}
-bool FBGui::showMouse(bool /*show*/)
+bool
+FBGui::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;
+ 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 FBGui::valid_x(int x) {
- if (x<0) x=0;
- if (x>=m_stage_width) x=m_stage_width-1;
- return x;
+int
+FBGui::valid_x(int x)
+{
+ if (x < 0) {
+ x = 0;
+ }
+ if (x >= m_stage_width) {
+ x = m_stage_width - 1;
+ }
+ return x;
}
-int FBGui::valid_y(int y) {
- if (y<0) y=0;
- if (y>=m_stage_height) y=m_stage_height-1;
- return y;
+int
+FBGui::valid_y(int y)
+{
+ if (y < 0) {
+ y = 0;
+ }
+ if (y >= m_stage_height) {
+ y = m_stage_height - 1;
+ }
+ return y;
}
-void FBGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
+void
+FBGui::setInvalidatedRegions(const InvalidatedRanges& ranges)
{
- _renderer->set_invalidated_regions(ranges);
+ // GNASH_REPORT_FUNCTION;
- _drawbounds.clear();
+ // We can't proceed without a renderer
+ assert(_renderer);
- 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;
+ _renderer->set_invalidated_regions(ranges);
+ _drawbounds.clear();
+
+ for (size_t 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);
+
+ }
- _drawbounds.push_back(bounds);
-
- }
-
}
-char* FBGui::find_accessible_tty(int no) {
-
- char* fn;
-
- fn = find_accessible_tty("/dev/vc/%d", no); if (fn) return fn;
- fn = find_accessible_tty("/dev/tty%d", no); if (fn) return fn;
- fn = find_accessible_tty("/dev/tty%02x", no); if (fn) return fn;
- fn = find_accessible_tty("/dev/tty%x", no); if (fn) return fn;
- fn = find_accessible_tty("/dev/tty%02d", no); if (fn) return fn;
-
- if (no==0) {
- fn = find_accessible_tty("/dev/tty", no); // just "/dev/tty"
- if (fn) return fn;
- }
+char *
+FBGui::find_accessible_tty(int no)
+{
+ GNASH_REPORT_FUNCTION;
- return NULL;
-
+ char* fn;
+
+ fn = find_accessible_tty("/dev/vc/%d", no); if (fn) return fn;
+ fn = find_accessible_tty("/dev/tty%d", no); if (fn) return fn;
+ fn = find_accessible_tty("/dev/tty%02x", no); if (fn) return fn;
+ fn = find_accessible_tty("/dev/tty%x", no); if (fn) return fn;
+ fn = find_accessible_tty("/dev/tty%02d", no); if (fn) return fn;
+
+ if (no == 0) {
+ fn = find_accessible_tty("/dev/tty", no); // just "/dev/tty"
+ if (fn) return fn;
+ }
+
+ return 0;
}
-char* FBGui::find_accessible_tty(const char* format, int no) {
-
- static char fname[1024];
-
- snprintf(fname, sizeof fname, format, no);
+char *
+FBGui::find_accessible_tty(const char* format, int no)
+{
+ // GNASH_REPORT_FUNCTION;
- if (access(fname, R_OK|W_OK) != -1) {
- return fname;
- }
-
- return NULL;
+ static char fname[1024];
+
+ snprintf(fname, sizeof fname, format, no);
+
+ if (access(fname, R_OK|W_OK) != -1) {
+ return fname;
+ }
+
+ return 0;
}
-bool FBGui::disable_terminal()
+bool
+FBGui::disable_terminal()
{
- original_kd = -1;
-
- struct vt_stat vts;
-
- // Find the TTY device name
-
- char* tty = find_accessible_tty(0);
-
- int fd;
-
- if (!tty) {
- log_debug(_("WARNING: Could not detect controlling TTY"));
- return false;
- }
-
-
- // Detect the currently active virtual terminal (so we can switch back to
- // it later)
-
- fd = open(tty, O_RDWR);
- if (fd<0) {
- log_debug(_("WARNING: Could not open %s"), tty);
- return false;
- }
-
- if (ioctl(fd, VT_GETSTATE, &vts) == -1) {
- log_debug(_("WARNING: Could not get current VT state"));
- close(fd);
- return false;
- }
+ GNASH_REPORT_FUNCTION;
+
+ original_kd = -1;
+
+ struct vt_stat vts;
+
+ // Find the TTY device name
+
+ char* tty = find_accessible_tty(0);
+
+ int fd;
+
+ if (!tty) {
+ log_debug(_("WARNING: Could not detect controlling TTY"));
+ return false;
+ }
+
+
+ // Detect the currently active virtual terminal (so we can switch back to
+ // it later)
+
+ fd = open(tty, O_RDWR);
+ if (fd<0) {
+ log_debug(_("WARNING: Could not open %s"), tty);
+ return false;
+ }
+
+ if (ioctl(fd, VT_GETSTATE, &vts) == -1) {
+ log_debug(_("WARNING: Could not get current VT state"));
+ close(fd);
+ return false;
+ }
+
+ original_vt = vts.v_active;
+ log_debug(_("Original TTY NO = %d"), original_vt);
- original_vt = vts.v_active;
- log_debug(_("Original TTY NO = %d"), original_vt);
-
#ifdef REQUEST_NEW_VT
-
- // Request a new VT number
- if (ioctl(fd, VT_OPENQRY, &own_vt) == -1) {
- log_debug(_("WARNING: Could not request a new VT"));
- close(fd);
- return false;
- }
-
- log_debug(_("Own TTY NO = %d"), own_vt);
-
- close(fd);
-
- // Activate our new VT
- tty = find_accessible_tty(own_vt);
- if (!tty) {
- log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
- return false;
- }
-
- fd = open(tty, O_RDWR);
- if (fd<0) {
- log_debug(_("WARNING: Could not open %s"), tty);
- return false;
- }
-
- if (ioctl(fd, VT_ACTIVATE, own_vt) == -1) {
- log_debug(_("WARNING: Could not activate VT number %d"), own_vt);
+
+ // Request a new VT number
+ if (ioctl(fd, VT_OPENQRY, &own_vt) == -1) {
+ log_debug(_("WARNING: Could not request a new VT"));
+ close(fd);
+ return false;
+ }
+
+ log_debug(_("Own TTY NO = %d"), own_vt);
+
close(fd);
- return false;
- }
+
+ // Activate our new VT
+ tty = find_accessible_tty(own_vt);
+ if (!tty) {
+ log_debug(_("WARNING: Could not find device for VT number %d"),
own_vt);
+ return false;
+ }
+
+ fd = open(tty, O_RDWR);
+ if (fd<0) {
+ log_debug(_("WARNING: Could not open %s"), tty);
+ return false;
+ }
- if (ioctl(fd, VT_WAITACTIVE, own_vt) == -1) {
- log_debug(_("WARNING: Error waiting for VT %d becoming active"), own_vt);
- //close(tty);
- //return false; don't abort
- }
+ if (ioctl(fd, VT_ACTIVATE, own_vt) == -1) {
+ log_debug(_("WARNING: Could not activate VT number %d"), own_vt);
+ close(fd);
+ return false;
+ }
+
+ if (ioctl(fd, VT_WAITACTIVE, own_vt) == -1) {
+ log_debug(_("WARNING: Error waiting for VT %d becoming active"),
own_vt);
+ //close(tty);
+ //return false; don't abort
+ }
#else
-
- own_vt = original_vt; // keep on using the original VT
-
- close(fd);
-
- // Activate our new VT
- tty = find_accessible_tty(own_vt);
- if (!tty) {
- log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
- return false;
- }
-
- fd = open(tty, O_RDWR);
- if (fd<0) {
- log_debug(_("WARNING: Could not open %s"), tty);
- return false;
- }
-
- /*
- // Become session leader and attach to terminal
- setsid();
- if (ioctl(fd, TIOCSCTTY, 0) == -1) {
+
+ own_vt = original_vt; // keep on using the original VT
+
+ close(fd);
+
+ // Activate our new VT
+ tty = find_accessible_tty(own_vt);
+ if (!tty) {
+ log_debug(_("WARNING: Could not find device for VT number %d"),
own_vt);
+ return false;
+ }
+
+ fd = open(tty, O_RDWR);
+ if (fd<0) {
+ log_debug(_("WARNING: Could not open %s"), tty);
+ return false;
+ }
+
+ /*
+ // Become session leader and attach to terminal
+ setsid();
+ if (ioctl(fd, TIOCSCTTY, 0) == -1) {
log_debug(_("WARNING: Could not attach controlling terminal (%s)"), tty);
- }
- */
-
-
+ }
+ */
+
+
#endif
-
- // Disable keyboard cursor
-
- if (ioctl(fd, KDGETMODE, &original_kd) == -1) {
- log_debug(_("WARNING: Could not query current keyboard mode on VT"));
- }
-
- if (ioctl(fd, KDSETMODE, KD_GRAPHICS) == -1) {
- log_debug(_("WARNING: Could not switch to graphics mode on new VT"));
- }
-
- close(fd);
-
- log_debug(_("VT %d ready"), own_vt);
-
-
- // NOTE: We could also implement virtual console switching by using
- // VT_GETMODE / VT_SETMODE ioctl calls and handling their signals, but
- // probably nobody will ever want to switch consoles, so I don't bother...
-
- return true;
+
+ // Disable keyboard cursor
+
+ if (ioctl(fd, KDGETMODE, &original_kd) == -1) {
+ log_debug(_("WARNING: Could not query current keyboard mode on VT"));
+ }
+
+ if (ioctl(fd, KDSETMODE, KD_GRAPHICS) == -1) {
+ log_debug(_("WARNING: Could not switch to graphics mode on new VT"));
+ }
+
+ close(fd);
+
+ log_debug(_("VT %d ready"), own_vt);
+
+
+ // NOTE: We could also implement virtual console switching by using
+ // VT_GETMODE / VT_SETMODE ioctl calls and handling their signals, but
+ // probably nobody will ever want to switch consoles, so I don't bother...
+
+ return true;
}
-bool FBGui::enable_terminal()
+bool
+FBGui::enable_terminal()
{
+ GNASH_REPORT_FUNCTION;
- log_debug(_("Restoring terminal..."));
-
- char* tty = find_accessible_tty(own_vt);
- if (!tty) {
- log_debug(_("WARNING: Could not find device for VT number %d"), own_vt);
- return false;
- }
+ log_debug(_("Restoring terminal..."));
+
+ char* tty = find_accessible_tty(own_vt);
+ if (!tty) {
+ log_debug(_("WARNING: Could not find device for VT number %d"),
own_vt);
+ return false;
+ }
- int fd = open(tty, O_RDWR);
- if (fd<0) {
- log_debug(_("WARNING: Could not open %s"), tty);
- return false;
- }
+ int fd = open(tty, O_RDWR);
+ if (fd<0) {
+ log_debug(_("WARNING: Could not open %s"), tty);
+ return false;
+ }
- if (ioctl(fd, VT_ACTIVATE, original_vt)) {
- log_debug(_("WARNING: Could not activate VT number %d"), original_vt);
- close(fd);
- return false;
- }
+ if (ioctl(fd, VT_ACTIVATE, original_vt)) {
+ log_debug(_("WARNING: Could not activate VT number %d"),
original_vt);
+ close(fd);
+ return false;
+ }
- if (ioctl(fd, VT_WAITACTIVE, original_vt)) {
- log_debug(_("WARNING: Error waiting for VT %d becoming active"),
original_vt);
- //close(tty);
- //return false; don't abort
- }
+ if (ioctl(fd, VT_WAITACTIVE, original_vt)) {
+ log_debug(_("WARNING: Error waiting for VT %d becoming active"),
original_vt);
+ //close(tty);
+ //return false; don't abort
+ }
- // Restore keyboard
+ // Restore keyboard
- if (ioctl(fd, KDSETMODE, original_kd)) {
- log_debug(_("WARNING: Could not restore keyboard mode"));
- }
+ if (ioctl(fd, KDSETMODE, original_kd)) {
+ log_debug(_("WARNING: Could not restore keyboard mode"));
+ }
- close(fd);
+ close(fd);
- return true;
-}
+ return true;
+ }
-void FBGui::read_mouse_data()
-{
- if (input_fd<0) return; // no mouse available
+ void FBGui::read_mouse_data()
+ {
+ if (input_fd<0) return; // no mouse available
- int count;
+ int count;
- unsigned char *ptr;
+ unsigned char *ptr;
- ptr = mouse_buf + mouse_buf_size;
+ ptr = mouse_buf + mouse_buf_size;
- count = read(input_fd, mouse_buf + mouse_buf_size,
- sizeof(mouse_buf) - mouse_buf_size);
+ count = read(input_fd, mouse_buf + mouse_buf_size,
+ sizeof(mouse_buf) - mouse_buf_size);
- if (count<=0) return;
+ if (count<=0) return;
- /*
- printf("read data: ");
- int i;
- for (i=0; i<count; i++)
- printf("%02x ", ptr[i]);
- printf("\n");
- */
+ /*
+ printf("read data: ");
+ int i;
+ for (i=0; i<count; i++)
+ printf("%02x ", ptr[i]);
+ printf("\n");
+ */
- mouse_buf_size += count;
+ mouse_buf_size += count;
-}
+ }
#ifdef USE_MOUSE_PS2
-bool FBGui::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()
+ bool FBGui::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 FBGui::init_mouse()
+bool
+FBGui::init_mouse()
{
- // see http://www.computer-engineering.org/ps2mouse/
+ // 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);
+ // 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;
- }
+ if (input_fd<0) {
+ log_debug(_("Could not open " MOUSE_DEVICE ": %s"),
strerror(errno));
+ return false;
+ }
- unsigned char buf[10], byte;
+ 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;
- }
+ 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 ) { }
+ // 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;
- }
+ // 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."));
+
+ log_debug(_("Mouse enabled."));
- mouse_x = 0;
- mouse_y = 0;
- mouse_btn = 0;
+ mouse_x = 0;
+ mouse_y = 0;
+ mouse_btn = 0;
- return true;
-}
+ return true;
+ }
#endif
#ifdef USE_MOUSE_PS2
-bool FBGui::check_mouse()
-{
- if (input_fd<0) return false; // no mouse available
+ bool FBGui::check_mouse()
+ {
+ if (input_fd<0) return false; // no mouse available
- int i;
- int xmove, ymove, btn, btn_changed;
+ int i;
+ int xmove, ymove, btn, btn_changed;
- read_mouse_data();
+ 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
+ // 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 (pos>0) {
+ // remove garbage:
+ memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+ mouse_buf_size -= pos;
+ }
- if (mouse_buf_size >= 3) {
+ if (mouse_buf_size >= 3) {
- xmove = mouse_buf[1];
- ymove = mouse_buf[2];
- btn = mouse_buf[0] & 1;
+ 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);
+ if (mouse_buf[0] & 0x10) xmove = -(256-xmove);
+ if (mouse_buf[0] & 0x20) ymove = -(256-ymove);
- ymove *= -1; // vertical movement is upside-down
+ ymove *= -1; // vertical movement is upside-down
- log_debug(_("x/y %d/%d btn %d"), xmove, ymove, btn);
+ log_debug(_("x/y %d/%d btn %d"), xmove, ymove, btn);
- // movement
- mouse_x += xmove;
- mouse_y += ymove;
+ // 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;
+ 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);
+ //log_debug(_("mouse @ %d / %d, btn %d"), mouse_x, mouse_y,
mouse_btn);
- notifyMouseMove(mouse_x, mouse_y);
+ notify_mouse_moved(mouse_x, mouse_y);
- // button
- if (btn != mouse_btn) {
- mouse_btn = btn;
-printf("clicked: %d\n", btn);
- notifyMouseClick(btn); // 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;
+ // button
+ if (btn != mouse_btn) {
+ mouse_btn = btn;
+ printf("clicked: %d\n", 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;
+ return true;
- }
+ }
-}
+ }
#endif
#ifdef USE_MOUSE_ETT
-bool FBGui::init_mouse()
-{
- // Try to open mouse device, be error tolerant (FD is kept open all the time)
- input_fd = open(MOUSE_DEVICE, O_RDWR);
+ bool FBGui::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;
- }
+ if (input_fd<0) {
+ log_debug(_("Could not open " MOUSE_DEVICE ": %s"),
strerror(errno));
+ return false;
+ }
- unsigned char buf[10];
+ 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;
- }
+ 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 ) { }
+ // Clear input buffer
+ while ( read(input_fd, buf, sizeof buf) > 0 ) { }
- mouse_buf_size=0;
+ mouse_buf_size=0;
- log_debug(_("Touchpad enabled."));
- return true;
-}
+ log_debug(_("Touchpad enabled."));
+ return true;
+ }
#endif
#ifdef USE_MOUSE_ETT
-bool FBGui::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]);
+ bool FBGui::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;
+ }
- /*
- 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);
- */
+ // 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 = static_cast<int>(((static_cast<double>(new_x )- 355) / (1702 - 355)
- * 1536 + 256));
- new_y = static_cast<int>(((static_cast<double>(new_y) - 482) / (1771 - 482)
- * 1536 + 256));
+ new_x = static_cast<int>(((static_cast<double>(new_x )- 355) /
(1702 - 355)
+ * 1536 + 256));
+ new_y = static_cast<int>(((static_cast<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;
- notifyMouseMove(mouse_x, mouse_y);
- activity = true;
- }
+ new_x = new_x * m_stage_width / 2048;
+ new_y = (2048-new_y) * m_stage_height / 2048;
- if (new_btn != mouse_btn) {
- mouse_btn = new_btn;
-printf("clicked: %d\n", mouse_btn);
- notifyMouseClick(mouse_btn); // mask=?
- activity = true;
- }
+ 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;
+ printf("clicked: %d\n", mouse_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;
- }
+ // remove from buffer
+ pos=5;
+ memmove(mouse_buf, mouse_buf + pos, mouse_buf_size - pos);
+ mouse_buf_size -= pos;
+ }
- return activity;
+ return activity;
-}
+ }
#endif
#ifdef USE_INPUT_EVENTS
-bool FBGui::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 FBGui::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;
+ bool FBGui::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 FBGui::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");
+ char* settings = std::getenv("TSCALIB");
- if (settings) {
+ if (settings) {
- // expected format:
- // 491,1635,1581,646 (cal1x,cal1y,cal2x,cal2y; all integers)
+ // expected format:
+ // 491,1635,1581,646 (cal1x,cal1y,cal2x,cal2y; all
integers)
- char buffer[1024];
- char* p1;
- char* p2;
- bool ok = false;
+ char buffer[1024];
+ char* p1;
+ char* p2;
+ bool ok = false;
- snprintf(buffer, sizeof buffer, "%s", settings);
- p1 = buffer;
+ 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;
+ 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;
+ // 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;
+ // cal2x
+ p2 = strchr(p1, ',');
+ if (!p2) continue; // stop here
+ *p2 = 0;
+ cal2x = atoi(p1);
+ p1=p2+1;
- // cal2y
- cal2y = atoi(p1);
+ // cal2y
+ cal2y = atoi(p1);
- ok = true;
+ ok = true;
- } while (0);
+ } while (0);
- if (!ok)
- log_debug(_("WARNING: Error parsing calibration data!"));
+ if (!ok)
+ log_debug(_("WARNING: Error parsing calibration data!"));
- log_debug(_("Using touchscreen calibration data: %.0f / %.0f / %.0f /
%.0f"),
- cal1x, cal1y, cal2x, cal2y);
+ 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"));
- }
+ } 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
+ } //!initialized
- // real duty:
- *cx = (rawx-cal1x) / (cal2x-cal1x) * (ref2x-ref1x) + ref1x;
- *cy = (rawy-cal1y) / (cal2y-cal1y) * (ref2y-ref1y) + ref1y;
-}
+ // real duty:
+ *cx = (rawx-cal1x) / (cal2x-cal1x) * (ref2x-ref1x) + ref1x;
+ *cy = (rawy-cal1y) / (cal2y-cal1y) * (ref2y-ref1y) + ref1y;
+ }
-bool FBGui::check_mouse()
-{
- bool activity = false;
+ bool FBGui::check_mouse()
+ {
+ bool activity = false;
- if (input_fd < 0) return false;
+ if (input_fd < 0) return false;
- struct input_event ev; // time,type,code,value
+ 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;
+ 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 notifyMouseMove()
- int notify_y=0;
- bool move_pending = false; // true: notifyMouseMove() should be called
+ 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;
+ // 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;
+ // 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...
+ // Assuming we will never read less than one full struct...
- while ((loops++ < 100) && (read(input_fd, &ev, sizeof ev) == (sizeof ev))) {
+ 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)) {
+ 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;
+ mouse_x = new_mouse_x;
+ mouse_y = new_mouse_y;
- float cx, cy;
+ 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; }
+ 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 notifyMouseMove() here because this would lead to
- // lots of calls, especially for touchscreens. Instead we save the
- // coordinate and call notifyMouseMove() only once.
- notify_x = cx;
- notify_y = cy;
- move_pending = true;
- }
+ // 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 (new_mouse_btn != mouse_btn) {
- if (move_pending) {
- notifyMouseMove(notify_x, notify_y);
- activity = true;
- move_pending = false;
- }
+ if (move_pending) {
+ notifyMouseMove(notify_x, notify_y);
+ activity = true;
+ move_pending = false;
+ }
- mouse_btn = new_mouse_btn;
- notifyMouseClick(mouse_btn); // mark=??
- activity = true;
- }
+ mouse_btn = new_mouse_btn;
+ notifyMouseClick(mouse_btn); // mark=??
+ activity = true;
+ }
- if (coordinatedebug)
- printf("DEBUG: % 5d / % 5d / % 5d\n", mouse_x, mouse_y, mouse_btn);
+ if (coordinatedebug)
+ printf("DEBUG: % 5d / % 5d / % 5d\n", mouse_x, mouse_y,
mouse_btn);
- }
+ }
- if (ev.type == EV_KEY) { // button down/up
+ if (ev.type == EV_KEY) { // button down/up
- // don't care which button, we support only one...
- new_mouse_btn = ev.value;
+ // 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.code == ABS_PRESSURE) new_mouse_btn = ev.value >= 128;
- }
+ 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.code == ABS_PRESSURE) new_mouse_btn = ev.value >= 128;
+ }
- 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 (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 < 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 (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) {
- notifyMouseMove(notify_x, notify_y);
- activity = true;
- }
+ if (move_pending) {
+ notifyMouseMove(notify_x, notify_y);
+ activity = true;
+ }
- return activity;
+ return activity;
-} //check_mouse
+ } //check_mouse
#endif
-bool FBGui::init_keyboard()
-{
- std::string dev;
+ bool FBGui::init_keyboard()
+ {
+ std::string dev;
- char* devname = std::getenv("KEYBOARD_DEVICE");
- if (devname) dev = devname;
- else dev = "/dev/input/event0";
+ 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);
+ // 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;
- }
+ 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());
+ 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;
- }
+ 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;
-}
+ return true;
+ }
-gnash::key::code FBGui::scancode_to_gnash_key(int code, bool shift) {
+ gnash::key::code FBGui::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;
+ // 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_MULTIPLY;
- 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;
-}
+ 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_MULTIPLY;
+ 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 FBGui::check_keyboard()
-{
- bool activity = false;
+ bool FBGui::check_keyboard()
+ {
+ bool activity = false;
- if (keyb_fd < 0) return false;
+ if (keyb_fd < 0) return false;
- struct input_event ev; // time,type,code,value
+ struct input_event ev; // time,type,code,value
- while (read(keyb_fd, &ev, sizeof ev) == (sizeof ev)) {
+ while (read(keyb_fd, &ev, sizeof ev) == (sizeof ev)) {
- if (ev.type == EV_KEY) {
+ if (ev.type == EV_KEY) {
- // code == scan code of the key (KEY_xxxx defines in input.h)
+ // 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 {
+ // 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);
+ gnash::key::code c =
scancode_to_gnash_key(ev.code,
+
keyb_lshift || keyb_rshift);
- // build modifier
+ // build modifier
- int modifier = gnash::key::GNASH_MOD_NONE;
+ int modifier =
gnash::key::GNASH_MOD_NONE;
- if (keyb_lshift || keyb_rshift)
- modifier = modifier | gnash::key::GNASH_MOD_SHIFT;
+ 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_lctrl || keyb_rctrl)
+ modifier = modifier |
gnash::key::GNASH_MOD_CONTROL;
- if (keyb_lalt || keyb_ralt)
- modifier = modifier | gnash::key::GNASH_MOD_ALT;
+ 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;
- }
+ // send event
+ if (c != gnash::key::INVALID) {
+ Gui::notify_key_event(c, modifier,
ev.value);
+ activity=true;
+ }
- } //if normal key
+ } //if normal key
- } //if EV_KEY
+ } //if EV_KEY
- } //while
+ } //while
- return activity;
+ return activity;
+
+ }
+ // end of namespace gnash
}
-// end of namespace gnash
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+// Simulate the ioctls used to get information from the framebuffer
+// driver. Since this is an emulator, we have to set these fields
+// to a reasonable default.
+int
+fakefb_ioctl(int /* fd */, int request, void *data)
+{
+ // GNASH_REPORT_FUNCTION;
+
+ switch (request) {
+ case FBIOGET_VSCREENINFO:
+ {
+ struct fb_var_screeninfo *ptr =
+ reinterpret_cast<struct fb_var_screeninfo *>(data);
+ // If we are using a simulated framebuffer, the default for
+ // fbe us 640x480, 8bits. So use that as a sensible
+ // default. Note that the fake framebuffer is only used for
+ // debugging and development.
+ ptr->xres = 640; // visible resolution
+ ptr->xres_virtual = 640; // virtual resolution
+ ptr->yres = 480; // visible resolution
+ ptr->yres_virtual = 480; // virtual resolution
+ ptr->width = 640; // width of picture in mm
+ ptr->height = 480; // height of picture in mm
+
+ // Android uses a 16bit framebuffer
+ ptr->bits_per_pixel = 16;
+ ptr->red.length = 5;
+ ptr->red.offset = 11;
+ ptr->green.length = 6;
+ ptr->green.offset = 5;
+ ptr->blue.length = 5;
+ ptr->blue.offset = 0;
+ ptr->transp.offset = 0;
+ ptr->transp.length = 0;
+ // 8bit framebuffer
+ // ptr->bits_per_pixel = 8;
+ // ptr->red.length = 8;
+ // ptr->red.offset = 0;
+ // ptr->green.length = 8;
+ // ptr->green.offset = 0;
+ // ptr->blue.length = 8;
+ // ptr->blue.offset = 0;
+ // ptr->transp.offset = 0;
+ // ptr->transp.length = 0;
+ ptr->grayscale = 1; // != 0 Graylevels instead of color
+
+ break;
+ }
+ case FBIOGET_FSCREENINFO:
+ {
+ struct fb_fix_screeninfo *ptr =
+ reinterpret_cast<struct fb_fix_screeninfo *>(data);
+ ptr->smem_len = 307200; // Length of frame buffer mem
+ ptr->type = FB_TYPE_PACKED_PIXELS; // see FB_TYPE_*
+ ptr->visual = FB_VISUAL_PSEUDOCOLOR; // see FB_VISUAL_*
+ ptr->xpanstep = 0; // zero if no hardware panning
+ ptr->ypanstep = 0; // zero if no hardware panning
+ ptr->ywrapstep = 0; // zero if no hardware panning
+ ptr->accel = FB_ACCEL_NONE; // Indicate to driver which specific
+ // chip/card we have
+ break;
+ }
+ case FBIOPUTCMAP:
+ {
+ // Fbe uses this name for the fake framebuffer, so in this
+ // case assume we're using fbe, so write to the known fbe
+ // cmap file.
+ std::string str = FAKEFB;
+ if (str == "/tmp/fbe_buffer") {
+ int fd = open("/tmp/fbe_cmap", O_WRONLY);
+ if (fd) {
+ write(fd, data, sizeof(struct fb_cmap));
+ close(fd);
+ } else {
+ gnash::log_error("Couldn't write to the fake cmap!");
+ return -1;
+ }
+ } else {
+ gnash::log_error("Couldn't write to the fake cmap, unknown
type!");
+ return -1;
+ }
+ // If we send a SIGUSR1 signal to fbe, it'll reload the
+ // color map.
+ int fd = open("/tmp/fbe.pid", O_RDONLY);
+ char buf[10];
+ if (fd) {
+ if (read(fd, buf, 10) == 0) {
+ close(fd);
+ return -1;
+ } else {
+ pid_t pid = strtol(buf, 0, NULL);
+ kill(pid, SIGUSR1);
+ gnash::log_debug("Signaled fbe to reload it's colormap.");
+ }
+ close(fd);
+ }
+ break;
+ }
+ default:
+ gnash::log_unimpl("fakefb_ioctl(%d)", request);
+ break;
+ }
+
+ return 0;
}
+#endif // ENABLE_FAKE_FRAMEBUFFER
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fb_glue_ovg.h b/gui/fb/fb_glue_ovg.h
new file mode 100644
index 0000000..2a5c992
--- /dev/null
+++ b/gui/fb/fb_glue_ovg.h
@@ -0,0 +1,74 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+
+#ifndef FB_GLUE_OVG_H
+#define FB_GLUE_OVG_H 1
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <boost/cstdint.hpp>
+
+#include "fbsup.h"
+
+#ifdef HAVE_VG_OPENVG_H
+#include <VG/openvg.h>
+#endif
+
+namespace gnash {
+
+class render_handler;
+
+class FBOvgGlue : public FBGlue
+{
+public:
+ FBOvgGlue(int fd);
+ FBOvgGlue(int x, int y, int width, int height);
+ ~FBOvgGlue();
+
+ virtual bool init(int argc, char ***argv);
+ virtual void render();
+
+ // resize(int width, int height);
+ void draw();
+ // Renderer* createRenderHandler();
+ void initBuffer(int width, int height);
+ void resize(int width, int height);
+ // void render(geometry::Range2d<int>& bounds);
+
+private:
+ int _width;
+ int _height;
+ int _stride;
+ boost::uint8_t *_offscreenbuf;
+ // Renderer *_renderer;
+
+ //Rectangle _bounds;
+ geometry::Range2d<int> _drawbounds;
+ geometry::Range2d<int> _validbounds;
+};
+
+} // end of namespace gnash
+
+#endif // end of FB_GLUE_OVG_H
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/fb/fbsup.h b/gui/fb/fbsup.h
index 2d3a4a1..506a3bc 100644
--- a/gui/fb/fbsup.h
+++ b/gui/fb/fbsup.h
@@ -31,16 +31,6 @@
#define PIXELFORMAT_LUT8
#define CMAP_SIZE (256*2)
-// If defined, an internal software-buffer is used for rendering and is then
-// copied to the video RAM. This avoids flicker and is faster for complex
-// graphics, as video RAM access is usually slower.
-// (strongly suggested)
-#define DOUBLE_BUFFER
-
-
-// TODO: Make this configurable via ./configure!
-
-
// Define this to read from /dev/input/mice (any PS/2 compatbile mouse or
// emulated by the Kernel)
//#define USE_MOUSE_PS2
@@ -60,16 +50,13 @@
#define MOUSE_DEVICE "/dev/usb/tkpanel0"
#endif
-
// Define this to request a new virtual terminal at startup. This doesn't
always
// work and probably is not necessary anyway
//#define REQUEST_NEW_VT
-
namespace gnash
{
-
/// A Framebuffer-based GUI for Gnash.
/// ----------------------------------
///
@@ -108,87 +95,98 @@ namespace gnash
///
/// any PS/2 compatible mouse (may be emulated by the kernel) talking
/// to /dev/input/mice
+
+class Renderer;
+
+/// Base class for Framebuffer renderer used by the GUI
+class FBGlue
+{
+public:
+ FBGlue();
+ virtual ~FBGlue();
+
+ /// Initialize the glue between the Renderer and the GUI
+ virtual bool init(int argc, char ***argv) = 0;
+
+ /// Create a new render handler
+ virtual Renderer *createRenderHandler() = 0;
+
+ virtual void setInvalidatedRegions(const InvalidatedRanges& ranges) = 0;
+
+ virtual int width() = 0;
+ virtual int height() = 0;
+
+ virtual void render() = 0;
+};
+
+/// Base class for Framebuffer based displays
class FBGui : public Gui
{
- private:
- int fd;
- int original_vt; // virtual terminal that was active at
startup
- int original_kd; // keyboard mode at startup
- int own_vt; // virtual terminal we are running in
- unsigned char *fbmem; // framebuffer memory
-#ifdef DOUBLE_BUFFER
- unsigned char *buffer; // offscreen buffer
-#endif
+private:
+ int _fd;
+ int original_vt; // virtual terminal that was active at startup
+ int original_kd; // keyboard mode at startup
+ int own_vt; // virtual terminal we are running in
std::vector< geometry::Range2d<int> > _drawbounds;
-
+
int m_stage_width;
int m_stage_height;
- unsigned m_rowsize;
-
- int input_fd; /// file descriptor for /dev/input/mice
- int keyb_fd; /// file descriptor for /dev/input/event* (keyboard)
- int mouse_x, mouse_y, mouse_btn;
- unsigned char mouse_buf[256];
- int mouse_buf_size;
-
- // Keyboard SHIFT/CTRL/ALT states (left + right)
- bool keyb_lshift, keyb_rshift, keyb_lctrl, keyb_rctrl, keyb_lalt,
keyb_ralt;
-
- struct fb_var_screeninfo var_screeninfo;
- struct fb_fix_screeninfo fix_screeninfo;
-
- /// For 8 bit (palette / LUT) modes, sets a grayscale palette.
- //
- /// This GUI currently does not support palette modes.
- ///
- bool set_grayscale_lut8();
-
- bool initialize_renderer();
-
- /// Tries to find a accessible tty
- char* find_accessible_tty(int no);
- char* find_accessible_tty(const char* format, int no);
-
- /// switches from text mode to graphics mode (disables the text
terminal)
- bool disable_terminal();
-
- /// reverts disable_terminal() changes
- bool enable_terminal();
-
+
+ int input_fd; /// file descriptor for /dev/input/mice
+ int keyb_fd; /// file descriptor for /dev/input/event* (keyboard)
+ int mouse_x, mouse_y, mouse_btn;
+ unsigned char mouse_buf[256];
+ int mouse_buf_size;
+
+ // Keyboard SHIFT/CTRL/ALT states (left + right)
+ bool keyb_lshift, keyb_rshift, keyb_lctrl, keyb_rctrl, keyb_lalt,
keyb_ralt;
+
+ FBGlue *fb_glue;
+
+ /// Tries to find a accessible tty
+ char* find_accessible_tty(int no);
+ char* find_accessible_tty(const char* format, int no);
+
+ /// switches from text mode to graphics mode (disables the text terminal)
+ bool disable_terminal();
+
+ /// reverts disable_terminal() changes
+ bool enable_terminal();
+
#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);
+ /// 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();
-
- /// Initializes keyboard routines
- bool init_keyboard();
-
- /// Translates a scancode from the Linux Input Subsystem to a Gnash key
code
+
+ /// Initializes mouse routines
+ bool init_mouse();
+
+ /// Checks for and processes any mouse activity. Returns true on activity.
+ bool check_mouse();
+
+ /// 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();
-
+
+ /// Checks for and processes any keyboard activity. Returns true on
activity.
+ bool check_keyboard();
+
#ifdef USE_INPUT_EVENTS
/// Applies builtin touchscreen calibration
- void apply_ts_calibration(float* cx, float* cy, int rawx, int rawy);
+ void apply_ts_calibration(float* cx, float* cy, int rawx, int rawy);
#endif
-
- int valid_x(int x);
- int valid_y(int y);
-
- public:
- FBGui(unsigned long xid, float scale, bool loop, RunResources&
r);
+
+ int valid_x(int x);
+ int valid_y(int y);
+
+public:
+ FBGui(unsigned long xid, float scale, bool loop, RunResources& r);
virtual ~FBGui();
virtual bool init(int argc, char ***argv);
virtual bool createWindow(const char *title, int width, int height,
@@ -209,9 +207,21 @@ class FBGui : public Gui
virtual void setInvalidatedRegions(const InvalidatedRanges& ranges);
virtual bool want_multiple_regions() { return true; }
};
-
-// end of namespace gnash
+
+ // end of namespace gnash
}
+#ifdef ENABLE_FAKE_FRAMEBUFFER
+/// Simulate the ioctls used to get information from the framebuffer driver.
+///
+/// Since this is an emulator, we have to set these fields to a reasonable
default.
+int
+fakefb_ioctl(int /* fd */, int request, void *data);
#endif
+#endif // end of GNASH_FBSUP_H
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/gtk/gtk.am b/gui/gtk/gtk.am
index 8bbc3bd..78aece7 100644
--- a/gui/gtk/gtk.am
+++ b/gui/gtk/gtk.am
@@ -75,5 +75,13 @@ gtk_gnash_LDADD =
$(top_builddir)/librender/libgnashrender.la \
$(GNASH_LIBS) $(GTK_LIBS) $(CAIRO_LIBS)
endif # BUILD_CAIRO_RENDERER
+if BUILD_OVG_RENDERER
+gtk_gnash_CPPFLAGS += $(OPENVG_CFLAGS) $(EGL_CFLAGS)
+gtk_gnash_SOURCES += gtk/gtk_glue_egl.cpp gtk/gtk_glue_egl.h
+gtk_gnash_LDADD = $(top_builddir)/librender/libgnashrender.la \
+ $(GNASH_LIBS) $(GTK_LIBS) $(OPENVG_LIBS) $(EGL_LIBS)
+
+endif # BUILD_OVG_RENDERER
+
endif # BUILD_GTK_GUI
diff --git a/gui/gtk/gtk_canvas.cpp b/gui/gtk/gtk_canvas.cpp
index 42a57df..e7ea3ea 100644
--- a/gui/gtk/gtk_canvas.cpp
+++ b/gui/gtk/gtk_canvas.cpp
@@ -36,25 +36,29 @@
// OpenGL support for rendering in the canvas. This also requires
// the GtkGL widget for GTK2.
#ifdef HAVE_GTK_GTKGL_H
-#include "gtk_glue_gtkglext.h"
+# include "gtk_glue_gtkglext.h"
+#endif
+
+#ifdef HAVE_VG_OPENVG_H
+# include "gtk_glue_egl.h"
#endif
// Cairo support for rendering in the canvas.
#ifdef HAVE_CAIRO_H
-#include "gtk_glue_cairo.h"
+# include "gtk_glue_cairo.h"
#endif
// This uses the Xv extension to X11, which has widespread support
// for Hw video scaling.
#ifdef HAVE_XV
-#include "gtk_glue_agg_xv.h"
+# include "gtk_glue_agg_xv.h"
#endif
// AGG support, which is the default, for rendering in the canvas.
#include "gtk_glue_agg.h"
#ifdef HAVE_VA_VA_H
-#include "gtk_glue_agg_vaapi.h"
+# include "gtk_glue_agg_vaapi.h"
#endif
struct _GnashCanvas
@@ -80,6 +84,7 @@ namespace {
gnash::RcInitFile& rcfile = gnash::RcInitFile::getDefaultInstance();
}
+// allocate memory for GtkCanvas
GtkWidget *
gnash_canvas_new ()
{
@@ -87,6 +92,7 @@ gnash_canvas_new ()
return GTK_WIDGET(g_object_new (GNASH_TYPE_CANVAS, NULL));
}
+// Initialize canvas,set allocate, expose, comfigure, realize event handlers
static void
gnash_canvas_class_init(GnashCanvasClass *gnash_canvas_class)
{
@@ -101,6 +107,7 @@ gnash_canvas_class_init(GnashCanvasClass
*gnash_canvas_class)
widget_class->realize = gnash_canvas_realize;
}
+// Disable double bufferinf in the canvas, add reaize event handlers
static void
gnash_canvas_init(GnashCanvas *canvas)
{
@@ -163,6 +170,7 @@ static void
gnash_canvas_realize(GtkWidget *widget)
{
GNASH_REPORT_FUNCTION;
+
GnashCanvas *canvas = GNASH_CANVAS(widget);
GdkWindowAttr attributes;
gint attributes_mask;
@@ -197,6 +205,7 @@ static void
gnash_canvas_after_realize(GtkWidget *widget)
{
GNASH_REPORT_FUNCTION;
+
GnashCanvas *canvas = GNASH_CANVAS(widget);
canvas->renderer.reset(canvas->glue->createRenderHandler());
@@ -205,14 +214,14 @@ gnash_canvas_after_realize(GtkWidget *widget)
widget->allocation.height);
}
+// Select renderer and hwaccel, prep canvas for drawing
void
gnash_canvas_setup(GnashCanvas *canvas, std::string& hwaccel,
std::string& renderer, int argc, char **argv[])
{
-
GNASH_REPORT_FUNCTION;
- // Order should be VAAPI, Xv, X11
+ // Order should be VAAPI, Xv, Omap
bool initialized_renderer = false;
// If a renderer hasn't been defined in gnashrc, or on the command
@@ -230,6 +239,7 @@ gnash_canvas_setup(GnashCanvas *canvas, std::string&
hwaccel,
std::string next_hwaccel = hwaccel;
while (!initialized_renderer) {
+ gnash::log_debug("Trying Renderer %s, and HWAccel %s", renderer,
hwaccel);
renderer = next_renderer;
hwaccel = next_hwaccel;
#ifdef HAVE_VA_VA_H
@@ -262,6 +272,17 @@ gnash_canvas_setup(GnashCanvas *canvas, std::string&
hwaccel,
// rendering performance issues.
}
#endif
+#ifdef RENDERER_OPENVG
+ // Use OpenVG, which uses EGL as the display API. This works with
+ // Mesa on desktop unix systems, and on ARM based devices running
+ // Linux, often with manufacturer provided SDKs.
+ if (renderer == "openvg") {
+ canvas->glue.reset(new gnash::GtkEGLGlue);
+ // Set the renderer to the next one to try if initializing
+ // fails.
+ next_renderer = "agg";
+ }
+#endif
if (renderer == "agg") {
// Use LibVva, which works on Nvidia, AT, or Intel 965 GPUs
// with AGG or OpenGL.
@@ -297,9 +318,13 @@ gnash_canvas_setup(GnashCanvas *canvas, std::string&
hwaccel,
(hwaccel == "none")) {
break;
}
+ if (!initialized_renderer) {
+ gnash::log_debug("Trying to find new Renderer %s, and HWAccel %s",
+ renderer, hwaccel);
+ }
}
- if (initialized_renderer && renderer == "opengl") {
+ if (initialized_renderer && (renderer == "opengl" || renderer ==
"openvg")) {
// OpenGL glue needs to prepare the drawing area for OpenGL
// rendering before
// widgets are realized and before the configure event is fired.
@@ -312,12 +337,16 @@ gnash_canvas_setup(GnashCanvas *canvas, std::string&
hwaccel,
void
gnash_canvas_before_rendering(GnashCanvas *canvas)
{
+ // GNASH_REPORT_FUNCTION;
+
canvas->glue->beforeRendering();
}
boost::shared_ptr<gnash::Renderer>
gnash_canvas_get_renderer(GnashCanvas *canvas)
{
+ // GNASH_REPORT_FUNCTION;
+
return canvas->renderer;
}
diff --git a/gui/gtk/gtk_canvas.h b/gui/gtk/gtk_canvas.h
index 15684df..caa66f9 100644
--- a/gui/gtk/gtk_canvas.h
+++ b/gui/gtk/gtk_canvas.h
@@ -36,7 +36,7 @@ typedef struct _GnashCanvasClass GnashCanvasClass;
#define GNASH_TYPE_CANVAS (gnash_canvas_get_type())
#define GNASH_CANVAS(object) (G_TYPE_CHECK_INSTANCE_CAST((object),
GNASH_TYPE_CANVAS, GnashCanvas))
-#define GNASH_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
GNASH_TYPE_CANVAS, GnashCanvasClass))
+#define GNASH_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),
GNASH_TYPE_CANVAS, GnashCanvasClass))
#define GNASH_IS_CANVAS(object) (G_TYPE_CHECK_INSTANCE_TYPE((object),
GNASH_TYPE_CANVAS))
#define GNASH_IS_CANVAS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),
GNASH_TYPE_CANVAS))
#define GNASH_CANVAS_GET_CLASS(object) (G_TYPE_INSTANCE_GET_CLASS((object),
GNASH_TYPE_CANVAS, GnashCanvasClass))
@@ -45,12 +45,19 @@ struct _GnashCanvasClass {
GtkDrawingAreaClass base_class;
};
-GType gnash_canvas_get_type ();
-GtkWidget *gnash_canvas_new ();
+GType gnash_canvas_get_type();
-void gnash_canvas_setup (GnashCanvas *canvas,
std::string &hwaccel, std::string &renderer, int argc, char **argv[]);
-void gnash_canvas_before_rendering (GnashCanvas *canvas);
-boost::shared_ptr<gnash::Renderer> gnash_canvas_get_renderer (GnashCanvas
*canvas);
+/// allocate memory for canvas to draw in
+GtkWidget *gnash_canvas_new();
+
+/// Select renderer and hwaccel, prep canvas for drawing
+void gnash_canvas_setup (GnashCanvas *canvas, std::string &hwaccel,
+ std::string &renderer, int argc, char **argv[]);
+
+void gnash_canvas_before_rendering (GnashCanvas *canvas);
+
+/// Get the Renderer for this canvas
+boost::shared_ptr<gnash::Renderer> gnash_canvas_get_renderer(GnashCanvas
*canvas);
G_END_DECLS
diff --git a/gui/gtk/gtk_glue_cairo.cpp b/gui/gtk/gtk_glue_cairo.cpp
index 7729179..ad6b9e7 100644
--- a/gui/gtk/gtk_glue_cairo.cpp
+++ b/gui/gtk/gtk_glue_cairo.cpp
@@ -53,6 +53,8 @@ void
GtkCairoGlue::prepDrawingArea(GtkWidget *drawing_area)
{
_drawing_area = drawing_area;
+ // Disable double buffering, otherwise gtk tries to update widget
+ // contents from its internal offscreen buffer at the end of expose event
gtk_widget_set_double_buffered(_drawing_area, FALSE);
}
diff --git a/gui/gtk/gtk_glue_egl.cpp b/gui/gtk/gtk_glue_egl.cpp
new file mode 100644
index 0000000..112563a
--- /dev/null
+++ b/gui/gtk/gtk_glue_egl.cpp
@@ -0,0 +1,747 @@
+//
+// Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <cerrno>
+#include <exception>
+#include <gtk/gtk.h>
+#include <gdk/gdk.h>
+
+#include "gnash.h"
+#include "log.h"
+#include "RunResources.h"
+#include "Renderer.h"
+#include "Renderer_ovg.h"
+#include "gtk_glue_egl.h"
+#include "GnashException.h"
+
+#ifdef HAVE_VG_OPENVG_H
+#include <VG/openvg.h>
+#endif
+
+#ifdef HAVE_EGL_EGL_H
+# include <EGL/egl.h>
+#else
+# error "This file needs EGL, which is part of OpenGL-ES"
+#endif
+
+#include <GL/gl.h>
+
+namespace gnash
+{
+
+static const EGLint attrib32_list[] = {
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 0,
+#ifdef RENDERER_GLES
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT,
+#endif
+#ifdef RENDERER_OPENVG
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_DEPTH_SIZE, 24,
+ EGL_STENCIL_SIZE, 8,
+#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_OPENVG
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_DEPTH_SIZE, 0,
+ EGL_STENCIL_SIZE, 0,
+#endif
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_SAMPLE_BUFFERS, 0,
+ EGL_NONE
+};
+
+const EGLint window_attrib_list[] = {
+ // Back buffering is used for window and pbuffer surfaces. Windows
+ // require eglSwapBuffers() to become visible, and pbuffers don't.
+ // EGL_SINGLE_BUFFER is by pixmap surfaces. With OpenVG, windows
+ // can also be single buffered. eglCopyBuffers() can be used to copy
+ // both back and single buffered surfaces to a pixmap.
+ EGL_RENDER_BUFFER, EGL_BACK_BUFFER,
+ EGL_COLORSPACE, EGL_COLORSPACE_sRGB,
+ EGL_NONE
+};
+
+// From the EGL 1.4 spec:
+//
+// EGL defines several types of drawing surfaces collectively referred
+// to as EGLSurfaces. These include windows, used for onscreen
+// rendering; pbuffers, used for offscreen rendering; and pixmaps,
+// used for offscreen rendering into buffers that may be accessed
+// through native APIs. EGL windows and pixmaps are tied to native
+// window system windows and pixmaps.
+//
+// depth, multisample, and stencil buffers are currently used only by
+// OpenGL-ES.
+
+// EGL and OpenGL ES supports two rendering models: back buffered and
+// single buffered. Back buffered rendering is used by window and
+// pbuffer surfaces. Memory for the color buffer used during rendering
+// is allocated and owned by EGL. When the client is finished drawing
+// a frame, the back buffer may be copied to a visible window using
+// eglSwapBuffers. Pbuffer surfaces have a back buffer but no
+// associated window, so the back buffer need not be copied.
+//
+// Single buffered rendering is used by pixmap surfaces. Memory for
+// the color buffer is specified at surface creation time in the form
+// of a native pixmap, and client APIs are required to use that memory
+// during rendering. When the client is finished drawing a frame, the
+// native pixmap contains the final image. Pixmap surfaces typically
+// do not support multisampling, since the native pixmap used as the
+// color buffer is unlikely to provide space to store multisample
+// information. Some client APIs , such as OpenGL and OpenVG , also
+// support single buffered rendering to window surfaces. This behavior
+// can be selected when creating the window surface, as defined in
+// section 3.5.1. When mixing use of client APIs which do not support
+// single buffered rendering into windows, like OpenGL ES , with
+// client APIs which do support it, back color buffers and visible
+// window contents must be kept consistent when binding window
+// surfaces to contexts for each API type. Both back and single
+// buffered surfaces may also be copied to a specified native pixmap
+// using eglCopyBuffers.
+
+// Native rendering will always be supported by pixmap surfaces (to
+// the extent that native rendering APIs can draw to native
+// pixmaps). Pixmap surfaces are typically used when mixing native and
+// client API rendering is desirable, since there is no need to move
+// data between the back buffer visible to the client APIs and the
+// native pixmap visible to native rendering APIs. However, pixmap
+// surfaces may, for the same reason, have restricted capabilities and
+// performance relative to window and pbuffer surfaces.
+
+GtkEGLGlue::GtkEGLGlue()
+: _offscreenbuf(0),
+ _renderer(0),
+ _eglConfig(0),
+ _eglContext(EGL_NO_CONTEXT),
+ _eglSurface(EGL_NO_SURFACE),
+ _eglDisplay(EGL_NO_DISPLAY),
+ _eglNumOfConfigs(0),
+ _nativeWindow(0),
+ _max_num_config(1),
+ _bpp(32),
+ _width(0),
+ _height(0)
+{
+ GNASH_REPORT_FUNCTION;
+}
+
+GtkEGLGlue::~GtkEGLGlue()
+{
+ GNASH_REPORT_FUNCTION;
+
+#ifdef ENABLE_EGL_OFFSCREEN
+ if (_offscreenbuf) {
+ gdk_image_destroy(_offscreenbuf);
+ }
+#endif
+ if (_eglDisplay != EGL_NO_DISPLAY) {
+ eglMakeCurrent(_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE,
EGL_NO_CONTEXT);
+
+ if (_eglContext != EGL_NO_CONTEXT)
+ eglDestroyContext(_eglDisplay, _eglContext);
+
+ if (_eglSurface != EGL_NO_SURFACE)
+ eglDestroySurface(_eglDisplay, _eglSurface);
+
+ // if (_eglwin_native)
+ // free(_eglwin_native);
+
+ eglTerminate(_eglDisplay);
+ }
+}
+
+bool
+GtkEGLGlue::init(int /*argc*/, char ** /*argv*/[])
+{
+ GNASH_REPORT_FUNCTION;
+
+ 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
+
+ // step 1 - get an EGL display
+
+ // This can be called multiple times, and always returns the same display
+ _eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); // FIXME: gdk_display ?
+ if (EGL_NO_DISPLAY == _eglDisplay) {
+ log_error( "eglGetDisplay() failed (error 0x%x)", eglGetError() );
+ return false;
+ }
+
+ // This can be called multiple times safely
+ if (EGL_FALSE == eglInitialize(_eglDisplay, &major, &minor)) {
+ log_error( "eglInitialize() failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+ // log_debug("EGL_CLIENT_APIS = %s", eglQueryString(_eglDisplay,
EGL_CLIENT_APIS));
+ // log_debug("EGL_EXTENSIONS = %s", eglQueryString(_eglDisplay,
EGL_EXTENSIONS));
+ log_debug("EGL_VERSION = %s, EGL_VENDOR = %s",
+ eglQueryString(_eglDisplay, EGL_VERSION),
+ eglQueryString(_eglDisplay, EGL_VENDOR));
+
+ // step2 - bind to the wanted client API
+#ifdef RENDERER_GLES
+ if(EGL_FALSE == eglBindAPI(EGL_OPENGL_ES_API)) {
+ log_error("eglBindAPI() failed to retrive the number of configs (error
%s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+#endif
+#ifdef RENDERER_OPENVG
+ if(EGL_FALSE == eglBindAPI(EGL_OPENVG_API)) {
+ log_error("eglBindAPI() failed to retrive the number of configs (error
%s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+#endif
+
+// queryEGLConfig(_eglDisplay);
+
+ // step3 - find a suitable config
+ if (_bpp == 32) {
+ if (EGL_FALSE == eglChooseConfig(_eglDisplay, attrib32_list,
&_eglConfig,
+ 1, &_eglNumOfConfigs)) {
+ log_error("eglChooseConfig() failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+ } else if (_bpp == 16) {
+ if (EGL_FALSE == eglChooseConfig(_eglDisplay, attrib16_list,
&_eglConfig,
+ 1, &_eglNumOfConfigs)) {
+ log_error("eglChooseConfig() failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+ } else {
+ log_error("No supported bpp value!");
+ }
+
+ if (0 == _eglNumOfConfigs) {
+ log_error("eglChooseConfig() was unable to find a suitable config");
+ return false;
+ }
+
+ EGLint vid;
+ if (!eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_NATIVE_VISUAL_ID,
&vid)) {
+ log_error("eglGetConfigAttrib() failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ }
+
+ XVisualInfo *visInfo, visTemplate;
+ int num_visuals;
+ // The X window visual must match the EGL config
+ visTemplate.visualid = vid;
+ visInfo = XGetVisualInfo(gdk_display, VisualIDMask, &visTemplate,
&num_visuals);
+ if (!visInfo) {
+ log_error("couldn't get X visual");
+ return false;
+ }
+ XFree(visInfo);
+
+ if (!checkEGLConfig(_eglConfig)) {
+ log_error("EGL configuration doesn't match!");
+// return false;
+ } else {
+ //printEGLConfig(_eglConfig);
+ }
+
+ // step4 - create a window surface
+ _nativeWindow = gdk_x11_get_default_root_xwindow();
+
+
+#ifdef RENDERER_GLES
+ _eglSurface = eglCreateWindowSurface(_eglDisplay, &_eglConfig,
_nativeWindow, NULL);
+#endif
+#ifdef RENDERER_OPENVG
+ if (_nativeWindow) {
+ _eglSurface = eglCreateWindowSurface(_eglDisplay, _eglConfig,
+ _nativeWindow, 0); // was
window_attrib_list
+ } else {
+ log_error("No native window!");
+ return false;
+ }
+#endif
+
+ if (EGL_NO_SURFACE == _eglSurface) {
+ log_error("eglCreateWindowSurface failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ } else {
+ //printEGLSurface(_eglSurface);
+ }
+
+ // step5 - create a context
+ _eglContext = eglCreateContext(_eglDisplay, _eglConfig, EGL_NO_CONTEXT,
NULL);
+ if (EGL_NO_CONTEXT == _eglContext) {
+ log_error("eglCreateContext failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ } else {
+ printEGLContext(_eglContext);
+ }
+
+ // step6 - make the context and surface current
+ if (EGL_FALSE == eglMakeCurrent(_eglDisplay, _eglSurface, _eglSurface,
_eglContext)) {
+ log_error("eglMakeCurrent failed (error %s)",
+ getErrorString(eglGetError()));
+ return false;
+ } // begin user code
+
+#if 0
+#if 1
+ eglSwapInterval(_eglDisplay, 0);
+#else
+ eglSwapBuffers(_eglDisplay, _eglSurface);
+#endif
+
+ log_debug("Gnash EGL Frame width %d height %d bpp %d \n", _width, _height,
_bpp);
+#endif
+
+ return true;
+}
+
+void
+GtkEGLGlue::prepDrawingArea(GtkWidget *drawing_area)
+{
+ GNASH_REPORT_FUNCTION;
+
+ _drawing_area = drawing_area;
+
+ // Disable double buffering, otherwise gtk tries to update widget
+ // contents from its internal offscreen buffer at the end of expose event
+ gtk_widget_set_double_buffered(_drawing_area, FALSE);
+
+ DUMP_CURRENT_SURFACE;
+ DUMP_CURRENT_CONTEXT;
+}
+
+Renderer*
+GtkEGLGlue::createRenderHandler()
+{
+ GNASH_REPORT_FUNCTION;
+
+ if (!_drawing_area) {
+ log_error("No area to draw in!");
+ return 0;
+ }
+
+ GdkVisual* wvisual = gdk_drawable_get_visual(_drawing_area->window);
+
+ GdkImage* tmpimage = gdk_image_new (GDK_IMAGE_FASTEST, wvisual, 1, 1);
+
+ const GdkVisual* visual = tmpimage->visual;
+
+ // FIXME: we use bpp instead of depth, because depth doesn't appear to
+ // include the padding byte(s) the GdkImage actually has.
+ const char *pixelformat = 0;
+ // agg_detect_pixel_format(visual->red_shift, visual->red_prec,
+ // visual->green_shift, visual->green_prec, visual->blue_shift,
visual->blue_prec,
+ // tmpimage->bpp * 8);
+
+ gdk_image_destroy(tmpimage);
+
+ _renderer = create_Renderer_ovg(pixelformat);
+ if (! _renderer) {
+ boost::format fmt = boost::format(
+ _("Could not create OPENVG renderer with pixelformat %s")
+ ) % pixelformat;
+ throw GnashException(fmt.str());
+ }
+
+ return _renderer;
+}
+
+void
+GtkEGLGlue::setRenderHandlerSize(int width, int height)
+{
+ GNASH_REPORT_FUNCTION;
+
+ assert(width > 0);
+ assert(height > 0);
+ assert(_renderer != NULL);
+
+#ifdef ENABLE_EGL_OFFSCREEN
+ if (_offscreenbuf && _offscreenbuf->width == width &&
+ _offscreenbuf->height == height) {
+ return;
+ }
+
+ if (_offscreenbuf) {
+ gdk_image_destroy(_offscreenbuf);
+ }
+
+ GdkVisual* visual = gdk_drawable_get_visual(_drawing_area->window);
+
+ _offscreenbuf = gdk_image_new (GDK_IMAGE_FASTEST, visual, width,
+ height);
+
+ static_cast<Renderer_ovg_base *>(_renderer)->init_buffer(
+ (unsigned char*) _offscreenbuf->mem,
+ _offscreenbuf->bpl * _offscreenbuf->height,
+ _offscreenbuf->width,
+ _offscreenbuf->height,
+ _offscreenbuf->bpl);
+#else
+ _renderer->init(width, height);
+#endif
+}
+
+void
+GtkEGLGlue::beforeRendering()
+{
+ GNASH_REPORT_FUNCTION;
+
+#ifdef ENABLE_EGL_OFFSCREEN
+ if (_offscreenbuf && _offscreenbuf->type == GDK_IMAGE_SHARED) {
+ gdk_flush();
+ }
+#endif
+}
+
+void
+GtkEGLGlue::render()
+{
+ GNASH_REPORT_FUNCTION;
+
+#if 0
+ // clear the color buffer
+ glClearColor(1.0, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glFlush();
+#endif
+
+#ifdef ENABLE_EGL_OFFSCREEN
+ if ( _drawbounds.size() == 0 ) {
+ return; // nothing to do
+ }
+
+ if (!_offscreenbuf) {
+ log_error("No off screen buffer!");
+ return;
+ }
+
+ render(0, 0, _offscreenbuf->width, _offscreenbuf->height);
+#else
+ render(0, 0, _width, _height);
+#endif
+}
+
+void
+GtkEGLGlue::render(int minx, int miny, int maxx, int maxy)
+{
+ GNASH_REPORT_FUNCTION;
+
+#ifdef ENABLE_EGL_OFFSCREEN
+ if (!_offscreenbuf) {
+ log_error("No off screen buffer!");
+ return;
+ }
+
+ const int& x = minx;
+ const int& y = miny;
+ size_t width = std::min(_offscreenbuf->width, maxx - minx);
+ size_t height = std::min(_offscreenbuf->height, maxy - miny);
+
+ GdkGC* gc = gdk_gc_new(_drawing_area->window);
+
+ gdk_draw_image(_drawing_area->window, gc, _offscreenbuf, x, y, x, y, width,
+ height);
+ gdk_gc_unref(gc);
+#else
+ eglSwapBuffers(_eglDisplay, _eglSurface);
+#endif
+}
+
+void
+GtkEGLGlue::configure(GtkWidget *const /*widget*/, GdkEventConfigure *const
event)
+{
+ GNASH_REPORT_FUNCTION;
+
+ if (_renderer) {
+ setRenderHandlerSize(event->width, event->height);
+ }
+}
+
+const char *
+GtkEGLGlue::getErrorString(int error)
+{
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_NOT_INITIALIZED:
+ return "EGL_NOT_INITIALIZED";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_CONTEXT_LOST:
+ return "EGL_CONTEXT_LOST";
+ default:
+ return "unknown error code";
+ }
+}
+
+bool
+GtkEGLGlue::checkEGLConfig(EGLConfig config)
+{
+ // GNASH_REPORT_FUNCTION;
+
+ // Use this to explicitly check that the EGL config has the expected color
depths
+ EGLint value;
+ if (_bpp == 32) {
+ eglGetConfigAttrib(_eglDisplay, config, EGL_RED_SIZE, &value);
+ if (8 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_GREEN_SIZE, &value);
+ if (8 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_BLUE_SIZE, &value);
+ if (8 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_ALPHA_SIZE, &value);
+ if (8 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_SAMPLES, &value);
+ if (0 != value) {
+ return false;
+ }
+ } else if (_bpp == 16) {
+ eglGetConfigAttrib(_eglDisplay, config, EGL_RED_SIZE, &value);
+ if ( 5 != value ) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_GREEN_SIZE, &value);
+ if (6 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_BLUE_SIZE, &value);
+ if (5 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_ALPHA_SIZE, &value);
+ if (0 != value) {
+ return false;
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_SAMPLES, &value);
+#ifdef RENDERER_GLES
+ if (4 != value) {
+ return false;
+ }
+#endif
+#ifdef RENDERER_OPENVG
+ if (0 != value) {
+ return false;
+ }
+#endif
+ } else {
+ return false;
+ }
+
+ return true;
+}
+
+/// Query the system for all supported configs
+int
+GtkEGLGlue::queryEGLConfig(EGLDisplay display)
+{
+ GNASH_REPORT_FUNCTION;
+ EGLConfig *configs = 0;
+ EGLint max_num_config = 0;
+
+ // Get the number of supported configurations
+ if ( EGL_FALSE == eglGetConfigs(display, 0, 0, &max_num_config) ) {
+ log_error("eglGetConfigs() failed to retrive the number of configs
(error %s)",
+ getErrorString(eglGetError()));
+ return 0;
+ }
+ if(max_num_config <= 0) {
+ printf( "No EGLconfigs found\n" );
+ return 0;
+ }
+ log_debug("Max number of EGL Configs is %d", max_num_config);
+
+ configs = new EGLConfig[max_num_config];
+ if (0 == configs) {
+ log_error( "Out of memory\n" );
+ return 0;
+ }
+
+ if ( EGL_FALSE == eglGetConfigs(display, configs, max_num_config,
&max_num_config)) {
+ log_error("eglGetConfigs() failed to retrive the configs (error %s)",
+ getErrorString(eglGetError()));
+ return 0;
+ }
+ for (int i=0; i<max_num_config; i++ ) {
+ log_debug("Config[%d] is:", i);
+ printEGLConfig(configs[i]);
+ }
+
+ return max_num_config;
+}
+
+void
+GtkEGLGlue::printEGLConfig(EGLConfig config)
+{
+ EGLint red, blue, green;
+ EGLint value;
+ eglGetConfigAttrib(_eglDisplay, config, EGL_RED_SIZE, &red);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_GREEN_SIZE, &green);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_BLUE_SIZE, &blue);
+ log_debug("\tConfig has RED = %d, GREEN = %d, BLUE = %d", red, green,
blue);
+
+ eglGetConfigAttrib(_eglDisplay, config, EGL_ALPHA_SIZE, &value);
+ log_debug("\tEGL_ALPHA_SIZE is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_STENCIL_SIZE, &value);
+ log_debug("\tEGL_STENCIL_SIZE is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_SAMPLES, &value);
+ log_debug("\tEGL_SAMPLES is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_DEPTH_SIZE, &value);
+ log_debug("\tEGL_DEPTH_SIZE is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_MAX_SWAP_INTERVAL, &value);
+ log_debug("\tEGL_MAX_SWAP_INTERVAL is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_MIN_SWAP_INTERVAL, &value);
+ log_debug("\tEGL_MIN_SWAP_INTERVAL is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_NATIVE_RENDERABLE, &value);
+ log_debug("\tEGL_NATIVE_RENDERABLE is %s", (value)? "true" : "false");
+ eglGetConfigAttrib(_eglDisplay, config, EGL_SAMPLE_BUFFERS, &value);
+ log_debug("\tEGL_SAMPLE_BUFFERS is %d", value);
+ eglGetConfigAttrib(_eglDisplay, config, EGL_RENDERABLE_TYPE, &value);
+ if (value > 0) {
+ std::string str;
+ if (value & EGL_OPENGL_ES_BIT) {
+ str += " OpenGL-ES 1.1";
+ }
+ if (value & EGL_OPENVG_BIT) {
+ str += " OpenVG";
+ }
+ if (value & EGL_OPENGL_BIT) {
+ str += " OpenGL";
+ }
+ log_debug("\tEGL_RENDERABLE_TYPE = %s", str);
+ } else {
+ log_debug("\tEGL_RENDERABLE_TYPE (default)");
+ }
+ eglGetConfigAttrib(_eglDisplay, config, EGL_SURFACE_TYPE, &value);
+ if (value > 0) {
+ std::string str;
+ if (value & EGL_WINDOW_BIT) {
+ str += " Window";
+ }
+ if (value & EGL_PIXMAP_BIT) {
+ str += " Pixmap";
+ }
+ if (value & EGL_PBUFFER_BIT) {
+ str += " Pbuffer";
+ }
+ log_debug("\tEGL_SURFACE_TYPE = %s", str);
+ } else {
+ log_debug("\tEGL_SURFACE_TYPE (default)");
+ }
+}
+
+void
+GtkEGLGlue::printEGLContext(EGLContext context)
+{
+ EGLint value;
+ eglQueryContext(_eglDisplay, context, EGL_CONFIG_ID, &value);
+ log_debug("Context EGL_CONFIG_ID is %d", value);
+ eglQueryContext(_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
+ log_debug("\tEGL_CONTEXT_CLIENT_TYPE is %d", (value == EGL_OPENVG_API)
+ ? "EGL_OPENVG_API" : "EGL_OPENGL_ES_API");
+ // eglQueryContext(_eglDisplay, context, EGL_CONTEXT_CLIENT_VERSION,
&value);
+ // log_debug("EGL_CONTEXT_CLIENT_VERSION is %d", value);
+ eglQueryContext(_eglDisplay, context, EGL_RENDER_BUFFER, &value);
+ log_debug("\tEGL_RENDER_BUFFER is %s", (value == EGL_BACK_BUFFER)
+ ? "EGL_BACK_BUFFER" : "EGL_SINGLE_BUFFER");
+}
+
+void
+GtkEGLGlue::printEGLSurface(EGLSurface surface)
+{
+ EGLint value;
+ eglQuerySurface(_eglDisplay, surface, EGL_CONFIG_ID, &value);
+ log_debug("Surface EGL_CONFIG_ID is %d", value);
+ eglQuerySurface(_eglDisplay, surface, EGL_HEIGHT, &value);
+ log_debug("\tEGL_HEIGHT is %d", value);
+ eglQuerySurface(_eglDisplay, surface, EGL_WIDTH, &value);
+ log_debug("\tEGL_WIDTH is %d", value);
+ eglQuerySurface(_eglDisplay, surface, EGL_RENDER_BUFFER, &value);
+ log_debug("\tEGL_RENDER_BUFFER is %s", (value == EGL_BACK_BUFFER)
+ ? "EGL_BACK_BUFFER" : "EGL_SINGLE_BUFFER");
+ eglQuerySurface(_eglDisplay, surface, EGL_VERTICAL_RESOLUTION, &value);
+ log_debug("\tEGL_VERTICAL_RESOLUTION is %d", value);
+ eglQuerySurface(_eglDisplay, surface, EGL_HORIZONTAL_RESOLUTION, &value);
+ log_debug("\tEGL_HORIZONTAL_RESOLUTION is %d", value);
+ eglQuerySurface(_eglDisplay, surface, EGL_SWAP_BEHAVIOR, &value);
+ log_debug("\tEGL_SWAP_BEHAVIOR is %d", (value == EGL_BUFFER_DESTROYED)
+ ? "EGL_BUFFER_DESTROYED" : "EGL_BUFFER_PRESERVED");
+ eglQuerySurface(_eglDisplay, surface, EGL_MULTISAMPLE_RESOLVE, &value);
+ log_debug("\tEGL_MULTISAMPLE_RESOLVE is %d", (value ==
EGL_MULTISAMPLE_RESOLVE_BOX)
+ ? "EGL_MULTISAMPLE_RESOLVE_BOX" :
"EGL_MULTISAMPLE_RESOLVE_DEFAULT");
+}
+
+} // namespace gnash
+
+// local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/gui/gtk/gtksup.h b/gui/gtk/gtksup.h
index 1f5a470..60c97ce 100644
--- a/gui/gtk/gtksup.h
+++ b/gui/gtk/gtksup.h
@@ -47,7 +47,6 @@ extern "C" {
namespace gnash
{
-
class GtkGui : public Gui
{
public:
@@ -187,3 +186,8 @@ private:
} // namespace gnash
#endif
+
+// Local Variables:
+// mode: C++
+// indent-tabs-mode: nil
+// End:
diff --git a/librender/Makefile.am b/librender/Makefile.am
index f6f0165..1c6ecd4 100644
--- a/librender/Makefile.am
+++ b/librender/Makefile.am
@@ -16,7 +16,6 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
-
## Process this file with automake to generate Makefile.in
AUTOMAKE_OPTIONS =
@@ -58,8 +57,10 @@ GNASH_LIBS = \
noinst_HEADERS = \
Renderer.h \
+ Renderer_ovg.h \
Renderer_agg.h \
Renderer_agg_bitmap.h \
+ Renderer_ovg_bitmap.h \
Renderer_agg_style.h \
Renderer_cairo.h \
Renderer_ogl.h \
@@ -79,6 +80,11 @@ libgnashrender_la_SOURCES += Renderer_agg.cpp
libgnashrender_la_LIBADD += $(AGG_LIBS) $(LIBVA)
endif
+if BUILD_OVG_RENDERER
+libgnashrender_la_SOURCES += Renderer_ovg.cpp
+libgnashrender_la_LIBADD += $(AGG_LIBS) $(LIBVA)
+endif
+
if BUILD_CAIRO_RENDERER
libgnashrender_la_SOURCES += Renderer_cairo.cpp
libgnashrender_la_LIBADD += $(CAIRO_LIBS)
@@ -92,7 +98,6 @@ mudflap:
clean-hook:
-rm -f core.*
-
if ENABLE_PCH
AM_CXXFLAGS = $(PCH_FLAGS)
endif
-----------------------------------------------------------------------
hooks/post-receive
--
Gnash
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Gnash-commit] [SCM] Gnash branch, openvg, created. 25d315301e008059e614f299bdd16bbb40d7ab73,
Rob Savoye <=