mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-27 19:22:49 +01:00
restorable: Do not record pixels if restoring is not requried
Fixes #1022
This commit is contained in:
parent
67706ce6ed
commit
5e1f263d6d
@ -26,15 +26,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/internal/png"
|
"github.com/hajimehoshi/ebiten/internal/png"
|
||||||
)
|
)
|
||||||
|
|
||||||
type lastCommand int
|
|
||||||
|
|
||||||
const (
|
|
||||||
lastCommandNone lastCommand = iota
|
|
||||||
lastCommandClear
|
|
||||||
lastCommandDrawTriangles
|
|
||||||
lastCommandReplacePixels
|
|
||||||
)
|
|
||||||
|
|
||||||
// Image represents an image that is implemented with OpenGL.
|
// Image represents an image that is implemented with OpenGL.
|
||||||
type Image struct {
|
type Image struct {
|
||||||
image driver.Image
|
image driver.Image
|
||||||
@ -51,8 +42,6 @@ type Image struct {
|
|||||||
id int
|
id int
|
||||||
|
|
||||||
bufferedRP []*driver.ReplacePixelsArgs
|
bufferedRP []*driver.ReplacePixelsArgs
|
||||||
|
|
||||||
lastCommand lastCommand
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nextID = 1
|
var nextID = 1
|
||||||
@ -151,12 +140,6 @@ func (i *Image) InternalSize() (int, int) {
|
|||||||
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
// If the source image is not specified, i.e., src is nil and there is no image in the uniform variables, the
|
||||||
// elements for the source image are not used.
|
// elements for the source image are not used.
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [graphics.ShaderImageNum - 1][2]float32, vertices []float32, indices []uint16, clr *affine.ColorM, mode driver.CompositeMode, filter driver.Filter, address driver.Address, sourceRegion driver.Region, shader *Shader, uniforms []interface{}) {
|
||||||
if i.lastCommand == lastCommandNone {
|
|
||||||
if !i.screen && mode != driver.CompositeModeClear {
|
|
||||||
panic("graphicscommand: the image must be cleared first")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, src := range srcs {
|
for _, src := range srcs {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
continue
|
continue
|
||||||
@ -169,12 +152,6 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageNum]*Image, offsets [gra
|
|||||||
i.resolveBufferedReplacePixels()
|
i.resolveBufferedReplacePixels()
|
||||||
|
|
||||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms)
|
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, clr, mode, filter, address, sourceRegion, shader, uniforms)
|
||||||
|
|
||||||
if i.lastCommand == lastCommandNone && !i.screen {
|
|
||||||
i.lastCommand = lastCommandClear
|
|
||||||
} else {
|
|
||||||
i.lastCommand = lastCommandDrawTriangles
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pixels returns the image's pixels.
|
// Pixels returns the image's pixels.
|
||||||
@ -193,12 +170,6 @@ func (i *Image) Pixels() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||||
// ReplacePixels for a part might invalidate the current image that are drawn by DrawTriangles (#593, #738).
|
|
||||||
if i.lastCommand == lastCommandDrawTriangles {
|
|
||||||
if x != 0 || y != 0 || i.width != width || i.height != height {
|
|
||||||
panic("graphicscommand: ReplacePixels for a part after DrawTriangles is forbidden")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
i.bufferedRP = append(i.bufferedRP, &driver.ReplacePixelsArgs{
|
i.bufferedRP = append(i.bufferedRP, &driver.ReplacePixelsArgs{
|
||||||
Pixels: pixels,
|
Pixels: pixels,
|
||||||
X: x,
|
X: x,
|
||||||
@ -206,7 +177,6 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
Width: width,
|
Width: width,
|
||||||
Height: height,
|
Height: height,
|
||||||
})
|
})
|
||||||
i.lastCommand = lastCommandReplacePixels
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) IsInvalidated() bool {
|
func (i *Image) IsInvalidated() bool {
|
||||||
|
@ -63,11 +63,6 @@ func TestClear(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||||
defer func() {
|
|
||||||
if r := recover(); r == nil {
|
|
||||||
t.Errorf("ReplacePixels must panic but not")
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
const w, h = 32, 32
|
const w, h = 32, 32
|
||||||
clr := NewImage(w, h)
|
clr := NewImage(w, h)
|
||||||
src := NewImage(w/2, h/2)
|
src := NewImage(w/2, h/2)
|
||||||
@ -77,6 +72,8 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
|||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeClear, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
dst.DrawTriangles([graphics.ShaderImageNum]*Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, nil, driver.CompositeModeSourceOver, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||||
|
|
||||||
|
// TODO: Check the result.
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestShader(t *testing.T) {
|
func TestShader(t *testing.T) {
|
||||||
|
@ -153,6 +153,18 @@ func NewImage(width, height int, volatile bool) *Image {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func newImageWithColor(width, height int, volatile bool, clr color.RGBA) *Image {
|
||||||
|
i := &Image{
|
||||||
|
image: graphicscommand.NewImage(width, height),
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
volatile: volatile,
|
||||||
|
}
|
||||||
|
fillImage(i.image, clr)
|
||||||
|
theImages.add(i)
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
// Extend extends the image by the given size.
|
// Extend extends the image by the given size.
|
||||||
// Extend creates a new image with the given size and copies the pixels of the given source image.
|
// Extend creates a new image with the given size and copies the pixels of the given source image.
|
||||||
// Extend disposes itself after its call.
|
// Extend disposes itself after its call.
|
||||||
@ -167,21 +179,22 @@ func (i *Image) Extend(width, height int) *Image {
|
|||||||
panic(fmt.Sprintf("restorable: the original size (%d, %d) cannot be extended to (%d, %d)", i.width, i.height, width, height))
|
panic(fmt.Sprintf("restorable: the original size (%d, %d) cannot be extended to (%d, %d)", i.width, i.height, width, height))
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.stale {
|
newImg := newImageWithColor(width, height, i.volatile, i.basePixels.baseColor)
|
||||||
panic("restorable: Extend at a stale image is forbidden")
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(i.drawTrianglesHistory) > 0 {
|
// Use DrawTriangles instead of ReplacePixels because the image i might be stale and not have its pixels
|
||||||
panic("restorable: Extend after DrawTriangles is forbidden")
|
// information.
|
||||||
}
|
srcs := [graphics.ShaderImageNum]*Image{i}
|
||||||
|
var offsets [graphics.ShaderImageNum - 1][2]float32
|
||||||
|
sw, sh := i.image.InternalSize()
|
||||||
|
vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1)
|
||||||
|
is := graphics.QuadIndices()
|
||||||
|
newImg.DrawTriangles(srcs, offsets, vs, is, nil, driver.CompositeModeCopy, driver.FilterNearest, driver.AddressUnsafe, driver.Region{}, nil, nil)
|
||||||
|
|
||||||
newImg := NewImage(width, height, i.volatile)
|
// Overwrite the history as if the image newImg is created only by ReplacePixels. Now drawTrianglesHistory
|
||||||
i.basePixels.Apply(newImg.image)
|
// and basePixels cannot be mixed.
|
||||||
|
newImg.drawTrianglesHistory = nil
|
||||||
if i.basePixels.baseColor != (color.RGBA{}) {
|
|
||||||
panic("restorable: baseColor must be empty at Extend")
|
|
||||||
}
|
|
||||||
newImg.basePixels = i.basePixels
|
newImg.basePixels = i.basePixels
|
||||||
|
newImg.stale = i.stale
|
||||||
|
|
||||||
i.Dispose()
|
i.Dispose()
|
||||||
|
|
||||||
@ -312,6 +325,11 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
i.image.ReplacePixels(make([]byte, 4*width*height), x, y, width, height)
|
i.image.ReplacePixels(make([]byte, 4*width*height), x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !needsRestoring() || i.screen || i.volatile {
|
||||||
|
i.makeStale()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
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)
|
i.basePixels.AddOrReplace(pixels, 0, 0, w, h)
|
||||||
@ -323,9 +341,7 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// It looked like ReplacePixels on a part of image deletes other region that are rendered by DrawTriangles
|
// drawTrianglesHistory and basePixels cannot be mixed.
|
||||||
// (#593, #758).
|
|
||||||
|
|
||||||
if len(i.drawTrianglesHistory) > 0 {
|
if len(i.drawTrianglesHistory) > 0 {
|
||||||
panic("restorable: ReplacePixels for a part after DrawTriangles is forbidden")
|
panic("restorable: ReplacePixels for a part after DrawTriangles is forbidden")
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user