mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-23 17:32:02 +01:00
internal/atlas: Reuse byte array for ReplacePixels
This reduces memory allocation at ReplacePixels. Updates #1681
This commit is contained in:
parent
371bbfc0f2
commit
38ce46328a
@ -38,6 +38,53 @@ var (
|
|||||||
maxSize = 0
|
maxSize = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type temporaryPixels struct {
|
||||||
|
pixels []byte
|
||||||
|
pos int
|
||||||
|
totalUse int
|
||||||
|
unusedTime int
|
||||||
|
}
|
||||||
|
|
||||||
|
var theTemporaryPixels temporaryPixels
|
||||||
|
|
||||||
|
func (t *temporaryPixels) alloc(size int) []byte {
|
||||||
|
if len(t.pixels) < t.pos+size {
|
||||||
|
newL := len(t.pixels)
|
||||||
|
if newL == 0 {
|
||||||
|
newL = 16
|
||||||
|
}
|
||||||
|
for newL < t.pos+size {
|
||||||
|
newL *= 2
|
||||||
|
}
|
||||||
|
t.pixels = make([]byte, newL)
|
||||||
|
t.pos = 0
|
||||||
|
}
|
||||||
|
pix := t.pixels[t.pos : t.pos+size]
|
||||||
|
t.pos += size
|
||||||
|
t.totalUse += size
|
||||||
|
return pix
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t *temporaryPixels) resetAtFrameEnd() {
|
||||||
|
const maxUnusedTime = 60
|
||||||
|
|
||||||
|
if t.totalUse == 0 {
|
||||||
|
if t.unusedTime < maxUnusedTime {
|
||||||
|
t.unusedTime++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
t.unusedTime = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Let the pixels GCed if this is not used for a while.
|
||||||
|
if t.unusedTime == maxUnusedTime && len(t.pixels) > 0 {
|
||||||
|
t.pixels = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
t.pos = 0
|
||||||
|
t.totalUse = 0
|
||||||
|
}
|
||||||
|
|
||||||
func max(a, b int) int {
|
func max(a, b int) int {
|
||||||
if a > b {
|
if a > b {
|
||||||
return a
|
return a
|
||||||
@ -487,7 +534,7 @@ func (i *Image) replacePixels(pix []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a padding around the image.
|
// Add a padding around the image.
|
||||||
pixb := make([]byte, 4*w*h)
|
pixb := theTemporaryPixels.alloc(4 * w * h)
|
||||||
for j := 0; j < oh; j++ {
|
for j := 0; j < oh; j++ {
|
||||||
copy(pixb[4*((j+paddingSize)*w+paddingSize):], pix[4*j*ow:4*(j+1)*ow])
|
copy(pixb[4*((j+paddingSize)*w+paddingSize):], pix[4*j*ow:4*(j+1)*ow])
|
||||||
}
|
}
|
||||||
@ -700,6 +747,8 @@ func NewScreenFramebufferImage(width, height int) *Image {
|
|||||||
func EndFrame() error {
|
func EndFrame() error {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
|
|
||||||
|
theTemporaryPixels.resetAtFrameEnd()
|
||||||
|
|
||||||
return restorable.ResolveStaleImages()
|
return restorable.ResolveStaleImages()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,11 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
|
|
||||||
if x == 0 && y == 0 && width == w && height == h {
|
if x == 0 && y == 0 && width == w && height == h {
|
||||||
if pixels != nil {
|
if pixels != nil {
|
||||||
i.basePixels.AddOrReplace(pixels, 0, 0, w, h)
|
// pixels can point to a shared region.
|
||||||
|
// This function is responsible to copy this.
|
||||||
|
copiedPixels := make([]byte, len(pixels))
|
||||||
|
copy(copiedPixels, pixels)
|
||||||
|
i.basePixels.AddOrReplace(copiedPixels, 0, 0, w, h)
|
||||||
} else {
|
} else {
|
||||||
i.basePixels.Remove(0, 0, w, h)
|
i.basePixels.Remove(0, 0, w, h)
|
||||||
}
|
}
|
||||||
@ -324,7 +328,11 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if pixels != nil {
|
if pixels != nil {
|
||||||
i.basePixels.AddOrReplace(pixels, x, y, width, height)
|
// pixels can point to a shared region.
|
||||||
|
// This function is responsible to copy this.
|
||||||
|
copiedPixels := make([]byte, len(pixels))
|
||||||
|
copy(copiedPixels, pixels)
|
||||||
|
i.basePixels.AddOrReplace(copiedPixels, x, y, width, height)
|
||||||
} else {
|
} else {
|
||||||
i.basePixels.Remove(x, y, width, height)
|
i.basePixels.Remove(x, y, width, height)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user