Try using std::call_once

Now that we've got std library support, perhaps we should start using it.
This CL acts as a little canary, and may help fix the linked bug.

I'm not really sure what's going on in the linked bug, but using
std::call_once over homegrown atomics has to be the right answer...

BUG=chromium:418041
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1550893002
CQ_EXTRA_TRYBOTS=client.skia:Test-Ubuntu-GCC-GCE-CPU-AVX2-x86_64-Release-SKNX_NO_SIMD-Trybot

Going to land this ahead of review while the tree is quiet to see how it rolls.
TBR=herb@google.com

Review URL: https://codereview.chromium.org/1550893002
This commit is contained in:
mtklein 2015-12-28 22:27:18 -08:00 committed by Commit bot
parent 636270245f
commit 8895b72f78

View File

@ -13,8 +13,8 @@
#include "SkBlitRow.h"
#include "SkBlitRow_opts_SSE2.h"
#include "SkBlitRow_opts_SSE4.h"
#include "SkOncePtr.h"
#include "SkRTConf.h"
#include <mutex>
#if defined(_MSC_VER) && defined(_WIN64)
#include <intrin.h>
@ -68,37 +68,12 @@ static inline void getcpuid(int info_type, int info[4]) {
////////////////////////////////////////////////////////////////////////////////
/* Fetch the SIMD level directly from the CPU, at run-time.
* Only checks the levels needed by the optimizations in this file.
*/
static int* get_SIMD_level() {
int cpu_info[4] = { 0, 0, 0, 0 };
getcpuid(1, cpu_info);
int* level = new int;
if ((cpu_info[2] & (1<<20)) != 0) {
*level = SK_CPU_SSE_LEVEL_SSE42;
} else if ((cpu_info[2] & (1<<19)) != 0) {
*level = SK_CPU_SSE_LEVEL_SSE41;
} else if ((cpu_info[2] & (1<<9)) != 0) {
*level = SK_CPU_SSE_LEVEL_SSSE3;
} else if ((cpu_info[3] & (1<<26)) != 0) {
*level = SK_CPU_SSE_LEVEL_SSE2;
} else {
*level = 0;
}
return level;
}
SK_DECLARE_STATIC_ONCE_PTR(int, gSIMDLevel);
/* Verify that the requested SIMD level is supported in the build.
* If not, check if the platform supports it.
*/
static inline bool supports_simd(int minLevel) {
static inline bool supports_simd(int level) {
#if defined(SK_CPU_SSE_LEVEL)
if (minLevel <= SK_CPU_SSE_LEVEL) {
if (level <= SK_CPU_SSE_LEVEL) {
return true;
} else
#endif
@ -112,7 +87,18 @@ static inline bool supports_simd(int minLevel) {
*/
return false;
#else
return minLevel <= *gSIMDLevel.get(get_SIMD_level);
static std::once_flag once;
static int maxLevel = 0;
std::call_once(once, [&]{
int cpu_info[4] = { 0, 0, 0, 0 };
getcpuid(1, cpu_info);
if (cpu_info[3] & (1<<26)) { maxLevel = SK_CPU_SSE_LEVEL_SSE2 ; }
if (cpu_info[2] & (1<< 9)) { maxLevel = SK_CPU_SSE_LEVEL_SSSE3; }
if (cpu_info[2] & (1<<19)) { maxLevel = SK_CPU_SSE_LEVEL_SSE41; }
if (cpu_info[2] & (1<<20)) { maxLevel = SK_CPU_SSE_LEVEL_SSE42; }
});
return level <= maxLevel;
#endif
}
}