Hi,
I started a SDL engine for evas and would like some feedback. First
it's
working and you will see something with evas_sdl_test. But I have already a
few questions.
I wanted to directly manipulate SDL_Surface inside RGBA_Image, but this
means
that for the destruction, I need to call SDL_FreeSurface or I didn't find a
way to do that using the evas_common API. To handle this case, I implemented
my own cache mechanism and copy/pasted all functions destroying some
RGBA_Image. Well that is working, but that's definitely not clean. So I
extract the cache mechanism and make it an evas API (separate patch in
evas-data-cache.diff). But this didn't change the problem with evas_common
function, like module loaders and others need to be copied. I really don't
know how to handle this case correctly. Perhaps adding some callbacks for
freeing and creating new image to evas_common_image_init() could be a
solution to this duplication of code. Did you prefer a separate cache API, or
should I put it back in the SDL engine ?
Right now SDL cache is only handling one RGBA_Image with the same
key/filename at a time. This means that if one RGBA_Image is dirty but still
referenced, the new one will not be able to evict it. I could fix this by
storing a list of RGBA_Image per key/filename, but right now the
evas_sdl_test seems to be correct. Did I need to take care of this kind of
issue or is it ok this way ?
In the same idea, what are the purpose of engine_image_border_set,
engine_image_border_get and engine_image_format_get ? They seem empty in all
engine I am looking in.
Now if you tried the test program and hide the SDL output, you will
notice
that the part that didn't change stays black. To solve this, I need to handle
SDL_ExposeEvent, but I don't really know where. As I understood most events
are handle in ecore. But X11 backend for example, seems to be aware of this
kind of issue. Did I need to check for SDL pending event every time
evas_engine_sdl_output_flush is running ? Or did it exist a better way to do
that ?
Cedric
diff -Nru -x CVS e17-main/libs/evas/src/lib/data/evas_cache.c e17-dev/libs/evas/src/lib/data/evas_cache.c
--- e17-main/libs/evas/src/lib/data/evas_cache.c 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/lib/data/evas_cache.c 2006-08-08 18:58:28.000000000 +0200
@@ -0,0 +1,482 @@
+#include <values.h>
+#include "evas_common.h"
+#include "evas_private.h"
+
+#define EVAS_CACHE_MAGIC 0xDEADBEEF
+
+static int _evas_cache_empty_necessity (Evas_Cache* cache, int object_size, int force);
+static void _evas_cache_remove_object (Evas_Cache* cache, int position);
+static Evas_Cache_Object* _evas_cache_lookup (Evas_Cache* cache, const char* key);
+static int _evas_cache_lookup_int (Evas_Cache* cache, const char* key);
+static Evas_Data_Error _evas_cache_match_size (Evas_Cache* cache, int adding_size);
+static Evas_Data_Error _evas_cache_match_count (Evas_Cache* cache);
+
+/**
+ * @defgroup Evas_Cache Memory pool manipulation functions for fixed size object
+ *
+ */
+
+/**
+ * Build a new Evas_Cache object
+ * @param evict Function called when an object must be removed from the cache.
+ * @param max_objects_count Limit the maximum number of objects in the cache (0 means no limit).
+ * @param max_size Limit the size of the stored object in the cache (0 means no limit).
+ * @return A pointer to the new allocated cache object
+ * @ingroup Evas_Cache
+ */
+EAPI Evas_Cache*
+evas_cache_init (void (*evict)(Evas_Cache* cache, const char* key, void* object, int reference), int max_objects_count, int max_size)
+{
+ Evas_Cache* new_cache = malloc (sizeof (struct _Evas_Cache));
+
+ if (new_cache)
+ {
+ new_cache->magic = EVAS_CACHE_MAGIC;
+
+ new_cache->cache_content = NULL;
+ new_cache->objects = NULL;
+ new_cache->current_objects_limit = 0;
+
+ new_cache->max_size = max_size;
+ new_cache->max_objects_count = max_objects_count;
+
+ new_cache->current_size = 0;
+ new_cache->current_objects_count = 0;
+
+ new_cache->evict = evict;
+ }
+ return new_cache;
+}
+
+/**
+ * Destroy the cache and evict all the object stored in it
+ * @param cache The cache object to be destroyed
+ * @return EVAS_DATA_NONE if no error happen during the destruction or the error code corresponding to the encoutered error.
+ * @ingroup Evas_Cache
+ */
+EAPI Evas_Data_Error
+evas_cache_shutdown (Evas_Cache* cache)
+{
+ Evas_Data_Error error = EVAS_DATA_NONE;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return EVAS_DATA_NULL;
+
+ error = evas_cache_force_flush (cache);
+ if (error != EVAS_DATA_NONE)
+ return error;
+
+ free (cache);
+ return EVAS_DATA_NONE;
+}
+
+/**
+ * This function search inside the cache an object matching the key and increase the reference to it.
+ * @param cache The cache we refer to
+ * @param key The key pointing to the object we whant to get a reference to.
+ * @return A pointer to the increased reference object or NULL if the object was not found.
+ * @ingroup Evas_Cache
+ */
+EAPI void*
+evas_cache_reference (Evas_Cache* cache, const char* key)
+{
+ int i = 0;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return NULL;
+
+ cache->error = EVAS_DATA_NONE;
+
+ i = _evas_cache_lookup_int (cache, key);
+ if (i != -1)
+ {
+ cache->objects[i].requested_time++;
+ cache->objects[i].reference++;
+
+ return cache->objects[i].object;
+ }
+
+ return NULL;
+}
+
+/**
+ * This function push inside the cache a new version of the requested object. If
+ * an object with the same key and still referenced is detected, the insertion
+ * will be aborded.
+ *
+ * The insertion of a new object will result in the call of evict on other
+ * objects (to match constraint on the cache, or because an object with the same
+ * key already exist).
+ *
+ * @param cache The cache in which we want to insert/update the object.
+ * @param key The key describing the object.
+ * @param object The object to be inserted inside the cache.
+ * @param force Enforce or not the limit set to this cache (maximum number of objects or maximum size).
+ * @return A pointer to the inserted object.
+ * @ingroup Evas_Cache
+ */
+EAPI void*
+evas_cache_update (Evas_Cache* cache, const char* key, void* object, int object_size, int force)
+{
+ int i = 0;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return NULL;
+
+ cache->error = EVAS_DATA_NONE;
+
+ i = _evas_cache_lookup_int (cache, key);
+ if (i != -1)
+ {
+ /* Security: If the object is still referenced somewhere we will refuse to destroy it */
+ if (cache->objects[i].reference > 0)
+ {
+ cache->error = EVAS_DATA_CONFLICT;
+ return NULL;
+ }
+ _evas_cache_remove_object (cache, i);
+ }
+
+ i = _evas_cache_empty_necessity (cache, object_size, force);
+ if (i == -1)
+ {
+ cache->error = EVAS_DATA_FULL;
+ return NULL;
+ }
+
+ cache->objects[i].object = object;
+ cache->objects[i].object_size = object_size;
+ cache->objects[i].requested_time = 0;
+ cache->objects[i].key = evas_stringshare_add (key);
+ cache->objects[i].reference = 0;
+
+ cache->cache_content = evas_hash_direct_add (cache->cache_content, cache->objects[i].key, i + 1);
+
+ (cache->current_objects_count)++;
+ cache->current_size += object_size;
+
+ return object;
+}
+
+/**
+ * This decrease by one the number of instance of the object pointed by the key. The object will not be removed at this
+ * point, but it could if requested.
+ *
+ * @param cache The current cache in which we want to dereference the object.
+ * @param key The key describing the object to dereference.
+ * @return EVAS_DATA_NONE if no error happen during the destruction or the error code corresponding to the encoutered error.
+ * @ingroup Evas_Cache
+ */
+EAPI Evas_Data_Error
+evas_cache_unreference (Evas_Cache* cache, const char* key)
+{
+ Evas_Cache_Object* obj = NULL;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return EVAS_DATA_NULL;
+
+ obj = _evas_cache_lookup (cache, key);
+ if (!obj)
+ {
+ cache->error = EVAS_DATA_NOT_FOUND;
+ return EVAS_DATA_NOT_FOUND;
+ }
+
+ obj->reference--;
+
+ return EVAS_DATA_NONE;
+}
+
+/**
+ * This function lookup in the cache if an object with the matching key exist. If found it will return a pointer to this object.
+ *
+ * @param cache The cache in which we do our lookup.
+ * @param key The key that could match an object.
+ * @return A pointer to the object we found, or NULL if none match.
+ * @ingroup Evas_Cache
+ */
+EAPI void*
+evas_cache_find (Evas_Cache* cache, const char* key)
+{
+ Evas_Cache_Object* obj = NULL;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return NULL;
+
+ obj = _evas_cache_lookup (cache, key);
+ if (!obj)
+ {
+ cache->error = EVAS_DATA_NOT_FOUND;
+ return NULL;
+ }
+
+ return obj->object;
+}
+
+/**
+ * This function lookup in the cache if an object with the matching key exist. If found it will return the known size of the object.
+ *
+ * @param cache The cache in which we do our lookup.
+ * @param key The key that could match an object.
+ * @return A pointer to the object we found, or NULL if none match.
+ * @ingroup Evas_Cache
+ */
+EAPI int
+evas_cache_find_size (Evas_Cache* cache, const char* key)
+{
+ Evas_Cache_Object* obj = NULL;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+
+ obj = _evas_cache_lookup (cache, key);
+ if (!obj)
+ {
+ cache->error = EVAS_DATA_NOT_FOUND;
+ return 0;
+ }
+
+ return obj->object_size;
+}
+
+/**
+ * This function return the global size of the cache.
+ *
+ * @param cache The cache we want to learn the size of.
+ * @return The size of the cache.
+ * @ingroup Evas_Cache
+ */
+EAPI int
+evas_cache_memsize (Evas_Cache* cache)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+ return cache->current_size;
+}
+
+/**
+ * This function return the number of objects stored in the cache.
+ *
+ * @param cache The cache we want to learn the number of objects from.
+ * @return The number of object in this cache.
+ * @ingroup Evas_Cache
+ */
+EAPI int
+evas_cache_objects_count(Evas_Cache* cache)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+ return cache->current_objects_count;
+}
+
+/**
+ * This function force the flush of all object that have no external reference.
+ *
+ * @param cache The cache we want to flush.
+ * @return The number of object removed from the cache.
+ */
+EAPI int
+evas_cache_force_flush (Evas_Cache* cache)
+{
+ int before = 0;
+ int i = 0;
+
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+
+ before = cache->current_objects_count;
+
+ while (i < cache->current_objects_count)
+ {
+ if (cache->objects[i].reference > 0)
+ ++i;
+ else
+ _evas_cache_remove_object (cache, i);
+ }
+
+ return before - cache->current_objects_count;
+}
+
+
+EAPI Evas_Data_Error
+evas_cache_set_maximum_size(Evas_Cache* cache, int max_size)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return EVAS_DATA_NULL;
+
+ cache->max_size = max_size;
+ return _evas_cache_match_size (cache, 0);
+}
+
+EAPI int
+evas_cache_get_maximum_size(Evas_Cache* cache)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+
+ return cache->max_size;
+}
+
+EAPI Evas_Data_Error
+evas_cache_set_maximum_objects (Evas_Cache* cache, int max_objects_count)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return EVAS_DATA_NULL;
+
+ cache->max_objects_count = max_objects_count;
+ return _evas_cache_match_count (cache);
+}
+
+EAPI int
+evas_cache_get_maximum_objects (Evas_Cache* cache)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return 0;
+
+ return cache->max_objects_count;
+}
+
+EAPI Evas_Data_Error
+evas_cache_get_last_error (Evas_Cache* cache)
+{
+ if (!cache || cache->magic != EVAS_CACHE_MAGIC)
+ return EVAS_DATA_NULL;
+
+ return cache->error;
+}
+
+/** Private function */
+
+static int
+_evas_cache_lookup_int (Evas_Cache* cache, const char* key)
+{
+ int i = evas_hash_find (cache->cache_content, key) - 1;
+
+ if (i < 0)
+ return -1;
+
+ return i;
+}
+
+static Evas_Cache_Object*
+_evas_cache_lookup (Evas_Cache* cache, const char* key)
+{
+ Evas_Cache_Object* obj = NULL;
+ int i = _evas_cache_lookup_int (cache, key);
+
+ if (i == - 1)
+ return NULL;
+
+ obj = cache->objects + i;
+ return obj;
+}
+
+static void
+_evas_cache_remove_object (Evas_Cache* cache, int position)
+{
+ Evas_Cache_Object* objects = cache->objects;
+ const char* key = objects[position].key;
+ int current_objects_count = 0;
+
+ if (cache->evict)
+ cache->evict (cache, key, objects[position].object, objects[position].reference);
+
+ current_objects_count = --(cache->current_objects_count);
+
+ cache->current_size -= objects[position].object_size;
+ cache->cache_content = evas_hash_del (cache->cache_content, key, NULL);
+
+ evas_stringshare_del (key);
+
+ memmove (objects + position, objects + position + 1, sizeof (struct _Evas_Cache_Object) * (current_objects_count - position));
+ memset (objects + current_objects_count, 0, sizeof (struct _Evas_Cache_Object));
+
+ if (cache->current_objects_limit - 8 > current_objects_count)
+ {
+ cache->current_objects_limit -= 8;
+ cache->objects = realloc (cache->objects, sizeof (struct _Evas_Cache_Object) * cache->current_objects_limit);
+ }
+}
+
+static int
+_evas_cache_less_used (Evas_Cache* cache)
+{
+ Evas_Cache_Object* objects = cache->objects;
+ int count = cache->current_objects_count;
+ int requested_time = MAXINT;
+ int i = 0;
+ int to_be_killed = -1;
+
+ for (i = 0; i < count; ++objects, ++i)
+ if (objects->reference == 0 && requested_time > objects->requested_time)
+ {
+ to_be_killed = i;
+ requested_time = objects->requested_time;
+ }
+
+ return to_be_killed;
+}
+
+static Evas_Data_Error
+_evas_cache_match_size (Evas_Cache* cache, int adding_size)
+{
+ if (cache->max_size != 0 && cache->max_size < cache->current_size + adding_size)
+ {
+ /* This cache care a little about memory consuption, so comply with it */
+ while (cache->current_size + adding_size > cache->max_size)
+ {
+ int i = _evas_cache_less_used (cache);
+
+ if (i == -1)
+ {
+ cache->error = EVAS_DATA_FULL;
+ return EVAS_DATA_FULL;
+ }
+
+ _evas_cache_remove_object (cache, i);
+ }
+ }
+
+ return EVAS_DATA_NONE;
+}
+
+static Evas_Data_Error
+_evas_cache_match_count (Evas_Cache* cache)
+{
+ if (cache->max_objects_count != 0 && cache->max_objects_count < cache->current_objects_count + 1)
+ /* We reach the maximum number of stored object limit */
+ {
+ int i = _evas_cache_less_used (cache);
+
+ if (i == -1)
+ {
+ cache->error = EVAS_DATA_FULL;
+ return EVAS_DATA_FULL;
+ }
+ _evas_cache_remove_object (cache, i);
+ }
+
+ return EVAS_DATA_NONE;
+}
+
+static int
+_evas_cache_empty_necessity (Evas_Cache* cache, int object_size, int force)
+{
+ if (!force && object_size > cache->max_size)
+ return -1;
+
+ if (!force && _evas_cache_match_size (cache, object_size) != EVAS_DATA_NONE)
+ return -1;
+
+ if (!force && _evas_cache_match_count (cache) != EVAS_DATA_NONE)
+ return -1;
+
+ if (cache->current_objects_limit < cache->current_objects_count + 1)
+ {
+ /* We need to expand the cache, step by step */
+ cache->current_objects_limit += 8;
+ cache->objects = realloc (cache->objects, sizeof (struct _Evas_Cache_Object) * cache->current_objects_limit);
+ }
+
+ return cache->current_objects_count;
+}
diff -Nru -x CVS e17-main/libs/evas/src/lib/data/Makefile.am e17-dev/libs/evas/src/lib/data/Makefile.am
--- e17-main/libs/evas/src/lib/data/Makefile.am 2005-11-28 16:18:00.000000000 +0100
+++ e17-dev/libs/evas/src/lib/data/Makefile.am 2006-07-27 10:47:46.000000000 +0200
@@ -15,6 +15,7 @@
evas_hash.c \
evas_list.c \
evas_object_list.c \
-evas_stringshare.c
+evas_stringshare.c \
+evas_cache.c
libevas_data_la_DEPENDENCIES = $(top_builddir)/config.h
diff -Nru -x CVS e17-main/libs/evas/config.h.in e17-dev/libs/evas/config.h.in
--- e17-main/libs/evas/config.h.in 2006-08-10 15:05:03.000000000 +0200
+++ e17-dev/libs/evas/config.h.in 2006-08-10 11:58:02.000000000 +0200
@@ -99,6 +99,9 @@
/* OpenGL X11 Rendering Backend */
#undef BUILD_ENGINE_GL_X11
+/* SDL Rendering Backend */
+#undef BUILD_ENGINE_SDL
+
/* Qtopia Rendering Backend */
#undef BUILD_ENGINE_SOFTWARE_QTOPIA
diff -Nru -x CVS e17-main/libs/evas/configure.in e17-dev/libs/evas/configure.in
--- e17-main/libs/evas/configure.in 2006-08-04 23:52:45.000000000 +0200
+++ e17-dev/libs/evas/configure.in 2006-08-09 20:54:07.000000000 +0200
@@ -63,6 +63,8 @@
qt_cflags=""
qt_libs=""
qt_moc="moc"
+sdl_cflags=""
+sdl_libs=""
#####################################################################
@@ -258,6 +260,58 @@
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";
ENGINE_FB_PRG="";
@@ -1690,6 +1744,9 @@
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)
@@ -1731,6 +1788,7 @@
AC_SUBST(ENGINE_SOFTWARE_X11_PRG)
AC_SUBST(ENGINE_SOFTWARE_XCB_PRG)
AC_SUBST(ENGINE_DIRECTFB_PRG)
+AC_SUBST(ENGINE_SDL_PRG)
AC_SUBST(ENGINE_FB_PRG)
AC_SUBST(ENGINE_BUFFER_PRG)
AC_SUBST(ENGINE_SOFTWARE_QTOPIA_PRG)
@@ -1780,6 +1838,7 @@
src/modules/engines/cairo_x11/Makefile
src/modules/engines/xrender_x11/Makefile
src/modules/engines/xrender_xcb/Makefile
+src/modules/engines/sdl/Makefile
src/modules/loaders/Makefile
src/modules/loaders/edb/Makefile
src/modules/loaders/eet/Makefile
@@ -1823,6 +1882,7 @@
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"
diff -Nru -x CVS e17-main/libs/evas/README.in e17-dev/libs/evas/README.in
--- e17-main/libs/evas/README.in 2005-08-25 06:37:24.000000000 +0200
+++ e17-dev/libs/evas/README.in 2006-07-27 09:58:55.000000000 +0200
@@ -14,6 +14,7 @@
X11R6
XCB
DirectFB
+ SDL
OpenGL (underway at the moment)
Linux
Qtopia
@@ -127,6 +128,12 @@
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
diff -Nru -x CVS e17-main/libs/evas/src/bin/evas_sdl_main.c e17-dev/libs/evas/src/bin/evas_sdl_main.c
--- e17-main/libs/evas/src/bin/evas_sdl_main.c 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/bin/evas_sdl_main.c 2006-08-01 16:34:31.000000000 +0200
@@ -0,0 +1,39 @@
+#include "evas_test_main.h"
+
+#include "Evas.h"
+#include "Evas_Engine_SDL.h"
+
+#include <stdio.h>
+#include <string.h>
+
+int
+main(int argc, char **argv)
+{
+ int rot = 0;
+
+ evas_init();
+ evas = evas_new();
+ evas_output_method_set(evas, evas_render_method_lookup("sdl"));
+ evas_output_size_set(evas, win_w, win_h);
+ evas_output_viewport_set(evas, 0, 0, win_w, win_h);
+ {
+ Evas_Engine_Info_SDL *einfo;
+
+ einfo = (Evas_Engine_Info_SDL *) evas_engine_info_get(evas);
+
+ /* the following is specific to the engine */
+ einfo->info.fullscreen = 0;
+ einfo->info.noframe = 0;
+
+ evas_engine_info_set(evas, (Evas_Engine_Info *) einfo);
+ }
+ setup();
+ orig_start_time = start_time = get_time();
+ for (;;)
+ {
+ loop();
+ evas_render(evas);
+ }
+ evas_shutdown();
+ return 0;
+}
diff -Nru -x CVS e17-main/libs/evas/src/bin/Makefile.am e17-dev/libs/evas/src/bin/Makefile.am
--- e17-main/libs/evas/src/bin/Makefile.am 2006-07-13 21:48:09.000000000 +0200
+++ e17-dev/libs/evas/src/bin/Makefile.am 2006-08-07 18:53:00.000000000 +0200
@@ -3,6 +3,7 @@
INCLUDES = \
-I. -I$(top_srcdir)/src/modules/engines -I$(top_srcdir)/src/lib -I$(top_srcdir) \
@DIRECTFB_CFLAGS@ @qt_cflags@ @gl_cflags@ \
+-I$(top_srcdir)/src/modules/engines/sdl \
-I$(top_srcdir)/src/modules/engines/buffer \
-I$(top_srcdir)/src/modules/engines/cairo_x11 \
-I$(top_srcdir)/src/modules/engines/directfb \
@@ -28,7 +29,8 @@
@ENGINE_GL_X11_PRG@ \
@ENGINE_CAIRO_X11_PRG@ \
@ENGINE_XRENDER_X11_PRG@ \
[EMAIL PROTECTED]@
[EMAIL PROTECTED]@ \
[EMAIL PROTECTED]@
EXTRA_PROGRAMS = \
evas_software_x11_test \
@@ -40,6 +42,7 @@
evas_directfb_test \
evas_directfb_window \
evas_fb_test \
+evas_sdl_test \
evas_buffer_test \
evas_software_qtopia_test \
evas_gl_x11_test \
@@ -94,4 +97,9 @@
evas_fb_test_CFLAGS = $(CFLAGS)
evas_fb_test_DEPENDENCIES = $(top_builddir)/src/lib/libevas.la
+evas_sdl_test_SOURCES = evas_test_main.h evas_test_main.c evas_sdl_main.c
+evas_sdl_test_LDADD = $(top_builddir)/src/lib/libevas.la -lm @sdl_libs@ @FREETYPE_LIBS@
+evas_sdl_test_CFLAGS = $(CFLAGS) @sdl_cflags@ @FREETYPE_CFLAGS@
+evas_sdl_test_DEPENDENCIES = $(top_builddir)/src/lib/libevas.la
+
evas_buffer_test_SOURCES = evas_test_main.h evas_test_main.c evas_buffer_main.c
diff -Nru -x CVS e17-main/libs/evas/src/lib/Evas.h e17-dev/libs/evas/src/lib/Evas.h
--- e17-main/libs/evas/src/lib/Evas.h 2006-08-10 14:57:42.000000000 +0200
+++ e17-dev/libs/evas/src/lib/Evas.h 2006-08-10 11:40:24.000000000 +0200
@@ -307,6 +307,46 @@
unsigned int timestamp;
};
+typedef struct _Evas_Cache Evas_Cache;
+typedef struct _Evas_Cache_Object Evas_Cache_Object;
+
+typedef enum _Evas_Data_Error
+{
+ EVAS_DATA_NONE = 0,
+ EVAS_DATA_NOT_FOUND,
+ EVAS_DATA_FULL,
+ EVAS_DATA_NULL,
+ EVAS_DATA_CONFLICT
+} Evas_Data_Error;
+
+struct _Evas_Cache_Object /** A cache object entry */
+{
+ const char* key; /**< The key referencing this object */
+ void* object;
+ int object_size;
+ int requested_time;
+ int reference;
+};
+
+struct _Evas_Cache /** A cache */
+{
+ int magic;
+
+ Evas_Hash* cache_content; /**< The hash table for quick search */
+ Evas_Cache_Object* objects; /**< Preallocated cache objects */
+ int current_objects_limit;
+
+ int max_objects_count;
+ int max_size;
+
+ int current_size;
+ int current_objects_count;
+
+ Evas_Data_Error error;
+
+ void (*evict)(Evas_Cache* cache, const char* key, void* object, int reference);
+};
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -340,19 +380,34 @@
*
* do we really need this? hmmm - let me think... there may be a better way
*/
- EAPI Evas_Hash *evas_hash_add (Evas_Hash *hash, const char *key, const void *data);
- EAPI Evas_Hash *evas_hash_direct_add (Evas_Hash *hash, const char *key, const void *data);
- EAPI Evas_Hash *evas_hash_del (Evas_Hash *hash, const char *key, const void *data);
+ EAPI Evas_Hash *evas_hash_add (Evas_Hash *hash, const char *key, const void*data);
+ EAPI Evas_Hash *evas_hash_direct_add (Evas_Hash *hash, const char *key, const void*data);
+ EAPI Evas_Hash *evas_hash_del (Evas_Hash *hash, const char *key, const void*data);
EAPI void *evas_hash_find (Evas_Hash *hash, const char *key);
- EAPI void *evas_hash_modify (Evas_Hash *hash, const char *key, const void *data);
+ EAPI void *evas_hash_modify (Evas_Hash *hash, const char *key, const void*data);
EAPI int evas_hash_size (Evas_Hash *hash);
EAPI void evas_hash_free (Evas_Hash *hash);
EAPI void evas_hash_foreach (Evas_Hash *hash, Evas_Bool (*func) (Evas_Hash *hash, const char *key, void *data, void *fdata), const void *fdata);
EAPI int evas_hash_alloc_error (void);
-
+
EAPI const char *evas_stringshare_add (const char *str);
EAPI void evas_stringshare_del (const char *str);
-
+
+ EAPI Evas_Cache *evas_cache_init (void (*evict)(Evas_Cache* cache, const char* key, void* object, int reference), int max_objects_count, int max_size);
+ EAPI Evas_Data_Error evas_cache_shutdown (Evas_Cache* cache);
+ EAPI void* evas_cache_reference (Evas_Cache* cache, const char* key);
+ EAPI void* evas_cache_update (Evas_Cache* cache, const char* key, void* object, int object_size, int force);
+ EAPI Evas_Data_Error evas_cache_unreference (Evas_Cache* cache, const char* key);
+ EAPI void* evas_cache_find (Evas_Cache* cache, const char* key);
+ EAPI int evas_cache_find_size (Evas_Cache* cache, const char* key);
+ EAPI int evas_cache_memsize (Evas_Cache* cache);
+ EAPI int evas_cache_objects_count (Evas_Cache* cache);
+ EAPI int evas_cache_force_flush (Evas_Cache* cache);
+ EAPI Evas_Data_Error evas_cache_set_maximum_size (Evas_Cache* cache, int max_size);
+ EAPI int evas_cache_get_maximum_size (Evas_Cache* cache);
+ EAPI Evas_Data_Error evas_cache_set_maximum_objects (Evas_Cache* cache, int max_objects_count);
+ EAPI int evas_cache_get_maximum_objects (Evas_Cache* cache);
+ EAPI Evas_Data_Error evas_cache_get_last_error (Evas_Cache* cache);
EAPI int evas_alloc_error (void);
diff -Nru -x CVS e17-main/libs/evas/src/modules/engines/Makefile.am e17-dev/libs/evas/src/modules/engines/Makefile.am
--- e17-main/libs/evas/src/modules/engines/Makefile.am 2006-04-25 06:00:20.000000000 +0200
+++ e17-dev/libs/evas/src/modules/engines/Makefile.am 2006-07-26 23:41:52.000000000 +0200
@@ -14,4 +14,5 @@
software_x11 \
software_xcb \
xrender_x11 \
-xrender_xcb
+xrender_xcb \
+sdl
diff -Nru -x CVS e17-main/libs/evas/src/modules/engines/sdl/evas_engine_sdl.c e17-dev/libs/evas/src/modules/engines/sdl/evas_engine_sdl.c
--- e17-main/libs/evas/src/modules/engines/sdl/evas_engine_sdl.c 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/modules/engines/sdl/evas_engine_sdl.c 2006-08-10 15:09:51.000000000 +0200
@@ -0,0 +1,975 @@
+#include "SDL/SDL.h"
+#include "evas_engine_sdl.h"
+#include "evas_common.h"
+#include "evas_private.h"
+#include <math.h>
+#include <string.h>
+#include <sys/time.h>
+#include <time.h>
+
+extern Evas_List* evas_modules;
+
+static Evas_Func func = {};
+static Evas_Func pfunc = {};
+static Evas_Cache* cache = NULL;
+
+static void _sdl_evicted_image (Evas_Cache* cache, const char* key, void* object, int reference);
+static void* _sdl_output_setup (int w, int h, int fullscreen, int noframe);
+static RGBA_Image* _sdl_image_new_from_sdl (SDL_Surface* sdl, const char* filename, const char* key);
+static RGBA_Image* _sdl_image_new_from_file(const char* filename, const char* key);
+static void _sdl_image_free (RGBA_Image* im);
+static void _sdl_debug_rgba_image (RGBA_Image* im);
+static void _sdl_stretch_blit (RGBA_Image* from, RGBA_Image* to, int w, int h);
+
+/* Stupid macro often used */
+#define CHECK_CACHE(COUNT, SIZE) \
+ if (!cache) cache = evas_cache_init (&_sdl_evicted_image, COUNT, SIZE);
+#define _SDL_BUILD_HASH_KEY(COMPUTE, FILENAME, KEY, RET) \
+ { \
+ int lfilename = (FILENAME) ? strlen (FILENAME) : 0; \
+ int lkey = (KEY) ? strlen (KEY) : 4; \
+ int lsum = lfilename + 3 + lkey + 4; \
+\
+ COMPUTE = alloca (lsum); \
+ if (!COMPUTE) \
+ return RET; \
+\
+ snprintf (COMPUTE, lsum, "%s/:/%s/:/", FILENAME, KEY ? KEY : "null"); \
+ }
+#define _SDL_UPDATE_PIXELS(IM) \
+ IM->image->data = ((SDL_Surface*) IM->extended_info)->pixels;
+#define _SDL_CACHE_UPDATE(REAL_KEY, IM) \
+ { \
+ RGBA_Image* rim = NULL; \
+ rim = evas_cache_update(cache, \
+ REAL_KEY, \
+ IM, evas_common_image_ram_usage (im), \
+ 1); \
+ if (!rim) \
+ _sdl_image_free(IM); \
+ *error = evas_cache_get_last_error(cache); \
+ }
+
+/* SDL engine info function */
+static void*
+evas_engine_sdl_info (Evas* e)
+{
+ Evas_Engine_Info_SDL* info = calloc(1, sizeof (Evas_Engine_Info_SDL));
+
+ if (!info)
+ return NULL;
+
+ info->magic.magic = rand();
+
+ return info;
+}
+
+static void
+evas_engine_sdl_info_free (Evas* e, void* info)
+{
+ Evas_Engine_Info_SDL* in = (Evas_Engine_Info_SDL*) info;
+
+ free(in);
+ in = NULL;
+}
+
+/* SDL engine output manipulation function */
+static void
+evas_engine_sdl_setup (Evas* e, void* in)
+{
+ Evas_Engine_Info_SDL* info = (Evas_Engine_Info_SDL*) in;
+
+ /* if we arent set to sdl, why the hell do we get called?! */
+ if (evas_output_method_get(e) != evas_render_method_lookup("sdl"))
+ return ;
+
+ if (SDL_Init(SDL_INIT_VIDEO) < 0)
+ {
+ fprintf(stderr, "SDL_Init failed with %s\n", SDL_GetError());
+ exit(-1);
+ }
+ atexit(SDL_Quit);
+
+ /* lets just set up */
+ e->engine.data.output = _sdl_output_setup(e->output.w, e->output.h,
+ info->info.fullscreen,
+ info->info.noframe);
+
+ if (!e->engine.data.output)
+ return;
+
+ e->engine.func = &func;
+ e->engine.data.context = e->engine.func->context_new(e->engine.data.output);
+ info->info.surface = ((Render_Engine*) e->engine.data.output)->surface;
+}
+
+static void
+evas_engine_sdl_output_free (void *data)
+{
+ Render_Engine* re = (Render_Engine*) data;
+
+ evas_common_tilebuf_free(re->tb);
+ if (re->rects)
+ evas_common_tilebuf_free_render_rects(re->rects);
+ _sdl_image_free(re->rgba_image);
+
+ if (re->update_rects)
+ free(re->update_rects);
+ memset(re, sizeof (Render_Engine), 0);
+ free(re);
+
+ evas_common_font_shutdown();
+ evas_common_image_shutdown();
+}
+
+static void
+evas_engine_sdl_output_resize (void *data, int w, int h)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = NULL;
+ SDL_Surface* tmp = NULL;
+
+ if (w == re->tb->outbuf_w && h == re->tb->outbuf_h)
+ return;
+
+ /* Make a copy of the scren */
+ tmp = SDL_DisplayFormatAlpha(re->surface);
+ if (!tmp)
+ return ;
+ im = _sdl_image_new_from_sdl(tmp, NULL, "SCREEN-OLD");
+
+ /* Destroy the screen */
+ _sdl_image_free (re->rgba_image);
+
+ /* Rebuil tilebuf */
+ evas_common_tilebuf_free(re->tb);
+ re->tb = evas_common_tilebuf_new(w, h);
+ if (re->tb)
+ evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+
+ /* Build the new screen */
+ re->surface = SDL_SetVideoMode(w, h, 32,
+ SDL_SWSURFACE
+ | (re->fullscreen ? SDL_FULLSCREEN : 0)
+ | (re->noframe ? SDL_NOFRAME : 0));
+
+ if (!re->surface)
+ {
+ fprintf(stderr, "Unable to change the resolution to : %ix%i\n", w, h);
+ exit(-1);
+ }
+ re->rgba_image = _sdl_image_new_from_sdl(re->surface, NULL, "SCREEN");
+ if (!re->rgba_image)
+ {
+ fprintf(stderr, "RGBA_Image allocation from SDL failed\n");
+ exit(-1);
+ }
+
+ /* Blit the old content to the new screen */
+ _sdl_stretch_blit(im, re->rgba_image, w, h);
+
+ /* Destroy the copy */
+ _sdl_image_free(im);
+}
+
+static void
+evas_engine_sdl_output_tile_size_set (void *data, int w, int h)
+{
+ Render_Engine* re = (Render_Engine*) data;
+
+ evas_common_tilebuf_set_tile_size(re->tb, w, h);
+}
+
+static void
+evas_engine_sdl_output_redraws_rect_add (void *data, int x, int y, int w, int h)
+{
+ Render_Engine* re = (Render_Engine*) data;
+
+ evas_common_tilebuf_add_redraw(re->tb, x, y, w, h);
+}
+
+static void
+evas_engine_sdl_output_redraws_rect_del (void *data, int x, int y, int w, int h)
+{
+ Render_Engine* re = (Render_Engine*) data;
+
+ evas_common_tilebuf_del_redraw(re->tb, x, y, w, h);
+}
+
+static void
+evas_engine_sdl_output_redraws_clear (void *data)
+{
+ Render_Engine* re = (Render_Engine*) data;
+
+ evas_common_tilebuf_clear(re->tb);
+}
+
+static void*
+evas_engine_sdl_output_redraws_next_update_get (void *data,
+ int *x, int *y, int *w, int *h,
+ int *cx, int *cy, int *cw, int *ch)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ Tilebuf_Rect* tb_rect = NULL;
+
+ if (re->end)
+ {
+ re->end = 0;
+ return NULL;
+ }
+ if (!re->rects)
+ {
+ re->rects = evas_common_tilebuf_get_render_rects(re->tb);
+ re->cur_rect = (Evas_Object_List *) re->rects;
+ }
+ if (!re->cur_rect)
+ return NULL;
+
+ tb_rect = (Tilebuf_Rect*) re->cur_rect;
+ *cx = *x = tb_rect->x;
+ *cy = *y = tb_rect->y;
+ *cw = *w = tb_rect->w;
+ *ch = *h = tb_rect->h;
+ re->cur_rect = re->cur_rect->next;
+ if (!re->cur_rect)
+ {
+ evas_common_tilebuf_free_render_rects(re->rects);
+ re->rects = NULL;
+ re->end = 1;
+ }
+
+ /* Return the "fake" surface so it is passed to the drawing routines. */
+ return re->rgba_image;
+}
+
+static void
+evas_engine_sdl_output_redraws_next_update_push (void *data, void *surface,
+ int x, int y, int w, int h)
+{
+ Render_Engine *re = (Render_Engine *) data;
+
+ if (re->update_rects_count + 1 > re->update_rects_limit)
+ {
+ re->update_rects_limit += 8;
+ re->update_rects = realloc(re->update_rects, sizeof (SDL_Rect) * re->update_rects_limit);
+ }
+
+ re->update_rects[re->update_rects_count].x = x;
+ re->update_rects[re->update_rects_count].y = y;
+ re->update_rects[re->update_rects_count].w = w;
+ re->update_rects[re->update_rects_count].h = h;
+
+ ++re->update_rects_count;
+
+ evas_common_cpu_end_opt();
+}
+
+static void
+evas_engine_sdl_output_flush (void *data)
+{
+ Render_Engine *re = (Render_Engine *) data;
+
+ SDL_UpdateRects(re->surface, re->update_rects_count, re->update_rects);
+
+ re->update_rects_count = 0;
+}
+
+/*
+ * Image objects
+ */
+
+static void*
+evas_engine_sdl_image_load(void *data, const char *file, const char *key, int *error)
+{
+ char* real_key = NULL;
+ Render_Engine* re = (Render_Engine*) data;;
+ RGBA_Image* im = NULL;
+ SDL_Surface* sdl = NULL;
+ SDL_Surface* tmp = NULL;
+
+ *error = 0;
+
+ if (!file)
+ return NULL;
+
+ CHECK_CACHE(0, 0);
+
+ _SDL_BUILD_HASH_KEY(real_key, file, key, NULL);
+ im = evas_cache_reference(cache, real_key);
+ if (im)
+ {
+ if (!(im->flags & RGBA_IMAGE_IS_DIRTY))
+ return im;
+ else
+ evas_cache_unreference(cache, real_key);
+ }
+
+ /* Image is not in cache -> create it */
+
+ /* First try to load the image directly with SDL */
+ tmp = SDL_LoadBMP(file);
+ if (tmp)
+ {
+ if (tmp->pixels != NULL)
+ {
+ if ((sdl = SDL_DisplayFormatAlpha(tmp)))
+ {
+ SDL_FreeSurface(tmp);
+ im = _sdl_image_new_from_sdl(sdl, file, key);
+
+ /* The update could failed if the real_key is already present
+ but dirty in the cache */
+ _SDL_CACHE_UPDATE(real_key, im);
+ return evas_cache_reference(cache, real_key);
+ }
+ }
+ SDL_FreeSurface(tmp);
+ tmp = NULL;
+ }
+
+ /* Failed, so use fallback */
+ im = _sdl_image_new_from_file(file, key);
+ if (im)
+ {
+ evas_common_load_image_data_from_file(im);
+ /* Convert the loaded image to a SDL_Surface */
+ tmp = SDL_CreateRGBSurfaceFrom(im->image->data,
+ im->image->w, im->image->h,
+ 32, im->image->w * 4,
+ 0xff0000, 0xff00, 0xff, 0xff000000);
+ if (tmp)
+ {
+ sdl = SDL_DisplayFormatAlpha(tmp);
+ SDL_FreeSurface(tmp);
+ if (sdl)
+ {
+ free(im->image->data);
+
+ im->image->data = (void*) sdl->pixels;
+ im->image->no_free = 1;
+ im->extended_info = sdl;
+
+ /* The update could failed if the real_key is already present
+ but dirty in the cache */
+ _SDL_CACHE_UPDATE(real_key, im);
+ im = evas_cache_reference(cache, real_key);
+ return im;
+ }
+ }
+ _sdl_image_free(im);
+ }
+ return NULL;
+}
+
+static void*
+evas_engine_sdl_image_new_from_copied_data(void *data,
+ int w, int h,
+ DATA32* image_data)
+{
+ Render_Engine *re = (Render_Engine*) data;
+ RGBA_Image *im = NULL;
+ SDL_Surface *sdl = NULL;
+
+ CHECK_CACHE(0, 0);
+
+ sdl = SDL_CreateRGBSurfaceFrom(image_data,
+ w, h,
+ 32, w * 4,
+ 0xff0000, 0xff00, 0xff, 0xff000000);
+
+ if (sdl)
+ {
+ RGBA_Image* rim = NULL;
+ char* real_key = NULL;
+
+ im = _sdl_image_new_from_sdl(sdl, NULL, NULL);
+ im->image->no_free = 0;
+ _SDL_BUILD_HASH_KEY(real_key, im->info.file, im->info.key, NULL);
+ evas_cache_update(cache, real_key, im, evas_common_image_ram_usage(im), 1);
+
+ return evas_cache_reference(cache, real_key);
+ }
+ return NULL;
+}
+
+static void*
+evas_engine_sdl_image_new_from_data(void *data, int w, int h, DATA32* image_data)
+{
+ return evas_engine_sdl_image_new_from_copied_data(data, w, h, image_data);
+}
+
+static void
+evas_engine_sdl_image_free(void *data, void *image)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ char* key = NULL;
+ RGBA_Image* im = (RGBA_Image*) image;
+
+ CHECK_CACHE(0, 0);
+ _SDL_BUILD_HASH_KEY(key, im->info.file, im->info.key, );
+
+ evas_cache_unreference(cache, key);
+}
+
+static void*
+evas_engine_sdl_image_size_set(void *data, void *image, int w, int h)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im_old = (RGBA_Image*) image;
+ RGBA_Image* im = NULL;
+ char* key = NULL;
+ SDL_Surface* sdl = NULL;
+
+ CHECK_CACHE(0, 0);
+ _SDL_BUILD_HASH_KEY(key, im_old->info.file, im_old->info.key, NULL);
+
+ sdl = SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_SRCALPHA,
+ w, h, 32,
+ 0xff0000, 0xff00, 0xff, 0xff000000);
+ if (!sdl)
+ return im_old;
+
+ im = _sdl_image_new_from_sdl(sdl, im_old->info.file, im_old->info.key);
+ if (!im)
+ {
+ SDL_FreeSurface(sdl);
+ return im_old;
+ }
+
+ if (im_old)
+ {
+ evas_common_load_image_data_from_file(im_old);
+ if (im_old->image->data)
+ _sdl_stretch_blit (im_old, im, w, h);
+
+ evas_cache_unreference(cache, key);
+ /* This update could failed if the real_key is still referenced by someone */
+ if (!evas_cache_update(cache,
+ key, im, evas_common_image_ram_usage (im),
+ 1))
+ _sdl_image_free(im);
+ }
+ return evas_cache_reference(cache, key);
+}
+
+void*
+evas_engine_sdl_image_dirty_region(void *data,
+ void *image,
+ int x, int y, int w, int h)
+{
+ RGBA_Image* im = (RGBA_Image*) image;
+
+ im->flags |= RGBA_IMAGE_IS_DIRTY;
+
+ return image;
+}
+
+void*
+evas_engine_sdl_image_data_get(void *data, void *image,
+ int to_write, DATA32** image_data)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = (RGBA_Image*) image;
+ DATA32* buffer = NULL;
+ int size = im->image->w * im->image->h * sizeof (DATA32);
+
+ buffer = malloc (size);
+ if (buffer)
+ {
+ if (im->extended_info && SDL_MUSTLOCK(((SDL_Surface*) im->extended_info)))
+ {
+ SDL_LockSurface(im->extended_info);
+ _SDL_UPDATE_PIXELS(im);
+ }
+
+ memcpy (buffer, im->image->data, size);
+
+ if (im->extended_info && SDL_MUSTLOCK(((SDL_Surface*) im->extended_info)))
+ SDL_UnlockSurface(im->extended_info);
+ }
+ *image_data = buffer;
+
+ return im;
+}
+
+void*
+evas_engine_sdl_image_data_put(void *data, void *image, DATA32* image_data)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = (RGBA_Image*) image;
+ SDL_Surface* sdl = NULL;
+
+ CHECK_CACHE(0, 0);
+ if (image_data != im->image->data)
+ {
+ char* str = NULL;
+ int w = im->image->w;
+ int h = im->image->h;
+
+ _SDL_BUILD_HASH_KEY(str, im->info.file, im->info.key, NULL);
+ evas_cache_unreference (cache, str);
+
+ sdl = SDL_CreateRGBSurfaceFrom (image_data,
+ w, h, 32, w * 4,
+ 0xff0000, 0xff00, 0xff, 0xff000000);
+ if (sdl)
+ {
+ im = _sdl_image_new_from_sdl (sdl, im->info.file, im->info.key);
+ if (im)
+ {
+ im->image->no_free = 0;
+ /* This update could failed if the real_key is
+ still referenced by someone */
+ if (!evas_cache_update (cache,
+ str, im, evas_common_image_ram_usage (im),
+ 1))
+ _sdl_image_free (im);
+ }
+ else
+ SDL_FreeSurface (sdl);
+ return evas_cache_reference (cache, str);
+ }
+ return NULL;
+ }
+
+ im->flags |= RGBA_IMAGE_IS_DIRTY;
+ return im;
+}
+
+void*
+evas_engine_sdl_image_alpha_set(void *data, void *image, int has_alpha)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = (RGBA_Image*) image;
+
+ /* FIXME: update SDL_Surface flags */
+ if (has_alpha)
+ im->flags |= RGBA_IMAGE_HAS_ALPHA;
+ else
+ im->flags &= ~RGBA_IMAGE_HAS_ALPHA;
+ return im;
+}
+
+int
+evas_engine_sdl_image_alpha_get(void *data, void *image)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = (RGBA_Image*) image;
+
+ if (im->flags & RGBA_IMAGE_HAS_ALPHA)
+ return 1;
+ return 0;
+}
+
+void*
+evas_engine_sdl_image_border_set(void *data, void *image, int l, int r, int t, int b)
+{
+ /* FIXME: need to know what evas expect from this call */
+ return image;
+}
+
+void
+evas_engine_sdl_image_border_get(void *data, void *image, int *l, int *r, int *t, int *b)
+{
+ /* FIXME: need to know what evas expect from this call */
+}
+
+void
+evas_engine_sdl_image_draw(void *data, void *context, void *surface, void *image,
+ int src_region_x, int src_region_y, int src_region_w, int src_region_h,
+ int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h,
+ int smooth)
+{
+ Render_Engine* re = (Render_Engine*) data;
+ RGBA_Image* im = (RGBA_Image*) image;
+ RGBA_Draw_Context* dc = (RGBA_Draw_Context*) context;
+
+ /* Fallback to software method */
+ if (SDL_MUSTLOCK(((SDL_Surface*) re->surface)))
+ {
+ SDL_LockSurface (re->surface);
+ _SDL_UPDATE_PIXELS(re->rgba_image);
+ }
+
+ if (im->extended_info && SDL_MUSTLOCK(((SDL_Surface*) im->extended_info)))
+ {
+ SDL_LockSurface (im->extended_info);
+ _SDL_UPDATE_PIXELS(im);
+ }
+
+ if (smooth)
+ evas_common_scale_rgba_in_to_out_clip_smooth (im, re->rgba_image, dc,
+ src_region_x, src_region_y, src_region_w, src_region_h,
+ dst_region_x, dst_region_y, dst_region_w, dst_region_h);
+ else
+ evas_common_scale_rgba_in_to_out_clip_sample (im, re->rgba_image, dc,
+ src_region_x, src_region_y, src_region_w, src_region_h,
+ dst_region_x, dst_region_y, dst_region_w, dst_region_h);
+ if (im->extended_info && SDL_MUSTLOCK(((SDL_Surface*) im->extended_info)))
+ SDL_UnlockSurface (im->extended_info);
+
+ if (SDL_MUSTLOCK(((SDL_Surface*) re->surface)))
+ SDL_UnlockSurface (re->surface);
+
+ evas_common_cpu_end_opt ();
+}
+
+void
+evas_engine_sdl_image_cache_flush(void *data)
+{
+ CHECK_CACHE(0, 0);
+ evas_cache_force_flush (cache);
+}
+
+void
+evas_engine_sdl_image_cache_set(void *data, int bytes)
+{
+ CHECK_CACHE(0, 0);
+ evas_cache_set_maximum_size (cache, bytes);
+}
+
+int
+evas_engine_sdl_image_cache_get(void *data)
+{
+ CHECK_CACHE(0, 0);
+ return evas_cache_get_maximum_size (cache);
+}
+
+char*
+evas_engine_sdl_image_comment_get(void *data, void *image, char *key)
+{
+ RGBA_Image *im = (RGBA_Image*) image;
+
+ return im->info.comment;
+}
+
+char*
+evas_engine_sdl_image_format_get(void *data, void *image)
+{
+ /* FIXME: need to know what evas expect from this call */
+ return NULL;
+}
+
+
+int module_open(Evas_Module *em)
+{
+ if (!em) return 0;
+ /* get whatever engine module we inherit from */
+ if (!_evas_module_engine_inherit(&pfunc, "software_generic")) return 0;
+ /* store it for later use */
+ func = pfunc;
+ /* now to override methods */
+#define ORD(f) EVAS_API_OVERRIDE(f, &func, evas_engine_sdl_)
+ ORD(info);
+ ORD(info_free);
+ ORD(setup);
+ ORD(output_free);
+ ORD(output_resize);
+ ORD(output_tile_size_set);
+ ORD(output_redraws_rect_add);
+ ORD(output_redraws_rect_del);
+ ORD(output_redraws_clear);
+ ORD(output_redraws_next_update_get);
+ ORD(output_redraws_next_update_push);
+ ORD(output_flush);
+ ORD(image_load);
+ ORD(image_new_from_data);
+ ORD(image_new_from_copied_data);
+ ORD(image_free);
+ ORD(image_size_set);
+ ORD(image_dirty_region);
+ ORD(image_data_get);
+ ORD(image_data_put);
+ ORD(image_alpha_set);
+ ORD(image_alpha_get);
+ ORD(image_border_set);
+ ORD(image_border_get);
+ ORD(image_draw);
+ ORD(image_comment_get);
+ ORD(image_format_get);
+ ORD(image_cache_flush);
+ ORD(image_cache_set);
+ ORD(image_cache_get);
+ /* now advertise out own api */
+ em->functions = (void *)(&func);
+ return 1;
+}
+
+void module_close(void)
+{
+
+}
+
+Evas_Module_Api evas_modapi =
+{
+ EVAS_MODULE_API_VERSION,
+ EVAS_MODULE_TYPE_ENGINE,
+ "sdl",
+ "none"
+};
+
+/*
+ * Private routines. These are slightly modified versions of the ones in
+ * engines/sdl/evas_engine_sdl_image_objects.c
+ */
+
+struct ext_loader_s {
+ const char* extention;
+ const char* loader;
+};
+
+static struct ext_loader_s loaders[] = {
+ { "png", "png" },
+ { "jpg", "jpeg" },
+ { "jpeg", "jpeg" },
+ { "jfif", "jpeg" },
+ { "eet", "eet" },
+ { "edj", "eet" },
+ { "eap", "eet" },
+ { "edb", "edb" }
+};
+
+static RGBA_Image*
+_sdl_image_loader (RGBA_Image* im, const char* filename, const char* key)
+{
+ Evas_List* l = NULL;
+ char* dot = NULL;
+ const char* loader = NULL;
+ int i = 0;
+
+ if (!filename)
+ return im;
+
+ dot = strrchr (filename, '.');
+ if (dot)
+ {
+ for (i = 0, ++dot; i < (sizeof (loaders) / sizeof (struct ext_loader_s)); ++i)
+ {
+ if (!strcasecmp (dot, loaders[i].extention))
+ {
+ loader = loaders[i].loader;
+ break;
+ }
+ }
+ }
+
+ if (loader)
+ {
+ Evas_Module* em = NULL;
+
+ em = evas_module_find_type (EVAS_MODULE_TYPE_IMAGE_LOADER, loader);
+ if (em && evas_module_load (em))
+ {
+ Evas_Image_Load_Func* evas_image_load_func = em->functions;
+
+ if (evas_image_load_func->file_head (im, filename, key))
+ {
+ im->info.loader = (void*) evas_image_load_func;
+ return im;
+ }
+ }
+ }
+
+ for (l = evas_modules; l; l = l->next)
+ {
+ Evas_Image_Load_Func* evas_image_load_func = NULL;
+ Evas_Module* em = NULL;
+
+ em = l->data;
+ if (em->type != EVAS_MODULE_TYPE_IMAGE_LOADER) continue;
+ if (!evas_module_load (em)) continue;
+ evas_image_load_func = em->functions;
+ if (evas_image_load_func->file_head (im, filename, key))
+ {
+ im->info.loader = (void*) evas_image_load_func;
+ return im;
+ }
+ }
+
+ _sdl_image_free (im);
+ return NULL;
+}
+
+static RGBA_Image*
+_sdl_image_new_from_file (const char* filename, const char* key)
+{
+ RGBA_Image *im = NULL;
+ char* final_key = key ? NULL : alloca (sizeof (char) * 10);
+
+ im = evas_common_image_new ();
+ if (!im)
+ return NULL;
+ im->image = evas_common_image_surface_new (im);
+ if (!im->image)
+ {
+ evas_common_image_free (im);
+ return NULL;
+ }
+
+ im = _sdl_image_loader (im, filename, key);
+ if (!im)
+ return NULL;
+
+ im->image->data = NULL;
+ im->image->no_free = 1;
+ im->extended_info = NULL;
+
+ im->info.file = (char*) evas_stringshare_add (filename ? filename : "unknown");
+ if (!key)
+ {
+ if (!filename)
+ {
+ struct timeval tv;
+
+ gettimeofday(&tv, NULL);
+ snprintf (final_key, 10, "%i", (tv.tv_sec & 0xFFFFFFFF) ^ (tv.tv_usec & 0xFFFFFFFF));
+ }
+ else
+ final_key = "null";
+ }
+ else
+ final_key = (char*) key;
+
+ im->info.key = (char*) evas_stringshare_add (final_key);
+
+ return im;
+}
+
+static RGBA_Image*
+_sdl_image_new_from_sdl (SDL_Surface* sdl, const char* filename, const char* key)
+{
+ RGBA_Image* im = _sdl_image_new_from_file (filename, key);
+
+ if (!im)
+ return NULL;
+
+ im->image->data = (void*) sdl->pixels;
+ im->image->no_free = 1;
+ im->extended_info = sdl;
+ im->image->w = sdl->w;
+ im->image->h = sdl->h;
+
+ if (sdl->flags & SDL_SRCALPHA)
+ im->flags |= RGBA_IMAGE_HAS_ALPHA;
+
+ return im;
+}
+
+static void
+_sdl_image_free (RGBA_Image* im)
+{
+ if (im->image && im->extended_info)
+ SDL_FreeSurface(im->extended_info);
+ evas_common_image_free (im);
+}
+
+static void
+_sdl_evicted_image (Evas_Cache* cache, const char* key, void* object, int reference)
+{
+ RGBA_Image* im = (RGBA_Image*) object;
+
+ _sdl_image_free (im);
+}
+
+static void*
+_sdl_output_setup (int w, int h, int fullscreen, int noframe)
+{
+ Render_Engine *re = calloc(1, sizeof(Render_Engine));
+
+ /* if we haven't initialized - init (automatic abort if already done) */
+ evas_common_cpu_init();
+ evas_common_blend_init();
+ evas_common_image_init();
+ evas_common_convert_init();
+ evas_common_scale_init();
+ evas_common_rectangle_init();
+ evas_common_gradient_init();
+ evas_common_polygon_init();
+ evas_common_line_init();
+ evas_common_font_init();
+ evas_common_draw_init();
+ evas_common_tilebuf_init();
+
+ re->tb = evas_common_tilebuf_new(w, h);
+ /* in preliminary tests 16x16 gave highest framerates */
+ evas_common_tilebuf_set_tile_size(re->tb, TILESIZE, TILESIZE);
+
+ re->surface = SDL_SetVideoMode(w, h, 32,
+ SDL_SWSURFACE
+ | (fullscreen ? SDL_FULLSCREEN : 0)
+ | (noframe ? SDL_NOFRAME : 0));
+ if (!re->surface)
+ return NULL;
+
+ SDL_SetAlpha(re->surface, SDL_SRCALPHA | SDL_RLEACCEL, 0);
+
+ /* We create a "fake" RGBA_Image which points to the SDL surface. Each access
+ * to that surface is wrapped in Lock / Unlock calls whenever the data is
+ * manipulated directly. */
+ re->rgba_image = _sdl_image_new_from_sdl (re->surface, NULL, "SCREEN");
+
+ if (!re->rgba_image)
+ {
+ fprintf(stderr, "RGBA_Image allocation from SDL failed\n");
+ exit (-1);
+ }
+
+ re->fullscreen = fullscreen;
+ re->noframe = noframe;
+ return re;
+}
+
+static void
+_sdl_debug_rgba_image (RGBA_Image* im)
+{
+ printf ("*** Image (%p) ***\n", im);
+ if (im)
+ {
+ printf ("* W: %i\n* H: %i\n", im->image->w, im->image->h);
+ printf ("* Pixels: %p\n* SDL Surface: %p\n", im->image->data, im->extended_info);
+ printf ("* Flags: %i\n", im->flags);
+ printf ("* Filename: %s\n* Key: %s\n", im->info.file, im->info.key);
+ printf ("* SDL_Surface: %p\n", im->extended_info);
+ }
+ printf ("*** ***\n");
+}
+
+static void
+_sdl_stretch_blit (RGBA_Image* from,
+ RGBA_Image* to,
+ int w, int h)
+{
+ int is_sdl_from = 0;
+ int is_sdl_to = 0;
+
+ if (from->extended_info)
+ is_sdl_from = 1;
+ if (to->extended_info)
+ is_sdl_to = 1;
+
+ if (is_sdl_from)
+ {
+ if (SDL_MUSTLOCK(((SDL_Surface*) from->extended_info)))
+ {
+ SDL_LockSurface(from->extended_info);
+ _SDL_UPDATE_PIXELS(from);
+ }
+ }
+
+ if (is_sdl_to)
+ if (SDL_MUSTLOCK(((SDL_Surface*) to->extended_info)))
+ {
+ SDL_LockSurface(to->extended_info);
+ _SDL_UPDATE_PIXELS(to);
+ }
+
+ evas_common_blit_rectangle(from, to, 0, 0, w, h, 0, 0);
+
+ if (is_sdl_to && SDL_MUSTLOCK(((SDL_Surface*) to->extended_info)))
+ SDL_UnlockSurface(to->extended_info);
+
+ if (is_sdl_from && SDL_MUSTLOCK(((SDL_Surface*) from->extended_info)))
+ SDL_UnlockSurface(from->extended_info);
+
+ evas_common_cpu_end_opt();
+}
diff -Nru -x CVS e17-main/libs/evas/src/modules/engines/sdl/evas_engine_sdl.h e17-dev/libs/evas/src/modules/engines/sdl/evas_engine_sdl.h
--- e17-main/libs/evas/src/modules/engines/sdl/evas_engine_sdl.h 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/modules/engines/sdl/evas_engine_sdl.h 2006-08-09 00:02:44.000000000 +0200
@@ -0,0 +1,24 @@
+#ifndef EVAS_ENGINE_SDL_H
+#define EVAS_ENGINE_SDL_H
+#include "evas_common.h"
+#include "evas_private.h"
+#include "Evas_Engine_SDL.h"
+
+typedef struct _Render_Engine Render_Engine;
+
+struct _Render_Engine
+{
+ Tilebuf* tb;
+ Tilebuf_Rect* rects;
+ Evas_Object_List* cur_rect;
+ SDL_Surface* surface;
+ RGBA_Image* rgba_image;
+ SDL_Rect* update_rects;
+ int update_rects_count;
+ int update_rects_limit;
+ int fullscreen:1;
+ int noframe:1;
+ int end:1;
+};
+
+#endif
diff -Nru -x CVS e17-main/libs/evas/src/modules/engines/sdl/Evas_Engine_SDL.h e17-dev/libs/evas/src/modules/engines/sdl/Evas_Engine_SDL.h
--- e17-main/libs/evas/src/modules/engines/sdl/Evas_Engine_SDL.h 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/modules/engines/sdl/Evas_Engine_SDL.h 2006-08-01 16:33:12.000000000 +0200
@@ -0,0 +1,22 @@
+#ifndef _EVAS_ENGINE_SDL_H
+#define _EVAS_ENGINE_SDL_H
+
+#include <SDL/SDL.h>
+
+typedef struct _Evas_Engine_Info_SDL Evas_Engine_Info_SDL;
+
+struct _Evas_Engine_Info_SDL
+{
+ /* PRIVATE - don't mess with this baby or evas will poke its tongue out */
+ /* at you and make nasty noises */
+ Evas_Engine_Info magic;
+
+ struct {
+ SDL_Surface *surface;
+ int fullscreen : 1;
+ int noframe : 1;
+ } info;
+};
+#endif
+
+
diff -Nru -x CVS e17-main/libs/evas/src/modules/engines/sdl/Makefile.am e17-dev/libs/evas/src/modules/engines/sdl/Makefile.am
--- e17-main/libs/evas/src/modules/engines/sdl/Makefile.am 1970-01-01 01:00:00.000000000 +0100
+++ e17-dev/libs/evas/src/modules/engines/sdl/Makefile.am 2006-08-01 14:45:19.000000000 +0200
@@ -0,0 +1,28 @@
+AUTOMAKE_OPTIONS = 1.4 foreign
+
+MAINTAINERCLEANFILES = Makefile.in
+
+INCLUDES = -I. -I$(top_srcdir)/src/lib -I$(top_srcdir)/src/lib/include @FREETYPE_CFLAGS@ @DIRECTFB_CFLAGS@
+
+if BUILD_ENGINE_SDL
+
+pkgdir = $(libdir)/evas/modules/engines/sdl/$(MODULE_ARCH)
+
+pkg_LTLIBRARIES = module.la
+
+module_la_SOURCES = \
+evas_engine_sdl.c \
+evas_engine_sdl.h
+
+module_la_LIBADD = @DIRECTFB_LIBS@ $(top_builddir)/src/lib/libevas.la
+module_la_LDFLAGS = -module -avoid-version -L$(top_builddir)/src/lib -L$(top_builddir)/src/lib/.libs
+module_la_DEPENDENCIES = $(top_builddir)/config.h
+
+include_HEADERS = Evas_Engine_SDL.h
+
+endif
+
+EXTRA_DIST = \
+evas_engine_sdl.c \
+evas_engine_sdl.h \
+Evas_Engine_SDL.h
-------------------------------------------------------------------------
Using Tomcat but need to do more? Need to support web services, security?
Get stuff done quickly with pre-integrated technology to make your job easier
Download IBM WebSphere Application Server v.1.0.1 based on Apache Geronimo
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=120709&bid=263057&dat=121642
_______________________________________________
enlightenment-devel mailing list
enlightenment-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/enlightenment-devel