From c3e855ab0234ce8f705b2032fd7015d48bbc6fa1 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sun, 20 Mar 2022 16:44:11 +0900 Subject: [PATCH] internal/buffered: refactoring --- image.go | 5 ++--- internal/buffered/image.go | 39 ++++++++++++++++---------------------- internal/mipmap/mipmap.go | 11 ++++------- internal/ui/image.go | 13 ++++--------- 4 files changed, 26 insertions(+), 42 deletions(-) diff --git a/image.go b/image.go index 17b4f7205..629b72422 100644 --- a/image.go +++ b/image.go @@ -745,8 +745,7 @@ func (i *Image) Set(x, y int, clr color.Color) { } r, g, b, a := clr.RGBA() - pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)} - i.image.ReplaceSmallRegionPixels(pix, x, y, 1, 1) + i.image.Set(byte(r>>8), byte(g>>8), byte(b>>8), byte(a>>8), x, y) } // Dispose disposes the image data. @@ -792,7 +791,7 @@ func (i *Image) ReplacePixels(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.ReplaceLargeRegionPixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy()) + i.image.ReplacePixels(pixels, r.Min.X, r.Min.Y, r.Dx(), r.Dy()) } // NewImage returns an empty image. diff --git a/internal/buffered/image.go b/internal/buffered/image.go index 6fafdcab5..c88552991 100644 --- a/internal/buffered/image.go +++ b/internal/buffered/image.go @@ -166,10 +166,9 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name stri return i.img.DumpScreenshot(graphicsDriver, name, blackbg) } -// ReplaceLargeRegionPixels replaces the pixels with the specified region. -// ReplaceLargeRegionPixels is used for a relatively large region. +// ReplacePixels replaces the pixels at the specified region. // This call is not accumulated and send one draw call to replace pixels. -func (i *Image) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) error { +func (i *Image) ReplacePixels(pix []byte, x, y, width, height int) { if l := 4 * width * height; len(pix) != l { panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l)) } @@ -178,45 +177,37 @@ func (i *Image) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) er copied := make([]byte, len(pix)) copy(copied, pix) if tryAddDelayedCommand(func() error { - i.ReplaceLargeRegionPixels(copied, x, y, width, height) + i.ReplacePixels(copied, x, y, width, height) return nil }) { - return nil + return } } i.invalidatePendingPixels() i.img.ReplacePixels(pix, x, y, width, height) - return nil } -// ReplaceSmallRegionPixels replaces the pixels with the specified region. -// ReplaceSmallRegionPixels is used for a relatively small region. +// Set replaces the pixel at the specified position. // This call might be accumulated and send one draw call to replace pixels for the accumulated calls. -func (i *Image) ReplaceSmallRegionPixels(graphicsDriver graphicsdriver.Graphics, pix []byte, x, y, width, height int) error { - if l := 4 * width * height; len(pix) != l { - panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l)) - } - +func (i *Image) Set(graphicsDriver graphicsdriver.Graphics, r, g, b, a byte, x, y int) error { if maybeCanAddDelayedCommand() { - copied := make([]byte, len(pix)) - copy(copied, pix) if tryAddDelayedCommand(func() error { - i.ReplaceSmallRegionPixels(graphicsDriver, copied, x, y, width, height) + i.Set(graphicsDriver, r, g, b, a, x, y) return nil }) { return nil } } - if x == 0 && y == 0 && width == i.width && height == i.height { + if i.width == 1 && i.height == 1 { i.invalidatePendingPixels() // Call ReplacePixels immediately. Do not buffer the command. // If a lot of new images are created but they are used at different timings, // pixels are sent to GPU at different timings, which is very inefficient. - i.img.ReplacePixels(pix, x, y, width, height) + i.img.ReplacePixels([]byte{r, g, b, a}, x, y, 1, 1) return nil } @@ -227,14 +218,16 @@ func (i *Image) ReplaceSmallRegionPixels(graphicsDriver graphicsdriver.Graphics, } i.pixels = pix } - i.replacePendingPixels(pix, x, y, width, height) + i.setPendingPixel(r, g, b, a, x, y) return nil } -func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) { - for j := 0; j < height; j++ { - copy(i.pixels[4*((j+y)*i.width+x):], pix[4*j*width:4*(j+1)*width]) - } +func (i *Image) setPendingPixel(r, g, b, a byte, x, y int) { + idx := 4 * (y*i.width + x) + i.pixels[idx] = r + i.pixels[idx+1] = g + i.pixels[idx+2] = b + i.pixels[idx+3] = a i.needsToResolvePixels = true } diff --git a/internal/mipmap/mipmap.go b/internal/mipmap/mipmap.go index 966a86bcf..0a18002c2 100644 --- a/internal/mipmap/mipmap.go +++ b/internal/mipmap/mipmap.go @@ -71,16 +71,13 @@ func (m *Mipmap) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name str return m.orig.DumpScreenshot(graphicsDriver, name, blackbg) } -func (m *Mipmap) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) error { - if err := m.orig.ReplaceLargeRegionPixels(pix, x, y, width, height); err != nil { - return err - } +func (m *Mipmap) ReplacePixels(pix []byte, x, y, width, height int) { + m.orig.ReplacePixels(pix, x, y, width, height) m.disposeMipmaps() - return nil } -func (m *Mipmap) ReplaceSmallRegionPixels(graphicsDriver graphicsdriver.Graphics, pix []byte, x, y, width, height int) error { - if err := m.orig.ReplaceSmallRegionPixels(graphicsDriver, pix, x, y, width, height); err != nil { +func (m *Mipmap) Set(graphicsDriver graphicsdriver.Graphics, r, g, b, a byte, x, y int) error { + if err := m.orig.Set(graphicsDriver, r, g, b, a, x, y); err != nil { return err } m.disposeMipmaps() diff --git a/internal/ui/image.go b/internal/ui/image.go index 019590a7f..aca62db68 100644 --- a/internal/ui/image.go +++ b/internal/ui/image.go @@ -68,20 +68,15 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, vertices []f i.mipmap.DrawTriangles(srcMipmaps, vertices, indices, colorm, mode, filter, address, dstRegion, srcRegion, subimageOffsets, s, uniforms, evenOdd, canSkipMipmap) } -func (i *Image) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) { - if theGlobalState.error() != nil { - return - } - if err := i.mipmap.ReplaceLargeRegionPixels(pix, x, y, width, height); err != nil { - theGlobalState.setError(err) - } +func (i *Image) ReplacePixels(pix []byte, x, y, width, height int) { + i.mipmap.ReplacePixels(pix, x, y, width, height) } -func (i *Image) ReplaceSmallRegionPixels(pix []byte, x, y, width, height int) { +func (i *Image) Set(r, g, b, a byte, x, y int) { if theGlobalState.error() != nil { return } - if err := i.mipmap.ReplaceSmallRegionPixels(graphicsDriver(), pix, x, y, width, height); err != nil { + if err := i.mipmap.Set(graphicsDriver(), r, g, b, a, x, y); err != nil { theGlobalState.setError(err) } }