cedric's sdl patch.


			
			
				devs/devilhorns/wayland_egl
			
			
		
Carsten Haitzler 16 years ago
parent 64171b5ca6
commit 6c167c3a6d
  1. 7
      legacy/evas/README.in
  2. 60
      legacy/evas/configure.in
  3. 8
      legacy/evas/src/lib/Makefile.am
  4. 6
      legacy/evas/src/lib/cache/.cvsignore
  5. 18
      legacy/evas/src/lib/cache/Makefile.am
  6. 496
      legacy/evas/src/lib/cache/evas_cache_engine_image.c
  7. 593
      legacy/evas/src/lib/cache/evas_cache_image.c
  8. 3
      legacy/evas/src/lib/canvas/evas_main.c
  9. 20
      legacy/evas/src/lib/canvas/evas_object_image.c
  10. 1
      legacy/evas/src/lib/engines/common/Makefile.am
  11. 123
      legacy/evas/src/lib/engines/common/evas_image_data.c
  12. 110
      legacy/evas/src/lib/engines/common/evas_image_load.c
  13. 466
      legacy/evas/src/lib/engines/common/evas_image_main.c
  14. 18
      legacy/evas/src/lib/engines/common/evas_pipe.c
  15. 4
      legacy/evas/src/lib/imaging/evas_imaging.c
  16. 221
      legacy/evas/src/lib/include/evas_common.h
  17. 1
      legacy/evas/src/modules/engines/Makefile.am
  18. 6
      legacy/evas/src/modules/engines/buffer/evas_outbuf.c
  19. 8
      legacy/evas/src/modules/engines/fb/evas_outbuf.c
  20. 29
      legacy/evas/src/modules/engines/gl_common/evas_gl_image.c
  21. 5
      legacy/evas/src/modules/engines/software_16/evas_soft16_main.c
  22. 157
      legacy/evas/src/modules/engines/software_generic/evas_engine.c
  23. 6
      legacy/evas/src/modules/engines/software_sdl/.cvsignore
  24. 24
      legacy/evas/src/modules/engines/software_sdl/Evas_Engine_SDL.h
  25. 28
      legacy/evas/src/modules/engines/software_sdl/Makefile.am
  26. 1006
      legacy/evas/src/modules/engines/software_sdl/evas_engine_sdl.c
  27. 33
      legacy/evas/src/modules/engines/software_sdl/evas_engine_sdl.h
  28. 10
      legacy/evas/src/modules/engines/software_x11/evas_outbuf.c
  29. 10
      legacy/evas/src/modules/engines/software_xcb/evas_outbuf.c
  30. 4
      legacy/evas/src/modules/engines/xrender_x11/evas_engine.c
  31. 6
      legacy/evas/src/modules/engines/xrender_x11/evas_engine_gradient.c
  32. 10
      legacy/evas/src/modules/engines/xrender_x11/evas_engine_image.c
  33. 22
      legacy/evas/src/modules/engines/xrender_xcb/evas_engine_image.c

