mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-12 20:18:59 +01:00
internal/atlas: refactoring: move temporaryBytes to internal/graphicscommand
This commit is contained in:
parent
0fb1cdcfbd
commit
ce25583438
@ -21,6 +21,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphics"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/packing"
|
||||
"github.com/hajimehoshi/ebiten/v2/internal/restorable"
|
||||
@ -33,68 +34,6 @@ var (
|
||||
maxSize = 0
|
||||
)
|
||||
|
||||
type temporaryBytes struct {
|
||||
pixels []byte
|
||||
pos int
|
||||
notFullyUsedTime int
|
||||
}
|
||||
|
||||
var (
|
||||
theTemporaryBytesSet [2]temporaryBytes
|
||||
temporaryBytesIndex int
|
||||
)
|
||||
|
||||
func currentTemporaryBytes() *temporaryBytes {
|
||||
return &theTemporaryBytesSet[temporaryBytesIndex]
|
||||
}
|
||||
|
||||
func switchTemporaryBytes() {
|
||||
temporaryBytesIndex++
|
||||
temporaryBytesIndex %= len(theTemporaryBytesSet)
|
||||
}
|
||||
|
||||
func temporaryBytesSize(size int) int {
|
||||
l := 16
|
||||
for l < size {
|
||||
l *= 2
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// alloc allocates the pixels and returns it.
|
||||
// Be careful that the returned pixels might not be zero-cleared.
|
||||
func (t *temporaryBytes) alloc(size int) []byte {
|
||||
if len(t.pixels) < t.pos+size {
|
||||
t.pixels = make([]byte, max(len(t.pixels)*2, temporaryBytesSize(size)))
|
||||
t.pos = 0
|
||||
}
|
||||
pix := t.pixels[t.pos : t.pos+size]
|
||||
t.pos += size
|
||||
return pix
|
||||
}
|
||||
|
||||
func (t *temporaryBytes) resetAtFrameEnd() {
|
||||
const maxNotFullyUsedTime = 60
|
||||
|
||||
if temporaryBytesSize(t.pos) < len(t.pixels) {
|
||||
if t.notFullyUsedTime < maxNotFullyUsedTime {
|
||||
t.notFullyUsedTime++
|
||||
}
|
||||
} else {
|
||||
t.notFullyUsedTime = 0
|
||||
}
|
||||
|
||||
// Let the pixels GCed if this is not used for a while.
|
||||
if t.notFullyUsedTime == maxNotFullyUsedTime && len(t.pixels) > 0 {
|
||||
t.pixels = nil
|
||||
t.notFullyUsedTime = 0
|
||||
}
|
||||
|
||||
// Reset the position and reuse the allocated bytes.
|
||||
// t.pixels should already be sent to GPU, then this can be reused.
|
||||
t.pos = 0
|
||||
}
|
||||
|
||||
func max(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
@ -563,13 +502,13 @@ func (i *Image) writePixels(pix []byte, region image.Rectangle) {
|
||||
}
|
||||
|
||||
// Copy pixels in the case when pix is modified before the graphics command is executed.
|
||||
pix2 := currentTemporaryBytes().alloc(len(pix))
|
||||
pix2 := graphicscommand.AllocBytes(len(pix))
|
||||
copy(pix2, pix)
|
||||
i.backend.restorable.WritePixels(pix2, region)
|
||||
return
|
||||
}
|
||||
|
||||
pixb := currentTemporaryBytes().alloc(4 * r.Dx() * r.Dy())
|
||||
pixb := graphicscommand.AllocBytes(4 * r.Dx() * r.Dy())
|
||||
|
||||
// Clear the edges. pixb might not be zero-cleared.
|
||||
// TODO: These loops assume that paddingSize is 1.
|
||||
@ -807,9 +746,6 @@ func EndFrame(graphicsDriver graphicsdriver.Graphics, swapBuffersForGL func()) e
|
||||
return err
|
||||
}
|
||||
|
||||
currentTemporaryBytes().resetAtFrameEnd()
|
||||
switchTemporaryBytes()
|
||||
|
||||
for b := range theSourceBackendsForOneFrame {
|
||||
delete(theSourceBackendsForOneFrame, b)
|
||||
}
|
||||
|
71
internal/graphicscommand/bytes.go
Normal file
71
internal/graphicscommand/bytes.go
Normal file
@ -0,0 +1,71 @@
|
||||
// Copyright 2023 The Ebitengine 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 graphicscommand
|
||||
|
||||
type temporaryBytes struct {
|
||||
pixels []byte
|
||||
pos int
|
||||
notFullyUsedTime int
|
||||
}
|
||||
|
||||
func temporaryBytesSize(size int) int {
|
||||
l := 16
|
||||
for l < size {
|
||||
l *= 2
|
||||
}
|
||||
return l
|
||||
}
|
||||
|
||||
// alloc allocates the pixels and returns it.
|
||||
// Be careful that the returned pixels might not be zero-cleared.
|
||||
func (t *temporaryBytes) alloc(size int) []byte {
|
||||
if len(t.pixels) < t.pos+size {
|
||||
t.pixels = make([]byte, max(len(t.pixels)*2, temporaryBytesSize(size)))
|
||||
t.pos = 0
|
||||
}
|
||||
pix := t.pixels[t.pos : t.pos+size]
|
||||
t.pos += size
|
||||
return pix
|
||||
}
|
||||
|
||||
func (t *temporaryBytes) reset() {
|
||||
// reset is called in a render thread.
|
||||
// When reset is called, a queue is being flushed in a render thread, and the queue is never used in the game thread.
|
||||
// Thus, a mutex lock is not needed in alloc and reset.
|
||||
|
||||
const maxNotFullyUsedTime = 60
|
||||
|
||||
if temporaryBytesSize(t.pos) < len(t.pixels) {
|
||||
if t.notFullyUsedTime < maxNotFullyUsedTime {
|
||||
t.notFullyUsedTime++
|
||||
}
|
||||
} else {
|
||||
t.notFullyUsedTime = 0
|
||||
}
|
||||
|
||||
// Let the pixels GCed if this is not used for a while.
|
||||
if t.notFullyUsedTime == maxNotFullyUsedTime && len(t.pixels) > 0 {
|
||||
t.pixels = nil
|
||||
t.notFullyUsedTime = 0
|
||||
}
|
||||
|
||||
// Reset the position and reuse the allocated bytes.
|
||||
// t.pixels should already be sent to GPU, then this can be reused.
|
||||
t.pos = 0
|
||||
}
|
||||
|
||||
func AllocBytes(size int) []byte {
|
||||
return currentCommandQueue().temporaryBytes.alloc(size)
|
||||
}
|
@ -75,6 +75,8 @@ type commandQueue struct {
|
||||
|
||||
uint32sBuffer uint32sBuffer
|
||||
|
||||
temporaryBytes temporaryBytes
|
||||
|
||||
err atomic.Value
|
||||
}
|
||||
|
||||
@ -255,6 +257,7 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
|
||||
|
||||
if endFrame {
|
||||
q.uint32sBuffer.reset()
|
||||
q.temporaryBytes.reset()
|
||||
}
|
||||
}()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user