mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 02:38:53 +01:00
internal/graphicscommand: add a new paramter 'mask' to ReplacePixels
This commit is contained in:
parent
c1a0d83f8d
commit
5fe6791b5d
@ -584,7 +584,36 @@ func (c *replacePixelsCommand) String() string {
|
||||
|
||||
// Exec executes the replacePixelsCommand.
|
||||
func (c *replacePixelsCommand) Exec(graphicsDriver graphicsdriver.Graphics, indexOffset int) error {
|
||||
c.dst.image.ReplacePixels(c.args)
|
||||
var lastArgIdx int
|
||||
for i, a := range c.args {
|
||||
if a.Mask == nil {
|
||||
continue
|
||||
}
|
||||
if len(c.args[lastArgIdx:i]) > 0 {
|
||||
c.dst.image.ReplacePixels(c.args[lastArgIdx:i])
|
||||
lastArgIdx = i
|
||||
}
|
||||
|
||||
orig := make([]byte, 4*c.dst.width*c.dst.height)
|
||||
if err := c.dst.image.ReadPixels(orig); err != nil {
|
||||
return err
|
||||
}
|
||||
for j := 0; j < a.Height; j++ {
|
||||
for i := 0; i < a.Width; i++ {
|
||||
idx := j*a.Width + i
|
||||
if a.Mask[idx/8]>>(idx%8)&1 == 0 {
|
||||
srcIdx := (a.Y+j)*c.dst.width + a.X + i
|
||||
copy(a.Pixels[4*idx:4*(idx+1)], orig[4*srcIdx:4*(srcIdx+1)])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
a.Mask = nil
|
||||
}
|
||||
|
||||
if len(c.args[lastArgIdx:]) > 0 {
|
||||
c.dst.image.ReplacePixels(c.args[lastArgIdx:])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -180,9 +180,10 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, buf []byte) e
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||
func (i *Image) ReplacePixels(pixels []byte, mask []byte, x, y, width, height int) {
|
||||
i.bufferedRP = append(i.bufferedRP, &graphicsdriver.ReplacePixelsArgs{
|
||||
Pixels: pixels,
|
||||
Mask: mask,
|
||||
X: x,
|
||||
Y: y,
|
||||
Width: width,
|
||||
|
@ -85,11 +85,60 @@ func TestReplacePixelsPartAfterDrawTriangles(t *testing.T) {
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*graphicscommand.Image{clr}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeClear, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*graphicscommand.Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeSourceOver, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
|
||||
dst.ReplacePixels(make([]byte, 4), 0, 0, 1, 1)
|
||||
dst.ReplacePixels(make([]byte, 4), nil, 0, 0, 1, 1)
|
||||
|
||||
// TODO: Check the result.
|
||||
}
|
||||
|
||||
func TestReplacePixelsWithMask(t *testing.T) {
|
||||
const w, h = 4, 3
|
||||
src := graphicscommand.NewImage(w, h)
|
||||
dst := graphicscommand.NewImage(w, h)
|
||||
|
||||
vs := quadVertices(w, h)
|
||||
is := graphics.QuadIndices()
|
||||
dr := graphicsdriver.Region{
|
||||
X: 0,
|
||||
Y: 0,
|
||||
Width: w,
|
||||
Height: h,
|
||||
}
|
||||
dst.DrawTriangles([graphics.ShaderImageNum]*graphicscommand.Image{src}, [graphics.ShaderImageNum - 1][2]float32{}, vs, is, affine.ColorMIdentity{}, graphicsdriver.CompositeModeClear, graphicsdriver.FilterNearest, graphicsdriver.AddressUnsafe, dr, graphicsdriver.Region{}, nil, nil, false)
|
||||
|
||||
pix0 := make([]byte, 4*w*h)
|
||||
for i := range pix0 {
|
||||
pix0[i] = 0x40
|
||||
}
|
||||
dst.ReplacePixels(pix0, nil, 0, 0, w, h)
|
||||
|
||||
pix1 := make([]byte, 4*w*h)
|
||||
for i := range pix1 {
|
||||
pix1[i] = 0x80
|
||||
}
|
||||
mask1 := []byte{0b11110110, 0b00000110}
|
||||
dst.ReplacePixels(pix1, mask1, 0, 0, w, h)
|
||||
|
||||
readPix := make([]byte, 4*w*h)
|
||||
if err := dst.ReadPixels(ui.GraphicsDriverForTesting(), readPix); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
idx := 4 * (i + w*j)
|
||||
got := color.RGBA{readPix[idx], readPix[idx+1], readPix[idx+2], readPix[idx+3]}
|
||||
var want color.RGBA
|
||||
if (i != 0 && i != w-1) || (j != 0 && j != h-1) {
|
||||
want = color.RGBA{0x80, 0x80, 0x80, 0x80}
|
||||
} else {
|
||||
want = color.RGBA{0x40, 0x40, 0x40, 0x40}
|
||||
}
|
||||
if got != want {
|
||||
t.Errorf("dst.At(%d, %d) after ReplacePixels: got %v, want: %v", i, j, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShader(t *testing.T) {
|
||||
const w, h = 16, 16
|
||||
clr := graphicscommand.NewImage(w, h)
|
||||
|
@ -83,6 +83,7 @@ type ImageID int
|
||||
|
||||
type ReplacePixelsArgs struct {
|
||||
Pixels []byte
|
||||
Mask []byte
|
||||
X int
|
||||
Y int
|
||||
Width int
|
||||
|
@ -304,12 +304,12 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
||||
theImages.makeStaleIfDependingOn(i)
|
||||
|
||||
if pixels != nil {
|
||||
i.image.ReplacePixels(pixels, x, y, width, height)
|
||||
i.image.ReplacePixels(pixels, nil, x, y, width, height)
|
||||
} else {
|
||||
// TODO: When pixels == nil, we don't have to care the pixel state there. In such cases, the image
|
||||
// accepts only ReplacePixels and not Fill or DrawTriangles.
|
||||
// TODO: Separate Image struct into two: images for only-ReplacePixels, and the others.
|
||||
i.image.ReplacePixels(make([]byte, 4*width*height), x, y, width, height)
|
||||
i.image.ReplacePixels(make([]byte, 4*width*height), nil, x, y, width, height)
|
||||
}
|
||||
|
||||
if !NeedsRestoring() || i.screen || i.volatile {
|
||||
|
@ -117,6 +117,6 @@ func (pr *pixelsRecords) at(i, j int) (byte, byte, byte, byte, bool) {
|
||||
func (pr *pixelsRecords) apply(img *graphicscommand.Image) {
|
||||
// TODO: Isn't this too heavy? Can we merge the operations?
|
||||
for _, r := range pr.records {
|
||||
img.ReplacePixels(r.pix, r.rect.Min.X, r.rect.Min.Y, r.rect.Dx(), r.rect.Dy())
|
||||
img.ReplacePixels(r.pix, nil, r.rect.Min.X, r.rect.Min.Y, r.rect.Dx(), r.rect.Dy())
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user