diff --git a/internal/atlas/image.go b/internal/atlas/image.go index 934752b78..8d94f18e1 100644 --- a/internal/atlas/image.go +++ b/internal/atlas/image.go @@ -26,7 +26,6 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/graphicsdriver" "github.com/hajimehoshi/ebiten/v2/internal/packing" - "github.com/hajimehoshi/ebiten/v2/internal/restorable" "github.com/hajimehoshi/ebiten/v2/internal/shaderir" ) @@ -141,7 +140,7 @@ func (b *backend) extendIfNeeded(width, height int) { vs := quadVertices(0, 0, float32(sw), float32(sh), 0, 0, float32(sw), float32(sh), 1, 1, 1, 1) is := graphics.QuadIndices() dr := image.Rect(0, 0, sw, sh) - newImg.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(), nil, graphicsdriver.FillAll) b.image.Dispose() b.image = newImg @@ -165,7 +164,7 @@ func newClearedImage(width, height int, screen bool) *graphicscommand.Image { func clearImage(i *graphicscommand.Image, region image.Rectangle) { vs := quadVertices(float32(region.Min.X), float32(region.Min.Y), float32(region.Max.X), float32(region.Max.Y), 0, 0, 0, 0, 0, 0, 0, 0) is := graphics.QuadIndices() - i.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{}, vs, is, graphicsdriver.BlendClear, region, [graphics.ShaderImageCount]image.Rectangle{}, restorable.ClearShader.Shader, nil, graphicsdriver.FillAll) + i.DrawTriangles([graphics.ShaderImageCount]*graphicscommand.Image{}, vs, is, graphicsdriver.BlendClear, region, [graphics.ShaderImageCount]image.Rectangle{}, clearShader.ensureShader(), nil, graphicsdriver.FillAll) } func (b *backend) clearPixels(region image.Rectangle) { @@ -501,7 +500,7 @@ func (i *Image) drawTriangles(srcs [graphics.ShaderImageCount]*Image, vertices [ imgs[i] = src.backend.image } - i.backend.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(), uniforms, fillRule) for _, src := range srcs { if src == nil { diff --git a/internal/atlas/shader.go b/internal/atlas/shader.go index addb3188c..700e18e60 100644 --- a/internal/atlas/shader.go +++ b/internal/atlas/shader.go @@ -15,15 +15,20 @@ package atlas import ( + "fmt" "runtime" - "github.com/hajimehoshi/ebiten/v2/internal/restorable" + "golang.org/x/sync/errgroup" + + "github.com/hajimehoshi/ebiten/v2/internal/builtinshader" + "github.com/hajimehoshi/ebiten/v2/internal/graphics" + "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" "github.com/hajimehoshi/ebiten/v2/internal/shaderir" ) type Shader struct { ir *shaderir.Program - shader *restorable.Shader + shader *graphicscommand.Shader } func NewShader(ir *shaderir.Program) *Shader { @@ -33,11 +38,11 @@ func NewShader(ir *shaderir.Program) *Shader { } } -func (s *Shader) ensureShader() *restorable.Shader { +func (s *Shader) ensureShader() *graphicscommand.Shader { if s.shader != nil { return s.shader } - s.shader = restorable.NewShader(s.ir) + s.shader = graphicscommand.NewShader(s.ir) runtime.SetFinalizer(s, func(shader *Shader) { // A function from finalizer must not be blocked, but disposing operation can be blocked. // Defer this operation until it becomes safe. (#913) @@ -68,18 +73,49 @@ func (s *Shader) deallocate() { if s.shader == nil { return } - s.shader.Shader.Dispose() - s.shader.Shader = nil + s.shader.Dispose() s.shader = nil } var ( - NearestFilterShader = &Shader{ - shader: restorable.NearestFilterShader, - ir: restorable.LinearFilterShaderIR, - } - LinearFilterShader = &Shader{ - shader: restorable.LinearFilterShader, - ir: restorable.LinearFilterShaderIR, - } + NearestFilterShader *Shader + LinearFilterShader *Shader + clearShader *Shader ) + +func init() { + var wg errgroup.Group + wg.Go(func() error { + ir, err := graphics.CompileShader([]byte(builtinshader.Shader(builtinshader.FilterNearest, builtinshader.AddressUnsafe, false))) + if err != nil { + return fmt.Errorf("atlas: compiling the nearest shader failed: %w", err) + } + NearestFilterShader = NewShader(ir) + return nil + }) + wg.Go(func() error { + ir, err := graphics.CompileShader([]byte(builtinshader.Shader(builtinshader.FilterLinear, builtinshader.AddressUnsafe, false))) + if err != nil { + return fmt.Errorf("atlas: compiling the linear shader failed: %w", err) + } + LinearFilterShader = NewShader(ir) + return nil + }) + wg.Go(func() error { + ir, err := graphics.CompileShader([]byte(`//kage:unit pixels + +package main + +func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 { + return vec4(0) +}`)) + if err != nil { + return fmt.Errorf("atlas: compiling the clear shader failed: %w", err) + } + clearShader = NewShader(ir) + return nil + }) + if err := wg.Wait(); err != nil { + panic(err) + } +} diff --git a/internal/restorable/doc.go b/internal/restorable/doc.go deleted file mode 100644 index adc4c448f..000000000 --- a/internal/restorable/doc.go +++ /dev/null @@ -1,22 +0,0 @@ -// 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 used to offer an Image struct that stores image commands -// and restores its pixel data from the commands when context lost happens. -// -// However, now Ebitengine doesn't handle context losts, and this package is -// just a thin wrapper. -// -// TODO: Integrate this package into internal/atlas and internal/graphicscommand (#805). -package restorable diff --git a/internal/restorable/shader.go b/internal/restorable/shader.go deleted file mode 100644 index b8605f6b9..000000000 --- a/internal/restorable/shader.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright 2020 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 ( - "fmt" - - "golang.org/x/sync/errgroup" - - "github.com/hajimehoshi/ebiten/v2/internal/builtinshader" - "github.com/hajimehoshi/ebiten/v2/internal/graphics" - "github.com/hajimehoshi/ebiten/v2/internal/graphicscommand" - "github.com/hajimehoshi/ebiten/v2/internal/shaderir" -) - -type Shader struct { - Shader *graphicscommand.Shader -} - -func NewShader(ir *shaderir.Program) *Shader { - s := &Shader{ - Shader: graphicscommand.NewShader(ir), - } - return s -} - -var ( - NearestFilterShader *Shader - NearestFilterShaderIR *shaderir.Program - LinearFilterShader *Shader - LinearFilterShaderIR *shaderir.Program - ClearShader *Shader -) - -func init() { - var wg errgroup.Group - var nearestIR, linearIR, clearIR *shaderir.Program - wg.Go(func() error { - ir, err := graphics.CompileShader([]byte(builtinshader.Shader(builtinshader.FilterNearest, builtinshader.AddressUnsafe, false))) - if err != nil { - return fmt.Errorf("restorable: compiling the nearest shader failed: %w", err) - } - nearestIR = ir - return nil - }) - wg.Go(func() error { - ir, err := graphics.CompileShader([]byte(builtinshader.Shader(builtinshader.FilterLinear, builtinshader.AddressUnsafe, false))) - if err != nil { - return fmt.Errorf("restorable: compiling the linear shader failed: %w", err) - } - linearIR = ir - return nil - }) - wg.Go(func() error { - ir, err := graphics.CompileShader([]byte(`//kage:unit pixels - -package main - -func Fragment(dstPos vec4, srcPos vec2, color vec4) vec4 { - return vec4(0) -}`)) - if err != nil { - return fmt.Errorf("restorable: compiling the clear shader failed: %w", err) - } - clearIR = ir - return nil - }) - if err := wg.Wait(); err != nil { - panic(err) - } - NearestFilterShaderIR = nearestIR - NearestFilterShader = NewShader(nearestIR) - LinearFilterShaderIR = linearIR - LinearFilterShader = NewShader(linearIR) - ClearShader = NewShader(clearIR) -}