graphics: Refactoring: Reduce imageImpl's functions

This commit is contained in:
Hajime Hoshi 2017-05-03 01:54:25 +09:00
parent 76ad9cf42b
commit 16b0c9186e
2 changed files with 19 additions and 77 deletions

View File

@ -23,6 +23,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/graphics" "github.com/hajimehoshi/ebiten/internal/graphics"
"github.com/hajimehoshi/ebiten/internal/opengl" "github.com/hajimehoshi/ebiten/internal/opengl"
"github.com/hajimehoshi/ebiten/internal/restorable"
) )
func glContext() *opengl.Context { func glContext() *opengl.Context {
@ -38,19 +39,19 @@ func glContext() *opengl.Context {
} }
type images struct { type images struct {
images map[*imageImpl]struct{} images map[*restorable.Image]struct{}
m sync.Mutex m sync.Mutex
lastChecked *imageImpl lastChecked *imageImpl
} }
var theImagesForRestoring = images{ var theImagesForRestoring = images{
images: map[*imageImpl]struct{}{}, images: map[*restorable.Image]struct{}{},
} }
func (i *images) add(img *imageImpl) *Image { func (i *images) add(img *imageImpl) *Image {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
i.images[img] = struct{}{} i.images[img.restorable] = struct{}{}
eimg := &Image{img} eimg := &Image{img}
runtime.SetFinalizer(eimg, theImagesForRestoring.remove) runtime.SetFinalizer(eimg, theImagesForRestoring.remove)
return eimg return eimg
@ -62,7 +63,7 @@ func (i *images) remove(img *Image) {
} }
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
delete(i.images, img.impl) delete(i.images, img.impl.restorable)
runtime.SetFinalizer(img, nil) runtime.SetFinalizer(img, nil)
} }
@ -71,14 +72,14 @@ func (i *images) resolveStalePixels(context *opengl.Context) error {
defer i.m.Unlock() defer i.m.Unlock()
i.lastChecked = nil i.lastChecked = nil
for img := range i.images { for img := range i.images {
if err := img.resolveStalePixels(context); err != nil { if err := img.ReadPixelsFromVRAMIfStale(context); err != nil {
return err return err
} }
} }
return nil return nil
} }
func (i *images) resetPixelsIfDependingOn(target *Image, context *opengl.Context) { func (i *images) resetPixelsIfDependingOn(target *Image) {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
if i.lastChecked == target.impl { if i.lastChecked == target.impl {
@ -89,7 +90,7 @@ func (i *images) resetPixelsIfDependingOn(target *Image, context *opengl.Context
return return
} }
for img := range i.images { for img := range i.images {
img.resetPixelsIfDependingOn(target.impl, context) img.MakeStaleIfDependingOn(target.impl.restorable)
} }
} }
@ -98,10 +99,10 @@ func (i *images) restore(context *opengl.Context) error {
defer i.m.Unlock() defer i.m.Unlock()
// Framebuffers/textures cannot be disposed since framebuffers/textures that // Framebuffers/textures cannot be disposed since framebuffers/textures that
// don't belong to the current context. // don't belong to the current context.
imagesWithoutDependency := []*imageImpl{} imagesWithoutDependency := []*restorable.Image{}
imagesWithDependency := []*imageImpl{} imagesWithDependency := []*restorable.Image{}
for img := range i.images { for img := range i.images {
if img.hasDependency() { if img.HasDependency() {
imagesWithDependency = append(imagesWithDependency, img) imagesWithDependency = append(imagesWithDependency, img)
} else { } else {
imagesWithoutDependency = append(imagesWithoutDependency, img) imagesWithoutDependency = append(imagesWithoutDependency, img)
@ -109,12 +110,12 @@ func (i *images) restore(context *opengl.Context) error {
} }
// Images depending on other images should be processed first. // Images depending on other images should be processed first.
for _, img := range imagesWithoutDependency { for _, img := range imagesWithoutDependency {
if err := img.restore(context); err != nil { if err := img.Restore(context); err != nil {
return err return err
} }
} }
for _, img := range imagesWithDependency { for _, img := range imagesWithDependency {
if err := img.restore(context); err != nil { if err := img.Restore(context); err != nil {
return err return err
} }
} }
@ -125,7 +126,7 @@ func (i *images) clearVolatileImages() {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()
for img := range i.images { for img := range i.images {
img.clearIfVolatile() img.ClearIfVolatile()
} }
} }
@ -149,7 +150,7 @@ func (i *Image) Size() (width, height int) {
// //
// Clear always returns nil as of 1.5.0-alpha. // Clear always returns nil as of 1.5.0-alpha.
func (i *Image) Clear() error { func (i *Image) Clear() error {
theImagesForRestoring.resetPixelsIfDependingOn(i, glContext()) theImagesForRestoring.resetPixelsIfDependingOn(i)
i.impl.Fill(color.Transparent) i.impl.Fill(color.Transparent)
return nil return nil
} }
@ -160,7 +161,7 @@ func (i *Image) Clear() error {
// //
// Fill always returns nil as of 1.5.0-alpha. // Fill always returns nil as of 1.5.0-alpha.
func (i *Image) Fill(clr color.Color) error { func (i *Image) Fill(clr color.Color) error {
theImagesForRestoring.resetPixelsIfDependingOn(i, glContext()) theImagesForRestoring.resetPixelsIfDependingOn(i)
i.impl.Fill(clr) i.impl.Fill(clr)
return nil return nil
} }
@ -188,7 +189,7 @@ func (i *Image) Fill(clr color.Color) error {
// //
// DrawImage always returns nil as of 1.5.0-alpha. // DrawImage always returns nil as of 1.5.0-alpha.
func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error { func (i *Image) DrawImage(image *Image, options *DrawImageOptions) error {
theImagesForRestoring.resetPixelsIfDependingOn(i, glContext()) theImagesForRestoring.resetPixelsIfDependingOn(i)
i.impl.DrawImage(image, options) i.impl.DrawImage(image, options)
return nil return nil
} }
@ -225,7 +226,7 @@ func (i *Image) Dispose() error {
if i.impl.isDisposed() { if i.impl.isDisposed() {
return nil return nil
} }
theImagesForRestoring.resetPixelsIfDependingOn(i, glContext()) theImagesForRestoring.resetPixelsIfDependingOn(i)
i.impl.Dispose() i.impl.Dispose()
return nil return nil
} }
@ -242,7 +243,7 @@ func (i *Image) Dispose() error {
// //
// ReplacePixels always returns nil as of 1.5.0-alpha. // ReplacePixels always returns nil as of 1.5.0-alpha.
func (i *Image) ReplacePixels(p []uint8) error { func (i *Image) ReplacePixels(p []uint8) error {
theImagesForRestoring.resetPixelsIfDependingOn(i, glContext()) theImagesForRestoring.resetPixelsIfDependingOn(i)
i.impl.ReplacePixels(p) i.impl.ReplacePixels(p)
return nil return nil
} }

View File

@ -74,15 +74,6 @@ func (i *imageImpl) Fill(clr color.Color) {
i.restorable.Fill(rgba) i.restorable.Fill(rgba)
} }
func (i *imageImpl) clearIfVolatile() {
i.m.Lock()
defer i.m.Unlock()
if i.restorable == nil {
return
}
i.restorable.ClearIfVolatile()
}
func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) { func (i *imageImpl) DrawImage(image *Image, options *DrawImageOptions) {
// Calculate vertices before locking because the user can do anything in // Calculate vertices before locking because the user can do anything in
// options.ImageParts interface without deadlock (e.g. Call Image functions). // options.ImageParts interface without deadlock (e.g. Call Image functions).
@ -134,56 +125,6 @@ func (i *imageImpl) At(x, y int, context *opengl.Context) color.Color {
return clr return clr
} }
func (i *imageImpl) resolveStalePixels(context *opengl.Context) error {
i.m.Lock()
defer i.m.Unlock()
if i.restorable == nil {
return nil
}
if err := i.restorable.ReadPixelsFromVRAMIfStale(context); err != nil {
return err
}
return nil
}
func (i *imageImpl) resetPixelsIfDependingOn(target *imageImpl, context *opengl.Context) {
i.m.Lock()
defer i.m.Unlock()
if i == target {
return
}
if i.restorable == nil {
return
}
if target.isDisposed() {
panic("ebiten: target must not be disposed")
}
// target is an image that is about to be tried mutating.
// If pixels object is related to that image, the pixels must be reset.
i.restorable.MakeStaleIfDependingOn(target.restorable)
}
func (i *imageImpl) hasDependency() bool {
i.m.Lock()
defer i.m.Unlock()
if i.restorable == nil {
return false
}
return i.restorable.HasDependency()
}
func (i *imageImpl) restore(context *opengl.Context) error {
i.m.Lock()
defer i.m.Unlock()
if i.restorable == nil {
return nil
}
if err := i.restorable.Restore(context); err != nil {
return err
}
return nil
}
func (i *imageImpl) Dispose() { func (i *imageImpl) Dispose() {
i.m.Lock() i.m.Lock()
defer i.m.Unlock() defer i.m.Unlock()