mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 01:15:35 +00:00
ui/app/internal/gpu: track image and color in a state stack
Just like the other drawing state, the current image or color must be tracked in a stack. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+37
-33
@@ -67,12 +67,6 @@ type drawOps struct {
|
|||||||
zimageOps []imageOp
|
zimageOps []imageOp
|
||||||
pathOps []*pathOp
|
pathOps []*pathOp
|
||||||
pathOpCache []pathOp
|
pathOpCache []pathOp
|
||||||
|
|
||||||
// Current OpImage image and rect, if any.
|
|
||||||
img image.Image
|
|
||||||
imgRect image.Rectangle
|
|
||||||
// Current OpColor, if any.
|
|
||||||
color color.NRGBA
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type drawState struct {
|
type drawState struct {
|
||||||
@@ -81,6 +75,12 @@ type drawState struct {
|
|||||||
cpath *pathOp
|
cpath *pathOp
|
||||||
rect bool
|
rect bool
|
||||||
z int
|
z int
|
||||||
|
|
||||||
|
// Current OpImage image and rect, if any.
|
||||||
|
img image.Image
|
||||||
|
imgRect image.Rectangle
|
||||||
|
// Current OpColor, if any.
|
||||||
|
color color.NRGBA
|
||||||
}
|
}
|
||||||
|
|
||||||
type pathOp struct {
|
type pathOp struct {
|
||||||
@@ -652,7 +652,11 @@ func (d *drawOps) collect(cache *resourceCache, root *ui.Ops, viewport image.Poi
|
|||||||
Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)},
|
Max: f32.Point{X: float32(viewport.X), Y: float32(viewport.Y)},
|
||||||
}
|
}
|
||||||
d.reader.Reset(root.Data(), root.Refs())
|
d.reader.Reset(root.Data(), root.Refs())
|
||||||
d.collectOps(&d.reader, clip, ui.Transform{}, nil, true, 0)
|
state := drawState{
|
||||||
|
clip: clip,
|
||||||
|
rect: true,
|
||||||
|
}
|
||||||
|
d.collectOps(&d.reader, state)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *drawOps) newPathOp() *pathOp {
|
func (d *drawOps) newPathOp() *pathOp {
|
||||||
@@ -660,7 +664,7 @@ func (d *drawOps) newPathOp() *pathOp {
|
|||||||
return &d.pathOpCache[len(d.pathOpCache)-1]
|
return &d.pathOpCache[len(d.pathOpCache)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *drawOps) collectOps(r *ops.Reader, clip f32.Rectangle, t ui.Transform, cpath *pathOp, rect bool, z int) int {
|
func (d *drawOps) collectOps(r *ops.Reader, state drawState) int {
|
||||||
loop:
|
loop:
|
||||||
for {
|
for {
|
||||||
data, ok := r.Decode()
|
data, ok := r.Decode()
|
||||||
@@ -671,84 +675,84 @@ loop:
|
|||||||
case ops.TypeTransform:
|
case ops.TypeTransform:
|
||||||
var op ui.OpTransform
|
var op ui.OpTransform
|
||||||
op.Decode(data)
|
op.Decode(data)
|
||||||
t = t.Mul(op.Transform)
|
state.t = state.t.Mul(op.Transform)
|
||||||
case ops.TypeClip:
|
case ops.TypeClip:
|
||||||
var op gdraw.OpClip
|
var op gdraw.OpClip
|
||||||
op.Decode(data, r.Refs)
|
op.Decode(data, r.Refs)
|
||||||
if op.Path == nil {
|
if op.Path == nil {
|
||||||
clip = f32.Rectangle{}
|
state.clip = f32.Rectangle{}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
data := op.Path.Data().(*path.Path)
|
data := op.Path.Data().(*path.Path)
|
||||||
off := t.Transform(f32.Point{})
|
off := state.t.Transform(f32.Point{})
|
||||||
clip = clip.Intersect(data.Bounds.Add(off))
|
state.clip = state.clip.Intersect(data.Bounds.Add(off))
|
||||||
if clip.Empty() {
|
if state.clip.Empty() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
npath := d.newPathOp()
|
npath := d.newPathOp()
|
||||||
*npath = pathOp{
|
*npath = pathOp{
|
||||||
parent: cpath,
|
parent: state.cpath,
|
||||||
off: off,
|
off: off,
|
||||||
}
|
}
|
||||||
cpath = npath
|
state.cpath = npath
|
||||||
if len(data.Vertices) > 0 {
|
if len(data.Vertices) > 0 {
|
||||||
rect = false
|
state.rect = false
|
||||||
cpath.path = data
|
state.cpath.path = data
|
||||||
d.pathOps = append(d.pathOps, cpath)
|
d.pathOps = append(d.pathOps, state.cpath)
|
||||||
}
|
}
|
||||||
case ops.TypeColor:
|
case ops.TypeColor:
|
||||||
var op gdraw.OpColor
|
var op gdraw.OpColor
|
||||||
op.Decode(data, r.Refs)
|
op.Decode(data, r.Refs)
|
||||||
d.img = nil
|
state.img = nil
|
||||||
d.color = op.Col
|
state.color = op.Col
|
||||||
case ops.TypeImage:
|
case ops.TypeImage:
|
||||||
var op gdraw.OpImage
|
var op gdraw.OpImage
|
||||||
op.Decode(data, r.Refs)
|
op.Decode(data, r.Refs)
|
||||||
d.img = op.Img
|
state.img = op.Img
|
||||||
d.imgRect = op.Rect
|
state.imgRect = op.Rect
|
||||||
case ops.TypeDraw:
|
case ops.TypeDraw:
|
||||||
var op gdraw.OpDraw
|
var op gdraw.OpDraw
|
||||||
op.Decode(data, r.Refs)
|
op.Decode(data, r.Refs)
|
||||||
off := t.Transform(f32.Point{})
|
off := state.t.Transform(f32.Point{})
|
||||||
clip := clip.Intersect(op.Rect.Add(off))
|
clip := state.clip.Intersect(op.Rect.Add(off))
|
||||||
if clip.Empty() {
|
if clip.Empty() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
bounds := boundRectF(clip)
|
bounds := boundRectF(clip)
|
||||||
mat := d.materialFor(d.cache, op.Rect, off, bounds)
|
mat := state.materialFor(d.cache, op.Rect, off, bounds)
|
||||||
if bounds.Min == (image.Point{}) && bounds.Max == d.viewport && mat.opaque && mat.material == materialColor {
|
if bounds.Min == (image.Point{}) && bounds.Max == d.viewport && 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.zimageOps = d.zimageOps[:0]
|
d.zimageOps = d.zimageOps[:0]
|
||||||
d.imageOps = d.imageOps[:0]
|
d.imageOps = d.imageOps[:0]
|
||||||
z = 0
|
state.z = 0
|
||||||
copy(d.clearColor[:], mat.color[:3])
|
copy(d.clearColor[:], mat.color[:3])
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
z++
|
state.z++
|
||||||
// Assume 16-bit depth buffer.
|
// Assume 16-bit depth buffer.
|
||||||
const zdepth = 1 << 16
|
const zdepth = 1 << 16
|
||||||
// Convert z to window-space, assuming depth range [0;1].
|
// Convert z to window-space, assuming depth range [0;1].
|
||||||
zf := float32(z)*2/zdepth - 1.0
|
zf := float32(state.z)*2/zdepth - 1.0
|
||||||
img := imageOp{
|
img := imageOp{
|
||||||
z: zf,
|
z: zf,
|
||||||
path: cpath,
|
path: state.cpath,
|
||||||
off: off,
|
off: off,
|
||||||
clip: bounds,
|
clip: bounds,
|
||||||
material: mat,
|
material: mat,
|
||||||
}
|
}
|
||||||
if rect && img.material.opaque {
|
if state.rect && img.material.opaque {
|
||||||
d.zimageOps = append(d.zimageOps, img)
|
d.zimageOps = append(d.zimageOps, img)
|
||||||
} else {
|
} else {
|
||||||
d.imageOps = append(d.imageOps, img)
|
d.imageOps = append(d.imageOps, img)
|
||||||
}
|
}
|
||||||
case ops.TypePush:
|
case ops.TypePush:
|
||||||
z = d.collectOps(r, clip, t, cpath, rect, z)
|
state.z = d.collectOps(r, state)
|
||||||
case ops.TypePop:
|
case ops.TypePop:
|
||||||
break loop
|
break loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return z
|
return state.z
|
||||||
}
|
}
|
||||||
|
|
||||||
func expandPathOp(p *pathOp, clip image.Rectangle) {
|
func expandPathOp(p *pathOp, clip image.Rectangle) {
|
||||||
@@ -762,7 +766,7 @@ func expandPathOp(p *pathOp, clip image.Rectangle) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *drawOps) materialFor(cache *resourceCache, rect f32.Rectangle, off f32.Point, clip image.Rectangle) material {
|
func (d *drawState) materialFor(cache *resourceCache, rect f32.Rectangle, off f32.Point, clip image.Rectangle) material {
|
||||||
var m material
|
var m material
|
||||||
if d.img == nil {
|
if d.img == nil {
|
||||||
m.material = materialColor
|
m.material = materialColor
|
||||||
|
|||||||
Reference in New Issue
Block a user