mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 17:35:36 +00:00
gpu,gpu/backend: don't assume constant output framebuffer
Return the output framebuffer from BeginFrame, to make it clear that it may change between frames. Delete CurrentFramebuffer which is no longer needed. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -274,7 +274,8 @@ func NewBackend(d *Device) (*Backend, error) {
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) BeginFrame() {
|
func (b *Backend) BeginFrame() backend.Framebuffer {
|
||||||
|
return b.currentFramebuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) EndFrame() {
|
func (b *Backend) EndFrame() {
|
||||||
@@ -368,13 +369,13 @@ func (b *Backend) NewTexture(format backend.TextureFormat, width, height int, mi
|
|||||||
return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil
|
return &Texture{backend: b, format: d3dfmt, tex: tex, sampler: sampler, resView: resView, bindings: bindings, width: width, height: height}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) CurrentFramebuffer() backend.Framebuffer {
|
func (b *Backend) currentFramebuffer() backend.Framebuffer {
|
||||||
renderTarget := b.dev.ctx.OMGetRenderTargets()
|
renderTarget := b.dev.ctx.OMGetRenderTargets()
|
||||||
if renderTarget != nil {
|
if renderTarget != nil {
|
||||||
// Assume someone else is holding on to it.
|
// Assume someone else is holding on to it.
|
||||||
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
|
_IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.vtbl.Release)
|
||||||
}
|
}
|
||||||
if renderTarget == b.fbo.renderTarget {
|
if b.fbo != nil && renderTarget == b.fbo.renderTarget {
|
||||||
return b.fbo
|
return b.fbo
|
||||||
}
|
}
|
||||||
return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true}
|
return &Framebuffer{dev: b.dev, renderTarget: renderTarget, foreign: true}
|
||||||
@@ -823,7 +824,7 @@ func (f *Framebuffer) Invalidate() {
|
|||||||
|
|
||||||
func (f *Framebuffer) Release() {
|
func (f *Framebuffer) Release() {
|
||||||
if f.foreign {
|
if f.foreign {
|
||||||
panic("cannot release Framebuffer from CurrentFramebuffer")
|
panic("framebuffer not created by NewBuffer")
|
||||||
}
|
}
|
||||||
if f.renderTarget != nil {
|
if f.renderTarget != nil {
|
||||||
_IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release)
|
_IUnknownRelease(unsafe.Pointer(f.renderTarget), f.renderTarget.vtbl.Release)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import (
|
|||||||
// APIs such as OpenGL, Direct3D useful for rendering Gio
|
// APIs such as OpenGL, Direct3D useful for rendering Gio
|
||||||
// operations.
|
// operations.
|
||||||
type Device interface {
|
type Device interface {
|
||||||
BeginFrame()
|
BeginFrame() Framebuffer
|
||||||
EndFrame()
|
EndFrame()
|
||||||
Caps() Caps
|
Caps() Caps
|
||||||
NewTimer() Timer
|
NewTimer() Timer
|
||||||
@@ -20,7 +20,6 @@ type Device interface {
|
|||||||
// are valid at the point of call.
|
// are valid at the point of call.
|
||||||
IsTimeContinuous() bool
|
IsTimeContinuous() bool
|
||||||
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
|
NewTexture(format TextureFormat, width, height int, minFilter, magFilter TextureFilter, bindings BufferBinding) (Texture, error)
|
||||||
CurrentFramebuffer() Framebuffer
|
|
||||||
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
|
NewFramebuffer(tex Texture, depthBits int) (Framebuffer, error)
|
||||||
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
|
NewImmutableBuffer(typ BufferBinding, data []byte) (Buffer, error)
|
||||||
NewBuffer(typ BufferBinding, size int) (Buffer, error)
|
NewBuffer(typ BufferBinding, size int) (Buffer, error)
|
||||||
|
|||||||
+2
-4
@@ -29,7 +29,6 @@ type compute struct {
|
|||||||
cache *resourceCache
|
cache *resourceCache
|
||||||
maxTextureDim int
|
maxTextureDim int
|
||||||
|
|
||||||
defFBO backend.Framebuffer
|
|
||||||
programs struct {
|
programs struct {
|
||||||
elements backend.Program
|
elements backend.Program
|
||||||
tileAlloc backend.Program
|
tileAlloc backend.Program
|
||||||
@@ -197,7 +196,6 @@ func newCompute(ctx backend.Device) (*compute, error) {
|
|||||||
}
|
}
|
||||||
g := &compute{
|
g := &compute{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
defFBO: ctx.CurrentFramebuffer(),
|
|
||||||
cache: newResourceCache(),
|
cache: newResourceCache(),
|
||||||
maxTextureDim: maxDim,
|
maxTextureDim: maxDim,
|
||||||
conf: new(config),
|
conf: new(config),
|
||||||
@@ -290,7 +288,7 @@ func (g *compute) Frame() error {
|
|||||||
Y: (viewport.Y + tileHeightPx - 1) / tileHeightPx,
|
Y: (viewport.Y + tileHeightPx - 1) / tileHeightPx,
|
||||||
}
|
}
|
||||||
|
|
||||||
g.ctx.BeginFrame()
|
defFBO := g.ctx.BeginFrame()
|
||||||
defer g.ctx.EndFrame()
|
defer g.ctx.EndFrame()
|
||||||
|
|
||||||
if err := g.uploadImages(g.drawOps.allImageOps); err != nil {
|
if err := g.uploadImages(g.drawOps.allImageOps); err != nil {
|
||||||
@@ -305,6 +303,7 @@ func (g *compute) Frame() error {
|
|||||||
if err := g.render(tileDims); err != nil {
|
if err := g.render(tileDims); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
g.ctx.BindFramebuffer(defFBO)
|
||||||
g.blitOutput(viewport)
|
g.blitOutput(viewport)
|
||||||
g.cache.frame()
|
g.cache.frame()
|
||||||
g.drawOps.pathCache.frame()
|
g.drawOps.pathCache.frame()
|
||||||
@@ -331,7 +330,6 @@ func (g *compute) Profile() string {
|
|||||||
// shader can only write to RGBA textures, but since we actually render in sRGB
|
// shader can only write to RGBA textures, but since we actually render in sRGB
|
||||||
// format we can't use glBlitFramebuffer, because it does sRGB conversion.
|
// format we can't use glBlitFramebuffer, because it does sRGB conversion.
|
||||||
func (g *compute) blitOutput(viewport image.Point) {
|
func (g *compute) blitOutput(viewport image.Point) {
|
||||||
g.ctx.BindFramebuffer(g.defFBO)
|
|
||||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||||
g.ctx.BindTexture(0, g.output.image)
|
g.ctx.BindTexture(0, g.output.image)
|
||||||
g.ctx.BindProgram(g.output.blitProg)
|
g.ctx.BindProgram(g.output.blitProg)
|
||||||
|
|||||||
+4
-3
@@ -167,9 +167,10 @@ func NewBackend(ctx Context) (*Backend, error) {
|
|||||||
return b, nil
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) BeginFrame() {
|
func (b *Backend) BeginFrame() backend.Framebuffer {
|
||||||
// Assume GL state is reset between frames.
|
// Assume GL state is reset between frames.
|
||||||
b.state = glstate{}
|
b.state = glstate{}
|
||||||
|
return b.currentFramebuffer()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) EndFrame() {
|
func (b *Backend) EndFrame() {
|
||||||
@@ -228,7 +229,7 @@ func (b *Backend) NewFramebuffer(tex backend.Texture, depthBits int) (backend.Fr
|
|||||||
return fbo, nil
|
return fbo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *Backend) CurrentFramebuffer() backend.Framebuffer {
|
func (b *Backend) currentFramebuffer() backend.Framebuffer {
|
||||||
fboID := glimpl.Framebuffer(b.funcs.GetBinding(glimpl.FRAMEBUFFER_BINDING))
|
fboID := glimpl.Framebuffer(b.funcs.GetBinding(glimpl.FRAMEBUFFER_BINDING))
|
||||||
return &gpuFramebuffer{backend: b, obj: fboID, foreign: true}
|
return &gpuFramebuffer{backend: b, obj: fboID, foreign: true}
|
||||||
}
|
}
|
||||||
@@ -802,7 +803,7 @@ func (f *gpuFramebuffer) Invalidate() {
|
|||||||
|
|
||||||
func (f *gpuFramebuffer) Release() {
|
func (f *gpuFramebuffer) Release() {
|
||||||
if f.foreign {
|
if f.foreign {
|
||||||
panic("cannot release framebuffer created by CurrentFramebuffer")
|
panic("framebuffer not created by NewBuffer")
|
||||||
}
|
}
|
||||||
f.backend.funcs.DeleteFramebuffer(f.obj)
|
f.backend.funcs.DeleteFramebuffer(f.obj)
|
||||||
if f.hasDepth {
|
if f.hasDepth {
|
||||||
|
|||||||
+5
-8
@@ -48,7 +48,6 @@ type GPU interface {
|
|||||||
type gpu struct {
|
type gpu struct {
|
||||||
cache *resourceCache
|
cache *resourceCache
|
||||||
|
|
||||||
defFBO backend.Framebuffer
|
|
||||||
profile string
|
profile string
|
||||||
timers *timers
|
timers *timers
|
||||||
frameStart time.Time
|
frameStart time.Time
|
||||||
@@ -395,10 +394,8 @@ func New(ctx backend.Device) (GPU, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func newGPU(ctx backend.Device) (*gpu, error) {
|
func newGPU(ctx backend.Device) (*gpu, error) {
|
||||||
defFBO := ctx.CurrentFramebuffer()
|
|
||||||
g := &gpu{
|
g := &gpu{
|
||||||
defFBO: defFBO,
|
cache: newResourceCache(),
|
||||||
cache: newResourceCache(),
|
|
||||||
}
|
}
|
||||||
g.drawOps.pathCache = newOpCache()
|
g.drawOps.pathCache = newOpCache()
|
||||||
if err := g.init(ctx); err != nil {
|
if err := g.init(ctx); err != nil {
|
||||||
@@ -443,7 +440,7 @@ func (g *gpu) Collect(viewport image.Point, frameOps *op.Ops) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *gpu) Frame() error {
|
func (g *gpu) Frame() error {
|
||||||
g.ctx.BeginFrame()
|
defFBO := g.ctx.BeginFrame()
|
||||||
defer g.ctx.EndFrame()
|
defer g.ctx.EndFrame()
|
||||||
viewport := g.renderer.blitter.viewport
|
viewport := g.renderer.blitter.viewport
|
||||||
for _, img := range g.drawOps.imageOps {
|
for _, img := range g.drawOps.imageOps {
|
||||||
@@ -452,7 +449,7 @@ func (g *gpu) Frame() error {
|
|||||||
if g.drawOps.profile {
|
if g.drawOps.profile {
|
||||||
g.zopsTimer.begin()
|
g.zopsTimer.begin()
|
||||||
}
|
}
|
||||||
g.ctx.BindFramebuffer(g.defFBO)
|
g.ctx.BindFramebuffer(defFBO)
|
||||||
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.
|
||||||
@@ -472,13 +469,13 @@ func (g *gpu) Frame() error {
|
|||||||
g.renderer.intersect(g.drawOps.imageOps)
|
g.renderer.intersect(g.drawOps.imageOps)
|
||||||
g.stencilTimer.end()
|
g.stencilTimer.end()
|
||||||
g.coverTimer.begin()
|
g.coverTimer.begin()
|
||||||
g.ctx.BindFramebuffer(g.defFBO)
|
g.ctx.BindFramebuffer(defFBO)
|
||||||
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
g.ctx.Viewport(0, 0, viewport.X, viewport.Y)
|
||||||
g.renderer.drawOps(g.cache, 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()
|
||||||
g.ctx.BindFramebuffer(g.defFBO)
|
g.ctx.BindFramebuffer(defFBO)
|
||||||
g.cleanupTimer.begin()
|
g.cleanupTimer.begin()
|
||||||
g.cache.frame()
|
g.cache.frame()
|
||||||
g.drawOps.pathCache.frame()
|
g.drawOps.pathCache.frame()
|
||||||
|
|||||||
Reference in New Issue
Block a user