From f3cdb0537be2da5af2566e9bb7d225e95ea71ff0 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 22 Jun 2019 00:00:37 +0900 Subject: [PATCH] graphics: Move the vertices backend to ebiten package Now restorable/sharable packages cannot use the same vertices backend, but I think this won't affect the performance significantly. --- image.go | 8 ++-- internal/graphics/vertices.go | 42 ------------------ internal/graphicscommand/image_test.go | 4 +- internal/restorable/image.go | 2 +- internal/restorable/images_test.go | 2 +- internal/shareable/shareable.go | 2 +- internal/shareable/shareable_test.go | 6 +-- vertex.go | 59 ++++++++++++++++++++++++++ 8 files changed, 71 insertions(+), 54 deletions(-) create mode 100644 vertex.go diff --git a/image.go b/image.go index 88e9b3e73..4cbb57801 100644 --- a/image.go +++ b/image.go @@ -71,7 +71,7 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image { } s := shareable.NewImage(w2, h2) var src *shareable.Image - vs := graphics.VertexSlice(4) + vs := vertexSlice(4) if l := len(imgs); l == 0 { src = m.orig src.PutQuadVertices(vs, r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1) @@ -355,7 +355,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error { if level == 0 { src := img.mipmap.original() - vs := graphics.VertexSlice(4) + vs := vertexSlice(4) src.PutQuadVertices(vs, 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() i.mipmap.original().DrawTriangles(src, vs, is, colorm, mode, filter, graphics.AddressClampToZero) @@ -366,7 +366,7 @@ func (i *Image) DrawImage(img *Image, options *DrawImageOptions) error { b *= float32(s) c *= float32(s) d *= float32(s) - vs := graphics.VertexSlice(4) + vs := vertexSlice(4) src.PutQuadVertices(vs, 0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca) is := graphics.QuadIndices() i.mipmap.original().DrawTriangles(src, vs, is, colorm, mode, filter, graphics.AddressClampToZero) @@ -481,7 +481,7 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o filter = graphics.Filter(img.filter) } - vs := graphics.VertexSlice(len(vertices)) + vs := vertexSlice(len(vertices)) src := img.mipmap.original() r := img.Bounds() for idx, v := range vertices { diff --git a/internal/graphics/vertices.go b/internal/graphics/vertices.go index 03e9bf886..72fabc457 100644 --- a/internal/graphics/vertices.go +++ b/internal/graphics/vertices.go @@ -14,53 +14,11 @@ package graphics -import ( - "sync" -) - -var ( - theVerticesBackend = &verticesBackend{} -) - -type verticesBackend struct { - backend []float32 - head int - m sync.Mutex -} - const ( IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles. VertexFloatNum = 12 ) -func (v *verticesBackend) slice(n int) []float32 { - v.m.Lock() - - need := n * VertexFloatNum - if v.head+need > len(v.backend) { - v.backend = nil - v.head = 0 - } - - if v.backend == nil { - l := 1024 - if n > l { - l = n - } - v.backend = make([]float32, VertexFloatNum*l) - } - - s := v.backend[v.head : v.head+need] - v.head += need - - v.m.Unlock() - return s -} - -func VertexSlice(n int) []float32 { - return theVerticesBackend.slice(n) -} - type VertexPutter interface { PutVertex(dst []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) } diff --git a/internal/graphicscommand/image_test.go b/internal/graphicscommand/image_test.go index 2171614b7..f7b9c3ab4 100644 --- a/internal/graphicscommand/image_test.go +++ b/internal/graphicscommand/image_test.go @@ -69,7 +69,7 @@ func TestClear(t *testing.T) { src := NewImage(w/2, h/2) dst := NewImage(w, h) - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) graphics.PutQuadVertices(vs, &testVertexPutter{w / 2, h / 2}, 0, 0, w/2, h/2, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) is := graphics.QuadIndices() dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero) @@ -97,7 +97,7 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) { clr := NewImage(w, h) src := NewImage(16, 16) dst := NewImage(w, h) - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) graphics.PutQuadVertices(vs, &testVertexPutter{w / 2, h / 2}, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) is := graphics.QuadIndices() dst.DrawTriangles(clr, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero) diff --git a/internal/restorable/image.go b/internal/restorable/image.go index f23261db9..6b0d43e66 100644 --- a/internal/restorable/image.go +++ b/internal/restorable/image.go @@ -195,7 +195,7 @@ func (i *Image) fill(r, g, b, a uint8) { // As emptyImage is a priority image, this is restored before other regular images are restored. dw, dh := i.internalSize() sw, sh := emptyImage.Size() - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) graphics.PutQuadVertices(vs, i, 0, 0, sw, sh, float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0, rf, gf, bf, af) diff --git a/internal/restorable/images_test.go b/internal/restorable/images_test.go index a0d2c2a77..08133bf0d 100644 --- a/internal/restorable/images_test.go +++ b/internal/restorable/images_test.go @@ -106,7 +106,7 @@ func TestRestoreWithoutDraw(t *testing.T) { } func quadVertices(src *Image, sw, sh, x, y int) []float32 { - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) graphics.PutQuadVertices(vs, src, 0, 0, sw, sh, 1, 0, 0, 1, float32(x), float32(y), 1, 1, 1, 1) diff --git a/internal/shareable/shareable.go b/internal/shareable/shareable.go index 9e1459f07..41d698852 100644 --- a/internal/shareable/shareable.go +++ b/internal/shareable/shareable.go @@ -171,7 +171,7 @@ func (i *Image) ensureNotShared() { _, _, w, h := i.region() newImg := restorable.NewImage(w, h) - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) i.PutQuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) is := graphics.QuadIndices() newImg.DrawTriangles(i.backend.restorable, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) diff --git a/internal/shareable/shareable_test.go b/internal/shareable/shareable_test.go index fc7115a60..e918cf0b6 100644 --- a/internal/shareable/shareable_test.go +++ b/internal/shareable/shareable_test.go @@ -84,7 +84,7 @@ func TestEnsureNotShared(t *testing.T) { dy1 = size * 3 / 4 ) // img4.ensureNotShared() should be called. - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) img3.PutQuadVertices(vs, 0, 0, size/2, size/2, 1, 0, 0, 1, size/4, size/4, 1, 1, 1, 1) is := graphics.QuadIndices() img4.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) @@ -149,7 +149,7 @@ func TestReshared(t *testing.T) { } // Use img1 as a render target. - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) img2.PutQuadVertices(vs, 0, 0, size, size, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) is := graphics.QuadIndices() img1.DrawTriangles(img2, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) @@ -276,7 +276,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) { } src.ReplacePixels(pix) - vs := graphics.VertexSlice(4) + vs := make([]float32, 4*graphics.VertexFloatNum) src.PutQuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1) is := graphics.QuadIndices() dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) diff --git a/vertex.go b/vertex.go new file mode 100644 index 000000000..ad77b4b60 --- /dev/null +++ b/vertex.go @@ -0,0 +1,59 @@ +// Copyright 2019 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package ebiten + +import ( + "sync" + + "github.com/hajimehoshi/ebiten/internal/graphics" +) + +var ( + theVerticesBackend = &verticesBackend{} +) + +type verticesBackend struct { + backend []float32 + head int + m sync.Mutex +} + +func (v *verticesBackend) slice(n int) []float32 { + v.m.Lock() + + need := n * graphics.VertexFloatNum + if v.head+need > len(v.backend) { + v.backend = nil + v.head = 0 + } + + 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) []float32 { + return theVerticesBackend.slice(n) +}