svn update: 49540 (latest:49550)
authorDaniel Juyung Seo <juyung.seo@samsung.com>
Mon, 7 Jun 2010 03:13:37 +0000 (12:13 +0900)
committerDaniel Juyung Seo <juyung.seo@samsung.com>
Mon, 7 Jun 2010 03:13:37 +0000 (12:13 +0900)
87 files changed:
AUTHORS
README.in
configure.ac
debian/SVN_REV
evas.spec.in
m4/evas_check_loader.m4
src/lib/Evas.h
src/lib/cache/evas_cache.h
src/lib/cache/evas_cache_image.c
src/lib/canvas/evas_main.c
src/lib/canvas/evas_object_gradient.c
src/lib/canvas/evas_object_gradient2.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_main.c
src/lib/canvas/evas_object_smart.c
src/lib/canvas/evas_object_text.c
src/lib/canvas/evas_object_textblock.c
src/lib/canvas/evas_render.c
src/lib/engines/common/Makefile.am
src/lib/engines/common/evas_convert_rgb_32.c
src/lib/engines/common/evas_font_draw.c
src/lib/engines/common/evas_font_load.c
src/lib/engines/common/evas_font_main.c
src/lib/engines/common/evas_font_private.h [new file with mode: 0644]
src/lib/engines/common/evas_font_query.c
src/lib/engines/common/evas_gradient2_main.c
src/lib/engines/common/evas_gradient_main.c
src/lib/engines/common/evas_image_load.c
src/lib/engines/common/evas_image_main.c
src/lib/engines/common/evas_image_scalecache.c
src/lib/engines/common/evas_intl_utils.c
src/lib/engines/common/evas_map_image_core.c
src/lib/engines/common/evas_map_image_internal.c
src/lib/engines/common/evas_map_image_loop.c
src/lib/engines/common/evas_op_blend/op_blend_mask_color_neon.c
src/lib/engines/common/evas_pipe.c
src/lib/engines/common/evas_pipe.h
src/lib/file/evas_module.c
src/lib/include/evas_common.h
src/lib/main.c
src/modules/engines/buffer/Evas_Engine_Buffer.h
src/modules/engines/buffer/evas_engine.c
src/modules/engines/cairo_x11/Evas_Engine_Cairo_X11.h
src/modules/engines/cairo_x11/evas_engine.c
src/modules/engines/direct3d/Evas_Engine_Direct3D.h
src/modules/engines/direct3d/evas_engine.c
src/modules/engines/directfb/Evas_Engine_DirectFB.h
src/modules/engines/fb/Evas_Engine_FB.h
src/modules/engines/fb/evas_engine.c
src/modules/engines/gl_common/evas_gl_common.h
src/modules/engines/gl_common/evas_gl_context.c
src/modules/engines/gl_common/evas_gl_image.c
src/modules/engines/gl_glew/Evas_Engine_GL_Glew.h
src/modules/engines/gl_glew/evas_engine.c
src/modules/engines/gl_x11/Evas_Engine_GL_X11.h
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/gl_x11/evas_engine.h
src/modules/engines/quartz/Evas_Engine_Quartz.h
src/modules/engines/quartz/evas_engine.c
src/modules/engines/software_16_ddraw/Evas_Engine_Software_16_DDraw.h
src/modules/engines/software_16_ddraw/evas_engine.c
src/modules/engines/software_16_sdl/Evas_Engine_SDL_16.h
src/modules/engines/software_16_wince/Evas_Engine_Software_16_WinCE.h
src/modules/engines/software_16_wince/evas_engine.c
src/modules/engines/software_16_x11/Evas_Engine_Software_16_X11.h
src/modules/engines/software_16_x11/evas_engine.c
src/modules/engines/software_ddraw/Evas_Engine_Software_DDraw.h
src/modules/engines/software_ddraw/evas_engine.c
src/modules/engines/software_gdi/Evas_Engine_Software_Gdi.h
src/modules/engines/software_generic/evas_engine.c
src/modules/engines/software_qtopia/Evas_Engine_Software_Qtopia.h
src/modules/engines/software_qtopia/evas_engine.c
src/modules/engines/software_sdl/Evas_Engine_SDL.h
src/modules/engines/software_x11/Evas_Engine_Software_X11.h
src/modules/engines/software_x11/evas_engine.c
src/modules/engines/software_x11/evas_engine.h
src/modules/engines/software_x11/evas_xlib_buffer.c
src/modules/engines/software_x11/evas_xlib_outbuf.c
src/modules/engines/software_x11/evas_xlib_outbuf.h
src/modules/engines/xrender_x11/Evas_Engine_XRender_X11.h
src/modules/engines/xrender_x11/evas_engine.c
src/modules/loaders/Makefile.am
src/modules/loaders/bmp/Makefile.am [new file with mode: 0644]
src/modules/loaders/bmp/evas_image_load_bmp.c [new file with mode: 0644]
src/modules/loaders/png/evas_image_load_png.c
src/modules/loaders/tga/Makefile.am [new file with mode: 0644]
src/modules/loaders/tga/evas_image_load_tga.c [new file with mode: 0644]

diff --git a/AUTHORS b/AUTHORS
index fce4857..d9c7f7b 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -18,3 +18,5 @@ Tom Hacohen <tom@stosb.com>
 Mathieu Taillefumier <mathieu.taillefumier@free.fr>
 Iván Briano <ivan@profusion.mobi>
 Gustavo Lima Chaves <glima@profusion.mobi>
+Saumsung Electronics <tbd>
+Samsung SAIT <tbd>
index b0897f9..1e3e6c9 100644 (file)
--- a/README.in
+++ b/README.in
@@ -275,3 +275,8 @@ NOTES:
 
 For the arm optimizations you want to try:
   export CFLAGS="-O2 -march=armv5te -mcpu=arm1136jf-s -fomit-frame-pointer"
+
+To enable the async renderer compile with:
+  --enable-async-render
+and also runtime set this environment variable:
+  export EVAS_RENDER_MODE=non-blocking
index e865dd8..ec0ab30 100644 (file)
@@ -1,5 +1,23 @@
-# get rid of that stupid cache mechanism
-rm -f config.cache
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_define([v_maj], [0])
+m4_define([v_min], [9])
+m4_define([v_mic], [9])
+m4_define([v_rev], m4_esyscmd([(svnversion . | grep -v exported || echo 0) | awk -F : '{printf("%s\n", $1);}' | tr -d ' :MSP\n']))
+m4_if(v_rev, [0], [m4_define([v_rev], m4_esyscmd([git log 2> /dev/null | (grep -m1 git-svn-id || echo 0) | sed -e 's/.*@\([0-9]*\).*/\1/' | tr -d '\n']))])
+##--   When released, remove the dnl on the below line
+dnl m4_undefine([v_rev])
+##--   When doing snapshots - change soname. remove dnl on below line
+m4_define([relname], [ver-pre-svn-06])
+m4_define([v_rel], [-release relname])
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_ifdef([v_rev], [m4_define([v_ver], [v_maj.v_min.v_mic.v_rev])],
+[m4_define([v_ver], [v_maj.v_min.v_mic])])
+m4_define([lt_rev], m4_eval(v_maj + v_min))
+m4_define([lt_cur], v_mic)
+m4_define([lt_age], v_min)
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 
 # rw_PROG_OBJC_WORKS
 # Check whether the Objective C compiler works.
@@ -14,8 +32,7 @@ AC_CACHE_CHECK([whether the Objective C compiler works],
                 AC_LANG_POP([Objective C])])
 ])
 
-AC_INIT([evas], [0.9.9.063], [enlightenment-devel@lists.sourceforge.net])
-release="ver-pre-svn-05"
+AC_INIT([evas], [v_ver], [enlightenment-devel@lists.sourceforge.net])
 AC_PREREQ([2.52])
 AC_CONFIG_SRCDIR([configure.ac])
 AC_CONFIG_MACRO_DIR([m4])
@@ -31,12 +48,20 @@ AC_LIBTOOL_WIN32_DLL
 define([AC_LIBTOOL_LANG_F77_CONFIG], [:])dnl
 AC_PROG_LIBTOOL
 
-VMAJ=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $1);}'`
-VMIN=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $2);}'`
-VMIC=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $3);}'`
-SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'`
-version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+m4_ifdef([v_rev], , [m4_define([v_rev], [0])])
+m4_ifdef([v_rel], , [m4_define([v_rel], [])])
+AC_DEFINE_UNQUOTED(VMAJ, [v_maj], [Major version])
+AC_DEFINE_UNQUOTED(VMIN, [v_min], [Minor version])
+AC_DEFINE_UNQUOTED(VMIC, [v_mic], [Micro version])
+AC_DEFINE_UNQUOTED(VREV, [v_rev], [Revison])
+version_info="lt_rev:lt_cur:lt_age"
+release_info="v_rel"
 AC_SUBST(version_info)
+AC_SUBST(release_info)
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
+##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##--##
 
 EFL_CHECK_PATH_MAX
 
@@ -47,11 +72,9 @@ case "$host_os" in
       MODULE_ARCH="$host_os-$host_cpu"
       ;;
    *)
-      release_info="-release $release"
-      MODULE_ARCH="$host_os-$host_cpu-$release"
+      MODULE_ARCH="$host_os-$host_cpu-relname"
       ;;
 esac
-AC_SUBST(release_info)
 AC_SUBST(MODULE_ARCH)
 AC_DEFINE_UNQUOTED(MODULE_ARCH, "$MODULE_ARCH", "Module architecture")
 
@@ -94,6 +117,8 @@ want_evas_image_loader_png="yes"
 want_evas_image_loader_svg="yes"
 want_evas_image_loader_tiff="yes"
 want_evas_image_loader_xpm="yes"
+want_evas_image_loader_bmp="yes"
+want_evas_image_loader_tga="yes"
 
 want_evas_font_loader_eet="yes"
 
@@ -669,6 +694,10 @@ EVAS_CHECK_IMAGE_LOADER([Tiff], [${want_evas_image_loader_tiff}])
 
 EVAS_CHECK_IMAGE_LOADER([XPM], [${want_evas_image_loader_xpm}])
 
+EVAS_CHECK_IMAGE_LOADER([BMP], [${want_evas_image_loader_bmp}])
+
+EVAS_CHECK_IMAGE_LOADER([TGA], [${want_evas_image_loader_tga}])
+
 
 #####################################################################
 ## Cpu based optimizations
@@ -761,6 +790,38 @@ else
 fi
 
 #######################################
+## Async Renderer
+build_async_render="no"
+AC_MSG_CHECKING(whether to build Asynchronously Threaded Pipe Rendering support)
+AC_ARG_ENABLE(async-render,
+  AC_HELP_STRING([--enable-async-render], [enable asynchronously threaded pipe rendering support]),
+  [ build_async_render=$enableval ]
+)
+AC_MSG_RESULT($build_async_render)
+
+AC_MSG_CHECKING(whether we can build Asynchronously Threaded Pipe Rendering support)
+if test \( "x$build_async_render" = "xyes" \); then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE(EVAS_FRAME_QUEUING, 1, [Build async render support])
+  build_async_render="yes"
+  AC_DEFINE(BUILD_PIPE_RENDER, 1, [Build pipe render support])
+  build_pipe_render="yes"
+  need_pthreads="yes"
+
+  PKG_CHECK_MODULES([XEXT],
+     [xext < 1.1.1],
+     [ build_avoid_libXext_bug=yes ],
+     [ build_avoid_libXext_bug=no ]
+  )
+  if test \( "x$build_avoid_libXext_bug" = "xyes" \); then
+    AC_DEFINE(LIBXEXT_VERSION_LOW, 1, [To avoid bug on old libXext version])
+  fi
+else
+  AC_MSG_RESULT(no)
+  build_async_render="no"
+fi
+
+#######################################
 ## Async events
 build_async_events="auto"
 AC_MSG_CHECKING(whether to build Async Events support)
@@ -1351,6 +1412,8 @@ src/modules/loaders/jpeg/Makefile
 src/modules/loaders/png/Makefile
 src/modules/loaders/tiff/Makefile
 src/modules/loaders/xpm/Makefile
+src/modules/loaders/bmp/Makefile
+src/modules/loaders/tga/Makefile
 src/modules/loaders/svg/Makefile
 src/modules/loaders/pmaps/Makefile
 src/modules/savers/Makefile
@@ -1428,6 +1491,7 @@ echo "  PNG.....................: $have_evas_image_loader_png"
 echo "  SVG.....................: $have_evas_image_loader_svg"
 echo "  TIFF....................: $have_evas_image_loader_tiff"
 echo "  XPM.....................: $have_evas_image_loader_xpm"
+echo "  BMP.....................: $have_evas_image_loader_bmp"
 # FIXME: need to add modular image loader system
 # FIXME: add more image loader modules
 echo
@@ -1453,6 +1517,7 @@ echo "  MAGIC_DEBUG.............: $want_evas_magic_debug"
 echo "  Cache Server............: $want_evas_cserve"
 echo
 echo "  Threaded Pipe Rendering.: $build_pipe_render"
+echo "  Async Pipe Rendering....: $build_async_render"
 echo "  Async Events............: $build_async_events"
 echo "  Async Image Preload.....: $build_async_preload"
 echo
index 6127e16..dd0e91d 100644 (file)
@@ -1,2 +1,2 @@
-Revision 48959
-Last Changed Rev 48959
+Revision 49550
+Last Changed Rev 49540
index 65fd1b9..9ef36ae 100644 (file)
@@ -43,6 +43,8 @@
 %bcond_without module_loader_eet
 %bcond_without module_saver_eet
 %bcond_without module_loader_xpm
+%bcond_without module_loader_bmp
+%bcond_without module_loader_tga
 
 # This just keeps a missing doxygen from killing the build.
 %define _missing_doc_files_terminate_build 0
@@ -57,6 +59,8 @@
 %define ac_with_module_loader_edb --%{?with_module_loader_edb:en}%{!?with_module_loader_edb:dis}able-image-loader-edb
 %define ac_with_module_loader_xpm --%{?with_module_loader_xpm:en}%{!?with_module_loader_xpm:dis}able-image-loader-xpm
 %define ac_with_module_loader_svg --%{?with_module_loader_svg:en}%{!?with_module_loader_svg:dis}able-image-loader-svg
+%define ac_with_module_loader_bmp --%{?with_module_loader_bmp:en}%{!?with_module_loader_bmp:dis}able-image-loader-bmp
+%define ac_with_module_loader_tga --%{?with_module_loader_tga:en}%{!?with_module_loader_tga:dis}able-image-loader-tga
 %define ac_with_module_saver_eet --%{?with_module_saver_eet:en}%{!?with_module_saver_eet:dis}able-image-saver-eet
 %define ac_with_module_saver_jpeg --%{?with_module_saver_jpeg:en}%{!?with_module_saver_jpeg:dis}able-image-saver-jpeg
 %define ac_with_module_saver_png --%{?with_module_saver_png:en}%{!?with_module_saver_png:dis}able-image-saver-png
@@ -234,6 +238,24 @@ BuildRequires: librsvg-devel >= 2.14
 svg Image loader module for Evas
 %endif
 
+%if %{with module_loader_bmp}
+%package module_loader_bmp
+Summary: BMP Image loader module for Evas
+Group: System Environment/Libraries
+BuildRequires: libjpeg-devel
+%description module_loader_bmp
+BMP Image loader module for Evas
+%endif
+
+%if %{with module_loader_tga}
+%package module_loader_tga
+Summary: TGA Image loader module for Evas
+Group: System Environment/Libraries
+BuildRequires: libjpeg-devel
+%description module_loader_tga
+TGA Image loader module for Evas
+%endif
+
 %package module_engine_software_generic
 Summary: Software X11 rendering engine module for Evas
 Group: System Environment/Libraries
@@ -518,6 +540,18 @@ test "x$RPM_BUILD_ROOT" != "x/" && rm -rf $RPM_BUILD_ROOT
 %{_libdir}/evas/modules/loaders/svg/*/module.so
 %endif
 
+%if %{with module_loader_bmp}
+%files module_loader_bmp
+%defattr(-, root, root)
+%{_libdir}/evas/modules/loaders/bmp/*/module.so
+%endif
+
+%if %{with module_loader_tga}
+%files module_loader_tga
+%defattr(-, root, root)
+%{_libdir}/evas/modules/loaders/tga/*/module.so
+%endif
+
 %if %{with module_engine_software_x11}
 %files module_engine_software_x11
 %defattr(-, root, root)
index 7b95465..cd64c9d 100644 (file)
@@ -307,6 +307,46 @@ fi
 
 ])
 
+dnl use: EVAS_CHECK_LOADER_DEP_BMP(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_LOADER_DEP_BMP],
+[
+
+have_dep="yes"
+evas_image_loader_[]$1[]_cflags=""
+evas_image_loader_[]$1[]_libs=""
+
+AC_SUBST([evas_image_loader_$1_cflags])
+AC_SUBST([evas_image_loader_$1_libs])
+
+if test "x${have_dep}" = "xyes" ; then
+  m4_default([$3], [:])
+else
+  m4_default([$4], [:])
+fi
+
+])
+
+dnl use: EVAS_CHECK_LOADER_DEP_TGA(loader, want_static[, ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
+
+AC_DEFUN([EVAS_CHECK_LOADER_DEP_TGA],
+[
+
+have_dep="yes"
+evas_image_loader_[]$1[]_cflags=""
+evas_image_loader_[]$1[]_libs=""
+
+AC_SUBST([evas_image_loader_$1_cflags])
+AC_SUBST([evas_image_loader_$1_libs])
+
+if test "x${have_dep}" = "xyes" ; then
+  m4_default([$3], [:])
+else
+  m4_default([$4], [:])
+fi
+
+])
+
 dnl use: EVAS_CHECK_IMAGE_LOADER(loader, want_loader, macro)
 
 
index 0590049..88acd82 100644 (file)
 # endif
 #endif /* ! _WIN32 */
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EVAS_VERSION_MAJOR 0
+#define EVAS_VERSION_MINOR 9
+
+   typedef struct _Evas_Version
+     {
+        int major;
+        int minor;
+        int micro;
+        int revision;
+     } Evas_Version;
+   
+   EAPI extern Evas_Version *evas_version;
 
 /**
  * @file
@@ -373,6 +389,12 @@ typedef enum _Evas_Image_Scale_Hint
    EVAS_IMAGE_SCALE_HINT_STATIC = 2
 } Evas_Image_Scale_Hint;
 
+typedef enum _Evas_Engine_Render_Mode
+{
+   EVAS_RENDER_MODE_BLOCKING = 0,
+   EVAS_RENDER_MODE_NONBLOCKING = 1,
+} Evas_Engine_Render_Mode;
+
 typedef enum _Evas_Image_Content_Hint
 {
    EVAS_IMAGE_CONTENT_HINT_NONE = 0,
@@ -596,10 +618,6 @@ typedef void      (*Evas_Event_Cb) (void *data, Evas *e, void *event_info);
 typedef Eina_Bool (*Evas_Object_Event_Post_Cb) (void *data, Evas *e);
 typedef void      (*Evas_Object_Event_Cb) (void *data, Evas *e, Evas_Object *obj, void *event_info);
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 /**
  * @defgroup Evas_Group Top Level Functions
  *
@@ -721,6 +739,7 @@ extern "C" {
    EAPI void              evas_pointer_canvas_xy_get        (const Evas *e, Evas_Coord *x, Evas_Coord *y) EINA_ARG_NONNULL(1);
    EAPI int               evas_pointer_button_down_mask_get (const Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
    EAPI Eina_Bool         evas_pointer_inside_get           (const Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
+   EAPI void              evas_sync(Evas *e) EINA_ARG_NONNULL(1);
 
 
 /**
index 462d35a..80aedcf 100644 (file)
@@ -60,6 +60,9 @@ struct _Evas_Cache_Image
    int                           usage;
    int                           limit;
    int                           references;
+#ifdef EVAS_FRAME_QUEUING
+   LK(lock);
+#endif
 };
 
 struct _Evas_Cache_Engine_Image_Func
index 68a1d60..3d3bd12 100644 (file)
@@ -58,7 +58,13 @@ _evas_cache_image_make_dirty(Evas_Cache_Image *cache,
    im->flags.dirty = 1;
    im->flags.activ = 0;
    im->flags.lru_nodata = 0;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
    cache->dirty = eina_inlist_prepend(cache->dirty, EINA_INLIST_GET(im));
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+#endif
 
    if (im->cache_key)
      {
@@ -80,7 +86,13 @@ _evas_cache_image_make_activ(Evas_Cache_Image *cache,
         im->flags.activ = 1;
         im->flags.lru_nodata = 0;
         im->flags.dirty = 0;
+#ifdef EVAS_FRAME_QUEUING
+        LKL(cache->lock);
+#endif
        eina_hash_direct_add(cache->activ, key, im);
+#ifdef EVAS_FRAME_QUEUING
+        LKU(cache->lock);
+#endif
      }
    else
      {
@@ -98,9 +110,15 @@ _evas_cache_image_make_inactiv(Evas_Cache_Image *cache,
        im->flags.activ = 0;
        im->flags.dirty = 0;
        im->flags.cached = 1;
+#ifdef EVAS_FRAME_QUEUING
+        LKL(cache->lock);
+#endif
        eina_hash_direct_add(cache->inactiv, key, im);
        cache->lru = eina_inlist_prepend(cache->lru, EINA_INLIST_GET(im));
        cache->usage += cache->func.mem_size_get(im);
+#ifdef EVAS_FRAME_QUEUING
+        LKU(cache->lock);
+#endif
      }
    else
      {
@@ -115,9 +133,15 @@ _evas_cache_image_remove_lru_nodata(Evas_Cache_Image *cache,
    if (im->flags.lru_nodata)
      {
         im->flags.lru_nodata = 0;
+#ifdef EVAS_FRAME_QUEUING
+        LKL(cache->lock);
+#endif
         cache->lru_nodata = eina_inlist_remove(cache->lru_nodata, EINA_INLIST_GET(im));
         cache->usage -= cache->func.mem_size_get(im);
-     }
+#ifdef EVAS_FRAME_QUEUING
+        LKU(cache->lock);
+#endif
+    }
 }
 
 static void
@@ -126,8 +150,14 @@ _evas_cache_image_activ_lru_nodata(Evas_Cache_Image *cache,
 {
    im->flags.need_data = 0;
    im->flags.lru_nodata = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
    cache->lru_nodata = eina_inlist_prepend(cache->lru_nodata, EINA_INLIST_GET(im));
    cache->usage += cache->func.mem_size_get(im);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+#endif
 }
 
 static void
@@ -138,11 +168,20 @@ _evas_cache_image_remove_activ(Evas_Cache_Image *cache,
      {
         if (ie->flags.activ)
           {
+#ifdef EVAS_FRAME_QUEUING
+             LKL(cache->lock);
+#endif
             eina_hash_del(cache->activ, ie->cache_key, ie);
+#ifdef EVAS_FRAME_QUEUING
+             LKU(cache->lock);
+#endif
              _evas_cache_image_remove_lru_nodata(cache, ie);
           }
         else
           {
+#ifdef EVAS_FRAME_QUEUING
+             LKL(cache->lock);
+#endif
              if (ie->flags.dirty)
                {
                  cache->dirty = eina_inlist_remove(cache->dirty, EINA_INLIST_GET(ie));
@@ -153,6 +192,9 @@ _evas_cache_image_remove_activ(Evas_Cache_Image *cache,
                   cache->lru = eina_inlist_remove(cache->lru, EINA_INLIST_GET(ie));
                   cache->usage -= cache->func.mem_size_get(ie);
                }
+#ifdef EVAS_FRAME_QUEUING
+             LKU(cache->lock);
+#endif
           }
         ie->flags.cached = 0;
         ie->flags.dirty = 0;
@@ -163,7 +205,8 @@ _evas_cache_image_remove_activ(Evas_Cache_Image *cache,
 static void
 _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
 {
-   if (!ie) return ;
+   if (!ie)
+       return ;
 
    if (cache->func.debug)
      cache->func.debug("deleting", ie);
@@ -201,6 +244,9 @@ _evas_cache_image_entry_delete(Evas_Cache_Image *cache, Image_Entry *ie)
 #ifdef BUILD_ASYNC_PRELOAD
    LKD(ie->lock);
 #endif
+#ifdef EVAS_FRAME_QUEUING
+   LKD(ie->lock_references);
+#endif
 
    cache->func.dealloc(ie);
 }
@@ -237,6 +283,9 @@ _evas_cache_image_entry_new(Evas_Cache_Image *cache,
    ie->allocated.w = 0;
    ie->allocated.h = 0;
 
+#ifdef EVAS_FRAME_QUEUING
+   LKI(ie->lock_references);
+#endif
    ie->references = 0;
    ie->cache = cache;
 
@@ -382,6 +431,7 @@ _evas_cache_image_async_end(void *data)
 static void
 _evas_cache_image_async_cancel(void *data)
 {
+   Evas_Cache_Image *cache = NULL;
    Image_Entry *ie = (Image_Entry *) data;
 
    ie->preload = NULL;
@@ -400,12 +450,19 @@ _evas_cache_image_async_cancel(void *data)
        _evas_cache_image_async_end(ie);
      }
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(ie->lock_references);
+#endif
    if (ie->references == 0)
      {
        _evas_cache_image_remove_activ(ie->cache, ie);
        _evas_cache_image_make_inactiv(ie->cache, ie, ie->cache_key);
-       evas_cache_image_flush(ie->cache);
+        cache = ie->cache;
      }
+#ifdef EVAS_FRAME_QUEUING
+   LKU(ie->lock_references);
+#endif
+   if (cache) evas_cache_image_flush(cache);
 }
 
 static int
@@ -500,9 +557,21 @@ EAPI void
 evas_cache_image_set(Evas_Cache_Image *cache, int limit)
 {
    assert(cache != NULL);
-   if (cache->limit == limit) return;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
+   if (cache->limit == limit)
+     {
+#ifdef EVAS_FRAME_QUEUING
+        LKU(cache->lock);
+#endif
+        return;
+     }
    cache->limit = limit;
    evas_cache_image_flush(cache);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+#endif
 }
 
 EAPI Evas_Cache_Image *
@@ -530,6 +599,10 @@ evas_cache_image_init(const Evas_Cache_Image_Func *cb)
    new->preload = NULL;
    new->pending = NULL;
 
+#ifdef EVAS_FRAME_QUEUING
+   LKI(new->lock);
+#endif
+
    return new;
 }
 
@@ -550,10 +623,18 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
    Image_Entry  *im;
 
    assert(cache != NULL);
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
    cache->references--;
 
    if (cache->references > 0)
-     return ;
+     {
+#ifdef EVAS_FRAME_QUEUING
+        LKU(cache->lock);
+#endif
+        return ;
+     }
 
 #ifdef BUILD_ASYNC_PRELOAD
    EINA_LIST_FREE(cache->preload, im)
@@ -610,6 +691,11 @@ evas_cache_image_shutdown(Evas_Cache_Image *cache)
    eina_hash_free(cache->activ);
    eina_hash_free(cache->inactiv);
 
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+   LKD(cache->lock);
+#endif
+
    free(cache);
 }
 
@@ -711,7 +797,13 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
 
    hkey[size] = '\0';
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
    im = eina_hash_find(cache->activ, hkey);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+#endif
    if (im)
      {
         time_t  t;
@@ -733,7 +825,13 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
        _evas_cache_image_make_dirty(cache, im);
      }
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(cache->lock);
+#endif
    im = eina_hash_find(cache->inactiv, hkey);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(cache->lock);
+#endif
    if (im)
      {
         int     ok;
@@ -779,9 +877,15 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
 
  on_ok:
    *error = EVAS_LOAD_ERROR_NONE;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    im->references++;
    if (im->references > 1 && im->flags.lru_nodata)
      _evas_cache_image_remove_lru_nodata(cache, im);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
 
    return im;
 
@@ -812,15 +916,37 @@ EAPI void
 evas_cache_image_drop(Image_Entry *im)
 {
    Evas_Cache_Image    *cache;
+   int                              references;
 
    assert(im);
    assert(im->cache);
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    im->references--;
+   references = im->references;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
+   
    cache = im->cache;
 
-   if (im->references == 0)
+   if (references == 0)
      {
+#ifdef EVAS_FRAME_QUEUING
+        LKL(((RGBA_Image *)im)->ref_fq_add);
+        LKL(((RGBA_Image *)im)->ref_fq_del);
+        if (((RGBA_Image *)im)->ref_fq[0] != ((RGBA_Image *)im)->ref_fq[1])
+          {
+             LKU(((RGBA_Image *)im)->ref_fq_add);
+             LKU(((RGBA_Image *)im)->ref_fq_del);
+             return;
+          }
+       LKU(((RGBA_Image *)im)->ref_fq_add);
+       LKU(((RGBA_Image *)im)->ref_fq_del);
+#endif
+
 #ifdef BUILD_ASYNC_PRELOAD
        if (im->preload)
          {
@@ -845,13 +971,22 @@ EAPI void
 evas_cache_image_data_not_needed(Image_Entry *im)
 {
    Evas_Cache_Image    *cache;
-
+   int   references;
+   
    assert(im);
    assert(im->cache);
 
    cache = im->cache;
 
-   if (im->references > 1) return ;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
+   references = im->references;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
+
+   if (references > 1) return ;
    if (im->flags.dirty || !im->flags.need_data) return ;
 
    _evas_cache_image_activ_lru_nodata(cache, im);
@@ -862,6 +997,7 @@ evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
 {
    Image_Entry          *im_dirty = im;
    Evas_Cache_Image     *cache;
+   int                           references;
 
    assert(im);
    assert(im->cache);
@@ -869,9 +1005,17 @@ evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
    cache = im->cache;
    if (!(im->flags.dirty))
      {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
+   references = im->references;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
+
 #ifndef EVAS_CSERVE
 // if ref 1 also copy if using shared cache as its read-only
-        if (im->references == 1) im_dirty = im;
+        if (references == 1) im_dirty = im;
         else
 #endif
           {
@@ -900,7 +1044,13 @@ evas_cache_image_dirty(Image_Entry *im, int x, int y, int w, int h)
 
              if (error != 0) goto on_error;
  */
