surface.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. //go:build !js
  2. package wgpu
  3. /*
  4. #include <stdlib.h>
  5. #include "./lib/wgpu.h"
  6. extern void gowebgpu_error_callback_c(WGPUErrorType type, char const * message, void * userdata);
  7. static inline WGPUTexture gowebgpu_surface_get_current_texture(WGPUSurface surface, WGPUDevice device, void * error_userdata) {
  8. WGPUSurfaceTexture ref;
  9. wgpuDevicePushErrorScope(device, WGPUErrorFilter_Validation);
  10. wgpuSurfaceGetCurrentTexture(surface, &ref);
  11. wgpuDevicePopErrorScope(device, gowebgpu_error_callback_c, error_userdata);
  12. return ref.texture;
  13. }
  14. */
  15. import "C"
  16. import (
  17. "errors"
  18. "runtime/cgo"
  19. "unsafe"
  20. )
  21. type Surface struct {
  22. deviceRef C.WGPUDevice
  23. ref C.WGPUSurface
  24. }
  25. func (p *Surface) GetCapabilities(adapter *Adapter) (ret SurfaceCapabilities) {
  26. var caps C.WGPUSurfaceCapabilities
  27. C.wgpuSurfaceGetCapabilities(p.ref, adapter.ref, &caps)
  28. if caps.alphaModeCount == 0 && caps.formatCount == 0 && caps.presentModeCount == 0 {
  29. return
  30. }
  31. if caps.formatCount > 0 {
  32. caps.formats = (*C.WGPUTextureFormat)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUTextureFormat(0))) * caps.formatCount))
  33. defer C.free(unsafe.Pointer(caps.formats))
  34. }
  35. if caps.presentModeCount > 0 {
  36. caps.presentModes = (*C.WGPUPresentMode)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUPresentMode(0))) * caps.presentModeCount))
  37. defer C.free(unsafe.Pointer(caps.presentModes))
  38. }
  39. if caps.alphaModeCount > 0 {
  40. caps.alphaModes = (*C.WGPUCompositeAlphaMode)(C.malloc(C.size_t(unsafe.Sizeof(C.WGPUCompositeAlphaMode(0))) * caps.alphaModeCount))
  41. defer C.free(unsafe.Pointer(caps.alphaModes))
  42. }
  43. C.wgpuSurfaceGetCapabilities(p.ref, adapter.ref, &caps)
  44. if caps.formatCount > 0 {
  45. formatsTmp := unsafe.Slice((*TextureFormat)(caps.formats), caps.formatCount)
  46. ret.Formats = make([]TextureFormat, caps.formatCount)
  47. copy(ret.Formats, formatsTmp)
  48. }
  49. if caps.presentModeCount > 0 {
  50. presentModesTmp := unsafe.Slice((*PresentMode)(caps.presentModes), caps.presentModeCount)
  51. ret.PresentModes = make([]PresentMode, caps.presentModeCount)
  52. copy(ret.PresentModes, presentModesTmp)
  53. }
  54. if caps.alphaModeCount > 0 {
  55. alphaModesTmp := unsafe.Slice((*CompositeAlphaMode)(caps.alphaModes), caps.alphaModeCount)
  56. ret.AlphaModes = make([]CompositeAlphaMode, caps.alphaModeCount)
  57. copy(ret.AlphaModes, alphaModesTmp)
  58. }
  59. return
  60. }
  61. func (p *Surface) Configure(adapter *Adapter, device *Device, config *SurfaceConfiguration) {
  62. p.deviceRef = device.ref
  63. var cfg *C.WGPUSurfaceConfiguration
  64. if config != nil {
  65. cfg = &C.WGPUSurfaceConfiguration{
  66. device: p.deviceRef,
  67. format: C.WGPUTextureFormat(config.Format),
  68. usage: C.WGPUTextureUsageFlags(config.Usage),
  69. alphaMode: C.WGPUCompositeAlphaMode(config.AlphaMode),
  70. width: C.uint32_t(config.Width),
  71. height: C.uint32_t(config.Height),
  72. presentMode: C.WGPUPresentMode(config.PresentMode),
  73. }
  74. viewFormatCount := len(config.ViewFormats)
  75. if viewFormatCount > 0 {
  76. viewFormats := C.malloc(C.size_t(unsafe.Sizeof(C.WGPUTextureFormat(0))) * C.size_t(viewFormatCount))
  77. defer C.free(viewFormats)
  78. viewFormatsSlice := unsafe.Slice((*TextureFormat)(viewFormats), viewFormatCount)
  79. copy(viewFormatsSlice, config.ViewFormats)
  80. cfg.viewFormatCount = C.size_t(viewFormatCount)
  81. cfg.viewFormats = (*C.WGPUTextureFormat)(viewFormats)
  82. }
  83. }
  84. C.wgpuSurfaceConfigure(p.ref, cfg)
  85. }
  86. // NOTE: you should typically not call [Texture.Release] on the returned texture.
  87. // Instead, you should call [TextureView.Release] on any [TextureView] you create from it.
  88. func (p *Surface) GetCurrentTexture() (*Texture, error) {
  89. var err error = nil
  90. var cb errorCallback = func(_ ErrorType, message string) {
  91. err = errors.New("wgpu.(*Surface).GetCurrentTexture(): " + message)
  92. }
  93. errorCallbackHandle := cgo.NewHandle(cb)
  94. defer errorCallbackHandle.Delete()
  95. ref := C.gowebgpu_surface_get_current_texture(
  96. p.ref,
  97. p.deviceRef,
  98. unsafe.Pointer(&errorCallbackHandle),
  99. )
  100. if err != nil {
  101. if ref != nil {
  102. C.wgpuTextureRelease(ref)
  103. }
  104. return nil, err
  105. }
  106. return &Texture{p.deviceRef, ref}, nil
  107. }
  108. func (p *Surface) Present() {
  109. C.wgpuSurfacePresent(p.ref)
  110. }
  111. func (p *Surface) Release() {
  112. C.wgpuSurfaceRelease(p.ref)
  113. }