mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-25 03:08:54 +01:00
shareable: Remove (*Image).PutVertex
This commit is contained in:
parent
ea52aa52bb
commit
6095cd965b
@ -262,29 +262,22 @@ func (i *Image) Size() (width, height int) {
|
|||||||
return i.width, i.height
|
return i.width, i.height
|
||||||
}
|
}
|
||||||
|
|
||||||
// PutVertices puts the given dst with vertices that can be passed to DrawTriangles.
|
// DrawTriangles draws triangles with the given image.
|
||||||
func (i *Image) PutVertex(dst []float32, dx, dy, sx, sy float32, bx0, by0, bx1, by1 float32, cr, cg, cb, ca float32) {
|
|
||||||
// Specifying a range explicitly here is redundant but this helps optimization
|
|
||||||
// to eliminate boundary checks.
|
|
||||||
//
|
//
|
||||||
// VertexFloatNum is better than 12 in terms of code maintenanceability, but in GopherJS, optimization
|
// The vertex floats are:
|
||||||
// might not work.
|
//
|
||||||
vs := dst[0:12]
|
// 0: Destination X in pixels
|
||||||
|
// 1: Destination Y in pixels
|
||||||
vs[0] = dx
|
// 2: Source X in pixels (the upper-left is (0, 0))
|
||||||
vs[1] = dy
|
// 3: Source Y in pixels
|
||||||
vs[2] = sx
|
// 4: Bounds of the source min X in pixels
|
||||||
vs[3] = sy
|
// 5: Bounds of the source min Y in pixels
|
||||||
vs[4] = bx0
|
// 6: Bounds of the source max X in pixels
|
||||||
vs[5] = by0
|
// 7: Bounds of the source max Y in pixels
|
||||||
vs[6] = bx1
|
// 8: Color R [0.0-1.0]
|
||||||
vs[7] = by1
|
// 9: Color G
|
||||||
vs[8] = cr
|
// 10: Color B
|
||||||
vs[9] = cg
|
// 11: Color Y
|
||||||
vs[10] = cb
|
|
||||||
vs[11] = ca
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
|
@ -44,6 +44,23 @@ func TestMain(m *testing.M) {
|
|||||||
os.Exit(code)
|
os.Exit(code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func quadVertices(sw, sh, x, y int, scalex float32) []float32 {
|
||||||
|
dx0 := float32(x)
|
||||||
|
dy0 := float32(y)
|
||||||
|
dx1 := float32(x) + float32(sw)*scalex
|
||||||
|
dy1 := float32(y) + float32(sh)
|
||||||
|
sx0 := float32(0)
|
||||||
|
sy0 := float32(0)
|
||||||
|
sx1 := float32(sw)
|
||||||
|
sy1 := float32(sh)
|
||||||
|
return []float32{
|
||||||
|
dx0, dy0, sx0, sy0, sx0, sy0, sx1, sy1, 1, 1, 1, 1,
|
||||||
|
dx1, dy0, sx1, sy0, sx0, sy0, sx1, sy1, 1, 1, 1, 1,
|
||||||
|
dx0, dy1, sx0, sy1, sx0, sy0, sx1, sy1, 1, 1, 1, 1,
|
||||||
|
dx1, dy1, sx1, sy1, sx0, sy0, sx1, sy1, 1, 1, 1, 1,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const bigSize = 2049
|
const bigSize = 2049
|
||||||
|
|
||||||
func TestEnsureNotShared(t *testing.T) {
|
func TestEnsureNotShared(t *testing.T) {
|
||||||
@ -85,8 +102,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 := make([]float32, 4*graphics.VertexFloatNum)
|
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||||
graphics.PutQuadVertices(vs, img3, 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, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||||
want := false
|
want := false
|
||||||
@ -150,8 +166,7 @@ func TestReshared(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Use img1 as a render target.
|
// Use img1 as a render target.
|
||||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
vs := quadVertices(size, size, 0, 0, 1)
|
||||||
graphics.PutQuadVertices(vs, img2, 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, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||||
@ -277,8 +292,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
|||||||
}
|
}
|
||||||
src.ReplacePixels(pix)
|
src.ReplacePixels(pix)
|
||||||
|
|
||||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
graphics.PutQuadVertices(vs, src, 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, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||||
dst.ReplacePixels(pix)
|
dst.ReplacePixels(pix)
|
||||||
@ -313,8 +327,7 @@ func TestSmallImages(t *testing.T) {
|
|||||||
}
|
}
|
||||||
src.ReplacePixels(pix)
|
src.ReplacePixels(pix)
|
||||||
|
|
||||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
vs := quadVertices(w, h, 0, 0, 1)
|
||||||
graphics.PutQuadVertices(vs, src, 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, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
||||||
|
|
||||||
@ -349,8 +362,7 @@ func TestLongImages(t *testing.T) {
|
|||||||
src.ReplacePixels(pix)
|
src.ReplacePixels(pix)
|
||||||
|
|
||||||
const scale = 120
|
const scale = 120
|
||||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
vs := quadVertices(w, h, 0, 0, scale)
|
||||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, scale, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
||||||
|
|
||||||
|
42
mipmap.go
42
mipmap.go
@ -120,8 +120,7 @@ func (m *mipmap) drawImage(src *mipmap, bounds image.Rectangle, geom *GeoM, colo
|
|||||||
|
|
||||||
a, b, c, d, tx, ty := geom.elements()
|
a, b, c, d, tx, ty := geom.elements()
|
||||||
if level == 0 {
|
if level == 0 {
|
||||||
vs := vertexSlice(4)
|
vs := quadVertices(bounds.Min.X, bounds.Min.Y, bounds.Max.X, bounds.Max.Y, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||||
graphics.PutQuadVertices(vs, src.orig, 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()
|
||||||
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
||||||
} else if shared := src.level(bounds, level); shared != nil {
|
} else if shared := src.level(bounds, level); shared != nil {
|
||||||
@ -131,8 +130,7 @@ func (m *mipmap) drawImage(src *mipmap, bounds image.Rectangle, geom *GeoM, colo
|
|||||||
b *= s
|
b *= s
|
||||||
c *= s
|
c *= s
|
||||||
d *= s
|
d *= s
|
||||||
vs := vertexSlice(4)
|
vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||||
graphics.PutQuadVertices(vs, shared, 0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
m.orig.DrawTriangles(shared, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
m.orig.DrawTriangles(shared, vs, is, colorm, mode, filter, driver.AddressClampToZero)
|
||||||
}
|
}
|
||||||
@ -140,12 +138,28 @@ func (m *mipmap) drawImage(src *mipmap, bounds image.Rectangle, geom *GeoM, colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *mipmap) drawTriangles(src *mipmap, bounds image.Rectangle, vertices []Vertex, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
func (m *mipmap) drawTriangles(src *mipmap, bounds image.Rectangle, vertices []Vertex, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
||||||
|
bx0 := float32(bounds.Min.X)
|
||||||
|
by0 := float32(bounds.Min.Y)
|
||||||
|
bx1 := float32(bounds.Max.X)
|
||||||
|
by1 := float32(bounds.Max.Y)
|
||||||
|
|
||||||
|
// TODO: Needs boundary check optimization?
|
||||||
|
// See https://go101.org/article/bounds-check-elimination.html
|
||||||
|
|
||||||
vs := vertexSlice(len(vertices))
|
vs := vertexSlice(len(vertices))
|
||||||
for idx, v := range vertices {
|
for i, v := range vertices {
|
||||||
src.orig.PutVertex(vs[idx*graphics.VertexFloatNum:(idx+1)*graphics.VertexFloatNum],
|
vs[i*graphics.VertexFloatNum] = v.DstX
|
||||||
float32(v.DstX), float32(v.DstY), v.SrcX, v.SrcY,
|
vs[i*graphics.VertexFloatNum+1] = v.DstY
|
||||||
float32(bounds.Min.X), float32(bounds.Min.Y), float32(bounds.Max.X), float32(bounds.Max.Y),
|
vs[i*graphics.VertexFloatNum+2] = v.SrcX
|
||||||
v.ColorR, v.ColorG, v.ColorB, v.ColorA)
|
vs[i*graphics.VertexFloatNum+3] = v.SrcY
|
||||||
|
vs[i*graphics.VertexFloatNum+4] = bx0
|
||||||
|
vs[i*graphics.VertexFloatNum+5] = by0
|
||||||
|
vs[i*graphics.VertexFloatNum+6] = bx1
|
||||||
|
vs[i*graphics.VertexFloatNum+7] = by1
|
||||||
|
vs[i*graphics.VertexFloatNum+8] = v.ColorR
|
||||||
|
vs[i*graphics.VertexFloatNum+9] = v.ColorG
|
||||||
|
vs[i*graphics.VertexFloatNum+10] = v.ColorB
|
||||||
|
vs[i*graphics.VertexFloatNum+11] = v.ColorA
|
||||||
}
|
}
|
||||||
m.orig.DrawTriangles(src.orig, vs, indices, colorm, mode, filter, address)
|
m.orig.DrawTriangles(src.orig, vs, indices, colorm, mode, filter, address)
|
||||||
m.disposeMipmaps()
|
m.disposeMipmaps()
|
||||||
@ -170,12 +184,12 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var src *shareable.Image
|
var src *shareable.Image
|
||||||
vs := vertexSlice(4)
|
var vs []float32
|
||||||
var filter driver.Filter
|
var filter driver.Filter
|
||||||
switch {
|
switch {
|
||||||
case level == 1:
|
case level == 1:
|
||||||
src = m.orig
|
src = m.orig
|
||||||
graphics.PutQuadVertices(vs, src, r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1)
|
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
|
filter = driver.FilterLinear
|
||||||
case level > 1:
|
case level > 1:
|
||||||
src = m.level(r, level-1)
|
src = m.level(r, level-1)
|
||||||
@ -184,11 +198,11 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w, h := src.Size()
|
w, h := src.Size()
|
||||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1)
|
vs = quadVertices(0, 0, w, h, 0.5, 0, 0, 0.5, 0, 0, 1, 1, 1, 1)
|
||||||
filter = driver.FilterLinear
|
filter = driver.FilterLinear
|
||||||
case level == -1:
|
case level == -1:
|
||||||
src = m.orig
|
src = m.orig
|
||||||
graphics.PutQuadVertices(vs, src, r.Min.X, r.Min.Y, r.Max.X, r.Max.Y, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1)
|
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
|
filter = driver.FilterNearest
|
||||||
case level < -1:
|
case level < -1:
|
||||||
src = m.level(r, level+1)
|
src = m.level(r, level+1)
|
||||||
@ -197,7 +211,7 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
w, h := src.Size()
|
w, h := src.Size()
|
||||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1)
|
vs = quadVertices(0, 0, w, h, 2, 0, 0, 2, 0, 0, 1, 1, 1, 1)
|
||||||
filter = driver.FilterNearest
|
filter = driver.FilterNearest
|
||||||
default:
|
default:
|
||||||
panic(fmt.Sprintf("ebiten: invalid level: %d", level))
|
panic(fmt.Sprintf("ebiten: invalid level: %d", level))
|
||||||
|
66
vertex.go
66
vertex.go
@ -57,3 +57,69 @@ func (v *verticesBackend) slice(n int) []float32 {
|
|||||||
func vertexSlice(n int) []float32 {
|
func vertexSlice(n int) []float32 {
|
||||||
return theVerticesBackend.slice(n)
|
return theVerticesBackend.slice(n)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
_ = vs[:48]
|
||||||
|
|
||||||
|
// For each values, see the comment at shareable.(*Image).DrawTriangles.
|
||||||
|
vs[0] = tx
|
||||||
|
vs[1] = ty
|
||||||
|
vs[2] = u0
|
||||||
|
vs[3] = v0
|
||||||
|
vs[4] = u0
|
||||||
|
vs[5] = v0
|
||||||
|
vs[6] = u1
|
||||||
|
vs[7] = v1
|
||||||
|
vs[8] = cr
|
||||||
|
vs[9] = cg
|
||||||
|
vs[10] = cb
|
||||||
|
vs[11] = ca
|
||||||
|
|
||||||
|
vs[12] = ax + tx
|
||||||
|
vs[13] = cx + ty
|
||||||
|
vs[14] = u1
|
||||||
|
vs[15] = v0
|
||||||
|
vs[16] = u0
|
||||||
|
vs[17] = v0
|
||||||
|
vs[18] = u1
|
||||||
|
vs[19] = v1
|
||||||
|
vs[20] = cr
|
||||||
|
vs[21] = cg
|
||||||
|
vs[22] = cb
|
||||||
|
vs[23] = ca
|
||||||
|
|
||||||
|
vs[24] = by + tx
|
||||||
|
vs[25] = dy + ty
|
||||||
|
vs[26] = u0
|
||||||
|
vs[27] = v1
|
||||||
|
vs[28] = u0
|
||||||
|
vs[29] = v0
|
||||||
|
vs[30] = u1
|
||||||
|
vs[31] = v1
|
||||||
|
vs[32] = cr
|
||||||
|
vs[33] = cg
|
||||||
|
vs[34] = cb
|
||||||
|
vs[35] = ca
|
||||||
|
|
||||||
|
vs[36] = ax + by + tx
|
||||||
|
vs[37] = cx + dy + ty
|
||||||
|
vs[38] = u1
|
||||||
|
vs[39] = v1
|
||||||
|
vs[40] = u0
|
||||||
|
vs[41] = v0
|
||||||
|
vs[42] = u1
|
||||||
|
vs[43] = v1
|
||||||
|
vs[44] = cr
|
||||||
|
vs[45] = cg
|
||||||
|
vs[46] = cb
|
||||||
|
vs[47] = ca
|
||||||
|
|
||||||
|
return vs
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user