mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-13 22:47:26 +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.
|
// Exec executes the replacePixelsCommand.
|
||||||
func (c *replacePixelsCommand) Exec(graphicsDriver graphicsdriver.Graphics, indexOffset int) error {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -180,9 +180,10 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, buf []byte) e
|
|||||||
return nil
|
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{
|
i.bufferedRP = append(i.bufferedRP, &graphicsdriver.ReplacePixelsArgs{
|
||||||
Pixels: pixels,
|
Pixels: pixels,
|
||||||
|
Mask: mask,
|
||||||
X: x,
|
X: x,
|
||||||
Y: y,
|
Y: y,
|
||||||
Width: width,
|
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{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.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.
|
// 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) {
|
func TestShader(t *testing.T) {
|
||||||
const w, h = 16, 16
|
const w, h = 16, 16
|
||||||
clr := graphicscommand.NewImage(w, h)
|
clr := graphicscommand.NewImage(w, h)
|
||||||
|
@ -83,6 +83,7 @@ type ImageID int
|
|||||||
|
|
||||||
type ReplacePixelsArgs struct {
|
type ReplacePixelsArgs struct {
|
||||||
Pixels []byte
|
Pixels []byte
|
||||||
|
Mask []byte
|
||||||
X int
|
X int
|
||||||
Y int
|
Y int
|
||||||
Width int
|
Width int
|
||||||
|
@ -304,12 +304,12 @@ func (i *Image) ReplacePixels(pixels []byte, x, y, width, height int) {
|
|||||||
theImages.makeStaleIfDependingOn(i)
|
theImages.makeStaleIfDependingOn(i)
|
||||||
|
|
||||||
if pixels != nil {
|
if pixels != nil {
|
||||||
i.image.ReplacePixels(pixels, x, y, width, height)
|
i.image.ReplacePixels(pixels, nil, x, y, width, height)
|
||||||
} else {
|
} else {
|
||||||
// TODO: When pixels == nil, we don't have to care the pixel state there. In such cases, the image
|
// 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.
|
// accepts only ReplacePixels and not Fill or DrawTriangles.
|
||||||
// TODO: Separate Image struct into two: images for only-ReplacePixels, and the others.
|
// 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 {
|
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) {
|
func (pr *pixelsRecords) apply(img *graphicscommand.Image) {
|
||||||
// TODO: Isn't this too heavy? Can we merge the operations?
|
// TODO: Isn't this too heavy? Can we merge the operations?
|
||||||
for _, r := range pr.records {
|
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