graphics: Restrict QuadVertices to allow only power of 2 sizes

Now QuadVertices can skip calculating power of 2 values.
This commit is contained in:
Hajime Hoshi 2018-06-17 23:05:10 +09:00
parent 5680ce7f46
commit a3c754d2cc
3 changed files with 28 additions and 13 deletions

View File

@ -47,7 +47,18 @@ type GeoM interface {
Elements() (a, b, c, d, tx, ty float32) Elements() (a, b, c, d, tx, ty float32)
} }
func isPowerOf2(x int) bool {
return (x & (x - 1)) == 0
}
func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float32 { func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float32 {
if !isPowerOf2(width) {
panic("not reached")
}
if !isPowerOf2(height) {
panic("not reached")
}
if sx0 >= sx1 || sy0 >= sy1 { if sx0 >= sx1 || sy0 >= sy1 {
return nil return nil
} }
@ -55,18 +66,8 @@ func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float3
return nil return nil
} }
// it really feels like we should be able to cache this computation wf := float32(width)
// but it may not matter. hf := float32(height)
w := 1
h := 1
for w < width {
w *= 2
}
for h < height {
h *= 2
}
wf := float32(w)
hf := float32(h)
u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf u0, v0, u1, v1 := float32(sx0)/wf, float32(sy0)/hf, float32(sx1)/wf, float32(sy1)/hf
return quadVerticesImpl(float32(sx1-sx0), float32(sy1-sy0), u0, v0, u1, v1, geom) return quadVerticesImpl(float32(sx1-sx0), float32(sy1-sy0), u0, v0, u1, v1, geom)
} }

View File

@ -22,6 +22,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/affine" "github.com/hajimehoshi/ebiten/internal/affine"
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/graphicsutil" "github.com/hajimehoshi/ebiten/internal/graphicsutil"
"github.com/hajimehoshi/ebiten/internal/math"
"github.com/hajimehoshi/ebiten/internal/opengl" "github.com/hajimehoshi/ebiten/internal/opengl"
) )
@ -53,6 +54,9 @@ type Image struct {
// screen indicates whether the image is used as an actual screen. // screen indicates whether the image is used as an actual screen.
screen bool screen bool
w2 int
h2 int
} }
var dummyImage = newImageWithoutInit(16, 16, false) var dummyImage = newImageWithoutInit(16, 16, false)
@ -106,6 +110,16 @@ func (i *Image) Size() (int, int) {
return i.image.Size() return i.image.Size()
} }
// SizePowerOf2 returns the next power of 2 values for the size.
func (i *Image) SizePowerOf2() (int, int) {
if i.w2 == 0 || i.h2 == 0 {
w, h := i.image.Size()
i.w2 = math.NextPowerOf2Int(w)
i.h2 = math.NextPowerOf2Int(h)
}
return i.w2, i.h2
}
// makeStale makes the image stale. // makeStale makes the image stale.
func (i *Image) makeStale() { func (i *Image) makeStale() {
i.basePixels = nil i.basePixels = nil

View File

@ -164,7 +164,7 @@ func (i *Image) DrawImage(img *Image, sx0, sy0, sx1, sy1 int, geom graphicsutil.
} }
dx, dy, _, _ := img.region() dx, dy, _, _ := img.region()
w, h := img.backend.restorable.Size() w, h := img.backend.restorable.SizePowerOf2()
vs := graphicsutil.QuadVertices(w, h, sx0+dx, sy0+dy, sx1+dx, sy1+dy, geom) vs := graphicsutil.QuadVertices(w, h, sx0+dx, sy0+dy, sx1+dx, sy1+dy, geom)
i.backend.restorable.DrawImage(img.backend.restorable, vs, quadIndices, colorm, mode, filter) i.backend.restorable.DrawImage(img.backend.restorable, vs, quadIndices, colorm, mode, filter)
} }