mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-23 09:22:01 +01:00
all: unify terms for buffers and flushing
This commit is contained in:
parent
4d5b608d0c
commit
2855095ac9
4
image.go
4
image.go
@ -38,8 +38,8 @@ type Image struct {
|
|||||||
original *Image
|
original *Image
|
||||||
bounds image.Rectangle
|
bounds image.Rectangle
|
||||||
|
|
||||||
// Do not add a 'cache' member that are resolved lazily.
|
// Do not add a 'buffering' member that are resolved lazily.
|
||||||
// This tends to forget resolving the cache easily (#2362).
|
// This tends to forget resolving the buffer easily (#2362).
|
||||||
}
|
}
|
||||||
|
|
||||||
var emptyImage *Image
|
var emptyImage *Image
|
||||||
|
@ -95,7 +95,7 @@ func min(a, b int) int {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveDeferred() {
|
func flushDeferred() {
|
||||||
deferredM.Lock()
|
deferredM.Lock()
|
||||||
fs := deferred
|
fs := deferred
|
||||||
deferred = nil
|
deferred = nil
|
||||||
@ -568,8 +568,8 @@ func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte
|
|||||||
defer backendsM.Unlock()
|
defer backendsM.Unlock()
|
||||||
|
|
||||||
// In the tests, BeginFrame might not be called often and then images might not be disposed (#2292).
|
// In the tests, BeginFrame might not be called often and then images might not be disposed (#2292).
|
||||||
// To prevent memory leaks, resolve the deferred functions here.
|
// To prevent memory leaks, flush the deferred functions here.
|
||||||
resolveDeferred()
|
flushDeferred()
|
||||||
|
|
||||||
if i.backend == nil || i.backend.restorable == nil {
|
if i.backend == nil || i.backend.restorable == nil {
|
||||||
for i := range pixels {
|
for i := range pixels {
|
||||||
@ -776,7 +776,7 @@ func BeginFrame(graphicsDriver graphicsdriver.Graphics) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resolveDeferred()
|
flushDeferred()
|
||||||
if err := putImagesOnAtlas(graphicsDriver); err != nil {
|
if err := putImagesOnAtlas(graphicsDriver); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -303,5 +303,3 @@ func TestWritePixelsAndModifyBeforeMain(t *testing.T) {
|
|||||||
t.Errorf("got: %v, want: %v", got, want)
|
t.Errorf("got: %v, want: %v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Add tests for shaders and WritePixels to check resolvePendingPiexles works correctly.
|
|
||||||
|
@ -249,11 +249,11 @@ func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
|
|||||||
// FlushCommands flushes the command queue and present the screen if needed.
|
// FlushCommands flushes the command queue and present the screen if needed.
|
||||||
// If endFrame is true, the current screen might be used to present.
|
// If endFrame is true, the current screen might be used to present.
|
||||||
func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
|
func FlushCommands(graphicsDriver graphicsdriver.Graphics, endFrame bool) error {
|
||||||
// Resolve unresolved images only when the frame ends.
|
// Flush image buffers only when the frame ends.
|
||||||
// Resolving in tests might cause test flakiness on browsers (#2391).
|
// Flushing them in tests might cause test flakiness on browsers (#2391).
|
||||||
// TODO: Investigate why.
|
// TODO: Investigate why.
|
||||||
if endFrame {
|
if endFrame {
|
||||||
resolveImages()
|
flushImageBuffers()
|
||||||
}
|
}
|
||||||
|
|
||||||
return theCommandQueue.Flush(graphicsDriver, endFrame)
|
return theCommandQueue.Flush(graphicsDriver, endFrame)
|
||||||
|
@ -54,23 +54,22 @@ func genNextID() int {
|
|||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
|
||||||
// unresolvedImages is the set of unresolved images.
|
// imagesWithBuffers is the set of an image with buffers.
|
||||||
// An unresolved image is an image that might have an state unsent to the command queue yet.
|
var imagesWithBuffers []*Image
|
||||||
var unresolvedImages []*Image
|
|
||||||
|
|
||||||
// addUnresolvedImage adds an image to the list of unresolved images.
|
// addImageWithBuffer adds an image to the list of images with unflushed buffers.
|
||||||
func addUnresolvedImage(img *Image) {
|
func addImageWithBuffer(img *Image) {
|
||||||
unresolvedImages = append(unresolvedImages, img)
|
imagesWithBuffers = append(imagesWithBuffers, img)
|
||||||
}
|
}
|
||||||
|
|
||||||
// resolveImages resolves all the image states unsent to the command queue.
|
// flushImageBuffers flushes all the image buffers and send to the command queue.
|
||||||
// resolveImages should be called before flushing commands.
|
// flushImageBuffers should be called before flushing commands.
|
||||||
func resolveImages() {
|
func flushImageBuffers() {
|
||||||
for i, img := range unresolvedImages {
|
for i, img := range imagesWithBuffers {
|
||||||
img.resolveBufferedWritePixels()
|
img.flushBufferedWritePixels()
|
||||||
unresolvedImages[i] = nil
|
imagesWithBuffers[i] = nil
|
||||||
}
|
}
|
||||||
unresolvedImages = unresolvedImages[:0]
|
imagesWithBuffers = imagesWithBuffers[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewImage returns a new image.
|
// NewImage returns a new image.
|
||||||
@ -93,7 +92,7 @@ func NewImage(width, height int, screenFramebuffer bool) *Image {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) resolveBufferedWritePixels() {
|
func (i *Image) flushBufferedWritePixels() {
|
||||||
if len(i.bufferedWP) == 0 {
|
if len(i.bufferedWP) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -154,9 +153,9 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
|||||||
if src.screen {
|
if src.screen {
|
||||||
panic("graphicscommand: the screen image cannot be the rendering source")
|
panic("graphicscommand: the screen image cannot be the rendering source")
|
||||||
}
|
}
|
||||||
src.resolveBufferedWritePixels()
|
src.flushBufferedWritePixels()
|
||||||
}
|
}
|
||||||
i.resolveBufferedWritePixels()
|
i.flushBufferedWritePixels()
|
||||||
|
|
||||||
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
theCommandQueue.EnqueueDrawTrianglesCommand(i, srcs, offsets, vertices, indices, blend, dstRegion, srcRegion, shader, uniforms, evenOdd)
|
||||||
}
|
}
|
||||||
@ -164,7 +163,7 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, offsets [g
|
|||||||
// ReadPixels reads the image's pixels.
|
// ReadPixels reads the image's pixels.
|
||||||
// ReadPixels returns an error when an error happens in the graphics driver.
|
// ReadPixels returns an error when an error happens in the graphics driver.
|
||||||
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, buf []byte, x, y, width, height int) error {
|
func (i *Image) ReadPixels(graphicsDriver graphicsdriver.Graphics, buf []byte, x, y, width, height int) error {
|
||||||
i.resolveBufferedWritePixels()
|
i.flushBufferedWritePixels()
|
||||||
c := &readPixelsCommand{
|
c := &readPixelsCommand{
|
||||||
img: i,
|
img: i,
|
||||||
x: x,
|
x: x,
|
||||||
@ -188,7 +187,7 @@ func (i *Image) WritePixels(pixels []byte, x, y, width, height int) {
|
|||||||
Width: width,
|
Width: width,
|
||||||
Height: height,
|
Height: height,
|
||||||
})
|
})
|
||||||
addUnresolvedImage(i)
|
addImageWithBuffer(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, error) {
|
func (i *Image) IsInvalidated(graphicsDriver graphicsdriver.Graphics) (bool, error) {
|
||||||
|
@ -177,8 +177,8 @@ func (c *context) drawGame(graphicsDriver graphicsdriver.Graphics) error {
|
|||||||
c.game.DrawScreen()
|
c.game.DrawScreen()
|
||||||
|
|
||||||
// The final screen is never used as the rendering source.
|
// The final screen is never used as the rendering source.
|
||||||
// Flush its cache here just in case.
|
// Flush its buffer here just in case.
|
||||||
c.screen.flushCacheIfNeeded()
|
c.screen.flushBufferIfNeeded()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -35,7 +35,7 @@ type Image struct {
|
|||||||
height int
|
height int
|
||||||
volatile bool
|
volatile bool
|
||||||
|
|
||||||
dotsCache map[[2]int][4]byte
|
dotsBuffer map[[2]int][4]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewImage(width, height int, imageType atlas.ImageType) *Image {
|
func NewImage(width, height int, imageType atlas.ImageType) *Image {
|
||||||
@ -53,18 +53,18 @@ func (i *Image) MarkDisposed() {
|
|||||||
}
|
}
|
||||||
i.mipmap.MarkDisposed()
|
i.mipmap.MarkDisposed()
|
||||||
i.mipmap = nil
|
i.mipmap = nil
|
||||||
i.dotsCache = nil
|
i.dotsBuffer = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices []float32, indices []uint16, blend graphicsdriver.Blend, dstRegion, srcRegion graphicsdriver.Region, subimageOffsets [graphics.ShaderImageCount - 1][2]float32, shader *Shader, uniforms [][]float32, evenOdd bool, canSkipMipmap bool) {
|
||||||
i.flushCacheIfNeeded()
|
i.flushBufferIfNeeded()
|
||||||
|
|
||||||
var srcMipmaps [graphics.ShaderImageCount]*mipmap.Mipmap
|
var srcMipmaps [graphics.ShaderImageCount]*mipmap.Mipmap
|
||||||
for i, src := range srcs {
|
for i, src := range srcs {
|
||||||
if src == nil {
|
if src == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
src.flushCacheIfNeeded()
|
src.flushBufferIfNeeded()
|
||||||
srcMipmaps[i] = src.mipmap
|
srcMipmaps[i] = src.mipmap
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,22 +73,22 @@ func (i *Image) DrawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
|
|||||||
|
|
||||||
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
|
func (i *Image) WritePixels(pix []byte, x, y, width, height int) {
|
||||||
if width == 1 && height == 1 {
|
if width == 1 && height == 1 {
|
||||||
if i.dotsCache == nil {
|
if i.dotsBuffer == nil {
|
||||||
i.dotsCache = map[[2]int][4]byte{}
|
i.dotsBuffer = map[[2]int][4]byte{}
|
||||||
}
|
}
|
||||||
|
|
||||||
var clr [4]byte
|
var clr [4]byte
|
||||||
copy(clr[:], pix)
|
copy(clr[:], pix)
|
||||||
i.dotsCache[[2]int{x, y}] = clr
|
i.dotsBuffer[[2]int{x, y}] = clr
|
||||||
|
|
||||||
// One square requires 6 indices (= 2 triangles).
|
// One square requires 6 indices (= 2 triangles).
|
||||||
if len(i.dotsCache) >= graphics.IndicesCount/6 {
|
if len(i.dotsBuffer) >= graphics.IndicesCount/6 {
|
||||||
i.flushCacheIfNeeded()
|
i.flushBufferIfNeeded()
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
i.flushCacheIfNeeded()
|
i.flushBufferIfNeeded()
|
||||||
i.mipmap.WritePixels(pix, x, y, width, height)
|
i.mipmap.WritePixels(pix, x, y, width, height)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,14 +99,14 @@ func (i *Image) ReadPixels(pixels []byte, x, y, width, height int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if width == 1 && height == 1 {
|
if width == 1 && height == 1 {
|
||||||
if c, ok := i.dotsCache[[2]int{x, y}]; ok {
|
if c, ok := i.dotsBuffer[[2]int{x, y}]; ok {
|
||||||
copy(pixels, c[:])
|
copy(pixels, c[:])
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// Do not call flushCacheIfNeeded here. This would slow (image/draw).Draw.
|
// Do not call flushBufferIfNeeded here. This would slow (image/draw).Draw.
|
||||||
// See ebiten.TestImageDrawOver.
|
// See ebiten.TestImageDrawOver.
|
||||||
} else {
|
} else {
|
||||||
i.flushCacheIfNeeded()
|
i.flushBufferIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := theUI.readPixels(i.mipmap, pixels, x, y, width, height); err != nil {
|
if err := theUI.readPixels(i.mipmap, pixels, x, y, width, height); err != nil {
|
||||||
@ -121,17 +121,17 @@ func (i *Image) DumpScreenshot(name string, blackbg bool) (string, error) {
|
|||||||
return theUI.dumpScreenshot(i.mipmap, name, blackbg)
|
return theUI.dumpScreenshot(i.mipmap, name, blackbg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Image) flushCacheIfNeeded() {
|
func (i *Image) flushBufferIfNeeded() {
|
||||||
if len(i.dotsCache) == 0 {
|
if len(i.dotsBuffer) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
l := len(i.dotsCache)
|
l := len(i.dotsBuffer)
|
||||||
vs := graphics.Vertices(l * 4)
|
vs := graphics.Vertices(l * 4)
|
||||||
is := make([]uint16, l*6)
|
is := make([]uint16, l*6)
|
||||||
sx, sy := float32(1), float32(1)
|
sx, sy := float32(1), float32(1)
|
||||||
var idx int
|
var idx int
|
||||||
for p, c := range i.dotsCache {
|
for p, c := range i.dotsBuffer {
|
||||||
dx := float32(p[0])
|
dx := float32(p[0])
|
||||||
dy := float32(p[1])
|
dy := float32(p[1])
|
||||||
crf := float32(c[0]) / 0xff
|
crf := float32(c[0]) / 0xff
|
||||||
@ -181,7 +181,7 @@ func (i *Image) flushCacheIfNeeded() {
|
|||||||
|
|
||||||
idx++
|
idx++
|
||||||
}
|
}
|
||||||
i.dotsCache = nil
|
i.dotsBuffer = nil
|
||||||
|
|
||||||
srcs := [graphics.ShaderImageCount]*mipmap.Mipmap{emptyImage.mipmap}
|
srcs := [graphics.ShaderImageCount]*mipmap.Mipmap{emptyImage.mipmap}
|
||||||
dr := graphicsdriver.Region{
|
dr := graphicsdriver.Region{
|
||||||
|
Loading…
Reference in New Issue
Block a user