From 5966aab77e87d1d1b46f7fd21830511face44859 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 1 Jun 2019 19:46:46 +0200 Subject: [PATCH] ui: move ops reader to ui package To prepare support for cached OpBlock to refer to other Ops lists. The exposure of OpsReader is alleviated by the removal of the Refs and Data accessors for Ops. Signed-off-by: Elias Naur --- ui/app/internal/gpu/gpu.go | 6 +-- ui/app/window.go | 6 +-- ui/internal/ops/ops.go | 81 ----------------------------------- ui/key/queue.go | 6 +-- ui/ops.go | 87 ++++++++++++++++++++++++++++++++++---- ui/pointer/queue.go | 6 +-- 6 files changed, 90 insertions(+), 102 deletions(-) diff --git a/ui/app/internal/gpu/gpu.go b/ui/app/internal/gpu/gpu.go index 58693eb3..9f9f6bd0 100644 --- a/ui/app/internal/gpu/gpu.go +++ b/ui/app/internal/gpu/gpu.go @@ -56,7 +56,7 @@ type renderer struct { } type drawOps struct { - reader ops.Reader + reader ui.OpsReader cache *resourceCache viewport image.Point clearColor [3]float32 @@ -651,7 +651,7 @@ func (d *drawOps) collect(cache *resourceCache, root *ui.Ops, viewport image.Poi clip := f32.Rectangle{ Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)}, } - d.reader.Reset(root.Data(), root.Refs()) + d.reader.Reset(root) state := drawState{ clip: clip, rect: true, @@ -664,7 +664,7 @@ func (d *drawOps) newPathOp() *pathOp { return &d.pathOpCache[len(d.pathOpCache)-1] } -func (d *drawOps) collectOps(r *ops.Reader, state drawState) int { +func (d *drawOps) collectOps(r *ui.OpsReader, state drawState) int { loop: for { data, ok := r.Decode() diff --git a/ui/app/window.go b/ui/app/window.go index 71533ee3..60365c52 100644 --- a/ui/app/window.go +++ b/ui/app/window.go @@ -46,7 +46,7 @@ type Window struct { nextFrame time.Time delayedDraw *time.Timer - reader ops.Reader + reader ui.OpsReader } // driver is the interface for the platform implementation @@ -144,7 +144,7 @@ func (w *Window) Draw(root *ui.Ops) { w.timings = fmt.Sprintf("tot:%7s cpu:%7s %s", frameDur.Round(q), drawDur.Round(q), w.gpu.Timings()) w.setNextFrame(time.Time{}) } - w.reader.Reset(root.Data(), root.Refs()) + w.reader.Reset(root) if t, ok := collectRedraws(&w.reader); ok { w.setNextFrame(t) } @@ -152,7 +152,7 @@ func (w *Window) Draw(root *ui.Ops) { w.gpu.Draw(w.Profiling, size, root) } -func collectRedraws(r *ops.Reader) (time.Time, bool) { +func collectRedraws(r *ui.OpsReader) (time.Time, bool) { var t time.Time redraw := false for { diff --git a/ui/internal/ops/ops.go b/ui/internal/ops/ops.go index 8f0cff96..481f81aa 100644 --- a/ui/internal/ops/ops.go +++ b/ui/internal/ops/ops.go @@ -1,23 +1,5 @@ package ops -import ( - "encoding/binary" -) - -type Reader struct { - pc int - stack []block - Refs []interface{} - data []byte - - pseudoOp [1]byte -} - -type block struct { - retPC int - endPC int -} - type OpType byte const ( @@ -53,66 +35,3 @@ const ( TypePushLen = 1 TypePopLen = 1 ) - -var typeLengths = [...]int{ - TypeBlockDefLen, - TypeBlockLen, - TypeTransformLen, - TypeLayerLen, - TypeRedrawLen, - TypeClipLen, - TypeImageLen, - TypeDrawLen, - TypeColorLen, - TypePointerHandlerLen, - TypeKeyHandlerLen, - TypeHideInputLen, - TypePushLen, - TypePopLen, -} - -// Reset start reading from the op list. -func (r *Reader) Reset(data []byte, refs []interface{}) { - r.Refs = refs - r.data = data - r.stack = r.stack[:0] - r.pc = 0 -} - -func (r *Reader) Decode() ([]byte, bool) { - bo := binary.LittleEndian - for { - if r.pc == len(r.data) { - return nil, false - } - if len(r.stack) > 0 { - b := r.stack[len(r.stack)-1] - if r.pc == b.endPC { - r.pc = b.retPC - r.stack = r.stack[:len(r.stack)-1] - r.pseudoOp[0] = byte(TypePop) - return r.pseudoOp[:], true - } - } - t := OpType(r.data[r.pc]) - n := typeLengths[t] - data := r.data[r.pc : r.pc+n] - switch t { - case TypeBlock: - blockIdx := int(bo.Uint32(data[1:])) - if OpType(r.data[blockIdx]) != TypeBlockDef { - panic("invalid block reference") - } - blockLen := int(bo.Uint32(r.data[blockIdx+1:])) - r.stack = append(r.stack, block{r.pc + n, blockIdx + blockLen}) - r.pc = blockIdx + TypeBlockDefLen - r.pseudoOp[0] = byte(TypePush) - return r.pseudoOp[:], true - case TypeBlockDef: - r.pc += int(bo.Uint32(data[1:])) - continue - } - r.pc += n - return data, true - } -} diff --git a/ui/key/queue.go b/ui/key/queue.go index 0ed02817..2727b3eb 100644 --- a/ui/key/queue.go +++ b/ui/key/queue.go @@ -11,7 +11,7 @@ type Queue struct { focus Key events []Event handlers map[Key]bool - reader ops.Reader + reader ui.OpsReader } type listenerPriority uint8 @@ -25,7 +25,7 @@ const ( func (q *Queue) Frame(root *ui.Ops) TextInputState { q.events = q.events[:0] - q.reader.Reset(root.Data(), root.Refs()) + q.reader.Reset(root) f, pri, hide := resolveFocus(&q.reader, q.focus) changed := f != nil && f != q.focus for k, active := range q.handlers { @@ -74,7 +74,7 @@ func (q *Queue) For(k Key) []Event { return q.events } -func resolveFocus(r *ops.Reader, focus Key) (Key, listenerPriority, bool) { +func resolveFocus(r *ui.OpsReader, focus Key) (Key, listenerPriority, bool) { var k Key var pri listenerPriority var hide bool diff --git a/ui/ops.go b/ui/ops.go index fac6cf3c..3c2ec380 100644 --- a/ui/ops.go +++ b/ui/ops.go @@ -6,7 +6,7 @@ import ( "gioui.org/ui/internal/ops" ) -// Ops hold a list of serialized Ops. +// Ops holds a list of serialized Ops. type Ops struct { // Stack of block start indices. stack []int @@ -16,6 +16,37 @@ type Ops struct { refs []interface{} } +type OpsReader struct { + pc int + stack []block + Refs []interface{} + data []byte + + pseudoOp [1]byte +} + +type block struct { + retPC int + endPC int +} + +var typeLengths = [...]int{ + ops.TypeBlockDefLen, + ops.TypeBlockLen, + ops.TypeTransformLen, + ops.TypeLayerLen, + ops.TypeRedrawLen, + ops.TypeClipLen, + ops.TypeImageLen, + ops.TypeDrawLen, + ops.TypeColorLen, + ops.TypePointerHandlerLen, + ops.TypeKeyHandlerLen, + ops.TypeHideInputLen, + ops.TypePushLen, + ops.TypePopLen, +} + type OpBlock struct { idx int } @@ -46,14 +77,6 @@ func (o *Ops) Reset() { o.data = o.data[:0] } -func (o *Ops) Refs() []interface{} { - return o.refs -} - -func (o *Ops) Data() []byte { - return o.data -} - func (o *Ops) Ref(r interface{}) int { o.refs = append(o.refs, r) return len(o.refs) - 1 @@ -75,3 +98,49 @@ func (b OpBlock) Add(o *Ops) { bo.PutUint32(data[1:], uint32(b.idx)) o.Write(data) } + +// Reset start reading from the op list. +func (r *OpsReader) Reset(ops *Ops) { + r.Refs = ops.refs + r.data = ops.data + r.stack = r.stack[:0] + r.pc = 0 +} + +func (r *OpsReader) Decode() ([]byte, bool) { + bo := binary.LittleEndian + for { + if r.pc == len(r.data) { + return nil, false + } + if len(r.stack) > 0 { + b := r.stack[len(r.stack)-1] + if r.pc == b.endPC { + r.pc = b.retPC + r.stack = r.stack[:len(r.stack)-1] + r.pseudoOp[0] = byte(ops.TypePop) + return r.pseudoOp[:], true + } + } + t := ops.OpType(r.data[r.pc]) + n := typeLengths[t] + data := r.data[r.pc : r.pc+n] + switch t { + case ops.TypeBlock: + blockIdx := int(bo.Uint32(data[1:])) + if ops.OpType(r.data[blockIdx]) != ops.TypeBlockDef { + panic("invalid block reference") + } + blockLen := int(bo.Uint32(r.data[blockIdx+1:])) + r.stack = append(r.stack, block{r.pc + n, blockIdx + blockLen}) + r.pc = blockIdx + ops.TypeBlockDefLen + r.pseudoOp[0] = byte(ops.TypePush) + return r.pseudoOp[:], true + case ops.TypeBlockDef: + r.pc += int(bo.Uint32(data[1:])) + continue + } + r.pc += n + return data, true + } +} diff --git a/ui/pointer/queue.go b/ui/pointer/queue.go index 28f0bc0c..ef22218a 100644 --- a/ui/pointer/queue.go +++ b/ui/pointer/queue.go @@ -12,7 +12,7 @@ type Queue struct { hitTree []hitNode handlers map[Key]*handler pointers []pointerInfo - reader ops.Reader + reader ui.OpsReader scratch []Key } @@ -37,7 +37,7 @@ type handler struct { wantsGrab bool } -func (q *Queue) collectHandlers(r *ops.Reader, t ui.Transform, layer int) { +func (q *Queue) collectHandlers(r *ui.OpsReader, t ui.Transform, layer int) { for { data, ok := r.Decode() if !ok { @@ -116,7 +116,7 @@ func (q *Queue) Frame(root *ui.Ops) { } } q.hitTree = q.hitTree[:0] - q.reader.Reset(root.Data(), root.Refs()) + q.reader.Reset(root) q.collectHandlers(&q.reader, ui.Transform{}, 0) }