Skip to content

Commit 896af05

Browse files
committed
updated xmobile backend
1 parent a0ba7b2 commit 896af05

8 files changed

Lines changed: 292 additions & 813 deletions

File tree

backend/xmobilebackend/clip.go

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,15 @@ func (b *XMobileBackend) Clip(pts [][2]float64) {
3333

3434
b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.buf)
3535
b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&b.ptsBuf[0]), len(b.ptsBuf)*4), gl.STREAM_DRAW)
36-
b.glctx.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, 0)
36+
b.glctx.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, 0)
3737

38-
b.glctx.UseProgram(b.sr.ID)
39-
b.glctx.Uniform4f(b.sr.Color, 1, 1, 1, 1)
40-
b.glctx.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh))
41-
b.glctx.Uniform1f(b.sr.GlobalAlpha, 1)
42-
b.glctx.EnableVertexAttribArray(b.sr.Vertex)
38+
b.glctx.UseProgram(b.shd.ID)
39+
b.glctx.Uniform4f(b.shd.Color, 1, 1, 1, 1)
40+
b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh))
41+
b.glctx.Uniform1f(b.shd.GlobalAlpha, 1)
42+
b.glctx.Uniform1i(b.shd.UseAlphaTex, 0)
43+
b.glctx.Uniform1i(b.shd.Func, shdFuncSolid)
44+
b.glctx.EnableVertexAttribArray(b.shd.Vertex)
4345

4446
b.glctx.ColorMask(false, false, false, false)
4547

@@ -61,7 +63,7 @@ func (b *XMobileBackend) Clip(pts [][2]float64) {
6163
b.glctx.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO)
6264
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
6365

64-
b.glctx.DisableVertexAttribArray(b.sr.Vertex)
66+
b.glctx.DisableVertexAttribArray(b.shd.Vertex)
6567

6668
b.glctx.ColorMask(true, true, true, true)
6769
b.glctx.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP)

backend/xmobilebackend/fill.go

Lines changed: 101 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ func (b *XMobileBackend) Clear(pts [4][2]float64) {
3333
float32(pts[2][0]), float32(pts[2][1]),
3434
float32(pts[3][0]), float32(pts[3][1])}
3535

36-
b.glctx.UseProgram(b.sr.ID)
37-
b.glctx.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh))
38-
b.glctx.Uniform4f(b.sr.Color, 0, 0, 0, 0)
39-
b.glctx.Uniform1f(b.sr.GlobalAlpha, 1)
36+
b.glctx.UseProgram(b.shd.ID)
37+
b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh))
38+
b.glctx.Uniform4f(b.shd.Color, 0, 0, 0, 0)
39+
b.glctx.Uniform1f(b.shd.GlobalAlpha, 1)
40+
b.glctx.Uniform1i(b.shd.UseAlphaTex, 0)
41+
b.glctx.Uniform1i(b.shd.Func, shdFuncSolid)
4042

4143
b.glctx.Disable(gl.BLEND)
4244

@@ -45,10 +47,10 @@ func (b *XMobileBackend) Clear(pts [4][2]float64) {
4547

4648
b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF)
4749

48-
b.glctx.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, 0)
49-
b.glctx.EnableVertexAttribArray(b.sr.Vertex)
50+
b.glctx.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, 0)
51+
b.glctx.EnableVertexAttribArray(b.shd.Vertex)
5052
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
51-
b.glctx.DisableVertexAttribArray(b.sr.Vertex)
53+
b.glctx.DisableVertexAttribArray(b.shd.Vertex)
5254

5355
b.glctx.StencilFunc(gl.ALWAYS, 0, 0xFF)
5456

@@ -70,6 +72,8 @@ func (b *XMobileBackend) clearRect(x, y, w, h int) {
7072
}
7173

