This commit is contained in:
Hajime Hoshi 2022-10-23 01:12:34 +09:00
parent fcda4143a5
commit 4247d08d2a
7 changed files with 129 additions and 5 deletions

90
examples/skipdraw/main.go Normal file
View File

@ -0,0 +1,90 @@
// Copyright 2022 The Ebitengine 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.
//go:build example
// +build example
package main
import (
"bytes"
"image"
_ "image/jpeg"
"log"
"math"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/examples/resources/images"
"github.com/hajimehoshi/ebiten/v2/inpututil"
)
const (
screenWidth = 640
screenHeight = 480
)
var (
gophersImage *ebiten.Image
)
type Game struct {
count int
}
func (g *Game) Update() error {
g.count++
if len(inpututil.AppendPressedKeys(nil)) > 0 {
return nil
}
ebiten.SkipDraw()
return nil
}
func (g *Game) Draw(screen *ebiten.Image) {
w, h := gophersImage.Size()
op := &ebiten.DrawImageOptions{}
// Move the image's center to the screen's upper-left corner.
// This is a preparation for rotating. When geometry matrices are applied,
// the origin point is the upper-left corner.
op.GeoM.Translate(-float64(w)/2, -float64(h)/2)
// Rotate the image. As a result, the anchor point of this rotate is
// the center of the image.
op.GeoM.Rotate(float64(g.count%360) * 2 * math.Pi / 360)
// Move the image to the screen's center.
op.GeoM.Translate(screenWidth/2, screenHeight/2)
screen.DrawImage(gophersImage, op)
}
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
return screenWidth, screenHeight
}
func main() {
// Decode an image from the image file's byte slice.
img, _, err := image.Decode(bytes.NewReader(images.Gophers_jpg))
if err != nil {
log.Fatal(err)
}
gophersImage = ebiten.NewImageFromImage(img)
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowTitle("Rotate (Ebitengine Demo)")
if err := ebiten.RunGame(&Game{}); err != nil {
log.Fatal(err)
}
}

View File

@ -168,7 +168,8 @@ func (q *commandQueue) Flush(graphicsDriver graphicsdriver.Graphics, endFrame bo
// flush must be called the main thread. // flush must be called the main thread.
func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) (err error) { func (q *commandQueue) flush(graphicsDriver graphicsdriver.Graphics, endFrame bool) (err error) {
if len(q.commands) == 0 { // If endFrame is true, Begin/End should be called to ensure the framebuffer is swapped.
if len(q.commands) == 0 && !endFrame {
return nil return nil
} }

View File

@ -770,7 +770,7 @@ func (g *Graphics) End(present bool) error {
g.pipelineStates.resetConstantBuffers(g.frameIndex) g.pipelineStates.resetConstantBuffers(g.frameIndex)
if present { if present && g.swapChain != nil {
if microsoftgdk.IsXbox() { if microsoftgdk.IsXbox() {
if err := g.presentXbox(); err != nil { if err := g.presentXbox(); err != nil {
return err return err

View File

@ -199,11 +199,15 @@ func (g *Graphics) SetVertices(vertices []float32, indices []uint16) error {
} }
func (g *Graphics) flushIfNeeded(present bool) { func (g *Graphics) flushIfNeeded(present bool) {
if g.cb == (mtl.CommandBuffer{}) { if g.cb == (mtl.CommandBuffer{}) && !present {
return return
} }
g.flushRenderCommandEncoderIfNeeded() g.flushRenderCommandEncoderIfNeeded()
if g.screenDrawable == (ca.MetalDrawable{}) {
g.screenDrawable = g.view.nextDrawable()
}
if !g.view.presentsWithTransaction() && present && g.screenDrawable != (ca.MetalDrawable{}) { if !g.view.presentsWithTransaction() && present && g.screenDrawable != (ca.MetalDrawable{}) {
g.cb.PresentDrawable(g.screenDrawable) g.cb.PresentDrawable(g.screenDrawable)
} }

View File

@ -142,8 +142,16 @@ func (c *context) updateFrameImpl(graphicsDriver graphicsdriver.Graphics, update
} }
// Draw the game. // Draw the game.
if err := c.drawGame(graphicsDriver); err != nil { drawSkipped := theGlobalState.drawSkipped()
return err defer func() {
if updateCount > 0 {
theGlobalState.resetDrawSkipped()
}
}()
if !drawSkipped {
if err := c.drawGame(graphicsDriver); err != nil {
return err
}
} }
return nil return nil

View File

@ -32,6 +32,7 @@ type globalState struct {
fpsMode_ int32 fpsMode_ int32
isScreenClearedEveryFrame_ int32 isScreenClearedEveryFrame_ int32
graphicsLibrary_ int32 graphicsLibrary_ int32
drawSkipped_ int32
} }
func (g *globalState) error() error { func (g *globalState) error() error {
@ -76,6 +77,18 @@ func (g *globalState) graphicsLibrary() GraphicsLibrary {
return GraphicsLibrary(atomic.LoadInt32(&g.graphicsLibrary_)) return GraphicsLibrary(atomic.LoadInt32(&g.graphicsLibrary_))
} }
func (g *globalState) skipDraw() {
atomic.StoreInt32(&g.drawSkipped_, 1)
}
func (g *globalState) resetDrawSkipped() {
atomic.StoreInt32(&g.drawSkipped_, 0)
}
func (g *globalState) drawSkipped() bool {
return atomic.LoadInt32(&g.drawSkipped_) != 0
}
func FPSMode() FPSModeType { func FPSMode() FPSModeType {
return theGlobalState.fpsMode() return theGlobalState.fpsMode()
} }
@ -96,3 +109,7 @@ func SetScreenClearedEveryFrame(cleared bool) {
func GetGraphicsLibrary() GraphicsLibrary { func GetGraphicsLibrary() GraphicsLibrary {
return theGlobalState.graphicsLibrary() return theGlobalState.graphicsLibrary()
} }
func SkipDraw() {
theGlobalState.skipDraw()
}

4
run.go
View File

@ -537,3 +537,7 @@ func SetScreenTransparent(transparent bool) {
func SetInitFocused(focused bool) { func SetInitFocused(focused bool) {
ui.Get().SetInitFocused(focused) ui.Get().SetInitFocused(focused)
} }
func SkipDraw() {
ui.SkipDraw()
}