OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkXfermode.h" | 9 #include "SkXfermode.h" |
10 #include "SkXfermode_opts_SSE2.h" | 10 #include "SkXfermode_opts_SSE2.h" |
11 #include "SkXfermode_proccoeff.h" | 11 #include "SkXfermode_proccoeff.h" |
12 #include "Sk4px.h" | 12 #include "Sk4px.h" |
13 #include "SkColorPriv.h" | 13 #include "SkColorPriv.h" |
14 #include "SkLazyPtr.h" | 14 #include "SkLazyPtr.h" |
15 #include "SkMathPriv.h" | 15 #include "SkMathPriv.h" |
16 #include "SkPMFloat.h" | 16 #include "SkPMFloat.h" |
17 #include "SkReadBuffer.h" | 17 #include "SkReadBuffer.h" |
18 #include "SkString.h" | 18 #include "SkString.h" |
19 #include "SkUtilsArm.h" | 19 #include "SkUtilsArm.h" |
20 #include "SkWriteBuffer.h" | 20 #include "SkWriteBuffer.h" |
21 | 21 |
22 // When implemented, the Sk4f and Sk4px xfermodes beat src/opts/SkXfermodes_opts
_SSE2's. | 22 #if SK_CPU_X86 && SK_CPU_SSE_LEVEL < SK_CPU_SSE_LEVEL_SSE2 |
23 // When implemented, the Sk4px, but not Sk4f, xfermodes beat src/opts/SkXfermode
s_arm_neon's. | 23 #warning "SkXfermode will be much faster if you compile with support for SSE
2." |
24 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2 | 24 #endif |
25 #define SK_4F_XFERMODES_ARE_FAST | 25 |
26 #define SK_4PX_XFERMODES_ARE_FAST | 26 #if SK_CPU_X86 || defined(SK_ARM_HAS_NEON) |
27 #elif defined(SK_ARM_HAS_NEON) | 27 #define SK_USE_4PX_XFERMODES |
28 #define SK_4PX_XFERMODES_ARE_FAST | |
29 #endif | 28 #endif |
30 | 29 |
31 #if !SK_ARM_NEON_IS_NONE | 30 #if !SK_ARM_NEON_IS_NONE |
32 #include "SkXfermode_opts_arm_neon.h" | 31 #include "SkXfermode_opts_arm_neon.h" |
33 #endif | 32 #endif |
34 | 33 |
35 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) | 34 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) |
36 | 35 |
37 static inline unsigned saturated_add(unsigned a, unsigned b) { | 36 static inline unsigned saturated_add(unsigned a, unsigned b) { |
38 SkASSERT(a <= 255); | 37 SkASSERT(a <= 255); |
(...skipping 1136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1175 } | 1174 } |
1176 | 1175 |
1177 #ifndef SK_IGNORE_TO_STRING | 1176 #ifndef SK_IGNORE_TO_STRING |
1178 void SkDstInXfermode::toString(SkString* str) const { | 1177 void SkDstInXfermode::toString(SkString* str) const { |
1179 this->INHERITED::toString(str); | 1178 this->INHERITED::toString(str); |
1180 } | 1179 } |
1181 #endif | 1180 #endif |
1182 | 1181 |
1183 /////////////////////////////////////////////////////////////////////////////// | 1182 /////////////////////////////////////////////////////////////////////////////// |
1184 | 1183 |
1185 /* These modes can merge coverage into src-alpha | |
1186 * | |
1187 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, | |
1188 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, | |
1189 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, | |
1190 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, | |
1191 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, | |
1192 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, | |
1193 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, | |
1194 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, | |
1195 */ | |
1196 | |
1197 static const float gInv255 = 0.0039215683f; // (1.0f / 255) - ULP == SkBits2Flo
at(0x3B808080) | |
1198 | |
1199 static Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) { | |
1200 return v0 + (v1 - v0) * t; | |
1201 } | |
1202 | |
1203 static Sk4f clamp_255(const Sk4f& value) { | |
1204 return Sk4f::Min(Sk4f(255), value); | |
1205 } | |
1206 | |
1207 static Sk4f clamp_0_255(const Sk4f& value) { | |
1208 return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value)); | |
1209 } | |
1210 | |
1211 /** | |
1212 * Some modes can, due to very slight numerical error, generate "invalid" pmcol
ors... | |
1213 * | |
1214 * e.g. | |
1215 * alpha = 100.9999 | |
1216 * red = 101 | |
1217 * | |
1218 * or | |
1219 * alpha = 255.0001 | |
1220 * | |
1221 * If we know we're going to write-out the values as bytes, we can relax these
somewhat, | |
1222 * since we only really need to enforce that the bytes are valid premul... | |
1223 * | |
1224 * To that end, this method asserts that the resulting pmcolor will be valid, b
ut does not call | |
1225 * SkPMFloat::isValid(), as that would fire sometimes, but not result in a bad
pixel. | |
1226 */ | |
1227 static inline SkPMFloat check_as_pmfloat(const Sk4f& value) { | |
1228 SkPMFloat pm = value; | |
1229 #ifdef SK_DEBUG | |
1230 (void)pm.round(); | |
1231 #endif | |
1232 return pm; | |
1233 } | |
1234 | |
1235 #define XFERMODE(Name) \ | 1184 #define XFERMODE(Name) \ |
1236 struct Name { \ | 1185 struct Name { \ |
1237 static Sk4px Xfer(const Sk4px&, const Sk4px&); \ | 1186 static Sk4px Xfer(const Sk4px&, const Sk4px&); \ |
1238 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \ | 1187 static const SkXfermode::Mode kMode = SkXfermode::k##Name##_Mode; \ |
1239 }; \ | 1188 }; \ |
1240 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d) | 1189 inline Sk4px Name::Xfer(const Sk4px& s, const Sk4px& d) |
1241 | 1190 |
1242 XFERMODE(Clear) { return Sk4px((SkPMColor)0); } | 1191 XFERMODE(Clear) { return Sk4px((SkPMColor)0); } |
1243 XFERMODE(Src) { return s; } | 1192 XFERMODE(Src) { return s; } |
1244 XFERMODE(Dst) { return d; } | 1193 XFERMODE(Dst) { return d; } |
1245 XFERMODE(SrcIn) { return s.fastMulDiv255Round(d.alphas() ); } | 1194 XFERMODE(SrcIn) { return s.fastMulDiv255Round(d.alphas() ); } |
1246 XFERMODE(SrcOut) { return s.fastMulDiv255Round(d.alphas().inv()); } | 1195 XFERMODE(SrcOut) { return s.fastMulDiv255Round(d.alphas().inv()); } |
1247 XFERMODE(SrcOver) { return s + d.fastMulDiv255Round(s.alphas().inv()); } | 1196 XFERMODE(SrcOver) { return s + d.fastMulDiv255Round(s.alphas().inv()); } |
1248 XFERMODE(DstIn) { return SrcIn ::Xfer(d,s); } | 1197 XFERMODE(DstIn) { return SrcIn ::Xfer(d,s); } |
1249 XFERMODE(DstOut) { return SrcOut ::Xfer(d,s); } | 1198 XFERMODE(DstOut) { return SrcOut ::Xfer(d,s); } |
1250 XFERMODE(DstOver) { return SrcOver::Xfer(d,s); } | 1199 XFERMODE(DstOver) { return SrcOver::Xfer(d,s); } |
1251 | 1200 |
| 1201 // [ S * Da + (1 - Sa) * D] |
| 1202 XFERMODE(SrcATop) { |
| 1203 return Sk4px::Wide(s.mulWiden(d.alphas()) + d.mulWiden(s.alphas().inv())) |
| 1204 .div255RoundNarrow(); |
| 1205 } |
| 1206 XFERMODE(DstATop) { return SrcATop::Xfer(d,s); } |
| 1207 //[ S * (1 - Da) + (1 - Sa) * D ] |
| 1208 XFERMODE(Xor) { |
| 1209 return Sk4px::Wide(s.mulWiden(d.alphas().inv()) + d.mulWiden(s.alphas().inv(
))) |
| 1210 .div255RoundNarrow(); |
| 1211 } |
| 1212 // [S + D ] |
| 1213 XFERMODE(Plus) { return s.saturatedAdd(d); } |
| 1214 // [S * D ] |
| 1215 XFERMODE(Modulate) { return s.fastMulDiv255Round(d); } |
| 1216 // [S + D - S * D] |
| 1217 XFERMODE(Screen) { |
| 1218 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract
can be done |
| 1219 // in 8-bit space without overflow. S + (1-S)*D is a touch faster because i
nv() is cheap. |
| 1220 return s + d.fastMulDiv255Round(s.inv()); |
| 1221 } |
| 1222 XFERMODE(Multiply) { |
| 1223 return Sk4px::Wide(s.mulWiden(d.alphas().inv()) + |
| 1224 d.mulWiden(s.alphas().inv()) + |
| 1225 s.mulWiden(d)) |
| 1226 .div255RoundNarrow(); |
| 1227 } |
| 1228 // [ Sa + Da - Sa*Da, Sc + Dc - 2*min(Sc*Da, Dc*Sa) ] (And notice Sa*Da == min(
Sa*Da, Da*Sa).) |
| 1229 XFERMODE(Difference) { |
| 1230 auto m = Sk4px::Wide(Sk16h::Min(s.mulWiden(d.alphas()), d.mulWiden(s.alphas(
)))) |
| 1231 .div255RoundNarrow(); |
| 1232 // There's no chance of underflow, and if we subtract m before adding s+d, n
o overflow. |
| 1233 return (s - m) + (d - m.zeroAlphas()); |
| 1234 } |
| 1235 // [ Sa + Da - Sa*Da, Sc + Dc - 2*Sc*Dc ] |
| 1236 XFERMODE(Exclusion) { |
| 1237 auto p = s.fastMulDiv255Round(d); |
| 1238 // There's no chance of underflow, and if we subtract p before adding src+ds
t, no overflow. |
| 1239 return (s - p) + (d - p.zeroAlphas()); |
| 1240 } |
| 1241 |
1252 #undef XFERMODE | 1242 #undef XFERMODE |
1253 | 1243 |
1254 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] | |
1255 struct SrcATop4f { | |
1256 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1257 const Sk4f inv255(gInv255); | |
1258 return check_as_pmfloat(dst + (src * Sk4f(dst.a()) - dst * Sk4f(src.a())
) * inv255); | |
1259 } | |
1260 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1261 return Sk4px::Wide(src.mulWiden(dst.alphas()) + dst.mulWiden(src.alphas(
).inv())) | |
1262 .div255RoundNarrow(); | |
1263 } | |
1264 static const bool kFoldCoverageIntoSrcAlpha = true; | |
1265 static const SkXfermode::Mode kMode = SkXfermode::kSrcATop_Mode; | |
1266 }; | |
1267 | |
1268 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] | |
1269 struct DstATop4f { | |
1270 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1271 return SrcATop4f::Xfer(dst, src); | |
1272 } | |
1273 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1274 return SrcATop4f::Xfer(dst, src); | |
1275 } | |
1276 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1277 static const SkXfermode::Mode kMode = SkXfermode::kDstATop_Mode; | |
1278 }; | |
1279 | |
1280 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] | |
1281 struct Xor4f { | |
1282 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1283 const Sk4f inv255(gInv255); | |
1284 return check_as_pmfloat(src + dst - (src * Sk4f(dst.a()) + dst * Sk4f(sr
c.a())) * inv255); | |
1285 } | |
1286 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1287 return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) + dst.mulWiden(src.a
lphas().inv())) | |
1288 .div255RoundNarrow(); | |
1289 } | |
1290 static const bool kFoldCoverageIntoSrcAlpha = true; | |
1291 static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode; | |
1292 }; | |
1293 | |
1294 // kPlus_Mode [Sa + Da, Sc + Dc] | |
1295 struct Plus4f { | |
1296 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1297 return check_as_pmfloat(clamp_255(src + dst)); | |
1298 } | |
1299 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1300 return src.saturatedAdd(dst); | |
1301 } | |
1302 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1303 static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode; | |
1304 }; | |
1305 | |
1306 // kModulate_Mode [Sa * Da, Sc * Dc] | |
1307 struct Modulate4f { | |
1308 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1309 const Sk4f inv255(gInv255); | |
1310 return check_as_pmfloat(src * dst * inv255); | |
1311 } | |
1312 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1313 return src.fastMulDiv255Round(dst); | |
1314 } | |
1315 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1316 static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode; | |
1317 }; | |
1318 | |
1319 // kScreen_Mode [S + D - S * D] | |
1320 struct Screen4f { | |
1321 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1322 const Sk4f inv255(gInv255); | |
1323 return check_as_pmfloat(src + dst - src * dst * inv255); | |
1324 } | |
1325 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1326 // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subt
ract can be done | |
1327 // in 8-bit space without overflow. S + (1-S)*D is a touch faster becau
se inv() is cheap. | |
1328 return src + dst.fastMulDiv255Round(src.inv()); | |
1329 } | |
1330 static const bool kFoldCoverageIntoSrcAlpha = true; | |
1331 static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode; | |
1332 }; | |
1333 | |
1334 struct Multiply4f { | |
1335 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1336 const Sk4f inv255(gInv255); | |
1337 Sk4f sa = Sk4f(src.a()); | |
1338 Sk4f da = Sk4f(dst.a()); | |
1339 Sk4f sc = src; | |
1340 Sk4f dc = dst; | |
1341 Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255; | |
1342 // ra = srcover(sa, da), but the calc for rc happens to accomplish this
for us | |
1343 return check_as_pmfloat(clamp_0_255(rc)); | |
1344 } | |
1345 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1346 return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) + | |
1347 dst.mulWiden(src.alphas().inv()) + | |
1348 src.mulWiden(dst)) | |
1349 .div255RoundNarrow(); | |
1350 } | |
1351 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1352 static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode; | |
1353 }; | |
1354 | |
1355 // [ sa + da - sa*da, sc + dc - 2*min(sc*da, dc*sa) ] (And notice sa*da == min(
sa*da, da*sa).) | |
1356 struct Difference4f { | |
1357 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1358 const Sk4f inv255(gInv255); | |
1359 Sk4f sa = Sk4f(src.a()); | |
1360 Sk4f da = Sk4f(dst.a()); | |
1361 Sk4f sc = src; | |
1362 Sk4f dc = dst; | |
1363 Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255; | |
1364 Sk4f ra = sc + dc - min; | |
1365 return check_as_pmfloat(ra - min * SkPMFloat(0, 1, 1, 1)); | |
1366 } | |
1367 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1368 auto m = Sk4px::Wide(Sk16h::Min(src.mulWiden(dst.alphas()), dst.mulWiden
(src.alphas()))) | |
1369 .div255RoundNarrow(); | |
1370 // There's no chance of underflow, and if we subtract m before adding sr
c+dst, no overflow. | |
1371 return (src - m) + (dst - m.zeroAlphas()); | |
1372 } | |
1373 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1374 static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode; | |
1375 }; | |
1376 | |
1377 // [ sa + da - sa*da, sc + dc - 2*sc*dc ] | |
1378 struct Exclusion4f { | |
1379 static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) { | |
1380 const Sk4f inv255(gInv255); | |
1381 Sk4f sc = src; | |
1382 Sk4f dc = dst; | |
1383 Sk4f prod = sc * dc * inv255; | |
1384 Sk4f ra = sc + dc - prod; | |
1385 return check_as_pmfloat(ra - prod * SkPMFloat(0, 1, 1, 1)); | |
1386 } | |
1387 static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) { | |
1388 auto p = src.fastMulDiv255Round(dst); | |
1389 // There's no chance of underflow, and if we subtract p before adding sr
c+dst, no overflow. | |
1390 return (src - p) + (dst - p.zeroAlphas()); | |
1391 } | |
1392 static const bool kFoldCoverageIntoSrcAlpha = false; | |
1393 static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode; | |
1394 }; | |
1395 | |
1396 template <typename ProcType> | |
1397 class SkT4fXfermode : public SkProcCoeffXfermode { | |
1398 public: | |
1399 static SkXfermode* Create(const ProcCoeff& rec) { | |
1400 return SkNEW_ARGS(SkT4fXfermode, (rec)); | |
1401 } | |
1402 | |
1403 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { | |
1404 if (NULL == aa) { | |
1405 for (int i = 0; i < n; ++i) { | |
1406 dst[i] = ProcType::Xfer(SkPMFloat(src[i]), SkPMFloat(dst[i])).ro
und(); | |
1407 } | |
1408 } else { | |
1409 for (int i = 0; i < n; ++i) { | |
1410 const Sk4f aa4 = Sk4f(aa[i] * gInv255); | |
1411 SkPMFloat dstF(dst[i]); | |
1412 SkPMFloat srcF(src[i]); | |
1413 Sk4f res; | |
1414 if (ProcType::kFoldCoverageIntoSrcAlpha) { | |
1415 Sk4f src4 = srcF; | |
1416 res = ProcType::Xfer(src4 * aa4, dstF); | |
1417 } else { | |
1418 res = ramp(dstF, ProcType::Xfer(srcF, dstF), aa4); | |
1419 } | |
1420 dst[i] = SkPMFloat(res).round(); | |
1421 } | |
1422 } | |
1423 } | |
1424 | |
1425 private: | |
1426 SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMo
de) {} | |
1427 | |
1428 typedef SkProcCoeffXfermode INHERITED; | |
1429 }; | |
1430 | |
1431 template <typename ProcType> | 1244 template <typename ProcType> |
1432 class SkT4pxXfermode : public SkProcCoeffXfermode { | 1245 class SkT4pxXfermode : public SkProcCoeffXfermode { |
1433 public: | 1246 public: |
1434 static SkXfermode* Create(const ProcCoeff& rec) { | 1247 static SkXfermode* Create(const ProcCoeff& rec) { |
1435 return SkNEW_ARGS(SkT4pxXfermode, (rec)); | 1248 return SkNEW_ARGS(SkT4pxXfermode, (rec)); |
1436 } | 1249 } |
1437 | 1250 |
1438 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { | 1251 void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[
]) const override { |
1439 if (NULL == aa) { | 1252 if (NULL == aa) { |
1440 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { | 1253 Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& sr
c4) { |
1441 return ProcType::Xfer(src4, dst4); | 1254 return ProcType::Xfer(src4, dst4); |
1442 }); | 1255 }); |
1443 } else { | 1256 } else { |
1444 Sk4px::MapDstSrcAlpha(n, dst, src, aa, | 1257 Sk4px::MapDstSrcAlpha(n, dst, src, aa, |
1445 [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha
) { | 1258 [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha
) { |
1446 // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=2
4-bit intermediates. | |
1447 Sk4px res4 = ProcType::Xfer(src4, dst4); | 1259 Sk4px res4 = ProcType::Xfer(src4, dst4); |
1448 return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk4px(al
pha).inv())) | 1260 return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk4px(al
pha).inv())) |
1449 .div255RoundNarrow(); | 1261 .div255RoundNarrow(); |
1450 }); | 1262 }); |
1451 } | 1263 } |
1452 } | 1264 } |
1453 | 1265 |
1454 private: | 1266 private: |
1455 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM
ode) {} | 1267 SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kM
ode) {} |
1456 | 1268 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1510 namespace { | 1322 namespace { |
1511 SkXfermode* create_mode(int iMode) { | 1323 SkXfermode* create_mode(int iMode) { |
1512 SkXfermode::Mode mode = (SkXfermode::Mode)iMode; | 1324 SkXfermode::Mode mode = (SkXfermode::Mode)iMode; |
1513 | 1325 |
1514 ProcCoeff rec = gProcCoeffs[mode]; | 1326 ProcCoeff rec = gProcCoeffs[mode]; |
1515 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); | 1327 SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode); |
1516 if (pp != NULL) { | 1328 if (pp != NULL) { |
1517 rec.fProc = pp; | 1329 rec.fProc = pp; |
1518 } | 1330 } |
1519 | 1331 |
1520 #if defined(SK_4PX_XFERMODES_ARE_FAST) && !defined(SK_PREFER_LEGACY_FLOAT_XFERMO
DES) | 1332 #if defined(SK_USE_4PX_XFERMODES) |
1521 switch (mode) { | 1333 switch (mode) { |
1522 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create(
rec); | 1334 case SkXfermode::kClear_Mode: return SkT4pxXfermode<Clear>::Create(
rec); |
1523 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re
c); | 1335 case SkXfermode::kSrc_Mode: return SkT4pxXfermode<Src>::Create(re
c); |
1524 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re
c); | 1336 case SkXfermode::kDst_Mode: return SkT4pxXfermode<Dst>::Create(re
c); |
1525 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat
e(rec); | 1337 case SkXfermode::kSrcOver_Mode: return SkT4pxXfermode<SrcOver>::Creat
e(rec); |
1526 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat
e(rec); | 1338 case SkXfermode::kDstOver_Mode: return SkT4pxXfermode<DstOver>::Creat
e(rec); |
1527 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create(
rec); | 1339 case SkXfermode::kSrcIn_Mode: return SkT4pxXfermode<SrcIn>::Create(
rec); |
1528 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create(
rec); | 1340 case SkXfermode::kDstIn_Mode: return SkT4pxXfermode<DstIn>::Create(
rec); |
1529 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create
(rec); | 1341 case SkXfermode::kSrcOut_Mode: return SkT4pxXfermode<SrcOut>::Create
(rec); |
1530 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create
(rec); | 1342 case SkXfermode::kDstOut_Mode: return SkT4pxXfermode<DstOut>::Create
(rec); |
1531 | 1343 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop>::Creat
e(rec); |
1532 case SkXfermode::kSrcATop_Mode: return SkT4pxXfermode<SrcATop4f>::Cre
ate(rec); | 1344 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop>::Creat
e(rec); |
1533 case SkXfermode::kDstATop_Mode: return SkT4pxXfermode<DstATop4f>::Cre
ate(rec); | 1345 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor>::Create(re
c); |
1534 case SkXfermode::kXor_Mode: return SkT4pxXfermode<Xor4f>::Create(
rec); | 1346 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus>::Create(r
ec); |
1535 case SkXfermode::kPlus_Mode: return SkT4pxXfermode<Plus4f>::Create
(rec); | 1347 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate>::Crea
te(rec); |
1536 case SkXfermode::kModulate_Mode: return SkT4pxXfermode<Modulate4f>::Cr
eate(rec); | 1348 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen>::Create
(rec); |
1537 case SkXfermode::kScreen_Mode: return SkT4pxXfermode<Screen4f>::Crea
te(rec); | 1349 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply>::Crea
te(rec); |
1538 case SkXfermode::kMultiply_Mode: return SkT4pxXfermode<Multiply4f>::Cr
eate(rec); | 1350 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference>::Cr
eate(rec); |
1539 case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference4f>::
Create(rec); | 1351 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion>::Cre
ate(rec); |
1540 case SkXfermode::kExclusion_Mode: return SkT4pxXfermode<Exclusion4f>::C
reate(rec); | |
1541 default: break; | 1352 default: break; |
1542 } | 1353 } |
1543 #endif | 1354 #endif |
1544 | |
1545 #if defined(SK_4F_XFERMODES_ARE_FAST) | |
1546 switch (mode) { | |
1547 case SkXfermode::kSrcATop_Mode: return SkT4fXfermode<SrcATop4f>::Crea
te(rec); | |
1548 case SkXfermode::kDstATop_Mode: return SkT4fXfermode<DstATop4f>::Crea
te(rec); | |
1549 case SkXfermode::kXor_Mode: return SkT4fXfermode<Xor4f>::Create(r
ec); | |
1550 case SkXfermode::kPlus_Mode: return SkT4fXfermode<Plus4f>::Create(
rec); | |
1551 case SkXfermode::kModulate_Mode: return SkT4fXfermode<Modulate4f>::Cre
ate(rec); | |
1552 case SkXfermode::kScreen_Mode: return SkT4fXfermode<Screen4f>::Creat
e(rec); | |
1553 case SkXfermode::kMultiply_Mode: return SkT4fXfermode<Multiply4f>::Cre
ate(rec); | |
1554 case SkXfermode::kDifference_Mode: return SkT4fXfermode<Difference4f>::C
reate(rec); | |
1555 case SkXfermode::kExclusion_Mode: return SkT4fXfermode<Exclusion4f>::Cr
eate(rec); | |
1556 default: break; | |
1557 } | |
1558 #endif | |
1559 | 1355 |
1560 SkXfermode* xfer = NULL; | 1356 SkXfermode* xfer = NULL; |
1561 | 1357 |
1562 // check if we have a platform optim for that | 1358 // check if we have a platform optim for that |
1563 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); | 1359 SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode); |
1564 if (xfm != NULL) { | 1360 if (xfm != NULL) { |
1565 xfer = xfm; | 1361 xfer = xfm; |
1566 } else { | 1362 } else { |
1567 // All modes can in theory be represented by the ProcCoeff rec, since | 1363 // All modes can in theory be represented by the ProcCoeff rec, since |
1568 // it contains function ptrs. However, a few modes are both simple and | 1364 // it contains function ptrs. However, a few modes are both simple and |
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1850 } else { | 1646 } else { |
1851 proc16 = rec.fProc16_General; | 1647 proc16 = rec.fProc16_General; |
1852 } | 1648 } |
1853 } | 1649 } |
1854 return proc16; | 1650 return proc16; |
1855 } | 1651 } |
1856 | 1652 |
1857 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) | 1653 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) |
1858 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) | 1654 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) |
1859 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END | 1655 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END |
OLD | NEW |