use point pool

For internal operations (anything using getAndClearPoints), there's a
pretty good chance that the operation will repeatedly invoke something
like fillPolygon(), meaning that it needs to push "a few" points
and then invoke something that uses those points.

So, we add a slice for containing spare slices of points, and on the
way out of each such function, shove the current imd.points (as used
inside that function) onto a stack, and set imd.points to [0:0] of
the thing it was called with.

Performance goes from 11-13fps to 17-18fps on my test case.
This commit is contained in:
Seebs 2017-06-05 19:37:53 -05:00
parent 34cdd8729b
commit 9a7ab1c6b0
1 changed files with 25 additions and 2 deletions

View File

@ -52,6 +52,7 @@ type IMDraw struct {
EndShape EndShape EndShape EndShape
points []point points []point
pool [][]point
matrix pixel.Matrix matrix pixel.Matrix
mask pixel.RGBA mask pixel.RGBA
@ -109,7 +110,7 @@ func (imd *IMDraw) Clear() {
// //
// This does not affect matrix and color mask set by SetMatrix and SetColorMask. // This does not affect matrix and color mask set by SetMatrix and SetColorMask.
func (imd *IMDraw) Reset() { func (imd *IMDraw) Reset() {
imd.points = nil imd.points = imd.points[:0]
imd.Color = pixel.Alpha(1) imd.Color = pixel.Alpha(1)
imd.Picture = pixel.ZV imd.Picture = pixel.ZV
imd.Intensity = 0 imd.Intensity = 0
@ -256,10 +257,22 @@ func (imd *IMDraw) EllipseArc(radius pixel.Vec, low, high, thickness float64) {
func (imd *IMDraw) getAndClearPoints() []point { func (imd *IMDraw) getAndClearPoints() []point {
points := imd.points points := imd.points
// use one of the existing pools so we don't reallocate as often
if len(imd.pool) > 0 {
pos := len(imd.pool) - 1
imd.points = imd.pool[pos]
imd.pool = imd.pool[0:pos]
} else {
imd.points = nil imd.points = nil
}
return points return points
} }
func (imd *IMDraw) restorePoints(points []point) {
imd.pool = append(imd.pool, imd.points)
imd.points = points[:0]
}
func (imd *IMDraw) applyMatrixAndMask(off int) { func (imd *IMDraw) applyMatrixAndMask(off int) {
for i := range (*imd.tri)[off:] { for i := range (*imd.tri)[off:] {
(*imd.tri)[off+i].Position = imd.matrix.Project((*imd.tri)[off+i].Position) (*imd.tri)[off+i].Position = imd.matrix.Project((*imd.tri)[off+i].Position)
@ -271,6 +284,7 @@ func (imd *IMDraw) fillRectangle() {
points := imd.getAndClearPoints() points := imd.getAndClearPoints()
if len(points) < 2 { if len(points) < 2 {
imd.restorePoints(points)
return return
} }
@ -302,12 +316,14 @@ func (imd *IMDraw) fillRectangle() {
imd.applyMatrixAndMask(off) imd.applyMatrixAndMask(off)
imd.batch.Dirty() imd.batch.Dirty()
imd.restorePoints(points)
} }
func (imd *IMDraw) outlineRectangle(thickness float64) { func (imd *IMDraw) outlineRectangle(thickness float64) {
points := imd.getAndClearPoints() points := imd.getAndClearPoints()
if len(points) < 2 { if len(points) < 2 {
imd.restorePoints(points)
return return
} }
@ -323,12 +339,14 @@ func (imd *IMDraw) outlineRectangle(thickness float64) {
imd.pushPt(pixel.V(b.pos.X, a.pos.Y), mid) imd.pushPt(pixel.V(b.pos.X, a.pos.Y), mid)
imd.polyline(thickness, true) imd.polyline(thickness, true)
} }
imd.restorePoints(points)
} }
func (imd *IMDraw) fillPolygon() { func (imd *IMDraw) fillPolygon() {
points := imd.getAndClearPoints() points := imd.getAndClearPoints()
if len(points) < 3 { if len(points) < 3 {
imd.restorePoints(points)
return return
} }
@ -346,6 +364,7 @@ func (imd *IMDraw) fillPolygon() {
imd.applyMatrixAndMask(off) imd.applyMatrixAndMask(off)
imd.batch.Dirty() imd.batch.Dirty()
imd.restorePoints(points)
} }
func (imd *IMDraw) fillEllipseArc(radius pixel.Vec, low, high float64) { func (imd *IMDraw) fillEllipseArc(radius pixel.Vec, low, high float64) {
@ -387,6 +406,7 @@ func (imd *IMDraw) fillEllipseArc(radius pixel.Vec, low, high float64) {
imd.applyMatrixAndMask(off) imd.applyMatrixAndMask(off)
imd.batch.Dirty() imd.batch.Dirty()
} }
imd.restorePoints(points)
} }
func (imd *IMDraw) outlineEllipseArc(radius pixel.Vec, low, high, thickness float64, doEndShape bool) { func (imd *IMDraw) outlineEllipseArc(radius pixel.Vec, low, high, thickness float64, doEndShape bool) {
@ -485,12 +505,14 @@ func (imd *IMDraw) outlineEllipseArc(radius pixel.Vec, low, high, thickness floa
} }
} }
} }
imd.restorePoints(points)
} }
func (imd *IMDraw) polyline(thickness float64, closed bool) { func (imd *IMDraw) polyline(thickness float64, closed bool) {
points := imd.getAndClearPoints() points := imd.getAndClearPoints()
if len(points) == 0 { if len(points) == 0 {
imd.restorePoints(points)
return return
} }
if len(points) == 1 { if len(points) == 1 {
@ -591,4 +613,5 @@ func (imd *IMDraw) polyline(thickness float64, closed bool) {
imd.fillEllipseArc(pixel.V(thickness/2, thickness/2), normal.Angle(), normal.Angle()-math.Pi) imd.fillEllipseArc(pixel.V(thickness/2, thickness/2), normal.Angle(), normal.Angle()-math.Pi)
} }
} }
imd.restorePoints(points)
} }