diff --git a/include/core/SkPreConfig.h b/include/core/SkPreConfig.h index bbf0124117..55b1abf3bc 100644 --- a/include/core/SkPreConfig.h +++ b/include/core/SkPreConfig.h @@ -173,5 +173,21 @@ #define SK_API #endif +////////////////////////////////////////////////////////////////////// + +/** + * Use SK_PURE_FUNC as an attribute to indicate that a function's + * return value only depends on the value of its parameters. This + * can help the compiler optimize out successive calls. + * + * Usage: + * void function(int params) SK_PURE_FUNC; + */ +#if defined(__GNUC__) +# define SK_PURE_FUNC __attribute__((pure)) +#else +# define SK_PURE_FUNC /* nothing */ +#endif + #endif diff --git a/src/core/SkBitmapProcState_matrixProcs.cpp b/src/core/SkBitmapProcState_matrixProcs.cpp index 77c6200d03..64755be19e 100644 --- a/src/core/SkBitmapProcState_matrixProcs.cpp +++ b/src/core/SkBitmapProcState_matrixProcs.cpp @@ -496,17 +496,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { // clamp gets special version of filterOne fFilterOneX = SK_Fixed1; fFilterOneY = SK_Fixed1; -#if SK_ARM_NEON_IS_NONE - return ClampX_ClampY_Procs[index]; -#elif SK_ARM_NEON_IS_ALWAYS - return ClampX_ClampY_Procs_neon[index]; -#else // SK_ARM_NEON_IS_DYNAMIC - if (sk_cpu_arm_has_neon()) { - return ClampX_ClampY_Procs_neon[index]; - } else { - return ClampX_ClampY_Procs[index]; - } -#endif + return SK_ARM_NEON_WRAP(ClampX_ClampY_Procs)[index]; } // all remaining procs use this form for filterOne @@ -516,17 +506,7 @@ SkBitmapProcState::chooseMatrixProc(bool trivial_matrix) { if (SkShader::kRepeat_TileMode == fTileModeX && SkShader::kRepeat_TileMode == fTileModeY) { -#if SK_ARM_NEON_IS_NONE - return RepeatX_RepeatY_Procs[index]; -#elif SK_ARM_NEON_IS_ALWAYS - return RepeatX_RepeatY_Procs_neon[index]; -#else // SK_ARM_NEON_IS_DYNAMIC - if (sk_cpu_arm_has_neon()) { - return RepeatX_RepeatY_Procs_neon[index]; - } else { - return RepeatX_RepeatY_Procs[index]; - } -#endif + return SK_ARM_NEON_WRAP(RepeatX_RepeatY_Procs)[index]; } fTileProcX = choose_tile_proc(fTileModeX); diff --git a/src/core/SkUtilsArm.h b/src/core/SkUtilsArm.h index 4562b01923..6a5aab8067 100644 --- a/src/core/SkUtilsArm.h +++ b/src/core/SkUtilsArm.h @@ -47,7 +47,41 @@ static bool sk_cpu_arm_has_neon(void) { return true; } #else // SK_ARM_NEON_IS_DYNAMIC -extern bool sk_cpu_arm_has_neon(void); + +extern bool sk_cpu_arm_has_neon(void) SK_PURE_FUNC; +#endif + +// Use SK_ARM_NEON_WRAP(symbol) to map 'symbol' to a NEON-specific symbol +// when applicable. This will transform 'symbol' differently depending on +// the current NEON configuration, i.e.: +// +// NONE -> 'symbol' +// ALWAYS -> 'symbol_neon' +// DYNAMIC -> 'symbol' or 'symbol_neon' depending on runtime check. +// +// The goal is to simplify user code, for example: +// +// return SK_ARM_NEON_WRAP(do_something)(params); +// +// Replaces the equivalent: +// +// #if SK_ARM_NEON_IS_NONE +// return do_something(params); +// #elif SK_ARM_NEON_IS_ALWAYS +// return do_something_neon(params); +// #elif SK_ARM_NEON_IS_DYNAMIC +// if (sk_cpu_arm_has_neon()) +// return do_something_neon(params); +// else +// return do_something(params); +// #endif +// +#if SK_ARM_NEON_IS_NONE +# define SK_ARM_NEON_WRAP(x) (x) +#elif SK_ARM_NEON_IS_ALWAYS +# define SK_ARM_NEON_WRAP(x) (x ## _neon) +#elif SK_ARM_NEON_IS_DYNAMIC +# define SK_ARM_NEON_WRAP(x) (sk_cpu_arm_has_neon() ? x ## _neon : x) #endif #endif // SkUtilsArm_DEFINED