+#ifdef EVAS_FRAME_QUEUING
+             LKL(im_dirty->lock_references);
+#endif
              im_dirty->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+             LKU(im_dirty->lock_references);
+#endif
 
              evas_cache_image_drop(im);
           }
@@ -927,12 +1077,21 @@ evas_cache_image_alone(Image_Entry *im)
 {
    Evas_Cache_Image     *cache;
    Image_Entry          *im_dirty = im;
+   int                           references;
 
    assert(im);
    assert(im->cache);
 
    cache = im->cache;
-   if (im->references == 1)
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
+   references = im->references;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
+
+   if (references == 1)
      {
         if (!(im->flags.dirty))
           {
@@ -967,7 +1126,13 @@ evas_cache_image_alone(Image_Entry *im)
 
         if (error != 0) goto on_error;
  */
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im_dirty->lock_references);
+#endif
         im_dirty->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im_dirty->lock_references);
+#endif
 
         evas_cache_image_drop(im);
      }
@@ -1004,7 +1169,13 @@ evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *imag
         _evas_cache_image_entry_delete(cache, im);
         return NULL;
      }
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    im->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
 
    if (cache->func.debug)
      cache->func.debug("copied-data", im);
@@ -1032,7 +1203,13 @@ evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data,
         _evas_cache_image_entry_delete(cache, im);
         return NULL;
      }
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    im->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
 
    if (cache->func.debug)
      cache->func.debug("data", im);
@@ -1068,7 +1245,13 @@ evas_cache_image_size_set(Image_Entry *im, int w, int h)
 
    assert(im);
    assert(im->cache);
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    assert(im->references > 0);
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
 
    if ((im->space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
        (im->space == EVAS_COLORSPACE_YCBCR422P709_PL))
@@ -1091,7 +1274,13 @@ evas_cache_image_size_set(Image_Entry *im, int w, int h)
    error = cache->func.size_set(new, im, w, h);
    if (error != 0) goto on_error;
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(new->lock_references);
+#endif
    new->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(new->lock_references);
+#endif
 
    evas_cache_image_drop(im);
 
@@ -1157,7 +1346,10 @@ evas_cache_image_load_data(Image_Entry *im)
    LKL(im->lock);
 #endif
 
+   im->flags.in_progress = EINA_TRUE;
    error = cache->func.load(im);
+   im->flags.in_progress = EINA_FALSE;
+
 #ifdef BUILD_ASYNC_PRELOAD
    LKU(im->lock);
 #endif
@@ -1188,10 +1380,14 @@ evas_cache_image_unload_data(Image_Entry *im)
    assert(im->cache);
    cache = im->cache;
 
+   if (im->flags.in_progress) return ;
+
+   evas_cache_image_preload_cancel(im, NULL);
+
 #ifdef BUILD_ASYNC_PRELOAD
    LKL(im->lock);
 #endif
-   if ((!im->flags.loaded) || (!im->file) || 
+   if ((!im->flags.loaded) || (!im->file) ||
        (!im->info.module) || (im->flags.dirty))
      {
 #ifdef BUILD_ASYNC_PRELOAD
@@ -1201,7 +1397,7 @@ evas_cache_image_unload_data(Image_Entry *im)
      }
    evas_common_rgba_image_scalecache_dirty(im);
    cache->func.destructor(im);
-   
+
 #ifdef BUILD_ASYNC_PRELOAD
    LKU(im->lock);
 #endif
@@ -1314,7 +1510,13 @@ evas_cache_image_empty(Evas_Cache_Image *cache)
    im = _evas_cache_image_entry_new(cache, NULL, 0, NULL, NULL, NULL, NULL);
    if (!im) return NULL;
 
+#ifdef EVAS_FRAME_QUEUING
+   LKL(im->lock_references);
+#endif
    im->references = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKU(im->lock_references);
+#endif
    return im;
 }
 
index c60cb21..5c7e606 100644 (file)
@@ -48,6 +48,9 @@ evas_init(void)
 #ifdef BUILD_ASYNC_PRELOAD
    _evas_preload_thread_init();
 #endif
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_init();
+#endif
 
    return _evas_init_count;
 
@@ -84,6 +87,13 @@ evas_shutdown(void)
    if (--_evas_init_count != 0)
      return _evas_init_count;
 
+#ifdef EVAS_FRAME_QUEUING
+   if (evas_common_frameq_enabled())
+     {
+        evas_common_frameq_finish();
+        evas_common_frameq_destroy();
+     }
+#endif
 #ifdef BUILD_ASYNC_EVENTS
    _evas_preload_thread_shutdown();
 #endif
@@ -180,6 +190,10 @@ evas_free(Evas *e)
    return;
    MAGIC_CHECK_END();
 
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_flush();
+#endif
+
    if (e->walking_list == 0) evas_render_idle_flush(e);
    
    if (e->walking_list > 0) return;
@@ -424,6 +438,11 @@ evas_output_size_set(Evas *e, int w, int h)
    if ((w == e->output.w) && (h == e->output.h)) return;
    if (w < 1) w = 1;
    if (h < 1) h = 1;
+
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_flush();
+#endif
+
    e->output.w = w;
    e->output.h = h;
    e->output.changed = 1;
index 54b50c9..73dbc9f 100644 (file)
@@ -147,9 +147,15 @@ evas_object_gradient_color_stop_add(Evas_Object *obj, int r, int g, int b, int a
    return;
    MAGIC_CHECK_END();
    if (o->engine_data)
-      obj->layer->evas->engine.func->gradient_color_stop_add(obj->layer->evas->engine.data.output,
-                                                            o->engine_data,
-                                                            r, g, b, a, delta);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad_flush(o->engine_data);
+#endif
+
+        obj->layer->evas->engine.func->gradient_color_stop_add(obj->layer->evas->engine.data.output,
+                           o->engine_data,
+                           r, g, b, a, delta);
+     }
    o->gradient_changed = 1;
    o->changed = 1;
    evas_object_change(obj);
@@ -180,8 +186,13 @@ evas_object_gradient_alpha_stop_add(Evas_Object *obj, int a, int delta)
    return;
    MAGIC_CHECK_END();
    if (o->engine_data)
-      obj->layer->evas->engine.func->gradient_alpha_stop_add(obj->layer->evas->engine.data.output,
-                                                            o->engine_data, a, delta);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad_flush(o->engine_data);
+#endif
+        obj->layer->evas->engine.func->gradient_alpha_stop_add(obj->layer->evas->engine.data.output,
+                     o->engine_data, a, delta);
+     }
    o->gradient_changed = 1;
    o->changed = 1;
    evas_object_change(obj);
@@ -204,8 +215,13 @@ evas_object_gradient_clear(Evas_Object *obj)
    return;
    MAGIC_CHECK_END();
    if (o->engine_data)
-      obj->layer->evas->engine.func->gradient_clear(obj->layer->evas->engine.data.output,
-                                                   o->engine_data);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad_flush(o->engine_data);
+#endif
+        obj->layer->evas->engine.func->gradient_clear(obj->layer->evas->engine.data.output,
+                        o->engine_data);
+     }
    o->gradient_changed = 1;
    o->changed = 1;
    o->cur.gradient_opaque = 0;
@@ -236,9 +252,14 @@ evas_object_gradient_color_data_set(Evas_Object *obj, void *data, int len, Eina_
    return;
    MAGIC_CHECK_END();
    if (o->engine_data)
-       obj->layer->evas->engine.func->gradient_color_data_set(obj->layer->evas->engine.data.output,
-                                                               o->engine_data,
-                                                               data, len, has_alpha);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad_flush(o->engine_data);
+#endif
+        obj->layer->evas->engine.func->gradient_color_data_set(obj->layer->evas->engine.data.output,
+                        o->engine_data,
+                        data, len, has_alpha);
+     }
    o->gradient_changed = 1;
    o->changed = 1;
    evas_object_change(obj);
@@ -267,9 +288,14 @@ evas_object_gradient_alpha_data_set(Evas_Object *obj, void *data, int len)
    return;
    MAGIC_CHECK_END();
    if (o->engine_data)
-       obj->layer->evas->engine.func->gradient_alpha_data_set(obj->layer->evas->engine.data.output,
-                                                               o->engine_data,
-                                                               data, len);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad_flush(o->engine_data);
+#endif
+        obj->layer->evas->engine.func->gradient_alpha_data_set(obj->layer->evas->engine.data.output,
+                        o->engine_data,
+                        data, len);
+     }
    o->gradient_changed = 1;
    o->changed = 1;
    evas_object_change(obj);
index ab003ce..6511aa5 100644 (file)
@@ -53,9 +53,15 @@ evas_object_gradient2_color_np_stop_insert(Evas_Object *obj, int r, int g, int b
    MAGIC_CHECK_END();
    engine_data = obj->func->engine_data_get(obj);
    if (engine_data)
-      obj->layer->evas->engine.func->gradient2_color_np_stop_insert(obj->layer->evas->engine.data.output,
-                                                            engine_data,
-                                                            r, g, b, a, pos);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad2_flush(engine_data);
+#endif
+
+        obj->layer->evas->engine.func->gradient2_color_np_stop_insert(obj->layer->evas->engine.data.output,
+                           engine_data,
+                           r, g, b, a, pos);
+     }
    og->gradient_changed = 1;
    evas_object_change(obj);
 }
@@ -79,8 +85,13 @@ evas_object_gradient2_clear(Evas_Object *obj)
    MAGIC_CHECK_END();
    engine_data = obj->func->engine_data_get(obj);
    if (engine_data)
-      obj->layer->evas->engine.func->gradient2_clear(obj->layer->evas->engine.data.output,
-                                                    engine_data);
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_grad2_flush(engine_data);
+#endif
+        obj->layer->evas->engine.func->gradient2_clear(obj->layer->evas->engine.data.output,
+                        engine_data);
+     }
    og->gradient_changed = 1;
    og->cur.gradient_opaque = 0;
    evas_object_change(obj);
index 233c5d8..0c52aeb 100644 (file)
@@ -960,6 +960,10 @@ evas_object_image_data_set(Evas_Object *obj, void *data)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+#ifdef EVAS_FRAME_QUEUING
+   if (o->engine_data)
+     evas_common_pipe_op_image_flush(o->engine_data);
+#endif
    p_data = o->engine_data;
    if (data)
      {
@@ -1031,6 +1035,10 @@ evas_object_image_data_get(const Evas_Object *obj, Eina_Bool for_writing)
    return NULL;
    MAGIC_CHECK_END();
    if (!o->engine_data) return NULL;
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_pipe_op_image_flush(o->engine_data);
+#endif
+
    data = NULL;
    o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
                                                                  o->engine_data,
@@ -1202,9 +1210,14 @@ evas_object_image_alpha_set(Evas_Object *obj, Eina_Bool has_alpha)
      return;
    o->cur.has_alpha = has_alpha;
    if (o->engine_data)
-     o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
+     {
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_pipe_op_image_flush(o->engine_data);
+#endif
+        o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
                                                                     o->engine_data,
                                                                     o->cur.has_alpha);
+     }
    evas_object_image_data_update_add(obj, 0, 0, o->cur.image.w, o->cur.image.h);
    EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
 }
@@ -1810,6 +1823,15 @@ evas_object_image_colorspace_set(Evas_Object *obj, Evas_Colorspace cspace)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+
+#ifdef EVAS_FRAME_QUEUING
+   if (o->cur.cspace != cspace)
+     {
+        if (o->engine_data)
+          evas_common_pipe_op_image_flush(o->engine_data);
+     }
+#endif
+
    o->cur.cspace = cspace;
    if (o->engine_data)
      obj->layer->evas->engine.func->image_colorspace_set(obj->layer->evas->engine.data.output,
@@ -1913,6 +1935,13 @@ evas_object_image_scale_hint_set(Evas_Object *obj, Evas_Image_Scale_Hint hint)
    MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
    return;
    MAGIC_CHECK_END();
+#ifdef EVAS_FRAME_QUEUING
+   if (o->scale_hint != hint)
+     {
+        if (o->engine_data)
+          evas_common_pipe_op_image_flush(o->engine_data);
+     }
+#endif
    o->scale_hint = hint;
 }
 
index 8173d4a..1cbb9aa 100644 (file)
@@ -368,6 +368,10 @@ evas_object_del(Evas_Object *obj)
 
    if (obj->delete_me) return;
 
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_flush();
+#endif
+
    _evas_object_event_new();
 
    evas_object_event_callback_call(obj, EVAS_CALLBACK_DEL, NULL);
index f695394..cfeddd9 100644 (file)
@@ -918,6 +918,7 @@ evas_object_smart_cleanup(Evas_Object *obj)
             free(cb);
          }
 
+       evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
        o->data = NULL;
      }
 
index 575b449..1b89f7e 100644 (file)
@@ -195,6 +195,12 @@ evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size siz
                                              obj->layer->evas->pointer.x,
                                              obj->layer->evas->pointer.y, 1, 1);
      }
+
+#ifdef EVAS_FRAME_QUEUING
+   if (o->engine_data)
+      evas_common_pipe_op_text_flush(o->engine_data);
+#endif
+
    /* DO IT */
    if (o->engine_data)
      {
@@ -1102,6 +1108,7 @@ evas_font_hinting_set(Evas *e, Evas_Font_Hinting_Flags hinting)
    MAGIC_CHECK_END();
    if (e->hinting == hinting) return;
    e->hinting = hinting;
+
    EINA_INLIST_FOREACH(e->layers, lay)
      {
        Evas_Object *obj;
@@ -1834,6 +1841,9 @@ _evas_object_text_rehint(Evas_Object *obj)
 
    o = (Evas_Object_Text *)(obj->object_data);
    if (!o->engine_data) return;
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_pipe_op_text_flush(o->engine_data);
+#endif
    evas_font_load_hinting_set(obj->layer->evas, o->engine_data,
                              obj->layer->evas->hinting);
    was = evas_object_is_in_output_rect(obj,
index 50f5295..4082bb6 100644 (file)
@@ -478,8 +478,8 @@ static const char escape_strings[] =
        "&Eacute;\0"   "\xc3\x89\0"
        "&Ecirc;\0"    "\xc3\x8a\0"
        "&Euml;\0"     "\xc3\x8b\0"
-       "&Egrave;\0"   "\xc3\x8c\0"
-       "&Eacute;\0"   "\xc3\x8d\0"
+       "&Igrave;\0"   "\xc3\x8c\0"
+       "&Iacute;\0"   "\xc3\x8d\0"
        "&Icirc;\0"    "\xc3\x8e\0"
        "&Iuml;\0"     "\xc3\x8f\0"
        "&Eth;\0"      "\xc3\x90\0"
@@ -6027,9 +6027,14 @@ _evas_object_textblock_rehint(Evas_Object *obj)
        EINA_INLIST_FOREACH(ln->items, it)
          {
             if (it->format->font.font)
-              evas_font_load_hinting_set(obj->layer->evas,
-                                         it->format->font.font,
+            {  
+#ifdef EVAS_FRAME_QUEUING
+               evas_common_pipe_op_text_flush(it->format->font.font);
+#endif
+                 evas_font_load_hinting_set(obj->layer->evas,
+                                         it->format->font.font,
                                          obj->layer->evas->hinting);
+              }
          }
      }
    o->formatted.valid = 0;
index e871e9e..a30f32c 100644 (file)
@@ -245,8 +245,13 @@ _evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
    obj->rect_del = 0;
    obj->render_pre = 0;
 
+#ifndef EVAS_FRAME_QUEUING
    /* because of clip objects - delete 2 cycles later */
-   if (obj->delete_me == 2) eina_array_push(delete_objects, obj);
+   if (obj->delete_me == 2)
+#else
+   if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
+#endif
+        eina_array_push(delete_objects, obj);
    else if (obj->delete_me != 0) obj->delete_me++;
    /* If the object will be removed, we should not cache anything during this run. */
    if (obj->delete_me != 0) clean_them = EINA_TRUE;
@@ -1236,6 +1241,10 @@ evas_render_updates(Evas *e)
    return NULL;
    MAGIC_CHECK_END();
 
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_flush_ready ();
+#endif
+
    if (!e->changed) return NULL;
    return evas_render_updates_internal(e, 1, 1);
 }
@@ -1254,6 +1263,10 @@ evas_render(Evas *e)
    return;
    MAGIC_CHECK_END();
 
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_frameq_flush_ready ();
+#endif
+
    if (!e->changed) return;
    evas_render_updates_internal(e, 0, 1);
 }
@@ -1316,6 +1329,18 @@ evas_render_idle_flush(Evas *e)
    e->invalidate = 1;
 }
 
+EAPI void
+evas_sync(Evas *e)
+{
+#ifdef EVAS_FRAME_QUEUING
+   MAGIC_CHECK(e, Evas, MAGIC_EVAS);
+   return;
+   MAGIC_CHECK_END();
+
+   evas_common_frameq_flush ();
+#endif
+}
+
 /**
  * Make the canvas discard as much data as possible used by the engine at
  * runtime.
@@ -1393,12 +1418,19 @@ evas_render_object_recalc(Evas_Object *obj)
    return;
    MAGIC_CHECK_END();
 
+#ifndef EVAS_FRAME_QUEUING
    if ((!obj->changed) && (obj->delete_me < 2))
+#else
+   if ((!obj->changed) )
+#endif
      {
        Evas *e;
 
        e = obj->layer->evas;
        if ((!e) || (e->cleanup)) return;
+#ifdef EVAS_FRAME_QUEUING
+   if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
+#endif
         eina_array_push(&e->pending_objects, obj);
        obj->changed = 1;
      }
index f8669ae..b0d0d35 100644 (file)
@@ -90,6 +90,7 @@ evas_convert_rgb_8.h \
 evas_convert_yuv.h \
 evas_draw.h \
 evas_font.h \
+evas_font_private.h \
 evas_gradient.h \
 evas_gradient_private.h \
 evas_image.h \
index 05ad414..dd5d450 100644 (file)
@@ -78,17 +78,60 @@ evas_common_convert_rgba_to_32bpp_rgb_8888_rot_270 (DATA32 *src, DATA8 *dst, int
 void
 evas_common_convert_rgba_to_32bpp_rgb_8888_rot_90 (DATA32 *src, DATA8 *dst, int src_jump, int dst_jump, int w, int h, int dith_x __UNUSED__, int dith_y __UNUSED__, DATA8 *pal __UNUSED__)
 {
+#ifndef BUILD_NEON
    DATA32 *src_ptr;
    DATA32 *dst_ptr;
    int x, y;
 
    dst_ptr = (DATA32 *)dst;
-
    CONVERT_LOOP_START_ROT_90();
 
    *dst_ptr = *src_ptr;
 
    CONVERT_LOOP_END_ROT_90();
+#else
+#define AP     "convert_rgba32_rot_90_"
+   asm volatile (
+       AP"outer:                                               \n\t"
+               // Set up src
+       "       sub             %[s1],          %[src], %[y],lsl #2     \n\t"
+       "       sub             %[s2],          %[src2], %[y],lsl #2    \n\t"
+       "       add             %[y],   #2                      \n\t"
+       "       add             %[x],   %[d1], %[w], lsl #2             \n\t"
+       AP"inner:                                               \n\t"
+       "       vldm            %[s1], {d0}                     \n\t"
+       "       vldm            %[s2], {d1}                     \n\t"
+       "       vtrn.u32        d1,d0                           \n\t"
+       "       vstm            %[d1]!, {d0}                    \n\t"
+       "       vstm            %[d2]!, {d1}                    \n\t"
+       "       add             %[s1],          %[sadv]         \n\t"
+       "       add             %[s2],          %[sadv]         \n\t"
+       "       cmp             %[x],           %[d1]           \n\t"
+       "       bhi             "AP"inner                       \n\t"
+
+       "       add             %[d1], %[djump]                 \n\t"
+       "       add             %[d2], %[djump]                 \n\t"
+       "       cmp             %[y],   %[h]                    \n\t"
+       "       blt             "AP"outer                       \n\t"
+
+
+       : // Out
+       :       [s1] "r" (src),
+               [s2] "r" (src + (h + src_jump) * 4),
+               [d1] "r" (dst),
+               [d2] "r" ((DATA32*)dst + w + dst_jump),
+               [sadv] "r" ((h + 2 * src_jump) * 8),
+               [src] "r" ((DATA32*)src + (h - 1)- 1),
+               [src2] "r" ((DATA32*)src + (h - 1)- 2),
+               [djump] "r" ((w + 2 * dst_jump) * 4),
+               [x] "r" (7),
+               [y] "r" (0),
+               [w] "r" (w),
+               [h] "r" (h)
+       : "q0", "q1", "memory", "cc"// Clober
+   );
+#undef AP
+#endif
    return;
 }
 #endif
index 87372de..d629718 100644 (file)
@@ -7,7 +7,23 @@
 #include "evas_blend_private.h"
 
 #include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
+#include "evas_font_private.h" /* for Frame-Queuing support */
 
+#ifdef EVAS_FRAME_QUEUING
+EAPI void
+evas_common_font_draw_init(void)
+{
+   LKI(lock_font_draw);
+   LKI(lock_fribidi);
+}
+
+EAPI void
+evas_common_font_draw_finish(void)
+{
+   LKD(lock_font_draw);
+   LKD(lock_fribidi);
+}
+#endif
 
 static void
 _fash_int_free(Fash_Int *fash)
@@ -123,9 +139,11 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
 //   fg = eina_hash_find(fi->glyphs, &hindex);
 //   if (fg) return fg;
 
+   FTLOCK();
 //   error = FT_Load_Glyph(fi->src->ft.face, index, FT_LOAD_NO_BITMAP);
    error = FT_Load_Glyph(fi->src->ft.face, index,
                         FT_LOAD_RENDER | hintflags[fi->hinting]);
+   FTUNLOCK();
    if (error)
      {
         if (!fi->fash) fi->fash = _fash_gl_new();
@@ -137,7 +155,9 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
    if (!fg) return NULL;
    memset(fg, 0, (sizeof(struct _RGBA_Font_Glyph)));
 
+   FTLOCK();
    error = FT_Get_Glyph(fi->src->ft.face->glyph, &(fg->glyph));
+   FTUNLOCK();
    if (error)
      {
        free(fg);
@@ -147,15 +167,18 @@ evas_common_font_int_cache_glyph_get(RGBA_Font_Int *fi, FT_UInt index)
      }
    if (fg->glyph->format != FT_GLYPH_FORMAT_BITMAP)
      {
+        FTLOCK();
        error = FT_Glyph_To_Bitmap(&(fg->glyph), FT_RENDER_MODE_NORMAL, 0, 1);
        if (error)
          {
             FT_Done_Glyph(fg->glyph);
+        FTUNLOCK();
             free(fg);
              if (!fi->fash) fi->fash = _fash_gl_new();
              if (fi->fash) _fash_gl_add(fi->fash, index, (void *)(-1));
             return NULL;
          }
+   FTUNLOCK();
      }
    fg->glyph_out = (FT_BitmapGlyph)fg->glyph;
    fg->index = hindex;
@@ -180,6 +203,7 @@ static FT_UInt
 _evas_common_get_char_index(RGBA_Font_Int* fi, int gl)
 {
    Font_Char_Index result;
+   FT_UInt ret;
 
 #ifdef HAVE_PTHREAD
 ///   pthread_mutex_lock(&fi->ft_mutex);
@@ -197,7 +221,9 @@ _evas_common_get_char_index(RGBA_Font_Int* fi, int gl)
 //     return FT_Get_Char_Index(fi->src->ft.face, gl);
 //     }
 
+   FTLOCK();
    result.index = FT_Get_Char_Index(fi->src->ft.face, gl);
+   FTUNLOCK();
    result.gl = gl;
 
 //   eina_hash_direct_add(fi->indexes, &result->gl, result);
@@ -583,7 +609,9 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
    if (ext_w <= 0) return;
    if (ext_h <= 0) return;
 
+#ifndef EVAS_FRAME_QUEUING
    LKL(fn->lock);
+#endif
 //   evas_common_font_size_use(fn);
    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
    func = evas_common_gfx_func_composite_mask_color_span_get(dc->col.col, dst, 1, dc->render_op);
@@ -616,5 +644,7 @@ evas_common_font_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int
           }
         dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
      }
+#ifndef EVAS_FRAME_QUEUING
    LKU(fn->lock);
+#endif
 }
index d754cf0..a6b07e1 100644 (file)
@@ -7,6 +7,8 @@
 
 #include <assert.h>
 
+#include "evas_font_private.h" /* for Frame-Queuing support */
+
 extern FT_Library         evas_ft_lib;
 
 static int                font_cache_usage = 0;
