Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 2 additions & 64 deletions experiments/bench_cairo_draw.nim
Original file line number Diff line number Diff line change
@@ -1,39 +1,4 @@
import benchy, cairo, pixie, pixie/blends, pixie/internal

when defined(amd64) and not defined(pixieNoSimd):
import nimsimd/sse2

when defined(release):
{.push checks: off.}

proc drawBasic(backdrop, source: Image) =
for y in 0 ..< min(backdrop.height, source.height):
if isOpaque(source.data, source.dataIndex(0, y), source.width):
copyMem(
backdrop.data[backdrop.dataIndex(0, y)].addr,
source.data[source.dataIndex(0, y)].addr,
min(backdrop.width, source.width) * 4
)
else:
var x: int
when defined(amd64) and not defined(pixieNoSimd):
let vec255 = mm_set1_epi32(cast[int32](uint32.high))
for _ in 0 ..< min(backdrop.width, source.width) div 4:
let sourceVec = mm_loadu_si128(source.data[source.dataIndex(x, y)].addr)
if mm_movemask_epi8(mm_cmpeq_epi8(sourceVec, mm_setzero_si128())) != 0xffff:
if (mm_movemask_epi8(mm_cmpeq_epi8(sourceVec, vec255)) and 0x8888) == 0x8888:
mm_storeu_si128(backdrop.data[backdrop.dataIndex(x, y)].addr, sourceVec)
else:
let backdropVec = mm_loadu_si128(backdrop.data[backdrop.dataIndex(x, y)].addr)
mm_storeu_si128(
backdrop.data[backdrop.dataIndex(x, y)].addr,
blendNormalInlineSimd(backdropVec, sourceVec)
)
x += 4
# No scalar for now

when defined(release):
{.pop.}
import benchy, cairo, pixie

block:
let
Expand All @@ -43,12 +8,6 @@ block:
ctx = tmp.create()

timeIt "cairo draw normal":
# ctx.setSourceRgba(0.5, 0.5, 0.5, 1)
# let operator = ctx.getOperator()
# ctx.setOperator(OperatorSource)
# ctx.paint()
# ctx.setOperator(operator)

ctx.setSource(backdrop, 0, 0)
ctx.paint()
ctx.setSource(source, 0, 0)
Expand All @@ -64,7 +23,6 @@ block:
tmp = newImage(1568, 940)

timeIt "pixie draw normal":
# tmp.fill(rgbx(127, 127, 127, 255))
tmp.draw(backdrop)
tmp.draw(source)

Expand All @@ -77,25 +35,11 @@ block:
tmp = newImage(1568, 940)

timeIt "pixie draw overwrite":
# tmp.fill(rgbx(127, 127, 127, 255))
tmp.draw(backdrop, blendMode = OverwriteBlend)
tmp.draw(source)

# tmp.writeFile("tmp2.png")

block:
let
backdrop = readImage("tests/fileformats/svg/masters/dragon2.png")
source = readImage("tests/fileformats/svg/masters/Ghostscript_Tiger.png")
tmp = newImage(1568, 940)

timeIt "pixie draw basic":
# tmp.fill(rgbx(127, 127, 127, 255))
tmp.drawBasic(backdrop)
tmp.drawBasic(source)

# tmp.writeFile("tmp2.png")

block:
let
backdrop = imageSurfaceCreateFromPng("tests/fileformats/svg/masters/dragon2.png")
Expand All @@ -104,17 +48,11 @@ block:
ctx = tmp.create()

timeIt "cairo draw mask":
ctx.setSourceRgba(1, 1, 1, 1)
let operator = ctx.getOperator()
ctx.setOperator(OperatorSource)
ctx.paint()
ctx.setOperator(operator)

ctx.setSource(backdrop, 0, 0)
ctx.mask(source, 0, 0)
tmp.flush()

# echo tmp.writeToPng("tmp_masked.png")
# tmp.writeToPng("tmp_masked.png")

