diff --git a/graphicscontext.go b/graphicscontext.go index e14d2fc1b..683015ace 100644 --- a/graphicscontext.go +++ b/graphicscontext.go @@ -151,7 +151,7 @@ func (c *graphicsContext) UpdateAndDraw(context *opengl.Context, updateCount int return err } if 0 < updateCount { - if err := theImages.savePixels(context); err != nil { + if err := theImagesForRestoring.savePixels(context); err != nil { return err } } @@ -162,7 +162,7 @@ func (c *graphicsContext) restore(context *opengl.Context) error { if err := graphics.Reset(context); err != nil { return err } - if err := theImages.restorePixels(context); err != nil { + if err := theImagesForRestoring.restorePixels(context); err != nil { return err } return nil diff --git a/image.go b/image.go index e4b5ef50d..0d1ce1fa9 100644 --- a/image.go +++ b/image.go @@ -17,7 +17,6 @@ package ebiten import ( "image" "image/color" - "image/draw" "runtime" "sync" @@ -30,7 +29,7 @@ type images struct { m sync.Mutex } -var theImages = images{ +var theImagesForRestoring = images{ images: map[*imageImpl]struct{}{}, } @@ -39,7 +38,7 @@ func (i *images) add(img *imageImpl) (*Image, error) { defer i.m.Unlock() i.images[img] = struct{}{} eimg := &Image{img} - runtime.SetFinalizer(eimg, theImages.remove) + runtime.SetFinalizer(eimg, theImagesForRestoring.remove) return eimg, nil } @@ -206,7 +205,7 @@ func NewImage(width, height int, filter Filter) (*Image, error) { if err := img.Fill(color.Transparent); err != nil { return nil, err } - eimg, err := theImages.add(img) + eimg, err := theImagesForRestoring.add(img) if err != nil { return nil, err } @@ -219,29 +218,11 @@ func NewImage(width, height int, filter Filter) (*Image, error) { // // This function is concurrent-safe. func NewImageFromImage(source image.Image, filter Filter) (*Image, error) { - size := source.Bounds().Size() - w, h := size.X, size.Y - // TODO: Return error when the image is too big! - // Don't lock while manipulating an image.Image interface. - rgbaImg, ok := source.(*image.RGBA) - if !ok || source.Bounds().Min != image.ZP { - origImg := source - newImg := image.NewRGBA(image.Rect(0, 0, w, h)) - draw.Draw(newImg, newImg.Bounds(), origImg, origImg.Bounds().Min, draw.Src) - rgbaImg = newImg - } - pixels := make([]uint8, 4*w*h) - for j := 0; j < h; j++ { - copy(pixels[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:]) - } - i, err := graphics.NewImageFromImage(rgbaImg, glFilter(filter)) + img, err := newImageImplFromImage(source, filter) if err != nil { - // TODO: texture should be removed here? return nil, err } - img, err := newImageImpl(i, filter) - img.pixels = pixels - eimg, err := theImages.add(img) + eimg, err := theImagesForRestoring.add(img) if err != nil { return nil, err } diff --git a/imageimpl.go b/imageimpl.go index d25ce5a8b..698a8f9b2 100644 --- a/imageimpl.go +++ b/imageimpl.go @@ -19,6 +19,7 @@ import ( "fmt" "image" "image/color" + "image/draw" "runtime" "sync" @@ -51,6 +52,38 @@ func newImageImpl(image *graphics.Image, filter Filter) (*imageImpl, error) { return i, nil } +func newImageImplFromImage(source image.Image, filter Filter) (*imageImpl, error) { + size := source.Bounds().Size() + w, h := size.X, size.Y + // TODO: Return error when the image is too big! + // Don't lock while manipulating an image.Image interface. + rgbaImg, ok := source.(*image.RGBA) + if !ok || source.Bounds().Min != image.ZP { + origImg := source + newImg := image.NewRGBA(image.Rect(0, 0, w, h)) + draw.Draw(newImg, newImg.Bounds(), origImg, origImg.Bounds().Min, draw.Src) + rgbaImg = newImg + } + pixels := make([]uint8, 4*w*h) + for j := 0; j < h; j++ { + copy(pixels[j*w*4:(j+1)*w*4], rgbaImg.Pix[j*rgbaImg.Stride:]) + } + img, err := graphics.NewImageFromImage(rgbaImg, glFilter(filter)) + if err != nil { + // TODO: texture should be removed here? + return nil, err + } + i := &imageImpl{ + image: img, + width: w, + height: h, + filter: filter, + pixels: pixels, + } + runtime.SetFinalizer(i, (*imageImpl).Dispose) + return i, nil +} + func (i *imageImpl) Fill(clr color.Color) error { i.m.Lock() defer i.m.Unlock()