diff --git a/gpu/caches.go b/gpu/caches.go index 3ad5ba1b..b4ab29db 100644 --- a/gpu/caches.go +++ b/gpu/caches.go @@ -27,9 +27,10 @@ type opCache struct { type opCacheValue struct { data pathData - // cpuData is the retained data, if kept by the compute renderer. - cpuData []byte - bounds f32.Rectangle + // computePath is the encoded path for compute. + computePath encoder + + bounds f32.Rectangle // the fields below are handled by opCache key ops.Key keep bool diff --git a/gpu/compute.go b/gpu/compute.go index 2df1dfa2..811a7ab2 100644 --- a/gpu/compute.go +++ b/gpu/compute.go @@ -409,7 +409,9 @@ func (g *compute) encodeClipStack(clip, bounds f32.Rectangle, p *pathOp) int { } if p != nil && p.path { pathData, _ := g.drawOps.pathCache.get(p.pathKey) - g.encodePath(p.off, pathData.cpuData) + g.enc.transform(f32.Affine2D{}.Offset(p.off)) + g.enc.append(pathData.computePath) + g.enc.transform(f32.Affine2D{}.Offset(p.off.Mul(-1))) } else { g.enc.rect(bounds, false) } @@ -419,7 +421,8 @@ func (g *compute) encodeClipStack(clip, bounds f32.Rectangle, p *pathOp) int { // encodePath takes a Path encoded with quadSplitter and encode it for elements.comp. // This is certainly wasteful, but minimizes implementation differences to the old // renderer. -func (g *compute) encodePath(off f32.Point, p []byte) { +func encodePath(p []byte) encoder { + var enc encoder for len(p) > 0 { // p contains quadratic curves encoded in vertex structs. vertex := p[:vertStride] @@ -436,12 +439,13 @@ func (g *compute) encodePath(off f32.Point, p []byte) { math.Float32frombits(bo.Uint32(vertex[24:])), math.Float32frombits(bo.Uint32(vertex[28:])), ) - g.enc.quad(from.Add(off), ctrl.Add(off), to.Add(off), false) + enc.quad(from, ctrl, to, false) // The vertex is duplicated 4 times, one for each corner of quads drawn // by the old renderer. p = p[vertStride*4:] } + return enc } func (g *compute) render(tileDims image.Point) error { @@ -696,6 +700,12 @@ func (e *encoder) numElements() int { return len(e.scene) / sceneElemSize } +func (e *encoder) append(e2 encoder) { + e.scene = append(e.scene, e2.scene...) + e.npath += e2.npath + e.npathseg += e2.npathseg +} + func (e *encoder) transform(m f32.Affine2D) { sx, hx, ox, hy, sy, oy := m.Elems() cmd := make([]byte, sceneElemSize) diff --git a/gpu/gpu.go b/gpu/gpu.go index eaa000f5..0079dfd1 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -824,15 +824,14 @@ func (d *drawOps) collect(ctx backend.Device, cache *resourceCache, root *op.Ops for _, p := range d.pathOps { if v, exists := d.pathCache.get(p.pathKey); !exists || v.data.data == nil { data := buildPath(ctx, p.pathVerts) - var pathVerts []byte + var computePath encoder if d.retainPathData { - pathVerts = make([]byte, len(p.pathVerts)) - copy(pathVerts, p.pathVerts) + computePath = encodePath(p.pathVerts) } d.pathCache.put(p.pathKey, opCacheValue{ - data: data, - bounds: p.bounds, - cpuData: pathVerts, + data: data, + bounds: p.bounds, + computePath: computePath, }) } p.pathVerts = nil