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 <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2019-06-01 19:46:46 +02:00
parent 528a588f2e
commit 5966aab77e
6 changed files with 90 additions and 102 deletions
+3 -3
View File
@@ -56,7 +56,7 @@ type renderer struct {
} }
type drawOps struct { type drawOps struct {
reader ops.Reader reader ui.OpsReader
cache *resourceCache cache *resourceCache
viewport image.Point viewport image.Point
clearColor [3]float32 clearColor [3]float32
@@ -651,7 +651,7 @@ func (d *drawOps) collect(cache *resourceCache, root *ui.Ops, viewport image.Poi
clip := f32.Rectangle{ clip := f32.Rectangle{
Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)}, Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)},
} }
d.reader.Reset(root.Data(), root.Refs()) d.reader.Reset(root)
state := drawState{ state := drawState{
clip: clip, clip: clip,
rect: true, rect: true,
@@ -664,7 +664,7 @@ func (d *drawOps) newPathOp() *pathOp {
return &d.pathOpCache[len(d.pathOpCache)-1] 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: loop:
for { for {
data, ok := r.Decode() data, ok := r.Decode()
+3 -3
View File
@@ -46,7 +46,7 @@ type Window struct {
nextFrame time.Time nextFrame time.Time
delayedDraw *time.Timer delayedDraw *time.Timer
reader ops.Reader reader ui.OpsReader
} }
// driver is the interface for the platform implementation // 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.timings = fmt.Sprintf("tot:%7s cpu:%7s %s", frameDur.Round(q), drawDur.Round(q), w.gpu.Timings())
w.setNextFrame(time.Time{}) w.setNextFrame(time.Time{})
} }
w.reader.Reset(root.Data(), root.Refs()) w.reader.Reset(root)
if t, ok := collectRedraws(&w.reader); ok { if t, ok := collectRedraws(&w.reader); ok {
w.setNextFrame(t) w.setNextFrame(t)
} }
@@ -152,7 +152,7 @@ func (w *Window) Draw(root *ui.Ops) {
w.gpu.Draw(w.Profiling, size, root) 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 var t time.Time
redraw := false redraw := false
for { for {
-81
View File
@@ -1,23 +1,5 @@
package ops 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 type OpType byte
const ( const (
@@ -53,66 +35,3 @@ const (
TypePushLen = 1 TypePushLen = 1
TypePopLen = 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
}
}
+3 -3
View File
@@ -11,7 +11,7 @@ type Queue struct {
focus Key focus Key
events []Event events []Event
handlers map[Key]bool handlers map[Key]bool
reader ops.Reader reader ui.OpsReader
} }
type listenerPriority uint8 type listenerPriority uint8
@@ -25,7 +25,7 @@ const (
func (q *Queue) Frame(root *ui.Ops) TextInputState { func (q *Queue) Frame(root *ui.Ops) TextInputState {
q.events = q.events[:0] q.events = q.events[:0]
q.reader.Reset(root.Data(), root.Refs()) q.reader.Reset(root)
f, pri, hide := resolveFocus(&q.reader, q.focus) f, pri, hide := resolveFocus(&q.reader, q.focus)
changed := f != nil && f != q.focus changed := f != nil && f != q.focus
for k, active := range q.handlers { for k, active := range q.handlers {
@@ -74,7 +74,7 @@ func (q *Queue) For(k Key) []Event {
return q.events 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 k Key
var pri listenerPriority var pri listenerPriority
var hide bool var hide bool
+78 -9
View File
@@ -6,7 +6,7 @@ import (
"gioui.org/ui/internal/ops" "gioui.org/ui/internal/ops"
) )
// Ops hold a list of serialized Ops. // Ops holds a list of serialized Ops.
type Ops struct { type Ops struct {
// Stack of block start indices. // Stack of block start indices.
stack []int stack []int
@@ -16,6 +16,37 @@ type Ops struct {
refs []interface{} 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 { type OpBlock struct {
idx int idx int
} }
@@ -46,14 +77,6 @@ func (o *Ops) Reset() {
o.data = o.data[:0] 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 { func (o *Ops) Ref(r interface{}) int {
o.refs = append(o.refs, r) o.refs = append(o.refs, r)
return len(o.refs) - 1 return len(o.refs) - 1
@@ -75,3 +98,49 @@ func (b OpBlock) Add(o *Ops) {
bo.PutUint32(data[1:], uint32(b.idx)) bo.PutUint32(data[1:], uint32(b.idx))
o.Write(data) 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
}
}
+3 -3
View File
@@ -12,7 +12,7 @@ type Queue struct {
hitTree []hitNode hitTree []hitNode
handlers map[Key]*handler handlers map[Key]*handler
pointers []pointerInfo pointers []pointerInfo
reader ops.Reader reader ui.OpsReader
scratch []Key scratch []Key
} }
@@ -37,7 +37,7 @@ type handler struct {
wantsGrab bool 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 { for {
data, ok := r.Decode() data, ok := r.Decode()
if !ok { if !ok {
@@ -116,7 +116,7 @@ func (q *Queue) Frame(root *ui.Ops) {
} }
} }
q.hitTree = q.hitTree[:0] q.hitTree = q.hitTree[:0]
q.reader.Reset(root.Data(), root.Refs()) q.reader.Reset(root)
q.collectHandlers(&q.reader, ui.Transform{}, 0) q.collectHandlers(&q.reader, ui.Transform{}, 0)
} }