From a3c754d2cc3753f526bff9e50c9b65b5faba2f7f Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 17 Jun 2018 23:05:10 +0900 Subject: [PATCH] graphics: Restrict QuadVertices to allow only power of 2 sizes Now QuadVertices can skip calculating power of 2 values. --- internal/graphicsutil/vertices.go | 25 +++++++++++++------------ internal/restorable/image.go | 14 ++++++++++++++ internal/shareable/shareable.go | 2 +- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/internal/graphicsutil/vertices.go b/internal/graphicsutil/vertices.go index 7ade62b63..e17f9faad 100644 --- a/internal/graphicsutil/vertices.go +++ b/internal/graphicsutil/vertices.go @@ -47,7 +47,18 @@ type GeoM interface { 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 { + if !isPowerOf2(width) { + panic("not reached") + } + if !isPowerOf2(height) { + panic("not reached") + } + if sx0 >= sx1 || sy0 >= sy1 { return nil } @@ -55,18 +66,8 @@ func QuadVertices(width, height int, sx0, sy0, sx1, sy1 int, geom GeoM) []float3 return nil } - // it really feels like we should be able to cache this computation - // but it may not matter. - w := 1 - h := 1 - for w < width { - w *= 2 - } - for h < height { - h *= 2 - } - wf := float32(w) - hf := float32(h) + wf := float32(width) + hf := float32(height) 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) } diff --git a/internal/restorable/image.go b/internal/restorable/image.go index 7f045e7bb..f4944eae9 100644 --- a/internal/restorable/image.go +++ b/internal/restorable/image.go @@ -22,6 +22,7 @@ import ( "github.com/hajimehoshi/ebiten/internal/affine" "github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphicsutil" + "github.com/hajimehoshi/ebiten/internal/math" "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 bool + + w2 int + h2 int } var dummyImage = newImageWithoutInit(16, 16, false) @@ -106,6 +110,16 @@ func (i *Image) Size() (int, int) { 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. func (i *Image) makeStale() { i.basePixels = nil diff --git a/internal/shareable/shareable.go b/internal/shareable/shareable.go index dd7200c73..b35ac3d40 100644 --- a/internal/shareable/shareable.go +++ b/internal/shareable/shareable.go @@ -164,7 +164,7 @@ func (i *Image) DrawImage(img *Image, sx0, sy0, sx1, sy1 int, geom graphicsutil. } 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) i.backend.restorable.DrawImage(img.backend.restorable, vs, quadIndices, colorm, mode, filter) }