@@ -45,7 +47,9 @@ _evas_font_cache_int_hash(const RGBA_Font_Int *key, int key_length __UNUSED__)
 static void
 _evas_common_font_source_free(RGBA_Font_Source *fs)
 {
+   FTLOCK();
    FT_Done_Face(fs->ft.face);
+   FTUNLOCK();
 #if 0 /* FIXME: Disable as it is only used by dead code using deprecated datatype. */
 //   if (fs->charmap) evas_array_hash_free(fs->charmap);
 #endif
@@ -59,7 +63,9 @@ font_flush_free_glyph_cb(const Eina_Hash *hash, const void *key, void *data, voi
    RGBA_Font_Glyph *fg;
 
    fg = data;
+   FTLOCK();
    FT_Done_Glyph(fg->glyph);
+   FTUNLOCK();
    // extension calls
    if (fg->ext_dat_free) fg->ext_dat_free(fg->ext_dat);
    free(fg);
@@ -137,7 +143,9 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data
    fs->data_size = data_size;
    fs->current_size = 0;
    memcpy(fs->data, data, data_size);
+   FTLOCK();
    error = FT_New_Memory_Face(evas_ft_lib, fs->data, fs->data_size, 0, &(fs->ft.face));
+   FTUNLOCK();
    if (error)
      {
        free(fs);
@@ -145,7 +153,9 @@ evas_common_font_source_memory_load(const char *name, const void *data, int data
      }
    fs->name = eina_stringshare_add(name);
    fs->file = NULL;
+   FTLOCK();
    error = FT_Select_Charmap(fs->ft.face, ft_encoding_unicode);
+   FTUNLOCK();
    fs->ft.orig_upem = fs->ft.face->units_per_EM;
    fs->references = 1;
 
@@ -183,9 +193,11 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs)
 {
    int error;
 
+   FTLOCK();
    error = FT_New_Face(evas_ft_lib, fs->file, 0, &(fs->ft.face));
    if (error)
      {
+        FTUNLOCK();
        fs->ft.face = NULL;
        return error;
      }
@@ -194,10 +206,12 @@ evas_common_font_source_load_complete(RGBA_Font_Source *fs)
    if (error)
      {
        FT_Done_Face(fs->ft.face);
+   FTUNLOCK();
        fs->ft.face = NULL;
        return error;
      }
 
+   FTUNLOCK();
    fs->ft.orig_upem = fs->ft.face->units_per_EM;
    return error;
 }
@@ -236,7 +250,9 @@ evas_common_font_size_use(RGBA_Font *fn)
      {
        if (fi->src->current_size != fi->size)
          {
+        FTLOCK();
             FT_Activate_Size(fi->ft.size);
+        FTUNLOCK();
             fi->src->current_size = fi->size;
          }
      }
@@ -369,6 +385,7 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
    int ret;
    int error;
 
+   FTLOCK();
    error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
    if (!error)
      {
@@ -381,6 +398,7 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
        fi->real_size = fi->size;
        error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
      }
+   FTUNLOCK();
    if (error)
      {
        int i;
@@ -405,7 +423,9 @@ evas_common_font_int_load_complete(RGBA_Font_Int *fi)
             if (d == 0) break;
          }
        fi->real_size = chosen_size;
+   FTLOCK();
        error = FT_Set_Pixel_Sizes(fi->src->ft.face, chosen_width, fi->real_size);
+   FTUNLOCK();
        if (error)
          {
             /* couldn't choose the size anyway... what now? */
@@ -457,6 +477,11 @@ evas_common_font_memory_load(const char *name, int size, const void *data, int d
    fi->hinting = fn->hinting;
    fn->references = 1;
    LKI(fn->lock);
+#ifdef EVAS_FRAME_QUEUING
+   LKI(fn->ref_fq_add);
+   LKI(fn->ref_fq_del);
+   pthread_cond_init(&(fn->cond_fq_del), NULL);
+#endif
    return fn;
 }
 
@@ -506,6 +531,11 @@ evas_common_font_load(const char *name, int size)
    fi->hinting = fn->hinting;
    fn->references = 1;
    LKI(fn->lock);
+#ifdef EVAS_FRAME_QUEUING
+   LKI(fn->ref_fq_add);
+   LKI(fn->ref_fq_del);
+   pthread_cond_init(&(fn->cond_fq_del), NULL);
+#endif
    return fn;
 }
 
@@ -552,6 +582,19 @@ evas_common_font_free(RGBA_Font *fn)
    if (!fn) return;
    fn->references--;
    if (fn->references > 0) return;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(fn->ref_fq_add);
+   LKL(fn->ref_fq_del);
+   if (fn->ref_fq[0] != fn->ref_fq[1])
+     {
+        LKU(fn->ref_fq_add);
+        LKU(fn->ref_fq_del);
+        return;
+     }
+   LKU(fn->ref_fq_add);
+   LKU(fn->ref_fq_del);
+#endif
+
    EINA_LIST_FOREACH(fn->fonts, l, fi)
      {
        fi->references--;
@@ -565,6 +608,12 @@ evas_common_font_free(RGBA_Font *fn)
    eina_list_free(fn->fonts);
    if (fn->fash) fn->fash->freeme(fn->fash);
    LKD(fn->lock);
+#ifdef EVAS_FRAME_QUEUING
+   LKD(fn->ref_fq_add);
+   LKD(fn->ref_fq_del);
+   pthread_cond_destroy(&(fn->cond_fq_del));
+#endif
+
    free(fn);
 }
 
index afe1b11..1201514 100644 (file)
@@ -7,6 +7,9 @@
 FT_Library      evas_ft_lib = 0;
 static int      initialised = 0;
 
+LK(lock_font_draw); // for freetype2 API calls
+LK(lock_fribidi); // for fribidi API calls
+
 EAPI void
 evas_common_font_init(void)
 {
@@ -17,6 +20,11 @@ evas_common_font_init(void)
    error = FT_Init_FreeType(&evas_ft_lib);
    if (error) return;
    evas_common_font_load_init();
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_font_draw_init();
+#endif
+   LKI(lock_font_draw);
+   LKI(lock_fribidi);
 }
 
 EAPI void
@@ -28,11 +36,17 @@ evas_common_font_shutdown(void)
    initialised--;
    if (initialised != 0) return;
 
+   LKD(lock_font_draw);
+   LKD(lock_fribidi);
+   
    evas_common_font_load_shutdown();
    evas_common_font_cache_set(0);
    evas_common_font_flush();
 
    error = FT_Done_FreeType(evas_ft_lib);
+#ifdef EVAS_FRAME_QUEUING
+   evas_common_font_draw_finish();
+#endif
    evas_ft_lib = 0;
 }
 
diff --git a/src/lib/engines/common/evas_font_private.h b/src/lib/engines/common/evas_font_private.h
new file mode 100644 (file)
index 0000000..31bdaed
--- /dev/null
@@ -0,0 +1,23 @@
+#ifndef _EVAS_FONT_PRIVATE_H
+# define _EVAS_FONT_PRIVATE_H
+
+#ifdef BUILD_PTHREAD
+extern LK(lock_font_draw); // for freetype2 API calls
+extern LK(lock_fribidi); // for fribidi API calls
+#endif
+
+# ifdef EVAS_FRAME_QUEUING
+#  define FTLOCK() LKL(lock_font_draw)
+#  define FTUNLOCK() LKU(lock_font_draw)
+
+#  define FBDLOCK() LKL(lock_fribidi)
+#  define FBDUNLOCK() LKU(lock_fribidi)
+# else
+#  define FTLOCK(x) 
+#  define FTUNLOCK(x) 
+
+#  define FBDLOCK() 
+#  define FBDUNLOCK() 
+# endif
+
+#endif /* !_EVAS_FONT_PRIVATE_H */
index c626612..d1b2f99 100644 (file)
@@ -1,5 +1,6 @@
 #include "evas_common.h"
 #include "evas_intl_utils.h" /*defines INTERNATIONAL_SUPPORT if possible */
+#include "evas_font_private.h" /* for Frame-Queuing support */
 
 EAPI int
 evas_common_font_query_kerning(RGBA_Font_Int* fi,
@@ -26,12 +27,14 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi,
     * values to kern by - given same font, same size and same
     * prev_index and index. auto/bytecode or none hinting doesnt
     * matter */
+   FTLOCK();
    if (FT_Get_Kerning(fi->src->ft.face,
                      key[0], key[1],
                      ft_kerning_default, &delta) == 0)
      {
        int *push;
 
+        FTUNLOCK();
        *kerning = delta.x >> 6;
 
        push = malloc(sizeof (int) * 3);
@@ -46,6 +49,7 @@ evas_common_font_query_kerning(RGBA_Font_Int* fi,
        goto on_correct;
      }
 
+        FTUNLOCK();
    error = 0;
 
  on_correct:
@@ -188,7 +192,9 @@ evas_common_font_query_advance(RGBA_Font *fn, const char *text, int *h_adv, int
    pen_x = 0;
    pen_y = 0;
 //   evas_common_font_size_use(fn);
+   FTLOCK();
    use_kerning = FT_HAS_KERNING(fi->src->ft.face);
+   FTUNLOCK();
    prev_index = 0;
    for (chr = 0; text[chr];)
      {
index e2b0d97..5d3893e 100644 (file)
@@ -68,6 +68,15 @@ evas_common_gradient2_free(RGBA_Gradient2 *gr)
    if (!gr) return;
    gr->references--;
    if (gr->references > 0) return;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(gr->ref_fq_add);  LKL(gr->ref_fq_del);
+   if (gr->ref_fq[0] != gr->ref_fq[1])
+     {
+        LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
+        return;
+     }
+   LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
+#endif
    evas_common_gradient2_clear(gr);
    if (gr->stops.cdata) free(gr->stops.cdata);
    if (gr->stops.adata) free(gr->stops.adata);
index 3d11fba..9aa9b67 100644 (file)
@@ -160,6 +160,15 @@ evas_common_gradient_free(RGBA_Gradient *gr)
    if (!gr) return;
    gr->references--;
    if (gr->references > 0) return;
+#ifdef EVAS_FRAME_QUEUING
+        LKL(gr->ref_fq_add);  LKL(gr->ref_fq_del);
+        if (gr->ref_fq[0] != gr->ref_fq[1])
+          {
+             LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
+             return;
+          }
+       LKU(gr->ref_fq_add); LKU(gr->ref_fq_del);
+#endif
    evas_common_gradient_clear(gr);
    if (gr->type.name) free(gr->type.name);
    if (gr->type.params) free(gr->type.params);
index 410d713..e776fcf 100644 (file)
@@ -6,12 +6,14 @@
 #include "evas_private.h"
 #include "evas_cs.h"
 
-struct ext_loader_s {
-   const char* extention;
-   const char* loader;
+struct ext_loader_s
+{
+   const char *extention;
+   const char *loader;
 };
 
-static struct ext_loader_s     const loaders[] = {
+static const struct ext_loader_s loaders[] =
+{
    { "png", "png" },
    { "jpg", "jpeg" },
    { "jpeg", "jpeg" },
@@ -29,11 +31,14 @@ static struct ext_loader_s  const loaders[] = {
    { "pbm", "pmaps" },
    { "pgm", "pmaps" },
    { "ppm", "pmaps" },
-   { "pnm", "pmaps" }
+   { "pnm", "pmaps" },
+   { "bmp", "bmp" },
+   { "tga", "tga" }
 };
 
-static const char *loaders_name[] = {
-  "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb"
+static const char *loaders_name[] =
+{
+  "png", "jpeg", "eet", "xpm", "tiff", "gif", "svg", "pmaps", "edb", "bmp", "tga"
 };
 
 struct evas_image_foreach_loader_data
index 899a769..d2efb67 100644 (file)
@@ -141,6 +141,12 @@ _evas_common_rgba_image_new(void)
    if (!im) return NULL;
    im->flags = RGBA_IMAGE_NOTHING;
    im->ref = 1;
+#ifdef EVAS_FRAME_QUEUING
+   LKI(im->ref_fq_add);
+   LKI(im->ref_fq_del);
+   pthread_cond_init(&(im->cond_fq_del), NULL);
+#endif
+
    evas_common_rgba_image_scalecache_init(&im->cache_entry);
    return &im->cache_entry;
 }
@@ -152,6 +158,11 @@ _evas_common_rgba_image_delete(Image_Entry *ie)
 
 #ifdef BUILD_PIPE_RENDER
    evas_common_pipe_free(im);
+# ifdef EVAS_FRAME_QUEUING
+   LKD(im->ref_fq_add);
+   LKD(im->ref_fq_del);
+   pthread_cond_destroy(&(im->cond_fq_del));
+# endif
 #endif   
    evas_common_rgba_image_scalecache_shutdown(&im->cache_entry);
    if (ie->info.module) evas_module_unref((Evas_Module *)ie->info.module);
@@ -180,8 +191,6 @@ evas_common_rgba_image_unload(Image_Entry *ie)
 {
    RGBA_Image   *im = (RGBA_Image *) ie;
 
-   evas_cache_image_preload_cancel(ie, NULL);
-
    if (!ie->flags.loaded) return;
    if ((!ie->info.module) && (!ie->data1)) return;
    if (!ie->file) return;
index 4391beb..71ae93e 100644 (file)
@@ -40,6 +40,9 @@ struct _Scaleitem
    int dst_w, dst_h;
    int flop;
    int size_adjust;
+#ifdef EVAS_FRAME_QUEUING
+   RWLK(lock);
+#endif
    Eina_Bool forced_unload : 1;
    Eina_Bool smooth : 1;
    Eina_Bool populate_me : 1;
@@ -90,7 +93,8 @@ evas_common_scalecache_shutdown(void)
 {
 #ifdef SCALECACHE
    init--;
-   LKD(cache_lock);
+   if (init ==0)
+      LKD(cache_lock);
 #endif
 }
 
@@ -123,6 +127,9 @@ evas_common_rgba_image_scalecache_dirty(Image_Entry *ie)
      {
         Scaleitem *sci;
         sci = im->cache.list->data;
+#ifdef EVAS_FRAME_QUEUING
+        WRLKL(sci->lock);
+#endif
         im->cache.list = eina_list_remove(im->cache.list, sci);
         if (sci->im)
           {
@@ -136,6 +143,10 @@ evas_common_rgba_image_scalecache_dirty(Image_Entry *ie)
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
              LKU(cache_lock);
           }
+#ifdef EVAS_FRAME_QUEUING
+         RWLKU(sci->lock);
+         RWLKD(sci->lock);
+#endif
         free(sci);
      }
    LKU(im->cache.lock);
@@ -230,6 +241,9 @@ _sci_find(RGBA_Image *im,
      {
         l = eina_list_last(im->cache.list);
         sci = l->data;
+#ifdef EVAS_FRAME_QUEUING
+        WRLKL(sci->lock);
+#endif
         im->cache.list = eina_list_remove_list(im->cache.list, l);
         if ((sci->usage == im->cache.newest_usage) ||
             (sci->usage_count == im->cache.newest_usage_count))
@@ -244,6 +258,9 @@ _sci_find(RGBA_Image *im,
 //             INF(" 1- %i", sci->dst_w * sci->dst_h * 4);
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
           }
+#ifdef EVAS_FRAME_QUEUING
+        RWLKU(sci->lock);
+#endif
         if (max_scale_items < 1) return NULL;
      }
    else
@@ -255,6 +272,9 @@ _sci_find(RGBA_Image *im,
         sci = malloc(sizeof(Scaleitem));
         memset(sci, 0, sizeof(Eina_Inlist));
         sci->parent_im = im;
+#ifdef EVAS_FRAME_QUEUING
+        RWLKI(sci->lock);
+#endif
      }
    sci->usage = 0;
    sci->usage_count = 0;
@@ -288,6 +308,9 @@ _cache_prune(Scaleitem *notsci, Eina_Bool copies_only)
              if (!sci) return;
           }
         if (sci == notsci) return;
+#ifdef EVAS_FRAME_QUEUING
+        WRLKL(sci->lock);
+#endif
         if (sci->im)
           {
              evas_common_rgba_image_free(&sci->im->cache_entry);
@@ -303,6 +326,10 @@ _cache_prune(Scaleitem *notsci, Eina_Bool copies_only)
              cache_list = eina_inlist_remove(cache_list, (Eina_Inlist *)sci);
              memset(sci, 0, sizeof(Eina_Inlist));
           }
+#ifdef EVAS_FRAME_QUEUING
+        RWLKU(sci->lock);
+#endif
+
 //        INF("FLUSH %i > %i", cache_size, max_cache_size);
       }
 }
@@ -467,9 +494,14 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
    LKL(im->cache.lock);
    if ((src_region_w == dst_region_w) && (src_region_h == dst_region_h))
      {
-        if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
-          evas_cache_image_load_data(&im->cache_entry);
-        evas_common_image_colorspace_normalize(im);
+#ifdef EVAS_FRAME_QUEUING
+        if (!evas_common_frameq_enabled())
+#endif
+         {
+            if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+               evas_cache_image_load_data(&im->cache_entry);
+            evas_common_image_colorspace_normalize(im);
+         }
 //        noscales++;
         LKU(im->cache.lock);
         if (im->image.data)
@@ -496,9 +528,14 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
    LKU(cache_lock);
    if (!sci)
      {
-        if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
-          evas_cache_image_load_data(&im->cache_entry);
-        evas_common_image_colorspace_normalize(im);
+#ifdef EVAS_FRAME_QUEUING
+        if (!evas_common_frameq_enabled())
+#endif
+          {
+             if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+                evas_cache_image_load_data(&im->cache_entry);
+             evas_common_image_colorspace_normalize(im);
+          }
 //        misses++;
         LKU(im->cache.lock);
         if (im->image.data)
@@ -656,6 +693,9 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
              if (sci->flop > 0) sci->flop -= FLOP_DEL;
           }
 //        INF("use cached!");
+#ifdef EVAS_FRAME_QUEUING
+        RDLKL(sci->lock);
+#endif
         LKU(im->cache.lock);
         evas_common_scale_rgba_in_to_out_clip_sample
           (sci->im, dst, dc,
@@ -663,11 +703,22 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
            dst_region_w, dst_region_h,
            dst_region_x, dst_region_y, 
            dst_region_w, dst_region_h);
+#ifdef EVAS_FRAME_QUEUING
+        RWLKU(sci->lock);
+#endif
 //        hits++;
 //        INF("check %p %i < %i", 
 //               im,
 //               (int)im->cache.orig_usage, 
 //               (int)im->cache.newest_usage);
+#ifndef EVAS_FRAME_QUEUING
+        /* while framequeuing is applied,
+         * original image data is loaded by the main thread 
+         * just before enqueuing the rendering op into the pipe.
+         * so unloading the original image data here 
+         * causes only speed-down side-effect and no memory usage gain;
+         * it will be loaded again for the very next rendering for this image.
+         */
         if ((dounload) || 
             ((im->cache_entry.flags.loaded) && 
              ((!im->cs.no_free) 
@@ -683,12 +734,18 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
                   evas_common_rgba_image_unload(&im->cache_entry);
                }
           }
+#endif
      }
    else
      {
-        if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
-          evas_cache_image_load_data(&im->cache_entry);
-        evas_common_image_colorspace_normalize(im);
+#ifdef EVAS_FRAME_QUEUING
+        if (!evas_common_frameq_enabled())
+#endif
+          {
+             if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+                evas_cache_image_load_data(&im->cache_entry);
+             evas_common_image_colorspace_normalize(im);
+          }
 //        misses++;
         LKU(im->cache.lock);
         if (im->image.data)
@@ -709,9 +766,14 @@ evas_common_rgba_image_scalecache_do(Image_Entry *ie, RGBA_Image *dst,
      }
 #else   
    RGBA_Image *im = (RGBA_Image *)ie;
-   if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
-     evas_cache_image_load_data(&im->cache_entry);
-   evas_common_image_colorspace_normalize(im);
+#ifdef EVAS_FRAME_QUEUING
+   if (!evas_common_frameq_enabled())
+#endif
+     {
+        if (im->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+           evas_cache_image_load_data(&im->cache_entry);
+        evas_common_image_colorspace_normalize(im);
+     }
    if (im->image.data)
      {
         if (smooth)
index 90ccfcb..0cf5212 100644 (file)
@@ -4,6 +4,8 @@
 #include "evas_common.h"
 #include "evas_intl_utils.h"
 
+#include "evas_font_private.h"
+
 #ifdef INTERNATIONAL_SUPPORT
 #include <fribidi/fribidi.h>
 
@@ -41,10 +43,12 @@ evas_intl_utf8_to_visual(const char *text,
    if (!unicode_in)
      {
        len = -1;
-       goto error1;
+        goto error1;
      }
 
+   FBDLOCK();
    len = fribidi_utf8_to_unicode(text, byte_len, unicode_in);
+   FBDUNLOCK();
    unicode_in[len] = 0;
 
    unicode_out = (FriBidiChar *)alloca(sizeof(FriBidiChar) * (len + 1));
@@ -109,7 +113,8 @@ evas_intl_utf8_to_visual(const char *text,
      }
 
    fribidi_unicode_to_utf8(unicode_out, len, text_out);
-
+   FBDUNLOCK();
+   
    *ret_len = len;
    return text_out;
 
index e18421c..d4788fe 100644 (file)
@@ -8,7 +8,7 @@
         for (y = ystart; y <= yend; y++)
           {
              int x, w, ww;
-             FPc u, v, ud, vd, dv;
+             FPc u, v, ud, vd, dv, ue, ve;
              DATA32 *d, *s;
 #ifdef COLMUL             
              FPc cv, cd, cc; // col
                        
                        ww = w;
                        u = span->u[0] << FPI;
+                       if (u < 0) u = 0;
+                       else if (u >= swp) u = swp - 1;
                        v = span->v[0] << FPI;
-                       ud = ((span->u[1] << FPI) - u) / w;
-                       vd = ((span->v[1] << FPI) - v) / w;
+                       if (v < 0) v = 0;
+                       else if (v >= shp) v = shp - 1;
+                       ue = span->u[1] << FPI;
+                       if (ue < 0) ue = 0;
+                       else if (ue >= swp) ue = swp - 1;
+                       ve = span->v[1] << FPI;
+                       if (ve < 0) ve = 0;
+                       else if (ve >= shp) ve = shp - 1;
+                       ud = (ue - u) / w;
+                       vd = (ve - v) / w;
                        tl = (long long)ud * (w << FP);
                        tl = tl / dv;
                        ud = tl;
         for (y = ystart; y <= yend; y++)
           {
              int x, w, ww;
-             FPc u, v, ud, vd;
+             FPc u, v, ud, vd, ue, ve;
              DATA32 *d, *s;
 #ifdef COLMUL
              FPc cv, cd, cc; // col
                        if (w <= 0) continue;
                        ww = w;
                        u = span->u[0] << FPI;
+                       if (u < 0) u = 0;
+                       else if (u >= swp) u = swp - 1;
                        v = span->v[0] << FPI;
-                       ud = ((span->u[1] << FPI) - u) / w;
-                       vd = ((span->v[1] << FPI) - v) / w;
-                       if (ud < 0) u -= 1;
-                       if (vd < 0) v -= 1;
-                       
+                       if (v < 0) v = 0;
+                       else if (v >= shp) v = shp - 1;
+                       ue = span->u[1] << FPI;
+                       if (ue < 0) ue = 0;
+                       else if (ue >= swp) ue = swp - 1;
+                       ve = span->v[1] << FPI;
+                       if (ve < 0) ve = 0;
+                       else if (ve >= shp) ve = shp - 1;
+                       ud = (ue - u) / w;
+                       vd = (ve - v) / w;
                        if (direct)
                          d = dst->image.data + (y * dst->cache_entry.w) + x;
                        else
index 94f129d..8026523 100644 (file)
@@ -106,7 +106,7 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
           func = evas_common_gfx_func_composite_pixel_span_get(src, dst, cw, dc->render_op);
         src->cache_entry.flags.alpha = pa;
      }
-   
+    
    if (!havecol)
      {
 #undef COLMUL     
index aa067e0..3e6c402 100644 (file)
      {
 # ifdef COLMUL
         DATA32 val1, cval; // col
-# endif        
+# endif
 # ifdef COLBLACK
         *d = 0xff000000; // col
-# else        
+# else
         s = sp + ((v >> (FP + FPI)) * sw) + 
           (u >> (FP + FPI));
 #  ifdef COLMUL
         cval = INTERP_256((cv >> 16), c2, c1); // col
         *d = MUL4_SYM(cval, val1);
         cv += cd; // col              
-#  else        
+#  else
         *d = *s;
-#  endif        
+#  endif
         u += ud;
         v += vd;
-# endif        
+# endif
         d++;
         ww--;
      }
index 7664248..09eca0e 100644 (file)
@@ -68,9 +68,8 @@ _op_blend_mas_c_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, int
        "       cmp             %[tmp], %[d]                    \n\t"
        "       ble             "AP"loopout                     \n\t"
        AP"quadloopint:                                         \n\t"
-//     "       vld1.32         d0[0],  [%[m]]!                 \n\t"
-       "       ldr.32          %[x],   [%[m]]                  \n\t"
-       "       add %[m], #4                                    \n\t"
+       "       ldr             %[x],   [%[m]]                  \n\t"
+       "       add             %[m], #4                        \n\t"
        "       cmp             %[x],   #0                      \n\t"
        "       beq             "AP"fastloop                    \n\t"
        "       vmov.32         d0[0],  %[x]                    \n\t"
@@ -232,7 +231,7 @@ _op_blend_mas_can_dp_neon(DATA32 *s __UNUSED__, DATA8 *m, DATA32 c, DATA32 *d, i
 
        AP"quadloopint:                                 \n\t"
                // Load the mask: 4 bytes: It has d0/d1
-       "       ldr.32          %[x],   [%[m]]          \n\t"
+       "       ldr             %[x],   [%[m]]          \n\t"
        "       add             %[m], #4                \n\t"
        "       cmp             %[x],   #0              \n\t"
        "       beq             "AP"fastloop            \n\t"
index bafb95a..c71d132 100644 (file)
@@ -7,6 +7,209 @@
 #include "evas_common.h"
 
 #ifdef BUILD_PIPE_RENDER
+
+#ifdef EVAS_FRAME_QUEUING
+#define SCALECACHE
+static Evas_FrameQ gframeq;    // global frameQ
+
+static Evas_Surface *
+evas_common_surface_alloc(void *surface, int x, int y, int w, int h)
+{
+   Evas_Surface *e_surface;
+
+   e_surface = calloc(1, sizeof(Evas_Surface));
+   e_surface->im = surface;
+   LKL(e_surface->im->ref_fq_add);
+   e_surface->im->ref_fq[0]++;
+   LKU(e_surface->im->ref_fq_add);
+   e_surface->x = x;
+   e_surface->y = y;
+   e_surface->w = w;
+   e_surface->h = h;
+
+   return e_surface;
+}
+
+static void
+evas_common_surface_dealloc(Evas_Surface *surface)
+{
+   Evas_Surface *d_surface;
+
+   while(surface)
+     {
+        d_surface = surface;
+        surface = (Evas_Surface *)eina_inlist_remove(EINA_INLIST_GET(surface), EINA_INLIST_GET(d_surface));
+        LKL(d_surface->im->ref_fq_del);
+        d_surface->im->ref_fq[1]++;
+        LKU(d_surface->im->ref_fq_del);
+
+        free(d_surface);
+
+     }
+}
+
+static void
+evas_common_surface_add(Evas_Frame *frame, Evas_Surface *surface)
+{
+   frame->surfaces = (Evas_Surface *)eina_inlist_append(EINA_INLIST_GET(frame->surfaces), EINA_INLIST_GET(surface));
+}
+
+static Evas_Frame * 
+evas_common_frame_alloc()
+{
+   Evas_Frame *frame;
+
+   frame = calloc(1, sizeof(Evas_Frame));
+   frame->surfaces = NULL;
+   return frame;
+}
+
+static void 
+evas_common_frame_dealloc(Evas_Frame *frame)
+{
+   evas_common_surface_dealloc(frame->surfaces);
+   free(frame);
+}
+
+static void
+evas_common_frame_add(Evas_FrameQ *frameq, Evas_Frame *frame)
+{
+   Evas_Frame *temp_frame;
+   
+   LKL(frameq->mutex);
+   while(eina_inlist_count(EINA_INLIST_GET(frameq->frames)) >= frameq->frameq_sz)
+     {
+        /* wait a worker thread finish previous frame */
+        pthread_cond_wait(&(frameq->cond_done), &(frameq->mutex));
+   }
+   frameq->frames = (Evas_Frame *) eina_inlist_append(EINA_INLIST_GET(frameq->frames), EINA_INLIST_GET(frame));
+
+   // this frame need not to be scheduled for flushing time
+   EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), temp_frame)
+    {
+       if (!temp_frame->ready)
+         {
+            break;
+         }
+     }
+   if (temp_frame && temp_frame == frame)
+      frame->dont_schedule = 1;
+
+   LKU(frameq->mutex);
+
+   pthread_cond_signal(&(frameq->cond_new));
+}
+
+EAPI Evas_Surface *
+evas_common_frameq_new_surface (void *surface, int x, int y, int w, int h)
+{
+   return evas_common_surface_alloc(surface, x, y, w, h);
+}
+
+EAPI void
+evas_common_frameq_add_surface(Evas_Surface *surface)
+{
+   evas_common_surface_add(gframeq.cur_frame, surface);
+}
+
+EAPI void 
+evas_common_frameq_set_frame_data(void *data, 
+     void (*fn_output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h),
+     void (*fn_output_flush)  (void *data),
+     void (*fn_output_set_priv)(void *data, void *cur, void *prev))
+{
+   if (gframeq.cur_frame) 
+     {
+        gframeq.cur_frame->data = data;
+        gframeq.cur_frame->output_redraws_next_update_push = fn_output_redraws_next_update_push;
+        gframeq.cur_frame->output_flush = fn_output_flush;
+        gframeq.cur_frame->output_set_priv = fn_output_set_priv;
+     }
+}
+
+EAPI void
+evas_common_frameq_prepare_frame()
+{
+   if (!gframeq.cur_frame )
+     {
+        gframeq.cur_frame = evas_common_frame_alloc();
+     }
+}
+
+EAPI void
+evas_common_frameq_ready_frame()
+{
+   if (gframeq.cur_frame)
+     {
+        evas_common_frame_add(&gframeq, gframeq.cur_frame);
+        gframeq.cur_frame = NULL; // create a new frame for the next frame later
+     }
+}
+
+
+EAPI void
+evas_common_frameq_init()
+{
+   gframeq.frames = NULL;
+   pthread_cond_init(&(gframeq.cond_new), NULL);
+   pthread_cond_init(&(gframeq.cond_ready), NULL);
+   pthread_cond_init(&(gframeq.cond_done), NULL);
+   LKI(gframeq.mutex);
+   gframeq.initialised = 0;    // worker thread are not created yet
+   gframeq.frameq_sz = 1;      // this value ensures the first frame can be enqueued.
+}
+
+EAPI void
+evas_common_frameq_destroy()
+{
+#if 0 // let them destroyed indirectly with program exit
+   LKL(gframeq.mutex);
+   pthread_cond_destroy(&(gframeq.cond_new));
+   pthread_cond_destroy(&(gframeq.cond_ready));
+   pthread_cond_destroy(&(gframeq.cond_done));
+   LKU(gframeq.mutex);
+#endif
+   LKD(gframeq.mutex);
+   
+   gframeq.frames = NULL;
+   gframeq.initialised = 0;
+}
+
+EAPI void
+evas_common_frameq_flush()
+{
+   if (! evas_common_frameq_enabled())
+      return;
+
+   LKL(gframeq.mutex);
+   while(eina_inlist_count(EINA_INLIST_GET(gframeq.frames)) > 0)
+     {
+        /* wait a worker thread finish previous frame */
+        pthread_cond_wait(&(gframeq.cond_done), &(gframeq.mutex));
+   }
+   LKU(gframeq.mutex);
+}
+
+
+EAPI void
+evas_common_frameq_flush_ready ()
+{
+   return;
+}
+
+EAPI int
+evas_common_frameq_get_frameq_sz()
+{
+   return gframeq.frameq_sz;
+}
+
+EAPI int
+evas_common_frameq_enabled()
+{
+   return gframeq.initialised;
+}
+#endif
+
 static RGBA_Pipe *evas_common_pipe_add(RGBA_Pipe *pipe, RGBA_Pipe_Op **op);
 static void evas_common_pipe_draw_context_copy(RGBA_Draw_Context *dc, RGBA_Pipe_Op *op);
 static void evas_common_pipe_op_free(RGBA_Pipe_Op *op);
@@ -20,23 +223,23 @@ evas_common_pipe_add(RGBA_Pipe *pipe, RGBA_Pipe_Op **op)
 
    if (!pipe)
      {
-       first_pipe = 1;
-       p = calloc(1, sizeof(RGBA_Pipe));
-       if (!p) return NULL;
-       pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
+        first_pipe = 1;
+        p = calloc(1, sizeof(RGBA_Pipe));
+        if (!p) return NULL;
+        pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
      }
    p = (RGBA_Pipe *)(EINA_INLIST_GET(pipe))->last;
    if (p->op_num == PIPE_LEN)
      {
-       p = calloc(1, sizeof(RGBA_Pipe));
-       if (!p) return NULL;
-       pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
+        p = calloc(1, sizeof(RGBA_Pipe));
+        if (!p) return NULL;
+        pipe = (RGBA_Pipe *)eina_inlist_append(EINA_INLIST_GET(pipe), EINA_INLIST_GET(p));
      }
    p->op_num++;
    *op = &(p->op[p->op_num - 1]);
    if (first_pipe)
      {
-       /* FIXME: PTHREAD init any thread locks etc */
+        /* FIXME: PTHREAD init any thread locks etc */
      }
    return pipe;
 }
@@ -47,11 +250,13 @@ evas_common_pipe_draw_context_copy(RGBA_Draw_Context *dc, RGBA_Pipe_Op *op)
    memcpy(&(op->context), dc, sizeof(RGBA_Draw_Context));
    if (op->context.cutout.active > 0)
      {
-       op->context.cutout.rects = malloc(sizeof(Cutout_Rect) * op->context.cutout.active);
-       memcpy(op->context.cutout.rects, dc->cutout.rects, sizeof(Cutout_Rect) * op->context.cutout.active);
+        op->context.cutout.rects = malloc(sizeof(Cutout_Rect) * op->context.cutout.active);
+        memcpy(op->context.cutout.rects, dc->cutout.rects, sizeof(Cutout_Rect) * op->context.cutout.active);
      }
    else
-     op->context.cutout.rects = NULL;
+     {
+        op->context.cutout.rects = NULL;
+     }
 }
 
 static void
@@ -60,54 +265,543 @@ evas_common_pipe_op_free(RGBA_Pipe_Op *op)
    evas_common_draw_context_apply_clean_cutouts(&op->context.cutout);
 }
 
-/* main api calls */
 #ifdef BUILD_PTHREAD
-typedef struct _Thinfo
+/* main api calls */
+static void *
+evas_common_pipe_thread(void *data)
 {
-   int                    thread_num;
-   pthread_t              thread_id;
-   pthread_barrier_t     *barrier;
-   RGBA_Pipe_Thread_Info *info;
-} Thinfo;
+   Thinfo *thinfo;
+
+// INF("TH [...........");
+   thinfo = data;
+   for (;;)
+     {
+        RGBA_Pipe_Thread_Info *info;
+        RGBA_Pipe *p;
+
+        /* wait for start signal */
+// INF(" TH %i START...", thinfo->thread_num);
+        pthread_barrier_wait(&(thinfo->barrier[0]));
+        info = thinfo->info;
+// if (info)
+//   {
+//      thinfo->info = NULL;
+//      INF(" TH %i GO", thinfo->thread_num);
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(info->im->pipe), p)
+          {
+             int i;
+
+             for (i = 0; i < p->op_num; i++)
+               {
+                  if (p->op[i].op_func)
+                  p->op[i].op_func(info->im, &(p->op[i]), info);
+               }
+          }
+        free(info);
+//   }
+// INF(" TH %i DONE", thinfo->thread_num);
+        /* send finished signal */
+        pthread_barrier_wait(&(thinfo->barrier[1]));
+     }
+   return NULL;
+}
+
+#ifdef EVAS_FRAME_QUEUING
+static void
+evas_common_frameq_release(void *data)
+{
+   Evas_FrameQ *frameq;
+   Evas_Frameq_Thread_Info *fq_info;
+   Thinfo *thinfo;
+
+   thinfo = data;
+   fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
+   frameq = fq_info->frameq;
+
+   /* This thread may or may not own the mutex.
+    * But there's no way to determine the ownership of the mutex, so release it anyway 
+    */
+   LKU(frameq->mutex);
+}
 
 static void *
-evas_common_pipe_thread(void *data)
+evas_common_frameq_thread(void *data)
 {
+   Evas_FrameQ *frameq;
+   Evas_Frame *frame;
+   Evas_Surface *surface;
+   RGBA_Pipe *p;
    Thinfo *thinfo;
+   Evas_Frameq_Thread_Info *fq_info;
+   RGBA_Pipe_Thread_Info p_info;
 
-//   INF("TH [...........");
    thinfo = data;
+   fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
+   frameq = fq_info->frameq;
+
+   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+   pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
+   /* install  thread cancelation cleanup handler */
+   pthread_cleanup_push(evas_common_frameq_release, data); 
+
    for (;;)
      {
-       RGBA_Pipe_Thread_Info *info;
-       RGBA_Pipe *p;
-
-       /* wait for start signal */
-//     INF(" TH %i START...", thinfo->thread_num);
-       pthread_barrier_wait(&(thinfo->barrier[0]));
-       info = thinfo->info;
-//     if (info)
-//       {
-//          thinfo->info = NULL;
-//          INF(" TH %i GO", thinfo->thread_num);
-       EINA_INLIST_FOREACH(EINA_INLIST_GET(info->im->pipe), p)
-              {
-                 int i;
-
-                 for (i = 0; i < p->op_num; i++)
-                   {
-                      if (p->op[i].op_func)
-                        p->op[i].op_func(info->im, &(p->op[i]), info);
-                   }
-              }
-            free(info);
-//       }
-//     INF(" TH %i DONE", thinfo->thread_num);
-       /* send finished signal */
-       pthread_barrier_wait(&(thinfo->barrier[1]));
+        frame = NULL;
+               
+        /* 1. pick a frame to draw */
+        LKL(frameq->mutex);
+        while(frame == NULL)
+          {
+             EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), frame)
+               {
+                  if (!frame->in_process)
+                    {
+                       frame->in_process = 1;
+                       break;
+                    }
+               }
+             if (frame)
+               {
+                  break;
+               }
+             pthread_testcancel();
+             pthread_cond_wait(&(frameq->cond_new), &(frameq->mutex));
+          }
+        LKU(frameq->mutex);
+
+        /* 2. draw selected frame */
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(frame->surfaces), surface)
+          {
+             p_info.im = surface->im;
+             p_info.x = 0;
+             p_info.y = 0;
+             p_info.w = surface->im->cache_entry.w;
+             p_info.h = surface->im->cache_entry.h;
+
+             EINA_INLIST_FOREACH(EINA_INLIST_GET(p_info.im->pipe), p)
+               {
+                  int i;
+
+                  for (i = 0; i < p->op_num; i++)
+                    {
+                       if (p->op[i].op_func)
+                         {
+                            p->op[i].op_func(p_info.im, &(p->op[i]), &p_info);
+                         }
+                    }
+               }
+
+             /* push surface out */
+             if (! surface->dontpush)
+               {
+                  frame->output_redraws_next_update_push(frame->data,  
+                              surface->im, surface->x, surface->y, surface->w, surface->h);
+               }
+          }
+
+        // record frame ready time, will be used in post worker thread, evas_common_frameq_thread_post()
+        gettimeofday(&frame->ready_time, NULL);
+
+        LKL(frameq->mutex);
+        frame->ready = 1;
+        pthread_cond_signal(&frameq->cond_ready);
+        LKU(frameq->mutex);
      }
+
+   // Remove cleanup handler
+   pthread_cleanup_pop(0);
    return NULL;
 }
+
+
+#define INTERVAL_QSIZE 17  // Actual size is 'INTERVAL_QSIZE - 1' because of not using index
+#define SATISFACTION_THRESHOLD 4 // 4 ms --> 250 FPS
+#define RESET_RATIO 4   // RESET_RATIO * [Average Ready Gap | get_max_interval()] --> Reset Threshold
+#define DOUBLE_RESET_TIME_INTERVAL_THRESHOLD 16000 // make it double in case of less 16ms
+#define RESET_ABSOLUTE_INTERVAL 600000  // 600 msec
+
+struct iq_node
+{
+   long long rt;
+   long long ri;
+};
+
+static struct iq_node _IQ[INTERVAL_QSIZE];
+static int _IQ_head = 0, _IQ_tail = 0;
+static int _IQ_length = 0;
+static long long min_ready, max_ready;
+static long long average_interval;
+
+static int 
+_IQ_next_index(int i)
+{
+   return (i + 1) % INTERVAL_QSIZE;
+}
+
+static int 
+_IQ_previous_index(int i)
+{
+   if (--i < 0) i += INTERVAL_QSIZE;
+   return i;
+}
+
+static void 
+_IQ_init(void)
+{
+   _IQ_length = _IQ_head = _IQ_tail = 0;
+   min_ready = LLONG_MAX, max_ready = LLONG_MIN;
+   average_interval = 0;
+}
+
+static int 
+_IQ_empty(void)
+{
+   return (_IQ_head == _IQ_tail) ? 1 : 0;
+}
+
+static int 
+_IQ_full(void)
+{
+   return (_IQ_head == ((_IQ_tail + 1) % INTERVAL_QSIZE)) ? 1 : 0;
+}
+
+static void 
+_IQ_insert(long long ready_time, long long last_interval)
+{
+   if (_IQ_full()) return;
+
+   if (_IQ_empty())
+     {
+        if (last_interval < 0)
+          {
+             last_interval = -last_interval;
+          }
+        _IQ[_IQ_tail].rt = ready_time;
+        _IQ[_IQ_tail].ri = last_interval;
+        min_ready = ready_time - last_interval;
+        max_ready = ready_time;
+        _IQ_tail = _IQ_next_index(_IQ_tail);
+        _IQ_length++;
+     }
+   else
+     {
+        if (max_ready < ready_time)
+          {
+             _IQ[_IQ_tail].rt = ready_time;
+             _IQ[_IQ_tail].ri = ready_time - max_ready;
+             _IQ_tail = _IQ_next_index(_IQ_tail);
+             _IQ_length++;
+             max_ready = ready_time;
+          }
+        else if (ready_time < min_ready)
+          {
+             last_interval = _IQ[_IQ_head].ri;
+             _IQ[_IQ_head].ri = _IQ[_IQ_head].rt - ready_time;
+             _IQ_head = _IQ_previous_index(_IQ_head);
+             _IQ[_IQ_head].rt = ready_time;
+             _IQ[_IQ_head].ri = last_interval;
+             min_ready = ready_time;
+             _IQ_length++;
+          }
+        else
+          {
+             int i, j, k, l = 0;
+             for (i = _IQ_head; i != _IQ_tail; i = j)
+               {
+                  j = _IQ_next_index(i);
+                  if (_IQ[j].rt < ready_time)
+                    {
+                       continue;
+                    }
+                  break;
+               }
+             for (k = _IQ_tail; k != j; k = l)
+               {
+                  l = _IQ_previous_index(k);
+                  _IQ[k] = _IQ[l];
+               }
+             i = _IQ_next_index(j);
+             _IQ[j].ri -= (_IQ[j].rt - ready_time);
+             _IQ[j].rt = ready_time;
+             _IQ[i].ri = _IQ[i].rt - ready_time;
+             _IQ_tail = _IQ_next_index(_IQ_tail);
+             _IQ_length++;
+          }
+     }
+   average_interval = (max_ready - min_ready) / _IQ_length;
+}
+
+static long long 
+_IQ_delete()
+{
+   struct iq_node oldest;
+   if (_IQ_empty()) return 0;
+   oldest = _IQ[_IQ_head];
+   _IQ_head = ++_IQ_head % INTERVAL_QSIZE;
+   if (--_IQ_length == 0)
+     {
+        _IQ_init();
+     }
+   else
+     {
+        min_ready = _IQ[_IQ_head].rt;
+        average_interval = (max_ready - min_ready) / _IQ_length;
+     }
+
+   return oldest.ri;
+}
+
+static long long 
+get_max_interval()
+{
+   int i;
+   long long max = LLONG_MIN;
+
+   for ( i= _IQ_head ; i != _IQ_tail ; i = _IQ_next_index(i))
+     {
+        if (_IQ[i].ri > max)
+          {
+             max = _IQ[i].ri;
+          }
+     }
+
+   return max;
+}
+
+static long long 
+tv_to_long_long(struct timeval *tv)
+{
+   if (tv == NULL)
+     {
+        return 0;
+     }
+
+   return tv->tv_sec * 1000000LL + tv->tv_usec;
+}
+
+static long long
+evas_common_frameq_schedule_flush_time( 
+                     int frameq_sz, int thread_no, 
+                     long long last_ready_time, long long current_ready_time,
+                     long long last_flush_time, int ready_frames_num,
+                     int dont_schedule)
+{
+   // to get each time and to do others
+   long long current_time = 0LL;
+   long long current_ready_interval = 0LL;
+   long long theshold_time = SATISFACTION_THRESHOLD * 1000LL;  // ms -> usec
+   long long reset_time_interval;
+   long long sleep_time = 0LL;
+   long long saved_ready_time, saved_ready_interval;
+   long long time_slept = 0LL;
+   static long long time_lag = 0;
+   struct timeval now;
+   int frameq_full_threshold =0;
+   int need_reset = 0;
+   int need_schedule = 0;
+
+   frameq_full_threshold = frameq_sz -thread_no;       // Qsize - threads#
+   
+   /* 1.5 defer flush time of current frame if need */
+   // in case of the first time, just keep ready time only
+   if (last_ready_time == 0LL)
+     {
+        last_ready_time = current_ready_time;
+     }
+   else
+     {
+        /* 1.5.1 get current ready time & interval */
+        saved_ready_time = current_ready_time;
+        saved_ready_interval = current_ready_interval = current_ready_time - last_ready_time;
+        // compensate a case which current ready time is older than previous one, 
+        // doesn't work on the interval queue
+        if (current_ready_interval < 0)
+          {
+             current_ready_time = last_ready_time;
+             current_ready_interval = 0;
+          }
+
+        /* 1.5.2 get the reset time interval before keeping a new one */
+        if (!_IQ_empty())
+          {
+             reset_time_interval = RESET_RATIO * average_interval;
+             if (average_interval < DOUBLE_RESET_TIME_INTERVAL_THRESHOLD) 
+               {
+                  reset_time_interval *= 2;
+               }
+          }
+
+        /* 1.5.3 reset - if too late, discard all saved interval and start from here */
+        if (current_ready_interval > RESET_ABSOLUTE_INTERVAL)
+          {
+             need_reset = 1;
+          }
+        else if (_IQ_length >= thread_no * 2 && current_ready_interval > reset_time_interval)
+          {
+             need_reset = 1;
+          }
+        else if (_IQ_length >= thread_no && _IQ_length < thread_no * 2 
+             && current_ready_interval > get_max_interval() * RESET_RATIO)
+          {
+             need_reset = 1;
+          }
+       
+        if (need_reset)
+          {
+             _IQ_init();
+          }
+        else
+          {
+             /* 1.5.4 enqueue - keep a new interval for next average interval */
+             if (_IQ_full())
+               {
+                  _IQ_delete();
+               }
+             _IQ_insert(saved_ready_time, saved_ready_interval);
+
+             /* 1.5.5 schedule - if faster than average interval, figure out sleep time to meet it */
+             if (!dont_schedule)
+               {
+                  need_schedule = 0;
+                  sleep_time = 0;
+                  if (_IQ_length >= thread_no * 2 && average_interval > theshold_time)
+                    {
+                       need_schedule = 1;
+                    }
+                  // compensate the case that postworker blocks the workers from getting a new fresh frame
+                  // It's actually occurred when during the wait time of postworker, the frame queue is full
+                  // Consequently check the number of currently ready frames and apply some time drop to average time according to the number
+                  if (ready_frames_num >= frameq_full_threshold)
+                    {
+                       need_schedule = 0;
+                    }
+                  if (need_schedule)
+                    {
+                       gettimeofday(&now, NULL);
+                       current_time = tv_to_long_long(&now);
+                       time_lag += (current_time - last_flush_time);
+                       sleep_time = (average_interval < time_lag) ? 0 : (average_interval - time_lag);
+                    }
+               }
+
+             /* 1.5.6 sleep - actually sleep and get over-slept time (time_lag) for next frame */
+             if (sleep_time > 0)
+               {
+                  sleep_time = sleep_time * 9 / 10;
+                  usleep((unsigned int)sleep_time);
+                  gettimeofday(&now, NULL);
+                  time_slept = tv_to_long_long(&now) - current_time;
+                  time_lag = time_slept - sleep_time;
+               }
+             else
+               {
+                  time_lag = 0;
+               }
+          }
+        last_ready_time = current_ready_time;
+     }
+
+   return last_ready_time;
+}
+
+static void *
+evas_common_frameq_thread_post(void *data)
+{
+   Evas_FrameQ *frameq;
+   Evas_Frame *frame;
+   Evas_Surface *surface;
+   RGBA_Pipe *p;
+   Thinfo *thinfo;
+   Evas_Frameq_Thread_Info *fq_info;
+   RGBA_Pipe_Thread_Info p_info;
+   Eina_List   *pending_writes = NULL;
+   Eina_List   *prev_pending_writes = NULL;
+
+   long long last_ready_time = 0LL;
+   long long current_ready_time;
+   Evas_Frame *temp_frame = NULL;
+   int ready_frames_num;
+   long long last_flush_time = 0LL;
+   struct timeval now;
+   int dont_schedule = 0;
+
+   thinfo = data;
+   fq_info = (Evas_Frameq_Thread_Info *)(thinfo->fq_info);
+   frameq = fq_info->frameq;
+
+   pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
+   pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL);
+   /* install  thread cancelation cleanup handler */
+   pthread_cleanup_push(evas_common_frameq_release, data); 
+
+   _IQ_init();
+
+   for (;;)
+     {
+        /* 1. wait the first frame being done */
+        LKL(frameq->mutex);
+        while(!frameq->frames || !frameq->frames->ready)
+          {
+             pthread_cond_wait(&(frameq->cond_ready), &(frameq->mutex));
+          }
+        frame = frameq->frames;
+
+        /* 1.5. prepare to schedule flush time */
+        current_ready_time = tv_to_long_long(&frame->ready_time);
+        ready_frames_num = 0;
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(frameq->frames), temp_frame)
+          {
+             if (temp_frame->ready == 1)
+               {
+                  ready_frames_num++;
+               }
+          }
+        dont_schedule = (frame->dont_schedule)?1:0;
+        LKU(frameq->mutex);
+
+        /* 2. generate pending_writes */
+        EINA_INLIST_FOREACH(EINA_INLIST_GET(frame->surfaces), surface)
+         {
+            evas_common_pipe_flush(surface->im);
+            if (! surface->dontpush)
+              {
+                 pending_writes = eina_list_append(pending_writes, surface->im);
+              }
+         }
+
+        /* 2.5. schedule flush time */
+        last_ready_time = evas_common_frameq_schedule_flush_time(
+                                       frameq->frameq_sz, frameq->thread_num, 
+                                       last_ready_time, current_ready_time,
+                                       last_flush_time, ready_frames_num, dont_schedule);
+
+        /* 3. flush redraws */
+        frame->output_set_priv(frame->data, pending_writes, prev_pending_writes);
+        frame->output_flush(frame->data);
+        gettimeofday(&now, NULL);
+        // keep as the last flush time
+        last_flush_time = now.tv_sec * 1000000LL + now.tv_usec;
+
+        prev_pending_writes = pending_writes;
+        pending_writes = NULL;
+
+        /* 4. remove this frame from the frame queue */
+        LKL(frameq->mutex);
+        frameq->frames = 
+            (Evas_Frame *)eina_inlist_remove(EINA_INLIST_GET(frameq->frames), 
+                  EINA_INLIST_GET(frame));
+
+        LKU(frameq->mutex);
+        pthread_cond_broadcast(&frameq->cond_done);
+        evas_common_frame_dealloc(frame);
+     }
+
+   // Remove cleanup handler
+   pthread_cleanup_pop(0);
+   return NULL;
+}
+
+#endif /* EVAS_FRAME_QUEUING */
 #endif
 
 #ifdef BUILD_PTHREAD
@@ -122,6 +816,10 @@ evas_common_pipe_begin(RGBA_Image *im)
 #ifdef BUILD_PTHREAD
    int i, y, h;
 
+#ifdef EVAS_FRAME_QUEUING
+   return;
+#endif
+
    if (!im->pipe) return;
    if (thread_num == 1) return;
    y = 0;
@@ -129,34 +827,138 @@ evas_common_pipe_begin(RGBA_Image *im)
    if (h < 1) h = 1;
    for (i = 0; i < thread_num; i++)
      {
-       RGBA_Pipe_Thread_Info *info;
+        RGBA_Pipe_Thread_Info *info;
 
-//          if (y >= im->cache_entry.h) break;
-       info = calloc(1, sizeof(RGBA_Pipe_Thread_Info));
-       info->im = im;
+//      if (y >= im->cache_entry.h) break;
+        info = calloc(1, sizeof(RGBA_Pipe_Thread_Info));
+        info->im = im;
 #ifdef EVAS_SLI
-       info->x = 0;
-       info->w = im->cache_entry.w;
-       info->y = i;
-       info->h = thread_num;
+        info->x = 0;
+        info->w = im->cache_entry.w;
+        info->y = i;
+        info->h = thread_num;
 #else
-       info->x = 0;
-       info->y = y;
-       info->w = im->cache_entry.w;
-       if (i == (thread_num - 1))
-         info->h = im->cache_entry.h - y;
-       else
-         info->h = h;
-       y += info->h;
+        info->x = 0;
+        info->y = y;
+        info->w = im->cache_entry.w;
+        if (i == (thread_num - 1))
+          {
+             info->h = im->cache_entry.h - y;
+          }
+        else
+          {
+             info->h = h;
+          }
+        y += info->h;
 #endif
-       thinfo[i].info = info;
+        thinfo[i].info = info;
      }
    /* tell worker threads to start */
    pthread_barrier_wait(&(thbarrier[0]));
 #endif
 }
 
-static void
+#ifdef EVAS_FRAME_QUEUING
+EAPI void
+evas_common_frameq_begin()
+{
+#ifdef BUILD_PTHREAD
+   int i;
+   Evas_Frameq_Thread_Info *fp_info;
+   pthread_attr_t attr;
+   cpu_set_t cpu;
+
+   if (!gframeq.initialised)
+     {
+        int cpunum, set_cpu_affinity;
+
+        cpunum = eina_cpu_count();
+        gframeq.thread_num = cpunum;
+        gframeq.frameq_sz = cpunum * FRAMEQ_SZ_PER_THREAD;
+
+        for (i = 0; i < gframeq.thread_num; i++)
+          {
+
+             fp_info = calloc(1, sizeof(Evas_Frameq_Thread_Info));
+             fp_info->frameq = &gframeq;
+
+             gframeq.thinfo[i].thread_num = i;
+             gframeq.thinfo[i].fq_info = fp_info;
+
+             pthread_attr_init(&attr);
+             if (set_cpu_affinity)
+               {
+                  CPU_ZERO(&cpu);
+                  CPU_SET((i+1) % cpunum, &cpu);
+                  pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
+               }
+
+             pthread_create(&(gframeq.thinfo[i].thread_id), &attr,
+                     evas_common_frameq_thread, &(gframeq.thinfo[i]));
+
+             pthread_attr_destroy(&attr);
+             pthread_detach(gframeq.thinfo[i].thread_id);
+          }
+
+          {
+             fp_info = calloc(1, sizeof(Evas_Frameq_Thread_Info));
+             fp_info->frameq = &gframeq;
+
+             gframeq.thinfo[i].thread_num = i;
+             gframeq.thinfo[i].fq_info = fp_info;
+
+             pthread_attr_init(&attr);
+             if (set_cpu_affinity)
+               {
+                  CPU_ZERO(&cpu);
+                  CPU_SET((i+1) % cpunum, &cpu);
+                  pthread_attr_setaffinity_np(&attr, sizeof(cpu), &cpu);
+               }
+
+             pthread_create(&(gframeq.thinfo[i].thread_id), &attr,
+                     evas_common_frameq_thread_post, &(gframeq.thinfo[i]));
+             pthread_attr_destroy(&attr);
+             pthread_detach(gframeq.thinfo[i].thread_id);
+          }
+        gframeq.initialised = 1;       // now worker threads are created.
+
+       INF("initialised");
+       DBG("%d cpus, set_cpu_affinity=%d, frameq_sz=%d",
+           cpunum, set_cpu_affinity, gframeq.frameq_sz);
+     }
+#endif /* BUILD_PTHREAD */
+}
+
+EAPI void
+evas_common_frameq_finish()
+{
+   int i;
+   
+   /* 1. cancel all worker threads */
+   for (i = 0; i < gframeq.thread_num; i++)
+     {
+        pthread_cancel(gframeq.thinfo[i].thread_id);
+     }
+     // cancel post-worker thread
+     pthread_cancel(gframeq.thinfo[i].thread_id);
+
+   /* 2. send signal to worker threads so that they enter to the thread cancelation cleanup handler */
+   for (i = 0; i < gframeq.thread_num; i++)
+     {
+        pthread_cond_signal(&(gframeq.cond_new));
+     }
+   // send signal to post-worker thread
+   pthread_cond_signal(&(gframeq.cond_ready));
+
+   /* all the workers were created and detached before
+    *  so don't need to join them here.
+    */
+
+}
+
+#endif /* EVAS_FRAME_QUEUING */
+
+EAPI void
 evas_common_pipe_flush(RGBA_Image *im)
 {
 
@@ -164,25 +966,31 @@ evas_common_pipe_flush(RGBA_Image *im)
    int i;
 
    if (!im->pipe) return;
+
+#ifndef EVAS_FRAME_QUEUING
+
 #ifdef BUILD_PTHREAD
    if (thread_num > 1)
      {
-       /* sync worker threads */
-       pthread_barrier_wait(&(thbarrier[1]));
+            /* sync worker threads */
+        pthread_barrier_wait(&(thbarrier[1]));
      }
    else
 #endif
      {
-       /* process pipe - 1 thead */
-       for (p = im->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
-         {
-            for (i = 0; i < p->op_num; i++)
-              {
-                 if (p->op[i].op_func)
-                   p->op[i].op_func(im, &(p->op[i]), NULL);
-              }
-         }
+        /* process pipe - 1 thead */
+        for (p = im->pipe; p; p = (RGBA_Pipe *)(EINA_INLIST_GET(p))->next)
+          {
+             for (i = 0; i < p->op_num; i++)
+               {
+                  if (p->op[i].op_func)
+                    {
+                       p->op[i].op_func(im, &(p->op[i]), NULL);
+                    }
+               }
+          }
      }
+#endif /* !EVAS_FRAME_QUEUING */
    evas_common_cpu_end_opt();
    evas_common_pipe_free(im);
 }
@@ -200,14 +1008,16 @@ evas_common_pipe_free(RGBA_Image *im)
    /* free pipe */
    while (im->pipe)
      {
-       p = im->pipe;
-       for (i = 0; i < p->op_num; i++)
-         {
-            if (p->op[i].free_func)
-              p->op[i].free_func(&(p->op[i]));
-         }
-       im->pipe = (RGBA_Pipe *)eina_inlist_remove(EINA_INLIST_GET(im->pipe), EINA_INLIST_GET(p));
-       free(p);
+        p = im->pipe;
+        for (i = 0; i < p->op_num; i++)
+          {
+             if (p->op[i].free_func)
+               {
+                  p->op[i].free_func(&(p->op[i]));
+               }
+          }
+        im->pipe = (RGBA_Pipe *)eina_inlist_remove(EINA_INLIST_GET(im->pipe), EINA_INLIST_GET(p));
+        free(p);
      }
 }
 
@@ -220,27 +1030,29 @@ evas_common_pipe_rectangle_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
-       evas_common_rectangle_draw(dst, &(context),
-                                  op->op.rect.x, op->op.rect.y,
-                                  op->op.rect.w, op->op.rect.h);
+        evas_common_rectangle_draw(dst, &(context),
+               op->op.rect.x, op->op.rect.y,
+               op->op.rect.w, op->op.rect.h);
      }
    else
-     evas_common_rectangle_draw(dst, &(op->context),
-                               op->op.rect.x, op->op.rect.y,
-                               op->op.rect.w, op->op.rect.h);
+     {
+        evas_common_rectangle_draw(dst, &(op->context),
+               op->op.rect.x, op->op.rect.y,
+               op->op.rect.w, op->op.rect.h);
+     }
 }
 
 EAPI void
 evas_common_pipe_rectangle_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                               int x, int y, int w, int h)
