aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-28 20:04:11 +0000
committerGravatar commit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>2014-03-28 20:04:11 +0000
commit140950cc595a3058144681b088e44ff1f8f52d5b (patch)
tree71f2c9a9feb906b25f4a925b4b8dc7685bf30575
parent5be2def19a5f91497d1e4b98c5e383dd36c1ecab (diff)
SkOnce for SkXfermode::Create(Mode)
This removes the mutex from the fast path when we've already cached it. BUG=skia: R=reed@google.com, bungeman@google.com, mtklein@google.com Author: mtklein@chromium.org Review URL: https://codereview.chromium.org/215533002 git-svn-id: http://skia.googlecode.com/svn/trunk@13986 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r--src/core/SkXfermode.cpp98
1 files changed, 51 insertions, 47 deletions
diff --git a/src/core/SkXfermode.cpp b/src/core/SkXfermode.cpp
index 9b66a66f17..674078ef3a 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);
}