7274
func extent(pts [][2]float64) (min, max vec) {
75+
max[0] = -math.MaxFloat64
76+
max[1] = -math.MaxFloat64
7377
min[0] = math.MaxFloat64
7478
min[1] = math.MaxFloat64
7579
for _, v := range pts {
@@ -111,7 +115,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
111115
b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&b.ptsBuf[0]), len(b.ptsBuf)*4), gl.STREAM_DRAW)
112116

113117
if !canOverlap || style.Color.A >= 255 {
114-
vertex := b.useShader(style)
118+
vertex, _ := b.useShader(style, false, 0)
115119

116120
b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF)
117121
b.glctx.EnableVertexAttribArray(vertex)
@@ -125,21 +129,23 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
125129
b.glctx.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
126130
b.glctx.StencilMask(0x01)
127131

128-
b.glctx.UseProgram(b.sr.ID)
129-
b.glctx.Uniform4f(b.sr.Color, 0, 0, 0, 0)
130-
b.glctx.Uniform2f(b.sr.CanvasSize, float32(b.fw), float32(b.fh))
131-
b.glctx.Uniform1f(b.sr.GlobalAlpha, 1)
132+
b.glctx.UseProgram(b.shd.ID)
133+
b.glctx.Uniform4f(b.shd.Color, 0, 0, 0, 0)
134+
b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh))
135+
b.glctx.Uniform1f(b.shd.GlobalAlpha, 1)
136+
b.glctx.Uniform1i(b.shd.UseAlphaTex, 0)
137+
b.glctx.Uniform1i(b.shd.Func, shdFuncSolid)
132138

133-
b.glctx.EnableVertexAttribArray(b.sr.Vertex)
134-
b.glctx.VertexAttribPointer(b.sr.Vertex, 2, gl.FLOAT, false, 0, 0)
139+
b.glctx.EnableVertexAttribArray(b.shd.Vertex)
140+
b.glctx.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, 0)
135141
b.glctx.DrawArrays(mode, 4, len(pts))
136-
b.glctx.DisableVertexAttribArray(b.sr.Vertex)
142+
b.glctx.DisableVertexAttribArray(b.shd.Vertex)
137143

138144
b.glctx.ColorMask(true, true, true, true)
139145

140146
b.glctx.StencilFunc(gl.EQUAL, 1, 0xFF)
141147

142-
vertex := b.useShader(style)
148+
vertex, _ := b.useShader(style, false, 0)
143149
b.glctx.EnableVertexAttribArray(vertex)
144150
b.glctx.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, 0)
145151

@@ -154,7 +160,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, ca
154160
}
155161

156162
if style.Blur > 0 {
157-
b.drawBlurred(style.Blur)
163+
b.drawBlurred(style.Blur, min, max)
158164
}
159165
}
160166

@@ -181,7 +187,7 @@ func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image
181187

182188
b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.buf)
183189

184-
vertex, alphaTexCoord := b.useAlphaShader(style, 1)
190+
vertex, alphaTexCoord := b.useShader(style, true, 1)
185191

186192
b.glctx.EnableVertexAttribArray(vertex)
187193
b.glctx.EnableVertexAttribArray(alphaTexCoord)
@@ -216,105 +222,103 @@ func (b *XMobileBackend) FillImageMask(style *backendbase.FillStyle, mask *image
216222
b.glctx.ActiveTexture(gl.TEXTURE0)
217223

218224
if style.Blur > 0 {
219-
b.drawBlurred(style.Blur)
225+
min, max := extent(pts[:])
226+
b.drawBlurred(style.Blur, min, max)
220227
}
221228
}
222229

