internal/buffered: refactoring

This commit is contained in:
Hajime Hoshi 2022-03-20 16:44:11 +09:00
parent 673556d03f
commit c3e855ab02
4 changed files with 26 additions and 42 deletions

View File

@ -745,8 +745,7 @@ func (i *Image) Set(x, y int, clr color.Color) {
} }
r, g, b, a := clr.RGBA() r, g, b, a := clr.RGBA()
pix := []byte{byte(r >> 8), byte(g >> 8), byte(b >> 8), byte(a >> 8)} i.image.Set(byte(r>>8), byte(g>>8), byte(b>>8), byte(a>>8), x, y)
i.image.ReplaceSmallRegionPixels(pix, x, y, 1, 1)
} }
// Dispose disposes the image data. // Dispose disposes the image data.
@ -792,7 +791,7 @@ func (i *Image) ReplacePixels(pixels []byte) {
// Do not need to copy pixels here. // Do not need to copy pixels here.
// * In internal/mipmap, pixels are copied when necessary. // * In internal/mipmap, pixels are copied when necessary.
// * In internal/atlas, pixels are copied to make its paddings. // * 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. // NewImage returns an empty image.

View File

@ -166,10 +166,9 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name stri
return i.img.DumpScreenshot(graphicsDriver, name, blackbg) return i.img.DumpScreenshot(graphicsDriver, name, blackbg)
} }
// ReplaceLargeRegionPixels replaces the pixels with the specified region. // ReplacePixels replaces the pixels at the specified region.
// ReplaceLargeRegionPixels is used for a relatively large region.
// This call is not accumulated and send one draw call to replace pixels. // 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 { if l := 4 * width * height; len(pix) != l {
panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", 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)) copied := make([]byte, len(pix))
copy(copied, pix) copy(copied, pix)
if tryAddDelayedCommand(func() error { if tryAddDelayedCommand(func() error {
i.ReplaceLargeRegionPixels(copied, x, y, width, height) i.ReplacePixels(copied, x, y, width, height)
return nil return nil
}) { }) {
return nil return
} }
} }
i.invalidatePendingPixels() i.invalidatePendingPixels()
i.img.ReplacePixels(pix, x, y, width, height) i.img.ReplacePixels(pix, x, y, width, height)
return nil
} }
// ReplaceSmallRegionPixels replaces the pixels with the specified region. // Set replaces the pixel at the specified position.
// ReplaceSmallRegionPixels is used for a relatively small region.
// This call might be accumulated and send one draw call to replace pixels for the accumulated calls. // 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 { func (i *Image) Set(graphicsDriver graphicsdriver.Graphics, r, g, b, a byte, x, y 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))
}
if maybeCanAddDelayedCommand() { if maybeCanAddDelayedCommand() {
copied := make([]byte, len(pix))
copy(copied, pix)
if tryAddDelayedCommand(func() error { 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
}) { }) {
return nil return nil
} }
} }
if x == 0 && y == 0 && width == i.width && height == i.height { if i.width == 1 && i.height == 1 {
i.invalidatePendingPixels() i.invalidatePendingPixels()
// Call ReplacePixels immediately. Do not buffer the command. // Call ReplacePixels immediately. Do not buffer the command.
// If a lot of new images are created but they are used at different timings, // 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. // 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 return nil
} }
@ -227,14 +218,16 @@ func (i *Image) ReplaceSmallRegionPixels(graphicsDriver graphicsdriver.Graphics,
} }
i.pixels = pix i.pixels = pix
} }
i.replacePendingPixels(pix, x, y, width, height) i.setPendingPixel(r, g, b, a, x, y)
return nil return nil
} }
func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) { func (i *Image) setPendingPixel(r, g, b, a byte, x, y int) {
for j := 0; j < height; j++ { idx := 4 * (y*i.width + x)
copy(i.pixels[4*((j+y)*i.width+x):], pix[4*j*width:4*(j+1)*width]) i.pixels[idx] = r
} i.pixels[idx+1] = g
i.pixels[idx+2] = b
i.pixels[idx+3] = a
i.needsToResolvePixels = true i.needsToResolvePixels = true
} }

View File

@ -71,16 +71,13 @@ func (m *Mipmap) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name str
return m.orig.DumpScreenshot(graphicsDriver, name, blackbg) return m.orig.DumpScreenshot(graphicsDriver, name, blackbg)
} }
func (m *Mipmap) ReplaceLargeRegionPixels(pix []byte, x, y, width, height int) error { func (m *Mipmap) ReplacePixels(pix []byte, x, y, width, height int) {
if err := m.orig.ReplaceLargeRegionPixels(pix, x, y, width, height); err != nil { m.orig.ReplacePixels(pix, x, y, width, height)
return err
}
m.disposeMipmaps() m.disposeMipmaps()
return nil
} }
func (m *Mipmap) ReplaceSmallRegionPixels(graphicsDriver graphicsdriver.Graphics, pix []byte, x, y, width, height int) error { func (m *Mipmap) Set(graphicsDriver graphicsdriver.Graphics, r, g, b, a byte, x, y int) error {
if err := m.orig.ReplaceSmallRegionPixels(graphicsDriver, pix, x, y, width, height); err != nil { if err := m.orig.Set(graphicsDriver, r, g, b, a, x, y); err != nil {
return err return err
} }
m.disposeMipmaps() m.disposeMipmaps()

View File

@ -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) 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) { func (i *Image) ReplacePixels(pix []byte, x, y, width, height int) {
if theGlobalState.error() != nil { i.mipmap.ReplacePixels(pix, x, y, width, height)
return
}
if err := i.mipmap.ReplaceLargeRegionPixels(pix, x, y, width, height); err != nil {
theGlobalState.setError(err)
}
} }
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 { if theGlobalState.error() != nil {
return 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) theGlobalState.setError(err)
} }
} }