]> Cypherpunks repositories - gostls13.git/commitdiff
image/draw: optimize out some bounds checks.
authorNigel Tao <nigeltao@golang.org>
Mon, 31 Aug 2015 03:38:13 +0000 (13:38 +1000)
committerNigel Tao <nigeltao@golang.org>
Tue, 1 Sep 2015 00:34:26 +0000 (00:34 +0000)
We could undoubtedly squeeze even more out of these loops, and in the
long term, a better compiler would be smarter with bounds checks, but in
the short term, this small change is an easy win.

benchmark                      old ns/op     new ns/op     delta
BenchmarkFillOver-8            1619470       1323192       -18.29%
BenchmarkCopyOver-8            1129369       1062787       -5.90%
BenchmarkGlyphOver-8           420070        378608        -9.87%

On github.com/golang/freetype/truetype's BenchmarkDrawString:
benchmark                 old ns/op     new ns/op     delta
BenchmarkDrawString-8     9561435       8807019       -7.89%

Change-Id: Ib1c6271ac18bced85e0fb5ebf250dd57d7747e75
Reviewed-on: https://go-review.googlesource.com/14093
Reviewed-by: Rob Pike <r@golang.org>
src/image/draw/draw.go

index 9419d5e72a757ac798bb51e68d23787d1acba5c9..e47c48d961e96afcb3dbb0902e36689494d9a999 100644 (file)
@@ -240,15 +240,15 @@ func drawFillOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform) {
        i1 := i0 + r.Dx()*4
        for y := r.Min.Y; y != r.Max.Y; y++ {
                for i := i0; i < i1; i += 4 {
-                       dr := uint32(dst.Pix[i+0])
-                       dg := uint32(dst.Pix[i+1])
-                       db := uint32(dst.Pix[i+2])
-                       da := uint32(dst.Pix[i+3])
-
-                       dst.Pix[i+0] = uint8((dr*a/m + sr) >> 8)
-                       dst.Pix[i+1] = uint8((dg*a/m + sg) >> 8)
-                       dst.Pix[i+2] = uint8((db*a/m + sb) >> 8)
-                       dst.Pix[i+3] = uint8((da*a/m + sa) >> 8)
+                       dr := &dst.Pix[i+0]
+                       dg := &dst.Pix[i+1]
+                       db := &dst.Pix[i+2]
+                       da := &dst.Pix[i+3]
+
+                       *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+                       *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+                       *db = uint8((uint32(*db)*a/m + sb) >> 8)
+                       *da = uint8((uint32(*da)*a/m + sa) >> 8)
                }
                i0 += dst.Stride
                i1 += dst.Stride
@@ -310,18 +310,18 @@ func drawCopyOver(dst *image.RGBA, r image.Rectangle, src *image.RGBA, sp image.
                        sb := uint32(spix[i+2]) * 0x101
                        sa := uint32(spix[i+3]) * 0x101
 
-                       dr := uint32(dpix[i+0])
-                       dg := uint32(dpix[i+1])
-                       db := uint32(dpix[i+2])
-                       da := uint32(dpix[i+3])
+                       dr := &dpix[i+0]
+                       dg := &dpix[i+1]
+                       db := &dpix[i+2]
+                       da := &dpix[i+3]
 
                        // The 0x101 is here for the same reason as in drawRGBA.
                        a := (m - sa) * 0x101
 
-                       dpix[i+0] = uint8((dr*a/m + sr) >> 8)
-                       dpix[i+1] = uint8((dg*a/m + sg) >> 8)
-                       dpix[i+2] = uint8((db*a/m + sb) >> 8)
-                       dpix[i+3] = uint8((da*a/m + sa) >> 8)
+                       *dr = uint8((uint32(*dr)*a/m + sr) >> 8)
+                       *dg = uint8((uint32(*dg)*a/m + sg) >> 8)
+                       *db = uint8((uint32(*db)*a/m + sb) >> 8)
+                       *da = uint8((uint32(*da)*a/m + sa) >> 8)
                }
                d0 += ddelta
                s0 += sdelta
@@ -471,18 +471,18 @@ func drawGlyphOver(dst *image.RGBA, r image.Rectangle, src *image.Uniform, mask
                        }
                        ma |= ma << 8
 
-                       dr := uint32(dst.Pix[i+0])
-                       dg := uint32(dst.Pix[i+1])
-                       db := uint32(dst.Pix[i+2])
-                       da := uint32(dst.Pix[i+3])
+                       dr := &dst.Pix[i+0]
+                       dg := &dst.Pix[i+1]
+                       db := &dst.Pix[i+2]
+                       da := &dst.Pix[i+3]
 
                        // The 0x101 is here for the same reason as in drawRGBA.
                        a := (m - (sa * ma / m)) * 0x101
 
-                       dst.Pix[i+0] = uint8((dr*a + sr*ma) / m >> 8)
-                       dst.Pix[i+1] = uint8((dg*a + sg*ma) / m >> 8)
-                       dst.Pix[i+2] = uint8((db*a + sb*ma) / m >> 8)
-                       dst.Pix[i+3] = uint8((da*a + sa*ma) / m >> 8)
+                       *dr = uint8((uint32(*dr)*a + sr*ma) / m >> 8)
+                       *dg = uint8((uint32(*dg)*a + sg*ma) / m >> 8)
+                       *db = uint8((uint32(*db)*a + sb*ma) / m >> 8)
+                       *da = uint8((uint32(*da)*a + sa*ma) / m >> 8)
                }
                i0 += dst.Stride
                i1 += dst.Stride