Mathieu Taillefumier <mathieu.taillefumier@free.fr>
Iván Briano <ivan@profusion.mobi>
Gustavo Lima Chaves <glima@profusion.mobi>
+Saumsung Electronics <tbd>
+Samsung SAIT <tbd>
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
-# 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.
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])
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
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")
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"
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
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)
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
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
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
-Revision 48959
-Last Changed Rev 48959
+Revision 49550
+Last Changed Rev 49540
%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
%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
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
%{_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)
])
+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)
# 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
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,
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
*
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);
/**
int usage;
int limit;
int references;
+#ifdef EVAS_FRAME_QUEUING
+ LK(lock);
+#endif
};
struct _Evas_Cache_Engine_Image_Func
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)
{
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
{
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
{
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
{
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
{
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));
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;
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);
#ifdef BUILD_ASYNC_PRELOAD
LKD(ie->lock);
#endif
+#ifdef EVAS_FRAME_QUEUING
+ LKD(ie->lock_references);
+#endif
cache->func.dealloc(ie);
}
ie->allocated.w = 0;
ie->allocated.h = 0;
+#ifdef EVAS_FRAME_QUEUING
+ LKI(ie->lock_references);
+#endif
ie->references = 0;
ie->cache = cache;
static void
_evas_cache_image_async_cancel(void *data)
{
+ Evas_Cache_Image *cache = NULL;
Image_Entry *ie = (Image_Entry *) data;
ie->preload = NULL;
_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
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 *
new->preload = NULL;
new->pending = NULL;
+#ifdef EVAS_FRAME_QUEUING
+ LKI(new->lock);
+#endif
+
return new;
}
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)
eina_hash_free(cache->activ);
eina_hash_free(cache->inactiv);
+#ifdef EVAS_FRAME_QUEUING
+ LKU(cache->lock);
+ LKD(cache->lock);
+#endif
+
free(cache);
}
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;
_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;
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;
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)
{
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);
{
Image_Entry *im_dirty = im;
Evas_Cache_Image *cache;
+ int references;
assert(im);
assert(im->cache);
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
{
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);
}
{
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))
{
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);
}
_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);
_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);
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))
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);
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
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
}
evas_common_rgba_image_scalecache_dirty(im);
cache->func.destructor(im);
-
+
#ifdef BUILD_ASYNC_PRELOAD
LKU(im->lock);
#endif
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;
}
#ifdef BUILD_ASYNC_PRELOAD
_evas_preload_thread_init();
#endif
+#ifdef EVAS_FRAME_QUEUING
+ evas_common_frameq_init();
+#endif
return _evas_init_count;
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
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;
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;
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);
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);
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;
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);
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);
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);
}
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);
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)
{
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,
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);
}
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,
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;
}
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);
free(cb);
}
+ evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
o->data = NULL;
}
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)
{
MAGIC_CHECK_END();
if (e->hinting == hinting) return;
e->hinting = hinting;
+
EINA_INLIST_FOREACH(e->layers, lay)
{
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,
"É\0" "\xc3\x89\0"
"Ê\0" "\xc3\x8a\0"
"Ë\0" "\xc3\x8b\0"
- "È\0" "\xc3\x8c\0"
- "É\0" "\xc3\x8d\0"
+ "Ì\0" "\xc3\x8c\0"
+ "Í\0" "\xc3\x8d\0"
"Î\0" "\xc3\x8e\0"
"Ï\0" "\xc3\x8f\0"
"&Eth;\0" "\xc3\x90\0"
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;
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;
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);
}
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);
}
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.
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;
}
evas_convert_yuv.h \
evas_draw.h \
evas_font.h \
+evas_font_private.h \
evas_gradient.h \
evas_gradient_private.h \
evas_image.h \
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
#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)
// 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();
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);
}
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;
_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);
// 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);
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);
}
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
}
#include <assert.h>
+#include "evas_font_private.h" /* for Frame-Queuing support */
+
extern FT_Library evas_ft_lib;
static int font_cache_usage = 0;
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
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);
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);
}
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;
{
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;
}
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;
}
{
if (fi->src->current_size != fi->size)
{
+ FTLOCK();
FT_Activate_Size(fi->ft.size);
+ FTUNLOCK();
fi->src->current_size = fi->size;
}
}
int ret;
int error;
+ FTLOCK();
error = FT_New_Size(fi->src->ft.face, &(fi->ft.size));
if (!error)
{
fi->real_size = fi->size;
error = FT_Set_Pixel_Sizes(fi->src->ft.face, 0, fi->real_size);
}
+ FTUNLOCK();
if (error)
{
int i;
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? */
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;
}
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;
}
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--;
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);
}
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)
{
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
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;
}
--- /dev/null
+#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 */
#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,
* 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);
goto on_correct;
}
+ FTUNLOCK();
error = 0;
on_correct:
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];)
{
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);
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);
#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" },
{ "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
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;
}
#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);
{
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;
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;
{
#ifdef SCALECACHE
init--;
- LKD(cache_lock);
+ if (init ==0)
+ LKD(cache_lock);
#endif
}
{
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)
{
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);
{
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))
// 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
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;
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);
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);
}
}
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)
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)
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,
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)
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)
}
#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)
#include "evas_common.h"
#include "evas_intl_utils.h"
+#include "evas_font_private.h"
+
#ifdef INTERNATIONAL_SUPPORT
#include <fribidi/fribidi.h>
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));
}
fribidi_unicode_to_utf8(unicode_out, len, text_out);
-
+ FBDUNLOCK();
+
*ret_len = len;
return text_out;
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
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
{
# 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--;
}
" 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"
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"
#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);
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;
}
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
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
#ifdef BUILD_PTHREAD
int i, y, h;
+#ifdef EVAS_FRAME_QUEUING
+ return;
+#endif
+
if (!im->pipe) return;
if (thread_num == 1) return;
y = 0;
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)
{
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);
}
/* 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);
}
}
{
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;
{
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;
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);
}
{
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;
/* 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;
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;
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;
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;
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;
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;
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;
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
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
}
}
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);
}
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
evas_common_pipe_map4_render(root);
}
+
#endif
#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
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 */
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);
# 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));
# 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
# 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
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;
time_t laststat;
int references;
+#ifdef EVAS_FRAME_QUEUING
+ LK(lock_references); // needed for accessing references
+#endif
unsigned char scale;
};
#ifdef BUILD_PIPE_RENDER
+#include "../engines/common/evas_map_image.h"
+
struct _RGBA_Pipe_Op
{
RGBA_Draw_Context context;
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;
} 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;
} 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;
};
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
#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;
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
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;
}
} 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
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;
}
unsigned short height;
unsigned char *mask;
} *shape;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
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;
}
IDirectFB *dfb;
IDirectFBSurface *surface;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
int refresh;
int rotation;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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;
}
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;
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);
_evas_gl_common_context = gc;
+ gc->shader.render_op = EVAS_RENDER_BLEND;
+
if (!shared)
{
GLint linked;
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;
}
_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))
HWND window;
int depth;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
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;
}
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
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;
}
}
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;
}
}
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;
# include <X11/Xresource.h> // xres - dpi
#endif
# else
-# include <GL/glx.h>
# include <X11/Xlib.h>
# include <X11/Xatom.h>
# include <X11/Xutil.h>
struct {
CGContextRef context;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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;
}
int rotation;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
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;
}
int noframe : 1;
int alpha : 1;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
int (*suspend) (int backend);
int (*resume) (int backend);
} func;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
info->magic.magic = rand();
info->func.suspend = _suspend;
info->func.resume = _resume;
+ info->render_mode = EVAS_RENDER_MODE_BLOCKING;
return info;
e = NULL;
}
Drawable drawable;
int rotation;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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;
}
int rotation;
unsigned int fullscreen : 1;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
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;
}
unsigned int layered : 1;
unsigned int fullscreen : 1;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
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
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
{
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
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
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
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
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,
(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;
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 *
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
QWidget *target;
int rotation;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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;
}
int noframe : 1;
int alpha : 1;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
} func;
int mask_changed;
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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);
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 */
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;
}
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
{
int ponebuf = 0;
+#ifdef EVAS_FRAME_QUEUING
+ evas_common_frameq_flush ();
+#endif
re = e->engine.data.output;
ponebuf = re->ob->onebuf;
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
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;
}
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;
return (re->ob->priv.destination_alpha) || (re->outbuf_alpha_get(re->ob));
}
+
/* module advertising code */
static int
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;
}
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;
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);
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)
{
else
lbytes = ((w + 31) / 32) * 4;
sz = lbytes * h;
+ SHMPOOL_LOCK();
EINA_LIST_FOREACH(shmpool, l, xob2)
{
int szdif;
}
}
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;
xob->xim->height = xob->h;
xob->xim->bytes_per_line = xob->bpl;
shmsize -= xob->psize * (xob->xim->depth / 8);
+ SHMPOOL_UNLOCK();
return xob;
}
// 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)) ||
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);
static void
_clear_xob(int sync)
{
+ SHMPOOL_LOCK();
while (shmpool)
{
X_Output_Buffer *xob;
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;
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)
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);
}
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;
}
/* 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;
}
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;
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
}
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)
{
if (obr->mxob) _unfind_xob(obr->mxob, 0);
free(obr);
}
+#ifdef EVAS_FRAME_QUEUING
+ LKU(buf->priv.lock);
+#endif
_clear_xob(0);
}
}
{
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
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
void *visual;
unsigned char destination_alpha : 1;
} info;
+
+ /* non-blocking or blocking mode */
+ Evas_Engine_Render_Mode render_mode;
};
#endif
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;
}
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
+
--- /dev/null
+
+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
--- /dev/null
+
+#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
#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)
--- /dev/null
+
+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
--- /dev/null
+
+#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