From 723d153800da2076eaa7c7baf308e6672aaa4cd5 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Mon, 11 Dec 2017 23:07:01 +0900 Subject: [PATCH] Reland(2): graphics: Appropriate rendering of edges on linear filter --- graphics.go | 15 ++-------- image.go | 7 +++-- image_test.go | 26 +++++++++++++++++ internal/graphics/command.go | 22 +++++++++----- internal/graphics/image.go | 4 +-- internal/graphics/program.go | 20 ++++++++++++- internal/graphics/shader.go | 47 ++++++++++++++++++++++++++---- internal/graphics/texture.go | 9 ++++++ internal/opengl/context.go | 2 -- internal/opengl/context_desktop.go | 32 ++++++++++---------- internal/opengl/context_js.go | 12 ++++---- internal/opengl/context_mobile.go | 30 ++++++++++--------- internal/opengl/types.go | 1 - internal/restorable/image.go | 6 ++-- internal/restorable/images_test.go | 33 +++++++++++---------- 15 files changed, 180 insertions(+), 86 deletions(-) diff --git a/graphics.go b/graphics.go index 1838f48c1..86a85c3b7 100644 --- a/graphics.go +++ b/graphics.go @@ -15,6 +15,7 @@ package ebiten import ( + "github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/opengl" ) @@ -23,22 +24,12 @@ type Filter int const ( // FilterNearest represents nearest (crisp-edged) filter - FilterNearest Filter = iota + FilterNearest Filter = Filter(graphics.FilterNearest) // FilterLinear represents linear filter - FilterLinear + FilterLinear Filter = Filter(graphics.FilterLinear) ) -func glFilter(filter Filter) opengl.Filter { - switch filter { - case FilterNearest: - return opengl.Nearest - case FilterLinear: - return opengl.Linear - } - panic("not reach") -} - // CompositeMode represents Porter-Duff composition mode. type CompositeMode int diff --git a/image.go b/image.go index 9dc24b817..abaa7c0f2 100644 --- a/image.go +++ b/image.go @@ -20,6 +20,7 @@ import ( "image/color" "runtime" + "github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/math" "github.com/hajimehoshi/ebiten/internal/opengl" "github.com/hajimehoshi/ebiten/internal/restorable" @@ -244,7 +245,7 @@ type DrawImageOptions struct { // Error returned by NewImage is always nil as of 1.5.0-alpha. func NewImage(width, height int, filter Filter) (*Image, error) { checkSize(width, height) - r := restorable.NewImage(width, height, glFilter(filter), false) + r := restorable.NewImage(width, height, graphics.Filter(filter), false) r.Fill(0, 0, 0, 0) i := &Image{r} runtime.SetFinalizer(i, (*Image).Dispose) @@ -268,7 +269,7 @@ func NewImage(width, height int, filter Filter) (*Image, error) { // Error returned by newVolatileImage is always nil as of 1.5.0-alpha. func newVolatileImage(width, height int, filter Filter) *Image { checkSize(width, height) - r := restorable.NewImage(width, height, glFilter(filter), true) + r := restorable.NewImage(width, height, graphics.Filter(filter), true) r.Fill(0, 0, 0, 0) i := &Image{r} runtime.SetFinalizer(i, (*Image).Dispose) @@ -283,7 +284,7 @@ func newVolatileImage(width, height int, filter Filter) *Image { func NewImageFromImage(source image.Image, filter Filter) (*Image, error) { size := source.Bounds().Size() checkSize(size.X, size.Y) - r := restorable.NewImageFromImage(source, glFilter(filter)) + r := restorable.NewImageFromImage(source, graphics.Filter(filter)) i := &Image{r} runtime.SetFinalizer(i, (*Image).Dispose) return i, nil diff --git a/image_test.go b/image_test.go index 0f57e0eea..9a0d317e5 100644 --- a/image_test.go +++ b/image_test.go @@ -25,6 +25,7 @@ import ( "testing" . "github.com/hajimehoshi/ebiten" + "github.com/hajimehoshi/ebiten/ebitenutil" emath "github.com/hajimehoshi/ebiten/internal/math" ) @@ -595,3 +596,28 @@ func BenchmarkDrawImage(b *testing.B) { img0.DrawImage(img1, op) } } + +func TestImageLinear(t *testing.T) { + src, _ := NewImage(32, 32, FilterLinear) + dst, _ := NewImage(64, 64, FilterNearest) + src.Fill(color.RGBA{0, 0xff, 0, 0xff}) + ebitenutil.DrawRect(src, 8, 8, 16, 16, color.RGBA{0xff, 0, 0, 0xff}) + + op := &DrawImageOptions{} + op.GeoM.Translate(8, 8) + op.GeoM.Scale(2, 2) + r := image.Rect(8, 8, 24, 24) + op.SourceRect = &r + dst.DrawImage(src, op) + + for j := 0; j < 64; j++ { + for i := 0; i < 64; i++ { + c := color.RGBAModel.Convert(dst.At(i, j)).(color.RGBA) + got := c.G + want := uint8(0) + if got != want { + t.Errorf("dst At(%d, %d).G: got %#v, want: %#v", i, j, got, want) + } + } + } +} diff --git a/internal/graphics/command.go b/internal/graphics/command.go index ac32df5c6..7ac6a74e5 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -242,12 +242,18 @@ func (c *drawImageCommand) Exec(indexOffsetInBytes int) error { if n == 0 { return nil } - _, h := c.dst.Size() - proj := f.projectionMatrix(h) - theOpenGLState.useProgram(proj, c.src.texture.native, c.color) + sw, sh := c.src.Size() + sw = emath.NextPowerOf2Int(sw) + sh = emath.NextPowerOf2Int(sh) + _, dh := c.dst.Size() + proj := f.projectionMatrix(dh) + theOpenGLState.useProgram(proj, c.src.texture.native, sw, sh, c.color, c.src.texture.filter) // TODO: We should call glBindBuffer here? // The buffer is already bound at begin() but it is counterintuitive. opengl.GetContext().DrawElements(opengl.Triangles, 6*n, indexOffsetInBytes) + + // This is necessary at least on MacBook Pro (a smilar problem at #419) + opengl.GetContext().Flush() return nil } @@ -338,7 +344,7 @@ func (c *disposeCommand) Exec(indexOffsetInBytes int) error { type newImageFromImageCommand struct { result *Image img *image.RGBA - filter opengl.Filter + filter Filter } // Exec executes the newImageFromImageCommand. @@ -354,12 +360,13 @@ func (c *newImageFromImageCommand) Exec(indexOffsetInBytes int) error { if c.img.Bounds() != image.Rect(0, 0, emath.NextPowerOf2Int(w), emath.NextPowerOf2Int(h)) { panic(fmt.Sprintf("graphics: invalid image bounds: %v", c.img.Bounds())) } - native, err := opengl.GetContext().NewTexture(w, h, c.img.Pix, c.filter) + native, err := opengl.GetContext().NewTexture(w, h, c.img.Pix) if err != nil { return err } c.result.texture = &texture{ native: native, + filter: c.filter, } return nil } @@ -369,7 +376,7 @@ type newImageCommand struct { result *Image width int height int - filter opengl.Filter + filter Filter } // Exec executes a newImageCommand. @@ -382,12 +389,13 @@ func (c *newImageCommand) Exec(indexOffsetInBytes int) error { if h < 1 { return errors.New("graphics: height must be equal or more than 1.") } - native, err := opengl.GetContext().NewTexture(w, h, nil, c.filter) + native, err := opengl.GetContext().NewTexture(w, h, nil) if err != nil { return err } c.result.texture = &texture{ native: native, + filter: c.filter, } return nil } diff --git a/internal/graphics/image.go b/internal/graphics/image.go index 430141499..e4d6c7968 100644 --- a/internal/graphics/image.go +++ b/internal/graphics/image.go @@ -33,7 +33,7 @@ type Image struct { // MaxImageSize is the maximum of width/height of an image. const MaxImageSize = defaultViewportSize -func NewImage(width, height int, filter opengl.Filter) *Image { +func NewImage(width, height int, filter Filter) *Image { i := &Image{ width: width, height: height, @@ -48,7 +48,7 @@ func NewImage(width, height int, filter opengl.Filter) *Image { return i } -func NewImageFromImage(img *image.RGBA, width, height int, filter opengl.Filter) *Image { +func NewImageFromImage(img *image.RGBA, width, height int, filter Filter) *Image { i := &Image{ width: width, height: height, diff --git a/internal/graphics/program.go b/internal/graphics/program.go index adf73c38b..c1657de3e 100644 --- a/internal/graphics/program.go +++ b/internal/graphics/program.go @@ -121,6 +121,9 @@ type openGLState struct { lastProjectionMatrix []float32 lastColorMatrix []float32 lastColorMatrixTranslation []float32 + lastFilterType Filter + lastSourceWidth int + lastSourceHeight int } var ( @@ -150,6 +153,9 @@ func (s *openGLState) reset() error { s.lastProjectionMatrix = nil s.lastColorMatrix = nil s.lastColorMatrixTranslation = nil + s.lastFilterType = FilterNone + s.lastSourceWidth = 0 + s.lastSourceHeight = 0 // When context lost happens, deleting programs or buffers is not necessary. // However, it is not assumed that reset is called only when context lost happens. @@ -214,7 +220,7 @@ func areSameFloat32Array(a, b []float32) bool { } // useProgram uses the program (programTexture). -func (s *openGLState) useProgram(proj []float32, texture opengl.Texture, colorM affine.ColorM) { +func (s *openGLState) useProgram(proj []float32, texture opengl.Texture, sourceWidth, sourceHeight int, colorM affine.ColorM, filter Filter) { c := opengl.GetContext() program := s.programTexture @@ -273,6 +279,18 @@ func (s *openGLState) useProgram(proj []float32, texture opengl.Texture, colorM copy(s.lastColorMatrixTranslation, colorMatrixTranslation) } + if s.lastFilterType != filter { + c.UniformInt(program, "filter_type", int(filter)) + s.lastFilterType = filter + } + + if s.lastSourceWidth != sourceWidth || s.lastSourceHeight != sourceHeight { + c.UniformFloats(program, "source_size", + []float32{float32(sourceWidth), float32(sourceHeight)}) + s.lastSourceWidth = sourceWidth + s.lastSourceHeight = sourceHeight + } + // We don't have to call gl.ActiveTexture here: GL_TEXTURE0 is the default active texture // See also: https://www.opengl.org/sdk/docs/man2/xhtml/glActiveTexture.xml c.BindTexture(texture) diff --git a/internal/graphics/shader.go b/internal/graphics/shader.go index 962befda9..01ac96192 100644 --- a/internal/graphics/shader.go +++ b/internal/graphics/shader.go @@ -63,17 +63,54 @@ precision mediump float; uniform sampler2D texture; uniform mat4 color_matrix; uniform vec4 color_matrix_translation; +uniform int filter_type; +uniform vec2 source_size; + varying vec2 varying_tex_coord; varying vec2 varying_tex_coord_min; varying vec2 varying_tex_coord_max; +vec2 roundTexel(vec2 p) { + vec2 factor = 1.0 / (source_size * 256.0); + if (factor.x > 0.0) { + p.x -= mod(p.x + factor.x * 0.5, factor.x) - factor.x * 0.5; + } + if (factor.y > 0.0) { + p.y -= mod(p.y + factor.y * 0.5, factor.y) - factor.y * 0.5; + } + return p; +} + +vec4 getColorAt(vec2 pos) { + if (pos.x < varying_tex_coord_min.x || + pos.y < varying_tex_coord_min.y || + varying_tex_coord_max.x <= pos.x || + varying_tex_coord_max.y <= pos.y) { + return vec4(0, 0, 0, 0); + } + return texture2D(texture, pos); +} + void main(void) { vec4 color = vec4(0, 0, 0, 0); - if (varying_tex_coord_min.x <= varying_tex_coord.x && - varying_tex_coord_min.y <= varying_tex_coord.y && - varying_tex_coord.x < varying_tex_coord_max.x && - varying_tex_coord.y < varying_tex_coord_max.y) { - color = texture2D(texture, varying_tex_coord); + + vec2 pos = roundTexel(varying_tex_coord); + if (filter_type == 1) { + // Nearest neighbor + color = getColorAt(pos); + } else if (filter_type == 2) { + // Bi-linear + vec2 texel_size = 1.0 / source_size; + pos -= texel_size * 0.5; + vec4 c0 = getColorAt(pos); + vec4 c1 = getColorAt(pos + vec2(texel_size.x, 0)); + vec4 c2 = getColorAt(pos + vec2(0, texel_size.y)); + vec4 c3 = getColorAt(pos + texel_size); + float rateX = fract(pos.x * source_size.x); + float rateY = fract(pos.y * source_size.y); + color = mix(mix(c0, c1, rateX), mix(c2, c3, rateX), rateY); + } else { + color = vec4(1, 0, 0, 1); } // Un-premultiply alpha diff --git a/internal/graphics/texture.go b/internal/graphics/texture.go index 7fa53e5c1..b52146f32 100644 --- a/internal/graphics/texture.go +++ b/internal/graphics/texture.go @@ -18,7 +18,16 @@ import ( "github.com/hajimehoshi/ebiten/internal/opengl" ) +type Filter int + +const ( + FilterNone Filter = iota + FilterNearest + FilterLinear +) + // texture represents OpenGL's texture. type texture struct { native opengl.Texture + filter Filter } diff --git a/internal/opengl/context.go b/internal/opengl/context.go index 1117db7a3..37d7cd406 100644 --- a/internal/opengl/context.go +++ b/internal/opengl/context.go @@ -38,8 +38,6 @@ func adjustForClearColor(x float32) float32 { } var ( - Nearest Filter - Linear Filter VertexShader ShaderType FragmentShader ShaderType ArrayBuffer BufferType diff --git a/internal/opengl/context_desktop.go b/internal/opengl/context_desktop.go index 87c6c7b23..6ef8c17b3 100644 --- a/internal/opengl/context_desktop.go +++ b/internal/opengl/context_desktop.go @@ -26,11 +26,13 @@ import ( "github.com/go-gl/gl/v2.1/gl" ) -type Texture uint32 -type Framebuffer uint32 -type Shader uint32 -type Program uint32 -type Buffer uint32 +type ( + Texture uint32 + Framebuffer uint32 + Shader uint32 + Program uint32 + Buffer uint32 +) func (t Texture) equals(other Texture) bool { return t == other @@ -40,8 +42,10 @@ func (f Framebuffer) equals(other Framebuffer) bool { return f == other } -type uniformLocation int32 -type attribLocation int32 +type ( + uniformLocation int32 + attribLocation int32 +) type programID uint32 @@ -55,8 +59,6 @@ func (p Program) id() programID { } func init() { - Nearest = gl.NEAREST - Linear = gl.LINEAR VertexShader = gl.VERTEX_SHADER FragmentShader = gl.FRAGMENT_SHADER ArrayBuffer = gl.ARRAY_BUFFER @@ -137,7 +139,7 @@ func (c *Context) BlendFunc(mode CompositeMode) { }) } -func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { +func (c *Context) NewTexture(width, height int, pixels []uint8) (Texture, error) { var texture Texture if err := c.runOnContextThread(func() error { var t uint32 @@ -154,10 +156,8 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) ( } c.BindTexture(texture) _ = c.runOnContextThread(func() error { - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int32(filter)) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int32(filter)) - //gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP) - //gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) var p interface{} if pixels != nil { @@ -408,12 +408,14 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) { _ = c.runOnContextThread(func() error { l := int32(c.locationCache.GetUniformLocation(c, p, location)) switch len(v) { + case 2: + gl.Uniform2fv(l, 1, (*float32)(gl.Ptr(v))) case 4: gl.Uniform4fv(l, 1, (*float32)(gl.Ptr(v))) case 16: gl.UniformMatrix4fv(l, 1, false, (*float32)(gl.Ptr(v))) default: - panic("not reach") + panic("not reached") } return nil }) diff --git a/internal/opengl/context_js.go b/internal/opengl/context_js.go index 0e393e255..dc42d3778 100644 --- a/internal/opengl/context_js.go +++ b/internal/opengl/context_js.go @@ -77,8 +77,6 @@ func (p Program) id() programID { func init() { // Accessing the prototype is rquired on Safari. c := js.Global.Get("WebGLRenderingContext").Get("prototype") - Nearest = Filter(c.Get("NEAREST").Int()) - Linear = Filter(c.Get("LINEAR").Int()) VertexShader = ShaderType(c.Get("VERTEX_SHADER").Int()) FragmentShader = ShaderType(c.Get("FRAGMENT_SHADER").Int()) ArrayBuffer = BufferType(c.Get("ARRAY_BUFFER").Int()) @@ -159,7 +157,7 @@ func (c *Context) BlendFunc(mode CompositeMode) { gl.BlendFunc(int(s), int(d)) } -func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { +func (c *Context) NewTexture(width, height int, pixels []uint8) (Texture, error) { gl := c.gl t := gl.CreateTexture() if t == nil { @@ -168,8 +166,8 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) ( gl.PixelStorei(gl.UNPACK_ALIGNMENT, 4) c.BindTexture(Texture{t}) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, int(filter)) - gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, int(filter)) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) + gl.TexParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) // TODO: Can we use glTexSubImage2D with linear filtering? @@ -348,12 +346,14 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) { gl := c.gl l := c.locationCache.GetUniformLocation(c, p, location) switch len(v) { + case 2: + gl.Call("uniform2fv", l.Object, v) case 4: gl.Call("uniform4fv", l.Object, v) case 16: gl.UniformMatrix4fv(l.Object, false, v) default: - panic("not reach") + panic("not reached") } } diff --git a/internal/opengl/context_mobile.go b/internal/opengl/context_mobile.go index 10d31a4c0..9cfde1d5d 100644 --- a/internal/opengl/context_mobile.go +++ b/internal/opengl/context_mobile.go @@ -25,11 +25,13 @@ import ( mgl "golang.org/x/mobile/gl" ) -type Texture mgl.Texture -type Framebuffer mgl.Framebuffer -type Shader mgl.Shader -type Program mgl.Program -type Buffer mgl.Buffer +type ( + Texture mgl.Texture + Framebuffer mgl.Framebuffer + Shader mgl.Shader + Program mgl.Program + Buffer mgl.Buffer +) func (t Texture) equals(other Texture) bool { return t == other @@ -39,8 +41,10 @@ func (f Framebuffer) equals(other Framebuffer) bool { return f == other } -type uniformLocation mgl.Uniform -type attribLocation mgl.Attrib +type ( + uniformLocation mgl.Uniform + attribLocation mgl.Attrib +) type programID uint32 @@ -54,8 +58,6 @@ func (p Program) id() programID { } func init() { - Nearest = mgl.NEAREST - Linear = mgl.LINEAR VertexShader = mgl.VERTEX_SHADER FragmentShader = mgl.FRAGMENT_SHADER ArrayBuffer = mgl.ARRAY_BUFFER @@ -127,7 +129,7 @@ func (c *Context) BlendFunc(mode CompositeMode) { gl.BlendFunc(mgl.Enum(s), mgl.Enum(d)) } -func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) (Texture, error) { +func (c *Context) NewTexture(width, height int, pixels []uint8) (Texture, error) { gl := c.gl t := gl.CreateTexture() if t.Value <= 0 { @@ -136,8 +138,8 @@ func (c *Context) NewTexture(width, height int, pixels []uint8, filter Filter) ( gl.PixelStorei(mgl.UNPACK_ALIGNMENT, 4) c.BindTexture(Texture(t)) - gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MAG_FILTER, int(filter)) - gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MIN_FILTER, int(filter)) + gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MAG_FILTER, mgl.NEAREST) + gl.TexParameteri(mgl.TEXTURE_2D, mgl.TEXTURE_MIN_FILTER, mgl.NEAREST) var p []uint8 if pixels != nil { @@ -317,12 +319,14 @@ func (c *Context) UniformFloats(p Program, location string, v []float32) { gl := c.gl l := mgl.Uniform(c.locationCache.GetUniformLocation(c, p, location)) switch len(v) { + case 2: + gl.Uniform2fv(l, v) case 4: gl.Uniform4fv(l, v) case 16: gl.UniformMatrix4fv(l, v) default: - panic("not reach") + panic("not reached") } } diff --git a/internal/opengl/types.go b/internal/opengl/types.go index 81be11d9f..a1272d00b 100644 --- a/internal/opengl/types.go +++ b/internal/opengl/types.go @@ -15,7 +15,6 @@ package opengl type ( - Filter int ShaderType int BufferType int BufferUsage int diff --git a/internal/restorable/image.go b/internal/restorable/image.go index bc7466eae..9cf50e198 100644 --- a/internal/restorable/image.go +++ b/internal/restorable/image.go @@ -60,7 +60,7 @@ func (d *drawImageHistoryItem) canMerge(image *Image, colorm *affine.ColorM, mod // Image represents an image that can be restored when GL context is lost. type Image struct { image *graphics.Image - filter opengl.Filter + filter graphics.Filter // baseImage and baseColor are exclusive. basePixels []uint8 @@ -84,7 +84,7 @@ type Image struct { } // NewImage creates an empty image with the given size and filter. -func NewImage(width, height int, filter opengl.Filter, volatile bool) *Image { +func NewImage(width, height int, filter graphics.Filter, volatile bool) *Image { i := &Image{ image: graphics.NewImage(width, height, filter), filter: filter, @@ -96,7 +96,7 @@ func NewImage(width, height int, filter opengl.Filter, volatile bool) *Image { } // NewImageFromImage creates an image with source image. -func NewImageFromImage(source image.Image, filter opengl.Filter) *Image { +func NewImageFromImage(source image.Image, filter graphics.Filter) *Image { size := source.Bounds().Size() width, height := size.X, size.Y rgbaImg := CopyImage(source) diff --git a/internal/restorable/images_test.go b/internal/restorable/images_test.go index 5bfee4510..aa0b63d90 100644 --- a/internal/restorable/images_test.go +++ b/internal/restorable/images_test.go @@ -23,6 +23,7 @@ import ( "github.com/hajimehoshi/ebiten" "github.com/hajimehoshi/ebiten/internal/affine" + "github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/opengl" . "github.com/hajimehoshi/ebiten/internal/restorable" ) @@ -47,7 +48,7 @@ func uint8SliceToColor(b []uint8, index int) color.RGBA { } func TestRestore(t *testing.T) { - img0 := NewImage(1, 1, opengl.Nearest, false) + img0 := NewImage(1, 1, graphics.FilterNearest, false) // Clear images explicitly. // In this 'restorable' layer, reused texture might not be cleared. img0.Fill(0, 0, 0, 0) @@ -89,7 +90,7 @@ func TestRestoreChain(t *testing.T) { const num = 10 imgs := []*Image{} for i := 0; i < num; i++ { - img := NewImage(1, 1, opengl.Nearest, false) + img := NewImage(1, 1, graphics.FilterNearest, false) img.Fill(0, 0, 0, 0) imgs = append(imgs, img) } @@ -119,13 +120,13 @@ func TestRestoreChain(t *testing.T) { } func TestRestoreOverrideSource(t *testing.T) { - img0 := NewImage(1, 1, opengl.Nearest, false) + img0 := NewImage(1, 1, graphics.FilterNearest, false) img0.Fill(0, 0, 0, 0) - img1 := NewImage(1, 1, opengl.Nearest, false) + img1 := NewImage(1, 1, graphics.FilterNearest, false) img1.Fill(0, 0, 0, 0) - img2 := NewImage(1, 1, opengl.Nearest, false) + img2 := NewImage(1, 1, graphics.FilterNearest, false) img2.Fill(0, 0, 0, 0) - img3 := NewImage(1, 1, opengl.Nearest, false) + img3 := NewImage(1, 1, graphics.FilterNearest, false) img3.Fill(0, 0, 0, 0) defer func() { img3.Dispose() @@ -194,18 +195,18 @@ func TestRestoreComplexGraph(t *testing.T) { base.Pix[1] = 0xff base.Pix[2] = 0xff base.Pix[3] = 0xff - img0 := NewImageFromImage(base, opengl.Nearest) - img1 := NewImageFromImage(base, opengl.Nearest) - img2 := NewImageFromImage(base, opengl.Nearest) - img3 := NewImage(4, 1, opengl.Nearest, false) + img0 := NewImageFromImage(base, graphics.FilterNearest) + img1 := NewImageFromImage(base, graphics.FilterNearest) + img2 := NewImageFromImage(base, graphics.FilterNearest) + img3 := NewImage(4, 1, graphics.FilterNearest, false) img3.Fill(0, 0, 0, 0) - img4 := NewImage(4, 1, opengl.Nearest, false) + img4 := NewImage(4, 1, graphics.FilterNearest, false) img4.Fill(0, 0, 0, 0) - img5 := NewImage(4, 1, opengl.Nearest, false) + img5 := NewImage(4, 1, graphics.FilterNearest, false) img5.Fill(0, 0, 0, 0) - img6 := NewImage(4, 1, opengl.Nearest, false) + img6 := NewImage(4, 1, graphics.FilterNearest, false) img6.Fill(0, 0, 0, 0) - img7 := NewImage(4, 1, opengl.Nearest, false) + img7 := NewImage(4, 1, graphics.FilterNearest, false) img7.Fill(0, 0, 0, 0) defer func() { img7.Dispose() @@ -298,8 +299,8 @@ func TestRestoreRecursive(t *testing.T) { base.Pix[1] = 0xff base.Pix[2] = 0xff base.Pix[3] = 0xff - img0 := NewImageFromImage(base, opengl.Nearest) - img1 := NewImage(4, 1, opengl.Nearest, false) + img0 := NewImageFromImage(base, graphics.FilterNearest) + img1 := NewImage(4, 1, graphics.FilterNearest, false) img1.Fill(0, 0, 0, 0) defer func() { img1.Dispose()