mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
gpu, op, internal/ops: add affine transformations
Add support for affine transformations. The key changes are outlined below. - Painting/clipping with rectangles is handled by, for complex transforms, creating clipping paths representing the transformed rectangle and using a larger bounding box. Cover/Blit shaders updated correspondingly to correctly map texture cordinates from the new bounding boxes. - Since path splitting must happen on CPU the transforms must happen CPU side as well - offsets removed from shaders. - Complex transforms will lead to different path splitting which means that GPU arrays can no longer be cached if the transform has changed. Thus the current transform is added as a key to the cache. - Add a public API to op for setting Affine transformations. There are a number of optimizations that could be explored further but which are left out now: - Caching also of CPU operations (e.g path splitting & transforms) and not only caching the GPU arrays. - Allow for re-use of cached GPU vertices if the transformation change is a pure offset / scaling since the splitting is then the same. Signed-off-by: Viktor <viktor.ogeman@gmail.com>
This commit is contained in:
@@ -117,10 +117,10 @@ type InvalidateOp struct {
|
||||
At time.Time
|
||||
}
|
||||
|
||||
// TransformOp applies a transform to the current transform.
|
||||
// TransformOp applies a transform to the current transform. The zero value
|
||||
// for TransformOp represents the identity transform.
|
||||
type TransformOp struct {
|
||||
// TODO: general transformations.
|
||||
offset f32.Point
|
||||
t f32.Affine2D
|
||||
}
|
||||
|
||||
// stack tracks the integer identities of StackOp and MacroOp
|
||||
@@ -264,39 +264,33 @@ func (r InvalidateOp) Add(o *Ops) {
|
||||
}
|
||||
}
|
||||
|
||||
// Offset the transformation.
|
||||
// Offset creates a TransformOp with the offset o.
|
||||
func Offset(o f32.Point) TransformOp {
|
||||
return TransformOp{t: f32.Affine2D{}.Offset(o)}
|
||||
}
|
||||
|
||||
// Affine creates a TransformOp representing the transformation a.
|
||||
func Affine(a f32.Affine2D) TransformOp {
|
||||
return TransformOp{t: a}
|
||||
}
|
||||
|
||||
// Offset the transfomraiton.
|
||||
func (t TransformOp) Offset(o f32.Point) TransformOp {
|
||||
return t.Multiply(TransformOp{o})
|
||||
}
|
||||
|
||||
// Invert the transformation.
|
||||
func (t TransformOp) Invert() TransformOp {
|
||||
return TransformOp{offset: t.offset.Mul(-1)}
|
||||
}
|
||||
|
||||
// Transform a point.
|
||||
func (t TransformOp) Transform(p f32.Point) f32.Point {
|
||||
return p.Add(t.offset)
|
||||
}
|
||||
|
||||
// Multiply by a transformation.
|
||||
func (t TransformOp) Multiply(t2 TransformOp) TransformOp {
|
||||
return TransformOp{
|
||||
offset: t.offset.Add(t2.offset),
|
||||
}
|
||||
t.t = t.t.Offset(o)
|
||||
return t
|
||||
}
|
||||
|
||||
func (t TransformOp) Add(o *Ops) {
|
||||
data := o.Write(opconst.TypeTransformLen)
|
||||
data[0] = byte(opconst.TypeTransform)
|
||||
bo := binary.LittleEndian
|
||||
// write it out as an affine matrix although we only support offset yet
|
||||
bo.PutUint32(data[1:], math.Float32bits(1.0))
|
||||
bo.PutUint32(data[1+4*1:], math.Float32bits(0))
|
||||
bo.PutUint32(data[1+4*2:], math.Float32bits(t.offset.X))
|
||||
bo.PutUint32(data[1+4*3:], math.Float32bits(0))
|
||||
bo.PutUint32(data[1+4*4:], math.Float32bits(1))
|
||||
bo.PutUint32(data[1+4*5:], math.Float32bits(t.offset.Y))
|
||||
a, b, c, d, e, f := t.t.Elems()
|
||||
bo.PutUint32(data[1:], math.Float32bits(a))
|
||||
bo.PutUint32(data[1+4*1:], math.Float32bits(b))
|
||||
bo.PutUint32(data[1+4*2:], math.Float32bits(c))
|
||||
bo.PutUint32(data[1+4*3:], math.Float32bits(d))
|
||||
bo.PutUint32(data[1+4*4:], math.Float32bits(e))
|
||||
bo.PutUint32(data[1+4*5:], math.Float32bits(f))
|
||||
}
|
||||
|
||||
func (s *stack) push() stackID {
|
||||
|
||||
Reference in New Issue
Block a user