internal/restorable: remove Image

Updates #805
This commit is contained in:
Hajime Hoshi 2024-01-13 19:29:43 +09:00
parent 59896e4447
commit 812cd494de
2 changed files with 41 additions and 71 deletions

View File

@ -88,8 +88,8 @@ func putImagesOnSourceBackend(graphicsDriver graphicsdriver.Graphics) {
} }
type backend struct { type backend struct {
// restorable is an atlas on which there might be multiple images. // image is an atlas on which there might be multiple images.
restorable *restorable.Image image *graphicscommand.Image
width int width int
height int height int
@ -136,16 +136,15 @@ func (b *backend) extendIfNeeded(width, height int) {
// Use DrawTriangles instead of WritePixels because the image i might be stale and not have its pixels // Use DrawTriangles instead of WritePixels because the image i might be stale and not have its pixels
// information. // information.
srcs := [graphics.ShaderImageCount]*graphicscommand.Image{b.restorable.Image} srcs := [graphics.ShaderImageCount]*graphicscommand.Image{b.image}
sw, sh := b.restorable.Image.InternalSize() sw, sh := b.image.InternalSize()
vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1) vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1)
is := graphics.QuadIndices() is := graphics.QuadIndices()
dr := image.Rect(0, 0, sw, sh) dr := image.Rect(0, 0, sw, sh)
newImg.Image.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader.ensureShader().Shader, nil, graphicsdriver.FillAll) newImg.DrawTriangles(srcs, vs, is, graphicsdriver.BlendCopy, dr, [graphics.ShaderImageCount]image.Rectangle{}, NearestFilterShader.ensureShader().Shader, nil, graphicsdriver.FillAll)
b.restorable.Image.Dispose() b.image.Dispose()
b.restorable.Image = nil
b.restorable = newImg b.image = newImg
b.width = width b.width = width
b.height = height b.height = height
} }
@ -153,15 +152,13 @@ func (b *backend) extendIfNeeded(width, height int) {
// newClearedImage creates an emtpy image with the given size. // newClearedImage creates an emtpy image with the given size.
// //
// Note that Dispose is not called automatically. // Note that Dispose is not called automatically.
func newClearedImage(width, height int, screen bool) *restorable.Image { func newClearedImage(width, height int, screen bool) *graphicscommand.Image {
i := &restorable.Image{ i := graphicscommand.NewImage(width, height, screen)
Image: graphicscommand.NewImage(width, height, screen),
}
// This needs to use 'InternalSize' to render the whole region, or edges are unexpectedly cleared on some // This needs to use 'InternalSize' to render the whole region, or edges are unexpectedly cleared on some
// devices. // devices.
iw, ih := i.Image.InternalSize() iw, ih := i.InternalSize()
clearImage(i.Image, image.Rect(0, 0, iw, ih)) clearImage(i, image.Rect(0, 0, iw, ih))
return i return i
} }
@ -175,7 +172,7 @@ func (b *backend) clearPixels(region image.Rectangle) {
if region.Dx() <= 0 || region.Dy() <= 0 { if region.Dx() <= 0 || region.Dy() <= 0 {
panic("atlas: width/height must be positive") panic("atlas: width/height must be positive")
} }
clearImage(b.restorable.Image, region.Intersect(image.Rect(0, 0, b.width, b.height))) clearImage(b.image, region.Intersect(image.Rect(0, 0, b.width, b.height)))
} }
func (b *backend) writePixels(pixels *graphics.ManagedBytes, region image.Rectangle) { func (b *backend) writePixels(pixels *graphics.ManagedBytes, region image.Rectangle) {
@ -185,7 +182,7 @@ func (b *backend) writePixels(pixels *graphics.ManagedBytes, region image.Rectan
if !region.In(image.Rect(0, 0, b.width, b.height)) { if !region.In(image.Rect(0, 0, b.width, b.height)) {
panic(fmt.Sprintf("atlas: out of range %v", region)) panic(fmt.Sprintf("atlas: out of range %v", region))
} }
b.restorable.Image.WritePixels(pixels, region) b.image.WritePixels(pixels, region)
} }
var ( var (
@ -231,7 +228,7 @@ type Image struct {
// usedAsSourceCount represents how long the image is used as a rendering source and kept not modified with // usedAsSourceCount represents how long the image is used as a rendering source and kept not modified with
// DrawTriangles. // DrawTriangles.
// In the current implementation, if an image is being modified by DrawTriangles, the image is separated from // In the current implementation, if an image is being modified by DrawTriangles, the image is separated from
// a restorable image on an atlas by ensureIsolatedFromSource. // a graphicscommand.Image on an atlas by ensureIsolatedFromSource.
// //
// usedAsSourceCount is increased if the image is used as a rendering source, or set to 0 if the image is // usedAsSourceCount is increased if the image is used as a rendering source, or set to 0 if the image is
// modified. // modified.
@ -443,7 +440,7 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
for _, src := range srcs { for _, src := range srcs {
// Compare i and source images after ensuring i is not on an atlas, or // Compare i and source images after ensuring i is not on an atlas, or
// i and a source image might share the same atlas even though i != src. // i and a source image might share the same atlas even though i != src.
if src != nil && i.backend.restorable == src.backend.restorable { if src != nil && i.backend.image == src.backend.image {
panic("atlas: Image.DrawTriangles: source must be different from the receiver") panic("atlas: Image.DrawTriangles: source must be different from the receiver")
} }
} }
@ -466,7 +463,7 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
vertices[i+3] += oyf vertices[i+3] += oyf
} }
if shader.ir.Unit == shaderir.Texels { if shader.ir.Unit == shaderir.Texels {
sw, sh := srcs[0].backend.restorable.Image.InternalSize() sw, sh := srcs[0].backend.image.InternalSize()
swf, shf := float32(sw), float32(sh) swf, shf := float32(sw), float32(sh)
for i := 0; i < n; i += graphics.VertexFloatCount { for i := 0; i < n; i += graphics.VertexFloatCount {
vertices[i+2] /= swf vertices[i+2] /= swf
@ -501,10 +498,10 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [
if src == nil { if src == nil {
continue continue
} }
imgs[i] = src.backend.restorable.Image imgs[i] = src.backend.image
} }
i.backend.restorable.Image.DrawTriangles(imgs, vertices, indices, blend, dstRegion, srcRegions, shader.ensureShader().Shader, uniforms, fillRule) i.backend.image.DrawTriangles(imgs, vertices, indices, blend, dstRegion, srcRegions, shader.ensureShader().Shader, uniforms, fillRule)
for _, src := range srcs { for _, src := range srcs {
if src == nil { if src == nil {
@ -620,14 +617,14 @@ func (i *Image) readPixels(graphicsDriver graphicsdriver.Graphics, pixels []byte
// To prevent memory leaks, flush the deferred functions here. // To prevent memory leaks, flush the deferred functions here.
flushDeferred() flushDeferred()
if i.backend == nil || i.backend.restorable == nil { if i.backend == nil || i.backend.image == nil {
for i := range pixels { for i := range pixels {
pixels[i] = 0 pixels[i] = 0
} }
return nil return nil
} }
if err := i.backend.restorable.Image.ReadPixels(graphicsDriver, []graphicsdriver.PixelsArgs{ if err := i.backend.image.ReadPixels(graphicsDriver, []graphicsdriver.PixelsArgs{
{ {
Pixels: pixels, Pixels: pixels,
Region: region.Add(i.regionWithPadding().Min), Region: region.Add(i.regionWithPadding().Min),
@ -672,8 +669,8 @@ func (i *Image) deallocate() {
} }
if !i.isOnAtlas() { if !i.isOnAtlas() {
i.backend.restorable.Image.Dispose() i.backend.image.Dispose()
i.backend.restorable.Image = nil i.backend.image = nil
return return
} }
@ -685,8 +682,8 @@ func (i *Image) deallocate() {
return return
} }
i.backend.restorable.Image.Dispose() i.backend.image.Dispose()
i.backend.restorable.Image = nil i.backend.image = nil
for idx, sh := range theBackends { for idx, sh := range theBackends {
if sh == i.backend { if sh == i.backend {
@ -743,9 +740,9 @@ func (i *Image) allocate(forbiddenBackends []*backend, asSource bool) {
} }
// A screen image doesn't have a padding. // A screen image doesn't have a padding.
i.backend = &backend{ i.backend = &backend{
restorable: newClearedImage(i.width, i.height, true), image: newClearedImage(i.width, i.height, true),
width: i.width, width: i.width,
height: i.height, height: i.height,
} }
theBackends = append(theBackends, i.backend) theBackends = append(theBackends, i.backend)
return return
@ -760,10 +757,10 @@ func (i *Image) allocate(forbiddenBackends []*backend, asSource bool) {
} }
i.backend = &backend{ i.backend = &backend{
restorable: newClearedImage(wp, hp, false), image: newClearedImage(wp, hp, false),
width: wp, width: wp,
height: hp, height: hp,
source: asSource && i.imageType == ImageTypeRegular, source: asSource && i.imageType == ImageTypeRegular,
} }
theBackends = append(theBackends, i.backend) theBackends = append(theBackends, i.backend)
return return
@ -808,11 +805,11 @@ loop:
} }
b := &backend{ b := &backend{
restorable: newClearedImage(width, height, false), image: newClearedImage(width, height, false),
width: width, width: width,
height: height, height: height,
page: packing.NewPage(width, height, maxSize), page: packing.NewPage(width, height, maxSize),
source: asSource, source: asSource,
} }
theBackends = append(theBackends, b) theBackends = append(theBackends, b)
@ -832,7 +829,7 @@ func (i *Image) DumpScreenshot(graphicsDriver graphicsdriver.Graphics, path stri
panic("atlas: DumpScreenshots must be called in between BeginFrame and EndFrame") panic("atlas: DumpScreenshots must be called in between BeginFrame and EndFrame")
} }
return i.backend.restorable.Image.Dump(graphicsDriver, path, blackbg, image.Rect(0, 0, i.width, i.height)) return i.backend.image.Dump(graphicsDriver, path, blackbg, image.Rect(0, 0, i.width, i.height))
} }
func EndFrame() error { func EndFrame() error {
@ -870,10 +867,10 @@ func SwapBuffers(graphicsDriver graphicsdriver.Graphics) error {
debug.Logf("Internal image sizes:\n") debug.Logf("Internal image sizes:\n")
imgs := make([]*graphicscommand.Image, 0, len(theBackends)) imgs := make([]*graphicscommand.Image, 0, len(theBackends))
for _, backend := range theBackends { for _, backend := range theBackends {
if backend.restorable == nil { if backend.image == nil {
continue continue
} }
imgs = append(imgs, backend.restorable.Image) imgs = append(imgs, backend.image)
} }
graphicscommand.LogImagesInfo(imgs) graphicscommand.LogImagesInfo(imgs)
} }
@ -950,10 +947,10 @@ func DumpImages(graphicsDriver graphicsdriver.Graphics, dir string) (string, err
images := make([]*graphicscommand.Image, 0, len(theBackends)) images := make([]*graphicscommand.Image, 0, len(theBackends))
for _, backend := range theBackends { for _, backend := range theBackends {
if backend.restorable == nil { if backend.image == nil {
continue continue
} }
images = append(images, backend.restorable.Image) images = append(images, backend.image)
} }
return graphicscommand.DumpImages(images, graphicsDriver, dir) return graphicscommand.DumpImages(images, graphicsDriver, dir)
} }

View File

@ -1,27 +0,0 @@
// Copyright 2016 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
import (
"github.com/hajimehoshi/ebiten/v2/internal/graphicscommand"
)
// Image represents an image.
type Image struct {
// Image is the underlying image.
// This member is exported on purpose.
// TODO: Move the implementation to internal/atlas package (#805).
Image *graphicscommand.Image
}