From 15dcd5764d3d8bfcd51b739d388a1b65f38c834a Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 5 Apr 2018 02:35:30 +0900 Subject: [PATCH] shareable: Add shareable_test --- internal/shareable/shareable.go | 24 +++++++ internal/shareable/shareable_test.go | 99 ++++++++++++++++++++++++++++ 2 files changed, 123 insertions(+) create mode 100644 internal/shareable/shareable_test.go diff --git a/internal/shareable/shareable.go b/internal/shareable/shareable.go index 953e31ce8..ecfee20b1 100644 --- a/internal/shareable/shareable.go +++ b/internal/shareable/shareable.go @@ -87,6 +87,20 @@ type Image struct { node *packing.Node } +type rand struct { + x, y, z, w uint32 +} + +func (r *rand) next() uint32 { + // Xorshift: http://en.wikipedia.org/wiki/Xorshift + t := r.x ^ (r.x << 11) + r.x, r.y, r.z = r.y, r.z, r.w + r.w = (r.w ^ (r.w >> 19)) ^ (t ^ (t >> 8)) + return r.w +} + +var theRand = &rand{12345678, 4185243, 776511, 45411} + func (s *Image) ensureNotShared() { if s.node == nil { return @@ -94,6 +108,16 @@ func (s *Image) ensureNotShared() { x, y, w, h := s.region() newImg := restorable.NewImage(w, h, false) + + // Put a random color pixel on newImg to make tests reliable. + // + // Of course this function works without this ReplacePixels, + // but the tests might pass even if there is a bug in DrawImage + // because of GPU memory cache. + v := theRand.next() + r, g, b := uint8(v>>24), uint8(v>>16), uint8(v>>8) + newImg.ReplacePixels([]byte{r, g, b, 0xff}, 0, 0, 1, 1) + newImg.DrawImage(s.backend.restorable, x, y, x+w, y+h, nil, nil, opengl.CompositeModeCopy, graphics.FilterNearest) s.dispose() diff --git a/internal/shareable/shareable_test.go b/internal/shareable/shareable_test.go new file mode 100644 index 000000000..a69c85259 --- /dev/null +++ b/internal/shareable/shareable_test.go @@ -0,0 +1,99 @@ +// Copyright 2018 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package shareable_test + +import ( + "errors" + "image/color" + "os" + "testing" + + "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/shareable" +) + +func TestMain(m *testing.M) { + code := 0 + regularTermination := errors.New("regular termination") + f := func(screen *ebiten.Image) error { + code = m.Run() + return regularTermination + } + if err := ebiten.Run(f, 320, 240, 1, "Test"); err != nil && err != regularTermination { + panic(err) + } + os.Exit(code) +} + +func TestEnsureNotShared(t *testing.T) { + // Create img1 and img2 with this size so that the next images are allocated + // with non-upper-left location. + img1 := NewImage(2049, 100) + defer img1.Dispose() + + img2 := NewImage(100, 2049) + defer img2.Dispose() + + const size = 32 + + img3 := NewImage(size/2, size/2) + defer img3.Dispose() + + img4 := NewImage(size, size) + defer img4.Dispose() + + img3.ReplacePixels(make([]byte, (size/2)*(size/2)*4)) + + pix := make([]byte, size*size*4) + for j := 0; j < size; j++ { + for i := 0; i < size; i++ { + pix[4*(i+j*size)] = byte(i + j) + pix[4*(i+j*size)+1] = byte(i + j) + pix[4*(i+j*size)+2] = byte(i + j) + pix[4*(i+j*size)+3] = byte(i + j) + } + } + img4.ReplacePixels(pix) + + const ( + dx0 = size / 4 + dy0 = size / 4 + dx1 = size * 3 / 4 + dy1 = size * 3 / 4 + ) + // img4.ensureNotShared() should be called. + geom := (*affine.GeoM)(nil).Translate(size/4, size/4) + img4.DrawImage(img3, 0, 0, size/2, size/2, geom, nil, opengl.CompositeModeCopy, graphics.FilterNearest) + + for j := 0; j < size; j++ { + for i := 0; i < size; i++ { + got, err := img4.At(i, j) + if err != nil { + t.Fatal(err) + } + var want color.RGBA + if i < dx0 || dx1 <= i || j < dy0 || dy1 <= j { + c := byte(i + j) + want = color.RGBA{c, c, c, c} + } + if got != want { + t.Errorf("img4.At(%d, %d): got: %v, want: %v", i, j, got, want) + } + } + } +}