Commit 40a1516a authored by Nigel Tao's avatar Nigel Tao

image/draw: fix double-draw when the dst is paletted.

The second (fallback) draw is a no-op, but it's a non-trivial amount of work.

Fixes #11550.

benchmark               old ns/op     new ns/op     delta
BenchmarkPaletted-4     16301219      7309568       -55.16%

Change-Id: Ic88c537b2b0c710cf517888f3dd15cb702dd142f
Reviewed-on: https://go-review.googlesource.com/11858Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
parent 09b5463d
...@@ -7,6 +7,7 @@ package draw ...@@ -7,6 +7,7 @@ package draw
import ( import (
"image" "image"
"image/color" "image/color"
"reflect"
"testing" "testing"
) )
...@@ -15,6 +16,11 @@ const ( ...@@ -15,6 +16,11 @@ const (
srcw, srch = 400, 300 srcw, srch = 400, 300
) )
var palette = color.Palette{
color.Black,
color.White,
}
// bench benchmarks drawing src and mask images onto a dst image with the // bench benchmarks drawing src and mask images onto a dst image with the
// given op and the color models to create those images from. // given op and the color models to create those images from.
// The created images' pixels are initialized to non-zero values. // The created images' pixels are initialized to non-zero values.
...@@ -50,8 +56,20 @@ func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) { ...@@ -50,8 +56,20 @@ func bench(b *testing.B, dcm, scm, mcm color.Model, op Op) {
} }
dst = dst1 dst = dst1
default: default:
// The == operator isn't defined on a color.Palette (a slice), so we
// use reflection.
if reflect.DeepEqual(dcm, palette) {
dst1 := image.NewPaletted(image.Rect(0, 0, dstw, dsth), palette)
for y := 0; y < dsth; y++ {
for x := 0; x < dstw; x++ {
dst1.SetColorIndex(x, y, uint8(x^y)&1)
}
}
dst = dst1
} else {
b.Fatal("unknown destination color model", dcm) b.Fatal("unknown destination color model", dcm)
} }
}
var src image.Image var src image.Image
switch scm { switch scm {
...@@ -218,6 +236,10 @@ func BenchmarkRGBA(b *testing.B) { ...@@ -218,6 +236,10 @@ func BenchmarkRGBA(b *testing.B) {
bench(b, color.RGBAModel, color.RGBA64Model, nil, Src) bench(b, color.RGBAModel, color.RGBA64Model, nil, Src)
} }
func BenchmarkPaletted(b *testing.B) {
bench(b, palette, color.RGBAModel, nil, Src)
}
// The BenchmarkGenericFoo functions exercise the generic, slow-path code. // The BenchmarkGenericFoo functions exercise the generic, slow-path code.
func BenchmarkGenericOver(b *testing.B) { func BenchmarkGenericOver(b *testing.B) {
......
...@@ -176,6 +176,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas ...@@ -176,6 +176,7 @@ func DrawMask(dst Image, r image.Rectangle, src image.Image, sp image.Point, mas
case *image.Paletted: case *image.Paletted:
if op == Src && mask == nil && !processBackward(dst, r, src, sp) { if op == Src && mask == nil && !processBackward(dst, r, src, sp) {
drawPaletted(dst0, r, src, sp, false) drawPaletted(dst0, r, src, sp, false)
return
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment