d3d11_windows.go raw
1 // SPDX-License-Identifier: Unlicense OR MIT
2
3 package wm
4
5 import (
6 "fmt"
7 "unsafe"
8
9 "github.com/p9c/p9/pkg/gel/gio/gpu"
10 "github.com/p9c/p9/pkg/gel/gio/internal/d3d11"
11 )
12
13 type d3d11Context struct {
14 win *window
15 dev *d3d11.Device
16 ctx *d3d11.DeviceContext
17
18 swchain *d3d11.IDXGISwapChain
19 renderTarget *d3d11.RenderTargetView
20 depthView *d3d11.DepthStencilView
21 width, height int
22 }
23
24 const debug = false
25
26 func init() {
27 drivers = append(drivers, gpuAPI{
28 priority: 1,
29 initializer: func(w *window) (Context, error) {
30 hwnd, _, _ := w.HWND()
31 var flags uint32
32 if debug {
33 flags |= d3d11.CREATE_DEVICE_DEBUG
34 }
35 dev, ctx, _, err := d3d11.CreateDevice(
36 d3d11.DRIVER_TYPE_HARDWARE,
37 flags,
38 )
39 if err != nil {
40 return nil, fmt.Errorf("NewContext: %v", err)
41 }
42 swchain, err := d3d11.CreateSwapChain(dev, hwnd)
43 if err != nil {
44 d3d11.IUnknownRelease(unsafe.Pointer(ctx), ctx.Vtbl.Release)
45 d3d11.IUnknownRelease(unsafe.Pointer(dev), dev.Vtbl.Release)
46 return nil, err
47 }
48 return &d3d11Context{win: w, dev: dev, ctx: ctx, swchain: swchain}, nil
49 },
50 })
51 }
52
53 func (c *d3d11Context) API() gpu.API {
54 return gpu.Direct3D11{Device: unsafe.Pointer(c.dev)}
55 }
56
57 func (c *d3d11Context) Present() error {
58 err := c.swchain.Present(1, 0)
59 if err == nil {
60 return nil
61 }
62 if err, ok := err.(d3d11.ErrorCode); ok {
63 switch err.Code {
64 case d3d11.DXGI_STATUS_OCCLUDED:
65 // Ignore
66 return nil
67 case d3d11.DXGI_ERROR_DEVICE_RESET, d3d11.DXGI_ERROR_DEVICE_REMOVED, d3d11.D3DDDIERR_DEVICEREMOVED:
68 return ErrDeviceLost
69 }
70 }
71 return err
72 }
73
74 func (c *d3d11Context) MakeCurrent() error {
75 _, width, height := c.win.HWND()
76 if c.renderTarget != nil && width == c.width && height == c.height {
77 c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
78 return nil
79 }
80 c.releaseFBO()
81 if err := c.swchain.ResizeBuffers(0, 0, 0, d3d11.DXGI_FORMAT_UNKNOWN, 0); err != nil {
82 return err
83 }
84 c.width = width
85 c.height = height
86
87 desc, err := c.swchain.GetDesc()
88 if err != nil {
89 return err
90 }
91 backBuffer, err := c.swchain.GetBuffer(0, &d3d11.IID_Texture2D)
92 if err != nil {
93 return err
94 }
95 texture := (*d3d11.Resource)(unsafe.Pointer(backBuffer))
96 renderTarget, err := c.dev.CreateRenderTargetView(texture)
97 d3d11.IUnknownRelease(unsafe.Pointer(backBuffer), backBuffer.Vtbl.Release)
98 if err != nil {
99 return err
100 }
101 depthView, err := d3d11.CreateDepthView(c.dev, int(desc.BufferDesc.Width), int(desc.BufferDesc.Height), 24)
102 if err != nil {
103 d3d11.IUnknownRelease(unsafe.Pointer(renderTarget), renderTarget.Vtbl.Release)
104 return err
105 }
106 c.renderTarget = renderTarget
107 c.depthView = depthView
108
109 c.ctx.OMSetRenderTargets(c.renderTarget, c.depthView)
110 return nil
111 }
112
113 func (c *d3d11Context) Lock() {}
114
115 func (c *d3d11Context) Unlock() {}
116
117 func (c *d3d11Context) Release() {
118 c.releaseFBO()
119 if c.swchain != nil {
120 d3d11.IUnknownRelease(unsafe.Pointer(c.swchain), c.swchain.Vtbl.Release)
121 }
122 if c.ctx != nil {
123 d3d11.IUnknownRelease(unsafe.Pointer(c.ctx), c.ctx.Vtbl.Release)
124 }
125 if c.dev != nil {
126 d3d11.IUnknownRelease(unsafe.Pointer(c.dev), c.dev.Vtbl.Release)
127 }
128 *c = d3d11Context{}
129 }
130
131 func (c *d3d11Context) releaseFBO() {
132 if c.depthView != nil {
133 d3d11.IUnknownRelease(unsafe.Pointer(c.depthView), c.depthView.Vtbl.Release)
134 c.depthView = nil
135 }
136 if c.renderTarget != nil {
137 d3d11.IUnknownRelease(unsafe.Pointer(c.renderTarget), c.renderTarget.Vtbl.Release)
138 c.renderTarget = nil
139 }
140 }
141