Class: WGPU::Surface

Inherits:
Object
  • Object
show all
Includes:
NativeResource
Defined in:
lib/wgpu/core/surface.rb,
sig/wgpu.rbs

Constant Summary

Constants included from NativeResource

NativeResource::GUARDED_METHOD_EXEMPTIONS

Instance Attribute Summary collapse

Attributes included from NativeResource

#label

Class Method Summary collapse

Instance Method Summary collapse

Methods included from NativeResource

included, #inspect, #released?, #use

Constructor Details

#initialize(handle, instance) ⇒ Surface

Wraps a native presentation surface.

Parameters:

  • handle (FFI::Pointer)

    native surface handle

  • instance (Instance)

    owning instance



93
94
95
96
97
98
# File 'lib/wgpu/core/surface.rb', line 93

def initialize(handle, instance)
  @handle = handle
  @instance = instance
  @configured = false
  @config = nil
end

Instance Attribute Details

#handleObject (readonly)

Returns the value of attribute handle.

Returns:

  • (Object)


5
6
7
# File 'lib/wgpu/core/surface.rb', line 5

def handle
  @handle
end

Class Method Details

.from_metal_layer(instance, layer) ⇒ Surface

Creates a surface backed by a Core Animation Metal layer.

Parameters:

Returns:

Raises:



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/wgpu/core/surface.rb', line 10

def self.from_metal_layer(instance, layer)
  source = Native::SurfaceSourceMetalLayer.new
  source[:chain][:next] = nil
  source[:chain][:s_type] = Native::SType[:surface_source_metal_layer]
  source[:layer] = layer

  desc = Native::SurfaceDescriptor.new
  desc[:next_in_chain] = source.to_ptr
  desc[:label][:data] = nil
  desc[:label][:length] = 0

  handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
  raise SurfaceError, "Failed to create surface from Metal layer" if handle.null?

  new(handle, instance)
end

.from_wayland_surface(instance, display, surface) ⇒ Surface

Creates a surface backed by a Wayland surface.

Parameters:

Returns:

Raises:



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'lib/wgpu/core/surface.rb', line 72

def self.from_wayland_surface(instance, display, surface)
  source = Native::SurfaceSourceWaylandSurface.new
  source[:chain][:next] = nil
  source[:chain][:s_type] = Native::SType[:surface_source_wayland_surface]
  source[:display] = display
  source[:surface] = surface

  desc = Native::SurfaceDescriptor.new
  desc[:next_in_chain] = source.to_ptr
  desc[:label][:data] = nil
  desc[:label][:length] = 0

  handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
  raise SurfaceError, "Failed to create surface from Wayland surface" if handle.null?

  new(handle, instance)
end

.from_windows_hwnd(instance, hinstance, hwnd) ⇒ Surface

Creates a surface backed by a Windows window handle.

Parameters:

Returns:

Raises:



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/wgpu/core/surface.rb', line 30

def self.from_windows_hwnd(instance, hinstance, hwnd)
  source = Native::SurfaceSourceWindowsHWND.new
  source[:chain][:next] = nil
  source[:chain][:s_type] = Native::SType[:surface_source_windows_hwnd]
  source[:hinstance] = hinstance
  source[:hwnd] = hwnd

  desc = Native::SurfaceDescriptor.new
  desc[:next_in_chain] = source.to_ptr
  desc[:label][:data] = nil
  desc[:label][:length] = 0

  handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
  raise SurfaceError, "Failed to create surface from Windows HWND" if handle.null?

  new(handle, instance)
end

.from_xlib_window(instance, display, window) ⇒ Surface

Creates a surface backed by an Xlib window.

Parameters:

Returns:

Raises:



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/wgpu/core/surface.rb', line 51

def self.from_xlib_window(instance, display, window)
  source = Native::SurfaceSourceXlibWindow.new
  source[:chain][:next] = nil
  source[:chain][:s_type] = Native::SType[:surface_source_xlib_window]
  source[:display] = display
  source[:window] = window

  desc = Native::SurfaceDescriptor.new
  desc[:next_in_chain] = source.to_ptr
  desc[:label][:data] = nil
  desc[:label][:length] = 0

  handle = Native.wgpuInstanceCreateSurface(instance.handle, desc)
  raise SurfaceError, "Failed to create surface from Xlib window" if handle.null?

  new(handle, instance)
end

Instance Method Details

#capabilities(adapter) ⇒ Hash

Returns the formats, presentation modes, alpha modes, and usages supported by an adapter.

Parameters:

Returns:

  • (Hash)


217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
# File 'lib/wgpu/core/surface.rb', line 217

def capabilities(adapter)
  caps = Native::SurfaceCapabilities.new
  Native.wgpuSurfaceGetCapabilities(@handle, adapter.handle, caps)

  formats = []
  if caps[:format_count] > 0 && !caps[:formats].null?
    formats = caps[:formats].read_array_of_uint32(caps[:format_count]).map do |f|
      Native::TextureFormat[f]
    end
  end

  present_modes = []
  if caps[:present_mode_count] > 0 && !caps[:present_modes].null?
    present_modes = caps[:present_modes].read_array_of_uint32(caps[:present_mode_count]).map do |m|
      Native::PresentMode[m]
    end
  end

  alpha_modes = []
  if caps[:alpha_mode_count] > 0 && !caps[:alpha_modes].null?
    alpha_modes = caps[:alpha_modes].read_array_of_uint32(caps[:alpha_mode_count]).map do |a|
      Native::CompositeAlphaMode[a]
    end
  end

  {
    formats: formats,
    present_modes: present_modes,
    alpha_modes: alpha_modes,
    usages: caps[:usages]
  }