+            int x, int y, int w, int h)
 {
    RGBA_Pipe_Op *op;
 
@@ -262,27 +1074,29 @@ evas_common_pipe_line_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
-       evas_common_line_draw(dst, &(context),
-                             op->op.line.x0, op->op.line.y0,
-                             op->op.line.x1, op->op.line.y1);
+        evas_common_line_draw(dst, &(context),
+               op->op.line.x0, op->op.line.y0,
+               op->op.line.x1, op->op.line.y1);
      }
    else
-     evas_common_line_draw(dst, &(op->context),
-                          op->op.line.x0, op->op.line.y0,
-                          op->op.line.x1, op->op.line.y1);
+     {
+        evas_common_line_draw(dst, &(op->context),
+               op->op.line.x0, op->op.line.y0,
+               op->op.line.x1, op->op.line.y1);
+     }
 }
 
 EAPI void
 evas_common_pipe_line_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                          int x0, int y0, int x1, int y1)
+            int x0, int y0, int x1, int y1)
 {
    RGBA_Pipe_Op *op;
 
@@ -305,10 +1119,10 @@ evas_common_pipe_op_poly_free(RGBA_Pipe_Op *op)
 
    while (op->op.poly.points)
      {
-       p = op->op.poly.points;
-       op->op.poly.points = (RGBA_Polygon_Point *)eina_inlist_remove(EINA_INLIST_GET(op->op.poly.points),
-                                                                     EINA_INLIST_GET(p));
-       free(p);
+        p = op->op.poly.points;
+        op->op.poly.points = (RGBA_Polygon_Point *)eina_inlist_remove(EINA_INLIST_GET(op->op.poly.points),
+                                                      EINA_INLIST_GET(p));
+        free(p);
      }
    evas_common_pipe_op_free(op);
 }
