internal/buffer: remove the graphics-driver argument from ReplacePartialRegionPixels

This is necessary to remove the graphics driver usage from
(*ebiten.Image).At. And this is necessary to determine the graphics
driver after the window becomes transparent or not.

Unfortunately, it is not obvious to make a transparent window with
DirectX. Then, the determination of a graphics driver should be delayed.

Updates #1007
This commit is contained in:
Hajime Hoshi 2022-03-21 04:11:36 +09:00
parent 4f070915b2
commit 29f7a45ccc
3 changed files with 50 additions and 42 deletions

View File

@ -30,6 +30,7 @@ type Image struct {
height int height int
pixels []byte pixels []byte
mask []byte
needsToResolvePixels bool needsToResolvePixels bool
} }
@ -112,6 +113,7 @@ func (i *Image) initializeAsScreenFramebuffer(width, height int) {
func (i *Image) invalidatePendingPixels() { func (i *Image) invalidatePendingPixels() {
i.pixels = nil i.pixels = nil
i.mask = nil
i.needsToResolvePixels = false i.needsToResolvePixels = false
} }
@ -120,9 +122,10 @@ func (i *Image) resolvePendingPixels(keepPendingPixels bool) {
return return
} }
i.img.ReplacePixels(i.pixels, nil) i.img.ReplacePixels(i.pixels, i.mask)
if !keepPendingPixels { if !keepPendingPixels || i.mask != nil {
i.pixels = nil i.pixels = nil
i.mask = nil
} }
i.needsToResolvePixels = false i.needsToResolvePixels = false
} }
@ -140,28 +143,29 @@ func (i *Image) MarkDisposed() {
i.img.MarkDisposed() i.img.MarkDisposed()
} }
func (i *Image) ensurePixels(graphicsDriver graphicsdriver.Graphics) error {
if i.pixels != nil {
return nil
}
pix, err := i.img.Pixels(graphicsDriver)
if err != nil {
return err
}
i.pixels = pix
return nil
}
func (img *Image) At(graphicsDriver graphicsdriver.Graphics, x, y int) (r, g, b, a byte, err error) { func (img *Image) At(graphicsDriver graphicsdriver.Graphics, x, y int) (r, g, b, a byte, err error) {
checkDelayedCommandsFlushed("At") checkDelayedCommandsFlushed("At")
if err := img.ensurePixels(graphicsDriver); err != nil { idx := (y*img.width + x)
return 0, 0, 0, 0, err if img.pixels != nil {
if img.mask == nil {
return img.pixels[4*idx], img.pixels[4*idx+1], img.pixels[4*idx+2], img.pixels[4*idx+3], nil
}
if img.mask[idx/8]<<(idx%8)&1 != 0 {
return img.pixels[4*idx], img.pixels[4*idx+1], img.pixels[4*idx+2], img.pixels[4*idx+3], nil
} }
idx := 4 * (y*img.width + x) img.resolvePendingPixels(false)
return img.pixels[idx], img.pixels[idx+1], img.pixels[idx+2], img.pixels[idx+3], nil }
pix, err := img.img.Pixels(graphicsDriver)
if err != nil {
return 0, 0, 0, 0, err
}
img.pixels = pix
// When pixels represents the whole pixels, the mask is not needed.
img.mask = nil
return img.pixels[4*idx], img.pixels[4*idx+1], img.pixels[4*idx+2], img.pixels[4*idx+3], nil
} }
func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name string, blackbg bool) error { func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, name string, blackbg bool) error {
@ -194,7 +198,7 @@ func (i *Image) ReplacePixels(pix []byte) {
// ReplacePartial replaces the pixel at the specified partial region. // ReplacePartial replaces the pixel at the specified partial region.
// This call might be accumulated and send one draw call to replace pixels for the accumulated calls. // This call might be accumulated and send one draw call to replace pixels for the accumulated calls.
func (i *Image) ReplacePartialPixels(graphicsDriver graphicsdriver.Graphics, pix []byte, x, y, width, height int) error { func (i *Image) ReplacePartialPixels(pix []byte, x, y, width, height int) {
if l := 4 * width * height; len(pix) != l { if l := 4 * width * height; len(pix) != l {
panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l)) panic(fmt.Sprintf("buffered: len(pix) was %d but must be %d", len(pix), l))
} }
@ -203,26 +207,38 @@ func (i *Image) ReplacePartialPixels(graphicsDriver graphicsdriver.Graphics, pix
if tryAddDelayedCommand(func() error { if tryAddDelayedCommand(func() error {
copied := make([]byte, len(pix)) copied := make([]byte, len(pix))
copy(copied, pix) copy(copied, pix)
i.ReplacePartialPixels(graphicsDriver, copied, x, y, width, height) i.ReplacePartialPixels(copied, x, y, width, height)
return nil return nil
}) { }) {
return nil return
} }
} }
if err := i.ensurePixels(graphicsDriver); err != nil {
return err
}
i.replacePendingPixels(pix, x, y, width, height) i.replacePendingPixels(pix, x, y, width, height)
return nil
} }
func (i *Image) replacePendingPixels(pix []byte, x, y, width, height int) { func (img *Image) replacePendingPixels(pix []byte, x, y, width, height int) {
for j := 0; j < height; j++ { if img.pixels == nil {
copy(i.pixels[4*((j+y)*i.width+x):], pix[4*j*width:4*(j+1)*width]) img.pixels = make([]byte, 4*img.width*img.height)
if img.mask == nil {
img.mask = make([]byte, (img.width*img.height-1)/8+1)
} }
i.needsToResolvePixels = true }
for j := 0; j < height; j++ {
copy(img.pixels[4*((j+y)*img.width+x):], pix[4*j*width:4*(j+1)*width])
}
// A mask is created only when a partial regions are replaced by replacePendingPixels.
if img.mask != nil {
for j := 0; j < height; j++ {
for i := 0; i < width; i++ {
idx := (y+j)*img.width + x + i
img.mask[idx/8] |= 1 << (idx % 8)
}
}
}
img.needsToResolvePixels = true
} }
// DrawTriangles draws the src image with the given vertices. // DrawTriangles draws the src image with the given vertices.

