Index: src/core/SkXfermode.cpp |
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp |
index 9b66a66f1714260c6396da1c36659c3eab623885..674078ef3a1edebb3d63f69cef1beb4166a27bf4 100644 |
--- a/src/core/SkXfermode.cpp |
+++ b/src/core/SkXfermode.cpp |
@@ -10,11 +10,12 @@ |
#include "SkXfermode.h" |
#include "SkXfermode_proccoeff.h" |
#include "SkColorPriv.h" |
-#include "SkReadBuffer.h" |
-#include "SkWriteBuffer.h" |
#include "SkMathPriv.h" |
+#include "SkOnce.h" |
+#include "SkReadBuffer.h" |
#include "SkString.h" |
#include "SkUtilsArm.h" |
+#include "SkWriteBuffer.h" |
#if !SK_ARM_NEON_IS_NONE |
#include "SkXfermode_opts_arm_neon.h" |
@@ -1671,7 +1672,8 @@ void SkDstOutXfermode::toString(SkString* str) const { |
/////////////////////////////////////////////////////////////////////////////// |
SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); |
-static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; |
+static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; // All NULL to start. |
+static bool gXfermodeCached[SK_ARRAY_COUNT(gCachedXfermodes)]; // All false to start. |
void SkXfermode::Term() { |
SkAutoMutexAcquire ac(gCachedXfermodesMutex); |
@@ -1686,6 +1688,50 @@ extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, |
SkXfermode::Mode mode); |
extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); |
+ |
+static void create_mode(SkXfermode::Mode mode) { |
+ SkASSERT(NULL == gCachedXfermodes[mode]); |
+ |
+ ProcCoeff rec = gProcCoeffs[mode]; |
+ SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); |
+ if (pp != NULL) { |
+ rec.fProc = pp; |
+ } |
+ |
+ SkXfermode* xfer = NULL; |
+ // check if we have a platform optim for that |
+ SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); |
+ if (xfm != NULL) { |
+ xfer = xfm; |
+ } else { |
+ // All modes can in theory be represented by the ProcCoeff rec, since |
+ // it contains function ptrs. However, a few modes are both simple and |
+ // commonly used, so we call those out for their own subclasses here. |
+ switch (mode) { |
+ case SkXfermode::kClear_Mode: |
+ xfer = SkClearXfermode::Create(rec); |
+ break; |
+ case SkXfermode::kSrc_Mode: |
+ xfer = SkSrcXfermode::Create(rec); |
+ break; |
+ case SkXfermode::kSrcOver_Mode: |
+ SkASSERT(false); // should not land here |
+ break; |
+ case SkXfermode::kDstIn_Mode: |
+ xfer = SkDstInXfermode::Create(rec); |
+ break; |
+ case SkXfermode::kDstOut_Mode: |
+ xfer = SkDstOutXfermode::Create(rec); |
+ break; |
+ default: |
+ // no special-case, just rely in the rec and its function-ptrs |
+ xfer = SkProcCoeffXfermode::Create(rec, mode); |
+ break; |
+ } |
+ } |
+ gCachedXfermodes[mode] = xfer; |
+} |
+ |
SkXfermode* SkXfermode::Create(Mode mode) { |
SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); |
SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); |
@@ -1701,51 +1747,9 @@ SkXfermode* SkXfermode::Create(Mode mode) { |
return NULL; |
} |
- // guard our access to gCachedXfermodes, since we may write into it |
- SkAutoMutexAcquire ac(gCachedXfermodesMutex); |
- |
+ SkOnce(&gXfermodeCached[mode], &gCachedXfermodesMutex, create_mode, mode); |
SkXfermode* xfer = gCachedXfermodes[mode]; |
- if (NULL == xfer) { |
- ProcCoeff rec = gProcCoeffs[mode]; |
- |
- SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); |
- |
- if (pp != NULL) { |
- rec.fProc = pp; |
- } |
- |
- // check if we have a platform optim for that |
- SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); |
- if (xfm != NULL) { |
- xfer = xfm; |
- } else { |
- // All modes can in theory be represented by the ProcCoeff rec, since |
- // it contains function ptrs. However, a few modes are both simple and |
- // commonly used, so we call those out for their own subclasses here. |
- switch (mode) { |
- case kClear_Mode: |
- xfer = SkClearXfermode::Create(rec); |
- break; |
- case kSrc_Mode: |
- xfer = SkSrcXfermode::Create(rec); |
- break; |
- case kSrcOver_Mode: |
- SkASSERT(false); // should not land here |
- break; |
- case kDstIn_Mode: |
- xfer = SkDstInXfermode::Create(rec); |
- break; |
- case kDstOut_Mode: |
- xfer = SkDstOutXfermode::Create(rec); |
- break; |
- default: |
- // no special-case, just rely in the rec and its function-ptrs |
- xfer = SkProcCoeffXfermode::Create(rec, mode); |
- break; |
- } |
- } |
- gCachedXfermodes[mode] = xfer; |
- } |
+ SkASSERT(xfer != NULL); |
return SkSafeRef(xfer); |
} |