mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
restorable: Add Fill
This is useful to reduce opportunity to make the image stale.
This commit is contained in:
parent
40f728a326
commit
93d0b0dd09
@ -60,14 +60,20 @@ type Image struct {
|
|||||||
priority bool
|
priority bool
|
||||||
}
|
}
|
||||||
|
|
||||||
var dummyImage *Image
|
var emptyImage *Image
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
dummyImage = &Image{
|
const w, h = 16, 16
|
||||||
image: graphicscommand.NewImage(16, 16),
|
emptyImage = &Image{
|
||||||
|
image: graphicscommand.NewImage(w, h),
|
||||||
priority: true,
|
priority: true,
|
||||||
}
|
}
|
||||||
theImages.add(dummyImage)
|
pix := make([]byte, 4*w*h)
|
||||||
|
for i := range pix {
|
||||||
|
pix[i] = 0xff
|
||||||
|
}
|
||||||
|
emptyImage.ReplacePixels(pix, 0, 0, w, h)
|
||||||
|
theImages.add(emptyImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImage creates an empty image with the given size.
|
// NewImage creates an empty image with the given size.
|
||||||
@ -103,30 +109,61 @@ func NewScreenFramebufferImage(width, height int) *Image {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) Clear() {
|
func (i *Image) Fill(r, g, b, a uint8) {
|
||||||
theImages.makeStaleIfDependingOn(i)
|
theImages.makeStaleIfDependingOn(i)
|
||||||
i.clear()
|
i.fill(r, g, b, a)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) clear() {
|
func (i *Image) clear() {
|
||||||
|
i.fill(0, 0, 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *Image) fill(r, g, b, a uint8) {
|
||||||
if i.priority {
|
if i.priority {
|
||||||
panic("restorable: clear cannot be called on a priority image")
|
panic("restorable: clear cannot be called on a priority image")
|
||||||
}
|
}
|
||||||
|
|
||||||
// There are not 'drawImageHistoryItem's for this image and dummyImage.
|
rf := float32(0)
|
||||||
// As dummyImage is a priority image, this is restored before other regular images are restored.
|
gf := float32(0)
|
||||||
|
bf := float32(0)
|
||||||
|
af := float32(0)
|
||||||
|
if a > 0 {
|
||||||
|
rf = float32(r) / float32(a)
|
||||||
|
gf = float32(g) / float32(a)
|
||||||
|
bf = float32(b) / float32(a)
|
||||||
|
af = float32(a) / 0xff
|
||||||
|
}
|
||||||
|
|
||||||
|
// There are not 'drawImageHistoryItem's for this image and emptyImage.
|
||||||
|
// As emptyImage is a priority image, this is restored before other regular images are restored.
|
||||||
w, h := i.Size()
|
w, h := i.Size()
|
||||||
sw, sh := dummyImage.Size()
|
sw, sh := emptyImage.Size()
|
||||||
dw := graphics.NextPowerOf2Int(w)
|
dw := graphics.NextPowerOf2Int(w)
|
||||||
dh := graphics.NextPowerOf2Int(h)
|
dh := graphics.NextPowerOf2Int(h)
|
||||||
vs := graphics.QuadVertices(dw, dh, 0, 0, sw, sh,
|
vs := graphics.QuadVertices(dw, dh, 0, 0, sw, sh,
|
||||||
float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh),
|
float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0,
|
||||||
0, 0,
|
rf, gf, bf, af)
|
||||||
1, 1, 1, 1)
|
|
||||||
is := graphics.QuadIndices()
|
is := graphics.QuadIndices()
|
||||||
i.image.DrawImage(dummyImage.image, vs, is, nil, graphics.CompositeModeClear, graphics.FilterNearest, graphics.AddressClampToZero)
|
c := graphics.CompositeModeCopy
|
||||||
|
if a == 0 {
|
||||||
|
c = graphics.CompositeModeClear
|
||||||
|
}
|
||||||
|
i.image.DrawImage(emptyImage.image, vs, is, nil, c, graphics.FilterNearest, graphics.AddressClampToZero)
|
||||||
|
|
||||||
|
if a == 0 {
|
||||||
i.basePixels = nil
|
i.basePixels = nil
|
||||||
|
} else {
|
||||||
|
// TODO: Add baseColor?
|
||||||
|
if i.basePixels == nil {
|
||||||
|
i.basePixels = make([]byte, 4*w*h)
|
||||||
|
}
|
||||||
|
for idx := 0; idx < w*h; idx++ {
|
||||||
|
i.basePixels[4*idx] = r
|
||||||
|
i.basePixels[4*idx+1] = g
|
||||||
|
i.basePixels[4*idx+2] = b
|
||||||
|
i.basePixels[4*idx+3] = a
|
||||||
|
}
|
||||||
|
}
|
||||||
i.drawImageHistory = nil
|
i.drawImageHistory = nil
|
||||||
i.stale = false
|
i.stale = false
|
||||||
}
|
}
|
||||||
@ -406,7 +443,6 @@ func (i *Image) restore() error {
|
|||||||
gimg.ReplacePixels(i.basePixels, 0, 0, w, h)
|
gimg.ReplacePixels(i.basePixels, 0, 0, w, h)
|
||||||
} else {
|
} else {
|
||||||
// Clear the image explicitly.
|
// Clear the image explicitly.
|
||||||
// TODO: Is dummyImage available for clearing?
|
|
||||||
pix := make([]uint8, w*h*4)
|
pix := make([]uint8, w*h*4)
|
||||||
gimg.ReplacePixels(pix, 0, 0, w, h)
|
gimg.ReplacePixels(pix, 0, 0, w, h)
|
||||||
}
|
}
|
||||||
|
@ -252,22 +252,6 @@ func (i *Image) DrawImage(img *Image, vertices []float32, indices []uint16, colo
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// emptyImage is an empty image used for filling other images with a uniform color.
|
|
||||||
//
|
|
||||||
// Do not call Fill on emptyImage or the program causes infinite recursion.
|
|
||||||
var emptyImage = NewImage(16, 16)
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
// Initialize emptyImage. As emptyImage is used for Fill, emptyImage itself cannot be initialized with Fill.
|
|
||||||
// Call ReplacePixels instead.
|
|
||||||
w, h := emptyImage.Size()
|
|
||||||
pix := make([]byte, 4*w*h)
|
|
||||||
for i := range pix {
|
|
||||||
pix[i] = 0xff
|
|
||||||
}
|
|
||||||
emptyImage.ReplacePixels(pix)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill fills the image with a color. This affects not only the (0, 0)-(width, height) region but also the whole
|
// Fill fills the image with a color. This affects not only the (0, 0)-(width, height) region but also the whole
|
||||||
// framebuffer region.
|
// framebuffer region.
|
||||||
func (i *Image) Fill(r, g, b, a uint8) {
|
func (i *Image) Fill(r, g, b, a uint8) {
|
||||||
@ -278,35 +262,7 @@ func (i *Image) Fill(r, g, b, a uint8) {
|
|||||||
i.ensureNotShared()
|
i.ensureNotShared()
|
||||||
backendsM.Unlock()
|
backendsM.Unlock()
|
||||||
|
|
||||||
if r == 0 && g == 0 && b == 0 && a == 0 {
|
i.backend.restorable.Fill(r, g, b, a)
|
||||||
i.backend.restorable.Clear()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
rf := float32(0)
|
|
||||||
gf := float32(0)
|
|
||||||
bf := float32(0)
|
|
||||||
af := float32(0)
|
|
||||||
if a > 0 {
|
|
||||||
rf = float32(r) / float32(a)
|
|
||||||
gf = float32(g) / float32(a)
|
|
||||||
bf = float32(b) / float32(a)
|
|
||||||
af = float32(a) / 0xff
|
|
||||||
}
|
|
||||||
|
|
||||||
dw, dh := i.backend.restorable.SizePowerOf2()
|
|
||||||
sw, sh := emptyImage.Size()
|
|
||||||
vs := emptyImage.QuadVertices(0, 0, sw, sh,
|
|
||||||
float32(dw)/float32(sw), 0, 0, float32(dh)/float32(sh), 0, 0,
|
|
||||||
rf, gf, bf, af)
|
|
||||||
is := graphics.QuadIndices()
|
|
||||||
|
|
||||||
c := graphics.CompositeModeCopy
|
|
||||||
if a == 0xff {
|
|
||||||
// If the color is opaque, SourceOver is available and this is preferable for optimization.
|
|
||||||
c = graphics.CompositeModeSourceOver
|
|
||||||
}
|
|
||||||
i.DrawImage(emptyImage, vs, is, nil, c, graphics.FilterNearest, graphics.AddressClampToZero)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) ReplacePixels(p []byte) {
|
func (i *Image) ReplacePixels(p []byte) {
|
||||||
|
Loading…
Reference in New Issue
Block a user