small performance improvements

This commit is contained in:
Thomas Friedel 2019-05-23 16:32:03 +02:00
parent b5212c916a
commit 5ce888f8b9
10 changed files with 75 additions and 32 deletions

View file

@ -18,7 +18,7 @@ type Backend interface {
LoadRadialGradient(data Gradient) RadialGradient
Clear(pts [4][2]float64)
Fill(style *FillStyle, pts [][2]float64)
Fill(style *FillStyle, pts [][2]float64, canOverlap bool)
DrawImage(dimg Image, sx, sy, sw, sh float64, pts [4][2]float64, alpha float64)
FillImageMask(style *FillStyle, mask *image.Alpha, pts [4][2]float64) // pts must have four points

View file

@ -43,18 +43,21 @@ func (b *GoGLBackend) Clip(pts [][2]float64) {
gl.ColorMask(false, false, false, false)
// set bit 2 in the stencil buffer in the given shape
gl.StencilMask(0x04)
gl.StencilFunc(gl.ALWAYS, 4, 0x04)
gl.StencilFunc(gl.ALWAYS, 4, 0)
gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
gl.DrawArrays(mode, 4, int32(len(pts)))
// on entire screen, where neither bit 1 or 2 are set, invert bit 1
gl.StencilMask(0x02)
gl.StencilFunc(gl.EQUAL, 0, 0x06)
gl.StencilOp(gl.KEEP, gl.INVERT, gl.INVERT)
gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
// on entire screen, clear bit 2
gl.StencilMask(0x04)
gl.StencilFunc(gl.ALWAYS, 0, 0x04)
gl.StencilFunc(gl.ALWAYS, 0, 0)
gl.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO)
gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4)

View file

