diff options
Diffstat (limited to 'vendor/gioui.org/gpu/path.go')
-rw-r--r-- | vendor/gioui.org/gpu/path.go | 254 |
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() { |