d3d11_windows.go 3.1 KB

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