aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/gpu/path.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/gpu/path.go')
-rw-r--r--vendor/gioui.org/gpu/path.go254
1 files changed, 129 insertions, 125 deletions
diff --git a/vendor/gioui.org/gpu/path.go b/vendor/gioui.org/gpu/path.go
index 2dd5875..5fd73cf 100644
--- a/vendor/gioui.org/gpu/path.go
+++ b/vendor/gioui.org/gpu/path.go
@@ -12,13 +12,15 @@ import (
"unsafe"
"gioui.org/f32"
- "gioui.org/gpu/backend"
+ "gioui.org/gpu/internal/driver"
+ "gioui.org/internal/byteslice"
"gioui.org/internal/f32color"
- gunsafe "gioui.org/internal/unsafe"
+ "gioui.org/shader"
+ "gioui.org/shader/gio"
)
type pather struct {
- ctx backend.Device
+ ctx driver.Device
viewport image.Point
@@ -27,28 +29,28 @@ type pather struct {
}
type coverer struct {
- ctx backend.Device
- prog [2]*program
- texUniforms *coverTexUniforms
- colUniforms *coverColUniforms
- layout backend.InputLayout
+ ctx driver.Device
+ pipelines [3]*pipeline
+ texUniforms *coverTexUniforms
+ colUniforms *coverColUniforms
+ linearGradientUniforms *coverLinearGradientUniforms
}
type coverTexUniforms struct {
- vert struct {
- coverUniforms
- _ [12]byte // Padding to multiple of 16.
- }
+ coverUniforms
+ _ [12]byte // Padding to multiple of 16.
}
type coverColUniforms struct {
- vert struct {
- coverUniforms
- _ [12]byte // Padding to multiple of 16.
- }
- frag struct {
- colorUniforms
- }
+ coverUniforms
+ _ [128 - unsafe.Sizeof(coverUniforms{}) - unsafe.Sizeof(colorUniforms{})]byte // Padding to 128 bytes.
+ colorUniforms
+}
+
+type coverLinearGradientUniforms struct {
+ coverUniforms
+ _ [128 - unsafe.Sizeof(coverUniforms{}) - unsafe.Sizeof(gradientUniforms{})]byte // Padding to 128.
+ gradientUniforms
}
type coverUniforms struct {
@@ -60,28 +62,24 @@ type coverUniforms struct {
}
type stenciler struct {
- ctx backend.Device
- prog struct {
- prog *program
+ ctx driver.Device
+ pipeline struct {
+ pipeline *pipeline
uniforms *stencilUniforms
- layout backend.InputLayout
}
- iprog struct {
- prog *program
+ ipipeline struct {
+ pipeline *pipeline
uniforms *intersectUniforms
- layout backend.InputLayout
}
fbos fboSet
intersections fboSet
- indexBuf backend.Buffer
+ indexBuf driver.Buffer
}
type stencilUniforms struct {
- vert struct {
- transform [4]float32
- pathOffset [2]float32
- _ [8]byte // Padding to multiple of 16.
- }
+ transform [4]float32
+ pathOffset [2]float32
+ _ [8]byte // Padding to multiple of 16.
}
type intersectUniforms struct {
@@ -97,13 +95,12 @@ type fboSet struct {
type stencilFBO struct {
size image.Point
- fbo backend.Framebuffer
- tex backend.Texture
+ tex driver.Texture
}
type pathData struct {
ncurves int
- data backend.Buffer
+ data driver.Buffer
}
// vertex data suitable for passing to vertex programs.
@@ -132,10 +129,10 @@ const (
// Number of path quads per draw batch.
pathBatchSize = 10000
// Size of a vertex as sent to gpu
- vertStride = 7*4 + 2*2
+ vertStride = 8 * 4
)
-func newPather(ctx backend.Device) *pather {
+func newPather(ctx driver.Device) *pather {
return &pather{
ctx: ctx,
stenciler: newStenciler(ctx),
@@ -143,25 +140,24 @@ func newPather(ctx backend.Device) *pather {
}
}
-func newCoverer(ctx backend.Device) *coverer {
+func newCoverer(ctx driver.Device) *coverer {
c := &coverer{
ctx: ctx,
}
c.colUniforms = new(coverColUniforms)
c.texUniforms = new(coverTexUniforms)
- prog, layout, err := createColorPrograms(ctx, shader_cover_vert, shader_cover_frag,
- [2]interface{}{&c.colUniforms.vert, &c.texUniforms.vert},
- [2]interface{}{&c.colUniforms.frag, nil},
+ c.linearGradientUniforms = new(coverLinearGradientUniforms)
+ pipelines, err := createColorPrograms(ctx, gio.Shader_cover_vert, gio.Shader_cover_frag,
+ [3]interface{}{c.colUniforms, c.linearGradientUniforms, c.texUniforms},
)
if err != nil {
panic(err)
}
- c.prog = prog
- c.layout = layout
+ c.pipelines = pipelines
return c
}
-func newStenciler(ctx backend.Device) *stenciler {
+func newStenciler(ctx driver.Device) *stenciler {
// Allocate a suitably large index buffer for drawing paths.
indices := make([]uint16, pathBatchSize*6)
for i := 0; i < pathBatchSize; i++ {
@@ -173,51 +169,80 @@ func newStenciler(ctx backend.Device) *stenciler {
indices[i*6+4] = i*4 + 1
indices[i*6+5] = i*4 + 3
}
- indexBuf, err := ctx.NewImmutableBuffer(backend.BufferBindingIndices, gunsafe.BytesView(indices))
+ indexBuf, err := ctx.NewImmutableBuffer(driver.BufferBindingIndices, byteslice.Slice(indices))
if err != nil {
panic(err)
}
- progLayout, err := ctx.NewInputLayout(shader_stencil_vert, []backend.InputDesc{
- {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)
+ progLayout := driver.VertexLayout{
+ Inputs: []driver.InputDesc{
+ {Type: shader.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).Corner))},
+ {Type: shader.DataTypeFloat, Size: 1, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).MaxY))},
+ {Type: shader.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).FromX))},
+ {Type: shader.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).CtrlX))},
+ {Type: shader.DataTypeFloat, Size: 2, Offset: int(unsafe.Offsetof((*(*vertex)(nil)).ToX))},
+ },
+ Stride: vertStride,
}
- iprogLayout, err := ctx.NewInputLayout(shader_intersect_vert, []backend.InputDesc{
- {Type: backend.DataTypeFloat, Size: 2, Offset: 0},
- {Type: backend.DataTypeFloat, Size: 2, Offset: 4 * 2},
- })
- if err != nil {
- panic(err)
+ iprogLayout := driver.VertexLayout{
+ Inputs: []driver.InputDesc{
+ {Type: shader.DataTypeFloat, Size: 2, Offset: 0},
+ {Type: shader.DataTypeFloat, Size: 2, Offset: 4 * 2},
+ },
+ Stride: 4 * 4,
}
st := &stenciler{
ctx: ctx,
indexBuf: indexBuf,
}
- prog, err := ctx.NewProgram(shader_stencil_vert, shader_stencil_frag)
+ vsh, fsh, err := newShaders(ctx, gio.Shader_stencil_vert, gio.Shader_stencil_frag)
if err != nil {
panic(err)
}
- st.prog.uniforms = new(stencilUniforms)
- vertUniforms := newUniformBuffer(ctx, &st.prog.uniforms.vert)
- st.prog.prog = newProgram(prog, vertUniforms, nil)
- st.prog.layout = progLayout
- iprog, err := ctx.NewProgram(shader_intersect_vert, shader_intersect_frag)
+ defer vsh.Release()
+ defer fsh.Release()
+ st.pipeline.uniforms = new(stencilUniforms)
+ vertUniforms := newUniformBuffer(ctx, st.pipeline.uniforms)
+ pipe, err := st.ctx.NewPipeline(driver.PipelineDesc{
+ VertexShader: vsh,
+ FragmentShader: fsh,
+ VertexLayout: progLayout,
+ BlendDesc: driver.BlendDesc{
+ Enable: true,
+ SrcFactor: driver.BlendFactorOne,
+ DstFactor: driver.BlendFactorOne,
+ },
+ PixelFormat: driver.TextureFormatFloat,
+ Topology: driver.TopologyTriangles,
+ })
+ st.pipeline.pipeline = &pipeline{pipe, vertUniforms}
+ if err != nil {
+ panic(err)
+ }
+ vsh, fsh, err = newShaders(ctx, gio.Shader_intersect_vert, gio.Shader_intersect_frag)
if err != nil {
panic(err)
}
- st.iprog.uniforms = new(intersectUniforms)
- vertUniforms = newUniformBuffer(ctx, &st.iprog.uniforms.vert)
- st.iprog.prog = newProgram(iprog, vertUniforms, nil)
- st.iprog.layout = iprogLayout
+ defer vsh.Release()
+ defer fsh.Release()
+ st.ipipeline.uniforms = new(intersectUniforms)
+ vertUniforms = newUniformBuffer(ctx, &st.ipipeline.uniforms.vert)
+ ipipe, err := st.ctx.NewPipeline(driver.PipelineDesc{
+ VertexShader: vsh,
+ FragmentShader: fsh,
+ VertexLayout: iprogLayout,
+ BlendDesc: driver.BlendDesc{
+ Enable: true,
+ SrcFactor: driver.BlendFactorDstColor,
+ DstFactor: driver.BlendFactorZero,
+ },
+ PixelFormat: driver.TextureFormatFloat,
+ Topology: driver.TopologyTriangleStrip,
+ })
+ st.ipipeline.pipeline = &pipeline{ipipe, vertUniforms}
return st
}
-func (s *fboSet) resize(ctx backend.Device, sizes []image.Point) {
+func (s *fboSet) resize(ctx driver.Device, sizes []image.Point) {
// Add fbos.
for i := len(s.fbos); i < len(sizes); i++ {
s.fbos = append(s.fbos, stencilFBO{})
@@ -231,38 +256,25 @@ func (s *fboSet) resize(ctx backend.Device, sizes []image.Point) {
waste := float32(sz.X*sz.Y) / float32(f.size.X*f.size.Y)
resize = resize || waste > 1.2
if resize {
- if f.fbo != nil {
- f.fbo.Release()
+ if f.tex != nil {
f.tex.Release()
}
- tex, err := ctx.NewTexture(backend.TextureFormatFloat, sz.X, sz.Y, backend.FilterNearest, backend.FilterNearest,
- backend.BufferBindingTexture|backend.BufferBindingFramebuffer)
- if err != nil {
- panic(err)
- }
- fbo, err := ctx.NewFramebuffer(tex, 0)
+ tex, err := ctx.NewTexture(driver.TextureFormatFloat, sz.X, sz.Y, driver.FilterNearest, driver.FilterNearest,
+ driver.BufferBindingTexture|driver.BufferBindingFramebuffer)
if err != nil {
panic(err)
}
f.size = sz
f.tex = tex
- f.fbo = fbo
}
}
// Delete extra fbos.
s.delete(ctx, len(sizes))
}
-func (s *fboSet) invalidate(ctx backend.Device) {
- for _, f := range s.fbos {
- f.fbo.Invalidate()
- }
-}
-
-func (s *fboSet) delete(ctx backend.Device, idx int) {
+func (s *fboSet) delete(ctx driver.Device, idx int) {
for i := idx; i < len(s.fbos); i++ {
f := s.fbos[i]
- f.fbo.Release()
f.tex.Release()
}
s.fbos = s.fbos[:idx]
@@ -270,10 +282,9 @@ func (s *fboSet) delete(ctx backend.Device, idx int) {
func (s *stenciler) release() {
s.fbos.delete(s.ctx, 0)
- s.prog.layout.Release()
- s.prog.prog.Release()
- s.iprog.layout.Release()
- s.iprog.prog.Release()
+ s.intersections.delete(s.ctx, 0)
+ s.pipeline.pipeline.Release()
+ s.ipipeline.pipeline.Release()
s.indexBuf.Release()
}
@@ -283,14 +294,13 @@ func (p *pather) release() {
}
func (c *coverer) release() {
- for _, p := range c.prog {
+ for _, p := range c.pipelines {
p.Release()
}
- c.layout.Release()
}
-func buildPath(ctx backend.Device, p []byte) pathData {
- buf, err := ctx.NewImmutableBuffer(backend.BufferBindingVertices, p)
+func buildPath(ctx driver.Device, p []byte) pathData {
+ buf, err := ctx.NewImmutableBuffer(driver.BufferBindingVertices, p)
if err != nil {
panic(err)
}
@@ -313,17 +323,10 @@ func (p *pather) stencilPath(bounds image.Rectangle, offset f32.Point, uv image.
}
func (s *stenciler) beginIntersect(sizes []image.Point) {
- s.ctx.BlendFunc(backend.BlendFactorDstColor, backend.BlendFactorZero)
// 8 bit coverage is enough, but OpenGL ES only supports single channel
// floating point formats. Replace with GL_RGB+GL_UNSIGNED_BYTE if
// no floating point support is available.
s.intersections.resize(s.ctx, sizes)
- s.ctx.BindProgram(s.iprog.prog.prog)
-}
-
-func (s *stenciler) invalidateFBO() {
- s.intersections.invalidate(s.ctx)
- s.fbos.invalidate(s.ctx)
}
func (s *stenciler) cover(idx int) stencilFBO {
@@ -331,11 +334,7 @@ func (s *stenciler) cover(idx int) stencilFBO {
}
func (s *stenciler) begin(sizes []image.Point) {
- s.ctx.BlendFunc(backend.BlendFactorOne, backend.BlendFactorOne)
s.fbos.resize(s.ctx, sizes)
- s.ctx.BindProgram(s.prog.prog.prog)
- s.ctx.BindInputLayout(s.prog.layout)
- s.ctx.BindIndexBuffer(s.indexBuf)
}
func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv image.Point, data pathData) {
@@ -344,9 +343,9 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
texSize := f32.Point{X: float32(bounds.Dx()), Y: float32(bounds.Dy())}
scale := f32.Point{X: 2 / texSize.X, Y: 2 / texSize.Y}
orig := f32.Point{X: -1 - float32(bounds.Min.X)*2/texSize.X, Y: -1 - float32(bounds.Min.Y)*2/texSize.Y}
- s.prog.uniforms.vert.transform = [4]float32{scale.X, scale.Y, orig.X, orig.Y}
- s.prog.uniforms.vert.pathOffset = [2]float32{offset.X, offset.Y}
- s.prog.prog.UploadUniforms()
+ s.pipeline.uniforms.transform = [4]float32{scale.X, scale.Y, orig.X, orig.Y}
+ s.pipeline.uniforms.pathOffset = [2]float32{offset.X, offset.Y}
+ s.pipeline.pipeline.UploadUniforms(s.ctx)
// Draw in batches that fit in uint16 indices.
start := 0
nquads := data.ncurves / 4
@@ -356,35 +355,40 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima
batch = max
}
off := vertStride * start * 4
- s.ctx.BindVertexBuffer(data.data, vertStride, off)
- s.ctx.DrawElements(backend.DrawModeTriangles, 0, batch*6)
+ s.ctx.BindVertexBuffer(data.data, off)
+ s.ctx.DrawElements(0, batch*6)
start += batch
}
}
-func (p *pather) cover(z float32, mat materialType, col f32color.RGBA, scale, off f32.Point, uvTrans f32.Affine2D, coverScale, coverOff f32.Point) {
- p.coverer.cover(z, mat, col, scale, off, uvTrans, coverScale, coverOff)
+func (p *pather) cover(mat materialType, col f32color.RGBA, col1, col2 f32color.RGBA, scale, off f32.Point, uvTrans f32.Affine2D, coverScale, coverOff f32.Point) {
+ p.coverer.cover(mat, col, col1, col2, scale, off, uvTrans, coverScale, coverOff)
}
-func (c *coverer) cover(z float32, mat materialType, col f32color.RGBA, scale, off f32.Point, uvTrans f32.Affine2D, coverScale, coverOff f32.Point) {
- p := c.prog[mat]
- c.ctx.BindProgram(p.prog)
+func (c *coverer) cover(mat materialType, col f32color.RGBA, col1, col2 f32color.RGBA, scale, off f32.Point, uvTrans f32.Affine2D, coverScale, coverOff f32.Point) {
var uniforms *coverUniforms
switch mat {
case materialColor:
- c.colUniforms.frag.color = col
- uniforms = &c.colUniforms.vert.coverUniforms
+ c.colUniforms.color = col
+ uniforms = &c.colUniforms.coverUniforms
+ case materialLinearGradient:
+ c.linearGradientUniforms.color1 = col1
+ c.linearGradientUniforms.color2 = col2
+
+ t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
+ c.linearGradientUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
+ c.linearGradientUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
+ uniforms = &c.linearGradientUniforms.coverUniforms
case materialTexture:
t1, t2, t3, t4, t5, t6 := uvTrans.Elems()
- c.texUniforms.vert.uvTransformR1 = [4]float32{t1, t2, t3, 0}
- c.texUniforms.vert.uvTransformR2 = [4]float32{t4, t5, t6, 0}
- uniforms = &c.texUniforms.vert.coverUniforms
+ c.texUniforms.uvTransformR1 = [4]float32{t1, t2, t3, 0}
+ c.texUniforms.uvTransformR2 = [4]float32{t4, t5, t6, 0}
+ uniforms = &c.texUniforms.coverUniforms
}
- uniforms.z = z
uniforms.transform = [4]float32{scale.X, scale.Y, off.X, off.Y}
uniforms.uvCoverTransform = [4]float32{coverScale.X, coverScale.Y, coverOff.X, coverOff.Y}
- p.UploadUniforms()
- c.ctx.DrawArrays(backend.DrawModeTriangleStrip, 0, 4)
+ c.pipelines[mat].UploadUniforms(c.ctx)
+ c.ctx.DrawArrays(0, 4)
}
func init() {