mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 10:48:53 +01:00
ebiten: Sparate textures from uniforms at DrawTrianglesWithShader
Updates #1193 Updates #1239
This commit is contained in:
parent
914eb093f8
commit
d217bc6033
@ -130,9 +130,7 @@ func (g *Game) Draw(screen *ebiten.Image) {
|
||||
[]float32{float32(cx), float32(cy)}, // Cursor
|
||||
}
|
||||
if g.idx != 0 {
|
||||
op.Uniforms = append(op.Uniforms,
|
||||
gophersImage, // Image
|
||||
)
|
||||
op.Textures = append(op.Textures, gophersImage)
|
||||
}
|
||||
screen.DrawTrianglesWithShader(vs, is, s, op)
|
||||
|
||||
|
28
image.go
28
image.go
@ -337,11 +337,12 @@ func (i *Image) DrawTriangles(vertices []Vertex, indices []uint16, img *Image, o
|
||||
}
|
||||
}
|
||||
|
||||
i.buffered.DrawTriangles(img.buffered, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, nil, nil)
|
||||
i.buffered.DrawTriangles(img.buffered, vs, is, options.ColorM.impl, mode, filter, driver.Address(options.Address), sr, nil, nil, nil)
|
||||
}
|
||||
|
||||
type DrawTrianglesWithShaderOptions struct {
|
||||
Uniforms []interface{}
|
||||
Textures []*Image
|
||||
CompositeMode CompositeMode
|
||||
}
|
||||
|
||||
@ -370,22 +371,17 @@ func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, sha
|
||||
|
||||
mode := driver.CompositeMode(options.CompositeMode)
|
||||
|
||||
us := []interface{}{}
|
||||
for _, v := range options.Uniforms {
|
||||
switch v := v.(type) {
|
||||
case *Image:
|
||||
if v.isDisposed() {
|
||||
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
||||
}
|
||||
us = append(us, v.buffered)
|
||||
default:
|
||||
us = append(us, v)
|
||||
}
|
||||
}
|
||||
|
||||
// The first uniform variable is Internal_ViewportSize.
|
||||
// The actual value is set at graphicscommand package.
|
||||
us = append([]interface{}{[]float32{0, 0}}, us...)
|
||||
us := append([]interface{}{[]float32{0, 0}}, options.Uniforms...)
|
||||
|
||||
var ts []*buffered.Image
|
||||
for _, t := range options.Textures {
|
||||
if t.isDisposed() {
|
||||
panic("ebiten: the given image to DrawTriangles must not be disposed")
|
||||
}
|
||||
ts = append(ts, t.buffered)
|
||||
}
|
||||
|
||||
vs := make([]float32, len(vertices)*graphics.VertexFloatNum)
|
||||
for i, v := range vertices {
|
||||
@ -401,7 +397,7 @@ func (i *Image) DrawTrianglesWithShader(vertices []Vertex, indices []uint16, sha
|
||||
is := make([]uint16, len(indices))
|
||||
copy(is, indices)
|
||||
|
||||
i.buffered.DrawTriangles(nil, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, us)
|
||||
i.buffered.DrawTriangles(nil, vs, is, nil, mode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, shader.shader, us, ts)
|
||||
}
|
||||
|
||||
// SubImage returns an image representing the portion of the image p visible through r.
|
||||
|
@ -268,7 +268,7 @@ func (i *Image) drawImage(src *Image, bounds image.Rectangle, g mipmap.GeoM, col
|
||||
// DrawTriangles draws the src image with the given vertices.
|
||||
//
|
||||
// Copying vertices and indices is the caller's responsibility.
|
||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
var srcs []*Image
|
||||
if src != nil {
|
||||
srcs = append(srcs, src)
|
||||
@ -288,7 +288,7 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16,
|
||||
if maybeCanAddDelayedCommand() {
|
||||
if tryAddDelayedCommand(func() error {
|
||||
// Arguments are not copied. Copying is the caller's responsibility.
|
||||
i.DrawTriangles(src, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms)
|
||||
i.DrawTriangles(src, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms, textures)
|
||||
return nil
|
||||
}) {
|
||||
return
|
||||
@ -304,21 +304,18 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16,
|
||||
if shader != nil {
|
||||
s = shader.shader
|
||||
}
|
||||
us := make([]interface{}, len(uniforms))
|
||||
for k, v := range uniforms {
|
||||
switch v := v.(type) {
|
||||
case *Image:
|
||||
us[k] = v.img
|
||||
default:
|
||||
us[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
var srcImg *mipmap.Mipmap
|
||||
if src != nil {
|
||||
srcImg = src.img
|
||||
}
|
||||
i.img.DrawTriangles(srcImg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, us)
|
||||
|
||||
var ts []*mipmap.Mipmap
|
||||
for _, t := range textures {
|
||||
ts = append(ts, t.img)
|
||||
}
|
||||
|
||||
i.img.DrawTriangles(srcImg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, ts)
|
||||
i.invalidatePendingPixels()
|
||||
}
|
||||
|
||||
|
@ -55,8 +55,10 @@ type Graphics interface {
|
||||
// DrawShader draws the shader.
|
||||
//
|
||||
// uniforms represents a colletion of uniform variables. The values must be one of these types:
|
||||
// float32, []float32, or ImageID.
|
||||
DrawShader(dst ImageID, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, uniforms []interface{}) error
|
||||
//
|
||||
// * float32
|
||||
// * []float32
|
||||
DrawShader(dst ImageID, shader ShaderID, indexLen int, indexOffset int, mode CompositeMode, uniforms []interface{}, textures []ImageID) error
|
||||
}
|
||||
|
||||
// GraphicsNotReady represents that the graphics driver is not ready for recovering from the context lost.
|
||||
|
@ -143,7 +143,7 @@ func (q *commandQueue) appendIndices(indices []uint16, offset uint16) {
|
||||
}
|
||||
|
||||
// EnqueueDrawTrianglesCommand enqueues a drawing-image command.
|
||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []float32, indices []uint16, color *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
if len(indices) > graphics.IndicesNum {
|
||||
panic(fmt.Sprintf("graphicscommand: len(indices) must be <= graphics.IndicesNum but not at EnqueueDrawTrianglesCommand: len(indices): %d, graphics.IndicesNum: %d", len(indices), graphics.IndicesNum))
|
||||
}
|
||||
@ -157,15 +157,10 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []f
|
||||
|
||||
if src != nil {
|
||||
q.appendVertices(vertices, src)
|
||||
} else if len(textures) > 0 {
|
||||
q.appendVertices(vertices, textures[0])
|
||||
} else {
|
||||
var img *Image
|
||||
for _, v := range uniforms {
|
||||
if i, ok := v.(*Image); ok {
|
||||
img = i
|
||||
break
|
||||
}
|
||||
}
|
||||
q.appendVertices(vertices, img)
|
||||
q.appendVertices(vertices, nil)
|
||||
}
|
||||
q.appendIndices(indices, uint16(q.nextIndex))
|
||||
q.nextIndex += len(vertices) / graphics.VertexFloatNum
|
||||
@ -200,6 +195,7 @@ func (q *commandQueue) EnqueueDrawTrianglesCommand(dst, src *Image, vertices []f
|
||||
sourceRegion: sourceRegion,
|
||||
shader: shader,
|
||||
uniforms: uniforms,
|
||||
textures: textures,
|
||||
}
|
||||
q.commands = append(q.commands, c)
|
||||
}
|
||||
@ -326,6 +322,7 @@ type drawTrianglesCommand struct {
|
||||
sourceRegion driver.Region
|
||||
shader *Shader
|
||||
uniforms []interface{}
|
||||
textures []*Image
|
||||
}
|
||||
|
||||
func (c *drawTrianglesCommand) String() string {
|
||||
@ -410,23 +407,18 @@ func (c *drawTrianglesCommand) Exec(indexOffset int) error {
|
||||
}
|
||||
|
||||
if c.shader != nil {
|
||||
us := make([]interface{}, len(c.uniforms))
|
||||
for i := 0; i < len(c.uniforms); i++ {
|
||||
switch v := c.uniforms[i].(type) {
|
||||
case *Image:
|
||||
us[i] = v.image.ID()
|
||||
default:
|
||||
us[i] = v
|
||||
}
|
||||
var ts []driver.ImageID
|
||||
for _, t := range c.textures {
|
||||
ts = append(ts, t.image.ID())
|
||||
}
|
||||
|
||||
// The last uniform variables are added at /shader.go and represents a viewport size.
|
||||
w, h := c.dst.InternalSize()
|
||||
viewport := us[0].([]float32)
|
||||
viewport := c.uniforms[0].([]float32)
|
||||
viewport[0] = float32(w)
|
||||
viewport[1] = float32(h)
|
||||
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), c.shader.shader.ID(), c.nindices, indexOffset, c.mode, us)
|
||||
return theGraphicsDriver.DrawShader(c.dst.image.ID(), c.shader.shader.ID(), c.nindices, indexOffset, c.mode, c.uniforms, ts)
|
||||
}
|
||||
return theGraphicsDriver.Draw(c.dst.image.ID(), c.src.image.ID(), c.nindices, indexOffset, c.mode, c.color, c.filter, c.address, c.sourceRegion)
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ func processSrc(src *Image) {
|
||||
//
|
||||
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
||||
// elements for the source image are not used.
|
||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
if i.lastCommand == lastCommandNone {
|
||||
if !i.screen && mode != driver.CompositeModeClear {
|
||||
panic("graphicscommand: the image must be cleared first")
|
||||
@ -164,14 +164,12 @@ func (i *Image) DrawTriangles(src *Image, vertices []float32, indices []uint16,
|
||||
if src != nil {
|
||||
processSrc(src)
|
||||
}
|
||||
for _, u := range uniforms {
|
||||
if src, ok := u.(*Image); ok {
|
||||
processSrc(src)
|
||||
}
|
||||
for _, t := range textures {
|
||||
processSrc(t)
|
||||
}
|
||||
i.resolveBufferedReplacePixels()
|
||||
|
||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, src, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms)
|
||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, src, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms, textures)
|
||||
|
||||
if i.lastCommand == lastCommandNone && !i.screen {
|
||||
i.lastCommand = lastCommandClear
|
||||
|
@ -44,7 +44,7 @@ func TestClear(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w/2, h/2)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels()
|
||||
if err != nil {
|
||||
@ -74,8 +74,8 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||
dst := NewImage(w, h)
|
||||
vs := quadVertices(w/2, h/2)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
}
|
||||
|
||||
@ -89,14 +89,14 @@ func TestShader(t *testing.T) {
|
||||
dst := NewImage(w, h)
|
||||
vs := quadVertices(w, h)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(clr, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
ir := etesting.ShaderProgramFill(0xff, 0, 0, 0xff)
|
||||
s := NewShader(&ir)
|
||||
us := []interface{}{
|
||||
[]float32{0, 0},
|
||||
}
|
||||
dst.DrawTriangles(nil, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||
dst.DrawTriangles(nil, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
||||
|
||||
pix, err := dst.Pixels()
|
||||
if err != nil {
|
||||
|
@ -796,7 +796,7 @@ func (g *Graphics) NewShader(program *shaderir.Program) (driver.Shader, error) {
|
||||
panic("metal: NewShader is not implemented")
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}, textures []driver.ImageID) error {
|
||||
panic("metal: DrawShader is not implemented")
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@ func (g *Graphics) removeShader(shader *Shader) {
|
||||
delete(g.shaders, shader.id)
|
||||
}
|
||||
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}) error {
|
||||
func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexLen int, indexOffset int, mode driver.CompositeMode, uniforms []interface{}, textures []driver.ImageID) error {
|
||||
d := g.images[dst]
|
||||
s := g.shaders[shader]
|
||||
|
||||
@ -286,20 +286,17 @@ func (g *Graphics) DrawShader(dst driver.ImageID, shader driver.ShaderID, indexL
|
||||
}
|
||||
g.context.blendFunc(mode)
|
||||
|
||||
// TODO: Accept texture variables at another slice than uniforms.
|
||||
us := make([]uniformVariable, 0, len(uniforms))
|
||||
ts := []textureNative{}
|
||||
us := make([]uniformVariable, len(uniforms))
|
||||
for k, v := range uniforms {
|
||||
switch v := v.(type) {
|
||||
case driver.ImageID:
|
||||
ts = append(ts, g.images[v].textureNative)
|
||||
default:
|
||||
us = append(us, uniformVariable{
|
||||
name: fmt.Sprintf("U%d", k),
|
||||
value: v,
|
||||
})
|
||||
us[k].name = fmt.Sprintf("U%d", k)
|
||||
us[k].value = v
|
||||
}
|
||||
|
||||
ts := make([]textureNative, len(textures))
|
||||
for k, v := range textures {
|
||||
ts[k] = g.images[v].textureNative
|
||||
}
|
||||
|
||||
if err := g.useProgram(s.p, us, ts); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -286,5 +286,6 @@ func (g *Graphics) useProgram(program program, uniforms []uniformVariable, textu
|
||||
// Apparently, a texture must be bound every time. The cache is not used here.
|
||||
g.context.bindTexture(t)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom GeoM, color
|
||||
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)
|
||||
is := graphics.QuadIndices()
|
||||
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
m.orig.DrawTriangles(src.orig, vs, is, colorm, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
} else if buf := src.level(bounds, level); buf != nil {
|
||||
w, h := sizeForLevel(bounds.Dx(), bounds.Dy(), level)
|
||||
s := pow2(level)
|
||||
@ -161,12 +161,12 @@ func (m *Mipmap) DrawImage(src *Mipmap, bounds image.Rectangle, geom GeoM, color
|
||||
d *= s
|
||||
vs := quadVertices(0, 0, w, h, a, b, c, d, tx, ty, cr, cg, cb, ca, false)
|
||||
is := graphics.QuadIndices()
|
||||
m.orig.DrawTriangles(buf, vs, is, colorm, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
m.orig.DrawTriangles(buf, vs, is, colorm, mode, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
}
|
||||
m.disposeMipmaps()
|
||||
}
|
||||
|
||||
func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Mipmap) {
|
||||
// TODO: Use a mipmap? (#909)
|
||||
|
||||
if colorm != nil && colorm.ScaleOnly() {
|
||||
@ -190,22 +190,17 @@ func (m *Mipmap) DrawTriangles(src *Mipmap, vertices []float32, indices []uint16
|
||||
s = shader.shader
|
||||
}
|
||||
|
||||
us := make([]interface{}, len(uniforms))
|
||||
for k, v := range uniforms {
|
||||
switch v := v.(type) {
|
||||
case *Mipmap:
|
||||
us[k] = v.orig
|
||||
default:
|
||||
us[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
var srcOrig *shareable.Image
|
||||
if src != nil {
|
||||
srcOrig = src.orig
|
||||
}
|
||||
|
||||
m.orig.DrawTriangles(srcOrig, vertices, indices, colorm, mode, filter, address, sourceRegion, s, us)
|
||||
var ts []*shareable.Image
|
||||
for _, t := range textures {
|
||||
ts = append(ts, t.orig)
|
||||
}
|
||||
|
||||
m.orig.DrawTriangles(srcOrig, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, ts)
|
||||
m.disposeMipmaps()
|
||||
}
|
||||
|
||||
@ -268,7 +263,7 @@ func (m *Mipmap) level(r image.Rectangle, level int) *shareable.Image {
|
||||
return nil
|
||||
}
|
||||
s := shareable.NewImage(w2, h2, m.volatile)
|
||||
s.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
s.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, filter, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
imgs[level] = s
|
||||
|
||||
return imgs[level]
|
||||
|
@ -79,6 +79,7 @@ type drawTrianglesHistoryItem struct {
|
||||
sourceRegion driver.Region
|
||||
shader *Shader
|
||||
uniforms []interface{}
|
||||
textures []*Image
|
||||
}
|
||||
|
||||
// Image represents an image that can be restored when GL context is lost.
|
||||
@ -259,7 +260,7 @@ func fillImage(i *graphicscommand.Image, clr color.RGBA) {
|
||||
// Add 1 pixels for paddings.
|
||||
vs := quadVertices(0, 0, float32(dw), float32(dh), 1, 1, float32(sw-1), float32(sh-1), rf, gf, bf, af)
|
||||
is := graphics.QuadIndices()
|
||||
i.DrawTriangles(emptyImage.image, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
i.DrawTriangles(emptyImage.image, vs, is, nil, compositemode, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
}
|
||||
|
||||
// BasePixelsForTesting returns the image's basePixels for testing.
|
||||
@ -339,20 +340,6 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||
}
|
||||
}
|
||||
|
||||
// convertUniformVariables converts the uniform variables for the lower layer (graphicscommand).
|
||||
func convertUniformVariables(uniforms []interface{}) []interface{} {
|
||||
us := make([]interface{}, len(uniforms))
|
||||
for k, v := range uniforms {
|
||||
switch v := v.(type) {
|
||||
case *Image:
|
||||
us[k] = v.image
|
||||
default:
|
||||
us[k] = v
|
||||
}
|
||||
}
|
||||
return us
|
||||
}
|
||||
|
||||
// DrawTriangles draws triangles with the given image.
|
||||
//
|
||||
// The vertex floats are:
|
||||
@ -365,7 +352,7 @@ func convertUniformVariables(uniforms []interface{}) []interface{} {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 7: Color Y
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
if i.priority {
|
||||
panic("restorable: DrawTriangles cannot be called on a priority image")
|
||||
}
|
||||
@ -380,20 +367,18 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
||||
srcstale = true
|
||||
}
|
||||
if !srcstale {
|
||||
for _, u := range uniforms {
|
||||
if src, ok := u.(*Image); ok {
|
||||
if src.stale || src.volatile {
|
||||
for _, t := range textures {
|
||||
if t.stale || t.volatile {
|
||||
srcstale = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if srcstale || i.screen || !needsRestoring() || i.volatile {
|
||||
i.makeStale()
|
||||
} else {
|
||||
i.appendDrawTrianglesHistory(img, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms)
|
||||
i.appendDrawTrianglesHistory(img, vertices, indices, colorm, mode, filter, address, sourceRegion, shader, uniforms, textures)
|
||||
}
|
||||
var s *graphicscommand.Shader
|
||||
if shader != nil {
|
||||
@ -403,11 +388,16 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
||||
if img != nil {
|
||||
gimg = img.image
|
||||
}
|
||||
i.image.DrawTriangles(gimg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, convertUniformVariables(uniforms))
|
||||
|
||||
var ts []*graphicscommand.Image
|
||||
for _, t := range textures {
|
||||
ts = append(ts, t.image)
|
||||
}
|
||||
i.image.DrawTriangles(gimg, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, ts)
|
||||
}
|
||||
|
||||
// appendDrawTrianglesHistory appends a draw-image history item to the image.
|
||||
func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
if i.stale || i.volatile || i.screen {
|
||||
return
|
||||
}
|
||||
@ -436,6 +426,7 @@ func (i *Image) appendDrawTrianglesHistory(image *Image, vertices []float32, ind
|
||||
sourceRegion: sourceRegion,
|
||||
shader: shader,
|
||||
uniforms: uniforms,
|
||||
textures: textures,
|
||||
}
|
||||
i.drawTrianglesHistory = append(i.drawTrianglesHistory, item)
|
||||
}
|
||||
@ -527,8 +518,8 @@ func (i *Image) dependsOn(target *Image) bool {
|
||||
if c.image == target {
|
||||
return true
|
||||
}
|
||||
for _, v := range c.uniforms {
|
||||
if img, ok := v.(*Image); ok && img == target {
|
||||
for _, t := range c.textures {
|
||||
if t == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@ -553,10 +544,8 @@ func (i *Image) dependingImages() map[*Image]struct{} {
|
||||
if c.image != nil {
|
||||
r[c.image] = struct{}{}
|
||||
}
|
||||
for _, v := range c.uniforms {
|
||||
if img, ok := v.(*Image); ok {
|
||||
r[img] = struct{}{}
|
||||
}
|
||||
for _, t := range c.textures {
|
||||
r[t] = struct{}{}
|
||||
}
|
||||
}
|
||||
return r
|
||||
@ -615,7 +604,11 @@ func (i *Image) restore() error {
|
||||
if c.shader != nil {
|
||||
s = c.shader.shader
|
||||
}
|
||||
gimg.DrawTriangles(img, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.sourceRegion, s, convertUniformVariables(c.uniforms))
|
||||
var ts []*graphicscommand.Image
|
||||
for _, t := range c.textures {
|
||||
ts = append(ts, t.image)
|
||||
}
|
||||
gimg.DrawTriangles(img, c.vertices, c.indices, c.colorm, c.mode, c.filter, c.address, c.sourceRegion, s, c.uniforms, ts)
|
||||
}
|
||||
|
||||
if len(i.drawTrianglesHistory) > 0 {
|
||||
|
@ -131,7 +131,7 @@ func TestRestoreChain(t *testing.T) {
|
||||
for i := 0; i < num-1; i++ {
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
imgs[i+1].DrawTriangles(imgs[i], vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[i+1].DrawTriangles(imgs[i], vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
}
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -173,10 +173,10 @@ func TestRestoreChain2(t *testing.T) {
|
||||
imgs[8].ReplacePixels([]byte{clr8.R, clr8.G, clr8.B, clr8.A}, 0, 0, w, h)
|
||||
|
||||
is := graphics.QuadIndices()
|
||||
imgs[8].DrawTriangles(imgs[7], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[9].DrawTriangles(imgs[8], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[8].DrawTriangles(imgs[7], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
imgs[9].DrawTriangles(imgs[8], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
for i := 0; i < 7; i++ {
|
||||
imgs[i+1].DrawTriangles(imgs[i], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
imgs[i+1].DrawTriangles(imgs[i], quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
}
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -216,10 +216,10 @@ func TestRestoreOverrideSource(t *testing.T) {
|
||||
clr1 := color.RGBA{0x00, 0x00, 0x01, 0xff}
|
||||
img1.ReplacePixels([]byte{clr0.R, clr0.G, clr0.B, clr0.A}, 0, 0, w, h)
|
||||
is := graphics.QuadIndices()
|
||||
img2.DrawTriangles(img1, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles(img2, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img2.DrawTriangles(img1, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img3.DrawTriangles(img2, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, 0, 0, w, h)
|
||||
img1.DrawTriangles(img0, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img0, quadVertices(w, h, 0, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -298,23 +298,23 @@ func TestRestoreComplexGraph(t *testing.T) {
|
||||
}()
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
img3.DrawTriangles(img0, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles(img0, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img3.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img3.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img4.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles(img1, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 2, 0)
|
||||
img4.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img5.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img5.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img6.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img6.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 1, 0)
|
||||
img6.DrawTriangles(img4, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img6.DrawTriangles(img4, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 0, 0)
|
||||
img7.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img7.DrawTriangles(img2, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
vs = quadVertices(w, h, 2, 0)
|
||||
img7.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img7.DrawTriangles(img3, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -406,8 +406,8 @@ func TestRestoreRecursive(t *testing.T) {
|
||||
img0.Dispose()
|
||||
}()
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img0, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles(img1, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img0, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img0.DrawTriangles(img1, quadVertices(w, h, 1, 0), is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@ -501,7 +501,7 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
|
||||
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img1.ReplacePixels([]byte{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, 0, 0, 2, 1)
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -538,8 +538,8 @@ func TestDispose(t *testing.T) {
|
||||
defer img2.Dispose()
|
||||
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img2, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles(img1, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img2, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img0.DrawTriangles(img1, quadVertices(1, 1, 0, 0), is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img1.Dispose()
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -647,7 +647,7 @@ func TestReplacePixelsOnly(t *testing.T) {
|
||||
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img0, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
img0.ReplacePixels([]byte{5, 6, 7, 8}, 0, 0, 1, 1)
|
||||
|
||||
// BasePixelsForTesting is available without GPU accessing.
|
||||
@ -700,7 +700,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
|
||||
src.ReplacePixels(pix, 0, 0, w, h)
|
||||
vs := quadVertices(1, 1, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
// Read the pixels. If the implementation is correct, dst tries to read its pixels from GPU due to being
|
||||
// stale.
|
||||
@ -721,7 +721,7 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4*w*h), 0, 0, w, h)
|
||||
// ReplacePixels for a whole image doesn't panic.
|
||||
}
|
||||
@ -739,7 +739,7 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
}
|
||||
|
||||
@ -828,7 +828,7 @@ func TestFill2(t *testing.T) {
|
||||
dst := NewImage(w, h, false)
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
// Fill src with a different color. This should not affect dst.
|
||||
src.Fill(color.RGBA{0, 0xff, 0, 0xff})
|
||||
@ -867,7 +867,7 @@ func TestMutateSlices(t *testing.T) {
|
||||
vs := quadVertices(w, h, 0, 0)
|
||||
is := make([]uint16, len(graphics.QuadIndices()))
|
||||
copy(is, graphics.QuadIndices())
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
for i := range vs {
|
||||
vs[i] = 0
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ func TestShader(t *testing.T) {
|
||||
us := []interface{}{
|
||||
[]float32{0, 0},
|
||||
}
|
||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
t.Fatal(err)
|
||||
@ -74,9 +74,8 @@ func TestShaderChain(t *testing.T) {
|
||||
for i := 0; i < num-1; i++ {
|
||||
us := []interface{}{
|
||||
[]float32{0, 0},
|
||||
imgs[i],
|
||||
}
|
||||
imgs[i+1].DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||
imgs[i+1].DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, imgs[i:i+1])
|
||||
}
|
||||
|
||||
if err := ResolveStaleImages(); err != nil {
|
||||
@ -114,11 +113,8 @@ func TestShaderMultipleSources(t *testing.T) {
|
||||
s := NewShader(&ir)
|
||||
us := []interface{}{
|
||||
[]float32{0, 0},
|
||||
srcs[0],
|
||||
srcs[1],
|
||||
srcs[2],
|
||||
}
|
||||
dst.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||
dst.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, srcs)
|
||||
|
||||
// Clear one of the sources after DrawTriangles. dst should not be affected.
|
||||
srcs[0].Fill(color.RGBA{})
|
||||
@ -150,7 +146,7 @@ func TestShaderDispose(t *testing.T) {
|
||||
us := []interface{}{
|
||||
[]float32{0, 0},
|
||||
}
|
||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us)
|
||||
img.DrawTriangles(nil, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, s, us, nil)
|
||||
|
||||
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
|
||||
// stale.
|
||||
|
@ -220,7 +220,7 @@ func (i *Image) ensureNotShared() {
|
||||
dx1, dy1, sx1, sy1, 1, 1, 1, 1,
|
||||
}
|
||||
is := graphics.QuadIndices()
|
||||
newImg.DrawTriangles(i.backend.restorable, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
newImg.DrawTriangles(i.backend.restorable, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
i.dispose(false)
|
||||
i.backend = &backend{
|
||||
@ -305,7 +305,7 @@ func makeSharedIfNeeded(src *Image) {
|
||||
// 5: Color G
|
||||
// 6: Color B
|
||||
// 7: Color Y
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||
func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}, textures []*Image) {
|
||||
backendsM.Lock()
|
||||
// Do not use defer for performance.
|
||||
|
||||
@ -318,14 +318,12 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
||||
i.processSrc(img)
|
||||
}
|
||||
firstImg := img
|
||||
for _, u := range uniforms {
|
||||
if src, ok := u.(*Image); ok {
|
||||
for _, src := range textures {
|
||||
if firstImg == nil {
|
||||
firstImg = src
|
||||
}
|
||||
i.processSrc(src)
|
||||
}
|
||||
}
|
||||
|
||||
var dx, dy float32
|
||||
// A screen image doesn't have its padding.
|
||||
@ -358,21 +356,16 @@ func (i *Image) DrawTriangles(img *Image, vertices []float32, indices []uint16,
|
||||
s = shader.shader
|
||||
}
|
||||
|
||||
us := make([]interface{}, len(uniforms))
|
||||
for i := 0; i < len(uniforms); i++ {
|
||||
switch v := uniforms[i].(type) {
|
||||
case *Image:
|
||||
us[i] = v.backend.restorable
|
||||
default:
|
||||
us[i] = v
|
||||
}
|
||||
var ts []*restorable.Image
|
||||
for _, t := range textures {
|
||||
ts = append(ts, t.backend.restorable)
|
||||
}
|
||||
|
||||
var r *restorable.Image
|
||||
if img != nil {
|
||||
r = img.backend.restorable
|
||||
}
|
||||
i.backend.restorable.DrawTriangles(r, vertices, indices, colorm, mode, filter, address, sourceRegion, s, us)
|
||||
i.backend.restorable.DrawTriangles(r, vertices, indices, colorm, mode, filter, address, sourceRegion, s, uniforms, ts)
|
||||
|
||||
i.nonUpdatedCount = 0
|
||||
delete(imagesToMakeShared, i)
|
||||
|
@ -96,7 +96,7 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
// img4.ensureNotShared() should be called.
|
||||
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.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
want := false
|
||||
if got := img4.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
@ -126,7 +126,7 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
|
||||
// Check further drawing doesn't cause panic.
|
||||
// This bug was fixed by 03dcd948.
|
||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img4.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
}
|
||||
|
||||
func TestReshared(t *testing.T) {
|
||||
@ -166,7 +166,7 @@ func TestReshared(t *testing.T) {
|
||||
// Use img1 as a render target.
|
||||
vs := quadVertices(size, size, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img1.DrawTriangles(img2, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -176,7 +176,7 @@ func TestReshared(t *testing.T) {
|
||||
if err := MakeImagesSharedForTesting(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -203,7 +203,7 @@ func TestReshared(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles(img1, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if got, want := img1.IsSharedForTesting(), true; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -231,7 +231,7 @@ func TestReshared(t *testing.T) {
|
||||
if err := MakeImagesSharedForTesting(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
img0.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
img0.DrawTriangles(img3, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
if got, want := img3.IsSharedForTesting(), false; got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -326,7 +326,7 @@ func TestReplacePixelsAfterDrawTriangles(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
dst.ReplacePixels(pix)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, w, h)
|
||||
@ -368,7 +368,7 @@ func TestSmallImages(t *testing.T) {
|
||||
|
||||
vs := quadVertices(w, h, 0, 0, 1)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, w, h)
|
||||
if err != nil {
|
||||
@ -410,7 +410,7 @@ func TestLongImages(t *testing.T) {
|
||||
const scale = 120
|
||||
vs := quadVertices(w, h, 0, 0, scale)
|
||||
is := graphics.QuadIndices()
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||
dst.DrawTriangles(src, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil, nil)
|
||||
|
||||
pix, err := dst.Pixels(0, 0, dstW, dstH)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user