diff --git a/imageimpl.go b/imageimpl.go index 9bea77ba1..f08488c58 100644 --- a/imageimpl.go +++ b/imageimpl.go @@ -25,6 +25,7 @@ import ( "github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics/opengl" + "github.com/hajimehoshi/ebiten/internal/pixels" ) type imageImpl struct { @@ -33,7 +34,7 @@ type imageImpl struct { width int height int filter Filter - pixels *pixels + pixels *pixels.Pixels volatile bool screen bool m sync.Mutex @@ -50,11 +51,9 @@ func newImageImpl(width, height int, filter Filter, volatile bool) (*imageImpl, height: height, filter: filter, volatile: volatile, - pixels: &pixels{ - image: img, - }, + pixels: pixels.NewPixels(img), } - i.pixels.resetWithPixels(make([]uint8, width*height*4)) + i.pixels.ResetWithPixels(make([]uint8, width*height*4)) runtime.SetFinalizer(i, (*imageImpl).Dispose) return i, nil } @@ -85,11 +84,9 @@ func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error width: w, height: h, filter: filter, - pixels: &pixels{ - image: img, - }, + pixels: pixels.NewPixels(img), } - i.pixels.resetWithPixels(p) + i.pixels.ResetWithPixels(p) runtime.SetFinalizer(i, (*imageImpl).Dispose) return i, nil } @@ -105,11 +102,9 @@ func newScreenImageImpl(width, height int) (*imageImpl, error) { height: height, volatile: true, screen: true, - pixels: &pixels{ - image: img, - }, + pixels: pixels.NewPixels(img), } - i.pixels.resetWithPixels(make([]uint8, width*height*4)) + i.pixels.ResetWithPixels(make([]uint8, width*height*4)) runtime.SetFinalizer(i, (*imageImpl).Dispose) return i, nil } @@ -120,10 +115,10 @@ func (i *imageImpl) Fill(clr color.Color) error { if i.disposed { return errors.New("ebiten: image is already disposed") } - if clr == color.Transparent && i.pixels.isCleared() { + if clr == color.Transparent && i.pixels.IsCleared() { return nil } - i.pixels.fill(clr) + i.pixels.Fill(clr) return i.image.Fill(clr) } @@ -136,10 +131,10 @@ func (i *imageImpl) clearIfVolatile() error { if !i.volatile { return nil } - if i.pixels.isCleared() { + if i.pixels.IsCleared() { return nil } - i.pixels.clear() + i.pixels.Clear() return i.image.Fill(color.Transparent) } @@ -176,17 +171,10 @@ func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) error { } geom := options.GeoM colorm := options.ColorM - c := &drawImageHistoryItem{ - image: image.impl.image, - vertices: vertices, - geom: &geom, - colorm: &colorm, - mode: opengl.CompositeMode(options.CompositeMode), + if image.impl.pixels.IsInconsistent() { + i.pixels.MakeInconsistent() } - if image.impl.pixels.inconsistent { - i.pixels.makeInconsistent() - } - i.pixels.appendDrawImageHistory(c) + i.pixels.AppendDrawImageHistory(image.impl.image, vertices, &geom, &colorm, opengl.CompositeMode(options.CompositeMode)) mode := opengl.CompositeMode(options.CompositeMode) if err := i.image.DrawImage(image.impl.image, vertices, &geom, &colorm, mode); err != nil { return err @@ -204,7 +192,7 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color { return color.Transparent } idx := 4*x + 4*y*i.width - clr, err := i.pixels.at(idx, context) + clr, err := i.pixels.At(idx, context) if err != nil { panic(err) } @@ -217,7 +205,7 @@ func (i *imageImpl) flushPixelsIfInconsistent(context *opengl.Context) error { if i.disposed { return nil } - if err := i.pixels.flushIfInconsistent(context); err != nil { + if err := i.pixels.FlushIfInconsistent(context); err != nil { return err } return nil @@ -235,7 +223,7 @@ func (i *imageImpl) flushPixelsIfNeeded(target *imageImpl, context *opengl.Conte if target.isDisposed() { return errors.New("ebiten: target is already disposed") } - if err := i.pixels.flushIfNeeded(target.image, context); err != nil { + if err := i.pixels.FlushIfNeeded(target.image, context); err != nil { return err } return nil @@ -244,7 +232,7 @@ func (i *imageImpl) flushPixelsIfNeeded(target *imageImpl, context *opengl.Conte func (i *imageImpl) hasHistory() bool { i.m.Lock() defer i.m.Unlock() - return i.pixels.hasHistory() + return i.pixels.HasHistory() } func (i *imageImpl) restore(context *opengl.Context) error { @@ -272,7 +260,7 @@ func (i *imageImpl) restore(context *opengl.Context) error { return nil } var err error - i.image, err = i.pixels.restore(context, i.width, i.height, i.filter) + i.image, err = i.pixels.Restore(context, i.width, i.height, glFilter(i.filter)) if err != nil { return err } @@ -303,7 +291,7 @@ func (i *imageImpl) ReplacePixels(p []uint8) error { } i.m.Lock() defer i.m.Unlock() - i.pixels.resetWithPixels(p) + i.pixels.ResetWithPixels(p) if i.disposed { return errors.New("ebiten: image is already disposed") } diff --git a/pixels.go b/internal/pixels/pixels.go similarity index 77% rename from pixels.go rename to internal/pixels/pixels.go index 12174b83e..1be0b3f97 100644 --- a/pixels.go +++ b/internal/pixels/pixels.go @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package ebiten +package pixels import ( "image" @@ -32,7 +32,7 @@ type drawImageHistoryItem struct { // basePixels and baseColor are exclusive. -type pixels struct { +type Pixels struct { image *graphics.Image inconsistent bool basePixels []uint8 @@ -40,7 +40,13 @@ type pixels struct { drawImageHistory []*drawImageHistoryItem } -func (p *pixels) resetWithPixels(pixels []uint8) { +func NewPixels(image *graphics.Image) *Pixels { + return &Pixels{ + image: image, + } +} + +func (p *Pixels) ResetWithPixels(pixels []uint8) { if p.basePixels == nil { p.basePixels = make([]uint8, len(pixels)) } @@ -50,42 +56,53 @@ func (p *pixels) resetWithPixels(pixels []uint8) { p.drawImageHistory = nil } -func (p *pixels) clear() { +func (p *Pixels) Clear() { p.inconsistent = false p.basePixels = nil p.baseColor = nil p.drawImageHistory = nil } -func (p *pixels) isCleared() bool { +func (p *Pixels) IsCleared() bool { if p.inconsistent { return false } return p.basePixels == nil && p.baseColor == nil && p.drawImageHistory == nil } -func (p *pixels) fill(clr color.Color) { +func (p *Pixels) Fill(clr color.Color) { p.inconsistent = false p.basePixels = nil p.baseColor = clr p.drawImageHistory = nil } -func (p *pixels) makeInconsistent() { +func (p *Pixels) IsInconsistent() bool { + return p.inconsistent +} + +func (p *Pixels) MakeInconsistent() { p.inconsistent = true p.basePixels = nil p.baseColor = nil p.drawImageHistory = nil } -func (p *pixels) appendDrawImageHistory(item *drawImageHistoryItem) { +func (p *Pixels) AppendDrawImageHistory(image *graphics.Image, vertices []int16, geom graphics.Matrix, colorm graphics.Matrix, mode opengl.CompositeMode) { if p.inconsistent { return } + item := &drawImageHistoryItem{ + image: image, + vertices: vertices, + geom: geom, + colorm: colorm, + mode: mode, + } p.drawImageHistory = append(p.drawImageHistory, item) } -func (p *pixels) at(idx int, context *opengl.Context) (color.Color, error) { +func (p *Pixels) At(idx int, context *opengl.Context) (color.Color, error) { if p.inconsistent || p.basePixels == nil || p.drawImageHistory != nil { p.inconsistent = false var err error @@ -100,7 +117,7 @@ func (p *pixels) at(idx int, context *opengl.Context) (color.Color, error) { return color.RGBA{r, g, b, a}, nil } -func (p *pixels) hasHistoryWith(target *graphics.Image) bool { +func (p *Pixels) hasHistoryWith(target *graphics.Image) bool { for _, c := range p.drawImageHistory { if c.image == target { return true @@ -109,7 +126,7 @@ func (p *pixels) hasHistoryWith(target *graphics.Image) bool { return false } -func (p *pixels) flushIfInconsistent(context *opengl.Context) error { +func (p *Pixels) FlushIfInconsistent(context *opengl.Context) error { if !p.inconsistent { return nil } @@ -124,7 +141,7 @@ func (p *pixels) flushIfInconsistent(context *opengl.Context) error { return nil } -func (p *pixels) flushIfNeeded(target *graphics.Image, context *opengl.Context) error { +func (p *Pixels) FlushIfNeeded(target *graphics.Image, context *opengl.Context) error { if p.drawImageHistory == nil { return nil } @@ -133,7 +150,7 @@ func (p *pixels) flushIfNeeded(target *graphics.Image, context *opengl.Context) } if context == nil { // context is null when this is not initialized yet. - p.makeInconsistent() + p.MakeInconsistent() return nil } p.inconsistent = false @@ -147,21 +164,21 @@ func (p *pixels) flushIfNeeded(target *graphics.Image, context *opengl.Context) return nil } -func (p *pixels) hasHistory() bool { +func (p *Pixels) HasHistory() bool { return p.drawImageHistory != nil } // restore restores the pixels using its history. // // restore is the only function that the pixel data is not present on GPU when this is called. -func (p *pixels) restore(context *opengl.Context, width, height int, filter Filter) (*graphics.Image, error) { +func (p *Pixels) Restore(context *opengl.Context, width, height int, filter opengl.Filter) (*graphics.Image, error) { img := image.NewRGBA(image.Rect(0, 0, width, height)) if p.basePixels != nil { for j := 0; j < height; j++ { copy(img.Pix[j*img.Stride:], p.basePixels[j*width*4:(j+1)*width*4]) } } - gimg, err := graphics.NewImageFromImage(img, glFilter(filter)) + gimg, err := graphics.NewImageFromImage(img, filter) if err != nil { return nil, err }