mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-05 01:15:35 +00:00
app/internal/d3d11: add Direct3D backend
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
@@ -0,0 +1,102 @@
|
||||
// SPDX-License-Identifier: Unlicense OR MIT
|
||||
|
||||
package window
|
||||
|
||||
import (
|
||||
"gioui.org/app/internal/d3d11"
|
||||
"gioui.org/gpu/backend"
|
||||
)
|
||||
|
||||
type d3d11Context struct {
|
||||
win *window
|
||||
swchain *d3d11.SwapChain
|
||||
fbo *d3d11.Framebuffer
|
||||
backend backend.Device
|
||||
*d3d11.Device
|
||||
width, height int
|
||||
}
|
||||
|
||||
func init() {
|
||||
backends = append(backends, gpuAPI{
|
||||
priority: 1,
|
||||
initializer: func(w *window) (Context, error) {
|
||||
hwnd, _, _ := w.HWND()
|
||||
dev, err := d3d11.NewDevice()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
swchain, err := dev.CreateSwapChain(hwnd)
|
||||
if err != nil {
|
||||
dev.Release()
|
||||
return nil, err
|
||||
}
|
||||
return &d3d11Context{win: w, Device: dev, swchain: swchain}, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *d3d11Context) Backend() (backend.Device, error) {
|
||||
backend, err := d3d11.NewBackend(c.Device)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.backend = backend
|
||||
c.backend.BindFramebuffer(c.fbo)
|
||||
return backend, nil
|
||||
}
|
||||
|
||||
func (c *d3d11Context) Present() error {
|
||||
if err := c.swchain.Present(); err != nil {
|
||||
if err, ok := err.(d3d11.ErrorCode); ok {
|
||||
switch err.Code {
|
||||
case d3d11.DXGI_STATUS_OCCLUDED:
|
||||
// Ignore
|
||||
return nil
|
||||
case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED:
|
||||
return ErrDeviceLost
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *d3d11Context) MakeCurrent() error {
|
||||
_, width, height := c.win.HWND()
|
||||
if c.fbo != nil && width == c.width && height == c.height {
|
||||
c.backend.BindFramebuffer(c.fbo)
|
||||
return nil
|
||||
}
|
||||
if c.fbo != nil {
|
||||
c.fbo.Release()
|
||||
c.fbo = nil
|
||||
}
|
||||
if err := c.swchain.Resize(); err != nil {
|
||||
return err
|
||||
}
|
||||
c.width = width
|
||||
c.height = height
|
||||
fbo, err := c.swchain.Framebuffer(c.Device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.fbo = fbo
|
||||
if c.backend != nil {
|
||||
c.backend.BindFramebuffer(c.fbo)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *d3d11Context) Lock() {}
|
||||
|
||||
func (c *d3d11Context) Unlock() {}
|
||||
|
||||
func (c *d3d11Context) Release() {
|
||||
if c.fbo != nil {
|
||||
c.fbo.Release()
|
||||
}
|
||||
c.swchain.Release()
|
||||
c.Device.Release()
|
||||
c.fbo = nil
|
||||
c.swchain = nil
|
||||
c.Device = nil
|
||||
}
|
||||
@@ -6,28 +6,33 @@ import (
|
||||
"gioui.org/app/internal/egl"
|
||||
)
|
||||
|
||||
type context struct {
|
||||
type glContext struct {
|
||||
win *window
|
||||
*egl.Context
|
||||
}
|
||||
|
||||
func (w *window) NewContext() (Context, error) {
|
||||
disp := egl.NativeDisplayType(w.HDC())
|
||||
ctx, err := egl.NewContext(disp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &context{win: w, Context: ctx}, nil
|
||||
func init() {
|
||||
backends = append(backends, gpuAPI{
|
||||
priority: 2,
|
||||
initializer: func(w *window) (Context, error) {
|
||||
disp := egl.NativeDisplayType(w.HDC())
|
||||
ctx, err := egl.NewContext(disp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &glContext{win: w, Context: ctx}, nil
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (c *context) Release() {
|
||||
func (c *glContext) Release() {
|
||||
if c.Context != nil {
|
||||
c.Context.Release()
|
||||
c.Context = nil
|
||||
}
|
||||
}
|
||||
|
||||
func (c *context) MakeCurrent() error {
|
||||
func (c *glContext) MakeCurrent() error {
|
||||
c.Context.ReleaseSurface()
|
||||
win, width, height := c.win.HWND()
|
||||
eglSurf := egl.NativeWindowType(win)
|
||||
@@ -41,6 +46,6 @@ func (c *context) MakeCurrent() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *context) Lock() {}
|
||||
func (c *glContext) Lock() {}
|
||||
|
||||
func (c *context) Unlock() {}
|
||||
func (c *glContext) Unlock() {}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"image"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
"unicode"
|
||||
@@ -42,6 +43,15 @@ const _WM_REDRAW = windows.WM_USER + 0
|
||||
var onceMu sync.Mutex
|
||||
var mainDone = make(chan struct{})
|
||||
|
||||
// backends is the list of potential Context
|
||||
// implementations.
|
||||
var backends []gpuAPI
|
||||
|
||||
type gpuAPI struct {
|
||||
priority int
|
||||
initializer func(w *window) (Context, error)
|
||||
}
|
||||
|
||||
func Main() {
|
||||
<-mainDone
|
||||
}
|
||||
@@ -345,6 +355,26 @@ func (w *window) destroy() {
|
||||
}
|
||||
}
|
||||
|
||||
func (w *window) NewContext() (Context, error) {
|
||||
sort.Slice(backends, func(i, j int) bool {
|
||||
return backends[i].priority < backends[j].priority
|
||||
})
|
||||
var cerr error
|
||||
for _, b := range backends {
|
||||
ctx, err := b.initializer(w)
|
||||
if err == nil {
|
||||
return ctx, nil
|
||||
}
|
||||
if cerr == nil {
|
||||
cerr = err
|
||||
}
|
||||
}
|
||||
if cerr != nil {
|
||||
return nil, cerr
|
||||
}
|
||||
return nil, errors.New("NewContext: no available backends")
|
||||
}
|
||||
|
||||
func (w *window) ShowTextInput(show bool) {}
|
||||
|
||||
func (w *window) HDC() syscall.Handle {
|
||||
|
||||
Reference in New Issue
Block a user