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.
This commit is contained in:
Hajime Hoshi 2019-06-22 00:00:37 +09:00
parent 69ebc481e8
commit f3cdb0537b
8 changed files with 71 additions and 54 deletions

View File

@ -71,7 +71,7 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
} }
s := shareable.NewImage(w2, h2) s := shareable.NewImage(w2, h2)
var src *shareable.Image var src *shareable.Image
vs := graphics.VertexSlice(4) vs := vertexSlice(4)
if l := len(imgs); l == 0 { if l := len(imgs); l == 0 {
src = m.orig 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) 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 { if level == 0 {
src := img.mipmap.original() 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) 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() is := graphics.QuadIndices()
i.mipmap.original().DrawTriangles(src, vs, is, colorm, mode, filter, graphics.AddressClampToZero) 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) b *= float32(s)
c *= float32(s) c *= float32(s)
d *= 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) src.PutQuadVertices(vs, 0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca)
is := graphics.QuadIndices() is := graphics.QuadIndices()
i.mipmap.original().DrawTriangles(src, vs, is, colorm, mode, filter, graphics.AddressClampToZero) 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) filter = graphics.Filter(img.filter)
} }
vs := graphics.VertexSlice(len(vertices)) vs := vertexSlice(len(vertices))
src := img.mipmap.original() src := img.mipmap.original()
r := img.Bounds() r := img.Bounds()
for idx, v := range vertices { for idx, v := range vertices {

View File

@ -14,53 +14,11 @@
package graphics package graphics
import (
"sync"
)
var (
theVerticesBackend = &verticesBackend{}
)
type verticesBackend struct {
backend []float32
head int
m sync.Mutex
}
const ( const (
IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles. IndicesNum = (1 << 16) / 3 * 3 // Adjust num for triangles.
VertexFloatNum = 12 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 { type VertexPutter interface {
PutVertex(dst []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) PutVertex(dst []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32)
} }

View File

@ -69,7 +69,7 @@ func TestClear(t *testing.T) {
src := NewImage(w/2, h/2) src := NewImage(w/2, h/2)
dst := NewImage(w, h) 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) 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() is := graphics.QuadIndices()
dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero) 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) clr := NewImage(w, h)
src := NewImage(16, 16) src := NewImage(16, 16)
dst := NewImage(w, h) 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) 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() is := graphics.QuadIndices()
dst.DrawTriangles(clr, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero) dst.DrawTriangles(clr, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero)

View File

@ -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. // As emptyImage is a priority image, this is restored before other regular images are restored.
dw, dh := i.internalSize() dw, dh := i.internalSize()
sw, sh := emptyImage.Size() sw, sh := emptyImage.Size()
vs := graphics.VertexSlice(4) vs := make([]float32, 4*graphics.VertexFloatNum)
graphics.PutQuadVertices(vs, i, 0, 0, sw, sh, graphics.PutQuadVertices(vs, i, 0, 0, sw, sh,
float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0, float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0,
rf, gf, bf, af) rf, gf, bf, af)

View File

@ -106,7 +106,7 @@ func TestRestoreWithoutDraw(t *testing.T) {
} }
func quadVertices(src *Image, sw, sh, x, y int) []float32 { 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, graphics.PutQuadVertices(vs, src, 0, 0, sw, sh,
1, 0, 0, 1, float32(x), float32(y), 1, 0, 0, 1, float32(x), float32(y),
1, 1, 1, 1) 1, 1, 1, 1)

View File

@ -171,7 +171,7 @@ func (i *Image) ensureNotShared() {
_, _, w, h := i.region() _, _, w, h := i.region()
newImg := restorable.NewImage(w, h) 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) i.PutQuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
newImg.DrawTriangles(i.backend.restorable, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) newImg.DrawTriangles(i.backend.restorable, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)

View File

@ -84,7 +84,7 @@ func TestEnsureNotShared(t *testing.T) {
dy1 = size * 3 / 4 dy1 = size * 3 / 4
) )
// img4.ensureNotShared() should be called. // 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) img3.PutQuadVertices(vs, 0, 0, size/2, size/2, 1, 0, 0, 1, size/4, size/4, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
img4.DrawTriangles(img3, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) 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. // 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) img2.PutQuadVertices(vs, 0, 0, size, size, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
img1.DrawTriangles(img2, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) img1.DrawTriangles(img2, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)
@ -276,7 +276,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
} }
src.ReplacePixels(pix) 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) src.PutQuadVertices(vs, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero) dst.DrawTriangles(src, vs, is, nil, graphics.CompositeModeCopy, graphics.FilterNearest, graphics.AddressClampToZero)

59
vertex.go Normal file
View File

@ -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)
}