app/internal/d3d11: add Direct3D backend

Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
Elias Naur
2020-02-15 19:26:16 +01:00
parent d65bfdc275
commit e03b3cd808
10 changed files with 2431 additions and 44 deletions
+102
View File
@@ -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
}
+17 -12
View File
@@ -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() {}
+30
View File
@@ -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 {