@ -14,6 +14,7 @@ Optional:
X11R6
XCB
DirectFB
SDL
OpenGL (underway at the moment)
Linux
Qtopia
@ -127,6 +128,12 @@ really good. it may also be useful for embedded devices supported by
directfb that offer acceleration (otherwise the fb driver will likely be
faster).
--enable-sdl
this is the sdl engine that uses sdl library (http://www.libsdl.org). This
library should work on many operating system.
CPU:
--enable-cpu-c

@ -71,6 +71,8 @@ qt_dir=""
qt_cflags=""
qt_libs=""
qt_moc="moc"
sdl_cflags=""
sdl_libs=""
#####################################################################
@ -356,6 +358,58 @@ if test "x$have_evas_directfb" = "xyes"; then
fi
AM_CONDITIONAL(BUILD_ENGINE_DIRECTFB, test "x$have_evas_directfb" = "xyes")
#######################################
## SDL
AC_ARG_WITH(sdl-config, [ --with-sdl-config=SDL_CONFIG use sdl-config specified],
[ SDL_CONFIG=$withval;
echo "using "$SDL_CONFIG" for sdl-config"; ],
[ if test -z "$SDL_CONFIG"; then
AC_PATH_PROG(SDL_CONFIG, "sdl-config", "", $PATH)
fi
])
if test -z "$SDL_CONFIG" ; then SDL_CONFIG="sdl-config"; fi
#######################################
## Check if we should build the sdl engine
have_evas_sdl="no";
ENGINE_SDL_PRG="";
## Automatic check...
AC_CHECK_HEADER(SDL/SDL.h,
[ have_evas_sdl="yes" ],
[ have_evas_sdl="no" ]
)
# Manual override
AC_MSG_CHECKING(whether SDL backend is to be built)
AC_ARG_ENABLE(sdl, AC_HELP_STRING([--enable-sdl],[enable the SDL rendering backend]), [
if test x"$enableval" = x"yes" ; then
AC_MSG_RESULT(yes)
have_evas_sdl="yes"
else
AC_MSG_RESULT(no)
have_evas_sdl="no"
fi
], [
AC_MSG_RESULT($have_evas_sdl)
]
)
if test "x$have_evas_sdl" = "xyes"; then
if test "x$SDL_CONFIG" = "xno" ; then
have_evas_sdl= "no"
AM_CONDITIONAL(BUILD_ENGINE_SDL, false)
AC_MSG_RESULT(disabling sdl engine)
else
ENGINE_SDL_PRG="evas_sdl_test"
sdl_cflags=`$SDL_CONFIG --cflags`
sdl_libs=`$SDL_CONFIG --libs`
AM_CONDITIONAL(BUILD_ENGINE_SDL, true)
AC_DEFINE(BUILD_ENGINE_SDL, 1, [SDL Rendering Backend])
fi
else
AM_CONDITIONAL(BUILD_ENGINE_SDL, false)
have_evas_sdl="no"
fi
#######################################
## Check if we should build the fb engine
have_evas_fb="no";
@ -2017,6 +2071,9 @@ AC_SUBST(ddraw_libs)
AC_SUBST(x_cflags)
AC_SUBST(x_libs)
AC_SUBST(sdl_cflags)
AC_SUBST(sdl_libs)
AC_SUBST(xcb_cflags)
AC_SUBST(xcb_libs)
AC_SUBST(xcbrender_cflags)
@ -2068,6 +2125,7 @@ src/lib/canvas/Makefile
src/lib/data/Makefile
src/lib/file/Makefile
src/lib/imaging/Makefile
src/lib/cache/Makefile
src/lib/engines/Makefile
src/lib/engines/common/Makefile
src/lib/engines/common/evas_op_add/Makefile
@ -2093,6 +2151,7 @@ src/modules/engines/cairo_common/Makefile
src/modules/engines/cairo_x11/Makefile
src/modules/engines/xrender_x11/Makefile
src/modules/engines/xrender_xcb/Makefile
src/modules/engines/software_sdl/Makefile
src/modules/engines/glitz_x11/Makefile
src/modules/engines/software_16/Makefile
src/modules/engines/software_16_x11/Makefile
@ -2137,6 +2196,7 @@ echo " Software Framebuffer....: $have_evas_fb"
echo " Software Qtopia.........: $have_evas_qtopia"
echo " Software Memory Buffer..: $have_evas_buffer"
echo " DirectFB................: $have_evas_directfb"
echo " SDL.....................: $have_evas_sdl"
echo " OpenGL X11..............: $have_evas_gl_x11"
echo " Cairo X11...............: $have_evas_cairo_x11"
echo " XRender X11.............: $have_evas_xrender_x11"

@ -1,6 +1,6 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = canvas data file engines imaging include
SUBDIRS = canvas data cache file engines imaging include
AUTOMAKE_OPTIONS = 1.4 foreign
@ -24,6 +24,7 @@ libevas_la_LIBADD = \
canvas/libevas_canvas.la \
data/libevas_data.la \
file/libevas_file.la \
cache/libevas_cache.la \
imaging/libevas_imaging.la \
engines/common/libevas_engine_common.la \
-lm \
@ -39,6 +40,9 @@ libevas_la_DEPENDENCIES = \
canvas/libevas_canvas.la \
data/libevas_data.la \
file/libevas_file.la \
cache/libevas_cache.la \
imaging/libevas_imaging.la \
engines/common/libevas_engine_common.la
engines/common/libevas_engine_common.la
libevas_la_LDFLAGS = @create_shared_lib@ -version-info 1:0:0

@ -0,0 +1,6 @@
Makefile.in
Makefile
.deps
.libs
*.la
*.lo

@ -0,0 +1,18 @@
## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = 1.4 foreign
# A list of all the files in the current directory which can be regenerated
MAINTAINERCLEANFILES = Makefile.in
INCLUDES = -I. \
-I$(top_srcdir)/src/lib \
-I$(top_srcdir)/src/lib/include \
@FREETYPE_CFLAGS@
noinst_LTLIBRARIES = libevas_cache.la
libevas_cache_la_SOURCES = \
evas_cache_image.c \
evas_cache_engine_image.c
libevas_cache_la_DEPENDENCIES = $(top_builddir)/config.h

@ -0,0 +1,496 @@
#include <assert.h>
#include <Evas.h>
#include "evas_common.h"
#include "evas_private.h"
EAPI int
evas_cache_engine_image_usage_get(Evas_Cache_Engine_Image* cache)
{
assert(cache != NULL);
return cache->usage;
}
EAPI int
evas_cache_engine_image_get(Evas_Cache_Engine_Image* cache)
{
assert(cache != NULL);
return cache->limit;
}
EAPI void
evas_cache_engine_image_set(Evas_Cache_Engine_Image* cache, int limit)
{
assert(cache != NULL);
cache->limit = limit;
}
EAPI Evas_Cache_Engine_Image*
evas_cache_engine_image_init(const Evas_Cache_Engine_Image_Func *cb, Evas_Cache_Image *parent)
{
Evas_Cache_Engine_Image* new;
new = malloc(sizeof (Evas_Cache_Engine_Image));
if (!new)
return NULL;
new->func = *cb;
new->limit = -1;
new->usage = 0;
new->dirty = NULL;
new->activ = NULL;
new->parent = parent;
parent->references++;
return new;
}
static Evas_Bool
_evas_cache_engine_image_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata)
{
Evas_Cache_Engine_Image* cache = fdata;
RGBA_Engine_Image* eim = data;
RGBA_Image* im;
if (cache->func.debug)
cache->func.debug("shutdown-engine-activ", eim);
evas_stringshare_del(eim->cache_key);
eim->cache_key = NULL;
im = eim->src;
cache->func.destructor(eim);
if (im) evas_cache_image_drop(im);
free(eim);
return 1;
}
EAPI void
evas_cache_engine_image_shutdown(Evas_Cache_Engine_Image* cache)
{
RGBA_Engine_Image* eim;
RGBA_Image* im;
assert(cache != NULL);
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
while (cache->dirty)
{
eim = (RGBA_Engine_Image*) cache->dirty;
im = eim->src;
cache->dirty = evas_object_list_remove(cache->dirty, eim);
if (cache->func.debug)
cache->func.debug("shutdown-engine-dirty", eim);
cache->func.destructor(eim);
if (im) evas_cache_image_drop(im);
free(eim);
}
evas_hash_foreach(cache->activ, _evas_cache_engine_image_free_cb, cache);
evas_hash_free(cache->activ);
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_request(Evas_Cache_Engine_Image *cache, const char *file, const char *key,
RGBA_Image_Loadopts *lo, void *data, int *error)
{
RGBA_Engine_Image* eim;
RGBA_Image* im;
const char* ekey;
assert(cache != NULL);
im = evas_cache_image_request(cache->parent, file, key, lo, error);
if (!im)
{
*error = -1;
return NULL;
}
if (cache->func.key)
ekey = cache->func.key(im, file, key, lo, data);
else
ekey = evas_stringshare_add(im->cache_key);
if (!ekey)
{
*error = -1;
evas_cache_image_drop(im);
return NULL;
}
eim = evas_hash_find(cache->activ, ekey);
if (eim) goto on_ok;
eim = malloc(sizeof(RGBA_Engine_Image));
if (!eim) goto on_error;
eim->src = im;
eim->engine_data = NULL;
eim->flags.dirty = 0;
eim->flags.loaded = 0;
eim->cache = cache;
eim->cache_key = ekey;
eim->references = 0;
*error = cache->func.constructor(eim, data);
if (cache->func.debug)
cache->func.debug("constructor-engine", eim);
if (*error != 0) goto on_error;
cache->activ = evas_hash_add(cache->activ, ekey, eim);
cache->usage += strlen(eim->cache_key) + 1 + cache->func.mem_size_get(eim);
on_ok:
eim->references++;
return eim;
on_error:
evas_cache_image_drop(im);
evas_stringshare_del(ekey);
if (eim) free(eim);
return NULL;
}
static void
_evas_cache_engine_image_free(Evas_Cache_Engine_Image* cache, RGBA_Engine_Image *eim)
{
int size;
size = cache->func.mem_size_get(eim);
cache->usage -= size;
if (cache->func.debug)
cache->func.debug("drop-engine", eim);
cache->func.destructor(eim);
if (eim->src) evas_cache_image_drop(eim->src);
if (eim->cache_key) evas_stringshare_del(eim->cache_key);
free(eim);
}
EAPI void
evas_cache_engine_image_drop(RGBA_Engine_Image *eim)
{
Evas_Cache_Engine_Image* cache;
assert(eim);
assert(eim->cache);
eim->references--;
cache = eim->cache;
if (eim->flags.dirty)
{
cache->dirty = evas_object_list_remove(cache->dirty, eim);
_evas_cache_engine_image_free(cache, eim);
return ;
}
if (eim->references == 0)
{
cache->activ = evas_hash_del(cache->activ, eim->cache_key, eim);
_evas_cache_engine_image_free(cache, eim);
return ;
}
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_dirty(RGBA_Engine_Image *eim, int x, int y, int w, int h)
{
RGBA_Engine_Image* eim_dirty = eim;
RGBA_Image* im;
RGBA_Image* im_dirty;
Evas_Cache_Engine_Image* cache;
assert(eim);
assert(eim->cache);
cache = eim->cache;
if (!(eim->flags.dirty))
{
im = eim->src;
im_dirty = evas_cache_image_dirty(im, x, y, w, h);
/* If im == im_dirty, this meens that we have only one reference to the eim. */
if (im != im_dirty)
{
if (eim->references == 1)
{
const char* hkey;
hkey = eim->cache_key;
cache->activ = evas_hash_del(cache->activ, hkey, eim);
cache->usage -= strlen(hkey) + 1;
evas_stringshare_del(hkey);
eim_dirty = eim;
eim_dirty->src = im_dirty;
}
else
{
int error;
eim_dirty = malloc(sizeof(RGBA_Engine_Image));
if (!eim_dirty) goto on_error;
eim_dirty->src = im_dirty;
eim_dirty->engine_data = NULL;
eim_dirty->flags.dirty = 1;
eim_dirty->flags.loaded = 1;
eim_dirty->cache = cache;
eim_dirty->cache_key = NULL;
eim_dirty->references = 1;
error = cache->func.dirty(eim_dirty, eim);
if (cache->func.debug)
cache->func.debug("dirty-engine", eim_dirty);
if (error != 0) goto on_error;
cache->usage += cache->func.mem_size_get(eim_dirty);
evas_cache_engine_image_drop(eim);
}
eim_dirty->cache_key = NULL;
eim_dirty->flags.dirty = 1;
cache->dirty = evas_object_list_prepend(cache->dirty, eim_dirty);
}
}
if (cache->func.dirty_region)
cache->func.dirty_region(eim_dirty, x, y, w, h);
if (cache->func.debug)
cache->func.debug("dirty-region-engine", eim_dirty);
return eim_dirty;
on_error:
if (eim) evas_cache_engine_image_drop(eim);
if (eim_dirty)
evas_cache_engine_image_drop(eim_dirty);
else
if (im_dirty) evas_cache_image_drop(im_dirty);
return NULL;
}
static RGBA_Engine_Image*
_evas_cache_engine_image_push_dirty(Evas_Cache_Engine_Image *cache, RGBA_Image *im, void* engine_data)
{
RGBA_Engine_Image *eim;
int error;
eim = malloc(sizeof(RGBA_Engine_Image));
if (!eim) goto on_error;
eim->src = im;
eim->engine_data = NULL;
eim->flags.dirty = 1;
eim->flags.loaded = 1;
eim->cache = cache;
eim->cache_key = NULL;
eim->references = 1;
error = cache->func.update_data(eim, engine_data);
if (cache->func.debug)
cache->func.debug("dirty-update_data-engine", eim);
if (error != 0) goto on_error;
cache->dirty = evas_object_list_prepend(cache->dirty, eim);
return eim;
on_error:
if (eim)
evas_cache_engine_image_drop(eim);
else
evas_cache_image_drop(im);
return NULL;
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_copied_data(Evas_Cache_Engine_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace, void* engine_data)
{
RGBA_Image *im;
assert(cache);
im = evas_cache_image_copied_data(cache->parent, w, h, image_data, alpha, cspace);
return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_data(Evas_Cache_Engine_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace, void* engine_data)
{
RGBA_Image *im;
assert(cache);
im = evas_cache_image_data(cache->parent, w, h, image_data, alpha, cspace);
return _evas_cache_engine_image_push_dirty(cache, im, engine_data);
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_size_set(RGBA_Engine_Image *eim, int w, int h)
{
Evas_Cache_Engine_Image* cache;
RGBA_Engine_Image* new;
RGBA_Image* im;
int error;
assert(eim);
assert(eim->src);
assert(eim->cache);
assert(eim->references > 0);
if (eim->src->image->w == w
&& eim->src->image->h == h)
return eim;
cache = eim->cache;
im = evas_cache_image_size_set(eim->src, w, h);
/* Good idea to call update_data ? */
if (im == eim->src) return eim;
eim->src = NULL;
new = malloc(sizeof(RGBA_Engine_Image));
if (!new) goto on_error;
new->src = im;
new->engine_data = NULL;
new->flags = eim->flags;
new->flags.loaded = 1;
new->cache = cache;
new->cache_key = NULL;
new->references = 1;
error = cache->func.size_set(new, eim);
if (error) goto on_error;
assert(new->engine_data != eim->engine_data);
cache->usage += cache->func.mem_size_get(new);
if (new->flags.dirty || eim->references > 1)
{
new->flags.dirty = 1;
cache->dirty = evas_object_list_prepend(cache->dirty, new);
}
else
{
char* cache_key = NULL;
cache_key = eim->cache_key ? evas_stringshare_add(eim->cache_key) : NULL;
new->cache_key = cache_key;
cache->activ = evas_hash_add(cache->activ, cache_key, new);
cache->usage += strlen(new->cache_key) + 1;
}
evas_cache_engine_image_drop(eim);
return new;
on_error:
if (new)
evas_cache_engine_image_drop(new);
else
if (im)
evas_cache_image_drop(im);
evas_cache_engine_image_drop(eim);
return NULL;
}
EAPI void
evas_cache_engine_image_load_data(RGBA_Engine_Image *eim)
{
Evas_Cache_Engine_Image* cache;
int size;
assert(eim);
assert(eim->src);
assert(eim->cache);
if (eim->flags.loaded) return ;
evas_cache_image_load_data(eim->src);
cache = eim->cache;
if (cache->func.debug)
cache->func.debug("load-engine", eim);
size = cache->func.mem_size_get(eim);
cache = eim->cache;
cache->func.load(eim, eim->src);
cache->usage += cache->func.mem_size_get(eim) - size;
eim->flags.loaded = 1;
}
EAPI RGBA_Engine_Image*
evas_cache_engine_image_engine(Evas_Cache_Engine_Image *cache, void *engine_data)
{
RGBA_Engine_Image* eim;
int error;
eim = malloc(sizeof(RGBA_Engine_Image));
if (!eim) goto on_error;
eim->src = evas_cache_image_empty(cache->parent);
if (!eim->src) goto on_error;
eim->engine_data = NULL;
eim->flags.dirty = 1;
eim->flags.loaded = 1;
eim->cache = cache;
eim->cache_key = NULL;
eim->references = 1;
error = cache->func.update_data(eim, engine_data);
if (cache->func.debug)
cache->func.debug("update_data-engine", eim);
if (error != 0) goto on_error;
cache->dirty = evas_object_list_prepend(cache->dirty, eim);
return eim;
on_error:
if (eim)
evas_cache_engine_image_drop(eim);
return NULL;
}
EAPI void
evas_cache_engine_image_colorspace(RGBA_Engine_Image* eim, int cspace, void* engine_data)
{
Evas_Cache_Engine_Image* cache = eim->cache;
assert(cache);
cache->func.destructor(eim);
evas_cache_image_colorspace(eim->src, cspace);
cache->func.constructor(eim, engine_data);
if (cache->func.debug)
cache->func.debug("cosntructor-colorspace-engine", eim);
}

@ -0,0 +1,593 @@
#include <stdlib.h>
#include <assert.h>
#include <Evas.h>
#include "evas_common.h"
#include "evas_private.h"
EAPI int
evas_cache_image_usage_get(Evas_Cache_Image *cache)
{
assert(cache != NULL);
return cache->usage;
}
EAPI int
evas_cache_image_get(Evas_Cache_Image *cache)
{
assert(cache != NULL);
return cache->limit;
}
EAPI void
evas_cache_image_set(Evas_Cache_Image *cache, int limit)
{
assert(cache != NULL);
cache->limit = limit;
}
EAPI Evas_Cache_Image*
evas_cache_image_init(const Evas_Cache_Image_Func *cb)
{
Evas_Cache_Image* new;
new = malloc(sizeof (Evas_Cache_Image));
if (!new)
return NULL;
new->func = *cb;
new->limit = -1;
new->usage = 0;
new->dirty = NULL;
new->lru = NULL;
new->inactiv = NULL;
new->activ = NULL;
new->references = 1;
return new;
}
static Evas_Bool
_evas_cache_image_free_cb(Evas_Hash *hash, const char *key, void *data, void *fdata)
{
Evas_Cache_Image* cache = fdata;
RGBA_Image* im = data;
if (cache->func.debug)
cache->func.debug("shutdown-activ", im);
free(im->cache_key);
im->cache_key = NULL;
cache->func.destructor(im);
evas_common_image_delete(im);
return 1;
}
EAPI void
evas_cache_image_shutdown(Evas_Cache_Image *cache)
{
RGBA_Image* im;
assert(cache != NULL);
cache->references--;
if (cache->references > 0)
return ;
while (cache->lru)
{
im = (RGBA_Image*) cache->lru;
cache->lru = evas_object_list_remove(cache->lru, im);
free(im->cache_key);
im->cache_key = NULL;
if (cache->func.debug)
cache->func.debug("shutdown-lru", im);
cache->func.destructor(im);
evas_common_image_delete(im);
}
/* This is mad, I am about to destroy image still alive, but we need to prevent leak. */
while (cache->dirty)
{
im = (RGBA_Image*) cache->dirty;
cache->dirty = evas_object_list_remove(cache->dirty, im);
if (cache->func.debug)
cache->func.debug("shutdown-dirty", im);
cache->func.destructor(im);
evas_common_image_delete(im);
}
evas_hash_foreach(cache->activ, _evas_cache_image_free_cb, cache);
evas_hash_free(cache->activ);
evas_hash_free(cache->inactiv);
free(cache);
}
EAPI RGBA_Image*
evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *key, RGBA_Image_Loadopts *lo, int *error)
{
const char* format;
char* hkey;
RGBA_Image* im;
Evas_Image_Load_Opts prevent;
int size;
struct stat st;
assert(cache != NULL);
if (!file && !key) return NULL;
if (!file) return NULL;
if ((!lo) ||
(lo &&
(lo->scale_down_by == 0) &&
(lo->dpi = 0.0) &&
((lo->w == 0) || (lo->h == 0))))
{
lo = &prevent;
if (key)
format = "%s//://%s";
else
format = "%s//://%p";
}
else
{
if (key)
format = "%s//://%s//@/%i/%1.5f/%ix%i";
else
format = "%s//://%p//@/%i/%1.5f/%ix%i";
}
size = strlen(file) + (key ? strlen(key) : 6) + 64;
hkey = alloca(sizeof (char) * size);
snprintf(hkey, size, format, file, key, lo->scale_down_by, lo->dpi, lo->w, lo->h);
if (stat(file, &st) < 0) return NULL;
/* FIXME: Handle timestamp correctly. */
im = evas_hash_find(cache->activ, hkey);
if (im)
goto on_ok;
im = evas_hash_find(cache->inactiv, hkey);
if (im)
{
cache->lru = evas_object_list_remove(cache->lru, im);
cache->inactiv = evas_hash_del(cache->inactiv, hkey, im);
cache->activ = evas_hash_add(cache->activ, hkey, im);
goto on_ok;
}
im = evas_common_image_new();
if (!im)
{
*error = -1;
return NULL;
}
im->timestamp = st.st_mtime;
im->laststat = time(NULL);
if (lo) im->load_opts = *lo;
im->info.file = (char *) evas_stringshare_add(file);
if (key) im->info.key = (char *) evas_stringshare_add(key);
*error = cache->func.constructor(im);
if (*error != 0)
{
evas_common_image_delete(im);
return NULL;
}
if (cache->func.debug)
cache->func.debug("request", im);
cache->activ = evas_hash_add(cache->activ, hkey, im);
im->references = 0;
im->cache_key = strdup(hkey);
im->cache = cache;
cache->usage += strlen(im->cache_key) + 1 + cache->func.mem_size_get(im);
on_ok:
*error = 0;
im->references++;
return im;
}
EAPI void
evas_cache_image_drop(RGBA_Image *im)
{
Evas_Cache_Image* cache;
char* hkey;
assert(im);
assert(im->cache);
im->references--;
cache = im->cache;
if ((im->flags & RGBA_IMAGE_IS_DIRTY) == RGBA_IMAGE_IS_DIRTY)
{
int size;
size = cache->func.mem_size_get(im);
cache->usage -= size;
cache->dirty = evas_object_list_remove(cache->dirty, im);
if (cache->func.debug)
cache->func.debug("drop", im);
cache->func.destructor(im);
evas_common_image_delete(im);
return ;
}
if (im->references == 0)
{
hkey = im->cache_key;
cache->activ = evas_hash_del(cache->activ, hkey, im);
cache->inactiv = evas_hash_add(cache->inactiv, hkey, im);
cache->lru = evas_object_list_prepend(cache->lru, im);
/* FIXME: Enforce cache limit. */
}
}
EAPI RGBA_Image*
evas_cache_image_dirty(RGBA_Image *im, int x, int y, int w, int h)
{
RGBA_Image* im_dirty = im;
Evas_Cache_Image* cache;
char* hkey;
assert(im);
assert(im->cache);
cache = im->cache;
if (!(im->flags & RGBA_IMAGE_IS_DIRTY))
{
if (im->references == 1)
{
hkey = im->cache_key;
cache->activ = evas_hash_del(cache->activ, hkey, im);
cache->usage -= strlen(hkey) + 1;
free(hkey);
im_dirty = im;
}
else
{
int error;
im_dirty = evas_common_image_new();
if (!im_dirty) goto on_error;
im_dirty->image = evas_common_image_surface_new(im);
if (!im_dirty->image) goto on_error;
im_dirty->image->w = w;
im_dirty->image->h = h;
if (cache->func.debug)
cache->func.debug("dirty-src", im);
error = cache->func.dirty(im_dirty, im);
if (cache->func.debug)
cache->func.debug("dirty-out", im_dirty);
if (error != 0) goto on_error;
im_dirty->cache = cache;
im_dirty->references = 1;
cache->usage += cache->func.mem_size_get(im_dirty);
evas_cache_image_drop(im);
}
im_dirty->cache_key = NULL;
im_dirty->flags |= RGBA_IMAGE_IS_DIRTY;
cache->dirty = evas_object_list_prepend(cache->dirty, im_dirty);
}
if (cache->func.debug)
cache->func.debug("dirty-region", im_dirty);
if (cache->func.dirty_region)
cache->func.dirty_region(im_dirty, x, y, w, h);
return im_dirty;
on_error:
if (im_dirty) evas_common_image_delete(im_dirty);
evas_cache_image_drop(im);
return NULL;
}
EAPI RGBA_Image*
evas_cache_image_alone(RGBA_Image *im)
{
RGBA_Image* im_dirty = im;
Evas_Cache_Image* cache;
char* hkey;
assert(im);
assert(im->cache);
cache = im->cache;
if (im->references == 1)
{
if (!(im->flags & RGBA_IMAGE_IS_DIRTY))
{
hkey = im->cache_key;
cache->activ = evas_hash_del(cache->activ, hkey, im);
cache->usage -= strlen(hkey) + 1;
free(hkey);
im_dirty->cache_key = NULL;
im_dirty->flags |= RGBA_IMAGE_IS_DIRTY;
cache->dirty = evas_object_list_prepend(cache->dirty, im_dirty);
}
}
else
{
int error;
im_dirty = evas_common_image_new();
if (!im_dirty) goto on_error;
im_dirty->image = evas_common_image_surface_new(im);
if (!im_dirty->image) goto on_error;
im_dirty->image->w = im->image->w;
im_dirty->image->h = im->image->h;
if (cache->func.debug)
cache->func.debug("dirty-src", im);
error = cache->func.dirty(im_dirty, im);
if (cache->func.debug)
cache->func.debug("dirty-out", im_dirty);
if (error != 0) goto on_error;
im_dirty->cache_key = NULL;
im_dirty->flags |= RGBA_IMAGE_IS_DIRTY;
im_dirty->references = 1;
cache->dirty = evas_object_list_prepend(cache->dirty, im_dirty);
evas_cache_image_drop(im);
}
return im_dirty;
on_error:
if (im_dirty) evas_common_image_delete(im_dirty);
evas_cache_image_drop(im);
return NULL;
}
static RGBA_Image*
_evas_cache_image_push_dirty(Evas_Cache_Image *cache, RGBA_Image* im)
{
cache->dirty = evas_object_list_prepend(cache->dirty, im);
im->flags |= RGBA_IMAGE_IS_DIRTY;
im->cache_key = NULL;
im->cache = cache;
return im;
}
EAPI RGBA_Image*
evas_cache_image_copied_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
RGBA_Image* im;
assert(cache);
if (cspace != EVAS_COLORSPACE_ARGB8888)
w &= ~0x1;
im = evas_common_image_create(w, h);
if (!im) return NULL;
if (cache->func.copied_data(im, w, h, image_data, alpha, cspace) != 0)
{
evas_common_image_delete(im);
return NULL;
}
return _evas_cache_image_push_dirty(cache, im);
}
EAPI RGBA_Image*
evas_cache_image_data(Evas_Cache_Image *cache, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
RGBA_Image* im;
assert(cache);
im = evas_common_image_new();
if (!im) return NULL;
im->image = evas_common_image_surface_new(im);
if (!im->image)
{
evas_common_image_delete(im);
return NULL;
}
if (cache->func.data(im, w, h, image_data, alpha, cspace) != 0)
{
evas_common_image_delete(im);
return NULL;
}
return _evas_cache_image_push_dirty(cache, im);
}
EAPI RGBA_Image*
evas_cache_image_size_set(RGBA_Image *im, int w, int h)
{
Evas_Cache_Image* cache;
RGBA_Image* new;
int error;
assert(im);
assert(im->image);
assert(im->cache);
assert(im->references > 0);
if (im->image->w == w
&& im->image->h == h)
return im;
cache = im->cache;
new = evas_common_image_new();
if (!new) goto on_error;
new->image = evas_common_image_surface_new(im);
if (!new->image) goto on_error;
new->image->w = w;
new->image->h = h;
if (cache->func.debug)
cache->func.debug("size_set-in", im);
error = cache->func.size_set(new, im, w, h);
if (cache->func.debug)
cache->func.debug("size_set-out", new);
if (error != 0) goto on_error;
new->cache = cache;
new->cache_key = NULL;
new->references = 1;
cache->usage += cache->func.mem_size_get(new);
if ((im->flags & RGBA_IMAGE_IS_DIRTY) == RGBA_IMAGE_IS_DIRTY
|| im->references > 1)
{
new->flags |= RGBA_IMAGE_IS_DIRTY;
cache->dirty = evas_object_list_prepend(cache->dirty, new);
}
else
{
char* cache_key = NULL;
cache_key = im->cache_key ? strdup(im->cache_key) : NULL;
new->cache_key = cache_key;
cache->activ = evas_hash_add(cache->activ, cache_key, new);
cache->usage += strlen(new->cache_key) + 1;
}
evas_cache_image_drop(im);
return new;
on_error:
if (new) evas_common_image_delete(new);
evas_cache_image_drop(im);
return NULL;
}
EAPI void
evas_cache_image_load_data(RGBA_Image *im)
{
Evas_Cache_Image* cache;
int size;
assert(im);
assert(im->image);
assert(im->cache);
if ((im->flags & RGBA_IMAGE_LOADED) == RGBA_IMAGE_LOADED) return ;
cache = im->cache;
if (cache->func.debug)
cache->func.debug("load", im);
size = cache->func.mem_size_get(im);
cache->func.load(im);
cache->usage += cache->func.mem_size_get(im) - size;
im->flags |= RGBA_IMAGE_LOADED;
assert(im->image->data);
}
EAPI int
evas_cache_image_flush(Evas_Cache_Image *cache)
{
assert(cache);
if (cache->limit == -1)
return -1;
while (cache->lru && cache->limit < cache->usage)
{
RGBA_Image* im;
im = (RGBA_Image*) cache->lru->last;
cache->lru = evas_object_list_remove(cache->lru, im);
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
cache->usage -= strlen(im->cache_key) + 1;
cache->usage -= cache->func.mem_size_get(im);
free(im->cache_key);
im->cache_key = NULL;
cache->func.destructor(im);
evas_common_image_delete(im);
}
return cache->usage;
}
EAPI RGBA_Image*
evas_cache_image_empty(Evas_Cache_Image* cache)
{
RGBA_Image* new;
new = evas_common_image_new();
if (!new) goto on_error;
new->image = evas_common_image_surface_new(new);
if (!new->image) goto on_error;
new->cache = cache;
new->references = 1;
new->cache_key = NULL;
new->flags |= RGBA_IMAGE_IS_DIRTY;
cache->dirty = evas_object_list_prepend(cache->dirty, new);
return new;
on_error:
if (new) evas_common_image_delete(new);
return NULL;
}
EAPI void
evas_cache_image_colorspace(RGBA_Image* im, int cspace)
{
if (!im) return ;
if (im->cs.space == cspace) return ;
evas_common_image_colorspace_set(im, cspace);
}

@ -742,6 +742,9 @@ evas_render_method_list(void)
#ifdef BUILD_ENGINE_SOFTWARE_QTOPIA
methods = evas_list_append(methods, strdup("software_qtopia"));
#endif
#ifdef BUILD_ENGINE_SDL
methods = evas_list_append(methods, strdup("software_sdl"));
#endif
return methods;
}

@ -1061,20 +1061,18 @@ evas_object_image_save(Evas_Object *obj, const char *file, const char *key, cons
else break;
}
}
im = evas_common_image_new();
im = evas_cache_image_empty(evas_common_image_cache_get());
if (im)
{
if (o->cur.has_alpha) im->flags |= RGBA_IMAGE_HAS_ALPHA;
im->image = evas_common_image_surface_new(im);
if (im->image)
{
im->image->data = data;
im->image->w = o->cur.image.w;
im->image->h = o->cur.image.h;
im->image->no_free = 1;
ok = evas_common_save_image_to_file(im, file, key, quality, compress);
}
evas_common_image_free(im);
im->image->data = data;
im->image->w = o->cur.image.w;
im->image->h = o->cur.image.h;
im->image->no_free = 1;
ok = evas_common_save_image_to_file(im, file, key, quality, compress);
evas_cache_image_drop(im);
}
return ok;
}

