diff --git a/internal/graphics/command.go b/internal/graphics/command.go index 315bd9b86..0717e1b7f 100644 --- a/internal/graphics/command.go +++ b/internal/graphics/command.go @@ -27,6 +27,12 @@ import ( "github.com/hajimehoshi/ebiten/internal/sync" ) +// command represents a drawing command. +// +// A command for drawing that is created when Image functions are called like DrawImage, +// or Fill. +// A command is not immediately executed after created. Instaed, it is queued after created, +// and executed only when necessary. type command interface { Exec(indexOffsetInBytes int) error } diff --git a/internal/restorable/copy.go b/internal/restorable/copy.go index 2d6271be6..5da90a12b 100644 --- a/internal/restorable/copy.go +++ b/internal/restorable/copy.go @@ -23,6 +23,13 @@ import ( "github.com/hajimehoshi/ebiten/internal/math" ) +// CopyImage copies origImg to a new RGBA image. +// +// Basically CopyImage just calls draw.Draw. +// If origImg is a paletted image, an optimized copying method is used. +// +// CopyImage is used only from ebiten package but defined in restorable package, +// because this function needs to be tested but cannot be exposed to Ebiten users. func CopyImage(origImg image.Image) *image.RGBA { size := origImg.Bounds().Size() w, h := size.X, size.Y diff --git a/internal/restorable/doc.go b/internal/restorable/doc.go new file mode 100644 index 000000000..169e57403 --- /dev/null +++ b/internal/restorable/doc.go @@ -0,0 +1,67 @@ +// Copyright 2017 The Ebiten Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package restorable offers an Image struct that stores image commands +// and restores its pixel data from the commands when context lost happens. +// +// When a function like DrawImage or Fill is called, an Image tries to record +// the information for restoring. +// +// * Context lost +// +// Contest lost is a process that information on GPU memory are removed by OS +// to make more room on GPU memory. +// This can happen e.g. when GPU memory usage is high, or just switching applications +// might cause context lost on mobiles. +// As Ebiten's image data is on GPU memory, the game can't continue when context lost happens +// without restoring image information. +// The package restorable is the package to record information for such restoring. +// +// * DrawImage +// +// DrawImage function tries to record an item of 'draw image history' in the target image. +// If a target image is stale or volatile, no item is created. +// If an item of the history is created, +// it can be said that the target image depends on the source image. +// In other words, If A.DrawImage(B, ...) is called, +// it can be said that the image A depends on the image B. +// +// * Fill, ReplacePixels and Dispose +// +// These functions are also drawing functions and the target image stores the pixel data +// instead of draw image history items. There is no dependency here. +// +// * Making images stale +// +// After any of the drawing functions is called, the target image can't be depended on by +// any other images. For example, if an image A depends on an image B, and B is changed +// by a Fill call after that, the image A can't depend on the image B any more. +// In this case, as the image A is no longer relaiable, the image A becomes 'stale'. +// As all the stale images are resolved before context lost happens, +// draw image history items are kept as they are +// (even if an image C depends on the stale image A, it is still fine). +// +// * Stale image +// +// A stale image is an image that can't be restored from the recorded information. +// All stale images must be resolved by reading pixels from GPU before the frame ends. +// If a source image of DrawImage is a stale image, the target always becomes stale. +// +// * Volatile image +// +// A volatile image is a special image that is always cleared when a frame starts. +// For instance, the game screen passed via the update function is a volatile image. +// A volatile image doesn't have to record the drawing history. +// If a source image of DrawImage is a volatile image, the target always becomes stale. +package restorable diff --git a/internal/restorable/images.go b/internal/restorable/images.go index 27fa2066f..5e475abc4 100644 --- a/internal/restorable/images.go +++ b/internal/restorable/images.go @@ -22,16 +22,20 @@ import ( // restoringEnabled indicates if restoring happens or not. var restoringEnabled = true // This value is overridden at enabled_*.go. +// IsRestoringEnabled returns a boolean value indicating whether +// restoring process works or not. func IsRestoringEnabled() bool { // This value is updated only at init or EnableRestoringForTesting. // No need to lock here. return restoringEnabled } +// EnableRestoringForTesting forces to enable restoring for testing. func EnableRestoringForTesting() { restoringEnabled = true } +// images is a set of Image objects. type images struct { images map[*Image]struct{} lastChecked *Image @@ -42,6 +46,8 @@ var theImages = &images{ images: map[*Image]struct{}{}, } +// FlushAndResolveStalePixels flushes the queued draw commands and resolves +// all stale images. func FlushAndResolveStalePixels() error { if err := graphics.FlushCommands(); err != nil { return err