gpu: don't automatically clear screen before rendering

Gio UI may be overlaid on top of custom graphics such as in the glfw example.
That will only work if Gio doesn't clear the screen (to white).

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2021-01-22 18:33:34 +01:00
parent 686d680ea3
commit 84b586ae6c
5 changed files with 35 additions and 6 deletions
+2
View File
@@ -6,6 +6,7 @@ package headless
import ( import (
"image" "image"
"image/color"
"runtime" "runtime"
"gioui.org/gpu" "gioui.org/gpu"
@@ -108,6 +109,7 @@ func (w *Window) Release() {
// operation list. // operation list.
func (w *Window) Frame(frame *op.Ops) error { func (w *Window) Frame(frame *op.Ops) error {
return contextDo(w.ctx, func() error { return contextDo(w.ctx, func() error {
w.gpu.Clear(color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff})
w.gpu.Collect(w.size, frame) w.gpu.Collect(w.size, frame)
return w.gpu.Frame() return w.gpu.Frame()
}) })
+2
View File
@@ -4,6 +4,7 @@ package app
import ( import (
"image" "image"
"image/color"
"runtime" "runtime"
"gioui.org/app/internal/window" "gioui.org/app/internal/window"
@@ -85,6 +86,7 @@ func (l *renderLoop) renderLoop(ctx window.Context) error {
l.refreshErr <- ctx.MakeCurrent() l.refreshErr <- ctx.MakeCurrent()
case frame := <-l.frames: case frame := <-l.frames:
ctx.Lock() ctx.Lock()
g.Clear(color.NRGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff})
g.Collect(frame.viewport, frame.ops) g.Collect(frame.viewport, frame.ops)
// Signal that we're done with the frame ops. // Signal that we're done with the frame ops.
l.ack <- struct{}{} l.ack <- struct{}{}
+10 -2
View File
@@ -230,6 +230,11 @@ func (g *compute) Collect(viewport image.Point, ops *op.Ops) {
} }
} }
func (g *compute) Clear(col color.NRGBA) {
g.drawOps.clear = true
g.drawOps.clearColor = f32color.LinearFromSRGB(col)
}
func (g *compute) Frame() error { func (g *compute) Frame() error {
viewport := g.drawOps.viewport viewport := g.drawOps.viewport
tileDims := image.Point{ tileDims := image.Point{
@@ -285,8 +290,11 @@ func (g *compute) encode(viewport image.Point) {
// Flip Y-axis. // Flip Y-axis.
flipY := f32.Affine2D{}.Scale(f32.Pt(0, 0), f32.Pt(1, -1)).Offset(f32.Pt(0, float32(viewport.Y))) flipY := f32.Affine2D{}.Scale(f32.Pt(0, 0), f32.Pt(1, -1)).Offset(f32.Pt(0, float32(viewport.Y)))
g.enc.transform(flipY) g.enc.transform(flipY)
g.enc.rect(f32.Rectangle{Max: layout.FPt(viewport)}, false) if g.drawOps.clear {
g.enc.fill(f32color.NRGBAToRGBA(g.drawOps.clearColor.SRGB())) g.drawOps.clear = false
g.enc.rect(f32.Rectangle{Max: layout.FPt(viewport)}, false)
g.enc.fill(f32color.NRGBAToRGBA(g.drawOps.clearColor.SRGB()))
}
g.encodeOps(flipY, viewport, g.drawOps.allImageOps) g.encodeOps(flipY, viewport, g.drawOps.allImageOps)
} }
+20 -3
View File
@@ -31,9 +31,17 @@ import (
) )
type GPU interface { type GPU interface {
// Release non-Go resources. The GPU is no longer valid after Release.
Release() Release()
Collect(viewport image.Point, frameOps *op.Ops) // Clear sets the clear color for the next Frame.
Clear(color color.NRGBA)
// Collect the graphics operations from frame, given the viewport.
Collect(viewport image.Point, frame *op.Ops)
// Frame clears the color buffer and draws the collected operations.
Frame() error Frame() error
// Profile returns the last available profiling information. Profiling
// information is requested when Collect sees a ProfileOp, and the result
// is available through Profile at some later time.
Profile() string Profile() string
} }
@@ -65,6 +73,7 @@ type drawOps struct {
cache *resourceCache cache *resourceCache
vertCache []byte vertCache []byte
viewport image.Point viewport image.Point
clear bool
clearColor f32color.RGBA clearColor f32color.RGBA
// allImageOps is the combined list of imageOps and // allImageOps is the combined list of imageOps and
// zimageOps, in drawing order. // zimageOps, in drawing order.
@@ -404,6 +413,11 @@ func (g *gpu) init(ctx backend.Device) error {
return nil return nil
} }
func (g *gpu) Clear(col color.NRGBA) {
g.drawOps.clear = true
g.drawOps.clearColor = f32color.LinearFromSRGB(col)
}
func (g *gpu) Release() { func (g *gpu) Release() {
g.renderer.release() g.renderer.release()
g.drawOps.pathCache.release() g.drawOps.pathCache.release()
@@ -442,7 +456,10 @@ func (g *gpu) Frame() error {
g.ctx.DepthFunc(backend.DepthFuncGreater) g.ctx.DepthFunc(backend.DepthFuncGreater)
// Note that Clear must be before ClearDepth if nothing else is rendered // Note that Clear must be before ClearDepth if nothing else is rendered
// (len(zimageOps) == 0). If not, the Fairphone 2 will corrupt the depth buffer. // (len(zimageOps) == 0). If not, the Fairphone 2 will corrupt the depth buffer.
g.ctx.Clear(g.drawOps.clearColor.Float32()) if g.drawOps.clear {
g.drawOps.clear = false
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.cache, g.drawOps.zimageOps) g.renderer.drawZOps(g.cache, g.drawOps.zimageOps)
@@ -799,7 +816,6 @@ func floor(v float32) int {
func (d *drawOps) reset(cache *resourceCache, viewport image.Point) { func (d *drawOps) reset(cache *resourceCache, viewport image.Point) {
d.profile = false d.profile = false
d.clearColor = f32color.RGBA{R: 1.0, G: 1.0, B: 1.0, A: 1.0}
d.cache = cache d.cache = cache
d.viewport = viewport d.viewport = viewport
d.imageOps = d.imageOps[:0] d.imageOps = d.imageOps[:0]
@@ -1006,6 +1022,7 @@ loop:
d.imageOps = d.imageOps[:0] d.imageOps = d.imageOps[:0]
z = 0 z = 0
d.clearColor = mat.color.Opaque() d.clearColor = mat.color.Opaque()
d.clear = true
continue continue
} }
z++ z++
+1 -1
View File
@@ -161,7 +161,7 @@ func verifyRef(t *testing.T, img *image.RGBA, frame int) (ok bool) {
} }
ref, ok := r.(*image.RGBA) ref, ok := r.(*image.RGBA)
if !ok { if !ok {
t.Error("ref image note RGBA") t.Errorf("image is a %T, expected *image.RGBA", r)
return return
} }
if len(ref.Pix) != len(img.Pix) { if len(ref.Pix) != len(img.Pix) {