@ -45,6 +45,7 @@ evas_gradient_sinusoidal.c \
evas_image_load.c \
evas_image_save.c \
evas_image_main.c \
evas_image_data.c \
evas_line_main.c \
evas_polygon_main.c \
evas_rectangle_main.c \

@ -0,0 +1,123 @@
#include "evas_common.h"
#include "evas_private.h"
#include <assert.h>
EAPI int
evas_common_image_from_data(RGBA_Image* dst, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
switch (cspace)
{
case EVAS_COLORSPACE_ARGB8888:
dst->image->w = w;
dst->image->h = h;
dst->image->data = image_data;
dst->image->no_free = 1;
if (alpha)
dst->flags |= RGBA_IMAGE_HAS_ALPHA;
else
dst->flags &= ~RGBA_IMAGE_HAS_ALPHA;
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
w &= ~0x1;
dst->image->w = w;
dst->image->h = h;
evas_common_image_surface_alloc(dst->image);
dst->cs.data = image_data;
dst->cs.no_free = 1;
break;
default:
abort();
break;
}
dst->cs.space = cspace;
evas_common_image_colorspace_dirty(dst);
return 0;
}
EAPI int
evas_common_image_from_copied_data(RGBA_Image* dst, int w, int h, DATA32 *image_data, int alpha, int cspace)
{
switch (cspace)
{
case EVAS_COLORSPACE_ARGB8888:
if (alpha)
dst->flags |= RGBA_IMAGE_HAS_ALPHA;
else
dst->flags &= ~RGBA_IMAGE_HAS_ALPHA;
if (image_data)
memcpy(dst->image->data, image_data, w * h * sizeof(DATA32));
break;
case EVAS_COLORSPACE_YCBCR422P601_PL:
case EVAS_COLORSPACE_YCBCR422P709_PL:
dst->cs.data = calloc(1, dst->image->h * sizeof(unsigned char*) * 2);
if (image_data && (dst->cs.data))
memcpy(dst->cs.data, image_data, dst->image->h * sizeof(unsigned char*) * 2);
break;
default:
abort();
break;
}
dst->cs.space = cspace;
evas_common_image_colorspace_dirty(dst);
return 0;
}