block:
let
Expand Down
79 changes: 1 addition & 78 deletions src/pixie/blends.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Blending modes.

import chroma, common, simd, std/math
import chroma, common, std/math

# See https://www.w3.org/TR/compositing-1/
# See https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_blend_equation_advanced.txt
Expand Down Expand Up @@ -412,82 +412,5 @@ proc blender*(blendMode: BlendMode): Blender {.raises: [].} =
of SubtractMaskBlend: subtractMaskBlender
of ExcludeMaskBlend: excludeMaskBlender

when defined(amd64) and allowSimd:
type
BlenderSimd* = proc(blackdrop, source: M128i): M128i {.gcsafe, raises: [].}
## Function signature returned by blenderSimd.

proc blendNormalSimd*(backdrop, source: M128i): M128i {.inline.} =
let
alphaMask = mm_set1_epi32(cast[int32](0xff000000))
oddMask = mm_set1_epi16(cast[int16](0xff00))
div255 = mm_set1_epi16(cast[int16](0x8081))

var
sourceAlpha = mm_and_si128(source, alphaMask)
backdropEven = mm_slli_epi16(backdrop, 8)
backdropOdd = mm_and_si128(backdrop, oddMask)

sourceAlpha = mm_or_si128(sourceAlpha, mm_srli_epi32(sourceAlpha, 16))

let k = mm_sub_epi32(
mm_set1_epi32(cast[int32]([0.uint8, 255, 0, 255])),
sourceAlpha
)

backdropEven = mm_mulhi_epu16(backdropEven, k)
backdropOdd = mm_mulhi_epu16(backdropOdd, k)

backdropEven = mm_srli_epi16(mm_mulhi_epu16(backdropEven, div255), 7)
backdropOdd = mm_srli_epi16(mm_mulhi_epu16(backdropOdd, div255), 7)

mm_add_epi8(
source,
mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))
)

proc blendMaskSimd*(backdrop, source: M128i): M128i {.inline.} =
let
alphaMask = mm_set1_epi32(cast[int32](0xff000000))
oddMask = mm_set1_epi16(cast[int16](0xff00))
div255 = mm_set1_epi16(cast[int16](0x8081))

var
sourceAlpha = mm_and_si128(source, alphaMask)
backdropEven = mm_slli_epi16(backdrop, 8)
backdropOdd = mm_and_si128(backdrop, oddMask)

sourceAlpha = mm_or_si128(sourceAlpha, mm_srli_epi32(sourceAlpha, 16))

backdropEven = mm_mulhi_epu16(backdropEven, sourceAlpha)
backdropOdd = mm_mulhi_epu16(backdropOdd, sourceAlpha)

backdropEven = mm_srli_epi16(mm_mulhi_epu16(backdropEven, div255), 7)
backdropOdd = mm_srli_epi16(mm_mulhi_epu16(backdropOdd, div255), 7)

mm_or_si128(backdropEven, mm_slli_epi16(backdropOdd, 8))

proc normalSimdBlender(backdrop, source: M128i): M128i =
blendNormalSimd(backdrop, source)

proc maskSimdBlender(backdrop, source: M128i): M128i =
blendMaskSimd(backdrop, source)

proc overwriteSimdBlender(backdrop, source: M128i): M128i =
source

proc blenderSimd*(blendMode: BlendMode): BlenderSimd {.raises: [PixieError].} =
## Returns a blend function for a given blend mode with SIMD support.
case blendMode:
of NormalBlend: normalSimdBlender
of MaskBlend: maskSimdBlender
of OverwriteBlend: overwriteSimdBlender
else:
raise newException(PixieError, "No SIMD blender for " & $blendMode)

proc hasSimdBlender*(blendMode: BlendMode): bool {.inline, raises: [].} =
## Is there a blend function for a given blend mode with SIMD support?
blendMode in {NormalBlend, MaskBlend, OverwriteBlend}

when defined(release):
{.pop.}
Loading