From e11a86dc10c67014290efc32701764c6210a51b1 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Fri, 17 Jun 2022 01:09:30 -0500 Subject: [PATCH] linearScanEnd --- src/pixie/paths.nim | 45 ++++++++++++++++++++++++++++----------- tests/benchmark_paths.nim | 20 +++++++++++++++++ 2 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/pixie/paths.nim b/src/pixie/paths.nim index 5331395..4cbee75 100644 --- a/src/pixie/paths.nim +++ b/src/pixie/paths.nim @@ -1340,6 +1340,19 @@ proc fillCoverage( when allowSimd: when defined(amd64): + iterator simd( + coverages: seq[uint8], x: var int, startX: int + ): (M128i, bool, bool) = + for _ in 0 ..< coverages.len div 16: + let + coverageVec = mm_loadu_si128(coverages[x - startX].unsafeAddr) + eqZero = mm_cmpeq_epi8(coverageVec, mm_setzero_si128()) + eq255 = mm_cmpeq_epi8(coverageVec, mm_set1_epi8(cast[int8](255))) + allZeroes = mm_movemask_epi8(eqZero) == 0xffff + all255 = mm_movemask_epi8(eq255) == 0xffff + yield (coverageVec, allZeroes, all255) + x += 16 + proc source(colorVec, coverageVec: M128i): M128i {.inline.} = let oddMask = mm_set1_epi16(cast[int16](0xff00)) @@ -1357,19 +1370,6 @@ proc fillCoverage( sourceOdd = mm_srli_epi16(mm_mulhi_epu16(sourceOdd, div255), 7) result = mm_or_si128(sourceEven, mm_slli_epi16(sourceOdd, 8)) - iterator simd( - coverages: seq[uint8], x: var int, startX: int - ): (M128i, bool, bool) = - for _ in 0 ..< coverages.len div 16: - let - coverageVec = mm_loadu_si128(coverages[x - startX].unsafeAddr) - eqZero = mm_cmpeq_epi8(coverageVec, mm_setzero_si128()) - eq255 = mm_cmpeq_epi8(coverageVec, mm_set1_epi8(cast[int8](255))) - allZeroes = mm_movemask_epi8(eqZero) == 0xffff - all255 = mm_movemask_epi8(eq255) == 0xffff - yield (coverageVec, allZeroes, all255) - x += 16 - let colorVec = mm_set1_epi32(cast[int32](rgbx)) proc source(rgbx: ColorRGBX, coverage: uint8): ColorRGBX {.inline.} = @@ -1434,6 +1434,8 @@ proc fillCoverage( image.unsafe[x, y] = blendNormal(backdrop, source(rgbx, coverage)) of MaskBlend: + {.linearScanEnd.} + when allowSimd: when defined(amd64): for (coverageVec, allZeroes, all255) in simd(coverages, x, startX): @@ -1611,6 +1613,8 @@ proc fillHits( image.unsafe[x, y] = blendNormal(backdrop, rgbx) of MaskBlend: + {.linearScanEnd.} + var filledTo = startX for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width): block: # Clear any gap between this fill and the previous fill @@ -1634,6 +1638,21 @@ proc fillHits( image.clearUnsafe(0, y, startX, y) image.clearUnsafe(filledTo, y, image.width, y) + of SubtractMaskBlend: + for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width): + for x in start ..< start + len: + if rgbx.a == 255: + image.unsafe[x, y] = rgbx(0, 0, 0, 0) + else: + let backdrop = image.unsafe[x, y] + image.unsafe[x, y] = blendSubtractMask(backdrop, rgbx) + + of ExcludeMaskBlend: + for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width): + for x in start ..< start + len: + let backdrop = image.unsafe[x, y] + image.unsafe[x, y] = blendExcludeMask(backdrop, rgbx) + else: let blender = blendMode.blender() for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width): diff --git a/tests/benchmark_paths.nim b/tests/benchmark_paths.nim index 2cb55ed..f890b48 100644 --- a/tests/benchmark_paths.nim +++ b/tests/benchmark_paths.nim @@ -47,6 +47,16 @@ block: image.fill(rgbx(255, 255, 255, 255)) image.fillPath(rect, paint) + timeIt "rect Image SubtractMaskBlend": + paint.blendMode = SubtractMaskBlend + image.fill(rgbx(255, 255, 255, 255)) + image.fillPath(rect, paint) + + timeIt "rect Image ExcludeMaskBlend": + paint.blendMode = ExcludeMaskBlend + image.fill(rgbx(255, 255, 255, 255)) + image.fillPath(rect, paint) + timeIt "roundedRect Image OverwriteBlend": paint.blendMode = OverwriteBlend image.fillPath(roundedRect, paint) @@ -60,6 +70,16 @@ block: image.fill(rgbx(255, 255, 255, 255)) image.fillPath(roundedRect, paint) + timeIt "roundedRect Image SubtractMaskBlend": + paint.blendMode = SubtractMaskBlend + image.fill(rgbx(255, 255, 255, 255)) + image.fillPath(roundedRect, paint) + + timeIt "roundedRect Image ExcludeMaskBlend": + paint.blendMode = ExcludeMaskBlend + image.fill(rgbx(255, 255, 255, 255)) + image.fillPath(roundedRect, paint) + block: let mask = newMask(width, height)