223-
func (b *XMobileBackend) drawBlurred(blur float64) {
224-
b.glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
230+
func (b *XMobileBackend) drawBlurred(size float64, min, max vec) {
231+
b.offscr1.alpha = true
232+
b.offscr2.alpha = true
225233

226-
var kernel []float32
227-
var kernelBuf [255]float32
228-
var gs *gaussianShader
229-
if blur < 3 {
230-
gs = &b.gauss15r
231-
kernel = kernelBuf[:15]
232-
} else if blur < 12 {
233-
gs = &b.gauss63r
234-
kernel = kernelBuf[:63]
235-
} else {
236-
gs = &b.gauss127r
237-
kernel = kernelBuf[:127]
234+
// calculate box blur size
235+
fsize := math.Max(1, math.Floor(size))
236+
sizea := int(fsize)
237+
sizeb := sizea
238+
sizec := sizea
239+
if size-fsize > 0.333333333 {
240+
sizeb++
241+
}
242+
if size-fsize > 0.666666666 {
243+
sizec++
238244
}
239245

240-
gaussianKernel(blur, kernel)
241-
242-
b.offscr2.alpha = true
243-
b.enableTextureRenderTarget(&b.offscr2)
244-
b.glctx.ClearColor(0, 0, 0, 0)
245-
b.glctx.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
246-
247-
b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF)
246+
min[0] -= fsize * 3
247+
min[1] -= fsize * 3
248+
max[0] += fsize * 3
249+
max[1] += fsize * 3
250+
min[0] = math.Max(0.0, math.Min(b.fw, min[0]))
251+
min[1] = math.Max(0.0, math.Min(b.fh, min[1]))
252+
max[0] = math.Max(0.0, math.Min(b.fw, max[0]))
253+
max[1] = math.Max(0.0, math.Min(b.fh, max[1]))
248254

249255
b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.shadowBuf)
250-
data := [16]float32{0, 0, 0, float32(b.h), float32(b.w), float32(b.h), float32(b.w), 0, 0, 0, 0, 1, 1, 1, 1, 0}
256+
data := [16]float32{
257+
float32(min[0]), float32(min[1]),
258+
float32(min[0]), float32(max[1]),
259+
float32(max[0]), float32(max[1]),
260+
float32(max[0]), float32(min[1]),
261+
float32(min[0] / b.fw), 1 - float32(min[1]/b.fh),
262+
float32(min[0] / b.fw), 1 - float32(max[1]/b.fh),
263+
float32(max[0] / b.fw), 1 - float32(max[1]/b.fh),
264+
float32(max[0] / b.fw), 1 - float32(min[1]/b.fh),
265+
}
251266
b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&data[0]), len(data)*4), gl.STREAM_DRAW)
252267

253-
b.glctx.ActiveTexture(gl.TEXTURE0)
254-
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr1.tex)
255-
256-
b.glctx.UseProgram(gs.ID)
257-
b.glctx.Uniform1i(gs.Image, 0)
258-
b.glctx.Uniform2f(gs.CanvasSize, float32(b.fw), float32(b.fh))
259-
b.glctx.Uniform2f(gs.KernelScale, 1.0/float32(b.fw), 0.0)
260-
b.glctx.Uniform1fv(gs.Kernel, kernel)
261-
b.glctx.VertexAttribPointer(gs.Vertex, 2, gl.FLOAT, false, 0, 0)
262-
b.glctx.VertexAttribPointer(gs.TexCoord, 2, gl.FLOAT, false, 0, 8*4)
263-
b.glctx.EnableVertexAttribArray(gs.Vertex)
264-
b.glctx.EnableVertexAttribArray(gs.TexCoord)
265-
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
266-
b.glctx.DisableVertexAttribArray(gs.Vertex)
267-
b.glctx.DisableVertexAttribArray(gs.TexCoord)
268+
b.glctx.UseProgram(b.shd.ID)
269+
b.glctx.Uniform1i(b.shd.Image, 0)
270+
b.glctx.Uniform2f(b.shd.CanvasSize, float32(b.fw), float32(b.fh))
271+
b.glctx.Uniform1i(b.shd.UseAlphaTex, 0)
272+
b.glctx.Uniform1i(b.shd.Func, shdFuncBoxBlur)
268273