@@ -318,25 +1132,27 @@ evas_common_pipe_poly_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Threa
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
-       evas_common_polygon_draw(dst, &(context),
-                                op->op.poly.points, 0, 0);
+        evas_common_polygon_draw(dst, &(context),
+                     op->op.poly.points, 0, 0);
      }
    else
-     evas_common_polygon_draw(dst, &(op->context),
-                             op->op.poly.points, 0, 0);
+     {
+        evas_common_polygon_draw(dst, &(op->context),
+                     op->op.poly.points, 0, 0);
+     }
 }
 
 EAPI void
 evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                          RGBA_Polygon_Point *points, int x, int y)
+               RGBA_Polygon_Point *points, int x, int y)
 {
    RGBA_Pipe_Op *op;
    RGBA_Polygon_Point *pts = NULL, *p, *pp;
@@ -347,13 +1163,13 @@ evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    /* FIXME: copy points - maybe we should refcount? */
    for (p = points; p; p = (RGBA_Polygon_Point *)(EINA_INLIST_GET(p))->next)
      {
-       pp = calloc(1, sizeof(RGBA_Polygon_Point));
-       if (pp)
-         {
-            pp->x = p->x + x;
-            pp->y = p->y + y;
-            pts = (RGBA_Polygon_Point *)eina_inlist_append(EINA_INLIST_GET(pts), EINA_INLIST_GET(pp));
-         }
+        pp = calloc(1, sizeof(RGBA_Polygon_Point));
+        if (pp)
+          {
+             pp->x = p->x + x;
+             pp->y = p->y + y;
+             pts = (RGBA_Polygon_Point *)eina_inlist_append(EINA_INLIST_GET(pts), EINA_INLIST_GET(pp));
+          }
      }
    op->op.poly.points = pts;
    op->op_func = evas_common_pipe_poly_draw_do;
@@ -365,38 +1181,65 @@ evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
 static void
 evas_common_pipe_op_grad_free(RGBA_Pipe_Op *op)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(op->op.grad.grad->ref_fq_del);
+   op->op.grad.grad->ref_fq[1]++;
+   LKU(op->op.grad.grad->ref_fq_del);
+   pthread_cond_signal(&(op->op.grad.grad->cond_fq_del)); 
+#else
    evas_common_gradient_free(op->op.grad.grad);
+#endif
    evas_common_pipe_op_free(op);
 }
 
+#ifdef EVAS_FRAME_QUEUING
+EAPI void
+evas_common_pipe_op_grad_flush(RGBA_Gradient *gr)
+{
+   if (! evas_common_frameq_enabled())
+      return;
+
+   LKL(gr->ref_fq_add);
+   LKL(gr->ref_fq_del);
+
+   while (gr->ref_fq[0] != gr->ref_fq[1])
+      pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
+
+   LKU(gr->ref_fq_del);
+   LKU(gr->ref_fq_add);
+}
+#endif
+
 static void
 evas_common_pipe_grad_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
-       evas_common_gradient_draw(dst, &(context),
-                                 op->op.grad.x, op->op.grad.y,
-                                 op->op.grad.w, op->op.grad.h,
-                                 op->op.grad.grad);
+        evas_common_gradient_draw(dst, &(context),
+                  op->op.grad.x, op->op.grad.y,
+                  op->op.grad.w, op->op.grad.h,
+                  op->op.grad.grad);
      }
    else
-     evas_common_gradient_draw(dst, &(op->context),
-                              op->op.grad.x, op->op.grad.y,
-                              op->op.grad.w, op->op.grad.h,
-                              op->op.grad.grad);
+     {
+        evas_common_gradient_draw(dst, &(op->context),
+                  op->op.grad.x, op->op.grad.y,
+                  op->op.grad.w, op->op.grad.h,
+                  op->op.grad.grad);
+     }
 }
 
 EAPI void
 evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                          int x, int y, int w, int h, RGBA_Gradient *gr)
+            int x, int y, int w, int h, RGBA_Gradient *gr)
 {
    RGBA_Pipe_Op *op;
 
@@ -407,7 +1250,13 @@ evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    op->op.grad.y = y;
    op->op.grad.w = w;
    op->op.grad.h = h;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(gr->ref_fq_add);
+   gr->ref_fq[0]++;
+   LKU(gr->ref_fq_add);
+#else
    gr->references++;
+#endif
    op->op.grad.grad = gr;
    op->op_func = evas_common_pipe_grad_draw_do;
    op->free_func = evas_common_pipe_op_grad_free;
@@ -418,38 +1267,65 @@ evas_common_pipe_grad_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
 static void
 evas_common_pipe_op_grad2_free(RGBA_Pipe_Op *op)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(op->op.grad2.grad->ref_fq_del);
+   op->op.grad2.grad->ref_fq[1]++;
+   LKU(op->op.grad2.grad->ref_fq_del);
+   pthread_cond_signal(&(op->op.grad2.grad->cond_fq_del)); 
+#else
    evas_common_gradient2_free(op->op.grad2.grad);
+#endif
    evas_common_pipe_op_free(op);
 }
 
+#ifdef EVAS_FRAME_QUEUING
+EAPI void
+evas_common_pipe_op_grad2_flush(RGBA_Gradient2 *gr)
+{
+   if (! evas_common_frameq_enabled())
+      return;
+
+   LKL(gr->ref_fq_add);
+   LKL(gr->ref_fq_del);
+
+   while (gr->ref_fq[0] != gr->ref_fq[1])
+      pthread_cond_wait(&(gr->cond_fq_del), &(gr->ref_fq_del));
+
+   LKU(gr->ref_fq_del);
+   LKU(gr->ref_fq_add);
+}
+#endif
+
 static void
 evas_common_pipe_grad2_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
        
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else  
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif 
-       evas_common_gradient2_draw(dst, &(context),
-                                 op->op.grad2.x, op->op.grad2.y,
-                                 op->op.grad2.w, op->op.grad2.h,
-                                 op->op.grad2.grad);
+        evas_common_gradient2_draw(dst, &(context),
+               op->op.grad2.x, op->op.grad2.y,
+               op->op.grad2.w, op->op.grad2.h,
+               op->op.grad2.grad);
      }
    else
-     evas_common_gradient2_draw(dst, &(op->context),
-                              op->op.grad2.x, op->op.grad2.y,
-                              op->op.grad2.w, op->op.grad2.h,
-                              op->op.grad2.grad);
+     {
+        evas_common_gradient2_draw(dst, &(op->context),
+               op->op.grad2.x, op->op.grad2.y,
+               op->op.grad2.w, op->op.grad2.h,
+               op->op.grad2.grad);
+     }
 }
 
 EAPI void
 evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                          int x, int y, int w, int h, RGBA_Gradient2 *gr)
+            int x, int y, int w, int h, RGBA_Gradient2 *gr)
 {
    RGBA_Pipe_Op *op;
 
@@ -460,7 +1336,13 @@ evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    op->op.grad2.y = y;
    op->op.grad2.w = w;
    op->op.grad2.h = h;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(gr->ref_fq_add);
+   gr->ref_fq[0]++;
+   LKU(gr->ref_fq_add);
+#else
    gr->references++;
+#endif
    op->op.grad2.grad = gr;
    op->op_func = evas_common_pipe_grad2_draw_do;
    op->free_func = evas_common_pipe_op_grad2_free;
@@ -471,37 +1353,65 @@ evas_common_pipe_grad2_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
 static void
 evas_common_pipe_op_text_free(RGBA_Pipe_Op *op)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(op->op.text.font->ref_fq_del);
+   op->op.text.font->ref_fq[1]++;
+   LKU(op->op.text.font->ref_fq_del);
+   pthread_cond_signal(&(op->op.text.font->cond_fq_del));
+#else
    evas_common_font_free(op->op.text.font);
+#endif
    free(op->op.text.text);
    evas_common_pipe_op_free(op);
 }
 
+#ifdef EVAS_FRAME_QUEUING
+/* flush all op using @fn */
+EAPI void
+evas_common_pipe_op_text_flush(RGBA_Font *fn)
+{
+   if (! evas_common_frameq_enabled())
+      return;
+
+   LKL(fn->ref_fq_add);
+   LKL(fn->ref_fq_del);
+
+   while (fn->ref_fq[0] != fn->ref_fq[1])
+      pthread_cond_wait(&(fn->cond_fq_del), &(fn->ref_fq_del));
+
+   LKU(fn->ref_fq_del);
+   LKU(fn->ref_fq_add);
+}
+#endif
+
 static void
 evas_common_pipe_text_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
-       evas_common_font_draw(dst, &(context),
-                             op->op.text.font, op->op.text.x, op->op.text.y,
-                             op->op.text.text);
+        evas_common_font_draw(dst, &(context),
+                  op->op.text.font, op->op.text.x, op->op.text.y,
+                  op->op.text.text);
      }
    else
-     evas_common_font_draw(dst, &(op->context),
-                          op->op.text.font, op->op.text.x, op->op.text.y,
-                          op->op.text.text);
+     {
+        evas_common_font_draw(dst, &(op->context),
+                  op->op.text.font, op->op.text.x, op->op.text.y,
+                  op->op.text.text);
+     }
 }
 
 EAPI void
 evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
-                          RGBA_Font *fn, int x, int y, const char *text)
+               RGBA_Font *fn, int x, int y, const char *text)
 {
    RGBA_Pipe_Op *op;
 
@@ -511,7 +1421,13 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
    op->op.text.x = x;
    op->op.text.y = y;
    op->op.text.text = strdup(text);
+#ifdef EVAS_FRAME_QUEUING
+   LKL(fn->ref_fq_add);
+   fn->ref_fq[0]++;
+   LKU(fn->ref_fq_add);
+#else
    fn->references++;
+#endif
    op->op.text.font = fn;
    op->op_func = evas_common_pipe_text_draw_do;
    op->free_func = evas_common_pipe_op_text_free;
@@ -522,24 +1438,51 @@ evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc,
 static void
 evas_common_pipe_op_image_free(RGBA_Pipe_Op *op)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(op->op.image.src->ref_fq_del);
+   op->op.image.src->ref_fq[1]++;
+   LKU(op->op.image.src->ref_fq_del);
+   pthread_cond_signal(&(op->op.image.src->cond_fq_del)); 
+#else
    op->op.image.src->ref--;
    if (op->op.image.src->ref == 0)
-     evas_cache_image_drop(&op->op.image.src->cache_entry);
+     {
+        evas_cache_image_drop(&op->op.image.src->cache_entry);
+     }
+#endif
    evas_common_pipe_op_free(op);
 }
 
+#ifdef EVAS_FRAME_QUEUING
+EAPI void
+evas_common_pipe_op_image_flush(RGBA_Image *im)
+{
+   if (! evas_common_frameq_enabled())
+      return;
+   
+   LKL(im->ref_fq_add);
+   LKL(im->ref_fq_del);
+
+   while (im->ref_fq[0] != im->ref_fq[1])
+      pthread_cond_wait(&(im->cond_fq_del), &(im->ref_fq_del));
+
+   LKU(im->ref_fq_del);
+   LKU(im->ref_fq_add);
+}
+#endif
+
 static void
 evas_common_pipe_image_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thread_Info *info)
 {
    if (info)
      {
-       RGBA_Draw_Context context;
+        RGBA_Draw_Context context;
 
-       memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
+        memcpy(&(context), &(op->context), sizeof(RGBA_Draw_Context));
 #ifdef EVAS_SLI
-       evas_common_draw_context_set_sli(&(context), info->y, info->h);
+        evas_common_draw_context_set_sli(&(context), info->y, info->h);
 #else
-       evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
+        evas_common_draw_context_clip_clip(&(context), info->x, info->y, info->w, info->h);
 #endif
 
 #ifdef SCALECACHE
@@ -555,67 +1498,75 @@ evas_common_pipe_image_draw_do(RGBA_Image *dst, RGBA_Pipe_Op *op, RGBA_Pipe_Thre
                                              op->op.image.dw,
                                              op->op.image.dh);
 #else
-       if (op->op.image.smooth)
-         evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
-                                                      dst, &(context),
-                                                      op->op.image.sx,
-                                                      op->op.image.sy,
-                                                      op->op.image.sw,
-                                                      op->op.image.sh,
-                                                      op->op.image.dx,
-                                                      op->op.image.dy,
-                                                      op->op.image.dw,
-                                                      op->op.image.dh);
-       else
-         evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
-                                                      dst, &(context),
-                                                      op->op.image.sx,
-                                                      op->op.image.sy,
-                                                      op->op.image.sw,
-                                                      op->op.image.sh,
-                                                      op->op.image.dx,
-                                                      op->op.image.dy,
-                                                      op->op.image.dw,
-                                                      op->op.image.dh);
+        if (op->op.image.smooth)
+          {
+             evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
+                           dst, &(context),
+                           op->op.image.sx,
+                           op->op.image.sy,
+                           op->op.image.sw,
+                           op->op.image.sh,
+                           op->op.image.dx,
+                           op->op.image.dy,
+                           op->op.image.dw,
+                           op->op.image.dh);
+          }
+        else
+          {
+             evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
+                           dst, &(context),
+                           op->op.image.sx,
+                           op->op.image.sy,
+                           op->op.image.sw,
+                           op->op.image.sh,
+                           op->op.image.dx,
+                           op->op.image.dy,
+                           op->op.image.dw,
+                           op->op.image.dh);
+                   }
 #endif
      }
    else
      {
 #ifdef SCALECACHE
         evas_common_rgba_image_scalecache_do(op->op.image.src,
-                                             dst, &(op->context),
-                                             op->op.image.smooth,
-                                             op->op.image.sx,
-                                             op->op.image.sy,
-                                             op->op.image.sw,
-                                             op->op.image.sh,
-                                             op->op.image.dx,
-                                             op->op.image.dy,
-                                             op->op.image.dw,
-                                             op->op.image.dh);
+                           dst, &(op->context),
+                           op->op.image.smooth,
+                           op->op.image.sx,
+                           op->op.image.sy,
+                           op->op.image.sw,
+                           op->op.image.sh,
+                           op->op.image.dx,
+                           op->op.image.dy,
+                           op->op.image.dw,
+                           op->op.image.dh);
 #else
-       if (op->op.image.smooth)
-         evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
-                                                      dst, &(op->context),
-                                                      op->op.image.sx,
-                                                      op->op.image.sy,
-                                                      op->op.image.sw,
-                                                      op->op.image.sh,
-                                                      op->op.image.dx,
-                                                      op->op.image.dy,
-                                                      op->op.image.dw,
-                                                      op->op.image.dh);
-       else
-         evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
-                                                      dst, &(op->context),
-                                                      op->op.image.sx,
-                                                      op->op.image.sy,
-                                                      op->op.image.sw,
-                                                      op->op.image.sh,
-                                                      op->op.image.dx,
-                                                      op->op.image.dy,
-                                                      op->op.image.dw,
-                                                      op->op.image.dh);
+        if (op->op.image.smooth)
+          {
+             evas_common_scale_rgba_in_to_out_clip_smooth(op->op.image.src,
+                                 dst, &(op->context),
+                                 op->op.image.sx,
+                                 op->op.image.sy,
+                                 op->op.image.sw,
+                                 op->op.image.sh,
+                                 op->op.image.dx,
+                                 op->op.image.dy,
+                                 op->op.image.dw,
+                                 op->op.image.dh);
+          }
+        else
+                {
+             evas_common_scale_rgba_in_to_out_clip_sample(op->op.image.src,
+                                 dst, &(op->context),
+                                 op->op.image.sx,
+                                 op->op.image.sy,
+                                 op->op.image.sw,
+                                 op->op.image.sh,
+                                 op->op.image.dx,
+                                 op->op.image.dy,
+                                 op->op.image.dw,
+                                 op->op.image.dh);
+           }
 #endif
      }
 }
@@ -643,21 +1594,44 @@ evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst,
    op->op.image.dy = dst_region_y;
    op->op.image.dw = dst_region_w;
    op->op.image.dh = dst_region_h;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(src->ref_fq_add);
+   src->ref_fq[0]++;
+   LKU(src->ref_fq_add);
+#else
    src->ref++;
+#endif
    op->op.image.src = src;
    op->op_func = evas_common_pipe_image_draw_do;
    op->free_func = evas_common_pipe_op_image_free;
    evas_common_pipe_draw_context_copy(dc, op);
 
+#ifdef EVAS_FRAME_QUEUING
+   /* laod every src image here.
+    * frameq utilize all cpu cores already by worker threads
+    * so another threads and barrier waiting can't be of any benefit.
+    * therefore, not instantiate loader threads.
+    */
+   if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+      evas_cache_image_load_data(&src->cache_entry);
+   evas_common_image_colorspace_normalize(src);
+#else
    evas_common_pipe_image_load(src);
+#endif
 }
 
 static void
 evas_common_pipe_op_map4_free(RGBA_Pipe_Op *op)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(op->op.image.src->ref_fq_del);
+   op->op.image.src->ref_fq[1]++;
+   LKU(op->op.image.src->ref_fq_del);
+#else
    op->op.map4.src->ref--;
    if (op->op.map4.src->ref == 0)
      evas_cache_image_drop(&op->op.map4.src->cache_entry);
+#endif
    free(op->op.map4.p);
    evas_common_pipe_op_free(op);
 }
@@ -712,14 +1686,31 @@ evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
 
    op->op.map4.smooth = smooth;
    op->op.map4.level = level;
+#ifdef EVAS_FRAME_QUEUING
+   LKL(src->ref_fq_add);
+   src->ref_fq[0]++;
+   LKU(src->ref_fq_add);
+#else
    src->ref++;
+#endif
    op->op.map4.src = src;
    op->op.map4.p = pts_copy;
    op->op_func = evas_common_pipe_map4_draw_do;
    op->free_func = evas_common_pipe_op_map4_free;
    evas_common_pipe_draw_context_copy(dc, op);
 
+#ifdef EVAS_FRAME_QUEUING
+   /* laod every src image here.
+    * frameq utilize all cpu cores already by worker threads
+    * so another threads and barrier waiting can't be of any benefit.
+    * therefore, not instantiate loader threads.
+    */
+   if (src->cache_entry.space == EVAS_COLORSPACE_ARGB8888)
+      evas_cache_image_load_data(&src->cache_entry);
+   evas_common_image_colorspace_normalize(src);
+#else
    evas_common_pipe_image_load(src);
+#endif
 }
 
 static void
@@ -908,4 +1899,5 @@ evas_common_pipe_map4_begin(RGBA_Image *root)
 
   evas_common_pipe_map4_render(root);
 }
+
 #endif
index 77c5dd3..651582c 100644 (file)
@@ -1,6 +1,82 @@
 #ifndef _EVAS_PIPE_H
 #define _EVAS_PIPE_H
 
+#ifdef BUILD_PTHREAD
+typedef struct _Thinfo
+{
+   int                    thread_num;
+   pthread_t              thread_id;
+   pthread_barrier_t     *barrier;
+   RGBA_Pipe_Thread_Info *info;
+#ifdef EVAS_FRAME_QUEUING
+   void                 *fq_info;
+#endif
+} Thinfo;
+#endif
+
+#ifdef EVAS_FRAME_QUEUING
+struct _Evas_Surface
+{
+   EINA_INLIST;
+   RGBA_Image *im;
+   int x, y, w, h;
+   int dontpush; // dont push the surface out after drawing done
+};
+typedef struct _Evas_Surface Evas_Surface;
+
+struct _Evas_Frame
+{
+   EINA_INLIST;
+   Evas_Surface *surfaces;
+   void *data;
+   int in_process;
+   int ready;
+   int dont_schedule;
+   struct timeval ready_time;
+
+   void (*output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h);
+   void (*output_flush)  (void *data);
+   void (*output_set_priv)(void *data, void *cur, void *prev);
+};
+typedef struct _Evas_Frame Evas_Frame;
+
+
+struct _Evas_FrameQ
+{
+   int initialised;
+   Evas_Frame   *frames;
+   pthread_cond_t cond_new;
+   pthread_cond_t cond_ready;
+   pthread_cond_t cond_done;
+   LK(mutex);
+
+   int               thread_num;
+   Thinfo          thinfo[TH_MAX];
+   int            frameq_sz;
+
+   Evas_Frame *cur_frame;       
+};
+typedef struct _Evas_FrameQ Evas_FrameQ;
+#define FRAMEQ_SZ_PER_THREAD 2
+
+struct _Evas_Frameq_Thread_Info
+{
+   Evas_FrameQ *frameq;
+};
+typedef struct _Evas_Frameq_Thread_Info Evas_Frameq_Thread_Info;
+
+EAPI Evas_Surface *evas_common_frameq_new_surface (void *surface, int x, int y, int w, int h);
+EAPI void evas_common_frameq_add_surface(Evas_Surface *surface);
+EAPI void evas_common_frameq_set_frame_data(void *data, 
+     void (*fn_output_redraws_next_update_push) (void *data, void *surface, int x, int y, int w, int h),
+     void (*fn_output_flush)  (void *data),
+     void (*fn_output_set_priv)(void *data, void *cur, void *prev));
+EAPI void evas_common_frameq_prepare_frame();
+EAPI void evas_common_frameq_ready_frame();
+EAPI void evas_common_frameq_init();
+EAPI void evas_common_frameq_flush();
+EAPI void evas_common_frameq_flush_ready ();
+#endif
 
 /* image rendering pipelines... new optional system - non-immediate and
  * threadable
@@ -19,4 +95,11 @@ EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
                                     RGBA_Draw_Context *dc, RGBA_Map_Point *p,
                                     int smooth, int level);
 
+#ifdef EVAS_FRAME_QUEUING
+EAPI void evas_common_pipe_op_grad_flush(RGBA_Gradient *gr);
+EAPI void evas_common_pipe_op_grad2_flush(RGBA_Gradient2 *gr);
+EAPI void evas_common_pipe_op_text_flush(RGBA_Font *fn);
+EAPI void evas_common_pipe_op_image_flush(RGBA_Image *im);
+#endif
+
 #endif /* _EVAS_PIPE_H */
