all: refactoring: use image.Rectangle

This commit is contained in:
Hajime Hoshi 2023-04-28 00:55:10 +09:00
parent cdcffd7d4f
commit d2c991b774
8 changed files with 88 additions and 84 deletions

View File

@ -94,7 +94,7 @@ func (i *Image) Fill(clr color.Color) {
caf = float32(ca) / 0xffff
b := i.Bounds()
x, y := i.adjustPosition(b.Min.X, b.Min.Y)
i.image.Fill(crf, cgf, cbf, caf, x, y, b.Dx(), b.Dy())
i.image.Fill(crf, cgf, cbf, caf, image.Rect(x, y, x+b.Dx(), y+b.Dy()))
}
func canSkipMipmap(geom GeoM, filter builtinshader.Filter) bool {
@ -881,7 +881,7 @@ func (i *Image) ReadPixels(pixels []byte) {
}
x, y := i.adjustPosition(b.Min.X, b.Min.Y)
i.image.ReadPixels(pixels, x, y, b.Dx(), b.Dy())
i.image.ReadPixels(pixels, image.Rect(x, y, x+b.Dx(), y+b.Dy()))
}
// At returns the color of the image at (x, y).
@ -927,7 +927,7 @@ func (i *Image) at(x, y int) (r, g, b, a byte) {
x, y = i.adjustPosition(x, y)
var pix [4]byte
i.image.ReadPixels(pix[:], x, y, 1, 1)
i.image.ReadPixels(pix[:], image.Rect(x, y, x+1, y+1))
return pix[0], pix[1], pix[2], pix[3]
}
@ -950,7 +950,7 @@ func (i *Image) Set(x, y int, clr color.Color) {
dx, dy := i.adjustPosition(x, y)
cr, cg, cb, ca := clr.RGBA()
i.image.WritePixels([]byte{byte(cr / 0x101), byte(cg / 0x101), byte(cb / 0x101), byte(ca / 0x101)}, dx, dy, 1, 1)
i.image.WritePixels([]byte{byte(cr / 0x101), byte(cg / 0x101), byte(cb / 0x101), byte(ca / 0x101)}, image.Rect(dx, dy, dx+1, dy+1))
}
// Dispose disposes the image data.
@ -997,7 +997,7 @@ func (i *Image) WritePixels(pixels []byte) {
// Do not need to copy pixels here.
// * In internal/mipmap, pixels are copied when necessary.
// * In internal/atlas, pixels are copied to make its paddings.
i.image.WritePixels(pixels, x, y, r.Dx(), r.Dy())
i.image.WritePixels(pixels, image.Rect(x, y, x+r.Dx(), y+r.Dy()))
}
// ReplacePixels replaces the pixels of the image.

View File

