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
|
backend *backend
|
||||||
|
|
||||||
node *packing.Node
|
node *packing.Node
|
||||||
|
sharedCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) isShared() bool {
|
func (i *Image) isShared() bool {
|
||||||
return i.node != nil
|
return i.node != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Image) IsSharedForTesting() bool {
|
||||||
|
backendsM.Lock()
|
||||||
|
defer backendsM.Unlock()
|
||||||
|
return i.isShared()
|
||||||
|
}
|
||||||
|
|
||||||
func (i *Image) ensureNotShared() {
|
func (i *Image) ensureNotShared() {
|
||||||
if i.backend == nil {
|
if i.backend == nil {
|
||||||
i.allocate(false)
|
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) {
|
func (i *Image) region() (x, y, width, height int) {
|
||||||
if i.backend == nil {
|
if i.backend == nil {
|
||||||
panic("not reached")
|
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)
|
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) {
|
func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colorm *affine.ColorM, mode opengl.CompositeMode, filter graphics.Filter) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
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.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) {
|
func (i *Image) ReplacePixels(p []byte) {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
|
i.replacePixels(p)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) replacePixels(p []byte) {
|
||||||
if i.disposed {
|
if i.disposed {
|
||||||
panic("shareable: the image must not be 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 {
|
func (i *Image) At(x, y int) color.Color {
|
||||||
backendsM.Lock()
|
backendsM.Lock()
|
||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
|
return i.at(x, y)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) at(x, y int) color.Color {
|
||||||
if i.backend == nil {
|
if i.backend == nil {
|
||||||
return color.RGBA{}
|
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) {
|
func (i *Image) allocate(shareable bool) {
|
||||||
if i.backend != nil {
|
if i.backend != nil {
|
||||||
panic("not reached")
|
panic("not reached")
|
||||||
}
|
}
|
||||||
|
|
||||||
if !shareable || i.width > maxSize || i.height > maxSize {
|
if !shareable || !i.shareable() {
|
||||||
i.backend = &backend{
|
i.backend = &backend{
|
||||||
restorable: restorable.NewImage(i.width, i.height, false),
|
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)
|
vs := img3.QuadVertices(0, 0, size/2, size/2, 1, 0, 0, 1, size/4, size/4)
|
||||||
is := graphicsutil.QuadIndices()
|
is := graphicsutil.QuadIndices()
|
||||||
img4.DrawImage(img3, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
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 j := 0; j < size; j++ {
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
@ -107,3 +111,76 @@ func TestEnsureNotShared(t *testing.T) {
|
|||||||
// This bug was fixed by 03dcd948.
|
// This bug was fixed by 03dcd948.
|
||||||
img4.DrawImage(img3, vs, is, nil, opengl.CompositeModeCopy, graphics.FilterNearest)
|
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