269-
b.glctx.StencilFunc(gl.ALWAYS, 0, 0xFF)
274+
b.glctx.VertexAttribPointer(b.shd.Vertex, 2, gl.FLOAT, false, 0, 0)
275+
b.glctx.VertexAttribPointer(b.shd.TexCoord, 2, gl.FLOAT, false, 0, 8*4)
276+
b.glctx.EnableVertexAttribArray(b.shd.Vertex)
277+
b.glctx.EnableVertexAttribArray(b.shd.TexCoord)
270278

271-
b.disableTextureRenderTarget()
279+
b.glctx.Disable(gl.BLEND)
272280

273-
b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF)
281+
b.glctx.ActiveTexture(gl.TEXTURE0)
274282

275-
b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.shadowBuf)
276-
data = [16]float32{0, 0, 0, float32(b.h), float32(b.w), float32(b.h), float32(b.w), 0, 0, 0, 0, 1, 1, 1, 1, 0}
277-
b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&data[0]), len(data)*4), gl.STREAM_DRAW)
283+
b.glctx.ClearColor(0, 0, 0, 0)
278284

279-
b.glctx.ActiveTexture(gl.TEXTURE0)
285+
b.enableTextureRenderTarget(&b.offscr2)
286+
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr1.tex)
287+
b.glctx.Clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
288+
b.box3(sizea, 0, false)
289+
b.enableTextureRenderTarget(&b.offscr1)
280290
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr2.tex)
291+
b.box3(sizeb, -0.5, false)
292+
b.enableTextureRenderTarget(&b.offscr2)
293+
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr1.tex)
294+
b.box3(sizec, 0, false)
295+
b.enableTextureRenderTarget(&b.offscr1)
296+
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr2.tex)
297+
b.box3(sizea, 0, true)
298+
b.enableTextureRenderTarget(&b.offscr2)
299+
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr1.tex)
300+
b.box3(sizeb, -0.5, true)
301+
b.glctx.Enable(gl.BLEND)
302+
b.glctx.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
303+
b.disableTextureRenderTarget()
304+
b.glctx.BindTexture(gl.TEXTURE_2D, b.offscr2.tex)
305+
b.box3(sizec, 0, true)
281306

282-
b.glctx.UseProgram(gs.ID)
283-
b.glctx.Uniform1i(gs.Image, 0)
284-
b.glctx.Uniform2f(gs.CanvasSize, float32(b.fw), float32(b.fh))
285-
b.glctx.Uniform2f(gs.KernelScale, 0.0, 1.0/float32(b.fh))
286-
b.glctx.Uniform1fv(gs.Kernel, kernel)
287-
b.glctx.VertexAttribPointer(gs.Vertex, 2, gl.FLOAT, false, 0, 0)
288-
b.glctx.VertexAttribPointer(gs.TexCoord, 2, gl.FLOAT, false, 0, 8*4)
289-
b.glctx.EnableVertexAttribArray(gs.Vertex)
290-
b.glctx.EnableVertexAttribArray(gs.TexCoord)
291-
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
292-
b.glctx.DisableVertexAttribArray(gs.Vertex)
293-
b.glctx.DisableVertexAttribArray(gs.TexCoord)
294-
295-
b.glctx.StencilFunc(gl.ALWAYS, 0, 0xFF)
307+
b.glctx.DisableVertexAttribArray(b.shd.Vertex)
308+
b.glctx.DisableVertexAttribArray(b.shd.TexCoord)
296309

297310
b.glctx.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
298311
}
299312

