mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-06 09:55:40 +00:00
gpu: add and track fields needed by the compute renderer
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+4
-2
@@ -26,8 +26,10 @@ type opCache struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type opCacheValue struct {
|
type opCacheValue struct {
|
||||||
data pathData
|
data pathData
|
||||||
bounds f32.Rectangle
|
// cpuData is the retained data, if kept by the compute renderer.
|
||||||
|
cpuData []byte
|
||||||
|
bounds f32.Rectangle
|
||||||
// the fields below are handled by opCache
|
// the fields below are handled by opCache
|
||||||
key ops.Key
|
key ops.Key
|
||||||
keep bool
|
keep bool
|
||||||
|
|||||||
+50
-30
@@ -56,7 +56,10 @@ type drawOps struct {
|
|||||||
vertCache []byte
|
vertCache []byte
|
||||||
viewport image.Point
|
viewport image.Point
|
||||||
clearColor f32color.RGBA
|
clearColor f32color.RGBA
|
||||||
imageOps []imageOp
|
// allImageOps is the combined list of imageOps and
|
||||||
|
// zimageOps, in drawing order.
|
||||||
|
allImageOps []imageOp
|
||||||
|
imageOps []imageOp
|
||||||
// zimageOps are the rectangle clipped opaque images
|
// zimageOps are the rectangle clipped opaque images
|
||||||
// that can use fast front-to-back rendering with z-test
|
// that can use fast front-to-back rendering with z-test
|
||||||
// and no blending.
|
// and no blending.
|
||||||
@@ -65,6 +68,9 @@ type drawOps struct {
|
|||||||
pathOpCache []pathOp
|
pathOpCache []pathOp
|
||||||
qs quadSplitter
|
qs quadSplitter
|
||||||
pathCache *opCache
|
pathCache *opCache
|
||||||
|
// hack for the compute renderer to access
|
||||||
|
// converted path data.
|
||||||
|
retainPathData bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type drawState struct {
|
type drawState struct {
|
||||||
@@ -164,8 +170,11 @@ type material struct {
|
|||||||
color1 f32color.RGBA
|
color1 f32color.RGBA
|
||||||
color2 f32color.RGBA
|
color2 f32color.RGBA
|
||||||
// For materialTypeTexture.
|
// For materialTypeTexture.
|
||||||
texture *texture
|
data imageOpData
|
||||||
uvTrans f32.Affine2D
|
uvTrans f32.Affine2D
|
||||||
|
|
||||||
|
// For the compute backend.
|
||||||
|
trans f32.Affine2D
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipOp is the shadow of clip.Op.
|
// clipOp is the shadow of clip.Op.
|
||||||
@@ -414,7 +423,7 @@ func (g *GPU) BeginFrame() {
|
|||||||
g.ctx.Clear(g.drawOps.clearColor.Float32())
|
g.ctx.Clear(g.drawOps.clearColor.Float32())
|
||||||
g.ctx.ClearDepth(0.0)
|
g.ctx.ClearDepth(0.0)
|
||||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||||
g.renderer.drawZOps(g.drawOps.zimageOps)
|
g.renderer.drawZOps(g.cache, g.drawOps.zimageOps)
|
||||||
g.zopsTimer.end()
|
g.zopsTimer.end()
|
||||||
g.stencilTimer.begin()
|
g.stencilTimer.begin()
|
||||||
g.ctx.SetBlend(true)
|
g.ctx.SetBlend(true)
|
||||||
@@ -426,7 +435,7 @@ func (g *GPU) BeginFrame() {
|
|||||||
g.coverTimer.begin()
|
g.coverTimer.begin()
|
||||||
g.ctx.BindFramebuffer(g.defFBO)
|
g.ctx.BindFramebuffer(g.defFBO)
|
||||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||||
g.renderer.drawOps(g.drawOps.imageOps)
|
g.renderer.drawOps(g.cache, g.drawOps.imageOps)
|
||||||
g.ctx.SetBlend(false)
|
g.ctx.SetBlend(false)
|
||||||
g.renderer.pather.stenciler.invalidateFBO()
|
g.renderer.pather.stenciler.invalidateFBO()
|
||||||
g.coverTimer.end()
|
g.coverTimer.end()
|
||||||
@@ -453,17 +462,26 @@ func (g *GPU) Profile() string {
|
|||||||
return g.profile
|
return g.profile
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *renderer) texHandle(t *texture) backend.Texture {
|
func (r *renderer) texHandle(cache *resourceCache, data imageOpData) backend.Texture {
|
||||||
if t.tex != nil {
|
var tex *texture
|
||||||
return t.tex
|
t, exists := cache.get(data.handle)
|
||||||
|
if !exists {
|
||||||
|
t = &texture{
|
||||||
|
src: data.src,
|
||||||
|
}
|
||||||
|
cache.put(data.handle, t)
|
||||||
}
|
}
|
||||||
tex, err := r.ctx.NewTexture(backend.TextureFormatSRGB, t.src.Bounds().Dx(), t.src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
|
tex = t.(*texture)
|
||||||
|
if tex.tex != nil {
|
||||||
|
return tex.tex
|
||||||
|
}
|
||||||
|
handle, err := r.ctx.NewTexture(backend.TextureFormatSRGB, data.src.Bounds().Dx(), data.src.Bounds().Dy(), backend.FilterLinear, backend.FilterLinear, backend.BufferBindingTexture)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
tex.Upload(t.src)
|
handle.Upload(data.src)
|
||||||
t.tex = tex
|
tex.tex = handle
|
||||||
return t.tex
|
return tex.tex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *texture) release() {
|
func (t *texture) release() {
|
||||||
@@ -765,6 +783,7 @@ func (d *drawOps) reset(cache *resourceCache, viewport image.Point) {
|
|||||||
d.cache = cache
|
d.cache = cache
|
||||||
d.viewport = viewport
|
d.viewport = viewport
|
||||||
d.imageOps = d.imageOps[:0]
|
d.imageOps = d.imageOps[:0]
|
||||||
|
d.allImageOps = d.allImageOps[:0]
|
||||||
d.zimageOps = d.zimageOps[:0]
|
d.zimageOps = d.zimageOps[:0]
|
||||||
d.pathOps = d.pathOps[:0]
|
d.pathOps = d.pathOps[:0]
|
||||||
d.pathOpCache = d.pathOpCache[:0]
|
d.pathOpCache = d.pathOpCache[:0]
|
||||||
@@ -785,9 +804,15 @@ func (d *drawOps) collect(ctx backend.Device, cache *resourceCache, root *op.Ops
|
|||||||
for _, p := range d.pathOps {
|
for _, p := range d.pathOps {
|
||||||
if v, exists := d.pathCache.get(p.pathKey); !exists || v.data.data == nil {
|
if v, exists := d.pathCache.get(p.pathKey); !exists || v.data.data == nil {
|
||||||
data := buildPath(ctx, p.pathVerts)
|
data := buildPath(ctx, p.pathVerts)
|
||||||
|
var pathVerts []byte
|
||||||
|
if d.retainPathData {
|
||||||
|
pathVerts = make([]byte, len(p.pathVerts))
|
||||||
|
copy(pathVerts, p.pathVerts)
|
||||||
|
}
|
||||||
d.pathCache.put(p.pathKey, opCacheValue{
|
d.pathCache.put(p.pathKey, opCacheValue{
|
||||||
data: data,
|
data: data,
|
||||||
bounds: p.bounds,
|
bounds: p.bounds,
|
||||||
|
cpuData: pathVerts,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
p.pathVerts = nil
|
p.pathVerts = nil
|
||||||
@@ -943,11 +968,12 @@ loop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
bounds := boundRectF(clip)
|
bounds := boundRectF(clip)
|
||||||
mat := state.materialFor(d.cache, bnd, off, partialTrans, bounds)
|
mat := state.materialFor(bnd, off, partialTrans, bounds, state.t)
|
||||||
|
|
||||||
if bounds.Min == (image.Point{}) && bounds.Max == d.viewport && state.rect && mat.opaque && (mat.material == materialColor) {
|
if bounds.Min == (image.Point{}) && bounds.Max == d.viewport && state.rect && mat.opaque && (mat.material == materialColor) {
|
||||||
// The image is a uniform opaque color and takes up the whole screen.
|
// The image is a uniform opaque color and takes up the whole screen.
|
||||||
// Scrap images up to and including this image and set clear color.
|
// Scrap images up to and including this image and set clear color.
|
||||||
|
d.allImageOps = d.allImageOps[:0]
|
||||||
d.zimageOps = d.zimageOps[:0]
|
d.zimageOps = d.zimageOps[:0]
|
||||||
d.imageOps = d.imageOps[:0]
|
d.imageOps = d.imageOps[:0]
|
||||||
state.z = 0
|
state.z = 0
|
||||||
@@ -970,6 +996,7 @@ loop:
|
|||||||
material: mat,
|
material: mat,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d.allImageOps = append(d.allImageOps, img)
|
||||||
if state.rect && img.material.opaque {
|
if state.rect && img.material.opaque {
|
||||||
d.zimageOps = append(d.zimageOps, img)
|
d.zimageOps = append(d.zimageOps, img)
|
||||||
} else {
|
} else {
|
||||||
@@ -1000,7 +1027,7 @@ func expandPathOp(p *pathOp, clip image.Rectangle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f32.Point, trans f32.Affine2D, clip image.Rectangle) material {
|
func (d *drawState) materialFor(rect f32.Rectangle, off f32.Point, partTrans f32.Affine2D, clip image.Rectangle, trans f32.Affine2D) material {
|
||||||
var m material
|
var m material
|
||||||
switch d.matType {
|
switch d.matType {
|
||||||
case materialColor:
|
case materialColor:
|
||||||
@@ -1014,7 +1041,7 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
|
|||||||
m.color2 = f32color.LinearFromSRGB(d.color2)
|
m.color2 = f32color.LinearFromSRGB(d.color2)
|
||||||
m.opaque = m.color1.A == 1.0 && m.color2.A == 1.0
|
m.opaque = m.color1.A == 1.0 && m.color2.A == 1.0
|
||||||
|
|
||||||
m.uvTrans = trans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2))
|
m.uvTrans = partTrans.Mul(gradientSpaceTransform(clip, off, d.stop1, d.stop2))
|
||||||
case materialTexture:
|
case materialTexture:
|
||||||
m.material = materialTexture
|
m.material = materialTexture
|
||||||
dr := boundRectF(rect.Add(off))
|
dr := boundRectF(rect.Add(off))
|
||||||
@@ -1033,22 +1060,15 @@ func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f3
|
|||||||
sdy := sr.Dy()
|
sdy := sr.Dy()
|
||||||
sr.Min.Y += float32(clip.Min.Y-dr.Min.Y) * sdy / dy
|
sr.Min.Y += float32(clip.Min.Y-dr.Min.Y) * sdy / dy
|
||||||
sr.Max.Y -= float32(dr.Max.Y-clip.Max.Y) * sdy / dy
|
sr.Max.Y -= float32(dr.Max.Y-clip.Max.Y) * sdy / dy
|
||||||
tex, exists := cache.get(d.image.handle)
|
|
||||||
if !exists {
|
|
||||||
t := &texture{
|
|
||||||
src: d.image.src,
|
|
||||||
}
|
|
||||||
cache.put(d.image.handle, t)
|
|
||||||
tex = t
|
|
||||||
}
|
|
||||||
m.texture = tex.(*texture)
|
|
||||||
uvScale, uvOffset := texSpaceTransform(sr, sz)
|
uvScale, uvOffset := texSpaceTransform(sr, sz)
|
||||||
m.uvTrans = trans.Mul(f32.Affine2D{}.Scale(f32.Point{}, uvScale).Offset(uvOffset))
|
m.uvTrans = partTrans.Mul(f32.Affine2D{}.Scale(f32.Point{}, uvScale).Offset(uvOffset))
|
||||||
|
m.trans = trans
|
||||||
|
m.data = d.image
|
||||||
}
|
}
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *renderer) drawZOps(ops []imageOp) {
|
func (r *renderer) drawZOps(cache *resourceCache, ops []imageOp) {
|
||||||
r.ctx.SetDepthTest(true)
|
r.ctx.SetDepthTest(true)
|
||||||
r.ctx.BindVertexBuffer(r.blitter.quadVerts, 4*4, 0)
|
r.ctx.BindVertexBuffer(r.blitter.quadVerts, 4*4, 0)
|
||||||
r.ctx.BindInputLayout(r.blitter.layout)
|
r.ctx.BindInputLayout(r.blitter.layout)
|
||||||
@@ -1058,7 +1078,7 @@ func (r *renderer) drawZOps(ops []imageOp) {
|
|||||||
m := img.material
|
m := img.material
|
||||||
switch m.material {
|
switch m.material {
|
||||||
case materialTexture:
|
case materialTexture:
|
||||||
r.ctx.BindTexture(0, r.texHandle(m.texture))
|
r.ctx.BindTexture(0, r.texHandle(cache, m.data))
|
||||||
}
|
}
|
||||||
drc := img.clip
|
drc := img.clip
|
||||||
scale, off := clipSpaceTransform(drc, r.blitter.viewport)
|
scale, off := clipSpaceTransform(drc, r.blitter.viewport)
|
||||||
@@ -1067,7 +1087,7 @@ func (r *renderer) drawZOps(ops []imageOp) {
|
|||||||
r.ctx.SetDepthTest(false)
|
r.ctx.SetDepthTest(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *renderer) drawOps(ops []imageOp) {
|
func (r *renderer) drawOps(cache *resourceCache, ops []imageOp) {
|
||||||
r.ctx.SetDepthTest(true)
|
r.ctx.SetDepthTest(true)
|
||||||
r.ctx.DepthMask(false)
|
r.ctx.DepthMask(false)
|
||||||
r.ctx.BlendFunc(backend.BlendFactorOne, backend.BlendFactorOneMinusSrcAlpha)
|
r.ctx.BlendFunc(backend.BlendFactorOne, backend.BlendFactorOneMinusSrcAlpha)
|
||||||
@@ -1078,7 +1098,7 @@ func (r *renderer) drawOps(ops []imageOp) {
|
|||||||
m := img.material
|
m := img.material
|
||||||
switch m.material {
|
switch m.material {
|
||||||
case materialTexture:
|
case materialTexture:
|
||||||
r.ctx.BindTexture(0, r.texHandle(m.texture))
|
r.ctx.BindTexture(0, r.texHandle(cache, m.data))
|
||||||
}
|
}
|
||||||
drc := img.clip
|
drc := img.clip
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user