diff options
Diffstat (limited to 'chromium/third_party/skia/src/core/SkXfermode.cpp')
-rw-r--r-- | chromium/third_party/skia/src/core/SkXfermode.cpp | 370 |
1 files changed, 178 insertions, 192 deletions
diff --git a/chromium/third_party/skia/src/core/SkXfermode.cpp b/chromium/third_party/skia/src/core/SkXfermode.cpp index 176bcb50ea7..b5f95dad51b 100644 --- a/chromium/third_party/skia/src/core/SkXfermode.cpp +++ b/chromium/third_party/skia/src/core/SkXfermode.cpp @@ -8,12 +8,15 @@ #include "SkXfermode.h" +#include "SkXfermode_opts_SSE2.h" #include "SkXfermode_proccoeff.h" #include "SkColorPriv.h" -#include "SkFlattenableBuffers.h" +#include "SkLazyPtr.h" #include "SkMathPriv.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" @@ -771,116 +774,6 @@ void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, } } -/////////////////////////////////////////////////////////////////////////////// - -void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - dst[i] = proc(src[i], dst[i]); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkPMColor dstC = dst[i]; - SkPMColor C = proc(src[i], dstC); - if (a != 0xFF) { - C = SkFourByteInterp(C, dstC, a); - } - dst[i] = C; - } - } - } - } -} - -void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - SkPMColor dstC = SkPixel16ToPixel32(dst[i]); - dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkPMColor dstC = SkPixel16ToPixel32(dst[i]); - SkPMColor C = proc(src[i], dstC); - if (0xFF != a) { - C = SkFourByteInterp(C, dstC, a); - } - dst[i] = SkPixel32ToPixel16_ToU16(C); - } - } - } - } -} - -void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, - const SkPMColor* SK_RESTRICT src, int count, - const SkAlpha* SK_RESTRICT aa) const { - SkASSERT(dst && src && count >= 0); - - SkXfermodeProc proc = fProc; - - if (NULL != proc) { - if (NULL == aa) { - for (int i = count - 1; i >= 0; --i) { - SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); - dst[i] = SkToU8(SkGetPackedA32(res)); - } - } else { - for (int i = count - 1; i >= 0; --i) { - unsigned a = aa[i]; - if (0 != a) { - SkAlpha dstA = dst[i]; - SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); - unsigned A = SkGetPackedA32(res); - if (0xFF != a) { - A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); - } - dst[i] = SkToU8(A); - } - } - } - } -} - -SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) - : SkXfermode(buffer) { - fProc = NULL; - if (!buffer.isCrossProcess()) { - fProc = (SkXfermodeProc)buffer.readFunctionPtr(); - } -} - -void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { - this->INHERITED::flatten(buffer); - if (!buffer.isCrossProcess()) { - buffer.writeFunctionPtr((void*)fProc); - } -} - -#ifdef SK_DEVELOPER -void SkProcXfermode::toString(SkString* str) const { - str->appendf("SkProcXfermode: %p", fProc); -} -#endif - ////////////////////////////////////////////////////////////////////////////// #if SK_SUPPORT_GPU @@ -1071,13 +964,16 @@ public: break; } default: - GrCrash("Unknown XferEffect mode."); + SkFAIL("Unknown XferEffect mode."); break; } } static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { - return drawEffect.castEffect<XferEffect>().mode(); + // The background may come from the dst or from a texture. + int numTextures = (*drawEffect.effect())->numTextures(); + SkASSERT(numTextures <= 1); + return (drawEffect.castEffect<XferEffect>().mode() << 1) | numTextures; } private: @@ -1343,7 +1239,7 @@ GrEffectRef* XferEffect::TestCreate(SkRandom* rand, /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// -SkProcCoeffXfermode::SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { +SkProcCoeffXfermode::SkProcCoeffXfermode(SkReadBuffer& buffer) : INHERITED(buffer) { uint32_t mode32 = buffer.read32() % SK_ARRAY_COUNT(gProcCoeffs); if (mode32 >= SK_ARRAY_COUNT(gProcCoeffs)) { // out of range, just set to something harmless @@ -1352,11 +1248,10 @@ SkProcCoeffXfermode::SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHE fMode = (SkXfermode::Mode)mode32; const ProcCoeff& rec = gProcCoeffs[fMode]; + fProc = rec.fProc; // these may be valid, or may be CANNOT_USE_COEFF fSrcCoeff = rec.fSC; fDstCoeff = rec.fDC; - // now update our function-ptr in the super class - this->INHERITED::setProc(rec.fProc); } bool SkProcCoeffXfermode::asMode(Mode* mode) const { @@ -1380,6 +1275,93 @@ bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const { return true; } +void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst, + const SkPMColor* SK_RESTRICT src, int count, + const SkAlpha* SK_RESTRICT aa) const { + SkASSERT(dst && src && count >= 0); + + SkXfermodeProc proc = fProc; + + if (NULL != proc) { + if (NULL == aa) { + for (int i = count - 1; i >= 0; --i) { + dst[i] = proc(src[i], dst[i]); + } + } else { + for (int i = count - 1; i >= 0; --i) { + unsigned a = aa[i]; + if (0 != a) { + SkPMColor dstC = dst[i]; + SkPMColor C = proc(src[i], dstC); + if (a != 0xFF) { + C = SkFourByteInterp(C, dstC, a); + } + dst[i] = C; + } + } + } + } +} + +void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst, + const SkPMColor* SK_RESTRICT src, int count, + const SkAlpha* SK_RESTRICT aa) const { + SkASSERT(dst && src && count >= 0); + + SkXfermodeProc proc = fProc; + + if (NULL != proc) { + if (NULL == aa) { + for (int i = count - 1; i >= 0; --i) { + SkPMColor dstC = SkPixel16ToPixel32(dst[i]); + dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); + } + } else { + for (int i = count - 1; i >= 0; --i) { + unsigned a = aa[i]; + if (0 != a) { + SkPMColor dstC = SkPixel16ToPixel32(dst[i]); + SkPMColor C = proc(src[i], dstC); + if (0xFF != a) { + C = SkFourByteInterp(C, dstC, a); + } + dst[i] = SkPixel32ToPixel16_ToU16(C); + } + } + } + } +} + +void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst, + const SkPMColor* SK_RESTRICT src, int count, + const SkAlpha* SK_RESTRICT aa) const { + SkASSERT(dst && src && count >= 0); + + SkXfermodeProc proc = fProc; + + if (NULL != proc) { + if (NULL == aa) { + for (int i = count - 1; i >= 0; --i) { + SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); + dst[i] = SkToU8(SkGetPackedA32(res)); + } + } else { + for (int i = count - 1; i >= 0; --i) { + unsigned a = aa[i]; + if (0 != a) { + SkAlpha dstA = dst[i]; + SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); + unsigned A = SkGetPackedA32(res); + if (0xFF != a) { + A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); + } + dst[i] = SkToU8(A); + } + } + } + } +} + #if SK_SUPPORT_GPU bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect, GrTexture* background) const { @@ -1394,7 +1376,7 @@ bool SkProcCoeffXfermode::asNewEffect(GrEffectRef** effect, } #endif -void SkProcCoeffXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { +void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const { this->INHERITED::flatten(buffer); buffer.write32(fMode); } @@ -1412,7 +1394,7 @@ const char* SkXfermode::ModeName(Mode mode) { SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkProcCoeffXfermode::toString(SkString* str) const { str->append("SkProcCoeffXfermode: "); @@ -1443,16 +1425,19 @@ void SkProcCoeffXfermode::toString(SkString* str) const { class SkClearXfermode : public SkProcCoeffXfermode { public: - SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} + static SkClearXfermode* Create(const ProcCoeff& rec) { + return SkNEW_ARGS(SkClearXfermode, (rec)); + } virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; - SK_DEVELOPER_TO_STRING() + SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) private: - SkClearXfermode(SkFlattenableReadBuffer& buffer) + SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} + SkClearXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {} typedef SkProcCoeffXfermode INHERITED; @@ -1495,7 +1480,7 @@ void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, } } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkClearXfermode::toString(SkString* str) const { this->INHERITED::toString(str); } @@ -1505,16 +1490,19 @@ void SkClearXfermode::toString(SkString* str) const { class SkSrcXfermode : public SkProcCoeffXfermode { public: - SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} + static SkSrcXfermode* Create(const ProcCoeff& rec) { + return SkNEW_ARGS(SkSrcXfermode, (rec)); + } virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; - SK_DEVELOPER_TO_STRING() + SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) private: - SkSrcXfermode(SkFlattenableReadBuffer& buffer) + SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} + SkSrcXfermode(SkReadBuffer& buffer) : SkProcCoeffXfermode(buffer) {} typedef SkProcCoeffXfermode INHERITED; @@ -1562,7 +1550,7 @@ void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, } } } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkSrcXfermode::toString(SkString* str) const { this->INHERITED::toString(str); } @@ -1572,15 +1560,18 @@ void SkSrcXfermode::toString(SkString* str) const { class SkDstInXfermode : public SkProcCoeffXfermode { public: - SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} + static SkDstInXfermode* Create(const ProcCoeff& rec) { + return SkNEW_ARGS(SkDstInXfermode, (rec)); + } virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; - SK_DEVELOPER_TO_STRING() + SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) private: - SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} + SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} + SkDstInXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {} typedef SkProcCoeffXfermode INHERITED; }; @@ -1605,7 +1596,7 @@ void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, } while (--count != 0); } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkDstInXfermode::toString(SkString* str) const { this->INHERITED::toString(str); } @@ -1615,15 +1606,18 @@ void SkDstInXfermode::toString(SkString* str) const { class SkDstOutXfermode : public SkProcCoeffXfermode { public: - SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} + static SkDstOutXfermode* Create(const ProcCoeff& rec) { + return SkNEW_ARGS(SkDstOutXfermode, (rec)); + } virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; - SK_DEVELOPER_TO_STRING() + SK_TO_STRING_OVERRIDE() SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) private: - SkDstOutXfermode(SkFlattenableReadBuffer& buffer) + SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} + SkDstOutXfermode(SkReadBuffer& buffer) : INHERITED(buffer) {} typedef SkProcCoeffXfermode INHERITED; @@ -1649,7 +1643,7 @@ void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, } while (--count != 0); } -#ifdef SK_DEVELOPER +#ifndef SK_IGNORE_TO_STRING void SkDstOutXfermode::toString(SkString* str) const { this->INHERITED::toString(str); } @@ -1657,83 +1651,72 @@ void SkDstOutXfermode::toString(SkString* str) const { /////////////////////////////////////////////////////////////////////////////// -SK_DECLARE_STATIC_MUTEX(gCachedXfermodesMutex); -static SkXfermode* gCachedXfermodes[SkXfermode::kLastMode + 1]; +extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode); +extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); -void SkXfermode::Term() { - SkAutoMutexAcquire ac(gCachedXfermodesMutex); +// Technically, can't be static and passed as a template parameter. So we use anonymous namespace. +namespace { +SkXfermode* create_mode(int iMode) { + SkXfermode::Mode mode = (SkXfermode::Mode)iMode; - for (size_t i = 0; i < SK_ARRAY_COUNT(gCachedXfermodes); ++i) { - SkSafeUnref(gCachedXfermodes[i]); - gCachedXfermodes[i] = NULL; + 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; + } + } + return xfer; } +} // namespace -extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, - SkXfermode::Mode mode); -extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode); SkXfermode* SkXfermode::Create(Mode mode) { SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); - SkASSERT(SK_ARRAY_COUNT(gCachedXfermodes) == kModeCount); if ((unsigned)mode >= kModeCount) { // report error return NULL; } - // Skia's "defaut" mode is srcover. NULL in SkPaint is interpreted as srcover + // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover // so we can just return NULL from the factory. if (kSrcOver_Mode == mode) { return NULL; } - // guard our access to gCachedXfermodes, since we may write into it - SkAutoMutexAcquire ac(gCachedXfermodesMutex); - - 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 = SkNEW_ARGS(SkClearXfermode, (rec)); - break; - case kSrc_Mode: - xfer = SkNEW_ARGS(SkSrcXfermode, (rec)); - break; - case kSrcOver_Mode: - SkASSERT(false); // should not land here - break; - case kDstIn_Mode: - xfer = SkNEW_ARGS(SkDstInXfermode, (rec)); - break; - case kDstOut_Mode: - xfer = SkNEW_ARGS(SkDstOutXfermode, (rec)); - break; - default: - // no special-case, just rely in the rec and its function-ptrs - xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); - break; - } - } - gCachedXfermodes[mode] = xfer; - } - return SkSafeRef(xfer); + SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, kModeCount, create_mode); + return SkSafeRef(cached[mode]); } SkXfermodeProc SkXfermode::GetProc(Mode mode) { @@ -1976,4 +1959,7 @@ SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) #if !SK_ARM_NEON_IS_NONE SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkNEONProcCoeffXfermode) #endif +#if defined(SK_CPU_X86) && !defined(SK_BUILD_FOR_IOS) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSSE2ProcCoeffXfermode) +#endif SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |