vector: add a fast path for RGBA dst images.
name old time/op new time/op delta GlyphRGBA16Over-8 25.1µs ± 2% 6.0µs ± 0% -76.09% (p=0.000 n=10+10) GlyphRGBA16Src-8 17.3µs ± 2% 5.4µs ± 0% -68.68% (p=0.000 n=10+10) GlyphRGBA32Over-8 93.2µs ± 2% 14.5µs ± 0% -84.41% (p=0.000 n=10+10) GlyphRGBA32Src-8 59.3µs ± 2% 12.4µs ± 0% -79.04% (p=0.000 n=9+9) GlyphRGBA64Over-8 350µs ± 2% 45µs ± 0% -87.21% (p=0.000 n=9+9) GlyphRGBA64Src-8 223µs ± 2% 37µs ± 0% -83.58% (p=0.000 n=9+9) GlyphRGBA128Over-8 1.37ms ± 2% 0.16ms ± 1% -88.19% (p=0.000 n=9+10) GlyphRGBA128Src-8 868µs ± 2% 128µs ± 0% -85.21% (p=0.000 n=10+9) GlyphRGBA256Over-8 5.50ms ± 3% 0.59ms ± 0% -89.31% (p=0.000 n=10+10) GlyphRGBA256Src-8 3.47ms ± 2% 0.45ms ± 0% -86.91% (p=0.000 n=9+10) Change-Id: I3df60e6b7147872367715361c9d1ed52951b22e0 Reviewed-on: https://go-review.googlesource.com/29699 Reviewed-by: David Crawshaw <crawshaw@golang.org>
This commit is contained in:
parent
0080ac3d2c
commit
14bbbc8017
|
@ -228,7 +228,7 @@ func (z *Rasterizer) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp
|
|||
// r.Add(sp.Sub(r.Min)).
|
||||
|
||||
if src, ok := src.(*image.Uniform); ok {
|
||||
_, _, _, srcA := src.RGBA()
|
||||
srcR, srcG, srcB, srcA := src.RGBA()
|
||||
switch dst := dst.(type) {
|
||||
case *image.Alpha:
|
||||
// Fast path for glyph rendering.
|
||||
|
@ -240,6 +240,13 @@ func (z *Rasterizer) Draw(dst draw.Image, r image.Rectangle, src image.Image, sp
|
|||
}
|
||||
return
|
||||
}
|
||||
case *image.RGBA:
|
||||
if z.DrawOp == draw.Over {
|
||||
z.rasterizeDstRGBASrcUniformOpOver(dst, r, srcR, srcG, srcB, srcA)
|
||||
} else {
|
||||
z.rasterizeDstRGBASrcUniformOpSrc(dst, r, srcR, srcG, srcB, srcA)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -309,6 +316,43 @@ func (z *Rasterizer) rasterizeDstAlphaSrcOpaqueOpSrc(dst *image.Alpha, r image.R
|
|||
}
|
||||
}
|
||||
|
||||
func (z *Rasterizer) rasterizeDstRGBASrcUniformOpOver(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
|
||||
z.accumulateMask()
|
||||
pix := dst.Pix[dst.PixOffset(r.Min.X, r.Min.Y):]
|
||||
for y, y1 := 0, r.Max.Y-r.Min.Y; y < y1; y++ {
|
||||
for x, x1 := 0, r.Max.X-r.Min.X; x < x1; x++ {
|
||||
ma := z.bufU32[y*z.size.X+x]
|
||||
|
||||
// This formula is like rasterizeOpOver's, simplified for the
|
||||
// concrete dst type and uniform src assumption.
|
||||
a := 0xffff - (sa * ma / 0xffff)
|
||||
i := y*dst.Stride + 4*x
|
||||
pix[i+0] = uint8(((uint32(pix[i+0])*0x101*a + sr*ma) / 0xffff) >> 8)
|
||||
pix[i+1] = uint8(((uint32(pix[i+1])*0x101*a + sg*ma) / 0xffff) >> 8)
|
||||
pix[i+2] = uint8(((uint32(pix[i+2])*0x101*a + sb*ma) / 0xffff) >> 8)
|
||||
pix[i+3] = uint8(((uint32(pix[i+3])*0x101*a + sa*ma) / 0xffff) >> 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Rasterizer) rasterizeDstRGBASrcUniformOpSrc(dst *image.RGBA, r image.Rectangle, sr, sg, sb, sa uint32) {
|
||||
z.accumulateMask()
|
||||
pix := dst.Pix[dst.PixOffset(r.Min.X, r.Min.Y):]
|
||||
for y, y1 := 0, r.Max.Y-r.Min.Y; y < y1; y++ {
|
||||
for x, x1 := 0, r.Max.X-r.Min.X; x < x1; x++ {
|
||||
ma := z.bufU32[y*z.size.X+x]
|
||||
|
||||
// This formula is like rasterizeOpSrc's, simplified for the
|
||||
// concrete dst type and uniform src assumption.
|
||||
i := y*dst.Stride + 4*x
|
||||
pix[i+0] = uint8((sr * ma / 0xffff) >> 8)
|
||||
pix[i+1] = uint8((sg * ma / 0xffff) >> 8)
|
||||
pix[i+2] = uint8((sb * ma / 0xffff) >> 8)
|
||||
pix[i+3] = uint8((sa * ma / 0xffff) >> 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Rasterizer) rasterizeOpOver(dst draw.Image, r image.Rectangle, src image.Image, sp image.Point) {
|
||||
z.accumulateMask()
|
||||
out := color.RGBA64{}
|
||||
|
|
Loading…
Reference in New Issue
Block a user