diff options
Diffstat (limited to 'vendor/gioui.org/app/d3d11_windows.go')
-rw-r--r-- | vendor/gioui.org/app/d3d11_windows.go | 135 |
1 files changed, 135 insertions, 0 deletions
diff --git a/vendor/gioui.org/app/d3d11_windows.go b/vendor/gioui.org/app/d3d11_windows.go new file mode 100644 index 0000000..ab04ee4 --- /dev/null +++ b/vendor/gioui.org/app/d3d11_windows.go @@ -0,0 +1,135 @@ +// SPDX-License-Identifier: Unlicense OR MIT + +package app + +import ( + "fmt" + "unsafe" + + "gioui.org/gpu" + "gioui.org/internal/d3d11" +) + +type d3d11Context struct { + win *window + dev *d3d11.Device + ctx *d3d11.DeviceContext + + swchain *d3d11.IDXGISwapChain + renderTarget *d3d11.RenderTargetView + width, height int +} + +const debug = false + +func init() { + drivers = append(drivers, gpuAPI{ + priority: 1, + initializer: func(w *window) (context, error) { + hwnd, _, _ := w.HWND() + var flags uint32 + if debug { + flags |= d3d11.CREATE_DEVICE_DEBUG + } + dev, ctx, _, err := d3d11.CreateDevice( + d3d11.DRIVER_TYPE_HARDWARE, + flags, + ) + if err != nil { + return nil, fmt.Errorf("NewContext: %v", err) + } + swchain, err := d3d11.CreateSwapChain(dev, hwnd) + if err != nil { + d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release) + d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release) + return nil, err + } + return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil + }, + }) +} + +func (c *d3d11Context) API() gpu.API { + return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)} +} + +func (c *d3d11Context) RenderTarget() (gpu.RenderTarget, error) { + return gpu.Direct3D11RenderTarget{ + RenderTarget: unsafe.Pointer(c.renderTarget), + }, nil +} + +func (c *d3d11Context) Present() error { + err := c.swchain.Present(1, 0) + if err == nil { + return 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 gpu.ErrDeviceLost + } + } + return err +} + +func (c *d3d11Context) Refresh() error { + var width, height int + _, width, height = c.win.HWND() + if c.renderTarget != nil && width == c.width && height == c.height { + return nil + } + c.releaseFBO() + if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil { + return err + } + c.width = width + c.height = height + + backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D) + if err != nil { + return err + } + texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer)) + renderTarget, err := c.dev.CreateRenderTargetView(texture) + d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release) + if err != nil { + return err + } + c.renderTarget = renderTarget + return nil +} + +func (c *d3d11Context) Lock() error { + c.ctx.OMSetRenderTargets(c.renderTarget, nil) + return nil +} + +func (c *d3d11Context) Unlock() {} + +func (c *d3d11Context) Release() { + c.releaseFBO() + if c.swchain != nil { + d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release) + } + if c.ctx != nil { + d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release) + } + if c.dev != nil { + d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release) + } + *c = d3d11Context{} + if debug { + d3d11.ReportLiveObjects() + } +} + +func (c *d3d11Context) releaseFBO() { + if c.renderTarget != nil { + d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release) + c.renderTarget = nil + } +} |