@ -69,7 +69,19 @@ func (b *GoGLBackend) clearRect(x, y, w, h int) {
gl.Disable(gl.SCISSOR_TEST)
}
func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
func extent(pts [][2]float64) (min, max vec) {
min[0] = math.MaxFloat64
min[1] = math.MaxFloat64
for _, v := range pts {
min[0] = math.Min(min[0], v[0])
min[1] = math.Min(min[1], v[1])
max[0] = math.Max(max[0], v[0])
max[1] = math.Max(max[1], v[1])
}
return
}
func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, canOverlap bool) {
b.activate()
if style.Blur > 0 {
@ -80,11 +92,12 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
}
b.ptsBuf = b.ptsBuf[:0]
min, max := extent(pts)
b.ptsBuf = append(b.ptsBuf,
0, 0,
0, float32(b.fh),
float32(b.fw), float32(b.fh),
float32(b.fw), 0)
float32(min[0]), float32(min[1]),
float32(min[0]), float32(max[1]),
float32(max[0]), float32(max[1]),
float32(max[0]), float32(min[1]))
for _, pt := range pts {
b.ptsBuf = append(b.ptsBuf, float32(pt[0]), float32(pt[1]))
}
@ -97,7 +110,7 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
gl.BindBuffer(gl.ARRAY_BUFFER, b.buf)
gl.BufferData(gl.ARRAY_BUFFER, len(b.ptsBuf)*4, unsafe.Pointer(&b.ptsBuf[0]), gl.STREAM_DRAW)
if style.Color.A >= 255 {
if !canOverlap || style.Color.A >= 255 {
vertex := b.useShader(style)
gl.StencilFunc(gl.EQUAL, 0, 0xFF)
@ -130,7 +143,6 @@ func (b *GoGLBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
gl.EnableVertexAttribArray(vertex)
gl.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, nil)
b.ptsBuf = append(b.ptsBuf[:0], 0, 0, float32(b.fw), 0, float32(b.fw), float32(b.fh), 0, float32(b.fh))
gl.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
gl.DisableVertexAttribArray(vertex)

View file

@ -19,7 +19,7 @@ func (b *SoftwareBackend) Clear(pts [4][2]float64) {
})
}
func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
func (b *SoftwareBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, canOverlap bool) {
ffn := fillFunc(style)
if style.Blur > 0 {

View file

@ -43,18 +43,21 @@ func (b *XMobileBackend) Clip(pts [][2]float64) {
b.glctx.ColorMask(false, false, false, false)
// set bit 2 in the stencil buffer in the given shape
b.glctx.StencilMask(0x04)
b.glctx.StencilFunc(gl.ALWAYS, 4, 0x04)
b.glctx.StencilFunc(gl.ALWAYS, 4, 0)
b.glctx.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE)
b.glctx.DrawArrays(mode, 4, len(pts))
// on entire screen, where neither bit 1 or 2 are set, invert bit 1
b.glctx.StencilMask(0x02)
b.glctx.StencilFunc(gl.EQUAL, 0, 0x06)
b.glctx.StencilOp(gl.KEEP, gl.INVERT, gl.INVERT)
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
// on entire screen, clear bit 2
b.glctx.StencilMask(0x04)
b.glctx.StencilFunc(gl.ALWAYS, 0, 0x04)
b.glctx.StencilFunc(gl.ALWAYS, 0, 0)
b.glctx.StencilOp(gl.ZERO, gl.ZERO, gl.ZERO)
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)

View file

@ -69,7 +69,19 @@ func (b *XMobileBackend) clearRect(x, y, w, h int) {
b.glctx.Disable(gl.SCISSOR_TEST)
}
func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
func extent(pts [][2]float64) (min, max vec) {
min[0] = math.MaxFloat64
min[1] = math.MaxFloat64
for _, v := range pts {
min[0] = math.Min(min[0], v[0])
min[1] = math.Min(min[1], v[1])
max[0] = math.Max(max[0], v[0])
max[1] = math.Max(max[1], v[1])
}
return
}
func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64, canOverlap bool) {
b.activate()
if style.Blur > 0 {
@ -80,11 +92,12 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
}
b.ptsBuf = b.ptsBuf[:0]
min, max := extent(pts)
b.ptsBuf = append(b.ptsBuf,
0, 0,
0, float32(b.fh),
float32(b.fw), float32(b.fh),
float32(b.fw), 0)
float32(min[0]), float32(min[1]),
float32(min[0]), float32(max[1]),
float32(max[0]), float32(max[1]),
float32(max[0]), float32(min[1]))
for _, pt := range pts {
b.ptsBuf = append(b.ptsBuf, float32(pt[0]), float32(pt[1]))
}
@ -97,7 +110,7 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
b.glctx.BindBuffer(gl.ARRAY_BUFFER, b.buf)
b.glctx.BufferData(gl.ARRAY_BUFFER, byteSlice(unsafe.Pointer(&b.ptsBuf[0]), len(b.ptsBuf)*4), gl.STREAM_DRAW)
if style.Color.A >= 255 {
if !canOverlap || style.Color.A >= 255 {
vertex := b.useShader(style)
b.glctx.StencilFunc(gl.EQUAL, 0, 0xFF)
@ -130,7 +143,6 @@ func (b *XMobileBackend) Fill(style *backendbase.FillStyle, pts [][2]float64) {
b.glctx.EnableVertexAttribArray(vertex)
b.glctx.VertexAttribPointer(vertex, 2, gl.FLOAT, false, 0, 0)
b.ptsBuf = append(b.ptsBuf[:0], 0, 0, float32(b.fw), 0, float32(b.fw), float32(b.fh), 0, float32(b.fh))
b.glctx.DrawArrays(gl.TRIANGLE_FAN, 0, 4)
b.glctx.DisableVertexAttribArray(vertex)

View file

@ -169,7 +169,7 @@ func (cv *Canvas) DrawImage(image interface{}, coords ...float64) {
data[2] = cv.tf(vec{dx + dw, dy + dh})
data[3] = cv.tf(vec{dx + dw, dy})
cv.drawShadow(data[:], nil)
cv.drawShadow(data[:], nil, false)
cv.b.DrawImage(img.img, sx, sy, sw, sh, data, cv.state.globalAlpha)
}

View file

@ -95,10 +95,10 @@ func (cv *Canvas) strokePath(path *Path2D, inv mat, doInv bool) {
var triBuf [500][2]float64
tris := cv.strokeTris(path, inv, doInv, triBuf[:0])
cv.drawShadow(tris, nil)
cv.drawShadow(tris, nil, true)
stl := cv.backendFillStyle(&cv.state.stroke, 1)
cv.b.Fill(&stl, tris)
cv.b.Fill(&stl, tris, true)
}
func (cv *Canvas) strokeTris(path *Path2D, inv mat, doInv bool, target [][2]float64) [][2]float64 {
@ -371,10 +371,10 @@ func (cv *Canvas) fillPath(path *Path2D, tf mat) {
return
}
cv.drawShadow(tris, nil)
cv.drawShadow(tris, nil, false)
stl := cv.backendFillStyle(&cv.state.fill, 1)
cv.b.Fill(&stl, tris)
cv.b.Fill(&stl, tris, false)
}
func appendSubPathTriangles(tris [][2]float64, mat mat, path []pathPoint) [][2]float64 {
@ -412,8 +412,21 @@ func (cv *Canvas) clip(path *Path2D, tf mat) {
return
}
var triBuf [500][2]float64
tris := triBuf[:0]
var buf [500][2]float64
if path.p[len(path.p)-1].flags&pathIsRect != 0 {
cv.state.clip.p = make([]pathPoint, len(path.p))
copy(cv.state.clip.p, path.p)
quad := buf[:4]
for i := range quad {
quad[i] = path.p[i].pos
}
cv.b.Clip(quad)
return
}
tris := buf[:0]
runSubPaths(path.p, true, func(sp []pathPoint) bool {
tris = appendSubPathTriangles(tris, tf, sp)
return false
@ -467,10 +480,10 @@ func (cv *Canvas) FillRect(x, y, w, h float64) {
data := [4][2]float64{{p0[0], p0[1]}, {p1[0], p1[1]}, {p2[0], p2[1]}, {p3[0], p3[1]}}
cv.drawShadow(data[:], nil)
cv.drawShadow(data[:], nil, false)
stl := cv.backendFillStyle(&cv.state.fill, 1)
cv.b.Fill(&stl, data[:])
cv.b.Fill(&stl, data[:], false)
}
// ClearRect sets the color of the rectangle to transparent black

View file

@ -7,7 +7,7 @@ import (
"github.com/tfriedel6/canvas/backend/backendbase"
)
func (cv *Canvas) drawShadow(pts [][2]float64, mask *image.Alpha) {
func (cv *Canvas) drawShadow(pts [][2]float64, mask *image.Alpha, canOverlap bool) {
if cv.state.shadowColor.A == 0 {
return
}
@ -38,6 +38,6 @@ func (cv *Canvas) drawShadow(pts [][2]float64, mask *image.Alpha) {
copy(quad[:], cv.shadowBuf)
cv.b.FillImageMask(&style, mask, quad)
} else {
cv.b.Fill(&style, cv.shadowBuf)
cv.b.Fill(&style, cv.shadowBuf, canOverlap)
}
}

View file

@ -215,7 +215,7 @@ func (cv *Canvas) FillText(str string, x, y float64) {
mask := textImage.SubImage(image.Rect(0, 0, strWidth, strHeight)).(*image.Alpha)
cv.drawShadow(pts[:], mask)
cv.drawShadow(pts[:], mask, false)
stl := cv.backendFillStyle(&cv.state.fill, 1)
cv.b.FillImageMask(&stl, mask, pts)