300-
func gaussianKernel(stddev float64, target []float32) {
301-
stddevSqr := stddev * stddev
302-
center := float64(len(target) / 2)
303-
factor := 1.0 / math.Sqrt(2*math.Pi*stddevSqr)
304-
for i := range target {
305-
x := float64(i) - center
306-
target[i] = float32(factor * math.Pow(math.E, -x*x/(2*stddevSqr)))
307-
}
308-
// normalizeKernel(target)
309-
}
310-
311-
func normalizeKernel(kernel []float32) {
312-
var sum float32
313-
for _, v := range kernel {
314-
sum += v
315-
}
316-
factor := 1.0 / sum
317-
for i := range kernel {
318-
kernel[i] *= factor
313+
func (b *XMobileBackend) box3(size int, offset float32, vertical bool) {
314+
b.glctx.Uniform1i(b.shd.BoxSize, size)
315+
if vertical {
316+
b.glctx.Uniform1i(b.shd.BoxVertical, 1)
317+
b.glctx.Uniform1f(b.shd.BoxScale, 1/float32(b.fh))
318+
} else {
319+
b.glctx.Uniform1i(b.shd.BoxVertical, 0)
320+
b.glctx.Uniform1f(b.shd.BoxScale, 1/float32(b.fw))
319321
}
322+
b.glctx.Uniform1f(b.shd.BoxOffset, offset)
323+
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
320324
}

backend/xmobilebackend/gen/gen.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,12 @@ func rewrite(filename, src string) (string, string) {
142142
params[2] = params[2][1 : len(params[2])-3]
143143
return "b.glctx.Uniform1fv(" + params[0] + ", " + params[2] + ")"
144144
})
145+
src = rewriteCalls(src, "b.glctx.Uniform1i", func(params []string) string {
146+
if strings.HasPrefix(params[1], "int32(") {
147+
params[1] = params[1][6 : len(params[1])-1]
148+
}
149+
return "b.glctx.Uniform1i(" + strings.Join(params, ",") + ")"
150+
})
145151
src = rewriteCalls(src, "b.glctx.UniformMatrix3fv", func(params []string) string {
146152
return "b.glctx.UniformMatrix3fv(" + params[0] + ", " + params[3][1:len(params[3])-3] + "[:])"
147153
})
@@ -364,23 +370,18 @@ func byteSlice(ptr unsafe.Pointer, size int) []byte {
364370

365371
func rewriteShaders(src string) string {
366372
src = strings.Replace(src,
367-
`import (
368-
"bytes"
369-
"fmt"
370-
"strings"
371-
)
373+
`package xmobilebackend
372374
`,
373-
`import (
374-
"bytes"
375-
"fmt"
376-
"strings"
375+
`package xmobilebackend
377376
377+
import (
378378
"golang.org/x/mobile/gl"
379379
)
380380
`, 1)
381381

382382
src = strings.Replace(src, "uint32", "gl.Attrib", -1)
383383
src = strings.Replace(src, "int32", "gl.Uniform", -1)
384+
src = strings.Replace(src, "shdFuncSolid gl.Uniform", "shdFuncSolid int", -1)
384385

385386
return src
386387
}

backend/xmobilebackend/gradients.go

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ type RadialGradient struct {
2424
}
2525

2626
type gradient struct {
27-
b *XMobileBackend
28-
tex gl.Texture
29-
loaded bool
27+
b *XMobileBackend
28+
tex gl.Texture
3029
}
3130

3231
func (b *XMobileBackend) LoadLinearGradient(data backendbase.Gradient) backendbase.LinearGradient {
@@ -86,10 +85,6 @@ func (rg *RadialGradient) Replace(data backendbase.Gradient) { rg.load(data) }
8685

8786
func (g *gradient) load(stops backendbase.Gradient) {
8887
b := g.b
89-
if g.loaded {
90-
return
91-
}
92-
9388
g.b.activate()
9489

9590
b.glctx.ActiveTexture(gl.TEXTURE0)
@@ -106,5 +101,4 @@ func (g *gradient) load(stops backendbase.Gradient) {
106101
}
107102

108103
b.glctx.TexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 2048, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels[0:])
109-
g.loaded = true
110104
}

0 commit comments

Comments
 (0)