mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
op/clip, gpu: split complex curves in package gpu instead
This is a first step towards supporting affine drawing transforms. The rendering algorithm relies on quadratic curves that do not cross x = 0 more than once, thus curves must be split after any rotation/shear transforms. Move this logic and the generation of vertices to package gpu. Also close all curves and draw zero-width edges as preparation for transform since the will no longer implicitly be vertical with no effect. This commit will severely affect performance since vertexes are now transformed also for cached items, using cpu resources. Signed-off-by: Viktor <viktor.ogeman@gmail.com>
This commit is contained in:
+42
-9
@@ -6,13 +6,14 @@ package gpu
|
||||
// Pathfinder (https://github.com/servo/pathfinder).
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"image"
|
||||
"math"
|
||||
"unsafe"
|
||||
|
||||
"gioui.org/f32"
|
||||
"gioui.org/gpu/backend"
|
||||
"gioui.org/internal/f32color"
|
||||
"gioui.org/internal/path"
|
||||
gunsafe "gioui.org/internal/unsafe"
|
||||
)
|
||||
|
||||
@@ -104,9 +105,33 @@ type pathData struct {
|
||||
data backend.Buffer
|
||||
}
|
||||
|
||||
// vertex data suitable for passing to vertex programs.
|
||||
type vertex struct {
|
||||
// Corner encodes the corner: +0.5 for south, +.25 for east.
|
||||
Corner float32
|
||||
MaxY float32
|
||||
FromX, FromY float32
|
||||
CtrlX, CtrlY float32
|
||||
ToX, ToY float32
|
||||
}
|
||||
|
||||
func (v vertex) encode(d []byte, maxy uint32) {
|
||||
bo := binary.LittleEndian
|
||||
bo.PutUint32(d[0:], math.Float32bits(v.Corner))
|
||||
bo.PutUint32(d[4:], maxy)
|
||||
bo.PutUint32(d[8:], math.Float32bits(v.FromX))
|
||||
bo.PutUint32(d[12:], math.Float32bits(v.FromY))
|
||||
bo.PutUint32(d[16:], math.Float32bits(v.CtrlX))
|
||||
bo.PutUint32(d[20:], math.Float32bits(v.CtrlY))
|
||||
bo.PutUint32(d[24:], math.Float32bits(v.ToX))
|
||||
bo.PutUint32(d[28:], math.Float32bits(v.ToY))
|
||||
}
|
||||
|
||||
const (
|
||||
// Number of path quads per draw batch.
|
||||
pathBatchSize = 10000
|
||||
// Size of a vertex as sent to gpu
|
||||
vertStride = 7*4 + 2*2
|
||||
)
|
||||
|
||||
func newPather(ctx backend.Device) *pather {
|
||||
@@ -152,11 +177,11 @@ func newStenciler(ctx backend.Device) *stenciler {
|
||||
panic(err)
|
||||
}
|
||||
progLayout, err := ctx.NewInputLayout(shader_stencil_vert, []backend.InputDesc{
|
||||
{Type: backend.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).Corner))},
|
||||
{Type: backend.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).MaxY))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).FromX))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).CtrlX))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*path.Vertex)(nil)).ToX))},
|
||||
{Type: backend.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).Corner))},
|
||||
{Type: backend.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).MaxY))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).FromX))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).CtrlX))},
|
||||
{Type: backend.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).ToX))},
|
||||
})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
@@ -269,7 +294,7 @@ func buildPath(ctx backend.Device, p []byte) *pathData {
|
||||
panic(err)
|
||||
}
|
||||
return &pathData{
|
||||
ncurves: len(p) / path.VertStride,
|
||||
ncurves: len(p) / vertStride,
|
||||
data: buf,
|
||||
}
|
||||
}
|
||||
@@ -329,8 +354,8 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
|
||||
if max := pathBatchSize; batch > max {
|
||||
batch = max
|
||||
}
|
||||
off := path.VertStride * start * 4
|
||||
s.ctx.BindVertexBuffer(data.data, path.VertStride, off)
|
||||
off := vertStride * start * 4
|
||||
s.ctx.BindVertexBuffer(data.data, vertStride, off)
|
||||
s.ctx.DrawElements(backend.DrawModeTriangles, 0, batch*6)
|
||||
start += batch
|
||||
}
|
||||
@@ -358,3 +383,11 @@ func (c *coverer) cover(z float32, mat materialType, col f32color.RGBA, scale, o
|
||||
p.UploadUniforms()
|
||||
c.ctx.DrawArrays(backend.DrawModeTriangleStrip, 0, 4)
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Check that struct vertex has the expected size and
|
||||
// that it contains no padding.
|
||||
if unsafe.Sizeof(*(*vertex)(nil)) != vertStride {
|
||||
panic("unexpected struct size")
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user