index e00f4e7..9d8cfbc 100644 (file)
@@ -408,8 +408,9 @@ evas_module_unload(Evas_Module *em)
    if (em->definition == NULL)
      return ;
 
-   em->definition->func.close(em);
-   em->loaded = 0;
+// for now lets not unload modules - they may still be in use.   
+//   em->definition->func.close(em);
+//   em->loaded = 0;
 
 #ifdef BUILD_ASYNC_PRELOAD
    LKD(em->lock);
index dff7224..d2669ca 100644 (file)
@@ -136,7 +136,14 @@ extern EAPI int _evas_log_dom_global;
 # include <pthread.h>
 # include <sched.h>
 # define LK(x)  pthread_mutex_t x
+#ifndef EVAS_FRAME_QUEUING
 # define LKI(x) pthread_mutex_init(&(x), NULL);
+#else
+# define LKI(x) {pthread_mutexattr_t    attr;\
+         pthread_mutexattr_init(&attr); \
+         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);    \
+         pthread_mutex_init(&(x), &attr);}
+#endif
 # define LKD(x) pthread_mutex_destroy(&(x));
 # define LKL(x) pthread_mutex_lock(&(x));
 # define LKT(x) pthread_mutex_trylock(&(x));
@@ -145,6 +152,15 @@ extern EAPI int _evas_log_dom_global;
 # define THI(x) int x
 # define TH_MAX 8
 
+/* for rwlocks */
+#define RWLK(x) pthread_rwlock_t x
+#define RWLKI(x) pthread_rwlock_init(&(x), NULL);
+#define RWLKD(x) pthread_rwlock_destroy(&(x));
+#define RDLKL(x) pthread_rwlock_rdlock(&(x));
+#define WRLKL(x) pthread_rwlock_wrlock(&(x));
+#define RWLKU(x) pthread_rwlock_unlock(&(x));
+
+
 // even though in theory having every Nth rendered line done by a different
 // thread might even out load across threads - it actually slows things down.
 //#define EVAS_SLI 1
@@ -159,6 +175,15 @@ extern EAPI int _evas_log_dom_global;
 # define TH(x)
 # define THI(x)
 # define TH_MAX 0
+
+/* for rwlocks */
+#define RWLK(x) 
+#define RWLKI(x) 
+#define RWLKD(x)
+#define RDLKL(x) 
+#define WRLKL(x)
+#define RWLKU(x)
+
 #endif
 
 #ifdef HAVE_ALLOCA_H
@@ -482,6 +507,7 @@ struct _RGBA_Image_Loadopts
 struct _Image_Entry_Flags
 {
    Eina_Bool loaded       : 1;
+   Eina_Bool in_progress  : 1;
    Eina_Bool dirty        : 1;
    Eina_Bool activ        : 1;
    Eina_Bool need_data    : 1;
@@ -521,6 +547,9 @@ struct _Image_Entry
    time_t                 laststat;
 
    int                    references;
+#ifdef EVAS_FRAME_QUEUING
+   LK(lock_references);   // needed for accessing references
+#endif
 
    unsigned char          scale;
 
@@ -630,6 +659,8 @@ struct _RGBA_Draw_Context
 };
 
 #ifdef BUILD_PIPE_RENDER
+#include "../engines/common/evas_map_image.h"
+
 struct _RGBA_Pipe_Op
 {
    RGBA_Draw_Context         context;
@@ -707,6 +738,12 @@ struct _RGBA_Image
    void                *extended_info;
 #ifdef BUILD_PIPE_RENDER
    RGBA_Pipe           *pipe;
+#ifdef EVAS_FRAME_QUEUING
+   LK(ref_fq_add);
+   LK(ref_fq_del);
+   pthread_cond_t cond_fq_del;
+   int ref_fq[2];              // ref_fq[0] is for addition, ref_fq[1] is for deletion
+#endif
 #endif
    int                  ref;
 
@@ -790,6 +827,13 @@ struct _RGBA_Gradient
      } type;
 
    int references;
+#ifdef EVAS_FRAME_QUEUING
+   LK(ref_fq_add);
+   LK(ref_fq_del);
+   pthread_cond_t cond_fq_del;
+   int ref_fq[2];      //ref_fq[0] is for addition,
+                         //ref_fq[1] is for deletion
+#endif
 
    Eina_Bool imported_data : 1;
    Eina_Bool has_alpha : 1;
@@ -847,6 +891,13 @@ struct _RGBA_Gradient2
      } type;
 
    int references;
+#ifdef EVAS_FRAME_QUEUING
+   LK(ref_fq_add);
+   LK(ref_fq_del);
+   pthread_cond_t cond_fq_del;
+   int ref_fq[2];      //ref_fq[0] is for addition,
+                         //ref_fq[1] is for deletion
+#endif
 
    Eina_Bool has_alpha : 1;
 };
@@ -922,6 +973,12 @@ struct _RGBA_Font
    Fash_Int *fash;
    unsigned char sizeok : 1;
    LK(lock);
+#ifdef EVAS_FRAME_QUEUING
+   LK(ref_fq_add);
+   LK(ref_fq_del);
+   pthread_cond_t cond_fq_del;
+   int ref_fq[2];              //ref_fq[0] is for addition, ref_fq[1] is for deletion
+#endif
 };
 
 struct _RGBA_Font_Int
index 0dfe709..a7e9f29 100644 (file)
@@ -1,6 +1,9 @@
 #include "evas_common.h"
 #include "evas_private.h"
 
+static Evas_Version _version = { VMAJ, VMIN, VMIC, VREV };
+EAPI Evas_Version *evas_version = &_version;
+
 int _evas_alloc_error = 0;
 static int _evas_debug_init = 0;
 static int _evas_debug_show = 0;
index 02dea14..e6d11d1 100644 (file)
@@ -31,6 +31,9 @@ struct _Evas_Engine_Info_Buffer
         void   (*free_update_region) (int x, int y, int w, int h, void *data);
       } func;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 1c6abc0..0add001 100644 (file)
@@ -126,6 +126,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Buffer));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index 3a7d64a..65503a0 100644 (file)
@@ -21,6 +21,9 @@ struct _Evas_Engine_Info_Cairo_X11
    } info;
    /* engine specific function calls to query stuff about the destination */
    /* engine (what visual & colormap & depth to use, performance info etc. */
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index df81a2f..36c834d 100644 (file)
@@ -267,6 +267,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Cairo_X11));
    if (!info) return NULL;
    info->magic.magic = rand();   
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index 05359a3..f9b7a9c 100644 (file)
@@ -27,6 +27,9 @@ struct _Evas_Engine_Info_Direct3D
       unsigned short height;
       unsigned char *mask;
    } *shape;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 8514f75..5fcd89d 100644 (file)
@@ -77,6 +77,7 @@ eng_info(Evas *e)
    if (!info) return NULL;
    info->magic.magic = rand();
    memset(&info->info, 0, sizeof(info->info));
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index f4177e1..a2e9d3a 100644 (file)
@@ -16,6 +16,9 @@ struct _Evas_Engine_Info_DirectFB
       IDirectFB                 *dfb;
       IDirectFBSurface          *surface;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 7166e42..b548237 100644 (file)
@@ -16,6 +16,9 @@ struct _Evas_Engine_Info_FB
       int refresh;
       int rotation;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 47386ba..a0b5e3d 100644 (file)
@@ -81,6 +81,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_FB));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index fb4348c..e9dfbeb 100644 (file)
@@ -139,7 +139,7 @@ struct _Evas_GL_Context
       Eina_Bool       clip : 1;
       struct {
          GLuint          cur_prog;
-         GLuint          cur_tex, cur_texum, cur_texv;
+         GLuint          cur_tex, cur_texu, cur_texv;
          int             render_op;
          int             cx, cy, cw, ch;
          Eina_Bool       smooth : 1;
@@ -286,6 +286,7 @@ void glerr(int err, const char *file, const char *func, int line, const char *op
 Evas_GL_Context  *evas_gl_common_context_new(void);
 void              evas_gl_common_context_free(Evas_GL_Context *gc);
 void              evas_gl_common_context_use(Evas_GL_Context *gc);
+void              evas_gl_common_context_newframe(Evas_GL_Context *gc);
 void              evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h, int rot);
 void              evas_gl_common_context_target_surface_set(Evas_GL_Context *gc, Evas_GL_Image *surface);
 
index e5a0d1b..098c8b3 100644 (file)
@@ -369,6 +369,8 @@ evas_gl_common_context_new(void)
    
    _evas_gl_common_context = gc;
 
+   gc->shader.render_op = EVAS_RENDER_BLEND;
+   
    if (!shared)
      {
         GLint linked;
@@ -597,12 +599,97 @@ evas_gl_common_context_free(Evas_GL_Context *gc)
 void
 evas_gl_common_context_use(Evas_GL_Context *gc)
 {
-//   if (_evas_gl_common_context == gc) return;
+   if (_evas_gl_common_context == gc) return;
    _evas_gl_common_context = gc;
    _evas_gl_common_viewport_set(gc);
 }
 
 void
+evas_gl_common_context_newframe(Evas_GL_Context *gc)
+{
+   gc->clip.x = 0;
+   gc->clip.y = 0;
+   gc->clip.w = 0;
+   gc->clip.h = 0;
+   gc->clip.active = 0;
+   gc->shader.surface = NULL;
+   gc->shader.cur_prog = 0;
+   gc->shader.cur_tex = 0;
+   gc->shader.cur_texu = 0;
+   gc->shader.cur_texv = 0;
+   gc->shader.render_op = EVAS_RENDER_BLEND;
+   gc->shader.cx = 0;
+   gc->shader.cy = 0;
+   gc->shader.cw = 0;
+   gc->shader.ch = 0;
+   gc->shader.smooth = 0;
+   gc->shader.blend = 0;
+   gc->shader.clip = 0;
+   gc->shader.current.cur_prog = 0;
+   gc->shader.current.cur_tex = 0;
+   gc->shader.current.cur_texu = 0;
+   gc->shader.current.cur_texv = 0;
+   gc->shader.current.render_op = 0;
+   gc->shader.current.cx = 0;
+   gc->shader.current.cy = 0;
+   gc->shader.current.cw = 0;
+   gc->shader.current.ch = 0;
+   gc->shader.current.smooth = 0;
+   gc->shader.current.blend = 0;
+   gc->shader.current.clip = 0;
+   gc->change.size = 1;
+   
+   glDisable(GL_SCISSOR_TEST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glScissor(0, 0, 0, 0);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   
+   glDisable(GL_DEPTH_TEST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glEnable(GL_DITHER);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glDisable(GL_BLEND);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   // no dest alpha
+//   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // dest alpha
+//   glBlendFunc(GL_SRC_ALPHA, GL_ONE); // ???
+   glDepthMask(GL_FALSE);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+        
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT
+   if (shared->info.anisotropic > 0.0)
+     {
+        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0);
+        GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+     }
+#endif
+   
+   glEnableVertexAttribArray(SHAD_VERTEX);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glEnableVertexAttribArray(SHAD_COLOR);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glUseProgram(gc->shader.cur_prog);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   
+   glActiveTexture(GL_TEXTURE0);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+   glBindTexture(GL_TEXTURE_2D, gc->shader.cur_tex);
+   GLERR(__FUNCTION__, __FILE__, __LINE__, "");
+
+   _evas_gl_common_viewport_set(gc);
+}
+
+void
 evas_gl_common_context_resize(Evas_GL_Context *gc, int w, int h, int rot)
 {
    if ((gc->w == w) && (gc->h == h) && (gc->rot == rot)) return;
index b1ec6f1..72be3ae 100644 (file)
@@ -443,6 +443,11 @@ evas_gl_common_image_draw(Evas_GL_Context *gc, Evas_GL_Image *im, int sx, int sy
      }
    
    _evas_gl_common_image_update(gc, im);
+   if (!im->tex)
+     {
+        evas_gl_common_rect_draw(gc, dx, dy, dw, dh);
+        return;
+     }
 
    if ((im->cs.space == EVAS_COLORSPACE_YCBCR422P601_PL) ||
        (im->cs.space == EVAS_COLORSPACE_YCBCR422P709_PL))
index c254fd0..a83496e 100644 (file)
@@ -20,6 +20,9 @@ struct _Evas_Engine_Info_GL_Glew
       HWND  window;
       int   depth;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 1fabf66..37b0f43 100644 (file)
@@ -20,6 +20,7 @@ eng_info(Evas *e __UNUSED__)
    info = calloc(1, sizeof(Evas_Engine_Info_GL_Glew));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
 }
 
index 2e0461c..7224f9c 100644 (file)
@@ -29,13 +29,16 @@ struct _Evas_Engine_Info_GL_X11
       Colormap  (*best_colormap_get) (Evas_Engine_Info_GL_X11 *einfo);
       int       (*best_depth_get)    (Evas_Engine_Info_GL_X11 *einfo);
    } func;
-   
+
    struct {
       void      (*pre_swap)          (void *data, Evas *e);
       void      (*post_swap)         (void *data, Evas *e);
       
       void       *data; // data for callback calls
    } callback;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
    
    unsigned char vsync : 1; // does nothing right now
    unsigned char indirect : 1; // use indirect rendering
index 72b39c3..e9d2484 100644 (file)
@@ -184,6 +184,7 @@ eng_info(Evas *e)
    info->func.best_visual_get = eng_best_visual_get;
    info->func.best_colormap_get = eng_best_colormap_get;
    info->func.best_depth_get = eng_best_depth_get;
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
@@ -405,19 +406,8 @@ eng_output_free(void *data)
      }
    if ((initted == 1) && (gl_wins == 0))
      {
-        evas_common_cpu_shutdown();
-        
-        evas_common_blend_shutdown();
         evas_common_image_shutdown();
-        evas_common_convert_shutdown();
-        evas_common_scale_shutdown();
-        evas_common_rectangle_shutdown();
-        evas_common_gradient_shutdown();
-        evas_common_polygon_shutdown();
-        evas_common_line_shutdown();
         evas_common_font_shutdown();
-        evas_common_draw_shutdown();
-        evas_common_tilebuf_shutdown();
         initted = 0;
      }
 }
@@ -503,9 +493,11 @@ eng_output_redraws_next_update_get(void *data, int *x, int *y, int *w, int *h, i
    Render_Engine *re;
 
    re = (Render_Engine *)data;
-   evas_gl_common_context_flush(re->win->gl_context);
    /* get the upate rect surface - return engine data as dummy */
    if (!re->win->draw.redraw) return NULL;
+   evas_gl_common_context_flush(re->win->gl_context);
+   eng_window_use(re->win);
+   evas_gl_common_context_newframe(re->win->gl_context);
    if (x) *x = re->win->draw.x1;
    if (y) *y = re->win->draw.y1;
    if (w) *w = re->win->draw.x2 - re->win->draw.x1 + 1;
index 2d0a3f6..b83dc87 100644 (file)
@@ -26,7 +26,6 @@
 #   include <X11/Xresource.h> // xres - dpi
 #endif
 # else
-#  include <GL/glx.h>
 #  include <X11/Xlib.h>
 #  include <X11/Xatom.h>
 #  include <X11/Xutil.h>
index abca922..0a277f4 100644 (file)
@@ -15,6 +15,9 @@ struct _Evas_Engine_Info_Quartz
    struct {
       CGContextRef context;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 #endif
index 6843702..160f043 100644 (file)
@@ -44,6 +44,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Quartz));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
 }
 
index 7c3d888..3c1547a 100644 (file)
@@ -23,6 +23,9 @@ struct _Evas_Engine_Info_Software_16_DDraw
 
       int                 rotation;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 6e2abb0..90f1162 100644 (file)
@@ -54,6 +54,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Software_16_DDraw));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index 20adccf..5a133fe 100644 (file)
@@ -17,6 +17,9 @@ struct _Evas_Engine_Info_SDL_16
     int                         noframe : 1;
     int                         alpha : 1;
   } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 #endif
index d9d45a5..e94b7c2 100644 (file)
@@ -26,6 +26,9 @@ struct _Evas_Engine_Info_Software_16_WinCE
       int   (*suspend) (int backend);
       int   (*resume)  (int backend);
    } func;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 886fa0f..b994a9a 100644 (file)
@@ -95,6 +95,7 @@ eng_info(Evas *e)
    info->magic.magic = rand();
    info->func.suspend = _suspend;
    info->func.resume = _resume;
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index 47885fa..9768f0a 100644 (file)
@@ -17,6 +17,9 @@ struct _Evas_Engine_Info_Software_16_X11
       Drawable  drawable;
       int rotation;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 32a88ba..7f753fc 100644 (file)
@@ -103,6 +103,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Software_16_X11));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index e06ef4e..9735bb7 100644 (file)
@@ -21,6 +21,9 @@ struct _Evas_Engine_Info_Software_DDraw
       int          rotation;
       unsigned int fullscreen : 1;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 426f949..114f586 100644 (file)
@@ -97,6 +97,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Software_DDraw));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index a95b07e..032ec8d 100644 (file)
@@ -23,6 +23,9 @@ struct _Evas_Engine_Info_Software_Gdi
       unsigned int layered    : 1;
       unsigned int fullscreen : 1;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 
index 77671be..a28185e 100644 (file)
@@ -150,7 +150,11 @@ static void
 eng_rectangle_draw(void *data __UNUSED__, void *context, void *surface, int x, int y, int w, int h)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_rectangle_draw(surface, context, x, y, w, h);
    else
 #endif
@@ -164,8 +168,12 @@ static void
 eng_line_draw(void *data __UNUSED__, void *context, void *surface, int x1, int y1, int x2, int y2)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
-     evas_common_pipe_line_draw(surface, context, x1, y1, x2, y2);
+   if ((cpunum > 1)
+ #ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
+    evas_common_pipe_line_draw(surface, context, x1, y1, x2, y2);
    else
 #endif   
      {
@@ -190,7 +198,11 @@ static void
 eng_polygon_draw(void *data __UNUSED__, void *context, void *surface, void *polygon, int x, int y)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_poly_draw(surface, context, polygon, x, y);
    else
 #endif
@@ -284,7 +296,11 @@ static void
 eng_gradient2_linear_draw(void *data __UNUSED__, void *context, void *surface, void *linear_gradient, int x, int y, int w, int h)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_grad2_draw(surface, context, x, y, w, h, linear_gradient);
    else
 #endif
@@ -351,7 +367,11 @@ static void
 eng_gradient2_radial_draw(void *data __UNUSED__, void *context, void *surface, void *radial_gradient, int x, int y, int w, int h)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_grad2_draw(surface, context, x, y, w, h, radial_gradient);
    else
 #endif
@@ -484,7 +504,11 @@ static void
 eng_gradient_draw(void *data __UNUSED__, void *context, void *surface, void *gradient, int x, int y, int w, int h)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_grad_draw(surface, context, x, y, w, h, gradient);
    else
 #endif   
@@ -745,7 +769,11 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
    if (!image) return;
    im = image;
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      {
         evas_common_rgba_image_scalecache_prepare(im, surface, context, smooth,
                                                   src_x, src_y, src_w, src_h,
@@ -810,7 +838,7 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i
        (p[3].col == 0xffffffff))
      {
         int dx, dy, dw, dh;
-        
+
         dx = p[0].x >> FP;
         dy = p[0].y >> FP;
         dw = (p[2].x >> FP) - dx;
@@ -823,13 +851,18 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i
    else
      {
 #ifdef BUILD_PIPE_RENDER
-        if (cpunum > 1)
+        if ((cpunum > 1)
+# ifdef EVAS_FRAME_QUEUING
+       && evas_common_frameq_enabled()
+# endif
+        )
           evas_common_pipe_map4_draw(im, surface, context, p, smooth, level);
         else
 #endif
           evas_common_map4_rgba(im, surface, context, p, smooth, level);
      }
    evas_common_cpu_end_opt();
+
 }
 
 static void *
@@ -1000,7 +1033,11 @@ static void
 eng_font_draw(void *data __UNUSED__, void *context, void *surface, void *font, int x, int y, int w __UNUSED__, int h __UNUSED__, int ow __UNUSED__, int oh __UNUSED__, const char *text)
 {
 #ifdef BUILD_PIPE_RENDER
-   if (cpunum > 1)
+   if ((cpunum > 1)
+#ifdef EVAS_FRAME_QUEUING
+        && evas_common_frameq_enabled()
+#endif
+        )
      evas_common_pipe_text_draw(surface, context, font, x, y, text);
    else
 #endif   
index 5b863b0..6878b05 100644 (file)
@@ -25,6 +25,9 @@ struct _Evas_Engine_Info_Software_Qtopia
       QWidget *target;
       int      rotation;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 89b139a..bee5a80 100644 (file)
@@ -90,6 +90,7 @@ eng_info(Evas *e)
    info = calloc(1, sizeof(Evas_Engine_Info_Software_Qtopia));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
    e = NULL;
 }
index 71efa8a..3cce6ec 100644 (file)
@@ -18,6 +18,9 @@ struct _Evas_Engine_Info_SDL
      int                       noframe : 1;
      int                        alpha : 1;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
 
index 6b0f692..de6da96 100644 (file)
@@ -53,6 +53,8 @@ struct _Evas_Engine_Info_Software_X11
    } func;
 
    int mask_changed;
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 
 #endif
index 2788fc6..0812e4c 100644 (file)
@@ -84,7 +84,10 @@ struct _Render_Engine
       int        dpi; // xres - dpi
    } xr; // xres - dpi
 #endif
-   
+#ifdef EVAS_FRAME_QUEUING
+   Evas_Engine_Render_Mode render_mode;
+#endif
+
    void        (*outbuf_free)(Outbuf *ob);
    void        (*outbuf_reconfigure)(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth);
    int         (*outbuf_get_rot)(Outbuf *ob);
@@ -94,6 +97,9 @@ struct _Render_Engine
    void        (*outbuf_flush)(Outbuf *ob);
    void        (*outbuf_idle_flush)(Outbuf *ob);
    Eina_Bool   (*outbuf_alpha_get)(Outbuf *ob);
+#ifdef EVAS_FRAME_QUEUING
+   void                (*outbuf_set_priv)(Outbuf *ob, void *cur, void *prev);
+#endif
 };
 
 /* prototypes we will use here */
@@ -441,6 +447,7 @@ eng_info(Evas *e __UNUSED__)
    info->func.best_visual_get = _best_visual_get;
    info->func.best_colormap_get = _best_colormap_get;
    info->func.best_depth_get = _best_depth_get;
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
 }
 
@@ -502,6 +509,10 @@ eng_setup(Evas *e, void *in)
              re->outbuf_flush = evas_software_xlib_outbuf_flush;
              re->outbuf_idle_flush = evas_software_xlib_outbuf_idle_flush;
             re->outbuf_alpha_get = evas_software_xlib_outbuf_alpha_get;
+#ifdef EVAS_FRAME_QUEUING
+             re->outbuf_set_priv = evas_software_xlib_outbuf_set_priv;
+             re->render_mode = info->render_mode;
+#endif
           }
 #endif
 
@@ -542,6 +553,9 @@ eng_setup(Evas *e, void *in)
      {
        int            ponebuf = 0;
 
+#ifdef EVAS_FRAME_QUEUING
+        evas_common_frameq_flush ();
+#endif
        re = e->engine.data.output;
        ponebuf = re->ob->onebuf;
 
@@ -564,6 +578,9 @@ eng_setup(Evas *e, void *in)
                                                         info->info.shape_dither,
                                                         info->info.destination_alpha);
              evas_software_xlib_outbuf_debug_set(re->ob, info->info.debug);
+#ifdef EVAS_FRAME_QUEUING
+             re->render_mode = info->render_mode;
+#endif
           }
 #endif
 
@@ -714,18 +731,74 @@ static void
 eng_output_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
 {
    Render_Engine *re;
+#ifdef EVAS_FRAME_QUEUING
+   Evas_Surface *e_surface;
+#endif
 
    re = (Render_Engine *)data;
-#ifdef BUILD_PIPE_RENDER
+#if defined(BUILD_PIPE_RENDER) && !defined(EVAS_FRAME_QUEUING)
    evas_common_pipe_map4_begin(surface);
-#endif   
+#endif /* BUILD_PIPE_RENDER  && !EVAS_FRAME_QUEUING*/
+
+#ifdef EVAS_FRAME_QUEUING
+   if (re->render_mode == EVAS_RENDER_MODE_NONBLOCKING)
+     {
+        /* create a new frame if this is the first surface of this frame */
+        evas_common_frameq_prepare_frame();
+        /* add surface into the frame */
+        e_surface = evas_common_frameq_new_surface(surface, x, y, w, h);
+        evas_common_frameq_add_surface(e_surface);
+        return;
+     }
+#endif
+
    re->outbuf_push_updated_region(re->ob, surface, x, y, w, h);
    re->outbuf_free_region_for_update(re->ob, surface);
    evas_common_cpu_end_opt();
 }
 
+#ifdef EVAS_FRAME_QUEUING
+static void *
+eng_image_map_surface_new(void *data , int w, int h, int alpha)
+{
+   void *surface;
+   DATA32 *pixels;
+   Render_Engine *re;
+   Evas_Surface *e_surface;
+
+   re = (Render_Engine *)data;
+
+   surface = evas_cache_image_copied_data(evas_common_image_cache_get(), 
+                                          w, h, NULL, alpha, 
+                                          EVAS_COLORSPACE_ARGB8888);
+   pixels = evas_cache_image_pixels(surface);
+
+   if (re->render_mode == EVAS_RENDER_MODE_NONBLOCKING)
+     {
+        /* create a new frame if this is the first surface of this frame */
+        evas_common_frameq_prepare_frame();
+
+        /* add surface into the frame */
+        e_surface = evas_common_frameq_new_surface (surface, 0, 0, w, h);
+        e_surface->dontpush = 1; // this surface is not going to be pushed to screen
+        evas_common_frameq_add_surface(e_surface);
+     }
+   return surface;
+}
+
 static void
-eng_output_flush(void *data)
+eng_output_frameq_redraws_next_update_push(void *data, void *surface, int x, int y, int w, int h)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   re->outbuf_push_updated_region(re->ob, surface, x, y, w, h);
+   re->outbuf_free_region_for_update(re->ob, surface);
+   evas_common_cpu_end_opt();
+}
+
+static void
+eng_output_frameq_flush(void *data)
 {
    Render_Engine *re;
 
@@ -734,6 +807,39 @@ eng_output_flush(void *data)
 }
 
 static void
+eng_output_frameq_set_priv(void *data, void *cur, void *prev)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+   re->outbuf_set_priv(re->ob, cur, prev);
+}
+#endif
+
+static void
+eng_output_flush(void *data)
+{
+   Render_Engine *re;
+
+   re = (Render_Engine *)data;
+#ifdef EVAS_FRAME_QUEUING
+   if (re->render_mode == EVAS_RENDER_MODE_NONBLOCKING)
+     {
+        evas_common_frameq_set_frame_data(data,
+                        eng_output_frameq_redraws_next_update_push,
+                        eng_output_frameq_flush,
+                        eng_output_frameq_set_priv);
+        evas_common_frameq_ready_frame();
+        evas_common_frameq_begin();
+     } 
+   else
+#endif
+     {
+        re->outbuf_flush(re->ob);
+     }
+}
+
+static void
 eng_output_idle_flush(void *data)
 {
    Render_Engine *re;
@@ -751,6 +857,7 @@ eng_canvas_alpha_get(void *data, void *context __UNUSED__)
    return (re->ob->priv.destination_alpha) || (re->outbuf_alpha_get(re->ob));
 }
 
