From dfc1503c0070ee332d0ead88e60c09f42a91145b Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 22 Feb 2020 16:25:01 +0100 Subject: [PATCH] gpu: replace Backend.DefaultFramebuffer by Backend.CurrentFramebuffer DefaultFramebuffer was set up at Backend creation time, which is difficult to predict. Instead, let GPU query and cache the current FBO when created. Signed-off-by: Elias Naur --- gpu/backend.go | 2 +- gpu/gl/backend.go | 16 +++++++++------- gpu/gpu.go | 7 +++++-- gpu/path.go | 20 ++------------------ 4 files changed, 17 insertions(+), 28 deletions(-) diff --git a/gpu/backend.go b/gpu/backend.go index 92b1a5cf..b5082deb 100644 --- a/gpu/backend.go +++ b/gpu/backend.go @@ -19,7 +19,7 @@ type Backend interface { // are valid at the point of call. IsTimeContinuous() bool NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error) - DefaultFramebuffer() Framebuffer + CurrentFramebuffer() Framebuffer NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error) NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error) NewBuffer(typ BufferBinding, size int) (Buffer, error) diff --git a/gpu/gl/backend.go b/gpu/gl/backend.go index 939179e7..caa76429 100644 --- a/gpu/gl/backend.go +++ b/gpu/gl/backend.go @@ -15,8 +15,7 @@ import ( // Backend implements gpu.Backend. type Backend struct { - funcs Functions - defFBO *gpuFramebuffer + funcs Functions state glstate @@ -59,10 +58,11 @@ type gpuTexture struct { } type gpuFramebuffer struct { - backend *Backend + backend *Backend obj Framebuffer hasDepth bool depthBuf Renderbuffer + foreign bool } type gpuBuffer struct { @@ -127,14 +127,12 @@ func NewBackend(f Functions) (*Backend, error) { if err != nil { return nil, err } - defFBO := Framebuffer(f.GetBinding(FRAMEBUFFER_BINDING)) b := &Backend{ funcs: f, floatTriple: floatTriple, alphaTriple: alphaTripleFor(ver), srgbaTriple: srgbaTriple, } - b.defFBO = &gpuFramebuffer{backend: b, obj: defFBO} if hasExtension(exts, "GL_EXT_disjoint_timer_query_webgl2") || hasExtension(exts, "GL_EXT_disjoint_timer_query") { b.feats.Features |= gpu.FeatureTimers } @@ -202,8 +200,9 @@ func (b *Backend) NewFramebuffer(tex gpu.Texture, depthBits int) (gpu.Framebuffe return fbo, nil } -func (b *Backend) DefaultFramebuffer() gpu.Framebuffer { - return b.defFBO +func (b *Backend) CurrentFramebuffer() gpu.Framebuffer { + fboID := Framebuffer(b.funcs.GetBinding(FRAMEBUFFER_BINDING)) + return &gpuFramebuffer{backend: b, obj: fboID, foreign: true} } func (b *Backend) NewTexture(format gpu.TextureFormat, width, height int, minFilter, magFilter gpu.TextureFilter, binding gpu.BufferBinding) (gpu.Texture, error) { @@ -612,6 +611,9 @@ func (f *gpuFramebuffer) Invalidate() { } func (f *gpuFramebuffer) Release() { + if f.foreign { + panic("cannot release framebuffer created by CurrentFramebuffer") + } f.backend.funcs.DeleteFramebuffer(f.obj) if f.hasDepth { f.backend.funcs.DeleteRenderbuffer(f.depthBuf) diff --git a/gpu/gpu.go b/gpu/gpu.go index 7cf9c935..bd31a955 100644 --- a/gpu/gpu.go +++ b/gpu/gpu.go @@ -30,6 +30,7 @@ type GPU struct { pathCache *opCache cache *resourceCache + defFBO Framebuffer profile string timers *timers frameStart time.Time @@ -275,7 +276,9 @@ const ( ) func New(ctx Backend) (*GPU, error) { + defFBO := ctx.CurrentFramebuffer() g := &GPU{ + defFBO: defFBO, pathCache: newOpCache(), cache: newResourceCache(), } @@ -332,6 +335,7 @@ func (g *GPU) BeginFrame() { if g.drawOps.profile { g.zopsTimer.begin() } + g.ctx.BindFramebuffer(g.defFBO) g.ctx.DepthFunc(DepthFuncGreater) g.ctx.ClearColor(g.drawOps.clearColor[0], g.drawOps.clearColor[1], g.drawOps.clearColor[2], 1.0) g.ctx.ClearDepth(0.0) @@ -347,6 +351,7 @@ func (g *GPU) BeginFrame() { g.renderer.intersect(g.drawOps.imageOps) g.stencilTimer.end() g.coverTimer.begin() + g.ctx.BindFramebuffer(g.defFBO) g.ctx.Viewport(0, 0, viewport.X, viewport.Y) g.renderer.drawOps(g.drawOps.imageOps) g.ctx.SetBlend(false) @@ -502,7 +507,6 @@ func (r *renderer) stencilClips(pathCache *opCache, ops []*pathOp) { data, _ := pathCache.get(p.pathKey) r.pather.stencilPath(p.clip, p.off, p.place.Pos, data.(*pathData)) } - r.pather.end() } func (r *renderer) intersect(ops []imageOp) { @@ -526,7 +530,6 @@ func (r *renderer) intersect(ops []imageOp) { r.ctx.Viewport(img.place.Pos.X, img.place.Pos.Y, img.clip.Dx(), img.clip.Dy()) r.intersectPath(img.path, img.clip) } - r.pather.stenciler.endIntersect() } func (r *renderer) intersectPath(p *pathOp, clip image.Rectangle) { diff --git a/gpu/path.go b/gpu/path.go index 797836d0..120b2326 100644 --- a/gpu/path.go +++ b/gpu/path.go @@ -56,9 +56,8 @@ type coverUniforms struct { } type stenciler struct { - ctx Backend - defFBO Framebuffer - prog struct { + ctx Backend + prog struct { prog *program uniforms struct { vert struct { @@ -138,7 +137,6 @@ func newCoverer(ctx Backend) *coverer { } func newStenciler(ctx Backend) *stenciler { - defFBO := ctx.DefaultFramebuffer() // Allocate a suitably large index buffer for drawing paths. indices := make([]uint16, pathBatchSize*6) for i := 0; i < pathBatchSize; i++ { @@ -173,7 +171,6 @@ func newStenciler(ctx Backend) *stenciler { } st := &stenciler{ ctx: ctx, - defFBO: defFBO, indexBuf: indexBuf, } prog, err := ctx.NewProgram(shader_stencil_vert, shader_stencil_frag) @@ -281,10 +278,6 @@ func (p *pather) begin(sizes []image.Point) { p.stenciler.begin(sizes) } -func (p *pather) end() { - p.stenciler.end() -} - func (p *pather) stencilPath(bounds image.Rectangle, offset f32.Point, uv image.Point, data *pathData) { p.stenciler.stencilPath(bounds, offset, uv, data) } @@ -299,14 +292,9 @@ func (s *stenciler) beginIntersect(sizes []image.Point) { s.ctx.BindProgram(s.iprog.prog.prog) } -func (s *stenciler) endIntersect() { - s.ctx.BindFramebuffer(s.defFBO) -} - func (s *stenciler) invalidateFBO() { s.intersections.invalidate(s.ctx) s.fbos.invalidate(s.ctx) - s.ctx.BindFramebuffer(s.defFBO) } func (s *stenciler) cover(idx int) stencilFBO { @@ -347,10 +335,6 @@ func (s *stenciler) stencilPath(bounds image.Rectangle, offset f32.Point, uv ima } } -func (s *stenciler) end() { - s.ctx.BindFramebuffer(s.defFBO) -} - func (p *pather) cover(z float32, mat materialType, col [4]float32, scale, off, uvScale, uvOff, coverScale, coverOff f32.Point) { p.coverer.cover(z, mat, col, scale, off, uvScale, uvOff, coverScale, coverOff) }