mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
parent
2bba43d6db
commit
a6edb90898
@ -91,13 +91,20 @@ type Image struct {
|
||||
|
||||
backend *backend
|
||||
|
||||
node *packing.Node
|
||||
node *packing.Node
|
||||
sharedCount int
|
||||
}
|
||||
|
||||
func (i *Image) isShared() bool {
|
||||
return i.node != nil
|
||||
}
|
||||
|
||||
func (i *Image) IsSharedForTesting() bool {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
return i.isShared()
|
||||
}
|
||||
|
||||
func (i *Image) ensureNotShared() {
|
||||
if i.backend == nil {
|
||||
i.allocate(false)
|
||||
@ -121,6 +128,36 @@ func (i *Image) ensureNotShared() {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Image) forceShared() {
|
||||
if i.backend == nil {
|
||||
i.allocate(false)
|
||||
return
|
||||
}
|
||||
|
||||
if i.isShared() {
|
||||
return
|
||||
}
|
||||
|
||||
if !i.shareable() {
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
newI := NewImage(i.width, i.height)
|
||||
pixels := make([]byte, 4*i.width*i.height)
|
||||
for y := 0; y < i.height; y++ {
|
||||
for x := 0; x < i.width; x++ {
|
||||
c := i.at(x, y).(color.RGBA)
|
||||
pixels[4*(x+i.width*y)] = c.R
|
||||
pixels[4*(x+i.width*y)+1] = c.G
|
||||
pixels[4*(x+i.width*y)+2] = c.B
|
||||
pixels[4*(x+i.width*y)+3] = c.A
|
||||
}
|
||||
}
|
||||
newI.replacePixels(pixels)
|
||||
i.dispose(false)
|
||||
*i = *newI
|
||||
}
|
||||
|
||||
func (i *Image) region() (x, y, width, height int) {
|
||||
if i.backend == nil {
|
||||
panic("not reached")
|
||||
@ -145,6 +182,8 @@ func (i *Image) QuadVertices(sx0, sy0, sx1, sy1 int, a, b, c, d, tx, ty float32)
|
||||
return graphicsutil.QuadVertices(w, h, sx0+dx, sy0+dy, sx1+dx, sy1+dy, a, b, c, d, tx, ty)
|
||||
}
|
||||
|
||||
const ReshareCount = 10
|
||||
|
||||
func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode opengl.CompositeMode, filter graphics.Filter) {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
@ -168,12 +207,24 @@ func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colo
|
||||
}
|
||||
|
||||
i.backend.restorable.DrawImage(img.backend.restorable, vertices, indices, colorm, mode, filter)
|
||||
|
||||
i.sharedCount = 0
|
||||
if !img.isShared() && img.shareable() {
|
||||
img.sharedCount++
|
||||
if img.sharedCount >= ReshareCount {
|
||||
img.forceShared()
|
||||
img.sharedCount = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Image) ReplacePixels(p []byte) {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
i.replacePixels(p)
|
||||
}
|
||||
|
||||
func (i *Image) replacePixels(p []byte) {
|
||||
if i.disposed {
|
||||
panic("shareable: the image must not be disposed")
|
||||
}
|
||||
@ -191,7 +242,10 @@ func (i *Image) ReplacePixels(p []byte) {
|
||||
func (i *Image) At(x, y int) color.Color {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
return i.at(x, y)
|
||||
}
|
||||
|
||||
func (i *Image) at(x, y int) color.Color {
|
||||
if i.backend == nil {
|
||||
return color.RGBA{}
|
||||
}
|
||||
@ -271,12 +325,16 @@ func NewImage(width, height int) *Image {
|
||||
}
|
||||
}
|
||||
|
||||
func (i *Image) shareable() bool {
|
||||
return i.width <= maxSize && i.height <= maxSize
|
||||
}
|
||||
|
||||
func (i *Image) allocate(shareable bool) {
|
||||
if i.backend != nil {
|
||||
panic("not reached")
|
||||
}
|
||||
|
||||
if !shareable || i.width > maxSize || i.height > maxSize {
|
||||
if !shareable || !i.shareable() {
|
||||
i.backend = &backend{
|
||||
restorable: restorable.NewImage(i.width, i.height, false),
|
||||
}
|
||||
|
@ -88,6 +88,10 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
vs := img3.QuadVertices(0, 0, size/2, size/2, 1, 0, 0, 1, size/4, size/4)
|
||||
is := graphicsutil.QuadIndices()
|
||||
img4.DrawImage(img3, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||
want := false
|
||||
if got := img4.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
@ -107,3 +111,76 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
// This bug was fixed by 03dcd948.
|
||||
img4.DrawImage(img3, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||
}
|
||||
|
||||
func TestReshared(t *testing.T) {
|
||||
const size = 16
|
||||
|
||||
img0 := NewImage(size, size)
|
||||
defer img0.Dispose()
|
||||
img0.ReplacePixels(make([]byte, 4*size*size))
|
||||
|
||||
img1 := NewImage(size, size)
|
||||
defer img1.Dispose()
|
||||
img1.ReplacePixels(make([]byte, 4*size*size))
|
||||
want := true
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
img2 := NewImage(size, size)
|
||||
defer img2.Dispose()
|
||||
pix := make([]byte, 4*size*size)
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
pix[4*(i+j*size)] = byte(i + j)
|
||||
pix[4*(i+j*size)+1] = byte(i + j)
|
||||
pix[4*(i+j*size)+2] = byte(i + j)
|
||||
pix[4*(i+j*size)+3] = byte(i + j)
|
||||
}
|
||||
}
|
||||
img2.ReplacePixels(pix)
|
||||
|
||||
// Use img1 as a render target.
|
||||
vs := img2.QuadVertices(0, 0, size, size, 1, 0, 0, 1, 0, 0)
|
||||
is := graphicsutil.QuadIndices()
|
||||
img1.DrawImage(img2, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||
want = false
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
// Use img1 as a render source.
|
||||
for i := 0; i < ReshareCount-1; i++ {
|
||||
img0.DrawImage(img1, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||
want := false
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
want := color.RGBA{byte(i + j), byte(i + j), byte(i + j), byte(i + j)}
|
||||
got := img1.At(i, j).(color.RGBA)
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
img0.DrawImage(img1, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
||||
want = true
|
||||
if got := img1.IsSharedForTesting(); got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
want := color.RGBA{byte(i + j), byte(i + j), byte(i + j), byte(i + j)}
|
||||
got := img1.At(i, j).(color.RGBA)
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user