mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 01:45:36 +00:00
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:
@@ -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
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user