mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +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
|
||||
}
|
||||
|
||||
// PutVertices puts the given dst with vertices that can be passed to DrawTriangles.
|
||||
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
|
||||
// might not work.
|
||||
vs := dst[0:12]
|
||||
|
||||
vs[0] = dx
|
||||
vs[1] = dy
|
||||
vs[2] = sx
|
||||
vs[3] = sy
|
||||
vs[4] = bx0
|
||||
vs[5] = by0
|
||||
vs[6] = bx1
|
||||
vs[7] = by1
|
||||
vs[8] = cr
|
||||
vs[9] = cg
|
||||
vs[10] = cb
|
||||
vs[11] = ca
|
||||
}
|
||||
|
||||
// DrawTriangles draws triangles with the given image.
|
||||
//
|
||||
// The vertex floats are:
|
||||
//
|
||||
// 0: Destination X in pixels
|
||||
// 1: Destination Y in pixels
|
||||
// 2: Source X in pixels (the upper-left is (0, 0))
|
||||
// 3: Source Y in pixels
|
||||
// 4: Bounds of the source min X in pixels
|
||||
// 5: Bounds of the source min Y in pixels
|
||||
// 6: Bounds of the source max X in pixels
|
||||
// 7: Bounds of the source max Y in pixels
|
||||
// 8: Color R [0.0-1.0]
|
||||
// 9: Color G
|
||||
// 10: Color B
|
||||
// 11: Color Y
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address) {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
|
@ -44,6 +44,23 @@ func TestMain(m *testing.M) {
|
||||
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
|
||||
|
||||
func TestEnsureNotShared(t *testing.T) {
|
||||
@ -85,8 +102,7 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
dy1 = size * 3 / 4
|
||||
)
|
||||
// img4.ensureNotShared() should be called.
|
||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
||||
graphics.PutQuadVertices(vs, img3, 0, 0, size/2, size/2, 1, 0, 0, 1, size/4, size/4, 1, 1, 1, 1)
|
||||
vs := quadVertices(size/2, size/2, size/4, size/4, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||
want := false
|
||||
@ -150,8 +166,7 @@ func TestReshared(t *testing.T) {
|
||||
}
|
||||
|
||||
// Use img1 as a render target.
|
||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
||||
graphics.PutQuadVertices(vs, img2, 0, 0, size, size, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
vs := quadVertices(size, size, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
@ -277,8 +292,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
||||
}
|
||||
src.ReplacePixels(pix)
|
||||
|
||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressClampToZero)
|
||||
dst.ReplacePixels(pix)
|
||||
@ -313,8 +327,7 @@ func TestSmallImages(t *testing.T) {
|
||||
}
|
||||
src.ReplacePixels(pix)
|
||||
|
||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressClampToZero)
|
||||
|
||||
@ -349,8 +362,7 @@ func TestLongImages(t *testing.T) {
|
||||
src.ReplacePixels(pix)
|
||||
|
||||
const scale = 120
|
||||
vs := make([]float32, 4*graphics.VertexFloatNum)
|
||||
graphics.PutQuadVertices(vs, src, 0, 0, w, h, scale, 0, 0, 1, 0, 0, 1, 1, 1, 1)
|
||||
vs := quadVertices(w, h, 0, 0, scale)
|
||||
is := graphics.QuadIndices()
|
||||
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()
|
||||
if level == 0 {
|
||||
vs := vertexSlice(4)
|
||||
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)
|
||||
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 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
|
||||
c *= s
|
||||
d *= s
|
||||
vs := vertexSlice(4)
|
||||
graphics.PutQuadVertices(vs, shared, 0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca)
|
||||
is := graphics.QuadIndices()
|
||||
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) {
|
||||
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))
|
||||
for idx, v := range vertices {
|
||||
src.orig.PutVertex(vs[idx*graphics.VertexFloatNum:(idx+1)*graphics.VertexFloatNum],
|
||||
float32(v.DstX), float32(v.DstY), v.SrcX, v.SrcY,
|
||||
float32(bounds.Min.X), float32(bounds.Min.Y), float32(bounds.Max.X), float32(bounds.Max.Y),
|
||||
v.ColorR, v.ColorG, v.ColorB, v.ColorA)
|
||||
for i, v := range vertices {
|
||||
vs[i*graphics.VertexFloatNum] = v.DstX
|
||||
vs[i*graphics.VertexFloatNum+1] = v.DstY
|
||||
vs[i*graphics.VertexFloatNum+2] = v.SrcX
|
||||
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.disposeMipmaps()
|
||||
@ -170,12 +184,12 @@ func (m *mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
||||
}
|
||||
|
||||
var src *shareable.Image
|
||||
vs := vertexSlice(4)
|
||||
var vs []float32
|
||||
var filter driver.Filter
|
||||
switch {
|
||||
case level == 1:
|
||||
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
|
||||
case 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
|
||||
}
|
||||
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
|
||||
case level == -1:
|
||||
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
|
||||
case 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
|
||||
}
|
||||
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
|
||||
default:
|
||||
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 {
|
||||
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