Skip to content

Commit

Permalink
internal/restorable: treat texels instead of pixels
Browse files Browse the repository at this point in the history
Updates #1820
  • Loading branch information
hajimehoshi committed Apr 1, 2022
1 parent 0c6362c commit 34e23f5
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 96 deletions.
11 changes: 9 additions & 2 deletions internal/atlas/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,11 @@ func (i *Image) ensureIsolated() {
sy0 := float32(oy)
sx1 := float32(ox + w)
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.SetVolatile(i.volatile)
vs := []float32{
Expand Down Expand Up @@ -437,12 +442,14 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f
ox += paddingSize
oy += paddingSize
oxf, oyf = float32(ox), float32(oy)
sw, sh := srcs[0].backend.restorable.InternalSize()
swf, shf := float32(sw), float32(sh)
n := len(vertices)
for i := 0; i < n; i += graphics.VertexFloatNum {
vertices[i] += dx
vertices[i+1] += dy
vertices[i+2] += oxf
vertices[i+3] += oyf
vertices[i+2] = (vertices[i+2] + oxf) / swf
vertices[i+3] = (vertices[i+3] + oyf) / shf
}
// srcRegion can be delibarately empty when this is not needed in order to avoid unexpected
// performance issue (#1293).
Expand Down
19 changes: 17 additions & 2 deletions internal/atlas/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ func TestEnsureIsolated(t *testing.T) {
img4 := atlas.NewImage(size, size)
defer img4.MarkDisposed()

img5 := atlas.NewImage(size/2, size/2)
defer img3.MarkDisposed()

pix := make([]byte, size*size*4)
for j := 0; j < size; j++ {
for i := 0; i < size; i++ {
Expand Down Expand Up @@ -105,8 +108,20 @@ func TestEnsureIsolated(t *testing.T) {
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)
want := false
if got := img4.IsOnAtlasForTesting(); got != want {
if got, want := img4.IsOnAtlasForTesting(), false; 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)
}

Expand Down
35 changes: 0 additions & 35 deletions internal/graphicscommand/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,6 @@ type commandQueue struct {
// Rename or fix the program.
nvertices int

srcSizes []size

indices []uint16
nindices int

Expand All @@ -97,26 +95,8 @@ func (q *commandQueue) appendVertices(vertices []float32, src *Image) {
if len(q.vertices) < q.nvertices+len(vertices) {
n := q.nvertices + len(vertices) - len(q.vertices)
q.vertices = append(q.vertices, make([]float32, n)...)
q.srcSizes = append(q.srcSizes, make([]size, n/graphics.VertexFloatNum)...)
}
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)
}

Expand Down Expand Up @@ -231,14 +211,8 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics) error {
if graphicsDriver.HasHighPrecisionFloat() {
n := q.nvertices / graphics.VertexFloatNum
for i := 0; i < n; i++ {
s := q.srcSizes[i]

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).
// Instead, align the vertices with about 1/3 pixels.
x := vs[idx]
Expand Down Expand Up @@ -268,15 +242,6 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics) error {
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 {
Expand Down
4 changes: 2 additions & 2 deletions internal/graphicscommand/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,8 +126,8 @@ func (i *Image) InternalSize() (int, int) {
//
// 0: Destination X in pixels
// 1: Destination Y in pixels
// 2: Source X in pixels (not texels!)
// 3: Source Y in pixels
// 2: Source X in texels
// 3: Source Y in texels
// 4: Color R [0.0-1.0]
// 5: Color G
// 6: Color B
Expand Down
18 changes: 10 additions & 8 deletions internal/graphicscommand/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,14 @@ func TestMain(m *testing.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{
0, 0, 0, 0, 1, 1, 1, 1,
w, 0, w, 0, 1, 1, 1, 1,
0, w, 0, h, 1, 1, 1, 1,
w, h, w, h, 1, 1, 1, 1,
w, 0, w / swf, 0, 1, 1, 1, 1,
0, w, 0, h / shf, 1, 1, 1, 1,
w, h, w / swf, h / shf, 1, 1, 1, 1,
}
}

Expand All @@ -44,7 +46,7 @@ func TestClear(t *testing.T) {
src := graphicscommand.NewImage(w/2, h/2)
dst := graphicscommand.NewImage(w, h)

vs := quadVertices(w/2, h/2)
vs := quadVertices(src, w/2, h/2)
is := graphics.QuadIndices()
dr := graphicsdriver.Region{
X: 0,
Expand Down Expand Up @@ -75,7 +77,7 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
clr := graphicscommand.NewImage(w, h)
src := graphicscommand.NewImage(w/2, h/2)
dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w/2, h/2)
vs := quadVertices(src, w/2, h/2)
is := graphics.QuadIndices()
dr := graphicsdriver.Region{
X: 0,
Expand All @@ -95,7 +97,7 @@ func TestReplacePixelsWithMask(t *testing.T) {
src := graphicscommand.NewImage(w, h)
dst := graphicscommand.NewImage(w, h)

vs := quadVertices(w, h)
vs := quadVertices(src, w, h)
is := graphics.QuadIndices()
dr := graphicsdriver.Region{
X: 0,
Expand Down Expand Up @@ -143,7 +145,7 @@ func TestShader(t *testing.T) {
const w, h = 16, 16
clr := graphicscommand.NewImage(w, h)
dst := graphicscommand.NewImage(w, h)
vs := quadVertices(w, h)
vs := quadVertices(clr, w, h)
is := graphics.QuadIndices()
dr := graphicsdriver.Region{
X: 0,
Expand Down
26 changes: 15 additions & 11 deletions internal/restorable/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ func (i *Image) Extend(width, height int) *Image {
srcs := [graphics.ShaderImageNum]*Image{i}
var offsets [graphics.ShaderImageNum - 1][2]float32
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()
dr := graphicsdriver.Region{
X: 0,
Expand Down Expand Up @@ -230,12 +230,14 @@ func NewScreenFramebufferImage(width, height int) *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{
dx0, dy0, sx0, sy0, cr, cg, cb, ca,
dx1, dy0, sx1, sy0, cr, cg, cb, ca,
dx0, dy1, sx0, sy1, cr, cg, cb, ca,
dx1, dy1, sx1, sy1, cr, cg, cb, ca,
dx0, dy0, sx0 / swf, sy0 / shf, cr, cg, cb, ca,
dx1, dy0, sx1 / swf, sy0 / shf, cr, cg, cb, ca,
dx0, dy1, sx0 / swf, sy1 / shf, cr, cg, cb, ca,
dx1, dy1, sx1 / swf, sy1 / shf, cr, cg, cb, ca,
}
}

Expand All @@ -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
// devices.
//
// TODO: Can we unexport InternalSize()?
dw, dh := i.InternalSize()
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()
srcs := [graphics.ShaderImageNum]*graphicscommand.Image{emptyImage.image}
var offsets [graphics.ShaderImageNum - 1][2]float32
Expand Down Expand Up @@ -359,8 +359,8 @@ func (i *Image) ReplacePixels(pixels []byte, mask []byte, x, y, width, height in
//
// 0: Destination X in pixels
// 1: Destination Y in pixels
// 2: Source X in pixels (not texels!)
// 3: Source Y in pixels
// 2: Source X in texels
// 3: Source Y in texels
// 4: Color R [0.0-1.0]
// 5: Color G
// 6: Color B
Expand Down Expand Up @@ -673,3 +673,7 @@ func (i *Image) clearDrawTrianglesHistory() {
}
i.drawTrianglesHistory = i.drawTrianglesHistory[:0]
}

func (i *Image) InternalSize() (int, int) {
return i.image.InternalSize()
}
Loading

0 comments on commit 34e23f5

Please sign in to comment.