mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-04 00:45:35 +00:00
app,app/internal/gpu: split render loop from GPU
The policy of rendering on a separate goroutine is separate from the actual rendering. Reflect that by introducing the RenderLoop type for driving a GPU from a separate goroutine. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+19
-20
@@ -9,7 +9,6 @@ import (
|
||||
"time"
|
||||
|
||||
"gioui.org/app/internal/gl"
|
||||
"gioui.org/app/internal/gpu"
|
||||
"gioui.org/app/internal/input"
|
||||
"gioui.org/app/internal/window"
|
||||
"gioui.org/io/event"
|
||||
@@ -27,7 +26,7 @@ type Option func(opts *window.Options)
|
||||
// Window represents an operating system window.
|
||||
type Window struct {
|
||||
driver window.Driver
|
||||
gpu *gpu.GPU
|
||||
loop *renderLoop
|
||||
|
||||
// driverFuncs is a channel of functions to run when
|
||||
// the Window has a valid driver.
|
||||
@@ -127,7 +126,7 @@ func (w *Window) update(frame *op.Ops) {
|
||||
}
|
||||
|
||||
func (w *Window) draw(frameStart time.Time, size image.Point, frame *op.Ops) {
|
||||
sync := w.gpu.Draw(w.queue.q.Profiling(), size, frame)
|
||||
sync := w.loop.Draw(w.queue.q.Profiling(), size, frame)
|
||||
w.queue.q.Frame(frame)
|
||||
switch w.queue.q.TextInputState() {
|
||||
case input.TextInputOpen:
|
||||
@@ -139,7 +138,7 @@ func (w *Window) draw(frameStart time.Time, size image.Point, frame *op.Ops) {
|
||||
frameDur := time.Since(frameStart)
|
||||
frameDur = frameDur.Truncate(100 * time.Microsecond)
|
||||
q := 100 * time.Microsecond
|
||||
timings := fmt.Sprintf("tot:%7s %s", frameDur.Round(q), w.gpu.Timings())
|
||||
timings := fmt.Sprintf("tot:%7s %s", frameDur.Round(q), w.loop.Summary())
|
||||
w.queue.q.AddProfile(profile.Event{Timings: timings})
|
||||
}
|
||||
if t, ok := w.queue.q.WakeupTime(); ok {
|
||||
@@ -218,9 +217,9 @@ func (w *Window) destroy(err error) {
|
||||
}
|
||||
|
||||
func (w *Window) destroyGPU() {
|
||||
if w.gpu != nil {
|
||||
w.gpu.Release()
|
||||
w.gpu = nil
|
||||
if w.loop != nil {
|
||||
w.loop.Release()
|
||||
w.loop = nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,12 +251,12 @@ func (w *Window) run(opts *window.Options) {
|
||||
case e := <-w.in:
|
||||
switch e2 := e.(type) {
|
||||
case system.StageEvent:
|
||||
if w.gpu != nil {
|
||||
if w.loop != nil {
|
||||
if e2.Stage < system.StageRunning {
|
||||
w.gpu.Release()
|
||||
w.gpu = nil
|
||||
w.loop.Release()
|
||||
w.loop = nil
|
||||
} else {
|
||||
w.gpu.Refresh()
|
||||
w.loop.Refresh()
|
||||
}
|
||||
}
|
||||
w.stage = e2.Stage
|
||||
@@ -277,19 +276,19 @@ func (w *Window) run(opts *window.Options) {
|
||||
e2.Frame = w.update
|
||||
w.out <- e2.FrameEvent
|
||||
var err error
|
||||
if w.gpu != nil {
|
||||
if w.loop != nil {
|
||||
if e2.Sync {
|
||||
w.gpu.Refresh()
|
||||
w.loop.Refresh()
|
||||
}
|
||||
if err = w.gpu.Flush(); err != nil {
|
||||
w.gpu.Release()
|
||||
w.gpu = nil
|
||||
if err = w.loop.Flush(); err != nil {
|
||||
w.loop.Release()
|
||||
w.loop = nil
|
||||
}
|
||||
} else {
|
||||
var ctx gl.Context
|
||||
ctx, err = w.driver.NewContext()
|
||||
if err == nil {
|
||||
w.gpu, err = gpu.New(ctx)
|
||||
w.loop, err = newLoop(ctx)
|
||||
if err != nil {
|
||||
ctx.Release()
|
||||
}
|
||||
@@ -318,9 +317,9 @@ func (w *Window) run(opts *window.Options) {
|
||||
w.frameAck <- struct{}{}
|
||||
}
|
||||
if e2.Sync {
|
||||
if err := w.gpu.Flush(); err != nil {
|
||||
w.gpu.Release()
|
||||
w.gpu = nil
|
||||
if err := w.loop.Flush(); err != nil {
|
||||
w.loop.Release()
|
||||
w.loop = nil
|
||||
w.destroy(err)
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user