2013-12-08 22:57:50 -08:00
# ifndef EVAS_FILTER_PRIVATE_H
# define EVAS_FILTER_PRIVATE_H
# include "evas_filter.h"
# include "evas_private.h"
2015-06-03 03:59:11 -07:00
/* logging variables */
extern int _evas_filter_log_dom ;
# define EVAS_FILTER_LOG_COLOR EINA_COLOR_LIGHTBLUE
2016-01-21 21:38:32 -08:00
# ifdef DEBUG
2015-06-09 05:29:13 -07:00
# define FILTERS_DEBUG
2016-01-21 21:38:32 -08:00
# endif
2015-06-09 05:29:13 -07:00
2015-06-03 03:59:11 -07:00
# ifdef ERR
# undef ERR
# endif
# define ERR(...) EINA_LOG_DOM_ERR(_evas_filter_log_dom, __VA_ARGS__)
# ifdef INF
# undef INF
# endif
# define INF(...) EINA_LOG_DOM_INFO(_evas_filter_log_dom, __VA_ARGS__)
# ifdef WRN
# undef WRN
# endif
# define WRN(...) EINA_LOG_DOM_WARN(_evas_filter_log_dom, __VA_ARGS__)
# ifdef CRI
# undef CRI
# endif
# define CRI(...) EINA_LOG_DOM_CRIT(_evas_filter_log_dom, __VA_ARGS__)
# ifdef DBG
# undef DBG
# endif
# define DBG(...) EINA_LOG_DOM_DBG(_evas_filter_log_dom, __VA_ARGS__)
2015-06-09 05:29:13 -07:00
# ifdef FILTERS_DEBUG
# define XDBG(...) DBG(__VA_ARGS__)
# else
# define XDBG(...) do {} while (0)
# endif
2013-12-08 22:57:50 -08:00
// This is a potential optimization.
# define DIV_USING_BITSHIFT 1
# ifdef LITTLE_ENDIAN
# define ALPHA 3
# define RGB0 0
# define RGB3 3
# define RED 2
# define GREEN 1
# define BLUE 0
# else
# define ALPHA 0
# define RGB0 1
# define RGB3 4
# define RED 0
# define GREEN 1
# define BLUE 2
# endif
// RGBA = (((a) << 24) + ((r) << 16) + ((g) << 8) + (b))
# define ALPHA_OF(a) ((a) >> 24)
# define RED_OF(a) (((a) >> 16) & 0xff)
# define GREEN_OF(a) (((a) >> 8) & 0xff)
# define BLUE_OF(a) ((a) & 0xff)
2014-03-10 22:50:11 -07:00
// Enable debug if you're working on optimizations
# define DEBUG_TIME 1
// Windows build will break if CLOCK_MONOTONIC is used
# if !defined(_POSIX_MONOTONIC_CLOCK) || (_POSIX_MONOTONIC_CLOCK < 0)
# undef DEBUG_TIME
# define DEBUG_TIME 0
# endif
Evas filters: Add optimizable blur function
Prepare optimization paths for blur operations, as they are VERY
costly. This simple change, when using gcc -O3 flag, boosts
horizontal blur performance by > 50%, because STEP is 1 (and
so, memory accesses, increments, etc... are all very simple)
The objective is to have support for NEON, MMX, SSE, too, with
runtime detection.
2014-03-10 02:36:28 -07:00
// The 'restrict' keyword is part of C99
# if __STDC_VERSION__ < 199901L
# define restrict
# endif
2013-12-08 22:57:50 -08:00
// Helpers
# define ENFN ctx->evas->engine.func
# define ENDT ctx->evas->engine.data.output
2014-01-01 19:43:44 -08:00
# define BUFFERS_LOCK() do { if (cmd->input) cmd->input->locked = 1; if (cmd->output) cmd->output->locked = 1; if (cmd->mask) cmd->mask->locked = 1; } while (0)
# define BUFFERS_UNLOCK() do { if (cmd->input) cmd->input->locked = 0; if (cmd->output) cmd->output->locked = 0; if (cmd->mask) cmd->mask->locked = 0; } while (0)
2014-03-10 22:50:11 -07:00
# if DEBUG_TIME
# define DEBUG_TIME_BEGIN() \
struct timespec ts1 , ts2 ; \
clock_gettime ( CLOCK_MONOTONIC , & ts1 ) ;
# define DEBUG_TIME_END() \
clock_gettime ( CLOCK_MONOTONIC , & ts2 ) ; \
long long int t = 1000000LL * ( ts2 . tv_sec - ts1 . tv_sec ) \
2015-06-09 05:29:13 -07:00
+ ( ts2 . tv_nsec - ts1 . tv_nsec ) / 1000LL ; ( void ) t ; \
XDBG ( " TIME SPENT: %lldus " , t ) ;
2014-03-10 22:50:11 -07:00
# else
# define DEBUG_TIME_BEGIN() do {} while(0)
# define DEBUG_TIME_END() do {} while(0)
# endif
2014-03-11 00:18:41 -07:00
# if DIV_USING_BITSHIFT
# define DEFINE_DIVIDER(div) const int pow2 = evas_filter_smallest_pow2_larger_than((div) << 10); const int numerator = (1 << pow2) / (div);
# define DIVIDE(val) (((val) * numerator) >> pow2)
# else
# define DEFINE_DIVIDER(div) const int divider = (div);
# define DIVIDE(val) ((val) / divider)
# endif
2014-01-01 22:57:44 -08:00
typedef enum _Evas_Filter_Interpolation_Mode Evas_Filter_Interpolation_Mode ;
2017-01-16 23:13:35 -08:00
typedef Evas_Filter_Buffer * ( * evas_filter_buffer_scaled_get_func ) ( Evas_Filter_Context * ctx , Evas_Filter_Buffer * src , unsigned w , unsigned h ) ;
2013-12-08 22:57:50 -08:00
struct _Evas_Filter_Context
{
Evas_Public_Data * evas ;
Eina_Inlist * commands ;
Eina_List * buffers ; // Evas_Filter_Buffer *
int last_buffer_id ;
int last_command_id ;
2017-01-05 04:29:32 -08:00
void * user_data ; // used by textblock
2014-01-06 21:55:27 -08:00
2017-01-16 23:13:35 -08:00
// ugly hack (dlsym fail)
evas_filter_buffer_scaled_get_func buffer_scaled_get ;
2014-01-06 21:55:27 -08:00
// Variables changing at each run
int w , h ; // Dimensions of the input/output buffers
int padl , padt , padr , padb ; // Padding in the current input/output buffers
2013-12-08 22:57:50 -08:00
struct
{
/** Post-processing callback. The context can be safely destroyed here. */
Evas_Filter_Cb cb ;
void * data ;
} post_run ;
2014-01-16 18:19:02 -08:00
2014-01-16 22:05:23 -08:00
struct
{
int bufid ;
int x , y ;
2014-03-02 01:39:08 -08:00
int cx , cy , cw , ch ; // clip
2014-06-10 23:59:31 -07:00
int r , g , b , a ; // clip color
2014-11-12 17:31:41 -08:00
void * mask ; // mask
int mask_x , mask_y ; // mask offset
2017-03-09 00:36:39 -08:00
Evas_Render_Op rop ;
2014-03-02 01:39:08 -08:00
Eina_Bool clip_use : 1 ;
2014-06-10 23:59:31 -07:00
Eina_Bool color_use : 1 ;
2014-01-16 22:05:23 -08:00
} target ;
2014-01-22 23:54:50 -08:00
Eina_Bool async : 1 ;
2014-02-06 18:22:36 -08:00
Eina_Bool running : 1 ;
2014-03-01 21:55:42 -08:00
Eina_Bool has_proxies : 1 ;
2013-12-08 22:57:50 -08:00
} ;
struct _Evas_Filter_Command
{
EINA_INLIST ;
int id ;
Evas_Filter_Mode mode ;
Evas_Filter_Context * ctx ;
Evas_Filter_Buffer * input ;
Evas_Filter_Buffer * mask ;
Evas_Filter_Buffer * output ;
union
{
struct
{
int dx , dy ;
2014-03-11 02:21:46 -07:00
int count ;
2013-12-08 22:57:50 -08:00
Evas_Filter_Blur_Type type ;
2014-03-11 02:21:46 -07:00
Eina_Bool auto_count : 1 ; // If true, BOX blur will be smooth using
2013-12-08 22:57:50 -08:00
} blur ;
struct
{
DATA8 * data ; // Pointer to 256 char array
Evas_Filter_Channel channel ;
} curve ;
struct
{
2014-01-06 17:16:39 -08:00
// mask contains the map data
2013-12-08 22:57:50 -08:00
Evas_Filter_Displacement_Flags flags ;
int intensity ; // Max displacement in pixels
} displacement ;
struct
{
float xyangle ; // in degrees: 0-360 (modulo)
float zangle ; // degrees: 0-90 (defaults to 0)
float specular_factor ; // range TBD: 0-...
float elevation ;
DATA32 dark ;
DATA32 color ;
DATA32 white ;
Eina_Bool compensate : 1 ; // Compensate for darkening
//Eina_Bool specular : 1; // Use specular light as well (needs specular_factor > 0)
} bump ;
2014-01-06 23:44:10 -08:00
struct
{
Evas_Filter_Transform_Flags flags ;
} transform ;
2013-12-08 22:57:50 -08:00
} ;
struct {
2015-12-03 22:09:56 -08:00
Efl_Gfx_Render_Op rop ;
2013-12-08 22:57:50 -08:00
int R , G , B , A ;
int ox , oy ;
2014-01-02 01:44:01 -08:00
union {
struct {
int x , y , w , h ;
} ;
struct {
int l , r , t , b ;
} ;
} clip ;
2013-12-31 00:51:09 -08:00
Evas_Filter_Fill_Mode fillmode ;
2014-01-02 22:51:17 -08:00
Eina_Bool clip_use : 1 ;
2014-01-02 01:44:01 -08:00
Eina_Bool clip_mode_lrtb : 1 ;
2014-01-22 23:54:50 -08:00
Eina_Bool need_temp_buffer : 1 ;
2013-12-08 22:57:50 -08:00
} draw ;
} ;
struct _Evas_Filter_Buffer
{
EINA_REFCOUNT ;
int id ;
Evas_Filter_Context * ctx ;
Evas_Object * source ;
2014-01-22 23:54:50 -08:00
Eina_Stringshare * source_name ;
2016-05-11 04:57:06 -07:00
Ector_Buffer * buffer ;
2013-12-08 22:57:50 -08:00
int w , h ;
Eina_Bool alpha_only : 1 ; // 1 channel (A) instead of 4 (RGBA)
Eina_Bool transient : 1 ; // temporary buffer (automatic allocation)
Eina_Bool locked : 1 ; // internal flag
2014-01-22 21:58:05 -08:00
Eina_Bool delete_me : 1 ; // request delete asap (after released by client)
2014-03-20 20:20:11 -07:00
Eina_Bool dirty : 1 ; // Marked as dirty as soon as a command writes to it
2013-12-08 22:57:50 -08:00
} ;
2014-01-01 22:57:44 -08:00
enum _Evas_Filter_Interpolation_Mode
{
EVAS_FILTER_INTERPOLATION_MODE_NONE ,
2014-02-03 19:32:15 -08:00
EVAS_FILTER_INTERPOLATION_MODE_LINEAR
2014-01-01 22:57:44 -08:00
} ;
2017-01-16 23:13:35 -08:00
enum _Evas_Filter_Support
{
EVAS_FILTER_SUPPORT_NONE = 0 ,
EVAS_FILTER_SUPPORT_CPU ,
EVAS_FILTER_SUPPORT_GL
} ;
2013-12-08 22:57:50 -08:00
void evas_filter_context_clear ( Evas_Filter_Context * ctx ) ;
2014-02-04 18:40:10 -08:00
void evas_filter_context_source_set ( Evas_Filter_Context * ctx , Evas_Object * eo_proxy , Evas_Object * eo_source , int bufid , Eina_Stringshare * name ) ;
2013-12-08 22:57:50 -08:00
/* FIXME: CPU filters entry points. Move these to the Evas Engine itself. */
Evas_Filter_Apply_Func evas_filter_blur_cpu_func_get ( Evas_Filter_Command * cmd ) ;
Evas_Filter_Apply_Func evas_filter_bump_map_cpu_func_get ( Evas_Filter_Command * cmd ) ;
Evas_Filter_Apply_Func evas_filter_displace_cpu_func_get ( Evas_Filter_Command * cmd ) ;
2013-12-12 00:46:46 -08:00
Evas_Filter_Apply_Func evas_filter_fill_cpu_func_get ( Evas_Filter_Command * cmd ) ;
2014-01-06 23:44:10 -08:00
Evas_Filter_Apply_Func evas_filter_transform_cpu_func_get ( Evas_Filter_Command * cmd ) ;
2013-12-08 22:57:50 -08:00
/* Utility functions */
void _clip_to_target ( int * sx , int * sy , int sw , int sh , int ox , int oy , int dw , int dh , int * dx , int * dy , int * rows , int * cols ) ;
Eina_Bool evas_filter_buffer_alloc ( Evas_Filter_Buffer * fb , int w , int h ) ;
Evas_Filter_Buffer * _filter_buffer_get ( Evas_Filter_Context * ctx , int bufid ) ;
2014-01-22 23:54:50 -08:00
Eina_Bool _filter_buffer_data_set ( Evas_Filter_Context * ctx , int bufid , void * data , int w , int h , Eina_Bool alpha_only ) ;
Evas_Filter_Buffer * _filter_buffer_data_new ( Evas_Filter_Context * ctx , void * data , int w , int h , Eina_Bool alpha_only ) ;
# define evas_filter_buffer_alloc_new(ctx, w, h, a) _filter_buffer_data_new(ctx, NULL, w, h, a)
2013-12-31 02:38:58 -08:00
Evas_Filter_Buffer * evas_filter_temporary_buffer_get ( Evas_Filter_Context * ctx , int w , int h , Eina_Bool alpha_only ) ;
2014-01-22 23:54:50 -08:00
Evas_Filter_Buffer * evas_filter_buffer_scaled_get ( Evas_Filter_Context * ctx , Evas_Filter_Buffer * src , unsigned w , unsigned h ) ;
2015-05-27 22:37:10 -07:00
Eina_Bool evas_filter_interpolate ( DATA8 * output /* 256 values */ , int * points /* 256 values */ , Evas_Filter_Interpolation_Mode mode ) ;
2014-01-22 23:54:50 -08:00
Evas_Filter_Command * _evas_filter_command_get ( Evas_Filter_Context * ctx , int cmdid ) ;
2014-03-11 00:18:41 -07:00
int evas_filter_smallest_pow2_larger_than ( int val ) ;
2013-12-08 22:57:50 -08:00
2015-06-04 03:42:38 -07:00
void evas_filter_parser_shutdown ( void ) ;
2015-12-08 17:45:53 -08:00
# define E_READ ECTOR_BUFFER_ACCESS_FLAG_READ
# define E_WRITE ECTOR_BUFFER_ACCESS_FLAG_WRITE
# define E_ALPHA EFL_GFX_COLORSPACE_GRY8
# define E_ARGB EFL_GFX_COLORSPACE_ARGB8888
static inline void *
_buffer_map_all ( Ector_Buffer * buf , unsigned int * len , Ector_Buffer_Access_Flag mode , Efl_Gfx_Colorspace cspace , unsigned int * stride )
{
void * ret = NULL ;
int w , h ;
if ( ! buf ) return NULL ;
2016-03-01 10:06:28 -08:00
ector_buffer_size_get ( buf , & w , & h ) ;
ret = ector_buffer_map ( buf , len , mode , 0 , 0 , w , h , cspace , stride ) ;
2015-12-08 17:45:53 -08:00
return ret ;
}
2013-12-08 22:57:50 -08:00
# endif // EVAS_FILTER_PRIVATE_H