diff --git a/mipmap.go b/mipmap.go index 1968fe8c4..b41bc19bf 100644 --- a/mipmap.go +++ b/mipmap.go @@ -121,14 +121,9 @@ func (m *mipmap) drawImage(src *mipmap, bounds image.Rectangle, geom *GeoM, colo colorm = nil } - screen := filter == driver.FilterScreen - if screen && level != 0 { - panic("ebiten: Mipmap must not be used when the filter is FilterScreen") - } - a, b, c, d, tx, ty := geom.elements() if level == 0 { - vs := quadVertices(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, a, b, c, d, tx, ty, cr, cg, cb, ca, screen) + vs := quadVertices(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, a, b, c, d, tx, ty, cr, cg, cb, ca) is := graphics.QuadIndices() m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressClampToZero) } else if buf := src.level(bounds, level); buf != nil { @@ -138,7 +133,7 @@ func (m *mipmap) drawImage(src *mipmap, bounds image.Rectangle, geom *GeoM, colo b *= s c *= s d *= s - vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca, false) + vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca) is := graphics.QuadIndices() m.orig.DrawTriangles(buf, vs, is, colorm, mode, filter, driver.AddressClampToZero) } @@ -154,7 +149,7 @@ func (m *mipmap) drawTriangles(src *mipmap, bounds image.Rectangle, vertices []V // TODO: Needs boundary check optimization? // See https://go101.org/article/bounds-check-elimination.html - vs := vertexSlice(len(vertices), false) + vs := vertexSlice(len(vertices)) for i, v := range vertices { vs[i*graphics.VertexFloatNum] = v.DstX vs[i*graphics.VertexFloatNum+1] = v.DstY @@ -199,7 +194,7 @@ func (m *mipmap) level(r image.Rectangle, level int) *buffered.Image { switch { case level == 1: src = m.orig - vs = quadVertices(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1, false) + vs = quadVertices(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1) filter = driver.FilterLinear case level > 1: src = m.level(r, level-1) @@ -208,11 +203,11 @@ func (m *mipmap) level(r image.Rectangle, level int) *buffered.Image { return nil } w, h := sizeForLevel(r.Dx(), r.Dy(), level-1) - vs = quadVertices(0, 0, w, h, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1, false) + vs = quadVertices(0, 0, w, h, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1) filter = driver.FilterLinear case level == -1: src = m.orig - vs = quadVertices(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1, false) + vs = quadVertices(r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1) filter = driver.FilterNearest case level < -1: src = m.level(r, level+1) @@ -221,7 +216,7 @@ func (m *mipmap) level(r image.Rectangle, level int) *buffered.Image { return nil } w, h := sizeForLevel(r.Dx(), r.Dy(), level+1) - vs = quadVertices(0, 0, w, h, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1, false) + vs = quadVertices(0, 0, w, h, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1) filter = driver.FilterNearest default: panic(fmt.Sprintf("ebiten: invalid level: %d", level)) @@ -297,10 +292,6 @@ func (m *mipmap) mipmapLevel(geom *GeoM, width, height int, filter driver.Filter panic("ebiten: dst must be non zero at mipmapLevel") } - if filter == driver.FilterScreen { - return 0 - } - // Use 'negative' mipmap to render edges correctly (#611, #907). // It looks like 128 is the enlargement factor that causes edge missings to pass the test TestImageStretch. const tooBigScale = 128 diff --git a/vertex.go b/vertex.go index 40858f623..5e4c10f37 100644 --- a/vertex.go +++ b/vertex.go @@ -21,9 +21,7 @@ import ( ) var ( - theVerticesBackend = &verticesBackend{ - backend: make([]float32, graphics.VertexFloatNum*1024), - } + theVerticesBackend = &verticesBackend{} ) type verticesBackend struct { @@ -32,42 +30,42 @@ type verticesBackend struct { m sync.Mutex } -func (v *verticesBackend) slice(n int, last bool) []float32 { +func (v *verticesBackend) slice(n int) []float32 { v.m.Lock() need := n * graphics.VertexFloatNum - if l := len(v.backend); v.head+need > l { - for v.head+need > l { - l *= 2 - } - v.backend = make([]float32, l) + if v.head+need > len(v.backend) { + v.backend = nil v.head = 0 } - s := v.backend[v.head : v.head+need] - if last { - // If last is true, the vertices backend is sent to GPU and it is fine to reuse the slice. - v.head = 0 - } else { - v.head += need + if v.backend == nil { + l := 1024 + if n > l { + l = n + } + v.backend = make([]float32, graphics.VertexFloatNum*l) } + s := v.backend[v.head : v.head+need] + v.head += need + v.m.Unlock() return s } -func vertexSlice(n int, last bool) []float32 { - return theVerticesBackend.slice(n, last) +func vertexSlice(n int) []float32 { + return theVerticesBackend.slice(n) } -func quadVertices(sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32, last bool) []float32 { +func quadVertices(sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32, cr, cg, cb, ca float32) []float32 { x := float32(sx1 - sx0) y := float32(sy1 - sy0) ax, by, cx, dy := a*x, b*y, c*x, d*y u0, v0, u1, v1 := float32(sx0), float32(sy0), float32(sx1), float32(sy1) // This function is very performance-sensitive and implement in a very dumb way. - vs := vertexSlice(4, last) + vs := vertexSlice(4) _ = vs[:48] // For each values, see the comment at shareable.(*Image).DrawTriangles.