mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-10 04:57:26 +01:00
graphics: Improve Set speed
On GopherJS, copying a struct is very heavy. This change avoids copying (color) structs when possible.
This commit is contained in:
parent
6b110bf99e
commit
107dfe5074
13
image.go
13
image.go
@ -542,7 +542,8 @@ func (i *Image) At(x, y int) color.Color {
|
||||
return color.RGBA{}
|
||||
}
|
||||
i.resolvePixelsToSet(true)
|
||||
return i.mipmap.original().At(x, y)
|
||||
r, g, b, a := i.mipmap.original().At(x, y)
|
||||
return color.RGBA{r, g, b, a}
|
||||
}
|
||||
|
||||
// Set sets the color at (x, y).
|
||||
@ -570,11 +571,11 @@ func (img *Image) Set(x, y int, clr color.Color) {
|
||||
idx := 0
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
c := img.mipmap.original().At(i, j)
|
||||
pix[4*idx] = c.R
|
||||
pix[4*idx+1] = c.G
|
||||
pix[4*idx+2] = c.B
|
||||
pix[4*idx+3] = c.A
|
||||
r, g, b, a := img.mipmap.original().At(i, j)
|
||||
pix[4*idx] = r
|
||||
pix[4*idx+1] = g
|
||||
pix[4*idx+2] = b
|
||||
pix[4*idx+3] = a
|
||||
idx++
|
||||
}
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ package restorable
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
|
||||
"github.com/hajimehoshi/ebiten/internal/affine"
|
||||
"github.com/hajimehoshi/ebiten/internal/graphics"
|
||||
@ -278,22 +277,21 @@ func (i *Image) readPixelsFromGPUIfNeeded() {
|
||||
// At returns a color value at (x, y).
|
||||
//
|
||||
// Note that this must not be called until context is available.
|
||||
func (i *Image) At(x, y int) color.RGBA {
|
||||
func (i *Image) At(x, y int) (byte, byte, byte, byte) {
|
||||
w, h := i.image.Size()
|
||||
if x < 0 || y < 0 || w <= x || h <= y {
|
||||
return color.RGBA{}
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
i.readPixelsFromGPUIfNeeded()
|
||||
|
||||
// Even after readPixelsFromGPU, basePixels might be nil when OpenGL error happens.
|
||||
if i.basePixels == nil {
|
||||
return color.RGBA{}
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
idx := 4*x + 4*y*w
|
||||
r, g, b, a := i.basePixels[idx], i.basePixels[idx+1], i.basePixels[idx+2], i.basePixels[idx+3]
|
||||
return color.RGBA{r, g, b, a}
|
||||
return i.basePixels[idx], i.basePixels[idx+1], i.basePixels[idx+2], i.basePixels[idx+3]
|
||||
}
|
||||
|
||||
// makeStaleIfDependingOn makes the image stale if the image depends on target.
|
||||
|
@ -85,11 +85,11 @@ func Images() []image.Image {
|
||||
pix := make([]byte, 4*w*h)
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
c := img.At(i, j)
|
||||
pix[4*(i+j*w)] = byte(c.R)
|
||||
pix[4*(i+j*w)+1] = byte(c.G)
|
||||
pix[4*(i+j*w)+2] = byte(c.B)
|
||||
pix[4*(i+j*w)+3] = byte(c.A)
|
||||
r, g, b, a := img.At(i, j)
|
||||
pix[4*(i+j*w)] = r
|
||||
pix[4*(i+j*w)+1] = g
|
||||
pix[4*(i+j*w)+2] = b
|
||||
pix[4*(i+j*w)+3] = a
|
||||
}
|
||||
}
|
||||
imgs = append(imgs, &image.RGBA{
|
||||
|
@ -458,7 +458,8 @@ func TestReplacePixels(t *testing.T) {
|
||||
// Check the region (5, 7)-(9, 11). Outside state is indeterministic.
|
||||
for j := 7; j < 11; j++ {
|
||||
for i := 5; i < 9; i++ {
|
||||
got := img.At(i, j)
|
||||
r, g, b, a := img.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
want := color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
if got != want {
|
||||
t.Errorf("img.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
@ -471,7 +472,8 @@ func TestReplacePixels(t *testing.T) {
|
||||
}
|
||||
for j := 7; j < 11; j++ {
|
||||
for i := 5; i < 9; i++ {
|
||||
got := img.At(i, j)
|
||||
r, g, b, a := img.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
want := color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
if got != want {
|
||||
t.Errorf("img.At(%d, %d): got: %v, want: %v", i, j, got, want)
|
||||
@ -500,7 +502,8 @@ func TestDrawImageAndReplacePixels(t *testing.T) {
|
||||
if err := Restore(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := img1.At(0, 0)
|
||||
r, g, b, a := img1.At(0, 0)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
want := color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
if !sameColors(got, want, 1) {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
@ -533,7 +536,8 @@ func TestDispose(t *testing.T) {
|
||||
if err := Restore(); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := img0.At(0, 0)
|
||||
r, g, b, a := img0.At(0, 0)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
want := color.RGBA{0xff, 0xff, 0xff, 0xff}
|
||||
if !sameColors(got, want, 1) {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
|
@ -16,7 +16,6 @@ package shareable
|
||||
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"runtime"
|
||||
"sync"
|
||||
|
||||
@ -162,11 +161,11 @@ func (i *Image) forceShared() {
|
||||
pixels := make([]byte, 4*i.width*i.height)
|
||||
for y := 0; y < i.height; y++ {
|
||||
for x := 0; x < i.width; x++ {
|
||||
c := i.at(x, y)
|
||||
pixels[4*(x+i.width*y)] = c.R
|
||||
pixels[4*(x+i.width*y)+1] = c.G
|
||||
pixels[4*(x+i.width*y)+2] = c.B
|
||||
pixels[4*(x+i.width*y)+3] = c.A
|
||||
r, g, b, a := i.at(x, y)
|
||||
pixels[4*(x+i.width*y)] = r
|
||||
pixels[4*(x+i.width*y)+1] = g
|
||||
pixels[4*(x+i.width*y)+2] = b
|
||||
pixels[4*(x+i.width*y)+3] = a
|
||||
}
|
||||
}
|
||||
newI.replacePixels(pixels)
|
||||
@ -315,20 +314,20 @@ func (i *Image) replacePixels(p []byte) {
|
||||
i.backend.restorable.ReplacePixels(p, x, y, w, h)
|
||||
}
|
||||
|
||||
func (i *Image) At(x, y int) color.RGBA {
|
||||
func (i *Image) At(x, y int) (byte, byte, byte, byte) {
|
||||
backendsM.Lock()
|
||||
defer backendsM.Unlock()
|
||||
return i.at(x, y)
|
||||
}
|
||||
|
||||
func (i *Image) at(x, y int) color.RGBA {
|
||||
func (i *Image) at(x, y int) (byte, byte, byte, byte) {
|
||||
if i.backend == nil {
|
||||
return color.RGBA{}
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
ox, oy, w, h := i.region()
|
||||
if x < 0 || y < 0 || x >= w || y >= h {
|
||||
return color.RGBA{}
|
||||
return 0, 0, 0, 0
|
||||
}
|
||||
|
||||
return i.backend.restorable.At(x+ox, y+oy)
|
||||
|
@ -94,7 +94,8 @@ func TestEnsureNotShared(t *testing.T) {
|
||||
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
got := img4.At(i, j)
|
||||
r, g, b, a := img4.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
var want color.RGBA
|
||||
if i < dx0 || dx1 <= i || j < dy0 || dy1 <= j {
|
||||
c := byte(i + j)
|
||||
@ -168,7 +169,8 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
want := color.RGBA{byte(i + j), byte(i + j), byte(i + j), byte(i + j)}
|
||||
got := img1.At(i, j)
|
||||
r, g, b, a := img1.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -184,7 +186,8 @@ func Disabled_TestReshared(t *testing.T) {
|
||||
for j := 0; j < size; j++ {
|
||||
for i := 0; i < size; i++ {
|
||||
want := color.RGBA{byte(i + j), byte(i + j), byte(i + j), byte(i + j)}
|
||||
got := img1.At(i, j)
|
||||
r, g, b, a := img1.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
if got != want {
|
||||
t.Errorf("got: %v, want: %v", got, want)
|
||||
}
|
||||
@ -231,7 +234,8 @@ func TestExtend(t *testing.T) {
|
||||
|
||||
for j := 0; j < h0; j++ {
|
||||
for i := 0; i < w0; i++ {
|
||||
got := img0.At(i, j)
|
||||
r, g, b, a := img0.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
c := byte(i + w0*j)
|
||||
want := color.RGBA{c, c, c, c}
|
||||
if got != want {
|
||||
@ -242,7 +246,8 @@ func TestExtend(t *testing.T) {
|
||||
|
||||
for j := 0; j < h1; j++ {
|
||||
for i := 0; i < w1; i++ {
|
||||
got := img1.At(i, j)
|
||||
r, g, b, a := img1.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
c := byte(i + w1*j)
|
||||
want := color.RGBA{c, c, c, c}
|
||||
if got != want {
|
||||
@ -278,7 +283,8 @@ func TestReplacePixelsAfterDrawImage(t *testing.T) {
|
||||
|
||||
for j := 0; j < h; j++ {
|
||||
for i := 0; i < w; i++ {
|
||||
got := dst.At(i, j)
|
||||
r, g, b, a := dst.At(i, j)
|
||||
got := color.RGBA{r, g, b, a}
|
||||
c := byte(i + w*j)
|
||||
want := color.RGBA{c, c, c, c}
|
||||
if got != want {
|
||||
|
Loading…
Reference in New Issue
Block a user