+
 /* module advertising code */
 static int
 module_open(Evas_Module *em)
@@ -793,6 +900,10 @@ module_open(Evas_Module *em)
    ORD(output_flush);
    ORD(output_idle_flush);
    /* now advertise out own api */
+#ifdef EVAS_FRAME_QUEUING
+   ORD(image_map_surface_new);
+#endif
+
    em->functions = (void *)(&func);
    return 1;
 }
index e3eb184..808a3e5 100644 (file)
@@ -113,6 +113,10 @@ struct _Outbuf
       Eina_List   *pending_writes;
       /* a list of previous frame pending regions to write to the target */
       Eina_List   *prev_pending_writes;
+#ifdef EVAS_FRAME_QUEUING
+      /* protecting prev_pending_writes */
+      LK(lock);
+#endif
 
       unsigned char mask_dither : 1;
       unsigned char destination_alpha : 1;
index a077963..873a67e 100644 (file)
@@ -305,7 +305,18 @@ evas_software_xlib_x_output_buffer_new(Display *d, Visual *v, int depth, int w,
                                  ph = XSetErrorHandler((XErrorHandler)
                                                        x_output_tmp_x_err);
                               }
+#if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
+                    /* workaround for libXext of lower then 1.1.1 */
+                    if (evas_common_frameq_enabled())
+                       XLockDisplay(d);
+#endif
                            XShmAttach(d, xob->shm_info);
+#if defined(EVAS_FRAME_QUEUING) && defined(LIBXEXT_VERSION_LOW)
+                    /* workaround for libXext of lower then 1.1.1 */
+                    if (evas_common_frameq_enabled())
+                       XUnlockDisplay(d);
+#endif
+
                             if (try_shm == 2) // only needed during testing
                               {
                                  XSync(d, False); 
index 6e1ac92..7274c1a 100644 (file)
@@ -25,6 +25,15 @@ static int shmsize = 0;
 static int shmmemlimit = 10 * 1024 * 1024;
 static int shmcountlimit = 32;
 
+#ifdef EVAS_FRAME_QUEUING
+static LK(lock_shmpool);
+#define SHMPOOL_LOCK()         LKL(lock_shmpool)
+#define SHMPOOL_UNLOCK()       LKU(lock_shmpool)
+#else
+#define SHMPOOL_LOCK()
+#define SHMPOOL_UNLOCK()
+#endif
+
 static X_Output_Buffer *
 _find_xob(Display *d, Visual *v, int depth, int w, int h, int shm, void *data)
 {
@@ -46,6 +55,7 @@ _find_xob(Display *d, Visual *v, int depth, int w, int h, int shm, void *data)
    else
      lbytes = ((w + 31) / 32) * 4;
    sz = lbytes * h;
+   SHMPOOL_LOCK();
    EINA_LIST_FOREACH(shmpool, l, xob2)
      {
        int szdif;
@@ -69,8 +79,12 @@ _find_xob(Display *d, Visual *v, int depth, int w, int h, int shm, void *data)
          }
      }
    if ((fitness > (100 * 100)) || (!xob))
-     return evas_software_xlib_x_output_buffer_new(d, v, depth, w, h, shm, data);
-
+     {
+        SHMPOOL_UNLOCK();
+        xob = evas_software_xlib_x_output_buffer_new(d, v, depth, w, h, shm, data);
+        return xob;
+     }
+   
    have_xob:
    shmpool = eina_list_remove_list(shmpool, xl);
    xob->w = w;
@@ -80,6 +94,7 @@ _find_xob(Display *d, Visual *v, int depth, int w, int h, int shm, void *data)
    xob->xim->height = xob->h;
    xob->xim->bytes_per_line = xob->bpl;
    shmsize -= xob->psize * (xob->xim->depth / 8);
+   SHMPOOL_UNLOCK();
    return xob;
 }
 
@@ -89,6 +104,7 @@ _unfind_xob(X_Output_Buffer *xob, int sync)
 //   evas_software_xlib_x_output_buffer_free(xob, sync); return;
    if (xob->shm_info)
      {
+        SHMPOOL_LOCK();
        shmpool = eina_list_prepend(shmpool, xob);
        shmsize += xob->psize * xob->xim->depth / 8;
        while ((shmsize > (shmmemlimit)) ||
@@ -103,9 +119,11 @@ _unfind_xob(X_Output_Buffer *xob, int sync)
                  break;
               }
             xob = xl->data;
-            shmpool = eina_list_remove_list(shmpool, xl);
+             shmpool = eina_list_remove_list(shmpool, xl);
+             shmsize -= xob->psize * xob->xim->depth / 8;
             evas_software_xlib_x_output_buffer_free(xob, sync);
          }
+        SHMPOOL_UNLOCK();
      }
    else
      evas_software_xlib_x_output_buffer_free(xob, sync);
@@ -114,6 +132,7 @@ _unfind_xob(X_Output_Buffer *xob, int sync)
 static void
 _clear_xob(int sync)
 {
+   SHMPOOL_LOCK();
    while (shmpool)
      {
        X_Output_Buffer *xob;
@@ -123,16 +142,23 @@ _clear_xob(int sync)
        evas_software_xlib_x_output_buffer_free(xob, sync);
      }
    shmsize = 0;
+   SHMPOOL_UNLOCK();
 }
 
 void
 evas_software_xlib_outbuf_init(void)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKI(lock_shmpool);
+#endif
 }
 
 void
 evas_software_xlib_outbuf_free(Outbuf *buf)
 {
+#ifdef EVAS_FRAME_QUEUING
+   LKL(buf->priv.lock);
+#endif
    while (buf->priv.pending_writes)
      {
        RGBA_Image *im;
@@ -146,6 +172,9 @@ evas_software_xlib_outbuf_free(Outbuf *buf)
        if (obr->mxob) _unfind_xob(obr->mxob, 0);
        free(obr);
      }
+#ifdef EVAS_FRAME_QUEUING
+   LKU(buf->priv.lock);
+#endif
    evas_software_xlib_outbuf_idle_flush(buf);
    evas_software_xlib_outbuf_flush(buf);
    if (buf->priv.x11.xlib.gc)
@@ -155,6 +184,9 @@ evas_software_xlib_outbuf_free(Outbuf *buf)
    if (buf->priv.pal)
       evas_software_xlib_x_color_deallocate(buf->priv.x11.xlib.disp, buf->priv.x11.xlib.cmap,
                                           buf->priv.x11.xlib.vis, buf->priv.pal);
+#ifdef EVAS_FRAME_QUEUING
+   LKD(buf->priv.lock);
+#endif
    free(buf);
    _clear_xob(0);
 }
@@ -331,6 +363,9 @@ evas_software_xlib_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
       evas_software_xlib_outbuf_drawable_set(buf, draw);
       evas_software_xlib_outbuf_mask_set(buf, mask);
    }
+#ifdef EVAS_FRAME_QUEUING
+   LKI(buf->priv.lock);
+#endif
    return buf;
 }
 
@@ -578,7 +613,10 @@ evas_software_xlib_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w
      /* FIXME: faster memset! */
      memset(im->image.data, 0, w * h * sizeof(DATA32));
 
-   buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
+#ifdef EVAS_FRAME_QUEUING
+   if (!evas_common_frameq_enabled())
+#endif
+      buf->priv.pending_writes = eina_list_append(buf->priv.pending_writes, im);
    return im;
 }
 
@@ -653,6 +691,9 @@ evas_software_xlib_outbuf_flush(Outbuf *buf)
                                                       buf->priv.x11.xlib.gcm,
                                                       obr->x, obr->y, 0);
          }
+#ifdef EVAS_FRAME_QUEUING
+     LKL(buf->priv.lock);
+#endif
        while (buf->priv.prev_pending_writes)
          {
             im = buf->priv.prev_pending_writes->data;
@@ -670,6 +711,9 @@ evas_software_xlib_outbuf_flush(Outbuf *buf)
             free(obr);
          }
        buf->priv.prev_pending_writes = buf->priv.pending_writes;
+#ifdef EVAS_FRAME_QUEUING
+     LKU(buf->priv.lock);
+#endif
        buf->priv.pending_writes = NULL;
        XFlush(buf->priv.x11.xlib.disp);
 #else
@@ -734,6 +778,9 @@ evas_software_xlib_outbuf_idle_flush(Outbuf *buf)
      }
    else
      {
+#ifdef EVAS_FRAME_QUEUING
+     LKL(buf->priv.lock);
+#endif
        if (buf->priv.prev_pending_writes) XSync(buf->priv.x11.xlib.disp, False);
        while (buf->priv.prev_pending_writes)
          {
@@ -750,6 +797,9 @@ evas_software_xlib_outbuf_idle_flush(Outbuf *buf)
             if (obr->mxob) _unfind_xob(obr->mxob, 0);
             free(obr);
          }
+#ifdef EVAS_FRAME_QUEUING
+     LKU(buf->priv.lock);
+#endif
        _clear_xob(0);
      }
 }
@@ -1036,3 +1086,12 @@ evas_software_xlib_outbuf_alpha_get(Outbuf *buf)
 {
    return buf->priv.x11.xlib.mask;
 }
+
+#ifdef EVAS_FRAME_QUEUING
+void
+evas_software_xlib_outbuf_set_priv(Outbuf *buf, void *cur, void *prev)
+{
+   buf->priv.pending_writes = (Eina_List *)cur;
+}
+
+#endif
index 8745a1a..d70eb8d 100644 (file)
@@ -83,5 +83,10 @@ void         evas_software_xlib_outbuf_debug_show (Outbuf  *buf,
                                                    int      h);
 
 Eina_Bool    evas_software_xlib_outbuf_alpha_get (Outbuf *buf);
+#ifdef EVAS_FRAME_QUEUING
+void         evas_software_xlib_outbuf_set_priv (Outbuf *buf,
+                                                  void *cur,
+                                                  void *prev);
+#endif
 
 #endif
index 0b5b81a..b329ae4 100644 (file)
@@ -37,5 +37,8 @@ struct _Evas_Engine_Info_XRender_X11
       void                            *visual;
       unsigned char                    destination_alpha : 1;
    } info;
+
+   /* non-blocking or blocking mode */
+   Evas_Engine_Render_Mode render_mode;
 };
 #endif
index 174287d..fcb4f09 100644 (file)
@@ -462,6 +462,7 @@ eng_info(Evas *e __UNUSED__)
    info = calloc(1, sizeof(Evas_Engine_Info_XRender_X11));
    if (!info) return NULL;
    info->magic.magic = rand();
+   info->render_mode = EVAS_RENDER_MODE_BLOCKING;
    return info;
 }
 
index 569887c..7aa6cff 100644 (file)
@@ -56,3 +56,15 @@ SUBDIRS += xpm
 endif
 endif
 
