forked from joejulian/gio
op: introduce CallOp
We'd like to improve the API of Flex, Stack and similar layouts that use MacroOps internall. Unfortunately, the func (m MacroOp) Add(o *Ops) method causes the MacroOp to be allocated on the heap, ruining the nice garbage-free property of layouts. Fortunately, layouts don't need the feature that caused the heap allocation: invoking operation lists different than the current. CallOp separates the invoke-different-list semantic from MacroOp, in preparation for removing the feature from MacroOp. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -26,6 +26,7 @@ const (
|
|||||||
TypeAux
|
TypeAux
|
||||||
TypeClip
|
TypeClip
|
||||||
TypeProfile
|
TypeProfile
|
||||||
|
TypeCall
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -47,6 +48,7 @@ const (
|
|||||||
TypeAuxLen = 1
|
TypeAuxLen = 1
|
||||||
TypeClipLen = 1 + 4*4
|
TypeClipLen = 1 + 4*4
|
||||||
TypeProfileLen = 1
|
TypeProfileLen = 1
|
||||||
|
TypeCallLen = 1
|
||||||
)
|
)
|
||||||
|
|
||||||
func (t OpType) Size() int {
|
func (t OpType) Size() int {
|
||||||
@@ -69,12 +71,13 @@ func (t OpType) Size() int {
|
|||||||
TypeAuxLen,
|
TypeAuxLen,
|
||||||
TypeClipLen,
|
TypeClipLen,
|
||||||
TypeProfileLen,
|
TypeProfileLen,
|
||||||
|
TypeCallLen,
|
||||||
}[t-firstOpIndex]
|
}[t-firstOpIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t OpType) NumRefs() int {
|
func (t OpType) NumRefs() int {
|
||||||
switch t {
|
switch t {
|
||||||
case TypeMacro, TypeKeyInput, TypePointerInput, TypeProfile:
|
case TypeMacro, TypeKeyInput, TypePointerInput, TypeProfile, TypeCall:
|
||||||
return 1
|
return 1
|
||||||
case TypeImage:
|
case TypeImage:
|
||||||
return 2
|
return 2
|
||||||
|
|||||||
@@ -38,6 +38,11 @@ type macroOp struct {
|
|||||||
pc pc
|
pc pc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shadow of op.CallOp.
|
||||||
|
type callOp struct {
|
||||||
|
ops *op.Ops
|
||||||
|
}
|
||||||
|
|
||||||
type pc struct {
|
type pc struct {
|
||||||
data int
|
data int
|
||||||
refs int
|
refs int
|
||||||
@@ -94,6 +99,24 @@ func (r *Reader) Decode() (EncodedOp, bool) {
|
|||||||
block := r.stack[len(r.stack)-1]
|
block := r.stack[len(r.stack)-1]
|
||||||
n += block.endPC.data - r.pc.data - opconst.TypeAuxLen
|
n += block.endPC.data - r.pc.data - opconst.TypeAuxLen
|
||||||
data = data[:n]
|
data = data[:n]
|
||||||
|
case opconst.TypeCall:
|
||||||
|
var op callOp
|
||||||
|
op.decode(data, refs)
|
||||||
|
endPC := pc{
|
||||||
|
data: len(op.ops.Data()),
|
||||||
|
refs: len(op.ops.Refs()),
|
||||||
|
}
|
||||||
|
retPC := r.pc
|
||||||
|
retPC.data += n
|
||||||
|
retPC.refs += nrefs
|
||||||
|
r.stack = append(r.stack, macro{
|
||||||
|
ops: r.ops,
|
||||||
|
retPC: retPC,
|
||||||
|
endPC: endPC,
|
||||||
|
})
|
||||||
|
r.pc = pc{}
|
||||||
|
r.ops = op.ops
|
||||||
|
continue
|
||||||
case opconst.TypeMacro:
|
case opconst.TypeMacro:
|
||||||
var op macroOp
|
var op macroOp
|
||||||
op.decode(data, refs)
|
op.decode(data, refs)
|
||||||
@@ -148,6 +171,15 @@ func (op *opMacroDef) decode(data []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *callOp) decode(data []byte, refs []interface{}) {
|
||||||
|
if opconst.OpType(data[0]) != opconst.TypeCall {
|
||||||
|
panic("invalid op")
|
||||||
|
}
|
||||||
|
*m = callOp{
|
||||||
|
ops: refs[0].(*op.Ops),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (m *macroOp) decode(data []byte, refs []interface{}) {
|
func (m *macroOp) decode(data []byte, refs []interface{}) {
|
||||||
if opconst.OpType(data[0]) != opconst.TypeMacro {
|
if opconst.OpType(data[0]) != opconst.TypeMacro {
|
||||||
panic("invalid op")
|
panic("invalid op")
|
||||||
|
|||||||
@@ -45,6 +45,12 @@ The StackOp saves the current state to the state stack and restores it later:
|
|||||||
// Restore the previous transform.
|
// Restore the previous transform.
|
||||||
stack.Pop()
|
stack.Pop()
|
||||||
|
|
||||||
|
The CallOp invokes another operation list:
|
||||||
|
|
||||||
|
ops := new(op.Ops)
|
||||||
|
ops2 := new(op.Ops)
|
||||||
|
op.CallOp{Ops: ops2}.Add(ops)
|
||||||
|
|
||||||
The MacroOp records a list of operations to be executed later:
|
The MacroOp records a list of operations to be executed later:
|
||||||
|
|
||||||
ops := new(op.Ops)
|
ops := new(op.Ops)
|
||||||
@@ -105,6 +111,13 @@ type MacroOp struct {
|
|||||||
pc pc
|
pc pc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CallOp invokes all the operations from a separate
|
||||||
|
// operations list.
|
||||||
|
type CallOp struct {
|
||||||
|
// Ops is the list of operations to invoke.
|
||||||
|
Ops *Ops
|
||||||
|
}
|
||||||
|
|
||||||
// InvalidateOp requests a redraw at the given time. Use
|
// InvalidateOp requests a redraw at the given time. Use
|
||||||
// the zero value to request an immediate redraw.
|
// the zero value to request an immediate redraw.
|
||||||
type InvalidateOp struct {
|
type InvalidateOp struct {
|
||||||
@@ -134,6 +147,15 @@ type pc struct {
|
|||||||
refs int
|
refs int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the call to the operation list.
|
||||||
|
func (c CallOp) Add(o *Ops) {
|
||||||
|
if c.Ops == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
data := o.Write(opconst.TypeCallLen, c.Ops)
|
||||||
|
data[0] = byte(opconst.TypeCall)
|
||||||
|
}
|
||||||
|
|
||||||
// Push (save) the current operations state.
|
// Push (save) the current operations state.
|
||||||
func (s *StackOp) Push(o *Ops) {
|
func (s *StackOp) Push(o *Ops) {
|
||||||
if s.active {
|
if s.active {
|
||||||
|
|||||||
Reference in New Issue
Block a user