ensure
  Native.wgpuSurfaceCapabilitiesFreeMembers(caps) if caps
end

#configure(device:, format:, usage: :render_attachment, width:, height:, present_mode: :fifo, alpha_mode: :auto, view_formats: []) ⇒ Hash

Configures this surface for presentation by a device.

Parameters:

  • (Object)

Returns:

  • (Hash)

    stored configuration



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/wgpu/core/surface.rb', line 102

def configure(device:, format:, usage: :render_attachment, width:, height:, present_mode: :fifo, alpha_mode: :auto, view_formats: [])
  config = Native::SurfaceConfiguration.new
  config[:next_in_chain] = nil
  config[:device] = device.handle
  config[:format] = Native::EnumHelper.coerce(Native::TextureFormat, format, name: "surface format")
  config[:usage] = normalize_usage(usage)
  config[:width] = width
  config[:height] = height
  config[:view_format_count] = view_formats.size
  if view_formats.empty?
    @view_formats_ptr = nil
    config[:view_formats] = nil
  else
    format_values = view_formats.map do |view_format|
      Native::EnumHelper.coerce(Native::TextureFormat, view_format, name: "view format")
    end
    @view_formats_ptr = FFI::MemoryPointer.new(:uint32, format_values.size)
    @view_formats_ptr.write_array_of_uint32(format_values)
    config[:view_formats] = @view_formats_ptr
  end
  config[:alpha_mode] = Native::EnumHelper.coerce(
    Native::CompositeAlphaMode,
    alpha_mode,
    name: "alpha mode"
  )
  config[:present_mode] = Native::EnumHelper.coerce(
    Native::PresentMode,
    present_mode,
    name: "present mode"
  )

  Native.wgpuSurfaceConfigure(@handle, config)
  release_device_callback_lifetime
  @configured = true
  @device = device
  attach_device_callback_lifetime(device)
  @config = {
    device: device,
    format: format,
    usage: usage,
    width: width,
    height: height,
    present_mode: present_mode,
    alpha_mode: alpha_mode,
    view_formats: view_formats
  }
end

#current_textureTexture

Acquires the current surface texture.

Returns:

Raises:



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/wgpu/core/surface.rb', line 164

def current_texture
  raise SurfaceError, "Surface is not configured" unless @configured

  surface_texture = Native::SurfaceTexture.new
  Native.wgpuSurfaceGetCurrentTexture(@handle, surface_texture)

  status = Native::SurfaceGetCurrentTextureStatus[surface_texture[:status]]
  unless status == :success_optimal || status == :success_suboptimal
    raise SurfaceAcquisitionError.new(status)
  end

  texture_ptr = surface_texture[:texture]
  if texture_ptr.nil? || texture_ptr.null?
    raise SurfaceError, "Surface returned null texture"
  end

  Texture.from_handle(texture_ptr, surface_status: status, device: @device)
end

#get_configurationHash?

Returns the most recent surface configuration.

Returns:

  • (Hash, nil)

    configuration options, or nil when unconfigured



201
202
203
# File 'lib/wgpu/core/surface.rb', line 201

def get_configuration
  @config
end

#get_current_textureTexture

Acquires the texture for the current presentation frame.

Returns:

  • (Texture)

    acquired surface texture

Raises:



188
189
190
# File 'lib/wgpu/core/surface.rb', line 188

def get_current_texture
  current_texture
end

#get_preferred_format(adapter) ⇒ Symbol

Returns the first surface format supported by an adapter.

Parameters:

  • adapter (Adapter)

    adapter used to query surface capabilities

  • (Adapter)

Returns:

  • (Symbol)

    preferred texture format



209
210
211
212
# File 'lib/wgpu/core/surface.rb', line 209

def get_preferred_format(adapter)
  caps = capabilities(adapter)
  caps[:formats].first || :bgra8_unorm
end

#presentvoid

This method returns an undefined value.

Presents the current surface texture.



194
195
196
# File 'lib/wgpu/core/surface.rb', line 194

def present
  Native.wgpuSurfacePresent(@handle)
end

#releasevoid

This method returns an undefined value.

Releases the native surface handle.

Calling this method more than once has no effect.



256
257
258
259
260
# File 'lib/wgpu/core/surface.rb', line 256

def release
  return if @handle.null?
  Native.wgpuSurfaceRelease(@handle)
  @handle = FFI::Pointer::NULL
end

#unconfigurevoid

This method returns an undefined value.

Removes the current surface configuration.



152
153
154
155
156
157
158
# File 'lib/wgpu/core/surface.rb', line 152

def unconfigure
  Native.wgpuSurfaceUnconfigure(@handle)
  release_device_callback_lifetime
  @configured = false
  @device = nil
  @config = nil
end