View File

@ -76,12 +76,9 @@ func (m *Mipmap) ReplacePixels(pix []byte) {
m.disposeMipmaps() m.disposeMipmaps()
} }
func (m *Mipmap) ReplacePartialPixels(graphicsDriver graphicsdriver.Graphics, pix []byte, x, y, width, height int) error { func (m *Mipmap) ReplacePartialPixels(pix []byte, x, y, width, height int) {
if err := m.orig.ReplacePartialPixels(graphicsDriver, pix, x, y, width, height); err != nil { m.orig.ReplacePartialPixels(pix, x, y, width, height)
return err
}
m.disposeMipmaps() m.disposeMipmaps()
return nil
} }
func (m *Mipmap) At(graphicsDriver graphicsdriver.Graphics, x, y int) (r, g, b, a byte, err error) { func (m *Mipmap) At(graphicsDriver graphicsdriver.Graphics, x, y int) (r, g, b, a byte, err error) {

View File

@ -73,12 +73,7 @@ func (i *Image) ReplacePixels(pix []byte) {
} }
func (i *Image) ReplacePartialPixels(pix []byte, x, y, width, height int) { func (i *Image) ReplacePartialPixels(pix []byte, x, y, width, height int) {
if theGlobalState.error() != nil { i.mipmap.ReplacePartialPixels(pix, x, y, width, height)
return
}
if err := i.mipmap.ReplacePartialPixels(graphicsDriver(), pix, x, y, width, height); err != nil {
theGlobalState.setError(err)
}
} }
func (i *Image) At(x, y int) (r, g, b, a byte) { func (i *Image) At(x, y int) (r, g, b, a byte) {