forked from enlightenment/efl
1. configure/build changes to allow cross-compiling painlessly 2. pager module namespace changes - this was still dirty afdter the namespace cleanup, so clean it up 3. add a powersave subsystem - doesnt have an "automatic" way to turn on and off right now, this i think is best provided by modules (that do things like monitor acpi status's (eg close lid of laptop), AC power status etc. etc. this allows e to nicely defer "power" expensive actions to avoid disk spinups etc. 4. move to use the new ecore poller system - discussed long ago as part of power management/saving issues. now it exists 5. add a canvas idle flush call that helsp cope with the new shm greedy software x11 engine stuff 6. use the new powersave subsystem where appropriate 7. fix non-zeroed/initted memory access in e_fm_main 8. fix mem leak for e menus 9. remove ipc handlers for changed/removed config values 10. use animaotr not timer for menu scrolls - then menu scrolls obey the fps config 11. fix up timer/poll happienss of cursor idle stuff 12. remove avoid damage from popups for now - causing problems 13. change battery and temp readouts to b e shorter so they fit 14. pager can emit signals on focus change for mini-windows now 15. temperature module now uses a slave process and uses stdin/out to talk to it and get output - this makes e smoother as in my expereicne i found getting the temp on my laptop actually took like 200ms so e "hang" for 200ms while reading the acpi files - so now the subprocess does it and just writesa back to e when it gets it. ecore: 1. add ecore_pollers. see the documentation on them in doxygen comments :) 2. fix timers to only go off when they have to - bug there that made e's select time out a LOT more than it needed to. defensive coding hid the problem. now fixed. e should be much more power friendly now. 3. formatting/niceness in ecore_exe stuff 4. some comments on comments with SIGIO ideas vs. select 5. add call to be able to add an idle enterer at the start of the list of them, not just the end (as has been the default) 6. fix ecore_evas to support auto evas idler calls after 0.5 secs of idle in all canvases - and to do it right 7. if argb destination - set the shape EVENT shape (to mask out events in transparent regions much like shape does withotu translucency) 8. in ecore_x add support for the event shape evas: 1. fix cache to work properly and not just always fill up (as it seemed to like to think cahce useage dropped below 0 when it didnt and thus just over-fill) 2. software x11 engine now ONLY uses shm segments - no ximages over the socket. this ximage hack was there to avoid the 2 round trips involved in setting up an shm image - now i mitigated that wih an shm image cache pool. it keeps shm images around and repurposes them for new update regions if appropriate. this means many fewer shm creates (about 1/100th the number) and since we recycle the memory less 0 memory page filling by the kernel - in the end, i recorded about a 10-20% speedup over the old software x11 engine. simple tests i have seen up to 120% speedups. idle flush now does something - it frees all the cached shm segments. it has a hard-coded limit of 4mb worth of shm segments (or 32 segments - whichever comes first) to keep around. once can never complain much about speedups methinks :). also evas will defer sync until the NEXT frame is written - this means evas can calculate the next frame of data while x dma's/copies the images to the screen at the same time (if you hve a dual core or multi-cpu machnike or your xserver is able to use DMA to copy image data to the screen/video ram then this should see a decent speedup). SVN revision: 33448
This commit is contained in:
parent
2909ac19e4
commit
c1441e1c3a
|
@ -85,18 +85,23 @@ extern "C" {
|
|||
|
||||
enum _Ecore_Exe_Flags /* flags for executing a child with its stdin and/or stdout piped back */
|
||||
{
|
||||
|
||||
ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */
|
||||
ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */
|
||||
ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */
|
||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */
|
||||
ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */
|
||||
ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */
|
||||
ECORE_EXE_USE_SH = 128 /**< Use /bin/sh to run the command. */
|
||||
ECORE_EXE_PIPE_READ = 1, /**< Exe Pipe Read mask */
|
||||
ECORE_EXE_PIPE_WRITE = 2, /**< Exe Pipe Write mask */
|
||||
ECORE_EXE_PIPE_ERROR = 4, /**< Exe Pipe error mask */
|
||||
ECORE_EXE_PIPE_READ_LINE_BUFFERED = 8, /**< Reads are buffered until a newline and delivered 1 event per line */
|
||||
ECORE_EXE_PIPE_ERROR_LINE_BUFFERED = 16, /**< Errors are buffered until a newline and delivered 1 event per line */
|
||||
ECORE_EXE_PIPE_AUTO = 32, /**< stdout and stderr are buffered automatically */
|
||||
ECORE_EXE_RESPAWN = 64, /**< FIXME: Exe is restarted if it dies */
|
||||
ECORE_EXE_USE_SH = 128 /**< Use /bin/sh to run the command. */
|
||||
};
|
||||
typedef enum _Ecore_Exe_Flags Ecore_Exe_Flags;
|
||||
|
||||
enum _Ecore_Poller_Type /* Poller types */
|
||||
{
|
||||
ECORE_POLLER_CORE = 0 /**< The core poller interval */
|
||||
};
|
||||
typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef void Ecore_Exe; /**< A handle for spawned processes */
|
||||
#endif
|
||||
|
@ -109,6 +114,7 @@ extern "C" {
|
|||
typedef void Ecore_Event_Filter; /**< A handle for an event filter */
|
||||
typedef void Ecore_Event; /**< A handle for an event */
|
||||
typedef void Ecore_Animator; /**< A handle for animators */
|
||||
typedef void Ecore_Poller; /**< A handle for pollers */
|
||||
#endif
|
||||
typedef struct _Ecore_Event_Signal_User Ecore_Event_Signal_User; /**< User signal event */
|
||||
typedef struct _Ecore_Event_Signal_Hup Ecore_Event_Signal_Hup; /**< Hup signal event */
|
||||
|
@ -250,6 +256,7 @@ extern "C" {
|
|||
EAPI void *ecore_idler_del(Ecore_Idler *idler);
|
||||
|
||||
EAPI Ecore_Idle_Enterer *ecore_idle_enterer_add(int (*func) (void *data), const void *data);
|
||||
EAPI Ecore_Idle_Enterer *ecore_idle_enterer_before_add(int (*func) (void *data), const void *data);
|
||||
EAPI void *ecore_idle_enterer_del(Ecore_Idle_Enterer *idle_enterer);
|
||||
|
||||
EAPI Ecore_Idle_Exiter *ecore_idle_exiter_add(int (*func) (void *data), const void *data);
|
||||
|
@ -276,6 +283,12 @@ extern "C" {
|
|||
EAPI void ecore_animator_frametime_set(double frametime);
|
||||
EAPI double ecore_animator_frametime_get(void);
|
||||
|
||||
EAPI void ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time);
|
||||
EAPI double ecore_poller_poll_interval_get(Ecore_Poller_Type type);
|
||||
EAPI Ecore_Poller *ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data);
|
||||
EAPI void *ecore_poller_del(Ecore_Poller *poller);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,7 @@ ecore_time.c \
|
|||
ecore_timer.c \
|
||||
ecore_tree.c \
|
||||
ecore_value.c \
|
||||
ecore_poll.c \
|
||||
ecore_private.h
|
||||
|
||||
libecore_la_LIBADD = @dlopen_libs@ @winsock_libs@ -lm
|
||||
|
|
|
@ -84,6 +84,7 @@ ecore_shutdown(void)
|
|||
return _ecore_init_count;
|
||||
|
||||
if (_ecore_fps_debug) _ecore_fps_debug_shutdown();
|
||||
_ecore_poller_shutdown();
|
||||
_ecore_animator_shutdown();
|
||||
#ifndef _WIN32
|
||||
_ecore_exe_shutdown();
|
||||
|
|
|
@ -260,7 +260,7 @@ ecore_exe_run(const char *exe_cmd, const void *data)
|
|||
* terminated event have been called, the handle will be freed by Ecore.
|
||||
*
|
||||
* This function does the same thing as ecore_exe_run(), but also makes the
|
||||
* standard in and/or out as wel las stderr from the child process available
|
||||
* standard in and/or out as well as stderr from the child process available
|
||||
* for reading or writing. To write use ecore_exe_send(). To read listen to
|
||||
* ECORE_EXE_EVENT_DATA or ECORE_EXE_EVENT_ERROR events (set up handlers).
|
||||
* Ecore may buffer read and error data until a newline character if asked
|
||||
|
@ -288,16 +288,14 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
int ok = 1;
|
||||
int result;
|
||||
|
||||
if (!exe_cmd)
|
||||
return NULL;
|
||||
|
||||
if (!exe_cmd) return NULL;
|
||||
exe = calloc(1, sizeof(Ecore_Exe));
|
||||
if (exe == NULL)
|
||||
return NULL;
|
||||
if (exe == NULL) return NULL;
|
||||
|
||||
if ((flags & ECORE_EXE_PIPE_AUTO) && (!(flags & ECORE_EXE_PIPE_ERROR))
|
||||
&& (!(flags & ECORE_EXE_PIPE_READ)))
|
||||
flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR; /* We need something to auto pipe. */
|
||||
/* We need something to auto pipe. */
|
||||
flags |= ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR;
|
||||
|
||||
exe->child_fd_error = -1;
|
||||
exe->child_fd_read = -1;
|
||||
|
@ -308,37 +306,44 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
|
||||
/* Create some pipes. */
|
||||
if (ok)
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok)
|
||||
{
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(statusPipe), ok)
|
||||
{
|
||||
}
|
||||
}
|
||||
if (ok && (flags & ECORE_EXE_PIPE_ERROR))
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok)
|
||||
{
|
||||
exe->child_fd_error = errorPipe[0];
|
||||
exe->child_fd_error_x = errorPipe[1];
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(errorPipe), ok)
|
||||
{
|
||||
exe->child_fd_error = errorPipe[0];
|
||||
exe->child_fd_error_x = errorPipe[1];
|
||||
}
|
||||
}
|
||||
if (ok && (flags & ECORE_EXE_PIPE_READ))
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok)
|
||||
{
|
||||
exe->child_fd_read = readPipe[0];
|
||||
exe->child_fd_read_x = readPipe[1];
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(readPipe), ok)
|
||||
{
|
||||
exe->child_fd_read = readPipe[0];
|
||||
exe->child_fd_read_x = readPipe[1];
|
||||
}
|
||||
}
|
||||
if (ok && (flags & ECORE_EXE_PIPE_WRITE))
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok)
|
||||
{
|
||||
exe->child_fd_write = writePipe[1];
|
||||
exe->child_fd_write_x = writePipe[0];
|
||||
E_IF_NO_ERRNO_NOLOOP(result, pipe(writePipe), ok)
|
||||
{
|
||||
exe->child_fd_write = writePipe[1];
|
||||
exe->child_fd_write_x = writePipe[0];
|
||||
}
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
pid_t pid = 0;
|
||||
volatile int vfork_exec_errno = 0;
|
||||
|
||||
|
||||
/* FIXME: I should double check this. After a quick look around, this is already done, but via a more modern method. */
|
||||
/* signal(SIGPIPE, SIG_IGN); We only want EPIPE on errors */
|
||||
pid = fork();
|
||||
|
||||
|
||||
if (pid == -1)
|
||||
{
|
||||
fprintf(stderr, "Failed to fork process\n");
|
||||
|
@ -346,8 +351,9 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
}
|
||||
else if (pid == 0) /* child */
|
||||
{
|
||||
/* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the second pipe if it's open. */
|
||||
/* On the other hand, there was the Great FD Leak Scare of '06, so let's be paranoid. */
|
||||
/* dup2 STDERR, STDIN, and STDOUT. dup2() allegedly closes the
|
||||
* second pipe if it's open. On the other hand, there was the
|
||||
* Great FD Leak Scare of '06, so let's be paranoid. */
|
||||
if (ok && (flags & ECORE_EXE_PIPE_ERROR))
|
||||
{
|
||||
E_NO_ERRNO(result, close(STDERR_FILENO), ok);
|
||||
|
@ -369,10 +375,10 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
/* Setup the status pipe. */
|
||||
E_NO_ERRNO(result, close(statusPipe[0]), ok);
|
||||
E_IF_NO_ERRNO(result, fcntl(statusPipe[1], F_SETFD, FD_CLOEXEC), ok) /* close on exec shows sucess */
|
||||
{
|
||||
/* Run the actual command. */
|
||||
_ecore_exe_exec_it(exe_cmd, flags); /* Should not return from this. */
|
||||
}
|
||||
{
|
||||
/* Run the actual command. */
|
||||
_ecore_exe_exec_it(exe_cmd, flags); /* no return */
|
||||
}
|
||||
}
|
||||
|
||||
/* Something went 'orribly wrong. */
|
||||
|
@ -380,13 +386,13 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
|
||||
/* Close the pipes. */
|
||||
if (flags & ECORE_EXE_PIPE_ERROR)
|
||||
E_NO_ERRNO(result, close(errorPipe[1]), ok);
|
||||
E_NO_ERRNO(result, close(errorPipe[1]), ok);
|
||||
if (flags & ECORE_EXE_PIPE_READ)
|
||||
E_NO_ERRNO(result, close(readPipe[1]), ok);
|
||||
E_NO_ERRNO(result, close(readPipe[1]), ok);
|
||||
if (flags & ECORE_EXE_PIPE_WRITE)
|
||||
E_NO_ERRNO(result, close(writePipe[0]), ok);
|
||||
E_NO_ERRNO(result, close(writePipe[0]), ok);
|
||||
E_NO_ERRNO(result, close(statusPipe[1]), ok);
|
||||
|
||||
|
||||
_exit(-1);
|
||||
}
|
||||
else /* parent */
|
||||
|
@ -394,13 +400,28 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
/* Close the unused pipes. */
|
||||
E_NO_ERRNO(result, close(statusPipe[1]), ok);
|
||||
|
||||
/* FIXME: after having a good look at the current e fd handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */
|
||||
/* FIXME: after having a good look at the current e fd
|
||||
* handling, investigate fcntl(dataPipe[x], F_SETSIG, ...) */
|
||||
/* FIXME: above F_SETSIG etc. - this is async SIGIO based IO
|
||||
* which is also linux specific so we probably don't want to
|
||||
* do this as long as select() is working fine. the only time
|
||||
* we really want to think of SIGIO async IO is when it all
|
||||
* actually works basically everywhere and we can turn all
|
||||
* IO into DMA async activities (i.e. you do a read() then
|
||||
* the read is complete not on return but when you get a
|
||||
* SIGIO - the read() just starts the transfer and it is
|
||||
* completed in the background by DMA (or whatever mechanism
|
||||
* the kernel choses)) */
|
||||
|
||||
/* Wait for it to start executing. */
|
||||
while (1)
|
||||
/* FIXME: this doesn't seem very nice - we sit and block
|
||||
* waiting on a child process... even though it's just
|
||||
* the segment between the fork() and the exec) it just feels
|
||||
* wrong */
|
||||
for (;;)
|
||||
{
|
||||
char buf;
|
||||
|
||||
|
||||
E_NO_ERRNO(result, read(statusPipe[0], &buf, 1), ok);
|
||||
if (result == 0)
|
||||
{
|
||||
|
@ -433,7 +454,7 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
if ((exe->cmd = strdup(exe_cmd)))
|
||||
{
|
||||
if (flags & ECORE_EXE_PIPE_ERROR)
|
||||
{ /* Setup the error stuff. */
|
||||
{ /* Setup the error stuff. */
|
||||
E_IF_NO_ERRNO(result,
|
||||
fcntl(exe->child_fd_error, F_SETFL,
|
||||
O_NONBLOCK), ok) {}
|
||||
|
@ -454,7 +475,7 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
}
|
||||
}
|
||||
if (ok && (flags & ECORE_EXE_PIPE_READ))
|
||||
{ /* Setup the read stuff. */
|
||||
{ /* Setup the read stuff. */
|
||||
E_IF_NO_ERRNO(result,
|
||||
fcntl(exe->child_fd_read, F_SETFL,
|
||||
O_NONBLOCK), ok) {}
|
||||
|
@ -497,35 +518,34 @@ ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
|
|||
ok = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exes = _ecore_list2_append(exes, exe);
|
||||
n = 0;
|
||||
}
|
||||
else
|
||||
ok = 0;
|
||||
ok = 0;
|
||||
}
|
||||
else
|
||||
ok = 0;
|
||||
ok = 0;
|
||||
}
|
||||
|
||||
if (!ok)
|
||||
{ /* Something went wrong, so pull down everything. */
|
||||
if (exe->pid)
|
||||
ecore_exe_terminate(exe);
|
||||
{ /* Something went wrong, so pull down everything. */
|
||||
if (exe->pid) ecore_exe_terminate(exe);
|
||||
IF_FN_DEL(ecore_exe_free, exe);
|
||||
}
|
||||
else
|
||||
{
|
||||
Ecore_Exe_Event_Add *e;
|
||||
|
||||
|
||||
e = _ecore_exe_event_add_new();
|
||||
e->exe = exe;
|
||||
if (e) /* Send the event. */
|
||||
ecore_event_add(ECORE_EXE_EVENT_ADD, e,
|
||||
_ecore_exe_event_add_free, NULL);
|
||||
if (e) /* Send the event. */
|
||||
ecore_event_add(ECORE_EXE_EVENT_ADD, e,
|
||||
_ecore_exe_event_add_free, NULL);
|
||||
/* printf("Running as %d for %s.\n", exe->pid, exe->cmd); */
|
||||
}
|
||||
|
||||
|
||||
errno = n;
|
||||
return exe;
|
||||
}
|
||||
|
@ -549,8 +569,7 @@ ecore_exe_send(Ecore_Exe * exe, void *data, int size)
|
|||
void *buf;
|
||||
|
||||
buf = realloc(exe->write_data_buf, exe->write_data_size + size);
|
||||
if (buf == NULL)
|
||||
return 0;
|
||||
if (buf == NULL) return 0;
|
||||
|
||||
exe->write_data_buf = buf;
|
||||
memcpy((char *)exe->write_data_buf + exe->write_data_size, data, size);
|
||||
|
@ -1365,7 +1384,10 @@ _ecore_exe_data_generic_handler(void *data, Ecore_Fd_Handler * fd_handler,
|
|||
|
||||
lost_exe = 0;
|
||||
errno = 0;
|
||||
if ((num = read(child_fd, buf, READBUFSIZ)) < 1) /* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE (currently 64k) to inbuf, use that instead of buf, and save ourselves a memcpy(). */
|
||||
if ((num = read(child_fd, buf, READBUFSIZ)) < 1)
|
||||
/* FIXME: SPEED/SIZE TRADE OFF - add a smaller READBUFSIZE
|
||||
* (currently 64k) to inbuf, use that instead of buf, and
|
||||
* save ourselves a memcpy(). */
|
||||
{
|
||||
lost_exe = ((errno == EIO) ||
|
||||
(errno == EBADF) ||
|
||||
|
|
|
@ -27,6 +27,29 @@ ecore_idle_enterer_add(int (*func) (void *data), const void *data)
|
|||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an idle enterer handler at the start of the list so it gets called earlier than others.
|
||||
* @param func The function to call when entering an idle state.
|
||||
* @param data The data to be passed to the @p func call
|
||||
* @return A handle to the idle enterer callback if successful. Otherwise,
|
||||
* NULL is returned.
|
||||
* @ingroup Idle_Group
|
||||
*/
|
||||
EAPI Ecore_Idle_Enterer *
|
||||
ecore_idle_enterer_before_add(int (*func) (void *data), const void *data)
|
||||
{
|
||||
Ecore_Idle_Enterer *ie;
|
||||
|
||||
if (!func) return NULL;
|
||||
ie = calloc(1, sizeof(Ecore_Idle_Enterer));
|
||||
if (!ie) return NULL;
|
||||
ECORE_MAGIC_SET(ie, ECORE_MAGIC_IDLE_ENTERER);
|
||||
ie->func = func;
|
||||
ie->data = (void *)data;
|
||||
idle_enterers = _ecore_list2_prepend(idle_enterers, ie);
|
||||
return ie;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an idle enterer callback.
|
||||
* @param idle_enterer The idle enterer to delete
|
||||
|
|
|
@ -0,0 +1,352 @@
|
|||
#include "ecore_private.h"
|
||||
#include "Ecore.h"
|
||||
|
||||
static Ecore_Timer *timer = NULL;
|
||||
static int min_interval = -1;
|
||||
static int interval_incr = 0;
|
||||
static int at_tick = 0;
|
||||
static int just_added_poller = 0;
|
||||
static int poller_delete_count = 0;
|
||||
static int poller_walking = 0;
|
||||
static double poll_interval = 0.125;
|
||||
static double poll_cur_interval = 0.0;
|
||||
static double last_tick = 0.0;
|
||||
static Ecore_Poller *pollers[16] =
|
||||
{
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
|
||||
NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL
|
||||
};
|
||||
static unsigned short poller_counters[16] =
|
||||
{
|
||||
0,0,0,0,0,0,0,0,
|
||||
0,0,0,0,0,0,0,0
|
||||
};
|
||||
|
||||
static void _ecore_poller_next_tick_eval(void);
|
||||
static int _ecore_poller_cb_timer(void *data);
|
||||
|
||||
static void
|
||||
_ecore_poller_next_tick_eval(void)
|
||||
{
|
||||
int i;
|
||||
double interval;
|
||||
|
||||
min_interval = -1;
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
if (pollers[i])
|
||||
{
|
||||
min_interval = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (min_interval < 0)
|
||||
{
|
||||
/* no pollers */
|
||||
if (timer)
|
||||
{
|
||||
ecore_timer_del(timer);
|
||||
timer = NULL;
|
||||
}
|
||||
return;
|
||||
}
|
||||
interval_incr = (1 << min_interval);
|
||||
interval = interval_incr * poll_interval;
|
||||
/* we are at the tick callback - so no need to do inter-tick adjustments
|
||||
* so we can fasttrack this as t -= last_tick in theory is 0.0 (though
|
||||
* in practice it will be a very very very small value. also the tick
|
||||
* callback will adjust the timer interval at the end anyway */
|
||||
if (at_tick)
|
||||
{
|
||||
if (!timer)
|
||||
timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
double t;
|
||||
|
||||
if (!timer)
|
||||
timer = ecore_timer_add(interval, _ecore_poller_cb_timer, NULL);
|
||||
else
|
||||
{
|
||||
t = ecore_time_get();
|
||||
if (interval != poll_cur_interval)
|
||||
{
|
||||
t -= last_tick; /* time since we last ticked */
|
||||
/* delete the timer and reset it to tick off in the new
|
||||
* time interval. at the tick this will be adjusted */
|
||||
ecore_timer_del(timer);
|
||||
timer = ecore_timer_add(interval - t,
|
||||
_ecore_poller_cb_timer, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
poll_cur_interval = interval;
|
||||
}
|
||||
|
||||
static int
|
||||
_ecore_poller_cb_timer(void *data)
|
||||
{
|
||||
int i;
|
||||
Ecore_List2 *l;
|
||||
Ecore_Poller *poller;
|
||||
int changes = 0;
|
||||
|
||||
at_tick++;
|
||||
last_tick = ecore_time_get();
|
||||
/* we have 16 counters - each incriments every time the poller counter
|
||||
* "ticks". it incriments by the minimum interval (which can be 1, 2, 4,
|
||||
* 7, 16 etc. up to 32768) */
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
poller_counters[i] += interval_incr;
|
||||
/* wrap back to 0 if we exceed out loop count for the counter */
|
||||
if (poller_counters[i] >= (1 << i)) poller_counters[i] = 0;
|
||||
}
|
||||
|
||||
just_added_poller = 0;
|
||||
/* walk the pollers now */
|
||||
poller_walking++;
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
/* if the counter is @ 0 - this means that counter "went off" this
|
||||
* tick interval, so run all pollers hooked to that counter */
|
||||
if (poller_counters[i] == 0)
|
||||
{
|
||||
for (l = (Ecore_List2 *)pollers[i]; l; l = l->next)
|
||||
{
|
||||
poller = (Ecore_Poller *)l;
|
||||
if (!poller->delete_me)
|
||||
{
|
||||
if (!poller->func(poller->data))
|
||||
{
|
||||
if (!poller->delete_me)
|
||||
{
|
||||
poller->delete_me = 1;
|
||||
poller_delete_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
poller_walking--;
|
||||
|
||||
/* handle deletes afterwards */
|
||||
if (poller_delete_count > 0)
|
||||
{
|
||||
/* FIXME: walk all pollers and remove deleted ones */
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
for (l = (Ecore_List2 *)pollers[i]; l;)
|
||||
{
|
||||
poller = (Ecore_Poller *)l;
|
||||
l = l->next;
|
||||
if (poller->delete_me)
|
||||
{
|
||||
pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
|
||||
free(poller);
|
||||
poller_delete_count--;
|
||||
changes++;
|
||||
if (poller_delete_count <= 0) break;
|
||||
}
|
||||
}
|
||||
if (poller_delete_count <= 0) break;
|
||||
}
|
||||
}
|
||||
/* if we deleted or added any pollers, then we need to re-evaluate our
|
||||
* minimum poll interval */
|
||||
if ((changes > 0) || (just_added_poller > 0))
|
||||
_ecore_poller_next_tick_eval();
|
||||
|
||||
just_added_poller = 0;
|
||||
poller_delete_count = 0;
|
||||
|
||||
at_tick--;
|
||||
|
||||
/* if the timer was deleted then there is no point returning 1 - ambiguous
|
||||
* if we do as it im plies "keep running me" but we have been deleted
|
||||
* anyway */
|
||||
if (!timer) return 0;
|
||||
|
||||
/* adjust interval */
|
||||
ecore_timer_interval_set(timer, poll_cur_interval);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @defgroup Ecore_Poll_Group Ecore Poll Functions
|
||||
*
|
||||
* These functions are for the need to poll information, but provide a shared
|
||||
* abstracted API to pool such polling to minimise wakeup and ensure all the
|
||||
* polling happens in as few spots as possible areound a core poll interval.
|
||||
* For now only 1 core poller type is supprted: ECORE_POLLER_CORE
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Sets the time between ticks (in seconds) for the given ticker clock.
|
||||
* @param type The ticker type to adjust
|
||||
* @param poll_time The time (in seconds) between ticks of the clock
|
||||
* @ingroup Ecore_Poller_Group
|
||||
*
|
||||
* This will adjust the time between ticks of the given ticker type defined
|
||||
* by @p type to the time period defined by @p poll_time.
|
||||
*/
|
||||
EAPI void
|
||||
ecore_poller_poll_interval_set(Ecore_Poller_Type type, double poll_time)
|
||||
{
|
||||
poll_interval = poll_time;
|
||||
_ecore_poller_next_tick_eval();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the time between ticks (in seconds) for the fiven ticker clock.
|
||||
* @param type The ticker type to query
|
||||
* @return The time in seconds between ticks of the ticker clock
|
||||
* @ingroup Ecore_Poller_Group
|
||||
*
|
||||
* This will get the time between ticks of the specifider ticker clock.
|
||||
*/
|
||||
EAPI double
|
||||
ecore_poller_poll_interval_get(Ecore_Poller_Type type)
|
||||
{
|
||||
return poll_interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a poller to call the given function at a particular tick interval.
|
||||
* @param type The ticker type to attach the poller to
|
||||
* @param interval The poll interval
|
||||
* @param func The given function. If @p func returns 1, the poller is
|
||||
* rescheduled for the next tick interval.
|
||||
* @param data Data to pass to @p func when it is called.
|
||||
* @return A poller object on success. @c NULL on failure.
|
||||
* @ingroup Ecore_Poller_Group
|
||||
*
|
||||
* This function adds a poller callback that is to be called regularly
|
||||
* along with all other poller callbacks so the pollers are synchronized with
|
||||
* all other pollers running off the same poller type and at the same tick
|
||||
* interval. This should be used for polling things when polling is desired
|
||||
* or required, and you do not have specific requirements on the exact times
|
||||
* to poll and want to avoid extra process wakeups for polling. This will
|
||||
* save power as the CPU has more of a chance to go into a low power state
|
||||
* the longer it is asleep for, so this should be used if you are at all
|
||||
* power conscious.
|
||||
*
|
||||
* The @p type parameter defines the poller tick type (there is a virtual
|
||||
* clock ticking all the time - though ecore avoids making it tick when
|
||||
* there will not be any work to do at that tick point). There is only one
|
||||
* ticker at the moment - that is ECORE_POLLER_CORE. This is here for future
|
||||
* expansion if multiple clocks with different frequencies are really required.
|
||||
* The default time between ticks for the ECORE_POLLER_CORE ticker is 0.125
|
||||
* seconds.
|
||||
*
|
||||
* The @p interval is the number of ticker ticks that will pass by in between
|
||||
* invocations of the @p func callback. This must be between 1 and 32768
|
||||
* inclusive, and must be a power of 2 (i.e. 1, 2, 4, 8, 16, ... 16384, 32768).
|
||||
* If it is 1, then the function will be called every tick. if it is 2, then it
|
||||
* will be called every 2nd tick, if it is 8, then every 8th tick etc. Exactly
|
||||
* which tick is undefined, as only the interval between calls can be defined.
|
||||
* Ecore will endeavour to keep pollers synchronised and to call as many in
|
||||
* 1 wakeup event as possible.
|
||||
*
|
||||
* This function adds a poller and returns its handle on success and NULL on
|
||||
* failure. The function @p func will be called at tick intervals described
|
||||
* above. The function will be passed the @p data pointer as its parameter.
|
||||
*
|
||||
* When the poller @p func is called, it must return a value of either 1 or 0.
|
||||
* If it returns 1, it will be called again at the next tick, or if it returns
|
||||
* 0 it will be deleted automatically making any references/handles for it
|
||||
* invalid.
|
||||
*/
|
||||
EAPI Ecore_Poller *
|
||||
ecore_poller_add(Ecore_Poller_Type type, int interval, int (*func) (void *data), const void *data)
|
||||
{
|
||||
Ecore_Poller *poller;
|
||||
int ibit;
|
||||
|
||||
if (!func) return NULL;
|
||||
if (interval < 1) interval = 1;
|
||||
|
||||
poller = calloc(1, sizeof(Ecore_Poller));
|
||||
if (!poller) return NULL;
|
||||
ECORE_MAGIC_SET(poller, ECORE_MAGIC_POLLER);
|
||||
/* interval MUST be a power of 2, so enforce it */
|
||||
if (interval < 1) interval = 1;
|
||||
ibit = -1;
|
||||
while (interval != 0)
|
||||
{
|
||||
ibit++;
|
||||
interval >>= 1;
|
||||
}
|
||||
/* only allow up to 32768 - i.e. ibit == 15, so limit it */
|
||||
if (ibit > 15) ibit = 15;
|
||||
|
||||
poller->ibit = ibit;
|
||||
poller->func = func;
|
||||
poller->data = (void *)data;
|
||||
pollers[poller->ibit] = _ecore_list2_prepend(pollers[poller->ibit], poller);
|
||||
if (poller_walking)
|
||||
just_added_poller++;
|
||||
else
|
||||
_ecore_poller_next_tick_eval();
|
||||
return poller;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the specified poller from the timer list.
|
||||
* @param poller The poller to delete.
|
||||
* @return The data pointer set for the timer when @ref ecore_poller_add was
|
||||
* called. @c NULL is returned if the function is unsuccessful.
|
||||
* @ingroup Ecore_Poller_Group
|
||||
*
|
||||
* Note: @p poller must be a valid handle. If the poller function has already
|
||||
* returned 0, the handle is no longer valid (and does not need to be delete).
|
||||
*/
|
||||
EAPI void *
|
||||
ecore_poller_del(Ecore_Poller *poller)
|
||||
{
|
||||
void *data;
|
||||
|
||||
if (!ECORE_MAGIC_CHECK(poller, ECORE_MAGIC_POLLER))
|
||||
{
|
||||
ECORE_MAGIC_FAIL(poller, ECORE_MAGIC_POLLER,
|
||||
"ecore_poller_del");
|
||||
return NULL;
|
||||
}
|
||||
/* we are walking the poller list - a bad idea to remove from it while
|
||||
* walking it, so just flag it as delete_me and come back to it after
|
||||
* the loop has finished */
|
||||
if (poller_walking > 0)
|
||||
{
|
||||
poller_delete_count++;
|
||||
poller->delete_me = 1;
|
||||
return poller->data;
|
||||
}
|
||||
/* not in loop so safe - delete immediately */
|
||||
data = poller->data;
|
||||
pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
|
||||
free(poller);
|
||||
_ecore_poller_next_tick_eval();
|
||||
return data;
|
||||
}
|
||||
|
||||
void
|
||||
_ecore_poller_shutdown(void)
|
||||
{
|
||||
int i;
|
||||
Ecore_List2 *l;
|
||||
Ecore_Poller *poller;
|
||||
|
||||
for (i = 0; i < 15; i++)
|
||||
{
|
||||
for (l = (Ecore_List2 *)pollers[i]; l;)
|
||||
{
|
||||
poller = (Ecore_Poller *)l;
|
||||
l = l->next;
|
||||
pollers[poller->ibit] = _ecore_list2_remove(pollers[poller->ibit], poller);
|
||||
free(poller);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -88,6 +88,7 @@
|
|||
#define ECORE_MAGIC_EVENT_FILTER 0xf78218ff
|
||||
#define ECORE_MAGIC_EVENT 0xf77119fe
|
||||
#define ECORE_MAGIC_ANIMATOR 0xf7643ea5
|
||||
#define ECORE_MAGIC_POLLER 0xf7568127
|
||||
|
||||
#define ECORE_MAGIC Ecore_Magic __magic
|
||||
|
||||
|
@ -221,6 +222,11 @@ enum _Ecore_Exe_Flags
|
|||
*/
|
||||
};
|
||||
typedef enum _Ecore_Exe_Flags Ecore_Exe_Flags;
|
||||
enum _Ecore_Poller_Type
|
||||
{
|
||||
ECORE_POLLER_CORE = 0
|
||||
};
|
||||
typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
|
||||
|
||||
#ifndef _WIN32
|
||||
typedef struct _Ecore_Exe Ecore_Exe;
|
||||
|
@ -234,6 +240,7 @@ typedef struct _Ecore_Event_Handler Ecore_Event_Handler;
|
|||
typedef struct _Ecore_Event_Filter Ecore_Event_Filter;
|
||||
typedef struct _Ecore_Event Ecore_Event;
|
||||
typedef struct _Ecore_Animator Ecore_Animator;
|
||||
typedef struct _Ecore_Poller Ecore_Poller;
|
||||
|
||||
#ifndef _WIN32
|
||||
struct _Ecore_Exe
|
||||
|
@ -371,6 +378,16 @@ struct _Ecore_Animator
|
|||
void *data;
|
||||
};
|
||||
|
||||
struct _Ecore_Poller
|
||||
{
|
||||
Ecore_List2 __list_data;
|
||||
ECORE_MAGIC;
|
||||
int ibit;
|
||||
signed char delete_me : 1;
|
||||
int (*func) (void *data);
|
||||
void *data;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
EAPI void _ecore_magic_fail(void *d, Ecore_Magic m, Ecore_Magic req_m, const char *fname);
|
||||
|
@ -422,7 +439,8 @@ void _ecore_exe_event_del_free(void *data, void *ev);
|
|||
|
||||
void _ecore_animator_shutdown(void);
|
||||
|
||||
|
||||
void _ecore_poller_shutdown(void);
|
||||
|
||||
EAPI void *_ecore_list2_append (void *in_list, void *in_item);
|
||||
EAPI void *_ecore_list2_prepend (void *in_list, void *in_item);
|
||||
EAPI void *_ecore_list2_append_relative (void *in_list, void *in_item, void *in_relative);
|
||||
|
|
|
@ -153,10 +153,15 @@ _ecore_timer_next_get(void)
|
|||
{
|
||||
double now;
|
||||
double in;
|
||||
Ecore_Timer *timer;
|
||||
|
||||
if (!timers) return -1;
|
||||
now = ecore_time_get();
|
||||
in = timers->at - now;
|
||||
timer = (Ecore_Timer *)timers;
|
||||
while ((timer) && ((timer->delete_me) || (timer->just_added)))
|
||||
timer = (Ecore_Timer *)((Ecore_List2 *)timer)->next;
|
||||
if (!timer) return -1;
|
||||
in = timer->at - now;
|
||||
if (in < 0) in = 0;
|
||||
return in;
|
||||
}
|
||||
|
@ -166,7 +171,7 @@ _ecore_timer_call(double when)
|
|||
{
|
||||
Ecore_List2 *l;
|
||||
Ecore_Timer *timer;
|
||||
|
||||
|
||||
if (!timers) return 0;
|
||||
if (last_check > when)
|
||||
{
|
||||
|
@ -189,13 +194,18 @@ _ecore_timer_call(double when)
|
|||
_ecore_timer_call(when);
|
||||
if ((!timer->delete_me) && (timer->func(timer->data)))
|
||||
{
|
||||
/* if the timer would have gone off more than 30 seconds ago,
|
||||
/* if the timer would have gone off more than 15 seconds ago,
|
||||
* assume that the system hung and set the timer to go off
|
||||
* timer->in from now.
|
||||
* timer->in from now. this handles system hangs, suspends
|
||||
* and more, so ecore will only "replay" the timers while
|
||||
* the system is suspended if it is suspended for less than
|
||||
* 15 seconds (basically). this also handles if the process
|
||||
* is stopped in a debugger or IO and other handling gets
|
||||
* really slow within the main loop.
|
||||
*/
|
||||
if (!timer->delete_me)
|
||||
{
|
||||
if ((timer->at + timer->in) < (when - 30.0))
|
||||
if ((timer->at + timer->in) < (when - 15.0))
|
||||
_ecore_timer_set(timer, when + timer->in, timer->in, timer->func, timer->data);
|
||||
else
|
||||
_ecore_timer_set(timer, timer->at + timer->in, timer->in, timer->func, timer->data);
|
||||
|
|
|
@ -26,8 +26,8 @@
|
|||
*
|
||||
* * Need more buffer overflow checks.
|
||||
*/
|
||||
#include "Ecore.h"
|
||||
#include "ecore_private.h"
|
||||
#include "Ecore.h"
|
||||
#include "ecore_con_private.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
|
|
@ -120,7 +120,6 @@ _ecore_evas_buffer_render(Ecore_Evas *ee)
|
|||
if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
|
||||
_ecore_evas_buffer_render(ee2);
|
||||
if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
|
||||
_ecore_evas_idle_timeout_update(ee2);
|
||||
}
|
||||
if (ee->engine.buffer.image)
|
||||
{
|
||||
|
@ -143,7 +142,11 @@ _ecore_evas_buffer_render(Ecore_Evas *ee)
|
|||
r->x, r->y, r->w, r->h);
|
||||
}
|
||||
}
|
||||
if (updates) evas_render_updates_free(updates);
|
||||
if (updates)
|
||||
{
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -32,7 +32,6 @@ _ecore_evas_directfb_render(Ecore_Evas *ee)
|
|||
if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
|
||||
_ecore_evas_buffer_render(ee2);
|
||||
if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
|
||||
_ecore_evas_idle_timeout_update(ee2);
|
||||
}
|
||||
#endif
|
||||
if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
|
||||
|
@ -56,9 +55,9 @@ _ecore_evas_directfb_render(Ecore_Evas *ee)
|
|||
surface->Flip(surface, ®ion,DSFLIP_BLIT);
|
||||
}
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
@ -211,6 +211,8 @@ _ecore_evas_idle_enter(void *data __UNUSED__)
|
|||
ee = (Ecore_Evas *)l;
|
||||
if (ee->visible)
|
||||
{
|
||||
Evas_List *updates;
|
||||
|
||||
#ifdef BUILD_ECORE_EVAS_BUFFER
|
||||
Evas_List *ll;
|
||||
#endif
|
||||
|
@ -227,12 +229,16 @@ _ecore_evas_idle_enter(void *data __UNUSED__)
|
|||
if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
|
||||
}
|
||||
#endif
|
||||
evas_render(ee->evas);
|
||||
updates = evas_render_updates(ee->evas);
|
||||
if (updates)
|
||||
{
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
|
||||
}
|
||||
else
|
||||
evas_norender(ee->evas);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
if (_ecore_evas_fps_debug)
|
||||
{
|
||||
|
|
|
@ -231,10 +231,16 @@ _ecore_evas_idle_enter(void *data __UNUSED__)
|
|||
ee = (Ecore_Evas *)l;
|
||||
if (ee->visible)
|
||||
{
|
||||
Evas_List *updates;
|
||||
|
||||
if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
|
||||
|
||||
evas_render(ee->evas);
|
||||
|
||||
updates = evas_render_updates(ee->evas);
|
||||
if (updates)
|
||||
{
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -149,7 +149,6 @@ _ecore_evas_x_render(Ecore_Evas *ee)
|
|||
if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2);
|
||||
_ecore_evas_buffer_render(ee2);
|
||||
if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2);
|
||||
_ecore_evas_idle_timeout_update(ee2);
|
||||
}
|
||||
#endif
|
||||
if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee);
|
||||
|
@ -184,8 +183,14 @@ _ecore_evas_x_render(Ecore_Evas *ee)
|
|||
}
|
||||
if ((ee->shaped) && (updates))
|
||||
ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask);
|
||||
if ((ee->alpha) && (updates))
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, ee->engine.x.mask);
|
||||
}
|
||||
if (updates)
|
||||
{
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
if (updates) evas_render_updates_free(updates);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -291,7 +296,11 @@ _ecore_evas_x_render(Ecore_Evas *ee)
|
|||
ee->engine.x.damages = 0;
|
||||
}
|
||||
#endif /* HAVE_ECORE_X_XCB */
|
||||
if (updates) evas_render_updates_free(updates);
|
||||
if (updates)
|
||||
{
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (((ee->visible) && (ee->draw_ok)) ||
|
||||
|
@ -307,6 +316,7 @@ _ecore_evas_x_render(Ecore_Evas *ee)
|
|||
{
|
||||
ecore_x_window_shape_mask_set(ee->engine.x.win, ee->engine.x.mask);
|
||||
evas_render_updates_free(updates);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -334,13 +344,15 @@ _ecore_evas_x_render(Ecore_Evas *ee)
|
|||
}
|
||||
#endif
|
||||
evas_render_updates_free(updates);
|
||||
if (ee->alpha)
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, ee->engine.x.mask);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
evas_norender(ee->evas);
|
||||
if (ee->func.fn_post_render) ee->func.fn_post_render(ee);
|
||||
_ecore_evas_idle_timeout_update(ee);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -459,7 +471,6 @@ _ecore_evas_x_resize_shape(Ecore_Evas *ee)
|
|||
einfo->info.mask = ee->engine.x.mask;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
|
||||
|
||||
}
|
||||
#endif /* BUILD_ECORE_EVAS_X11 */
|
||||
}
|
||||
|
@ -1060,7 +1071,7 @@ _ecore_evas_x_event_window_configure(void *data __UNUSED__, int type __UNUSED__,
|
|||
ecore_evas_avoid_damage_set(ee, 0);
|
||||
ecore_evas_avoid_damage_set(ee, pdam);
|
||||
}
|
||||
if (ee->shaped)
|
||||
if ((ee->shaped) || (ee->alpha))
|
||||
_ecore_evas_x_resize_shape(ee);
|
||||
if ((ee->expecting_resize.w > 0) &&
|
||||
(ee->expecting_resize.h > 0))
|
||||
|
@ -1475,10 +1486,8 @@ _ecore_evas_x_resize(Ecore_Evas *ee, int w, int h)
|
|||
ecore_evas_avoid_damage_set(ee, 0);
|
||||
ecore_evas_avoid_damage_set(ee, pdam);
|
||||
}
|
||||
if (ee->shaped)
|
||||
{
|
||||
_ecore_evas_x_resize_shape(ee);
|
||||
}
|
||||
if ((ee->shaped) || (ee->alpha))
|
||||
_ecore_evas_x_resize_shape(ee);
|
||||
if (ee->func.fn_resize) ee->func.fn_resize(ee);
|
||||
}
|
||||
}
|
||||
|
@ -1526,10 +1535,8 @@ _ecore_evas_x_move_resize(Ecore_Evas *ee, int x, int y, int w, int h)
|
|||
ecore_evas_avoid_damage_set(ee, 0);
|
||||
ecore_evas_avoid_damage_set(ee, pdam);
|
||||
}
|
||||
if (ee->shaped)
|
||||
{
|
||||
_ecore_evas_x_resize_shape(ee);
|
||||
}
|
||||
if ((ee->shaped) || (ee->alpha))
|
||||
_ecore_evas_x_resize_shape(ee);
|
||||
if (change_pos)
|
||||
{
|
||||
if (ee->func.fn_move) ee->func.fn_move(ee);
|
||||
|
@ -1685,7 +1692,8 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
XGCValues gcv;
|
||||
#endif /* HAVE_ECORE_X_XCB */
|
||||
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
if (!ee->engine.x.mask)
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
# ifdef HAVE_ECORE_X_XCB
|
||||
gc = xcb_generate_id(ecore_x_connection_get());
|
||||
value_list = 0;
|
||||
|
@ -1713,6 +1721,7 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
einfo->info.mask = ee->engine.x.mask;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1721,6 +1730,7 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
einfo->info.mask = 0;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
ecore_x_window_shape_mask_set(ee->engine.x.win, 0);
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
}
|
||||
#endif /* BUILD_ECORE_EVAS_X11 */
|
||||
|
@ -1753,7 +1763,8 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
XGCValues gcv;
|
||||
# endif /* HAVE_ECORE_X_XCB */
|
||||
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
if (!ee->engine.x.mask)
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
# ifdef HAVE_ECORE_X_XCB
|
||||
gc = xcb_generate_id(ecore_x_connection_get());
|
||||
value_list = 0;
|
||||
|
@ -1781,6 +1792,7 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
einfo->info.mask = ee->engine.x.mask;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1789,6 +1801,7 @@ _ecore_evas_x_shaped_set(Ecore_Evas *ee, int shaped)
|
|||
einfo->info.mask = 0;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
ecore_x_window_shape_mask_set(ee->engine.x.win, 0);
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -1844,7 +1857,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
if (((ee->alpha) && (alpha)) || ((!ee->alpha) && (!alpha)))
|
||||
return;
|
||||
|
||||
if (!strcmp(ee->driver, "software_x11") || !strcmp(ee->driver, "software_xcb"))
|
||||
if (!strcmp(ee->driver, "software_x11"))
|
||||
{
|
||||
#ifdef BUILD_ECORE_EVAS_X11
|
||||
# ifdef HAVE_ECORE_X_XCB
|
||||
|
@ -1871,6 +1884,8 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (!ee->engine.x.mask)
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1878,6 +1893,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
|
||||
einfo->info.destination_alpha = alpha;
|
||||
|
@ -1900,9 +1918,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
einfo->info.depth = att.depth;
|
||||
# endif /* HAVE_ECORE_X_XCB */
|
||||
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
einfo->info.mask = 0;
|
||||
// if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
// ee->engine.x.mask = 0;
|
||||
einfo->info.mask = ee->engine.x.mask;
|
||||
einfo->info.drawable = ee->engine.x.win;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
|
||||
|
@ -1914,7 +1932,7 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
if (ee->prop.focused) ecore_x_window_focus(ee->engine.x.win);
|
||||
#endif /* BUILD_ECORE_EVAS_X11 */
|
||||
}
|
||||
else if (!strcmp(ee->driver, "xrender_x11") || !strcmp(ee->driver, "xrender_xcb"))
|
||||
else if (!strcmp(ee->driver, "xrender_x11"))
|
||||
{
|
||||
#ifdef BUILD_ECORE_EVAS_XRENDER
|
||||
# ifdef HAVE_ECORE_X_XCB
|
||||
|
@ -1940,6 +1958,8 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (!ee->engine.x.mask)
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1947,6 +1967,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
|
||||
einfo->info.destination_alpha = alpha;
|
||||
|
@ -1962,9 +1985,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
einfo->info.visual = att.visual;
|
||||
# endif /* HAVE_ECORE_X_XCB */
|
||||
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
einfo->info.mask = 0;
|
||||
// if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
// ee->engine.x.mask = 0;
|
||||
einfo->info.mask = ee->engine.x.mask;
|
||||
einfo->info.drawable = ee->engine.x.win;
|
||||
evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo);
|
||||
evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h);
|
||||
|
@ -1994,6 +2017,8 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_argb_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (!ee->engine.x.mask)
|
||||
ee->engine.x.mask = ecore_x_pixmap_new(ee->engine.x.win, ee->w, ee->h, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2001,6 +2026,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
ee->engine.x.win = ecore_x_window_override_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
else
|
||||
ee->engine.x.win = ecore_x_window_new(ee->engine.x.win_root, ee->x, ee->y, ee->w, ee->h);
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
ecore_x_window_shape_input_mask_set(ee->engine.x.win, 0);
|
||||
}
|
||||
|
||||
#if 0 /* XXX no alpha window support for software_16_x11 */
|
||||
|
@ -2008,9 +2036,9 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
|
|||
#endif /* XXX no alpha window support for software_16_x11 */
|
||||
|
||||
#if 0 /* XXX no shaped window support for software_16_x11 */
|
||||
if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
ee->engine.x.mask = 0;
|
||||
einfo->info.mask = 0;
|
||||
// if (ee->engine.x.mask) ecore_x_pixmap_del(ee->engine.x.mask);
|
||||
// ee->engine.x.mask = 0;
|
||||
einfo->info.mask = ee->engine.x.mask;
|
||||
#endif /* XXX no shaped window support for software_16_x11 */
|
||||
|
||||
einfo->info.drawable = ee->engine.x.win;
|
||||
|
|
|
@ -1216,6 +1216,7 @@ EAPI void ecore_x_window_shape_rectangles_get_prefetch(Ecore_X_Win
|
|||
EAPI void ecore_x_window_shape_rectangles_get_fetch(void);
|
||||
EAPI Ecore_X_Rectangle *ecore_x_window_shape_rectangles_get(Ecore_X_Window win, int *num_ret);
|
||||
EAPI void ecore_x_window_shape_events_select(Ecore_X_Window win, int on);
|
||||
EAPI void ecore_x_window_shape_input_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask);
|
||||
|
||||
EAPI Ecore_X_Pixmap ecore_x_pixmap_new(Ecore_X_Window win, int w, int h, int dep);
|
||||
EAPI void ecore_x_pixmap_del(Ecore_X_Pixmap pmap);
|
||||
|
|
|
@ -169,3 +169,21 @@ ecore_x_window_shape_events_select(Ecore_X_Window win, int on)
|
|||
else
|
||||
XShapeSelectInput(_ecore_x_disp, win, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the input shape of the given window to that given by the pixmap @p mask.
|
||||
* @param win The given window.
|
||||
* @param mask A 2-bit depth pixmap that provides the new input shape of the
|
||||
* window.
|
||||
* @ingroup Ecore_X_Window_Shape
|
||||
*/
|
||||
EAPI void
|
||||
ecore_x_window_shape_input_mask_set(Ecore_X_Window win, Ecore_X_Pixmap mask)
|
||||
{
|
||||
#ifdef ShapeInput
|
||||
XShapeCombineMask(_ecore_x_disp, win, ShapeInput, 0, 0, mask, ShapeSet);
|
||||
#else
|
||||
XShapeCombineMask(_ecore_x_disp, win, ShapeBounding, 0, 0, mask, ShapeSet);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -1313,7 +1313,6 @@ efreet_desktop_command_build(Efreet_Desktop_Command *command)
|
|||
Ecore_List *execs;
|
||||
char *exec;
|
||||
|
||||
printf("efreet_desktop_command_build()\n");
|
||||
execs = ecore_list_new();
|
||||
|
||||
ecore_list_first_goto(command->files);
|
||||
|
|
|
@ -165,6 +165,9 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
{
|
||||
cache->lru = evas_object_list_remove(cache->lru, im);
|
||||
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
||||
// printf("IMG %p %ix%i %s SUB %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
cache->usage -= cache->func.mem_size_get(im);
|
||||
if (im->cache_key)
|
||||
{
|
||||
|
@ -192,6 +195,9 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
cache->lru = evas_object_list_remove(cache->lru, im);
|
||||
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
||||
cache->activ = evas_hash_direct_add(cache->activ, im->cache_key, im);
|
||||
// printf("IMG %p %ix%i %s SUB %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
cache->usage -= cache->func.mem_size_get(im);
|
||||
goto on_ok;
|
||||
}
|
||||
|
@ -199,6 +205,9 @@ evas_cache_image_request(Evas_Cache_Image *cache, const char *file, const char *
|
|||
{
|
||||
cache->lru = evas_object_list_remove(cache->lru, im);
|
||||
cache->inactiv = evas_hash_del(cache->inactiv, im->cache_key, im);
|
||||
// printf("IMG %p %ix%i %s SUB %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
cache->usage -= cache->func.mem_size_get(im);
|
||||
if (im->cache_key)
|
||||
{
|
||||
|
@ -261,7 +270,11 @@ evas_cache_image_drop(RGBA_Image *im)
|
|||
// if (im->cache_key) printf("DROP %s -> ref = %i\n", im->cache_key, im->references);
|
||||
if ((im->flags & RGBA_IMAGE_IS_DIRTY) == RGBA_IMAGE_IS_DIRTY)
|
||||
{
|
||||
cache->usage -= cache->func.mem_size_get(im);
|
||||
// printf("IMG %p %ix%i %s SUB %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
//// don't decrement cache usage - unless we remove from the lru
|
||||
// cache->usage -= cache->func.mem_size_get(im);
|
||||
// if (im->cache_key) printf("IM-- %s, cache = %i\n", im->cache_key, cache->usage);
|
||||
cache->dirty = evas_object_list_remove(cache->dirty, im);
|
||||
if (cache->func.debug)
|
||||
|
@ -279,6 +292,9 @@ evas_cache_image_drop(RGBA_Image *im)
|
|||
cache->inactiv = evas_hash_direct_add(cache->inactiv, im->cache_key, im);
|
||||
cache->lru = evas_object_list_prepend(cache->lru, im);
|
||||
|
||||
// printf("IMG %p %ix%i %s ADD %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
cache->usage += cache->func.mem_size_get(im);
|
||||
// printf("FLUSH!\n");
|
||||
evas_cache_image_flush(cache);
|
||||
|
@ -562,6 +578,7 @@ evas_cache_image_flush(Evas_Cache_Image *cache)
|
|||
{
|
||||
assert(cache);
|
||||
|
||||
// printf("cache->limit = %i (used = %i)\n", cache->limit, cache->usage);
|
||||
if (cache->limit == -1)
|
||||
return -1;
|
||||
|
||||
|
@ -572,6 +589,9 @@ evas_cache_image_flush(Evas_Cache_Image *cache)
|
|||
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);
|
||||
// printf("IMG %p %ix%i %s SUB %i\n",
|
||||
// im, im->image->w, im->image->h, im->cache_key,
|
||||
// cache->func.mem_size_get(im));
|
||||
cache->usage -= cache->func.mem_size_get(im);
|
||||
|
||||
if (im->cache_key)
|
||||
|
@ -579,6 +599,7 @@ evas_cache_image_flush(Evas_Cache_Image *cache)
|
|||
evas_stringshare_del(im->cache_key);
|
||||
im->cache_key = NULL;
|
||||
}
|
||||
// printf("DEL IMG FROM CACHE\n");
|
||||
cache->func.destructor(im);
|
||||
evas_common_image_delete(im);
|
||||
}
|
||||
|
|
|
@ -216,6 +216,7 @@ evas_debug_magic_string_get(DATA32 magic)
|
|||
|
||||
|
||||
|
||||
//#define NOPOOL
|
||||
|
||||
typedef struct _Pool Pool;
|
||||
|
||||
|
@ -228,6 +229,12 @@ struct _Pool
|
|||
|
||||
Pool *
|
||||
_evas_mp_pool_new(Evas_Mempool *pool)
|
||||
#ifdef NOPOOL
|
||||
{
|
||||
static Pool thepool;
|
||||
return &thepool;
|
||||
}
|
||||
#else
|
||||
{
|
||||
Pool *p;
|
||||
void **ptr;
|
||||
|
@ -246,14 +253,19 @@ _evas_mp_pool_new(Evas_Mempool *pool)
|
|||
*ptr = NULL;
|
||||
return p;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
_evas_mp_pool_free(Pool *p)
|
||||
#ifdef NOPOOL
|
||||
{
|
||||
}
|
||||
#else
|
||||
{
|
||||
free(p);
|
||||
}
|
||||
#endif
|
||||
|
||||
//#define NOPOOL
|
||||
void *
|
||||
evas_mempool_malloc(Evas_Mempool *pool, int size)
|
||||
#ifdef NOPOOL
|
||||
|
@ -364,6 +376,11 @@ evas_mempool_free(Evas_Mempool *pool, void *ptr)
|
|||
|
||||
void *
|
||||
evas_mempool_calloc(Evas_Mempool *pool, int size)
|
||||
#ifdef NOPOOL
|
||||
{
|
||||
return calloc(1, size);
|
||||
}
|
||||
#else
|
||||
{
|
||||
void *mem;
|
||||
|
||||
|
@ -371,3 +388,4 @@ evas_mempool_calloc(Evas_Mempool *pool, int size)
|
|||
memset(mem, 0, size);
|
||||
return mem;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -58,6 +58,8 @@ struct _Outbuf
|
|||
|
||||
/* a list of pending regions to write to the target */
|
||||
Evas_List *pending_writes;
|
||||
/* a list of previous frame pending regions to write to the target */
|
||||
Evas_List *prev_pending_writes;
|
||||
|
||||
unsigned char mask_dither : 1;
|
||||
unsigned char destination_alpha : 1;
|
||||
|
@ -77,7 +79,10 @@ struct _X_Output_Buffer
|
|||
Display *display;
|
||||
XImage *xim;
|
||||
XShmSegmentInfo *shm_info;
|
||||
Visual *visual;
|
||||
void *data;
|
||||
int w, h, bpl;
|
||||
int psize;
|
||||
};
|
||||
|
||||
/****/
|
||||
|
|
|
@ -4,6 +4,110 @@
|
|||
#include <sys/time.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
static Evas_List *shmpool = NULL;
|
||||
static int shmsize = 0;
|
||||
|
||||
static X_Output_Buffer *
|
||||
_find_xob(Display *d, Visual *v, int depth, int w, int h, int shm, void *data)
|
||||
{
|
||||
Evas_List *l, *xl;
|
||||
X_Output_Buffer *xob = NULL;
|
||||
int fitness = 0x7fffffff;
|
||||
int sz, lbytes, bpp;
|
||||
|
||||
// return evas_software_x11_x_output_buffer_new(d, v, depth, w, h, shm, data);
|
||||
if (!shm)
|
||||
return evas_software_x11_x_output_buffer_new(d, v, depth, w, h, shm, data);
|
||||
if (depth > 1)
|
||||
{
|
||||
bpp = depth / 8;
|
||||
if (bpp == 3) bpp = 4;
|
||||
lbytes = (((w * bpp) + 3) / 4) * 4;
|
||||
}
|
||||
else
|
||||
lbytes = ((w + 31) / 32) * 4;
|
||||
sz = lbytes * h;
|
||||
for (l = shmpool; l; l = l->next)
|
||||
{
|
||||
X_Output_Buffer *xob2;
|
||||
int szdif;
|
||||
|
||||
xob2 = l->data;
|
||||
if ((xob2->xim->depth != depth) || (xob2->visual != v) ||
|
||||
(xob2->display != d))
|
||||
continue;
|
||||
szdif = xob2->psize - sz;
|
||||
if (szdif < 0) continue;
|
||||
if (szdif == 0)
|
||||
{
|
||||
xob = xob2;
|
||||
xl = l;
|
||||
goto have_xob;
|
||||
}
|
||||
if (szdif < fitness)
|
||||
{
|
||||
fitness = szdif;
|
||||
xob = xob2;
|
||||
xl = l;
|
||||
}
|
||||
}
|
||||
if ((fitness > (100 * 100)) || (!xob))
|
||||
return evas_software_x11_x_output_buffer_new(d, v, depth, w, h, shm, data);
|
||||
|
||||
have_xob:
|
||||
shmpool = evas_list_remove_list(shmpool, xl);
|
||||
xob->w = w;
|
||||
xob->h = h;
|
||||
xob->bpl = lbytes;
|
||||
xob->xim->width = xob->w;
|
||||
xob->xim->height = xob->h;
|
||||
xob->xim->bytes_per_line = xob->bpl;
|
||||
shmsize -= xob->psize * (xob->xim->depth / 8);
|
||||
return xob;
|
||||
}
|
||||
|
||||
static void
|
||||
_unfind_xob(X_Output_Buffer *xob, int sync)
|
||||
{
|
||||
// evas_software_x11_x_output_buffer_free(xob, sync); return;
|
||||
if (xob->shm_info)
|
||||
{
|
||||
shmpool = evas_list_prepend(shmpool, xob);
|
||||
shmsize += xob->psize * xob->xim->depth / 8;
|
||||
while ((shmsize > (1024 * 4096)) ||
|
||||
(evas_list_count(shmpool) > 32))
|
||||
{
|
||||
Evas_List *xl;
|
||||
|
||||
xl = evas_list_last(shmpool);
|
||||
if (!xl)
|
||||
{
|
||||
shmsize = 0;
|
||||
break;
|
||||
}
|
||||
xob = xl->data;
|
||||
shmpool = evas_list_remove_list(shmpool, xl);
|
||||
evas_software_x11_x_output_buffer_free(xob, sync);
|
||||
}
|
||||
}
|
||||
else
|
||||
evas_software_x11_x_output_buffer_free(xob, sync);
|
||||
}
|
||||
|
||||
static void
|
||||
_clear_xob(int sync)
|
||||
{
|
||||
while (shmpool)
|
||||
{
|
||||
X_Output_Buffer *xob;
|
||||
|
||||
xob = shmpool->data;
|
||||
shmpool = evas_list_remove_list(shmpool, shmpool);
|
||||
evas_software_x11_x_output_buffer_free(xob, sync);
|
||||
}
|
||||
shmsize = 0;
|
||||
}
|
||||
|
||||
void
|
||||
evas_software_x11_outbuf_init(void)
|
||||
{
|
||||
|
@ -12,6 +116,19 @@ evas_software_x11_outbuf_init(void)
|
|||
void
|
||||
evas_software_x11_outbuf_free(Outbuf *buf)
|
||||
{
|
||||
while (buf->priv.pending_writes)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
Outbuf_Region *obr;
|
||||
|
||||
im = buf->priv.pending_writes->data;
|
||||
buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
|
||||
obr = im->extended_info;
|
||||
evas_cache_image_drop(im);
|
||||
if (obr->xob) _unfind_xob(obr->xob, 0);
|
||||
if (obr->mxob) _unfind_xob(obr->mxob, 0);
|
||||
free(obr);
|
||||
}
|
||||
evas_software_x11_outbuf_idle_flush(buf);
|
||||
evas_software_x11_outbuf_flush(buf);
|
||||
if (buf->priv.x.gc)
|
||||
|
@ -22,6 +139,7 @@ evas_software_x11_outbuf_free(Outbuf *buf)
|
|||
evas_software_x11_x_color_deallocate(buf->priv.x.disp, buf->priv.x.cmap,
|
||||
buf->priv.x.vis, buf->priv.pal);
|
||||
free(buf);
|
||||
_clear_xob(0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -190,7 +308,7 @@ evas_software_x11_outbuf_setup_x(int w, int h, int rot, Outbuf_Depth depth,
|
|||
" At depth %i:\n"
|
||||
" RGB format mask: %08x, %08x, %08x\n"
|
||||
" Palette mode: %i\n"
|
||||
" Not supported by and compiled in converters!\n"
|
||||
" Not supported by compiled in converters!\n"
|
||||
" }\n",
|
||||
buf->priv.x.depth,
|
||||
buf->priv.mask.r,
|
||||
|
@ -342,7 +460,8 @@ evas_software_x11_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w,
|
|||
/* FIXME: magic - i found if shm regions are smaller than 200x200 its
|
||||
* faster to use ximages over unix sockets - trial and error
|
||||
*/
|
||||
if ((w * h) < (200 * 200)) use_shm = 0;
|
||||
// use_shm = 0; /* 630 -> 1006 fps */
|
||||
// if ((w * h) < (200 * 200)) use_shm = 0; /* 630 -> 962 fps */
|
||||
|
||||
if ((buf->rot == 0) &&
|
||||
(buf->priv.mask.r == 0xff0000) &&
|
||||
|
@ -355,19 +474,34 @@ evas_software_x11_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w,
|
|||
im->image->data = NULL;
|
||||
im->image->no_free = 1;
|
||||
im->extended_info = obr;
|
||||
obr->xob = _find_xob(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
/*
|
||||
obr->xob = evas_software_x11_x_output_buffer_new(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
*/
|
||||
im->image->data = (DATA32 *) evas_software_x11_x_output_buffer_data(obr->xob, &bpl);
|
||||
if (buf->priv.x.mask)
|
||||
obr->mxob = _find_xob(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
1, w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
/*
|
||||
obr->mxob = evas_software_x11_x_output_buffer_new(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
1, w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -377,25 +511,48 @@ evas_software_x11_outbuf_new_region_for_update(Outbuf *buf, int x, int y, int w,
|
|||
evas_common_image_surface_alloc(im->image);
|
||||
im->extended_info = obr;
|
||||
if ((buf->rot == 0) || (buf->rot == 180))
|
||||
obr->xob = _find_xob(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
/*
|
||||
obr->xob = evas_software_x11_x_output_buffer_new(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
*/
|
||||
else if ((buf->rot == 90) || (buf->rot == 270))
|
||||
obr->xob = _find_xob(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
h, w,
|
||||
use_shm,
|
||||
NULL);
|
||||
/*
|
||||
obr->xob = evas_software_x11_x_output_buffer_new(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
buf->priv.x.depth,
|
||||
h, w,
|
||||
use_shm,
|
||||
NULL);
|
||||
*/
|
||||
if (buf->priv.x.mask)
|
||||
obr->mxob = _find_xob(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
1, w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
/*
|
||||
obr->mxob = evas_software_x11_x_output_buffer_new(buf->priv.x.disp,
|
||||
buf->priv.x.vis,
|
||||
1, w, h,
|
||||
use_shm,
|
||||
NULL);
|
||||
*/
|
||||
}
|
||||
if ((buf->priv.x.mask) || (buf->priv.destination_alpha))
|
||||
{
|
||||
|
@ -461,6 +618,8 @@ evas_software_x11_outbuf_flush(Outbuf *buf)
|
|||
}
|
||||
else
|
||||
{
|
||||
#if 1
|
||||
XSync(buf->priv.x.disp, False);
|
||||
for (l = buf->priv.pending_writes; l; l = l->next)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
|
@ -468,7 +627,6 @@ evas_software_x11_outbuf_flush(Outbuf *buf)
|
|||
|
||||
im = l->data;
|
||||
obr = im->extended_info;
|
||||
/* paste now */
|
||||
if (buf->priv.debug)
|
||||
evas_software_x11_outbuf_debug_show(buf, buf->priv.x.win,
|
||||
obr->x, obr->y, obr->w, obr->h);
|
||||
|
@ -481,7 +639,53 @@ evas_software_x11_outbuf_flush(Outbuf *buf)
|
|||
buf->priv.x.gcm,
|
||||
obr->x, obr->y, 0);
|
||||
}
|
||||
while (buf->priv.prev_pending_writes)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
Outbuf_Region *obr;
|
||||
|
||||
im = buf->priv.prev_pending_writes->data;
|
||||
buf->priv.prev_pending_writes =
|
||||
evas_list_remove_list(buf->priv.prev_pending_writes,
|
||||
buf->priv.prev_pending_writes);
|
||||
obr = im->extended_info;
|
||||
evas_cache_image_drop(im);
|
||||
if (obr->xob) _unfind_xob(obr->xob, 0);
|
||||
if (obr->mxob) _unfind_xob(obr->mxob, 0);
|
||||
/*
|
||||
if (obr->xob) evas_software_x11_x_output_buffer_free(obr->xob, 0);
|
||||
if (obr->mxob) evas_software_x11_x_output_buffer_free(obr->mxob, 0);
|
||||
*/
|
||||
free(obr);
|
||||
}
|
||||
buf->priv.prev_pending_writes = buf->priv.pending_writes;
|
||||
buf->priv.pending_writes = NULL;
|
||||
XFlush(buf->priv.x.disp);
|
||||
#else
|
||||
/* XX async push - disable */
|
||||
/*
|
||||
for (l = buf->priv.pending_writes; l; l = l->next)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
Outbuf_Region *obr;
|
||||
|
||||
im = l->data;
|
||||
obr = im->extended_info;
|
||||
if (buf->priv.debug)
|
||||
evas_software_x11_outbuf_debug_show(buf, buf->priv.x.win,
|
||||
obr->x, obr->y, obr->w, obr->h);
|
||||
evas_software_x11_x_output_buffer_paste(obr->xob, buf->priv.x.win,
|
||||
buf->priv.x.gc,
|
||||
obr->x, obr->y, 0);
|
||||
if (obr->mxob)
|
||||
evas_software_x11_x_output_buffer_paste(obr->mxob,
|
||||
buf->priv.x.mask,
|
||||
buf->priv.x.gcm,
|
||||
obr->x, obr->y, 0);
|
||||
}
|
||||
*/
|
||||
XSync(buf->priv.x.disp, False);
|
||||
|
||||
while (buf->priv.pending_writes)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
|
@ -491,10 +695,15 @@ evas_software_x11_outbuf_flush(Outbuf *buf)
|
|||
buf->priv.pending_writes = evas_list_remove_list(buf->priv.pending_writes, buf->priv.pending_writes);
|
||||
obr = im->extended_info;
|
||||
evas_cache_image_drop(im);
|
||||
if (obr->xob) _unfind_xob(obr->xob, 0);
|
||||
if (obr->mxob) _unfind_xob(obr->mxob, 0);
|
||||
/*
|
||||
if (obr->xob) evas_software_x11_x_output_buffer_free(obr->xob, 0);
|
||||
if (obr->mxob) evas_software_x11_x_output_buffer_free(obr->mxob, 0);
|
||||
*/
|
||||
free(obr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
evas_common_cpu_end_opt();
|
||||
}
|
||||
|
@ -515,6 +724,26 @@ evas_software_x11_outbuf_idle_flush(Outbuf *buf)
|
|||
if (obr->mxob) evas_software_x11_x_output_buffer_free(obr->mxob, 0);
|
||||
free(obr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (buf->priv.prev_pending_writes) XSync(buf->priv.x.disp, False);
|
||||
while (buf->priv.prev_pending_writes)
|
||||
{
|
||||
RGBA_Image *im;
|
||||
Outbuf_Region *obr;
|
||||
|
||||
im = buf->priv.prev_pending_writes->data;
|
||||
buf->priv.prev_pending_writes =
|
||||
evas_list_remove_list(buf->priv.prev_pending_writes,
|
||||
buf->priv.prev_pending_writes);
|
||||
obr = im->extended_info;
|
||||
evas_cache_image_drop(im);
|
||||
if (obr->xob) _unfind_xob(obr->xob, 0);
|
||||
if (obr->mxob) _unfind_xob(obr->mxob, 0);
|
||||
free(obr);
|
||||
}
|
||||
_clear_xob(0);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -609,38 +838,40 @@ evas_software_x11_outbuf_push_updated_region(Outbuf *buf, RGBA_Image *update, in
|
|||
bpl /
|
||||
((evas_software_x11_x_output_buffer_depth(obr->xob) /
|
||||
8)) - obr->w, obr->w, obr->h, x, y, NULL);
|
||||
#if 0
|
||||
/* FIXME: this is evil - but it makes ARGB targets look correct */
|
||||
if ((buf->priv.destination_alpha) && (!obr->mxob) &&
|
||||
(evas_software_x11_x_output_buffer_depth(obr->xob) == 32))
|
||||
{
|
||||
int i;
|
||||
DATA32 a;
|
||||
DATA32 *s, *e;
|
||||
|
||||
for (i = 0; i < obr->h; i++)
|
||||
{
|
||||
s = ((DATA32 *)data) + ((bpl * i) / sizeof(DATA32));
|
||||
e = s + obr->w;
|
||||
while (s < e)
|
||||
{
|
||||
a = A_VAL(s) + 1;
|
||||
R_VAL(s) = (R_VAL(s) * a) >> 8;
|
||||
G_VAL(s) = (G_VAL(s) * a) >> 8;
|
||||
B_VAL(s) = (B_VAL(s) * a) >> 8;
|
||||
s++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#if 1
|
||||
#else
|
||||
/* XX async push */
|
||||
if (!((buf->priv.onebuf) && (buf->priv.onebuf_regions)))
|
||||
{
|
||||
if (buf->priv.debug)
|
||||
evas_software_x11_outbuf_debug_show(buf, buf->priv.x.win,
|
||||
obr->x, obr->y, obr->w, obr->h);
|
||||
evas_software_x11_x_output_buffer_paste(obr->xob, buf->priv.x.win,
|
||||
buf->priv.x.gc,
|
||||
obr->x, obr->y, 0);
|
||||
}
|
||||
#endif
|
||||
if (obr->mxob)
|
||||
{
|
||||
for (yy = 0; yy < obr->h; yy++)
|
||||
evas_software_x11_x_write_mask_line(buf, obr->mxob,
|
||||
src_data +
|
||||
(yy * obr->w), obr->w, yy);
|
||||
#if 1
|
||||
#else
|
||||
/* XX async push */
|
||||
if (!((buf->priv.onebuf) && (buf->priv.onebuf_regions)))
|
||||
evas_software_x11_x_output_buffer_paste(obr->mxob,
|
||||
buf->priv.x.mask,
|
||||
buf->priv.x.gcm,
|
||||
obr->x, obr->y, 0);
|
||||
#endif
|
||||
}
|
||||
#if 1
|
||||
#else
|
||||
XFlush(buf->priv.x.disp);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -103,8 +103,11 @@ evas_software_x11_x_output_buffer_new(Display *d, Visual *v, int depth, int w, i
|
|||
if (!xob) return NULL;
|
||||
|
||||
xob->display = d;
|
||||
xob->visual = v;
|
||||
xob->xim = NULL;
|
||||
xob->shm_info = NULL;
|
||||
xob->w = w;
|
||||
xob->h = h;
|
||||
|
||||
if (try_shm > 0)
|
||||
{
|
||||
|
@ -142,6 +145,8 @@ evas_software_x11_x_output_buffer_new(Display *d, Visual *v, int depth, int w, i
|
|||
// xob->xim->bytes_per_line * xob->xim->height,
|
||||
// creates);
|
||||
// creates++;
|
||||
xob->bpl = xob->xim->bytes_per_line;
|
||||
xob->psize = xob->bpl * xob->h;
|
||||
return xob;
|
||||
}
|
||||
}
|
||||
|
@ -177,6 +182,8 @@ evas_software_x11_x_output_buffer_new(Display *d, Visual *v, int depth, int w, i
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
xob->bpl = xob->xim->bytes_per_line;
|
||||
xob->psize = xob->bpl * xob->h;
|
||||
return xob;
|
||||
}
|
||||
|
||||
|
@ -209,13 +216,17 @@ evas_software_x11_x_output_buffer_paste(X_Output_Buffer *xob, Drawable d, GC gc,
|
|||
{
|
||||
if (xob->shm_info)
|
||||
{
|
||||
// printf("shm\n");
|
||||
XShmPutImage(xob->display, d, gc, xob->xim, 0, 0, x, y,
|
||||
xob->xim->width, xob->xim->height, False);
|
||||
xob->w, xob->h, False);
|
||||
if (sync) XSync(xob->display, False);
|
||||
}
|
||||
else
|
||||
XPutImage(xob->display, d, gc, xob->xim, 0, 0, x, y,
|
||||
xob->xim->width, xob->xim->height);
|
||||
{
|
||||
// printf("NO! shm\n");
|
||||
XPutImage(xob->display, d, gc, xob->xim, 0, 0, x, y,
|
||||
xob->w, xob->h);
|
||||
}
|
||||
}
|
||||
|
||||
DATA8 *
|
||||
|
|
Loading…
Reference in New Issue