@ -515,10 +515,10 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
}
// WritePixels replaces the pixels on the image.
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
backendsM.Lock()
defer backendsM.Unlock()
i.writePixels(pix, image.Rect(x, y, x+width, y+height))
i.writePixels(pix, region)
}
func (i *Image) writePixels(pix []byte, region image.Rectangle) {
@ -585,7 +585,7 @@ func (i *Image) writePixels(pix []byte, region image.Rectangle) {
i.backend.restorable.WritePixels(pixb, r)
}
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error {
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error {
backendsM.Lock()
defer backendsM.Unlock()
@ -601,9 +601,7 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte
}
r := i.regionWithPadding()
x += r.Min.X
y += r.Min.Y
return i.backend.restorable.ReadPixels(graphicsDriver, pixels, image.Rect(x, y, x+width, y+height))
return i.backend.restorable.ReadPixels(graphicsDriver, pixels, region.Add(r.Min))
}
// MarkDisposed marks the image as disposed. The actual operation is deferred.

View File

@ -15,6 +15,7 @@
package atlas_test
import (
"image"
"image/color"
"runtime"
"testing"
@ -63,17 +64,17 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) {
img1 := atlas.NewImage(bigSize, 100, atlas.ImageTypeRegular)
defer img1.MarkDisposed()
// Ensure img1's region is allocated.
img1.WritePixels(make([]byte, 4*bigSize*100), 0, 0, bigSize, 100)
img1.WritePixels(make([]byte, 4*bigSize*100), image.Rect(0, 0, bigSize, 100))
img2 := atlas.NewImage(100, bigSize, atlas.ImageTypeRegular)
defer img2.MarkDisposed()
img2.WritePixels(make([]byte, 4*100*bigSize), 0, 0, 100, bigSize)
img2.WritePixels(make([]byte, 4*100*bigSize), image.Rect(0, 0, 100, bigSize))
const size = 32
img3 := atlas.NewImage(size/2, size/2, atlas.ImageTypeRegular)
defer img3.MarkDisposed()
img3.WritePixels(make([]byte, (size/2)*(size/2)*4), 0, 0, size/2, size/2)
img3.WritePixels(make([]byte, (size/2)*(size/2)*4), image.Rect(0, 0, size/2, size/2))
img4 := atlas.NewImage(size, size, atlas.ImageTypeRegular)
defer img4.MarkDisposed()
@ -90,7 +91,7 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) {
pix[4*(i+j*size)+3] = byte(i + j)
}
}
img4.WritePixels(pix, 0, 0, size, size)
img4.WritePixels(pix, image.Rect(0, 0, size, size))
const (
dx0 = size / 4
@ -126,7 +127,7 @@ func TestEnsureIsolatedFromSourceBackend(t *testing.T) {
}
pix = make([]byte, 4*size*size)
if err := img4.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil {
if err := img4.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil {
t.Fatal(err)
}
for j := 0; j < size; j++ {
@ -158,11 +159,11 @@ func TestReputOnSourceBackend(t *testing.T) {
img0 := atlas.NewImage(size, size, atlas.ImageTypeRegular)
defer img0.MarkDisposed()
img0.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
img0.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size))
img1 := atlas.NewImage(size, size, atlas.ImageTypeRegular)
defer img1.MarkDisposed()
img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
img1.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size))
if got, want := img1.IsOnSourceBackendForTesting(), true; got != want {
t.Errorf("got: %v, want: %v", got, want)
}
@ -178,12 +179,12 @@ func TestReputOnSourceBackend(t *testing.T) {
pix[4*(i+j*size)+3] = byte(i + j)
}
}
img2.WritePixels(pix, 0, 0, size, size)
img2.WritePixels(pix, image.Rect(0, 0, size, size))
// Create a volatile image. This should always be on a non-source backend.
img3 := atlas.NewImage(size, size, atlas.ImageTypeVolatile)
defer img3.MarkDisposed()
img3.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
img3.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size))
if got, want := img3.IsOnSourceBackendForTesting(), false; got != want {
t.Errorf("got: %v, want: %v", got, want)
}
@ -232,7 +233,7 @@ func TestReputOnSourceBackend(t *testing.T) {
}
pix = make([]byte, 4*size*size)
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil {
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil {
t.Fatal(err)
}
for j := 0; j < size; j++ {
@ -256,7 +257,7 @@ func TestReputOnSourceBackend(t *testing.T) {
}
pix = make([]byte, 4*size*size)
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil {
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil {
t.Fatal(err)
}
for j := 0; j < size; j++ {
@ -288,7 +289,7 @@ func TestReputOnSourceBackend(t *testing.T) {
if err := atlas.PutImagesOnSourceBackendForTesting(ui.GraphicsDriverForTesting()); err != nil {
t.Fatal(err)
}
img1.WritePixels(make([]byte, 4*size*size), 0, 0, size, size)
img1.WritePixels(make([]byte, 4*size*size), image.Rect(0, 0, size, size))
vs := quadVertices(size, size, 0, 0, 1)
img0.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{img1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
if got, want := img1.IsOnSourceBackendForTesting(), false; got != want {
@ -333,7 +334,7 @@ func TestExtend(t *testing.T) {
p0[4*i+2] = byte(i)
p0[4*i+3] = byte(i)
}
img0.WritePixels(p0, 0, 0, w0, h0)
img0.WritePixels(p0, image.Rect(0, 0, w0, h0))
const w1, h1 = minSourceImageSizeForTesting + 1, 100
img1 := atlas.NewImage(w1, h1, atlas.ImageTypeRegular)
@ -347,10 +348,10 @@ func TestExtend(t *testing.T) {
p1[4*i+3] = byte(i)
}
// Ensure to allocate
img1.WritePixels(p1, 0, 0, w1, h1)
img1.WritePixels(p1, image.Rect(0, 0, w1, h1))
pix0 := make([]byte, 4*w0*h0)
if err := img0.ReadPixels(ui.GraphicsDriverForTesting(), pix0, 0, 0, w0, h0); err != nil {
if err := img0.ReadPixels(ui.GraphicsDriverForTesting(), pix0, image.Rect(0, 0, w0, h0)); err != nil {
t.Fatal(err)
}
for j := 0; j < h0; j++ {
@ -369,7 +370,7 @@ func TestExtend(t *testing.T) {
}
pix1 := make([]byte, 4*w1*h1)
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix1, 0, 0, w1, h1); err != nil {
if err := img1.ReadPixels(ui.GraphicsDriverForTesting(), pix1, image.Rect(0, 0, w1, h1)); err != nil {
t.Fatal(err)
}
for j := 0; j < h1; j++ {
@ -402,7 +403,7 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) {
pix[4*i+2] = byte(i)
pix[4*i+3] = byte(i)
}
src.WritePixels(pix, 0, 0, w, h)
src.WritePixels(pix, image.Rect(0, 0, w, h))
vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices()
@ -413,10 +414,10 @@ func TestWritePixelsAfterDrawTriangles(t *testing.T) {
Height: h,
}
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
dst.WritePixels(pix, 0, 0, w, h)
dst.WritePixels(pix, image.Rect(0, 0, w, h))
pix = make([]byte, 4*w*h)
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil {
t.Fatal(err)
}
for j := 0; j < h; j++ {
@ -450,7 +451,7 @@ func TestSmallImages(t *testing.T) {
pix[4*i+2] = 0xff
pix[4*i+3] = 0xff
}
src.WritePixels(pix, 0, 0, w, h)
src.WritePixels(pix, image.Rect(0, 0, w, h))
vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices()
@ -463,7 +464,7 @@ func TestSmallImages(t *testing.T) {
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
pix = make([]byte, 4*w*h)
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil {
t.Fatal(err)
}
for j := 0; j < h; j++ {
@ -497,7 +498,7 @@ func TestLongImages(t *testing.T) {
pix[4*i+2] = 0xff
pix[4*i+3] = 0xff
}
src.WritePixels(pix, 0, 0, w, h)
src.WritePixels(pix, image.Rect(0, 0, w, h))
const scale = 120
vs := quadVertices(w, h, 0, 0, scale)
@ -511,7 +512,7 @@ func TestLongImages(t *testing.T) {
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src}, vs, is, graphicsdriver.BlendSourceOver, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
pix = make([]byte, 4*dstW*dstH)
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, dstW, dstH); err != nil {
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, dstW, dstH)); err != nil {
t.Fatal(err)
}
for j := 0; j < h; j++ {
@ -547,12 +548,12 @@ func TestExtendWithBigImage(t *testing.T) {
img0 := atlas.NewImage(1, 1, atlas.ImageTypeRegular)
defer img0.MarkDisposed()
img0.WritePixels(make([]byte, 4*1*1), 0, 0, 1, 1)
img0.WritePixels(make([]byte, 4*1*1), image.Rect(0, 0, 1, 1))
img1 := atlas.NewImage(minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1, atlas.ImageTypeRegular)
defer img1.MarkDisposed()
img1.WritePixels(make([]byte, 4*(minSourceImageSizeForTesting+1)*(minSourceImageSizeForTesting+1)), 0, 0, minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1)
img1.WritePixels(make([]byte, 4*(minSourceImageSizeForTesting+1)*(minSourceImageSizeForTesting+1)), image.Rect(0, 0, minSourceImageSizeForTesting+1, minSourceImageSizeForTesting+1))
}
// Issue #1217
@ -565,7 +566,7 @@ func TestMaxImageSize(t *testing.T) {
s := maxImageSizeForTesting - 2*paddingSize
img1 := atlas.NewImage(s, s, atlas.ImageTypeRegular)
defer img1.MarkDisposed()
img1.WritePixels(make([]byte, 4*s*s), 0, 0, s, s)
img1.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s))
}
// Issue #1217 (disabled)
@ -578,7 +579,7 @@ func Disable_TestMinImageSize(t *testing.T) {
s := minSourceImageSizeForTesting
img := atlas.NewImage(s, s, atlas.ImageTypeRegular)
defer img.MarkDisposed()
img.WritePixels(make([]byte, 4*s*s), 0, 0, s, s)
img.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s))
}
func TestMaxImageSizeJust(t *testing.T) {
@ -587,7 +588,7 @@ func TestMaxImageSizeJust(t *testing.T) {
// TODO: Should we allow such this size for ImageTypeRegular?
img := atlas.NewImage(s, s, atlas.ImageTypeUnmanaged)
defer img.MarkDisposed()
img.WritePixels(make([]byte, 4*s*s), 0, 0, s, s)
img.WritePixels(make([]byte, 4*s*s), image.Rect(0, 0, s, s))
}
func TestMaxImageSizeExceeded(t *testing.T) {
@ -602,7 +603,7 @@ func TestMaxImageSizeExceeded(t *testing.T) {
}
}()
img.WritePixels(make([]byte, 4*(s+1)*s), 0, 0, s+1, s)
img.WritePixels(make([]byte, 4*(s+1)*s), image.Rect(0, 0, s+1, s))
}
// Issue #1421
@ -726,7 +727,7 @@ func TestImageWritePixelsModify(t *testing.T) {
pix[4*(i+j*size)+3] = byte(i + j)
}
}
img.WritePixels(pix, 0, 0, size, size)
img.WritePixels(pix, image.Rect(0, 0, size, size))
// Modify pix after WritePixels.
for j := 0; j < size; j++ {
@ -740,7 +741,7 @@ func TestImageWritePixelsModify(t *testing.T) {
// Check the pixels are the original ones.
pix = make([]byte, 4*size*size)
if err := img.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, size, size); err != nil {
if err := img.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, size, size)); err != nil {
t.Fatal(err)
}
for j := 0; j < size; j++ {

View File

@ -15,6 +15,7 @@
package atlas_test
import (
"image"
"image/color"
"testing"
@ -48,7 +49,7 @@ func TestShaderFillTwice(t *testing.T) {
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, s1, nil, false)
pix := make([]byte, 4*w*h)
if err := dst.ReadPixels(g, pix, 0, 0, w, h); err != nil {
if err := dst.ReadPixels(g, pix, image.Rect(0, 0, w, h)); err != nil {
t.Error(err)
}
if got, want := (color.RGBA{R: pix[0], G: pix[1], B: pix[2], A: pix[3]}), (color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xff}); got != want {
@ -61,9 +62,9 @@ func TestImageDrawTwice(t *testing.T) {
dst := atlas.NewImage(w, h, atlas.ImageTypeRegular)
src0 := atlas.NewImage(w, h, atlas.ImageTypeRegular)
src0.WritePixels([]byte{0xff, 0xff, 0xff, 0xff}, 0, 0, w, h)
src0.WritePixels([]byte{0xff, 0xff, 0xff, 0xff}, image.Rect(0, 0, w, h))
src1 := atlas.NewImage(w, h, atlas.ImageTypeRegular)
src1.WritePixels([]byte{0x80, 0x80, 0x80, 0xff}, 0, 0, w, h)
src1.WritePixels([]byte{0x80, 0x80, 0x80, 0xff}, image.Rect(0, 0, w, h))
vs := quadVertices(w, h, 0, 0, 1)
is := graphics.QuadIndices()
@ -80,7 +81,7 @@ func TestImageDrawTwice(t *testing.T) {
dst.DrawTriangles([graphics.ShaderImageCount]*atlas.Image{src1}, vs, is, graphicsdriver.BlendCopy, dr, graphicsdriver.Region{}, [graphics.ShaderImageCount - 1][2]float32{}, atlas.NearestFilterShader, nil, false)
pix := make([]byte, 4*w*h)
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, 0, 0, w, h); err != nil {
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), pix, image.Rect(0, 0, w, h)); err != nil {
t.Error(err)
}
if got, want := (color.RGBA{R: pix[0], G: pix[1], B: pix[2], A: pix[3]}), (color.RGBA{R: 0x80, G: 0x80, B: 0x80, A: 0xff}); got != want {

View File

@ -16,6 +16,7 @@ package buffered
import (
"fmt"
"image"
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
@ -89,12 +90,12 @@ func (i *Image) markDisposedImpl() {
i.img.MarkDisposed()
}
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error {
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error {
checkDelayedCommandsFlushed("ReadPixels")
// If restorable.AlwaysReadPixelsFromGPU() returns false, the pixel data is cached in the restorable package.
if !restorable.AlwaysReadPixelsFromGPU() {
if err := i.img.ReadPixels(graphicsDriver, pixels, x, y, width, height); err != nil {
if err := i.img.ReadPixels(graphicsDriver, pixels, region); err != nil {
return err
}
return nil
@ -102,16 +103,16 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte
if i.pixels == nil {
pix := make([]byte, 4*i.width*i.height)
if err := i.img.ReadPixels(graphicsDriver, pix, 0, 0, i.width, i.height); err != nil {
if err := i.img.ReadPixels(graphicsDriver, pix, image.Rect(0, 0, i.width, i.height)); err != nil {
return err
}
i.pixels = pix
}
lineWidth := 4 * width
for j := 0; j < height; j++ {
dstX := 4 * j * width
srcX := 4 * ((y+j)*i.width + x)
lineWidth := 4 * region.Dx()
for j := 0; j < region.Dy(); j++ {
dstX := 4 * j * region.Dx()
srcX := 4 * ((region.Min.Y+j)*i.width + region.Min.X)
copy(pixels[dstX:dstX+lineWidth], i.pixels[srcX:srcX+lineWidth])
}
return nil
@ -123,8 +124,8 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name stri
}
// WritePixels replaces the pixels at the specified region.
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
if l := 4 * width * height; len(pix) != l {
func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
if l := 4 * region.Dx() * region.Dy(); len(pix) != l {
panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l))
}
@ -132,17 +133,17 @@ func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
copied := make([]byte, len(pix))
copy(copied, pix)
if tryAddDelayedCommand(func() {
i.writePixelsImpl(copied, x, y, width, height)
i.writePixelsImpl(copied, region)
}) {
return
}
}
i.writePixelsImpl(pix, x, y, width, height)
i.writePixelsImpl(pix, region)
}
func (i *Image) writePixelsImpl(pix []byte, x, y, width, height int) {
func (i *Image) writePixelsImpl(pix []byte, region image.Rectangle) {
i.invalidatePixels()
i.img.WritePixels(pix, x, y, width, height)
i.img.WritePixels(pix, region)
}
// DrawTriangles draws the src image with the given vertices.

View File

@ -16,6 +16,7 @@ package mipmap
import (
"fmt"
"image"
"math"
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
@ -56,13 +57,13 @@ func (m *Mipmap) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name str
return m.orig.DumpScreenshot(graphicsDriver, name, blackbg)
}
func (m *Mipmap) WritePixels(pix []byte, x, y, width, height int) {
m.orig.WritePixels(pix, x, y, width, height)
func (m *Mipmap) WritePixels(pix []byte, region image.Rectangle) {
m.orig.WritePixels(pix, region)
m.disposeMipmaps()
}
func (m *Mipmap) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, x, y, width, height int) error {
return m.orig.ReadPixels(graphicsDriver, pixels, x, y, width, height)
func (m *Mipmap) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte, region image.Rectangle) error {
return m.orig.ReadPixels(graphicsDriver, pixels, region)
}
func (m *Mipmap) DrawTriangles(srcs [graphics.ShaderImageCount]*Mipmap, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms []uint32, evenOdd bool, canSkipMipmap bool) {

View File

@ -16,6 +16,7 @@ package ui
import (
"fmt"
"image"
"math"
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
@ -40,7 +41,7 @@ type Image struct {
height int
imageType atlas.ImageType
dotsBuffer map[[2]int][4]byte
dotsBuffer map[image.Point][4]byte
// bigOffscreenBuffer is a double-sized offscreen for anti-alias rendering.
bigOffscreenBuffer *bigOffscreenImage
@ -115,22 +116,22 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, blend, dstRegion, srcRegion, subimageOffsets, shader.shader, uniforms, evenOdd, canSkipMipmap)
}
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
func (i *Image) WritePixels(pix []byte, region image.Rectangle) {
if i.modifyCallback != nil {
i.modifyCallback()
}
if width == 1 && height == 1 {
if region.Dx() == 1 && region.Dy() == 1 {
// Flush the other buffer to make the buffers exclusive.
i.flushBigOffscreenBufferIfNeeded()
if i.dotsBuffer == nil {
i.dotsBuffer = map[[2]int][4]byte{}
i.dotsBuffer = map[image.Point][4]byte{}
}
var clr [4]byte
copy(clr[:], pix)
i.dotsBuffer[[2]int{x, y}] = clr
i.dotsBuffer[region.Min] = clr
// One square requires 6 indices (= 2 triangles).
if len(i.dotsBuffer) >= graphics.MaxVerticesCount/6 {
@ -140,10 +141,10 @@ func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
}
i.flushBufferIfNeeded()
i.mipmap.WritePixels(pix, x, y, width, height)
i.mipmap.WritePixels(pix, region)
}
func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) {
func (i *Image) ReadPixels(pixels []byte, region image.Rectangle) {
// Check the error existence and avoid unnecessary calls.
if theGlobalState.error() != nil {
return
@ -151,8 +152,8 @@ func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) {
i.flushBigOffscreenBufferIfNeeded()
if width == 1 && height == 1 {
if c, ok := i.dotsBuffer[[2]int{x, y}]; ok {
if region.Dx() == 1 && region.Dy() == 1 {
if c, ok := i.dotsBuffer[region.Min]; ok {
copy(pixels, c[:])
return
}
@ -162,7 +163,7 @@ func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) {
i.flushDotsBufferIfNeeded()
}
if err := theUI.readPixels(i.mipmap, pixels, x, y, width, height); err != nil {
if err := theUI.readPixels(i.mipmap, pixels, region); err != nil {
if panicOnErrorOnReadingPixels {
panic(err)
}
@ -192,8 +193,8 @@ func (i *Image) flushDotsBufferIfNeeded() {
sx, sy := float32(1), float32(1)
var idx int
for p, c := range i.dotsBuffer {
dx := float32(p[0])
dy := float32(p[1])
dx := float32(p.X)
dy := float32(p.Y)
crf := float32(c[0]) / 0xff
cgf := float32(c[1]) / 0xff
cbf := float32(c[2]) / 0xff
@ -273,19 +274,19 @@ func init() {
pix[i] = 0xff
}
// As whiteImage is used at Fill, use WritePixels instead.
whiteImage.WritePixels(pix, 0, 0, whiteImage.width, whiteImage.height)
whiteImage.WritePixels(pix, image.Rect(0, 0, whiteImage.width, whiteImage.height))
}
func (i *Image) clear() {
i.Fill(0, 0, 0, 0, 0, 0, i.width, i.height)
i.Fill(0, 0, 0, 0, image.Rect(0, 0, i.width, i.height))
}
func (i *Image) Fill(r, g, b, a float32, x, y, width, height int) {
func (i *Image) Fill(r, g, b, a float32, region image.Rectangle) {
dstRegion := graphicsdriver.Region{
X: float32(x),
Y: float32(y),
Width: float32(width),
Height: float32(height),
X: float32(region.Min.X),
Y: float32(region.Min.Y),
Width: float32(region.Dx()),
Height: float32(region.Dy()),
}
if len(i.tmpVerticesForFill) < 4*graphics.VertexFloatCount {

View File

@ -16,6 +16,7 @@ package ui
import (
"errors"
"image"
"github.com/hajimehoshi/ebiten/v2/internal/atlas"
"github.com/hajimehoshi/ebiten/v2/internal/mipmap"
@ -72,8 +73,8 @@ func Get() *UserInterface {
return theUI
}
func (u *UserInterface) readPixels(mipmap *mipmap.Mipmap, pixels []byte, x, y, width, height int) error {
return mipmap.ReadPixels(u.graphicsDriver, pixels, x, y, width, height)
func (u *UserInterface) readPixels(mipmap *mipmap.Mipmap, pixels []byte, region image.Rectangle) error {
return mipmap.ReadPixels(u.graphicsDriver, pixels, region)
}
func (u *UserInterface) dumpScreenshot(mipmap *mipmap.Mipmap, name string, blackbg bool) (string, error) {