internal/restorable: treat texels instead of pixels

Updates #1820
This commit is contained in:
Hajime Hoshi 2022-04-02 00:32:16 +09:00
parent 0c6362c93a
commit 34e23f5256
8 changed files with 95 additions and 96 deletions

View File

@ -277,6 +277,11 @@ func (i *Image) ensureIsolated() {
sy0 := float32(oy) sy0 := float32(oy)
sx1 := float32(ox + w) sx1 := float32(ox + w)
sy1 := float32(oy + h) sy1 := float32(oy + h)
sw, sh := i.backend.restorable.InternalSize()
sx0 /= float32(sw)
sy0 /= float32(sh)
sx1 /= float32(sw)
sy1 /= float32(sh)
newImg := restorable.NewImage(w, h) newImg := restorable.NewImage(w, h)
newImg.SetVolatile(i.volatile) newImg.SetVolatile(i.volatile)
vs := []float32{ vs := []float32{
@ -437,12 +442,14 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
ox += paddingSize ox += paddingSize
oy += paddingSize oy += paddingSize
oxf, oyf = float32(ox), float32(oy) oxf, oyf = float32(ox), float32(oy)
sw, sh := srcs[0].backend.restorable.InternalSize()
swf, shf := float32(sw), float32(sh)
n := len(vertices) n := len(vertices)
for i := 0; i < n; i += graphics.VertexFloatNum { for i := 0; i < n; i += graphics.VertexFloatNum {
vertices[i] += dx vertices[i] += dx
vertices[i+1] += dy vertices[i+1] += dy
vertices[i+2] += oxf vertices[i+2] = (vertices[i+2] + oxf) / swf
vertices[i+3] += oyf vertices[i+3] = (vertices[i+3] + oyf) / shf
} }
// srcRegion can be delibarately empty when this is not needed in order to avoid unexpected // srcRegion can be delibarately empty when this is not needed in order to avoid unexpected
// performance issue (#1293). // performance issue (#1293).

View File

@ -78,6 +78,9 @@ func TestEnsureIsolated(t *testing.T) {
img4 := atlas.NewImage(size, size) img4 := atlas.NewImage(size, size)
defer img4.MarkDisposed() defer img4.MarkDisposed()
img5 := atlas.NewImage(size/2, size/2)
defer img3.MarkDisposed()
pix := make([]byte, size*size*4) pix := make([]byte, size*size*4)
for j := 0; j < size; j++ { for j := 0; j < size; j++ {
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
@ -105,8 +108,20 @@ func TestEnsureIsolated(t *testing.T) {
Height: size, Height: size,
} }
img4.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{img3}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false) img4.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{img3}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
want := false if got, want := img4.IsOnAtlasForTesting(), false; got != want {
if got := img4.IsOnAtlasForTesting(); got != want { t.Errorf("got: %v, want: %v", got, want)
}
// Make img3 isolated before getting pixels.
vs = quadVertices(0, 0, size/2, size/2, 1)
dr = graphicsdriver.Region{
X: 0,
Y: 0,
Width: size / 2,
Height: size / 2,
}
img3.DrawTriangles([graphics.ShaderImageNum]*atlas.Image{img5}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, [graphics.ShaderImageNum - 1][2]float32{}, nil, nil, false)
if got, want := img3.IsOnAtlasForTesting(), false; got != want {
t.Errorf("got: %v, want: %v", got, want) t.Errorf("got: %v, want: %v", got, want)
} }

View File

@ -78,8 +78,6 @@ type commandQueue struct {
// Rename or fix the program. // Rename or fix the program.
nvertices int nvertices int
srcSizes []size
indices []uint16 indices []uint16
nindices int nindices int
@ -97,26 +95,8 @@ func (q *commandQueue) appendVertices(vertices []float32, src *Image) {
if len(q.vertices) < q.nvertices+len(vertices) { if len(q.vertices) < q.nvertices+len(vertices) {
n := q.nvertices + len(vertices) - len(q.vertices) n := q.nvertices + len(vertices) - len(q.vertices)
q.vertices = append(q.vertices, make([]float32, n)...) q.vertices = append(q.vertices, make([]float32, n)...)
q.srcSizes = append(q.srcSizes, make([]size, n/graphics.VertexFloatNum)...)
} }
copy(q.vertices[q.nvertices:], vertices) copy(q.vertices[q.nvertices:], vertices)
n := len(vertices) / graphics.VertexFloatNum
base := q.nvertices / graphics.VertexFloatNum
width := float32(1)
height := float32(1)
// src is nil when a shader is used and there are no specified images.
if src != nil {
w, h := src.InternalSize()
width = float32(w)
height = float32(h)
}
for i := 0; i < n; i++ {
idx := base + i
q.srcSizes[idx].width = width
q.srcSizes[idx].height = height
}
q.nvertices += len(vertices) q.nvertices += len(vertices)
} }
@ -231,14 +211,8 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics) error {
if graphicsDriver.HasHighPrecisionFloat() { if graphicsDriver.HasHighPrecisionFloat() {
n := q.nvertices / graphics.VertexFloatNum n := q.nvertices / graphics.VertexFloatNum
for i := 0; i < n; i++ { for i := 0; i < n; i++ {
s := q.srcSizes[i]
idx := i * graphics.VertexFloatNum idx := i * graphics.VertexFloatNum
// Convert pixels to texels.
vs[idx+2] /= s.width
vs[idx+3] /= s.height
// Avoid the center of the pixel, which is problematic (#929, #1171). // Avoid the center of the pixel, which is problematic (#929, #1171).
// Instead, align the vertices with about 1/3 pixels. // Instead, align the vertices with about 1/3 pixels.
x := vs[idx] x := vs[idx]
@ -268,15 +242,6 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics) error {
vs[idx+1] = iy + 16.0/16.0 vs[idx+1] = iy + 16.0/16.0
} }
} }
} else {
n := q.nvertices / graphics.VertexFloatNum
for i := 0; i < n; i++ {
s := q.srcSizes[i]
// Convert pixels to texels.
vs[i*graphics.VertexFloatNum+2] /= s.width
vs[i*graphics.VertexFloatNum+3] /= s.height
}
} }
if err := graphicsDriver.Begin(); err != nil { if err := graphicsDriver.Begin(); err != nil {

View File

@ -126,8 +126,8 @@ func (i *Image) InternalSize() (int, int) {
// //
// 0: Destination X in pixels // 0: Destination X in pixels
// 1: Destination Y in pixels // 1: Destination Y in pixels
// 2: Source X in pixels (not texels!) // 2: Source X in texels
// 3: Source Y in pixels // 3: Source Y in texels
// 4: Color R [0.0-1.0] // 4: Color R [0.0-1.0]
// 5: Color G // 5: Color G
// 6: Color B // 6: Color B

View File

@ -30,12 +30,14 @@ func TestMain(m *testing.M) {
etesting.MainWithRunLoop(m) etesting.MainWithRunLoop(m)
} }
func quadVertices(w, h float32) []float32 { func quadVertices(srcImage *graphicscommand.Image, w, h float32) []float32 {
sw, sh := srcImage.InternalSize()
swf, shf := float32(sw), float32(sh)
return []float32{ return []float32{
0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1,
w, 0, w, 0, 1, 1, 1, 1, w, 0, w / swf, 0, 1, 1, 1, 1,
0, w, 0, h, 1, 1, 1, 1, 0, w, 0, h / shf, 1, 1, 1, 1,
w, h, w, h, 1, 1, 1, 1, w, h, w / swf, h / shf, 1, 1, 1, 1,
} }
} }
@ -44,7 +46,7 @@ func TestClear(t *testing.T) {
src := graphicscommand.NewImage(w/2, h/2) src := graphicscommand.NewImage(w/2, h/2)
dst := graphicscommand.NewImage(w, h) dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w/2, h/2) vs := quadVertices(src, w/2, h/2)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -75,7 +77,7 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
clr := graphicscommand.NewImage(w, h) clr := graphicscommand.NewImage(w, h)
src := graphicscommand.NewImage(w/2, h/2) src := graphicscommand.NewImage(w/2, h/2)
dst := graphicscommand.NewImage(w, h) dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w/2, h/2) vs := quadVertices(src, w/2, h/2)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -95,7 +97,7 @@ func TestReplacePixelsWithMask(t *testing.T) {
src := graphicscommand.NewImage(w, h) src := graphicscommand.NewImage(w, h)
dst := graphicscommand.NewImage(w, h) dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w, h) vs := quadVertices(src, w, h)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -143,7 +145,7 @@ func TestShader(t *testing.T) {
const w, h = 16, 16 const w, h = 16, 16
clr := graphicscommand.NewImage(w, h) clr := graphicscommand.NewImage(w, h)
dst := graphicscommand.NewImage(w, h) dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w, h) vs := quadVertices(clr, w, h)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,

View File

@ -191,7 +191,7 @@ func (i *Image) Extend(width, height int) *Image {
srcs := [graphics.ShaderImageNum]*Image{i} srcs := [graphics.ShaderImageNum]*Image{i}
var offsets [graphics.ShaderImageNum - 1][2]float32 var offsets [graphics.ShaderImageNum - 1][2]float32
sw, sh := i.image.InternalSize() sw, sh := i.image.InternalSize()
vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1) vs := quadVertices(i, 0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -230,12 +230,14 @@ func NewScreenFramebufferImage(width, height int) *Image {
} }
// quadVertices returns vertices to render a quad. These values are passed to graphicscommand.Image. // quadVertices returns vertices to render a quad. These values are passed to graphicscommand.Image.
func quadVertices(dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1, cr, cg, cb, ca float32) []float32 { func quadVertices(src *Image, dx0, dy0, dx1, dy1, sx0, sy0, sx1, sy1, cr, cg, cb, ca float32) []float32 {
sw, sh := src.InternalSize()
swf, shf := float32(sw), float32(sh)
return []float32{ return []float32{
dx0, dy0, sx0, sy0, cr, cg, cb, ca, dx0, dy0, sx0 / swf, sy0 / shf, cr, cg, cb, ca,
dx1, dy0, sx1, sy0, cr, cg, cb, ca, dx1, dy0, sx1 / swf, sy0 / shf, cr, cg, cb, ca,
dx0, dy1, sx0, sy1, cr, cg, cb, ca, dx0, dy1, sx0 / swf, sy1 / shf, cr, cg, cb, ca,
dx1, dy1, sx1, sy1, cr, cg, cb, ca, dx1, dy1, sx1 / swf, sy1 / shf, cr, cg, cb, ca,
} }
} }
@ -248,11 +250,9 @@ func clearImage(i *graphicscommand.Image) {
// This needs to use 'InternalSize' to render the whole region, or edges are unexpectedly cleared on some // This needs to use 'InternalSize' to render the whole region, or edges are unexpectedly cleared on some
// devices. // devices.
//
// TODO: Can we unexport InternalSize()?
dw, dh := i.InternalSize() dw, dh := i.InternalSize()
sw, sh := emptyImage.width, emptyImage.height sw, sh := emptyImage.width, emptyImage.height
vs := quadVertices(0, 0, float32(dw), float32(dh), 1, 1, float32(sw-1), float32(sh-1), 0, 0, 0, 0) vs := quadVertices(emptyImage, 0, 0, float32(dw), float32(dh), 1, 1, float32(sw-1), float32(sh-1), 0, 0, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image} srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}
var offsets [graphics.ShaderImageNum - 1][2]float32 var offsets [graphics.ShaderImageNum - 1][2]float32
@ -359,8 +359,8 @@ func (i *Image) ReplacePixels(pixels []byte, mask []byte, x, y, width, height in
// //
// 0: Destination X in pixels // 0: Destination X in pixels
// 1: Destination Y in pixels // 1: Destination Y in pixels
// 2: Source X in pixels (not texels!) // 2: Source X in texels
// 3: Source Y in pixels // 3: Source Y in texels
// 4: Color R [0.0-1.0] // 4: Color R [0.0-1.0]
// 5: Color G // 5: Color G
// 6: Color B // 6: Color B
@ -673,3 +673,7 @@ func (i *Image) clearDrawTrianglesHistory() {
} }
i.drawTrianglesHistory = i.drawTrianglesHistory[:0] i.drawTrianglesHistory = i.drawTrianglesHistory[:0]
} }
func (i *Image) InternalSize() (int, int) {
return i.image.InternalSize()
}

View File

@ -99,7 +99,7 @@ func TestRestoreWithoutDraw(t *testing.T) {
} }
} }
func quadVertices(sw, sh, x, y int) []float32 { func quadVertices(srcImage *restorable.Image, sw, sh, x, y int) []float32 {
dx0 := float32(x) dx0 := float32(x)
dy0 := float32(y) dy0 := float32(y)
dx1 := float32(x + sw) dx1 := float32(x + sw)
@ -108,11 +108,17 @@ func quadVertices(sw, sh, x, y int) []float32 {
sy0 := float32(0) sy0 := float32(0)
sx1 := float32(sw) sx1 := float32(sw)
sy1 := float32(sh) sy1 := float32(sh)
iswf := float32(1)
ishf := float32(1)
if srcImage != nil {
isw, ish := srcImage.InternalSize()
iswf, ishf = float32(isw), float32(ish)
}
return []float32{ return []float32{
dx0, dy0, sx0, sy0, 1, 1, 1, 1, dx0, dy0, sx0 / iswf, sy0 / ishf, 1, 1, 1, 1,
dx1, dy0, sx1, sy0, 1, 1, 1, 1, dx1, dy0, sx1 / iswf, sy0 / ishf, 1, 1, 1, 1,
dx0, dy1, sx0, sy1, 1, 1, 1, 1, dx0, dy1, sx0 / iswf, sy1 / ishf, 1, 1, 1, 1,
dx1, dy1, sx1, sy1, 1, 1, 1, 1, dx1, dy1, sx1 / iswf, sy1 / ishf, 1, 1, 1, 1,
} }
} }
@ -131,7 +137,7 @@ func TestRestoreChain(t *testing.T) {
clr := color.RGBA{0x00, 0x00, 0x00, 0xff} clr := color.RGBA{0x00, 0x00, 0x00, 0xff}
imgs[0].ReplacePixels([]byte{clr.R, clr.G, clr.B, clr.A}, nil, 0, 0, 1, 1) imgs[0].ReplacePixels([]byte{clr.R, clr.G, clr.B, clr.A}, nil, 0, 0, 1, 1)
for i := 0; i < num-1; i++ { for i := 0; i < num-1; i++ {
vs := quadVertices(1, 1, 0, 0) vs := quadVertices(imgs[i], 1, 1, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -187,10 +193,10 @@ func TestRestoreChain2(t *testing.T) {
Width: w, Width: w,
Height: h, Height: h,
} }
imgs[8].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) imgs[8].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[7]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(imgs[7], w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
imgs[9].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) imgs[9].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[8]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(imgs[8], w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
for i := 0; i < 7; i++ { for i := 0; i < 7; i++ {
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(imgs[i], w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
@ -236,10 +242,10 @@ func TestRestoreOverrideSource(t *testing.T) {
Width: w, Width: w,
Height: h, Height: h,
} }
img2.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img2.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img1, w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img2, w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, nil, 0, 0, w, h) img0.ReplacePixels([]byte{clr1.R, clr1.G, clr1.B, clr1.A}, nil, 0, 0, w, h)
img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img0, w, h, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -316,7 +322,6 @@ func TestRestoreComplexGraph(t *testing.T) {
img1.Dispose() img1.Dispose()
img0.Dispose() img0.Dispose()
}() }()
vs := quadVertices(w, h, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -325,22 +330,23 @@ func TestRestoreComplexGraph(t *testing.T) {
Height: h, Height: h,
} }
var offsets [graphics.ShaderImageNum - 1][2]float32 var offsets [graphics.ShaderImageNum - 1][2]float32
vs := quadVertices(img0, w, h, 0, 0)
img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 1, 0) vs = quadVertices(img1, w, h, 1, 0)
img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img3.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 1, 0) vs = quadVertices(img1, w, h, 1, 0)
img4.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img4.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 2, 0) vs = quadVertices(img2, w, h, 2, 0)
img4.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img4.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 0, 0) vs = quadVertices(img3, w, h, 0, 0)
img5.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img5.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 0, 0) vs = quadVertices(img3, w, h, 0, 0)
img6.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img6.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 1, 0) vs = quadVertices(img4, w, h, 1, 0)
img6.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img4}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img6.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img4}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 0, 0) vs = quadVertices(img2, w, h, 0, 0)
img7.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img7.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
vs = quadVertices(w, h, 2, 0) vs = quadVertices(img3, w, h, 2, 0)
img7.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img7.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img3}, offsets, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
@ -439,8 +445,8 @@ func TestRestoreRecursive(t *testing.T) {
Width: w, Width: w,
Height: h, Height: h,
} }
img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img0}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img0, w, h, 1, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
img0.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(w, h, 1, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img0.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img1, w, h, 1, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -532,7 +538,7 @@ func TestDrawTrianglesAndReplacePixels(t *testing.T) {
img1 := restorable.NewImage(2, 1) img1 := restorable.NewImage(2, 1)
defer img1.Dispose() defer img1.Dispose()
vs := quadVertices(1, 1, 0, 0) vs := quadVertices(img0, 1, 1, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -583,8 +589,8 @@ func TestDispose(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img1.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img2}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img2, 1, 1, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
img0.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false) img0.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{img1}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(img1, 1, 1, 0, 0), is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
img1.Dispose() img1.Dispose()
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
@ -690,7 +696,7 @@ func TestReplacePixelsOnly(t *testing.T) {
img0.ReplacePixels([]byte{1, 2, 3, 4}, nil, i%w, i/w, 1, 1) img0.ReplacePixels([]byte{1, 2, 3, 4}, nil, i%w, i/w, 1, 1)
} }
vs := quadVertices(1, 1, 0, 0) vs := quadVertices(img0, 1, 1, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -750,7 +756,7 @@ func TestReadPixelsFromVolatileImage(t *testing.T) {
pix[i] = 0xff pix[i] = 0xff
} }
src.ReplacePixels(pix, nil, 0, 0, w, h) src.ReplacePixels(pix, nil, 0, 0, w, h)
vs := quadVertices(1, 1, 0, 0) vs := quadVertices(src, 1, 1, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -777,7 +783,7 @@ func TestAllowReplacePixelsAfterDrawTriangles(t *testing.T) {
src := restorable.NewImage(w, h) src := restorable.NewImage(w, h)
dst := restorable.NewImage(w, h) dst := restorable.NewImage(w, h)
vs := quadVertices(w, h, 0, 0) vs := quadVertices(src, w, h, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -801,7 +807,7 @@ func TestDisallowReplacePixelsForPartAfterDrawTriangles(t *testing.T) {
src := restorable.NewImage(w, h) src := restorable.NewImage(w, h)
dst := restorable.NewImage(w, h) dst := restorable.NewImage(w, h)
vs := quadVertices(w, h, 0, 0) vs := quadVertices(src, w, h, 0, 0)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{
X: 0, X: 0,
@ -877,7 +883,7 @@ func TestMutateSlices(t *testing.T) {
} }
src.ReplacePixels(pix, nil, 0, 0, w, h) src.ReplacePixels(pix, nil, 0, 0, w, h)
vs := quadVertices(w, h, 0, 0) vs := quadVertices(src, w, h, 0, 0)
is := make([]uint16, len(graphics.QuadIndices())) is := make([]uint16, len(graphics.QuadIndices()))
copy(is, graphics.QuadIndices()) copy(is, graphics.QuadIndices())
dr := graphicsdriver.Region{ dr := graphicsdriver.Region{

View File

@ -65,7 +65,7 @@ func TestShader(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
img.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false) img.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false)
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err) t.Fatal(err)
@ -100,7 +100,7 @@ func TestShaderChain(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false) imgs[i+1].DrawTriangles([graphics.ShaderImageNum]*restorable.Image{imgs[i]}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(imgs[i], 1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false)
} }
if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil { if err := restorable.ResolveStaleImages(ui.GraphicsDriverForTesting()); err != nil {
@ -138,7 +138,7 @@ func TestShaderMultipleSources(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false) dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false)
// Clear one of the sources after DrawTriangles. dst should not be affected. // Clear one of the sources after DrawTriangles. dst should not be affected.
clearImage(srcs[0], 1, 1) clearImage(srcs[0], 1, 1)
@ -179,7 +179,7 @@ func TestShaderMultipleSourcesOnOneTexture(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
dst.DrawTriangles(srcs, offsets, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false) dst.DrawTriangles(srcs, offsets, quadVertices(srcs[0], 1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false)
// Clear one of the sources after DrawTriangles. dst should not be affected. // Clear one of the sources after DrawTriangles. dst should not be affected.
clearImage(srcs[0], 3, 1) clearImage(srcs[0], 3, 1)
@ -209,7 +209,7 @@ func TestShaderDispose(t *testing.T) {
Width: 1, Width: 1,
Height: 1, Height: 1,
} }
img.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false) img.DrawTriangles([graphics.ShaderImageNum]*restorable.Image{}, [graphics.ShaderImageNum - 1][2]float32{}, quadVertices(nil, 1, 1, 0, 0), graphics.QuadIndices(), nil, graphicsdriver.CompositeModeCopy, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, s, nil, false)
// Dispose the shader. This should invalidates all the images using this shader i.e., all the images become // Dispose the shader. This should invalidates all the images using this shader i.e., all the images become
// stale. // stale.