+if BUILD_LOADER_BMP
+if !EVAS_STATIC_BUILD_BMP
+SUBDIRS += bmp
+endif
+endif
+
+if BUILD_LOADER_TGA
+if !EVAS_STATIC_BUILD_TGA
+SUBDIRS += tga
+endif
+endif
+
diff --git a/src/modules/loaders/bmp/Makefile.am b/src/modules/loaders/bmp/Makefile.am
new file mode 100644 (file)
index 0000000..430156a
--- /dev/null
@@ -0,0 +1,32 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+@FREETYPE_CFLAGS@ \
+@EINA_CFLAGS@ \
+@EVIL_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+if BUILD_LOADER_BMP
+if !EVAS_STATIC_BUILD_BMP
+
+pkgdir = $(libdir)/evas/modules/loaders/bmp/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = evas_image_load_bmp.c
+
+module_la_LIBADD = @EINA_LIBS@ @EVIL_LIBS@ $(top_builddir)/src/lib/libevas.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
+
+else
+
+noinst_LTLIBRARIES = libevas_loader_bmp.la
+libevas_loader_bmp_la_SOURCES = evas_image_load_bmp.c
+libevas_loader_bmp_la_LIBADD = 
+
+endif
+endif
diff --git a/src/modules/loaders/bmp/evas_image_load_bmp.c b/src/modules/loaders/bmp/evas_image_load_bmp.c
new file mode 100644 (file)
index 0000000..8b0d6f0
--- /dev/null
@@ -0,0 +1,1111 @@
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "evas_common.h"
+#include "evas_private.h"
+
+static Eina_Bool evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
+static Eina_Bool evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
+
+static Evas_Image_Load_Func evas_image_load_bmp_func =
+{
+  EINA_TRUE,
+  evas_image_load_file_head_bmp,
+  evas_image_load_file_data_bmp
+};
+
+static int
+read_short(FILE *file, short *ret)
+{
+   unsigned char b[2];
+   if (fread(b, sizeof(unsigned char), 2, file) != 2) return 0;
+   *ret = (b[1] << 8) | b[0];
+   return 1;
+}
+      
+static int
+read_int(FILE *file, int *ret)
+{
+   unsigned char       b[4];
+   if (fread(b, sizeof(unsigned char), 4, file) != 4) return 0;
+   *ret = (b[3] << 24) | (b[2] << 16) | (b[1] << 8) | b[0];
+   return 1;
+}
+
+static Eina_Bool
+evas_image_load_file_head_bmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
+{
+   FILE *f;
+   unsigned char buf[4096];
+   char hasa = 0;
+   int w = 0, h = 0, planes = 0, bit_count = 0, 
+     image_size = 0, comp = 0, hdpi = 0, vdpi = 0, 
+     palette_size = -1, important_colors = 0, rowlen = 0;
+   unsigned int offset, head_size, rmask = 0, gmask = 0, bmask = 0, amask = 0;
+   unsigned int *pal = NULL, pal_num = 0;
+   int right_way_up = 0;
+   int fsize = 0;
+   unsigned int bmpsize;
+   unsigned short res1, res2;
+
+   f = fopen(file, "rb");
+   if (!f)
+     {
+       *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+       return EINA_FALSE;
+     }
+
+   *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+   fseek(f, 0, SEEK_END);
+   fsize = ftell(f);
+   fseek(f, 0, SEEK_SET);
+   if (fsize < 2) goto close_file;
+   
+   if (fread(buf, 2, 1, f) != 1) goto close_file;
+   if (strncmp(buf, "BM", 2)) goto close_file; // magic number
+   *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+   if (!read_int(f, &bmpsize)) goto close_file;
+   if (!read_short(f, &res1)) goto close_file;
+   if (!read_short(f, &res2)) goto close_file;
+   if (!read_int(f, &offset)) goto close_file;
+   if (!read_int(f, &head_size)) goto close_file;
+   if (head_size == 12) // OS/2 V1 + Windows 3.0
+     {
+        short tmp;
+        
+        if (!read_short(f, &tmp)) goto close_file;
+        w = tmp; // width
+        if (!read_short(f, &tmp)) goto close_file;
+        h = tmp; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8 & 24
+     }
+   else if (head_size == 64) // OS/2 V2
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (fread(buf, 24, 1, f) != 1) goto close_file; // skip unused header
+        if (image_size == 0) image_size = fsize - offset;
+     }
+   else if (head_size == 40) // Windows 3.0 + (v3)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (image_size == 0) image_size = fsize - offset;
+     }
+   else if (head_size == 108) // Windows 95/NT4 + (v4)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (!read_int(f, &tmp2)) goto close_file;
+        rmask = tmp2; // red mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        gmask = tmp2; // green mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        bmask = tmp2; // blue mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        amask = tmp2; // alpha mask
+        if (fread(buf, 36, 1, f) != 1) goto close_file; // skip unused cie
+        if (fread(buf, 12, 1, f) != 1) goto close_file; // skip unused gamma
+        if (image_size == 0) image_size = fsize - offset;
+        if ((amask) && (bit_count == 32)) hasa = 1;
+     }
+   else if (head_size == 124) // Windows 98/2000 + (v5)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (!read_int(f, &tmp2)) goto close_file;
+        rmask = tmp2; // red mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        gmask = tmp2; // green mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        bmask = tmp2; // blue mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        amask = tmp2; // alpha mask
+        if (fread(buf, 36, 1, f) != 1) goto close_file; // skip unused cie
+        if (fread(buf, 12, 1, f) != 1) goto close_file; // skip unused gamma
+        if (fread(buf, 16, 1, f) != 1) goto close_file; // skip others
+        if (image_size == 0) image_size = fsize - offset;
+        if ((amask) && (bit_count == 32)) hasa = 1;
+     }
+   else
+     goto close_file;
+
+   if (h < 0)
+     {
+        h = -h;
+        right_way_up = 1;
+     }
+   
+   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+       IMG_TOO_BIG(w, h))
+     {
+        if (IMG_TOO_BIG(w, h))
+          *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        else
+          *error = EVAS_LOAD_ERROR_GENERIC;
+       goto close_file;
+     }
+   
+   if (bit_count < 16)
+     {
+        int i;
+        
+        if ((palette_size < 0) || (palette_size > 256)) pal_num = 256;
+        else pal_num = palette_size;
+        if (bit_count == 1)
+          {
+             if (comp == 0) // no compression
+               {
+               }
+             else
+               goto close_file;
+          }
+        else if (bit_count == 4)
+          {
+             if (comp == 0) // no compression
+               {
+               }
+             else if (comp == 2) // rle 4bit/pixel
+               {
+               }
+             else
+               goto close_file;
+          }
+        else if (bit_count == 8)
+          {
+             if (comp == 0) // no compression
+               {
+               }
+             else if (comp == 1) // rle 8bit/pixel
+               {
+               }
+             else
+               goto close_file;
+          }
+     }
+   else if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
+     {
+        if (comp == 0) // no compression
+          {
+             // handled
+          }
+        else if (comp == 3) // bit field
+          {
+             // handled
+          }
+        else if (comp == 4) // jpeg - only printer drivers
+          goto close_file;
+        else if (comp == 3) // png - only printer drivers
+          goto close_file;
+        else
+          goto close_file;
+     }
+   else
+     goto close_file;
+
+   ie->w = w;
+   ie->h = h;
+   if (hasa) ie->flags.alpha = 1;
+   
+   fclose(f);
+   *error = EVAS_LOAD_ERROR_NONE;
+   return EINA_TRUE;
+
+ close_file:
+   fclose(f);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+evas_image_load_file_data_bmp(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
+{
+   FILE *f;
+   unsigned char buf[4096], *buffer = NULL, *buffer_end = NULL, *p;
+   char hasa = 0;
+   int x = 0, y = 0, w = 0, h = 0, planes = 0, bit_count = 0, image_size = 0, 
+     comp = 0, hdpi = 0, vdpi = 0, palette_size = -1, important_colors = 0, 
+     offset = 0, head_size = 0;
+   unsigned int *pal = NULL, pal_num = 0, *pix = NULL, *surface = NULL, fix,
+     rmask = 0, gmask = 0, bmask = 0, amask = 0;
+   int right_way_up = 0;
+   unsigned char r, g, b, a;
+   int fsize = 0;
+   unsigned int bmpsize;
+   unsigned short res1, res2;
+   
+   f = fopen(file, "rb");
+   if (!f)
+     {
+       *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+       return EINA_FALSE;
+     }
+   
+   *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+   fseek(f, 0, SEEK_END);
+   fsize = ftell(f);
+   fseek(f, 0, SEEK_SET);
+   if (fsize < 2) goto close_file;
+   
+   if (fread(buf, 2, 1, f) != 1) goto close_file;
+   if (strncmp(buf, "BM", 2)) goto close_file; // magic number
+   *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+   if (!read_int(f, &bmpsize)) goto close_file;
+   if (!read_short(f, &res1)) goto close_file;
+   if (!read_short(f, &res2)) goto close_file;
+   if (!read_int(f, &offset)) goto close_file;
+   if (!read_int(f, &head_size)) goto close_file;
+   image_size = fsize - offset;
+   if (image_size < 1) goto close_file;
+   
+   if (head_size == 12) // OS/2 V1 + Windows 3.0
+     {
+        short tmp;
+        
+        if (!read_short(f, &tmp)) goto close_file;
+        w = tmp; // width
+        if (!read_short(f, &tmp)) goto close_file;
+        h = tmp; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8 & 24
+     }
+   else if (head_size == 64) // OS/2 V2
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (fread(buf, 24, 1, f) != 1) goto close_file; // skip unused header
+        if (image_size == 0) image_size = fsize - offset;
+     }
+   else if (head_size == 40) // Windows 3.0 + (v3)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (image_size == 0) image_size = fsize - offset;
+     }
+   else if (head_size == 108) // Windows 95/NT4 + (v4)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (!read_int(f, &tmp2)) goto close_file;
+        rmask = tmp2; // red mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        gmask = tmp2; // green mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        bmask = tmp2; // blue mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        amask = tmp2; // alpha mask
+        if (fread(buf, 36, 1, f) != 1) goto close_file; // skip unused cie
+        if (fread(buf, 12, 1, f) != 1) goto close_file; // skip unused gamma
+        if (image_size == 0) image_size = fsize - offset;
+        if ((amask) && (bit_count == 32)) hasa = 1;
+     }
+   else if (head_size == 124) // Windows 98/2000 + (v5)
+     {
+        short tmp;
+        int tmp2;
+        
+        if (!read_int(f, &tmp2)) goto close_file;
+        w = tmp2; // width
+        if (!read_int(f, &tmp2)) goto close_file;
+        h = tmp2; // height
+        if (!read_short(f, &tmp)) goto close_file;
+        planes = tmp; // must be 1
+        if (!read_short(f, &tmp)) goto close_file;
+        bit_count = tmp; // bits per pixel: 1, 4, 8, 16, 24 & 32
+        if (!read_int(f, &tmp2)) goto close_file;
+        comp = tmp2; // compression method
+        if (!read_int(f, &tmp2)) goto close_file;
+        image_size = tmp2; // bitmap data size
+        if (!read_int(f, &tmp2)) goto close_file;
+        hdpi = (tmp2 * 254) / 10000; // horizontal pixels/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        vdpi = (tmp2 * 254) / 10000; // vertical pixles/meter
+        if (!read_int(f, &tmp2)) goto close_file;
+        palette_size = tmp2; // number of palette colors power (2^n - so 0 - 8)
+        if (!read_int(f, &tmp2)) goto close_file;
+        important_colors = tmp2; // number of important colors - 0 if all
+        if (!read_int(f, &tmp2)) goto close_file;
+        rmask = tmp2; // red mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        gmask = tmp2; // green mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        bmask = tmp2; // blue mask
+        if (!read_int(f, &tmp2)) goto close_file;
+        amask = tmp2; // alpha mask
+        if (fread(buf, 36, 1, f) != 1) goto close_file; // skip unused cie
+        if (fread(buf, 12, 1, f) != 1) goto close_file; // skip unused gamma
+        if (fread(buf, 16, 1, f) != 1) goto close_file; // skip others
+        if (image_size == 0) image_size = fsize - offset;
+        if ((amask) && (bit_count == 32)) hasa = 1;
+     }
+   else
+     goto close_file;
+
+   if (h < 0)
+     {
+        h = -h;
+        right_way_up = 1;
+     }
+   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+       IMG_TOO_BIG(w, h))
+     {
+        if (IMG_TOO_BIG(w, h))
+          *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+        else
+          *error = EVAS_LOAD_ERROR_GENERIC;
+       goto close_file;
+     }
+   
+   if ((w != ie->w) || (h != ie->h))
+     {
+       *error = EVAS_LOAD_ERROR_GENERIC;
+       goto close_file;
+     }
+   evas_cache_image_surface_alloc(ie, w, h);
+   surface = evas_cache_image_pixels(ie);
+   if (!surface)
+     {
+       *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+       goto close_file;
+     }
+   
+   if (bit_count < 16)
+     {
+        int i;
+        
+        if (bit_count == 1)
+          {
+             if ((palette_size <= 0) || (palette_size > 2)) pal_num = 2;
+             else pal_num = palette_size;
+          }
+        else if (bit_count == 4)
+          {
+             if ((palette_size <= 0) || (palette_size > 16)) pal_num = 16;
+             else pal_num = palette_size;
+          }
+        else if (bit_count == 8)
+          {
+             if ((palette_size <= 0) || (palette_size > 256)) pal_num = 256;
+             else pal_num = palette_size;
+          }
+        pal = alloca(256 * 4);
+        for (i = 0; i < pal_num; i++)
+          {
+             if (fread(&b, 1, 1, f) != 1) goto close_file;
+             if (fread(&g, 1, 1, f) != 1) goto close_file;
+             if (fread(&r, 1, 1, f) != 1) goto close_file;
+             if ((head_size != 12) /*&& (palette_size != 0)*/)
+               { // OS/2 V1 doesnt do the pad byte
+                  if (fread(&a, 1, 1, f) != 1) goto close_file;
+               }
+             a = 0xff; // fillin a as solid for paletted images
+             pal[i] = (a << 24) | (r << 16) | (g << 8) | b;
+          }
+        fseek(f, offset, SEEK_SET);
+        buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+        if (!buffer)
+          {
+             *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+             goto close_file;
+          }
+        buffer_end = buffer + image_size;
+        p = buffer;
+        if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+        
+        if (bit_count == 1)
+          {
+             if (comp == 0) // no compression
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            if ((x & 0x7) == 0x0)
+                              {
+                                 *pix = pal[*p >> 7];
+                              }
+                            else if ((x & 0x7) == 0x1)
+                              {
+                                 *pix = pal[(*p >> 6) & 0x1];
+                              }
+                            else if ((x & 0x7) == 0x2)
+                              {
+                                 *pix = pal[(*p >> 5) & 0x1];
+                              }
+                            else if ((x & 0x7) == 0x3)
+                              {
+                                 *pix = pal[(*p >> 4) & 0x1];
+                              }
+                            else if ((x & 0x7) == 0x4)
+                              {
+                                 *pix = pal[(*p >> 3) & 0x1];
+                              }
+                            else if ((x & 0x7) == 0x5)
+                              {
+                                 *pix = pal[(*p >> 2) & 0x1];
+                              }
+                            else if ((x & 0x7) == 0x6)
+                              {
+                                 *pix = pal[(*p >> 1) & 0x1];
+                              }
+                            else
+                              {
+                                 *pix = pal[*p & 0x1];
+                                 p++;
+                              }
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       if ((x & 0x7) != 0) p++;
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else
+               goto close_file;
+          }
+        else if (bit_count == 4)
+          {
+             if (comp == 0) // no compression
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            if ((x & 0x1) == 0x1)
+                              {
+                                 *pix = pal[*p & 0x0f];
+                                 p++;
+                              }
+                            else
+                              {
+                                 *pix = pal[*p >> 4];
+                              }
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       if ((x & 0x1) != 0) p++;
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if (comp == 2) // rle 4bit/pixel
+               {
+                  int count = 0, done = 0, wpad;
+
+                  pix = surface;
+                  if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                  wpad = ((w + 1) / 2) * 2;
+                  while (p < buffer_end)
+                    {
+                       if (p[0])
+                         {
+                            unsigned int col1 = pal[p[1] >> 4];
+                            unsigned int col2 = pal[p[1] & 0xf];
+                            
+                            if ((x + p[0]) > wpad) break;
+                            count = p[0] / 2;
+                            while (count > 0)
+                              {
+                                 if (x < w)
+                                   {
+                                      pix[0] = col1;
+                                      x++;
+                                   }
+                                 if (x < w)
+                                   {
+                                      pix[1] = col2;
+                                      x++;
+                                   }
+                                 pix += 2;
+                                 count--;
+                              }
+                            if (p[0] & 0x1)
+                              {
+                                 *pix = col1;
+                                 x++;
+                                 pix++;
+                              }
+                            p += 2;
+                         }
+                       else
+                         {
+                            switch (p[1])
+                              {
+                              case 0: // EOL
+                                 x = 0;
+                                 y++;
+                                 if (!right_way_up)
+                                   pix = surface + ((h - 1 - y) * w);
+                                 else
+                                   pix = surface + (y * w);
+                                 if (y >= h)
+                                   {
+                                      p = buffer_end;
+                                   }
+                                 p += 2;
+                                 break;
+                              case 1: // EOB
+                                 p = buffer_end;
+                                 break;
+                              case 2: // DELTA
+                                 x += p[2];
+                                 y += p[3];
+                                 if ((x >= w) || (y >= h))
+                                   {
+                                      p = buffer_end;
+                                   }
+                                 if (!right_way_up)
+                                   pix = surface + x + ((h - 1 - y) * w);
+                                 else
+                                   pix = surface + x + (y * w);
+                                 p += 4;
+                                 break;
+                              default:
+                                 count = p[1];
+                                 if (((p + count) > buffer_end) ||
+                                     ((x + count) > w))
+                                   {
+                                      p = buffer_end;
+                                      break;
+                                   }
+                                 p += 2;
+                                 done = count;
+                                 count /= 2;
+                                 while (count > 0)
+                                   {
+                                      pix[0] = pal[*p >> 4];
+                                      pix[1] = pal[*p & 0xf];
+                                      pix += 2;
+                                      p++;
+                                      count--;
+                                   }
+                                 x += done;
+                                 if (done & 0x1)
+                                   {
+                                      *pix = pal[*p >> 4];
+                                      p++;
+                                   }
+                                 if ((done & 0x3) == 0x1)
+                                   p += 2;
+                                 else if ((done & 0x3) == 0x2)
+                                   p += 1;
+                                 break;
+                              }
+                         }
+                    }
+               }
+             else
+               goto close_file;
+          }
+        else if (bit_count == 8)
+          {
+             if (comp == 0) // no compression
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            *pix = pal[*p];
+                            p++;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if (comp == 1) // rle 8bit/pixel
+               {
+                  int count = 0, done = 0;
+
+                  pix = surface;
+                  if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                  while (p < buffer_end)
+                    {
+                       if (p[0])
+                         {
+                            unsigned int col = pal[p[1]];
+                            
+                            count = p[0];
+                            if ((x + p[0]) > w) break;
+                            while (count > 0)
+                              {
+                                 *pix = col;
+                                 pix++;
+                                 count--;
+                              }
+                            x += p[0];
+                            p += 2;
+                         }
+                       else
+                         {
+                            switch (p[1])
+                              {
+                              case 0: // EOL
+                                 x = 0;
+                                 y++;
+                                 if (!right_way_up)
+                                   pix = surface + ((h - 1 - y) * w);
+                                 else
+                                   pix = surface + (y * w);
+                                 if (y >= h)
+                                   {
+                                      p = buffer_end;
+                                   }
+                                 p += 2;
+                                 break;
+                              case 1: // EOB
+                                 p = buffer_end;
+                                 break;
+                              case 2: // DELTA
+                                 x += p[2];
+                                 y += p[3];
+                                 if ((x >= w) || (y >= h))
+                                   {
+                                      p = buffer_end;
+                                   }
+                                 if (!right_way_up)
+                                   pix = surface + x + ((h - 1 - y) * w);
+                                 else
+                                   pix = surface + x + (y * w);
+                                 p += 4;
+                                 break;
+                              default:
+                                 count = p[1];
+                                 if (((p + count) > buffer_end) ||
+                                     ((x + count) > w))
+                                   {
+                                      p = buffer_end;
+                                      break;
+                                   }
+                                 p += 2;
+                                 done = count;
+                                 while (count > 0)
+                                   {
+                                      *pix = pal[*p];
+                                      pix++;
+                                      p++;
+                                      count--;
+                                   }
+                                 x += done;
+                                 if (done & 0x1) p++;
+                                 break;
+                              }
+                         }
+                    }
+               }
+             else
+               goto close_file;
+          }
+     }
+   else if ((bit_count == 16) || (bit_count == 24) || (bit_count == 32))
+     {
+        if (comp == 0) // no compression
+          {
+             fseek(f, offset, SEEK_SET);
+             buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+             if (!buffer)
+               {
+                  *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+                  goto close_file;
+               }
+             buffer_end = buffer + image_size;
+             p = buffer;
+             if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+             if (bit_count == 16)
+               {
+                  unsigned short tmp;
+                  
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            tmp = *((unsigned short *)(p));
+
+                            r = (tmp >> 7) & 0xf8; r |= r >> 5;
+                            g = (tmp >> 2) & 0xf8; g |= g >> 5;
+                            b = (tmp << 3) & 0xf8; b |= b >> 5;
+                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            p += 2;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if (bit_count == 24)
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            b = p[0];
+                            g = p[1];
+                            r = p[2];
+                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            p += 3;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if (bit_count == 32)
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            b = p[0];
+                            g = p[1];
+                            r = p[2];
+                            a = p[3];
+                            if (!hasa) a = 0xff;
+                            *pix = (a << 24) | (r << 16) | (g << 8) | (b);
+                            p += 4;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else
+               goto close_file;
+          }
+        else if (comp == 3) // bit field
+          {
+             if (!read_int(f, &rmask)) goto close_file;
+             if (!read_int(f, &gmask)) goto close_file;
+             if (!read_int(f, &bmask)) goto close_file;
+
+             fseek(f, offset, SEEK_SET);
+             buffer = malloc(image_size + 8); // add 8 for padding to avoid checks
+             if (!buffer)
+               {
+                  *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+                  goto close_file;
+               }
+             buffer_end = buffer + image_size;
+             p = buffer;
+             if (fread(buffer, image_size, 1, f) != 1) goto close_file;
+             if ((bit_count == 16) && 
+                 (rmask == 0xf800) && (gmask == 0x07e0) && (bmask == 0x001f)
+                 )
+               {
+                  unsigned short tmp;
+                  
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            tmp = *((unsigned short *)(p));
+
+                            r = (tmp >> 8) & 0xf8; r |= r >> 5;
+                            g = (tmp >> 3) & 0xfc; g |= g >> 6;
+                            b = (tmp << 3) & 0xf8; b |= b >> 5;
+                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            p += 2;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if ((bit_count == 16) && 
+                      (rmask == 0x7c00) && (gmask == 0x03e0) && (bmask == 0x001f)
+                     )
+               {
+                  unsigned short tmp;
+                  
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            tmp = *((unsigned short *)(p));
+
+                            r = (tmp >> 7) & 0xf8; r |= r >> 5;
+                            g = (tmp >> 2) & 0xf8; g |= g >> 5;
+                            b = (tmp << 3) & 0xf8; b |= b >> 5;
+                            *pix = 0xff000000 | (r << 16) | (g << 8) | (b);
+                            p += 2;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else if (bit_count == 32)
+               {
+                  pix = surface;
+                  for (y = 0; y < h; y++)
+                    {
+                       if (!right_way_up) pix = surface + ((h - 1 - y) * w);
+                       for (x = 0; x < w; x++)
+                         {
+                            b = p[0];
+                            g = p[1];
+                            r = p[2];
+                            a = p[3];
+                            if (!hasa) a = 0xff;
+                            *pix = (a << 24) | (r << 16) | (g << 8) | (b);
+                            p += 4;
+                            if (p >= buffer_end) break;
+                            pix++;
+                         }
+                       fix = (int)(((unsigned long)p) & 0x3);
+                       if (fix > 0) p += 4 - fix; // align row read
+                       if (p >= buffer_end) break;
+                    }
+               }
+             else
+               goto close_file;
+          }
+        else if (comp == 4) // jpeg - only printer drivers
+          {
+             goto close_file;
+          }
+        else if (comp == 3) // png - only printer drivers
+          {
+             goto close_file;
+          }
+        else
+          goto close_file;
+     }
+   else
+     goto close_file;
+   
+   if (buffer) free(buffer);
+   fclose(f);
+
+   evas_common_image_premul(ie);
+   *error = EVAS_LOAD_ERROR_NONE;
+   return EINA_TRUE;
+
+ close_file:
+   if (buffer) free(buffer);
+   fclose(f);
+   return EINA_FALSE;
+}
+
+static int
+module_open(Evas_Module *em)
+{
+   if (!em) return 0;
+   em->functions = (void *)(&evas_image_load_bmp_func);
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em)
+{
+}
+
+static Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION,
+   "bmp",
+   "none",
+   {
+     module_open,
+     module_close
+   }
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, bmp);
+
+#ifndef EVAS_STATIC_BUILD_BMP
+EVAS_EINA_MODULE_DEFINE(image_loader, bmp);
+#endif
index 989fcfe..78216e7 100644 (file)
@@ -18,7 +18,7 @@
 #ifdef _WIN32_WCE
 # define E_FOPEN(file, mode) evil_fopen_native((file), (mode))
 # define E_FREAD(buffer, size, count, stream) evil_fread_native(buffer, size, count, stream)
-# define E_FCLOSE(stream) evil_fclose_native(stream)
+# define/ E_FCLOSE(stream) evil_fclose_native(stream)
 #else
 # define E_FOPEN(file, mode) fopen((file), (mode))
 # define E_FREAD(buffer, size, count, stream) fread(buffer, size, count, stream)
diff --git a/src/modules/loaders/tga/Makefile.am b/src/modules/loaders/tga/Makefile.am
new file mode 100644 (file)
index 0000000..f784d63
--- /dev/null
@@ -0,0 +1,32 @@
+
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I. \
+-I$(top_srcdir)/src/lib \
+-I$(top_srcdir)/src/lib/include \
+@FREETYPE_CFLAGS@ \
+@EINA_CFLAGS@ \
+@EVIL_CFLAGS@ \
+@WIN32_CPPFLAGS@
+
+if BUILD_LOADER_TGA
+if !EVAS_STATIC_BUILD_TGA
+
+pkgdir = $(libdir)/evas/modules/loaders/tga/$(MODULE_ARCH)
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = evas_image_load_tga.c
+
+module_la_LIBADD = @EINA_LIBS@ @EVIL_LIBS@ $(top_builddir)/src/lib/libevas.la
+module_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -module -avoid-version
+module_la_LIBTOOLFLAGS = --tag=disable-static
+
+else
+
+noinst_LTLIBRARIES = libevas_loader_tga.la
+libevas_loader_tga_la_SOURCES = evas_image_load_tga.c
+libevas_loader_tga_la_LIBADD = 
+
+endif
+endif
diff --git a/src/modules/loaders/tga/evas_image_load_tga.c b/src/modules/loaders/tga/evas_image_load_tga.c
new file mode 100644 (file)
index 0000000..8ce68f7
--- /dev/null
@@ -0,0 +1,528 @@
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#ifdef HAVE_EVIL
+# include <Evil.h>
+#endif
+
+#include "evas_common.h"
+#include "evas_private.h"
+
+/* TGA pixel formats */
+#define TGA_TYPE_MAPPED      1 // handle
+#define TGA_TYPE_COLOR       2
+#define TGA_TYPE_GRAY        3
+#define TGA_TYPE_MAPPED_RLE  9 // handle
+#define TGA_TYPE_COLOR_RLE  10
+#define TGA_TYPE_GRAY_RLE   11
+
+/* TGA header flags */
+#define TGA_DESC_ABITS      0x0f
+#define TGA_DESC_HORIZONTAL 0x10
+#define TGA_DESC_VERTICAL   0x20
+
+#define TGA_SIGNATURE "TRUEVISION-XFILE"
+
+typedef struct
+{
+   unsigned char       idLength;
+   unsigned char       colorMapType;
+   unsigned char       imageType;
+   unsigned char       colorMapIndexLo, colorMapIndexHi;
+   unsigned char       colorMapLengthLo, colorMapLengthHi;
+   unsigned char       colorMapSize;
+   unsigned char       xOriginLo, xOriginHi;
+   unsigned char       yOriginLo, yOriginHi;
+   unsigned char       widthLo, widthHi;
+   unsigned char       heightLo, heightHi;
+   unsigned char       bpp;
+   unsigned char       descriptor;
+} tga_header;
+                  
+typedef struct
+{
+   unsigned int        extensionAreaOffset;
+   unsigned int        developerDirectoryOffset;
+   char                signature[16];
+   char                dot;
+   char                null;
+} tga_footer;
+
+
+static Eina_Bool evas_image_load_file_head_tga(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
+static Eina_Bool evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
+
+static Evas_Image_Load_Func evas_image_load_tga_func =
+{
+  EINA_TRUE,
+  evas_image_load_file_head_tga,
+  evas_image_load_file_data_tga
+};
+
+static Eina_Bool
+evas_image_load_file_head_tga(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
+{
+   int fd;
+   unsigned char *seg = MAP_FAILED, *filedata;
+   struct stat ss;
+   tga_header *header;
+   tga_footer *footer;
+   char hasa = 0, footer_present = 0, vinverted = 0, rle = 0;
+   int w = 0, h = 0, bpp;
+
+   fd = open(file, O_RDONLY);
+   
+   *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+   if (fd < 0) return EINA_FALSE;
+   if (fstat(fd, &ss) < 0) goto close_file;
+   
+   *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+   if (ss.st_size < (sizeof(tga_header) + sizeof(tga_footer))) goto close_file;
+   seg = mmap(0, ss.st_size, PROT_READ, MAP_SHARED, fd, 0);
+   if (seg == MAP_FAILED) goto close_file;
+   filedata = seg;
+   
+   header = (tga_header *)filedata;
+   // no unaligned data accessed, so ok
+   footer = (tga_footer *)(filedata + (ss.st_size - sizeof(tga_footer)));
+   if (!memcmp(footer->signature, TGA_SIGNATURE, sizeof(footer->signature)))
+     {
+        // footer is ther and matches. this is a tga file - any problems now
+        // are a corrupt file
+        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+        footer_present = 1;
+     }
+   filedata = (char *)filedata + sizeof(tga_header);
+   vinverted = !(header->descriptor & TGA_DESC_VERTICAL);
+   switch (header->imageType)
+     {
+     case TGA_TYPE_COLOR_RLE:
+     case TGA_TYPE_GRAY_RLE:
+        rle = 1;
+        break;
+     case TGA_TYPE_COLOR:
+     case TGA_TYPE_GRAY:
+        rle = 0;
+        break;
+     default:
+        goto close_file;
+     }
+   bpp = header->bpp;
+   if (!((bpp == 32) || (bpp == 24) || (bpp == 16) || (bpp == 8)))
+     goto close_file;
+   if ((bpp == 32) && (header->descriptor & TGA_DESC_ABITS)) hasa = 1;
+   w = (header->widthHi << 8) | header->widthLo;
+   h = (header->heightHi << 8) | header->heightLo;
+   
+   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+       IMG_TOO_BIG(w, h))
+     goto close_file;
+   
+   ie->w = w;
+   ie->h = h;
+   if (hasa) ie->flags.alpha = 1;
+   
+   if (seg != MAP_FAILED) munmap(seg, ss.st_size);
+   close(fd);
+   *error = EVAS_LOAD_ERROR_NONE;
+   return EINA_TRUE;
+
+close_file:
+   if (seg != MAP_FAILED) munmap(seg, ss.st_size);
+   close(fd);
+   return EINA_FALSE;
+}
+
+static Eina_Bool
+evas_image_load_file_data_tga(Image_Entry *ie, const char *file, const char *key __UNUSED__, int *error)
+{
+   int fd;
+   unsigned char *seg = MAP_FAILED, *filedata;
+   struct stat ss;
+   tga_header *header;
+   tga_footer *footer;
+   char hasa = 0, footer_present = 0, vinverted = 0, rle = 0;
+   int w = 0, h = 0, x, y, bpp;
+   unsigned int *surface, *dataptr;
+   unsigned int  datasize;
+   unsigned char *bufptr, *bufend;
+   
+   fd = open(file, O_RDONLY);
+   
+   *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
+   if (fd < 0) return EINA_FALSE;
+   if (fstat(fd, &ss) < 0) goto close_file;
+   
+   *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
+   if (ss.st_size < (sizeof(tga_header) + sizeof(tga_footer))) goto close_file;
+   seg = mmap(0, ss.st_size, PROT_READ, MAP_SHARED, fd, 0);
+   if (seg == MAP_FAILED) goto close_file;
+   filedata = seg;
+   
+   header = (tga_header *)filedata;
+   // no unaligned data accessed, so ok
+   footer = (tga_footer *)(filedata + (ss.st_size - sizeof(tga_footer)));
+   if (!memcmp(footer->signature, TGA_SIGNATURE, sizeof(footer->signature)))
+     {
+        // footer is ther and matches. this is a tga file - any problems now
+        // are a corrupt file
+        *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
+        footer_present = 1;
+     }
+   filedata = (char *)filedata + sizeof(tga_header);
+   vinverted = !(header->descriptor & TGA_DESC_VERTICAL);
+   switch (header->imageType)
+     {
+     case TGA_TYPE_COLOR_RLE:
+     case TGA_TYPE_GRAY_RLE:
+        rle = 1;
+        break;
+     case TGA_TYPE_COLOR:
+     case TGA_TYPE_GRAY:
+        rle = 0;
+        break;
+     default:
+        goto close_file;
+     }
+   bpp = header->bpp;
+   if (!((bpp == 32) || (bpp == 24) || (bpp == 16) || (bpp == 8)))
+     goto close_file;
+   if ((bpp == 32) && (header->descriptor & TGA_DESC_ABITS)) hasa = 1;
+   w = (header->widthHi << 8) | header->widthLo;
+   h = (header->heightHi << 8) | header->heightLo;
+   
+   if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+       IMG_TOO_BIG(w, h))
+     goto close_file;
+   
+   if ((w != ie->w) || (h != ie->h))
+     {
+       *error = EVAS_LOAD_ERROR_GENERIC;
+       goto close_file;
+     }
+   evas_cache_image_surface_alloc(ie, w, h);
+   surface = evas_cache_image_pixels(ie);
+   if (!surface)
+     {
+       *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
+       goto close_file;
+     }
+
+   datasize = ss.st_size - sizeof(tga_header) - header->idLength;
+   if (footer_present)
+     datasize = ss.st_size - sizeof(tga_header) - header->idLength - 
+     sizeof(tga_footer);
+   
+   bufptr = filedata + header->idLength;
+   bufend = filedata + datasize;
+
+   dataptr = surface;
+
+   if (!rle)
+     {
+        for (y = 0; y < h; y++)
+          {
+             if (vinverted)
+               /* some TGA's are stored upside-down! */
+               dataptr = surface + ((h - y - 1) * w);
+             else
+               dataptr = surface + (y * w);
+             switch (bpp)
+               {
+               case 32:
+                  for (x = 0; (x < w) && ((bufptr + 4) <= bufend); x++)
+                    {
+                       if (hasa)
+                         *dataptr = 
+                         ((255 - bufptr[3]) << 24) | (bufptr[2] << 16) |
+                         (bufptr[1] <<  8) | (bufptr[0]      );
+                       else
+                         *dataptr = 
+                         (0xff      << 24) | (bufptr[2] << 16) |
+                         (bufptr[1] <<  8) | (bufptr[0]      );
+                       dataptr++;
+                       bufptr += 4;
+                    }
+                  break;
+               case 24:
+                  for (x = 0; (x < w) && ((bufptr + 3) <= bufend); x++)
+                    {
+                       *dataptr = 
+                         (0xff      << 24) | (bufptr[2] << 16) |
+                         (bufptr[1] <<  8) | (bufptr[0]      );
+                       dataptr++;
+                       bufptr += 3;
+                    }
+                  break;
+               case 16:
+                  for (x = 0; (x < w) && ((bufptr + 3) <= bufend); x++)
+                    {
+                       unsigned char r, g, b, a;
+                       unsigned short tmp;
+                       
+                       tmp = 
+                         (((unsigned short)bufptr[1]) << 8) | 
+                         (((unsigned short)bufptr[0]));
+                       r = (tmp >> 7) & 0xf8; r |= r >> 5;
+                       g = (tmp >> 2) & 0xf8; g |= g >> 5;
+                       b = (tmp << 3) & 0xf8; b |= b >> 5;
+                       a = 0xff;
+                       if ((hasa) && (tmp & 0x8000)) a = 0;
+                       *dataptr = 
+                         (a    << 24) | (r << 16) |
+                         (g    <<  8) | (b      );
+                       dataptr++;
+                       bufptr += 2;
+                    }
+                  break;
+               case 8:
+                  for (x = 0; (x < w) && ((bufptr + 1) <= bufend); x++)
+                    {
+                       *dataptr = 
+                         (0xff      << 24) | (bufptr[0] << 16) |
+                         (bufptr[0] <<  8) | (bufptr[0]      );
+                       dataptr++;
+                       bufptr += 1;
+                    }
+                  break;
+               default:
+                  break;
+               }
+          }
+     }
+   else
+     {
+        int count, i;
+        unsigned char val;
+        unsigned int *dataend;
+        
+        dataptr = surface;
+        dataend = dataptr + (w * h);
+        while ((bufptr < bufend) && (dataptr < dataend))
+          {
+             val = *bufptr;
+             bufptr++;
+             count = (val & 0x7f) + 1;
+             if (val & 0x80) // rel packet
+               {
+                  switch (bpp)
+                    {
+                    case 32:
+                       if (bufptr < (bufend - 4))
+                         {
+                            unsigned char r, g, b, a;
+                            
+                            a = 255 - bufptr[3];
+                            r = bufptr[2];
+                            g = bufptr[1];
+                            b = bufptr[0];
+                            if (!hasa) a = 0xff;
+                            bufptr += 4;
+                            for (i = 0; (i < count) && (dataptr < dataend); i++)
+                              {
+                                 *dataptr = 
+                                   (a << 24) | (r << 16) | (g <<  8) | (b);
+                                 dataptr++;
+                              }
+                         }
+                       break;
+                    case 24:
+                       if (bufptr < (bufend - 3))
+                         {
+                            unsigned char r, g, b;
+                            
+                            r = bufptr[2];
+                            g = bufptr[1];
+                            b = bufptr[0];
+                            bufptr += 3;
+                            for (i = 0; (i < count) && (dataptr < dataend); i++)
+                              {
+                                 *dataptr = 
+                                   (0xff << 24) | (r << 16) | (g <<  8) | (b);
+                                 dataptr++;
+                              }
+                         }
+                       break;
+                    case 16:
+                       if (bufptr < (bufend - 2))
+                         {
+                            unsigned char r, g, b, a;
+                            unsigned short tmp;
+                            
+                            tmp = 
+                              (((unsigned short)bufptr[1]) << 8) | 
+                              (((unsigned short)bufptr[0]));
+                            r = (tmp >> 7) & 0xf8; r |= r >> 5;
+                            g = (tmp >> 2) & 0xf8; g |= g >> 5;
+                            b = (tmp << 3) & 0xf8; b |= b >> 5;
+                            a = 0xff;
+                            if ((hasa) && (tmp & 0x8000)) a = 0;
+                            bufptr += 2;
+                            for (i = 0; (i < count) && (dataptr < dataend); i++)
+                              {
+                                 *dataptr = 
+                                   *dataptr = 
+                                   (a    << 24) | (r << 16) |
+                                   (g    <<  8) | (b      );
+                                 dataptr++;
+                              }
+                         }
+                       break;
+                    case 8:
+                       if (bufptr < (bufend - 1))
+                         {
+                            unsigned char g;
+                            
+                            g = bufptr[0];
+                            bufptr += 1;
+                            for (i = 0; (i < count) && (dataptr < dataend); i++)
+                              {
+                                 *dataptr = 
+                                   (0xff << 24) | (g << 16) | (g <<  8) | (g);
+                                 dataptr++;
+                              }
+                         }
+                       break;
+                    default:
+                       break;
+                    }
+               }
+             else // raw
+               {
+                  switch (bpp)
+                    {
+                    case 32:
+                       for (i = 0; (i < count) && (bufptr < (bufend - 4)) && (dataptr < dataend); i++)
+                         {
+                            if (hasa)
+                              *dataptr = 
+                              ((255 - bufptr[3]) << 24) | (bufptr[2] << 16) |
+                              (bufptr[1] <<  8) | (bufptr[0]      );
+                            else
+                              *dataptr = 
+                              (0xff      << 24) | (bufptr[2] << 16) |
+                              (bufptr[1] <<  8) | (bufptr[0]      );
+                            dataptr++;
+                            bufptr += 4;
+                         }
+                       break;
+                    case 24:
+                       for (i = 0; (i < count) && (bufptr < (bufend - 3)) && (dataptr < dataend); i++)
+                         {
+                            *dataptr = 
+                              (0xff      << 24) | (bufptr[2] << 16) |
+                              (bufptr[1] <<  8) | (bufptr[0]      );
+                            dataptr++;
+                            bufptr += 3;
+                         }
+                       break;
+                    case 16:
+                       for (i = 0; (i < count) && (bufptr < (bufend - 2)) && (dataptr < dataend); i++)
+                         {
+                            unsigned char r, g, b, a;
+                            unsigned short tmp;
+                            
+                            tmp = 
+                              (((unsigned short)bufptr[1]) << 8) | 
+                              (((unsigned short)bufptr[0]));
+                            r = (tmp >> 7) & 0xf8; r |= r >> 5;
+                            g = (tmp >> 2) & 0xf8; g |= g >> 5;
+                            b = (tmp << 3) & 0xf8; b |= b >> 5;
+                            a = 0xff;
+                            if ((hasa) && (tmp & 0x8000)) a = 0;
+                            *dataptr = 
+                              (a    << 24) | (r << 16) |
+                              (g    <<  8) | (b      );
+                            dataptr++;
+                            bufptr += 2;
+                         }
+                       break;
+                    case 8:
+                       for (i = 0; (i < count) && (bufptr < (bufend - 1)) && (dataptr < dataend); i++)
+                         {
+                            *dataptr = 
+                              (0xff      << 24) | (bufptr[0] << 16) |
+                              (bufptr[0] <<  8) | (bufptr[0]      );
+                            dataptr++;
+                            bufptr += 1;
+                         }
+                       break;
+                    default:
+                       break;
+                    }
+               }
+          }
+        if (vinverted)
+          {
+             unsigned int *adv, *adv2, tmp;
+             
+             adv = surface;
+             adv2 = surface + (w * (h - 1));
+             for (y = 0; y < (h / 2); y++)
+               {
+                  for (x = 0; x < w; x++)
+                    {
+                       tmp = adv[x];
+                       adv[x] = adv2[x];
+                       adv2[x] = tmp;
+                    }
+                  adv2 -= w;
+                  adv += w;
+               }                                        
+          }
+     }
+   
+   evas_common_image_premul(ie);
+   
+   if (seg != MAP_FAILED) munmap(seg, ss.st_size);
+   close(fd);
+   *error = EVAS_LOAD_ERROR_NONE;
+   return EINA_TRUE;
+
+close_file:
+   if (seg != MAP_FAILED) munmap(seg, ss.st_size);
+   close(fd);
+   return EINA_FALSE;
+}
+
+static int
+module_open(Evas_Module *em)
+{
+   if (!em) return 0;
+   em->functions = (void *)(&evas_image_load_tga_func);
+   return 1;
+}
+
+static void
+module_close(Evas_Module *em)
+{
+}
+
+static Evas_Module_Api evas_modapi =
+{
+   EVAS_MODULE_API_VERSION,
+   "tga",
+   "none",
+   {
+     module_open,
+     module_close
+   }
+};
+
+EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, tga);
+
+#ifndef EVAS_STATIC_BUILD_TGA
+EVAS_EINA_MODULE_DEFINE(image_loader, tga);
+#endif