avoid unsafe[] in loops
This commit is contained in:
parent
d2b84e76ca
commit
ee442977fa
1 changed files with 110 additions and 63 deletions
|
@ -1336,7 +1336,9 @@ proc fillCoverage(
|
||||||
coverages: seq[uint8],
|
coverages: seq[uint8],
|
||||||
blendMode: BlendMode
|
blendMode: BlendMode
|
||||||
) =
|
) =
|
||||||
var x = startX
|
var
|
||||||
|
x = startX
|
||||||
|
dataIndex = image.dataIndex(x, y)
|
||||||
|
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
|
@ -1389,51 +1391,61 @@ proc fillCoverage(
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
||||||
if not allZeroes:
|
if allZeroes:
|
||||||
|
dataIndex += 16
|
||||||
|
else:
|
||||||
if all255:
|
if all255:
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
mm_storeu_si128(image.unsafe[x + i * 4, y].addr, colorVec)
|
mm_storeu_si128(image.data[dataIndex].addr, colorVec)
|
||||||
|
dataIndex += 4
|
||||||
else:
|
else:
|
||||||
var coverageVec = coverageVec
|
var coverageVec = coverageVec
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
let source = source(colorVec, coverageVec)
|
let source = source(colorVec, coverageVec)
|
||||||
mm_storeu_si128(image.unsafe[x + i * 4, y].addr, source)
|
mm_storeu_si128(image.data[dataIndex].addr, source)
|
||||||
coverageVec = mm_srli_si128(coverageVec, 4)
|
coverageVec = mm_srli_si128(coverageVec, 4)
|
||||||
|
dataIndex += 4
|
||||||
|
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage != 0:
|
if coverage != 0:
|
||||||
image.unsafe[x, y] = source(rgbx, coverage)
|
image.data[dataIndex] = source(rgbx, coverage)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of NormalBlend:
|
of NormalBlend:
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
||||||
if not allZeroes:
|
if allZeroes:
|
||||||
|
dataIndex += 16
|
||||||
|
else:
|
||||||
if all255 and rgbx.a == 255:
|
if all255 and rgbx.a == 255:
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
mm_storeu_si128(image.unsafe[x + i * 4, y].addr, colorVec)
|
mm_storeu_si128(image.data[dataIndex].addr, colorVec)
|
||||||
|
dataIndex += 4
|
||||||
else:
|
else:
|
||||||
var coverageVec = coverageVec
|
var coverageVec = coverageVec
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
let
|
let
|
||||||
backdrop = mm_loadu_si128(image.unsafe[x + i * 4, y].addr)
|
backdrop = mm_loadu_si128(image.data[dataIndex].addr)
|
||||||
source = source(colorVec, coverageVec)
|
source = source(colorVec, coverageVec)
|
||||||
mm_storeu_si128(
|
mm_storeu_si128(
|
||||||
image.unsafe[x + i * 4, y].addr,
|
image.data[dataIndex].addr,
|
||||||
blendNormalSimd(backdrop, source)
|
blendNormalSimd(backdrop, source)
|
||||||
)
|
)
|
||||||
coverageVec = mm_srli_si128(coverageVec, 4)
|
coverageVec = mm_srli_si128(coverageVec, 4)
|
||||||
|
dataIndex += 4
|
||||||
|
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage == 255 and rgbx.a == 255:
|
if coverage == 255 and rgbx.a == 255:
|
||||||
image.unsafe[x, y] = rgbx
|
image.data[dataIndex] = rgbx
|
||||||
elif coverage == 0:
|
elif coverage == 0:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
let backdrop = image.unsafe[x, y]
|
let backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blendNormal(backdrop, source(rgbx, coverage))
|
image.data[dataIndex] = blendNormal(backdrop, source(rgbx, coverage))
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of MaskBlend:
|
of MaskBlend:
|
||||||
{.linearScanEnd.}
|
{.linearScanEnd.}
|
||||||
|
@ -1443,31 +1455,34 @@ proc fillCoverage(
|
||||||
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
for (coverageVec, allZeroes, all255) in simd(coverages, x, startX):
|
||||||
if not allZeroes:
|
if not allZeroes:
|
||||||
if all255:
|
if all255:
|
||||||
discard
|
dataIndex += 16
|
||||||
else:
|
else:
|
||||||
var coverageVec = coverageVec
|
var coverageVec = coverageVec
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
let
|
let
|
||||||
backdrop = mm_loadu_si128(image.unsafe[x + i * 4, y].addr)
|
backdrop = mm_loadu_si128(image.data[dataIndex].addr)
|
||||||
source = source(colorVec, coverageVec)
|
source = source(colorVec, coverageVec)
|
||||||
mm_storeu_si128(
|
mm_storeu_si128(
|
||||||
image.unsafe[x + i * 4, y].addr,
|
image.data[dataIndex].addr,
|
||||||
blendMaskSimd(backdrop, source)
|
blendMaskSimd(backdrop, source)
|
||||||
)
|
)
|
||||||
coverageVec = mm_srli_si128(coverageVec, 4)
|
coverageVec = mm_srli_si128(coverageVec, 4)
|
||||||
|
dataIndex += 4
|
||||||
else:
|
else:
|
||||||
for i in 0 ..< 4:
|
for i in 0 ..< 4:
|
||||||
mm_storeu_si128(image.unsafe[x + i * 4, y].addr, mm_setzero_si128())
|
mm_storeu_si128(image.data[dataIndex].addr, mm_setzero_si128())
|
||||||
|
dataIndex += 4
|
||||||
|
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage == 0:
|
if coverage == 0:
|
||||||
image.unsafe[x, y] = rgbx(0, 0, 0, 0)
|
image.data[dataIndex] = rgbx(0, 0, 0, 0)
|
||||||
elif coverage == 255:
|
elif coverage == 255:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
let backdrop = image.unsafe[x, y]
|
let backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blendMask(backdrop, source(rgbx, coverage))
|
image.data[dataIndex] = blendMask(backdrop, source(rgbx, coverage))
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
image.clearUnsafe(0, y, startX, y)
|
image.clearUnsafe(0, y, startX, y)
|
||||||
image.clearUnsafe(startX + coverages.len, y, image.width, y)
|
image.clearUnsafe(startX + coverages.len, y, image.width, y)
|
||||||
|
@ -1476,25 +1491,28 @@ proc fillCoverage(
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage == 255 and rgbx.a == 255:
|
if coverage == 255 and rgbx.a == 255:
|
||||||
image.unsafe[x, y] = rgbx(0, 0, 0, 0)
|
image.data[dataIndex] = rgbx(0, 0, 0, 0)
|
||||||
elif coverage != 0:
|
elif coverage != 0:
|
||||||
let backdrop = image.unsafe[x, y]
|
let backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blendSubtractMask(backdrop, source(rgbx, coverage))
|
image.data[dataIndex] = blendSubtractMask(backdrop, source(rgbx, coverage))
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of ExcludeMaskBlend:
|
of ExcludeMaskBlend:
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let
|
let
|
||||||
coverage = coverages[x - startX]
|
coverage = coverages[x - startX]
|
||||||
backdrop = image.unsafe[x, y]
|
backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blendExcludeMask(backdrop, source(rgbx, coverage))
|
image.data[dataIndex] = blendExcludeMask(backdrop, source(rgbx, coverage))
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
else:
|
else:
|
||||||
let blender = blendMode.blender()
|
let blender = blendMode.blender()
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage != 0:
|
if coverage != 0:
|
||||||
let backdrop = image.unsafe[x, y]
|
let backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blender(backdrop, source(rgbx, coverage))
|
image.data[dataIndex] = blender(backdrop, source(rgbx, coverage))
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
proc fillCoverage(
|
proc fillCoverage(
|
||||||
mask: Mask,
|
mask: Mask,
|
||||||
|
@ -1502,7 +1520,9 @@ proc fillCoverage(
|
||||||
coverages: seq[uint8],
|
coverages: seq[uint8],
|
||||||
blendMode: BlendMode
|
blendMode: BlendMode
|
||||||
) =
|
) =
|
||||||
var x = startX
|
var
|
||||||
|
x = startX
|
||||||
|
dataIndex = mask.dataIndex(x, y)
|
||||||
|
|
||||||
template simdBlob(blendProc: untyped) =
|
template simdBlob(blendProc: untyped) =
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
|
@ -1513,19 +1533,21 @@ proc fillCoverage(
|
||||||
eqZero = mm_cmpeq_epi8(coveragesVec, mm_setzero_si128())
|
eqZero = mm_cmpeq_epi8(coveragesVec, mm_setzero_si128())
|
||||||
allZeroes = mm_movemask_epi8(eqZero) == 0xffff
|
allZeroes = mm_movemask_epi8(eqZero) == 0xffff
|
||||||
if not allZeroes:
|
if not allZeroes:
|
||||||
let backdrop = mm_loadu_si128(mask.unsafe[x, y].addr)
|
let backdrop = mm_loadu_si128(mask.data[dataIndex].addr)
|
||||||
mm_storeu_si128(
|
mm_storeu_si128(
|
||||||
mask.unsafe[x, y].addr,
|
mask.data[dataIndex].addr,
|
||||||
blendProc(backdrop, coveragesVec)
|
blendProc(backdrop, coveragesVec)
|
||||||
)
|
)
|
||||||
x += 16
|
x += 16
|
||||||
|
dataIndex += 16
|
||||||
|
|
||||||
template blendBlob(blendProc: untyped) =
|
template blendBlob(blendProc: untyped) =
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage != 0:
|
if coverage != 0:
|
||||||
let backdrop = mask.unsafe[x, y]
|
let backdrop = mask.data[dataIndex]
|
||||||
mask.unsafe[x, y] = blendProc(backdrop, coverage)
|
mask.data[dataIndex] = blendProc(backdrop, coverage)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
case blendMode:
|
case blendMode:
|
||||||
of OverwriteBlend:
|
of OverwriteBlend:
|
||||||
|
@ -1550,22 +1572,24 @@ proc fillCoverage(
|
||||||
eqZero = mm_cmpeq_epi8(coveragesVec, mm_setzero_si128())
|
eqZero = mm_cmpeq_epi8(coveragesVec, mm_setzero_si128())
|
||||||
allZeroes = mm_movemask_epi8(eqZero) == 0xffff
|
allZeroes = mm_movemask_epi8(eqZero) == 0xffff
|
||||||
if not allZeroes:
|
if not allZeroes:
|
||||||
let backdrop = mm_loadu_si128(mask.unsafe[x, y].addr)
|
let backdrop = mm_loadu_si128(mask.data[dataIndex].addr)
|
||||||
mm_storeu_si128(
|
mm_storeu_si128(
|
||||||
mask.unsafe[x, y].addr,
|
mask.data[dataIndex].addr,
|
||||||
maskBlendMaskSimd(backdrop, coveragesVec)
|
maskBlendMaskSimd(backdrop, coveragesVec)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
mm_storeu_si128(mask.unsafe[x, y].addr, mm_setzero_si128())
|
mm_storeu_si128(mask.data[dataIndex].addr, mm_setzero_si128())
|
||||||
x += 16
|
x += 16
|
||||||
|
dataIndex += 16
|
||||||
|
|
||||||
for x in x ..< startX + coverages.len:
|
for x in x ..< startX + coverages.len:
|
||||||
let coverage = coverages[x - startX]
|
let coverage = coverages[x - startX]
|
||||||
if coverage != 0:
|
if coverage != 0:
|
||||||
let backdrop = mask.unsafe[x, y]
|
let backdrop = mask.data[dataIndex]
|
||||||
mask.unsafe[x, y] = maskBlendMask(backdrop, coverage)
|
mask.data[dataIndex] = maskBlendMask(backdrop, coverage)
|
||||||
else:
|
else:
|
||||||
mask.unsafe[x, y] = 0
|
mask.data[dataIndex] = 0
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
mask.clearUnsafe(0, y, startX, y)
|
mask.clearUnsafe(0, y, startX, y)
|
||||||
mask.clearUnsafe(startX + coverages.len, y, mask.width, y)
|
mask.clearUnsafe(startX + coverages.len, y, mask.width, y)
|
||||||
|
@ -1595,10 +1619,15 @@ proc fillHits(
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
let colorVec = mm_set1_epi32(cast[int32](rgbx))
|
let colorVec = mm_set1_epi32(cast[int32](rgbx))
|
||||||
|
var dataIndex = image.dataIndex(x, y)
|
||||||
for _ in 0 ..< len div 4:
|
for _ in 0 ..< len div 4:
|
||||||
let backdrop = mm_loadu_si128(image.unsafe[x, y].addr)
|
let backdrop = mm_loadu_si128(image.data[dataIndex].addr)
|
||||||
mm_storeu_si128(image.unsafe[x, y].addr, blendProc(backdrop, colorVec))
|
mm_storeu_si128(
|
||||||
|
image.data[dataIndex].addr,
|
||||||
|
blendProc(backdrop, colorVec)
|
||||||
|
)
|
||||||
x += 4
|
x += 4
|
||||||
|
dataIndex += 4
|
||||||
|
|
||||||
case blendMode:
|
case blendMode:
|
||||||
of OverwriteBlend:
|
of OverwriteBlend:
|
||||||
|
@ -1612,9 +1641,11 @@ proc fillHits(
|
||||||
else:
|
else:
|
||||||
var x = start
|
var x = start
|
||||||
simdBlob(image, x, len, blendNormalSimd)
|
simdBlob(image, x, len, blendNormalSimd)
|
||||||
for x in x ..< start + len:
|
var dataIndex = image.dataIndex(x, y)
|
||||||
let backdrop = image.unsafe[x, y]
|
for _ in x ..< start + len:
|
||||||
image.unsafe[x, y] = blendNormal(backdrop, rgbx)
|
let backdrop = image.data[dataIndex]
|
||||||
|
image.data[dataIndex] = blendNormal(backdrop, rgbx)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of MaskBlend:
|
of MaskBlend:
|
||||||
{.linearScanEnd.}
|
{.linearScanEnd.}
|
||||||
|
@ -1635,34 +1666,41 @@ proc fillHits(
|
||||||
if rgbx.a != 255:
|
if rgbx.a != 255:
|
||||||
var x = start
|
var x = start
|
||||||
simdBlob(image, x, len, blendMaskSimd)
|
simdBlob(image, x, len, blendMaskSimd)
|
||||||
for x in x ..< start + len:
|
var dataIndex = image.dataIndex(x, y)
|
||||||
let backdrop = image.unsafe[x, y]
|
for _ in x ..< start + len:
|
||||||
image.unsafe[x, y] = blendMask(backdrop, rgbx)
|
let backdrop = image.data[dataIndex]
|
||||||
|
image.data[dataIndex] = blendMask(backdrop, rgbx)
|
||||||
|
|
||||||
image.clearUnsafe(0, y, startX, y)
|
image.clearUnsafe(0, y, startX, y)
|
||||||
image.clearUnsafe(filledTo, y, image.width, y)
|
image.clearUnsafe(filledTo, y, image.width, y)
|
||||||
|
|
||||||
of SubtractMaskBlend:
|
of SubtractMaskBlend:
|
||||||
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
||||||
for x in start ..< start + len:
|
var dataIndex = image.dataIndex(start, y)
|
||||||
|
for _ in 0 ..< len:
|
||||||
if rgbx.a == 255:
|
if rgbx.a == 255:
|
||||||
image.unsafe[x, y] = rgbx(0, 0, 0, 0)
|
image.data[dataIndex] = rgbx(0, 0, 0, 0)
|
||||||
else:
|
else:
|
||||||
let backdrop = image.unsafe[x, y]
|
let backdrop = image.data[dataIndex]
|
||||||
image.unsafe[x, y] = blendSubtractMask(backdrop, rgbx)
|
image.data[dataIndex] = blendSubtractMask(backdrop, rgbx)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of ExcludeMaskBlend:
|
of ExcludeMaskBlend:
|
||||||
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
||||||
for x in start ..< start + len:
|
var dataIndex = image.dataIndex(start, y)
|
||||||
let backdrop = image.unsafe[x, y]
|
for _ in 0 ..< len:
|
||||||
image.unsafe[x, y] = blendExcludeMask(backdrop, rgbx)
|
let backdrop = image.data[dataIndex]
|
||||||
|
image.data[dataIndex] = blendExcludeMask(backdrop, rgbx)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
else:
|
else:
|
||||||
let blender = blendMode.blender()
|
let blender = blendMode.blender()
|
||||||
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
for (start, len) in hits.walkInteger(numHits, windingRule, y, image.width):
|
||||||
for x in start ..< start + len:
|
var dataIndex = image.dataIndex(start, y)
|
||||||
let backdrop = image.unsafe[x, y]
|
for _ in 0 ..< len:
|
||||||
image.unsafe[x, y] = blender(backdrop, rgbx)
|
let backdrop = image.data[dataIndex]
|
||||||
|
image.data[dataIndex] = blender(backdrop, rgbx)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
proc fillHits(
|
proc fillHits(
|
||||||
mask: Mask,
|
mask: Mask,
|
||||||
|
@ -1676,10 +1714,15 @@ proc fillHits(
|
||||||
when allowSimd:
|
when allowSimd:
|
||||||
when defined(amd64):
|
when defined(amd64):
|
||||||
let vec255 = mm_set1_epi8(255)
|
let vec255 = mm_set1_epi8(255)
|
||||||
|
var dataIndex = mask.dataIndex(x, y)
|
||||||
for _ in 0 ..< len div 16:
|
for _ in 0 ..< len div 16:
|
||||||
let backdrop = mm_loadu_si128(mask.unsafe[x, y].addr)
|
let backdrop = mm_loadu_si128(mask.data[dataIndex].addr)
|
||||||
mm_storeu_si128(mask.unsafe[x, y].addr, blendProc(backdrop, vec255))
|
mm_storeu_si128(
|
||||||
|
mask.data[dataIndex].addr,
|
||||||
|
blendProc(backdrop, vec255)
|
||||||
|
)
|
||||||
x += 16
|
x += 16
|
||||||
|
dataIndex += 16
|
||||||
|
|
||||||
case blendMode:
|
case blendMode:
|
||||||
of NormalBlend, OverwriteBlend:
|
of NormalBlend, OverwriteBlend:
|
||||||
|
@ -1703,17 +1746,21 @@ proc fillHits(
|
||||||
for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
|
for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
|
||||||
var x = start
|
var x = start
|
||||||
simdBlob(mask, x, len, maskBlendSubtractSimd)
|
simdBlob(mask, x, len, maskBlendSubtractSimd)
|
||||||
for x in x ..< start + len:
|
var dataIndex = mask.dataIndex(x, y)
|
||||||
let backdrop = mask.unsafe[x, y]
|
for _ in x ..< start + len:
|
||||||
mask.unsafe[x, y] = maskBlendSubtract(backdrop, 255)
|
let backdrop = mask.data[dataIndex]
|
||||||
|
mask.data[dataIndex] = maskBlendSubtract(backdrop, 255)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
of ExcludeMaskBlend:
|
of ExcludeMaskBlend:
|
||||||
for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
|
for (start, len) in hits.walkInteger(numHits, windingRule, y, mask.width):
|
||||||
var x = start
|
var x = start
|
||||||
simdBlob(mask, x, len, maskBlendExcludeSimd)
|
simdBlob(mask, x, len, maskBlendExcludeSimd)
|
||||||
for x in x ..< start + len:
|
var dataIndex = mask.dataIndex(x, y)
|
||||||
let backdrop = mask.unsafe[x, y]
|
for _ in x ..< start + len:
|
||||||
mask.unsafe[x, y] = maskBlendExclude(backdrop, 255)
|
let backdrop = mask.data[dataIndex]
|
||||||
|
mask.data[dataIndex] = maskBlendExclude(backdrop, 255)
|
||||||
|
inc dataIndex
|
||||||
|
|
||||||
else:
|
else:
|
||||||
failUnsupportedBlendMode(blendMode)
|
failUnsupportedBlendMode(blendMode)
|
||||||
|
|
Loading…
Reference in a new issue