mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 17:35:36 +00:00
gpu,gpu/headless,app/internal/wm: add explicit RenderTarget API
Both the OpenGL and the Direct3D API are stateful and gpu.GPU renders to the render target current when Frame is called. Modern GPU API such as Metal don't have a concept of a current render target, and the target even changes each frame. Add RenderTarget and add an explicit target argument to GPU.Frame as well as the underlying driver.Device.BeginFrame. Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -165,15 +165,23 @@ func newDirect3D11Device(api driver.Direct3D11) (driver.Device, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *Backend) BeginFrame(clear bool, viewport image.Point) driver.Framebuffer {
|
||||
renderTarget, depthView := b.ctx.OMGetRenderTargets()
|
||||
// Assume someone else is holding on to the render targets.
|
||||
if renderTarget != nil {
|
||||
d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
|
||||
}
|
||||
if depthView != nil {
|
||||
d3d11.IUnknownRelease(unsafe.Pointer(depthView), depthView.Vtbl.Release)
|
||||
func (b *Backend) BeginFrame(target driver.RenderTarget, clear bool, viewport image.Point) driver.Framebuffer {
|
||||
var (
|
||||
renderTarget *d3d11.RenderTargetView
|
||||
depthView *d3d11.DepthStencilView
|
||||
)
|
||||
if target != nil {
|
||||
switch t := target.(type) {
|
||||
case driver.Direct3D11RenderTarget:
|
||||
renderTarget = (*d3d11.RenderTargetView)(t.RenderTarget)
|
||||
depthView = (*d3d11.DepthStencilView)(t.DepthStencilView)
|
||||
case *Framebuffer:
|
||||
renderTarget, depthView = t.renderTarget, t.depthView
|
||||
default:
|
||||
panic(fmt.Errorf("opengl: invalid render target type: %T", target))
|
||||
}
|
||||
}
|
||||
b.ctx.OMSetRenderTargets(renderTarget, depthView)
|
||||
return &Framebuffer{ctx: b.ctx, dev: b.dev, renderTarget: renderTarget, depthView: depthView, foreign: true}
|
||||
}
|
||||
|
||||
@@ -713,6 +721,8 @@ func (f *Framebuffer) Release() {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *Framebuffer) ImplementsRenderTarget() {}
|
||||
|
||||
func (b *Backend) BindInputLayout(layout driver.InputLayout) {
|
||||
b.ctx.IASetInputLayout(layout.(*InputLayout).layout)
|
||||
}
|
||||
|
||||
@@ -15,6 +15,19 @@ type API interface {
|
||||
implementsAPI()
|
||||
}
|
||||
|
||||
type RenderTarget interface {
|
||||
ImplementsRenderTarget()
|
||||
}
|
||||
|
||||
type OpenGLRenderTarget gl.Framebuffer
|
||||
|
||||
type Direct3D11RenderTarget struct {
|
||||
// RenderTarget is a *ID3D11RenderTargetView.
|
||||
RenderTarget unsafe.Pointer
|
||||
// DepthStencilView is a *ID3D11DepthStencilView.
|
||||
DepthStencilView unsafe.Pointer
|
||||
}
|
||||
|
||||
type OpenGL struct {
|
||||
// ES forces the use of ANGLE OpenGL ES libraries on macOS. It is
|
||||
// ignored on all other platforms.
|
||||
@@ -55,5 +68,7 @@ func NewDevice(api API) (Device, error) {
|
||||
return nil, fmt.Errorf("driver: no driver available for the API %T", api)
|
||||
}
|
||||
|
||||
func (OpenGL) implementsAPI() {}
|
||||
func (Direct3D11) implementsAPI() {}
|
||||
func (OpenGL) implementsAPI() {}
|
||||
func (Direct3D11) implementsAPI() {}
|
||||
func (OpenGLRenderTarget) ImplementsRenderTarget() {}
|
||||
func (Direct3D11RenderTarget) ImplementsRenderTarget() {}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
// APIs such as OpenGL, Direct3D useful for rendering Gio
|
||||
// operations.
|
||||
type Device interface {
|
||||
BeginFrame(clear bool, viewport image.Point) Framebuffer
|
||||
BeginFrame(target RenderTarget, clear bool, viewport image.Point) Framebuffer
|
||||
EndFrame()
|
||||
Caps() Caps
|
||||
NewTimer() Timer
|
||||
@@ -155,6 +155,7 @@ type Buffer interface {
|
||||
}
|
||||
|
||||
type Framebuffer interface {
|
||||
RenderTarget
|
||||
Invalidate()
|
||||
Release()
|
||||
ReadPixels(src image.Rectangle, pixels []byte) error
|
||||
|
||||
@@ -212,12 +212,23 @@ func newOpenGLDevice(api driver.OpenGL) (driver.Device, error) {
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func (b *Backend) BeginFrame(clear bool, viewport image.Point) driver.Framebuffer {
|
||||
func (b *Backend) BeginFrame(target driver.RenderTarget, clear bool, viewport image.Point) driver.Framebuffer {
|
||||
b.clear = clear
|
||||
b.glstate = b.queryState()
|
||||
b.savedState = b.glstate
|
||||
b.state = state{}
|
||||
renderFBO := b.glstate.drawFBO
|
||||
var renderFBO gl.Framebuffer
|
||||
if target != nil {
|
||||
switch t := target.(type) {
|
||||
case driver.OpenGLRenderTarget:
|
||||
renderFBO = gl.Framebuffer(t)
|
||||
case *gpuFramebuffer:
|
||||
renderFBO = t.obj
|
||||
default:
|
||||
panic(fmt.Errorf("opengl: invalid render target type: %T", target))
|
||||
}
|
||||
}
|
||||
b.glstate.bindFramebuffer(b.funcs, gl.FRAMEBUFFER, renderFBO)
|
||||
if b.gles {
|
||||
// If the output framebuffer is not in the sRGB colorspace already, emulate it.
|
||||
var fbEncoding int
|
||||
@@ -1244,6 +1255,8 @@ func (f *gpuFramebuffer) Release() {
|
||||
}
|
||||
}
|
||||
|
||||
func (f *gpuFramebuffer) ImplementsRenderTarget() {}
|
||||
|
||||
func toTexFilter(f driver.TextureFilter) int {
|
||||
switch f {
|
||||
case driver.FilterNearest:
|
||||
|
||||
Reference in New Issue
Block a user