mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-01-11 19:48:54 +01:00
parent
59896e4447
commit
812cd494de
@ -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,7 +740,7 @@ 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,
|
||||||
}
|
}
|
||||||
@ -760,7 +757,7 @@ 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,
|
||||||
@ -808,7 +805,7 @@ 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),
|
||||||
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user