aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/internal
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/internal')
-rw-r--r--vendor/gioui.org/internal/byteslice/byteslice.go45
-rw-r--r--vendor/gioui.org/internal/cocoainit/cocoa_darwin.go20
-rw-r--r--vendor/gioui.org/internal/d3d11/d3d11_windows.go1682
-rw-r--r--vendor/gioui.org/internal/egl/egl.go253
-rw-r--r--vendor/gioui.org/internal/egl/egl_unix.go109
-rw-r--r--vendor/gioui.org/internal/egl/egl_windows.go169
-rw-r--r--vendor/gioui.org/internal/f32color/rgba.go128
-rw-r--r--vendor/gioui.org/internal/gl/gl.go130
-rw-r--r--vendor/gioui.org/internal/gl/gl_js.go458
-rw-r--r--vendor/gioui.org/internal/gl/gl_unix.go1222
-rw-r--r--vendor/gioui.org/internal/gl/gl_windows.go502
-rw-r--r--vendor/gioui.org/internal/gl/types.go77
-rw-r--r--vendor/gioui.org/internal/gl/types_js.go90
-rw-r--r--vendor/gioui.org/internal/gl/util.go87
-rw-r--r--vendor/gioui.org/internal/opconst/ops.go84
-rw-r--r--vendor/gioui.org/internal/ops/ops.go471
-rw-r--r--vendor/gioui.org/internal/ops/reader.go121
-rw-r--r--vendor/gioui.org/internal/scene/scene.go251
-rw-r--r--vendor/gioui.org/internal/stroke/stroke.go742
-rw-r--r--vendor/gioui.org/internal/unsafe/unsafe.go46
-rw-r--r--vendor/gioui.org/internal/vk/vulkan.go2081
-rw-r--r--vendor/gioui.org/internal/vk/vulkan_android.go45
-rw-r--r--vendor/gioui.org/internal/vk/vulkan_wayland.go46
-rw-r--r--vendor/gioui.org/internal/vk/vulkan_x11.go46
24 files changed, 8681 insertions, 224 deletions
diff --git a/vendor/gioui.org/internal/byteslice/byteslice.go b/vendor/gioui.org/internal/byteslice/byteslice.go
new file mode 100644
index 0000000..26ebdb2
--- /dev/null
+++ b/vendor/gioui.org/internal/byteslice/byteslice.go
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// Package byteslice provides byte slice views of other Go values such as
+// slices and structs.
+package byteslice
+
+import (
+ "reflect"
+ "unsafe"
+)
+
+// Struct returns a byte slice view of a struct.
+func Struct(s interface{}) []byte {
+ v := reflect.ValueOf(s).Elem()
+ sz := int(v.Type().Size())
+ var res []byte
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ h.Data = uintptr(unsafe.Pointer(v.UnsafeAddr()))
+ h.Cap = sz
+ h.Len = sz
+ return res
+}
+
+// Uint32 returns a byte slice view of a uint32 slice.
+func Uint32(s []uint32) []byte {
+ n := len(s)
+ if n == 0 {
+ return nil
+ }
+ blen := n * int(unsafe.Sizeof(s[0]))
+ return (*[1 << 30]byte)(unsafe.Pointer(&s[0]))[:blen:blen]
+}
+
+// Slice returns a byte slice view of a slice.
+func Slice(s interface{}) []byte {
+ v := reflect.ValueOf(s)
+ first := v.Index(0)
+ sz := int(first.Type().Size())
+ var res []byte
+ h := (*reflect.SliceHeader)(unsafe.Pointer(&res))
+ h.Data = first.UnsafeAddr()
+ h.Cap = v.Cap() * sz
+ h.Len = v.Len() * sz
+ return res
+}
diff --git a/vendor/gioui.org/internal/cocoainit/cocoa_darwin.go b/vendor/gioui.org/internal/cocoainit/cocoa_darwin.go
new file mode 100644
index 0000000..2a34e57
--- /dev/null
+++ b/vendor/gioui.org/internal/cocoainit/cocoa_darwin.go
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// Package cocoainit initializes support for multithreaded
+// programs in Cocoa.
+package cocoainit
+
+/*
+#cgo CFLAGS: -xobjective-c -fmodules -fobjc-arc
+#import <Foundation/Foundation.h>
+
+static inline void activate_cocoa_multithreading() {
+ [[NSThread new] start];
+}
+#pragma GCC visibility push(hidden)
+*/
+import "C"
+
+func init() {
+ C.activate_cocoa_multithreading()
+}
diff --git a/vendor/gioui.org/internal/d3d11/d3d11_windows.go b/vendor/gioui.org/internal/d3d11/d3d11_windows.go
new file mode 100644
index 0000000..450fde1
--- /dev/null
+++ b/vendor/gioui.org/internal/d3d11/d3d11_windows.go
@@ -0,0 +1,1682 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package d3d11
+
+import (
+ "fmt"
+ "math"
+ "syscall"
+ "unsafe"
+
+ "gioui.org/internal/f32color"
+
+ "golang.org/x/sys/windows"
+)
+
+type DXGI_SWAP_CHAIN_DESC struct {
+ BufferDesc DXGI_MODE_DESC
+ SampleDesc DXGI_SAMPLE_DESC
+ BufferUsage uint32
+ BufferCount uint32
+ OutputWindow windows.Handle
+ Windowed uint32
+ SwapEffect uint32
+ Flags uint32
+}
+
+type DXGI_SAMPLE_DESC struct {
+ Count uint32
+ Quality uint32
+}
+
+type DXGI_MODE_DESC struct {
+ Width uint32
+ Height uint32
+ RefreshRate DXGI_RATIONAL
+ Format uint32
+ ScanlineOrdering uint32
+ Scaling uint32
+}
+
+type DXGI_RATIONAL struct {
+ Numerator uint32
+ Denominator uint32
+}
+
+type TEXTURE2D_DESC struct {
+ Width uint32
+ Height uint32
+ MipLevels uint32
+ ArraySize uint32
+ Format uint32
+ SampleDesc DXGI_SAMPLE_DESC
+ Usage uint32
+ BindFlags uint32
+ CPUAccessFlags uint32
+ MiscFlags uint32
+}
+
+type SAMPLER_DESC struct {
+ Filter uint32
+ AddressU uint32
+ AddressV uint32
+ AddressW uint32
+ MipLODBias float32
+ MaxAnisotropy uint32
+ ComparisonFunc uint32
+ BorderColor [4]float32
+ MinLOD float32
+ MaxLOD float32
+}
+
+type SHADER_RESOURCE_VIEW_DESC_TEX2D struct {
+ SHADER_RESOURCE_VIEW_DESC
+ Texture2D TEX2D_SRV
+}
+
+type SHADER_RESOURCE_VIEW_DESC_BUFFEREX struct {
+ SHADER_RESOURCE_VIEW_DESC
+ Buffer BUFFEREX_SRV
+}
+
+type UNORDERED_ACCESS_VIEW_DESC_TEX2D struct {
+ UNORDERED_ACCESS_VIEW_DESC
+ Texture2D TEX2D_UAV
+}
+
+type UNORDERED_ACCESS_VIEW_DESC_BUFFER struct {
+ UNORDERED_ACCESS_VIEW_DESC
+ Buffer BUFFER_UAV
+}
+
+type SHADER_RESOURCE_VIEW_DESC struct {
+ Format uint32
+ ViewDimension uint32
+}
+
+type UNORDERED_ACCESS_VIEW_DESC struct {
+ Format uint32
+ ViewDimension uint32
+}
+
+type TEX2D_SRV struct {
+ MostDetailedMip uint32
+ MipLevels uint32
+}
+
+type BUFFEREX_SRV struct {
+ FirstElement uint32
+ NumElements uint32
+ Flags uint32
+}
+
+type TEX2D_UAV struct {
+ MipSlice uint32
+}
+
+type BUFFER_UAV struct {
+ FirstElement uint32
+ NumElements uint32
+ Flags uint32
+}
+
+type INPUT_ELEMENT_DESC struct {
+ SemanticName *byte
+ SemanticIndex uint32
+ Format uint32
+ InputSlot uint32
+ AlignedByteOffset uint32
+ InputSlotClass uint32
+ InstanceDataStepRate uint32
+}
+
+type IDXGISwapChain struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetPrivateData uintptr
+ GetParent uintptr
+ GetDevice uintptr
+ Present uintptr
+ GetBuffer uintptr
+ SetFullscreenState uintptr
+ GetFullscreenState uintptr
+ GetDesc uintptr
+ ResizeBuffers uintptr
+ ResizeTarget uintptr
+ GetContainingOutput uintptr
+ GetFrameStatistics uintptr
+ GetLastPresentCount uintptr
+ }
+}
+
+type Debug struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetFeatureMask uintptr
+ GetFeatureMask uintptr
+ SetPresentPerRenderOpDelay uintptr
+ GetPresentPerRenderOpDelay uintptr
+ SetSwapChain uintptr
+ GetSwapChain uintptr
+ ValidateContext uintptr
+ ReportLiveDeviceObjects uintptr
+ ValidateContextForDispatch uintptr
+ }
+}
+
+type Device struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ CreateBuffer uintptr
+ CreateTexture1D uintptr
+ CreateTexture2D uintptr
+ CreateTexture3D uintptr
+ CreateShaderResourceView uintptr
+ CreateUnorderedAccessView uintptr
+ CreateRenderTargetView uintptr
+ CreateDepthStencilView uintptr
+ CreateInputLayout uintptr
+ CreateVertexShader uintptr
+ CreateGeometryShader uintptr
+ CreateGeometryShaderWithStreamOutput uintptr
+ CreatePixelShader uintptr
+ CreateHullShader uintptr
+ CreateDomainShader uintptr
+ CreateComputeShader uintptr
+ CreateClassLinkage uintptr
+ CreateBlendState uintptr
+ CreateDepthStencilState uintptr
+ CreateRasterizerState uintptr
+ CreateSamplerState uintptr
+ CreateQuery uintptr
+ CreatePredicate uintptr
+ CreateCounter uintptr
+ CreateDeferredContext uintptr
+ OpenSharedResource uintptr
+ CheckFormatSupport uintptr
+ CheckMultisampleQualityLevels uintptr
+ CheckCounterInfo uintptr
+ CheckCounter uintptr
+ CheckFeatureSupport uintptr
+ GetPrivateData uintptr
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetFeatureLevel uintptr
+ GetCreationFlags uintptr
+ GetDeviceRemovedReason uintptr
+ GetImmediateContext uintptr
+ SetExceptionMode uintptr
+ GetExceptionMode uintptr
+ }
+}
+
+type DeviceContext struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ GetDevice uintptr
+ GetPrivateData uintptr
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ VSSetConstantBuffers uintptr
+ PSSetShaderResources uintptr
+ PSSetShader uintptr
+ PSSetSamplers uintptr
+ VSSetShader uintptr
+ DrawIndexed uintptr
+ Draw uintptr
+ Map uintptr
+ Unmap uintptr
+ PSSetConstantBuffers uintptr
+ IASetInputLayout uintptr
+ IASetVertexBuffers uintptr
+ IASetIndexBuffer uintptr
+ DrawIndexedInstanced uintptr
+ DrawInstanced uintptr
+ GSSetConstantBuffers uintptr
+ GSSetShader uintptr
+ IASetPrimitiveTopology uintptr
+ VSSetShaderResources uintptr
+ VSSetSamplers uintptr
+ Begin uintptr
+ End uintptr
+ GetData uintptr
+ SetPredication uintptr
+ GSSetShaderResources uintptr
+ GSSetSamplers uintptr
+ OMSetRenderTargets uintptr
+ OMSetRenderTargetsAndUnorderedAccessViews uintptr
+ OMSetBlendState uintptr
+ OMSetDepthStencilState uintptr
+ SOSetTargets uintptr
+ DrawAuto uintptr
+ DrawIndexedInstancedIndirect uintptr
+ DrawInstancedIndirect uintptr
+ Dispatch uintptr
+ DispatchIndirect uintptr
+ RSSetState uintptr
+ RSSetViewports uintptr
+ RSSetScissorRects uintptr
+ CopySubresourceRegion uintptr
+ CopyResource uintptr
+ UpdateSubresource uintptr
+ CopyStructureCount uintptr
+ ClearRenderTargetView uintptr
+ ClearUnorderedAccessViewUint uintptr
+ ClearUnorderedAccessViewFloat uintptr
+ ClearDepthStencilView uintptr
+ GenerateMips uintptr
+ SetResourceMinLOD uintptr
+ GetResourceMinLOD uintptr
+ ResolveSubresource uintptr
+ ExecuteCommandList uintptr
+ HSSetShaderResources uintptr
+ HSSetShader uintptr
+ HSSetSamplers uintptr
+ HSSetConstantBuffers uintptr
+ DSSetShaderResources uintptr
+ DSSetShader uintptr
+ DSSetSamplers uintptr
+ DSSetConstantBuffers uintptr
+ CSSetShaderResources uintptr
+ CSSetUnorderedAccessViews uintptr
+ CSSetShader uintptr
+ CSSetSamplers uintptr
+ CSSetConstantBuffers uintptr
+ VSGetConstantBuffers uintptr
+ PSGetShaderResources uintptr
+ PSGetShader uintptr
+ PSGetSamplers uintptr
+ VSGetShader uintptr
+ PSGetConstantBuffers uintptr
+ IAGetInputLayout uintptr
+ IAGetVertexBuffers uintptr
+ IAGetIndexBuffer uintptr
+ GSGetConstantBuffers uintptr
+ GSGetShader uintptr
+ IAGetPrimitiveTopology uintptr
+ VSGetShaderResources uintptr
+ VSGetSamplers uintptr
+ GetPredication uintptr
+ GSGetShaderResources uintptr
+ GSGetSamplers uintptr
+ OMGetRenderTargets uintptr
+ OMGetRenderTargetsAndUnorderedAccessViews uintptr
+ OMGetBlendState uintptr
+ OMGetDepthStencilState uintptr
+ SOGetTargets uintptr
+ RSGetState uintptr
+ RSGetViewports uintptr
+ RSGetScissorRects uintptr
+ HSGetShaderResources uintptr
+ HSGetShader uintptr
+ HSGetSamplers uintptr
+ HSGetConstantBuffers uintptr
+ DSGetShaderResources uintptr
+ DSGetShader uintptr
+ DSGetSamplers uintptr
+ DSGetConstantBuffers uintptr
+ CSGetShaderResources uintptr
+ CSGetUnorderedAccessViews uintptr
+ CSGetShader uintptr
+ CSGetSamplers uintptr
+ CSGetConstantBuffers uintptr
+ ClearState uintptr
+ Flush uintptr
+ GetType uintptr
+ GetContextFlags uintptr
+ FinishCommandList uintptr
+ }
+}
+
+type RenderTargetView struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type Resource struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type Texture2D struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type Buffer struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type SamplerState struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type PixelShader struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type ShaderResourceView struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type UnorderedAccessView struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type DepthStencilView struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type BlendState struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type DepthStencilState struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type VertexShader struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type ComputeShader struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type RasterizerState struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type InputLayout struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ GetBufferPointer uintptr
+ GetBufferSize uintptr
+ }
+}
+
+type DEPTH_STENCIL_DESC struct {
+ DepthEnable uint32
+ DepthWriteMask uint32
+ DepthFunc uint32
+ StencilEnable uint32
+ StencilReadMask uint8
+ StencilWriteMask uint8
+ FrontFace DEPTH_STENCILOP_DESC
+ BackFace DEPTH_STENCILOP_DESC
+}
+
+type DEPTH_STENCILOP_DESC struct {
+ StencilFailOp uint32
+ StencilDepthFailOp uint32
+ StencilPassOp uint32
+ StencilFunc uint32
+}
+
+type DEPTH_STENCIL_VIEW_DESC_TEX2D struct {
+ Format uint32
+ ViewDimension uint32
+ Flags uint32
+ Texture2D TEX2D_DSV
+}
+
+type TEX2D_DSV struct {
+ MipSlice uint32
+}
+
+type BLEND_DESC struct {
+ AlphaToCoverageEnable uint32
+ IndependentBlendEnable uint32
+ RenderTarget [8]RENDER_TARGET_BLEND_DESC
+}
+
+type RENDER_TARGET_BLEND_DESC struct {
+ BlendEnable uint32
+ SrcBlend uint32
+ DestBlend uint32
+ BlendOp uint32
+ SrcBlendAlpha uint32
+ DestBlendAlpha uint32
+ BlendOpAlpha uint32
+ RenderTargetWriteMask uint8
+}
+
+type IDXGIObject struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetPrivateData uintptr
+ GetParent uintptr
+ }
+}
+
+type IDXGIAdapter struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetPrivateData uintptr
+ GetParent uintptr
+ EnumOutputs uintptr
+ GetDesc uintptr
+ CheckInterfaceSupport uintptr
+ GetDesc1 uintptr
+ }
+}
+
+type IDXGIFactory struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetPrivateData uintptr
+ GetParent uintptr
+ EnumAdapters uintptr
+ MakeWindowAssociation uintptr
+ GetWindowAssociation uintptr
+ CreateSwapChain uintptr
+ CreateSoftwareAdapter uintptr
+ }
+}
+
+type IDXGIDebug struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ ReportLiveObjects uintptr
+ }
+}
+
+type IDXGIDevice struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ SetPrivateData uintptr
+ SetPrivateDataInterface uintptr
+ GetPrivateData uintptr
+ GetParent uintptr
+ GetAdapter uintptr
+ CreateSurface uintptr
+ QueryResourceResidency uintptr
+ SetGPUThreadPriority uintptr
+ GetGPUThreadPriority uintptr
+ }
+}
+
+type IUnknown struct {
+ Vtbl *struct {
+ _IUnknownVTbl
+ }
+}
+
+type _IUnknownVTbl struct {
+ QueryInterface uintptr
+ AddRef uintptr
+ Release uintptr
+}
+
+type BUFFER_DESC struct {
+ ByteWidth uint32
+ Usage uint32
+ BindFlags uint32
+ CPUAccessFlags uint32
+ MiscFlags uint32
+ StructureByteStride uint32
+}
+
+type GUID struct {
+ Data1 uint32
+ Data2 uint16
+ Data3 uint16
+ Data4_0 uint8
+ Data4_1 uint8
+ Data4_2 uint8
+ Data4_3 uint8
+ Data4_4 uint8
+ Data4_5 uint8
+ Data4_6 uint8
+ Data4_7 uint8
+}
+
+type VIEWPORT struct {
+ TopLeftX float32
+ TopLeftY float32
+ Width float32
+ Height float32
+ MinDepth float32
+ MaxDepth float32
+}
+
+type SUBRESOURCE_DATA struct {
+ pSysMem *byte
+}
+
+type BOX struct {
+ Left uint32
+ Top uint32
+ Front uint32
+ Right uint32
+ Bottom uint32
+ Back uint32
+}
+
+type MAPPED_SUBRESOURCE struct {
+ PData uintptr
+ RowPitch uint32
+ DepthPitch uint32
+}
+
+type ErrorCode struct {
+ Name string
+ Code uint32
+}
+
+type RASTERIZER_DESC struct {
+ FillMode uint32
+ CullMode uint32
+ FrontCounterClockwise uint32
+ DepthBias int32
+ DepthBiasClamp float32
+ SlopeScaledDepthBias float32
+ DepthClipEnable uint32
+ ScissorEnable uint32
+ MultisampleEnable uint32
+ AntialiasedLineEnable uint32
+}
+
+var (
+ IID_Texture2D = GUID{0x6f15aaf2, 0xd208, 0x4e89, 0x9a, 0xb4, 0x48, 0x95, 0x35, 0xd3, 0x4f, 0x9c}
+ IID_IDXGIDebug = GUID{0x119E7452, 0xDE9E, 0x40fe, 0x88, 0x06, 0x88, 0xF9, 0x0C, 0x12, 0xB4, 0x41}
+ IID_IDXGIDevice = GUID{0x54ec77fa, 0x1377, 0x44e6, 0x8c, 0x32, 0x88, 0xfd, 0x5f, 0x44, 0xc8, 0x4c}
+ IID_IDXGIFactory = GUID{0x7b7166ec, 0x21c7, 0x44ae, 0xb2, 0x1a, 0xc9, 0xae, 0x32, 0x1a, 0xe3, 0x69}
+ IID_ID3D11Debug = GUID{0x79cf2233, 0x7536, 0x4948, 0x9d, 0x36, 0x1e, 0x46, 0x92, 0xdc, 0x57, 0x60}
+
+ DXGI_DEBUG_ALL = GUID{0xe48ae283, 0xda80, 0x490b, 0x87, 0xe6, 0x43, 0xe9, 0xa9, 0xcf, 0xda, 0x8}
+)
+
+var (
+ d3d11 = windows.NewLazySystemDLL("d3d11.dll")
+
+ _D3D11CreateDevice = d3d11.NewProc("D3D11CreateDevice")
+ _D3D11CreateDeviceAndSwapChain = d3d11.NewProc("D3D11CreateDeviceAndSwapChain")
+
+ dxgi = windows.NewLazySystemDLL("dxgi.dll")
+
+ _DXGIGetDebugInterface1 = dxgi.NewProc("DXGIGetDebugInterface1")
+)
+
+const (
+ SDK_VERSION = 7
+ DRIVER_TYPE_HARDWARE = 1
+
+ DXGI_FORMAT_UNKNOWN = 0
+ DXGI_FORMAT_R16_FLOAT = 54
+ DXGI_FORMAT_R32_FLOAT = 41
+ DXGI_FORMAT_R32_TYPELESS = 39
+ DXGI_FORMAT_R32G32_FLOAT = 16
+ DXGI_FORMAT_R32G32B32_FLOAT = 6
+ DXGI_FORMAT_R32G32B32A32_FLOAT = 2
+ DXGI_FORMAT_R8G8B8A8_UNORM = 28
+ DXGI_FORMAT_R8G8B8A8_UNORM_SRGB = 29
+ DXGI_FORMAT_R16_SINT = 59
+ DXGI_FORMAT_R16G16_SINT = 38
+ DXGI_FORMAT_R16_UINT = 57
+ DXGI_FORMAT_D24_UNORM_S8_UINT = 45
+ DXGI_FORMAT_R16G16_FLOAT = 34
+ DXGI_FORMAT_R16G16B16A16_FLOAT = 10
+
+ DXGI_DEBUG_RLO_SUMMARY = 0x1
+ DXGI_DEBUG_RLO_DETAIL = 0x2
+ DXGI_DEBUG_RLO_IGNORE_INTERNAL = 0x4
+
+ FORMAT_SUPPORT_TEXTURE2D = 0x20
+ FORMAT_SUPPORT_RENDER_TARGET = 0x4000
+
+ DXGI_USAGE_RENDER_TARGET_OUTPUT = 1 << (1 + 4)
+
+ CPU_ACCESS_READ = 0x20000
+
+ MAP_READ = 1
+
+ DXGI_SWAP_EFFECT_DISCARD = 0
+
+ FEATURE_LEVEL_9_1 = 0x9100
+ FEATURE_LEVEL_9_3 = 0x9300
+ FEATURE_LEVEL_11_0 = 0xb000
+
+ USAGE_IMMUTABLE = 1
+ USAGE_STAGING = 3
+
+ BIND_VERTEX_BUFFER = 0x1
+ BIND_INDEX_BUFFER = 0x2
+ BIND_CONSTANT_BUFFER = 0x4
+ BIND_SHADER_RESOURCE = 0x8
+ BIND_RENDER_TARGET = 0x20
+ BIND_DEPTH_STENCIL = 0x40
+ BIND_UNORDERED_ACCESS = 0x80
+
+ PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4
+ PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5
+
+ FILTER_MIN_MAG_LINEAR_MIP_POINT = 0x14
+ FILTER_MIN_MAG_MIP_POINT = 0
+
+ TEXTURE_ADDRESS_MIRROR = 2
+ TEXTURE_ADDRESS_CLAMP = 3
+ TEXTURE_ADDRESS_WRAP = 1
+
+ SRV_DIMENSION_BUFFER = 1
+ UAV_DIMENSION_BUFFER = 1
+ SRV_DIMENSION_BUFFEREX = 11
+ SRV_DIMENSION_TEXTURE2D = 4
+ UAV_DIMENSION_TEXTURE2D = 4
+
+ BUFFER_UAV_FLAG_RAW = 0x1
+ BUFFEREX_SRV_FLAG_RAW = 0x1
+
+ RESOURCE_MISC_BUFFER_ALLOW_RAW_VIEWS = 0x20
+
+ CREATE_DEVICE_DEBUG = 0x2
+
+ FILL_SOLID = 3
+
+ CULL_NONE = 1
+
+ CLEAR_DEPTH = 0x1
+ CLEAR_STENCIL = 0x2
+
+ DSV_DIMENSION_TEXTURE2D = 3
+
+ DEPTH_WRITE_MASK_ALL = 1
+
+ COMPARISON_GREATER = 5
+ COMPARISON_GREATER_EQUAL = 7
+
+ BLEND_OP_ADD = 1
+ BLEND_ONE = 2
+ BLEND_INV_SRC_ALPHA = 6
+ BLEND_ZERO = 1
+ BLEND_DEST_COLOR = 9
+ BLEND_DEST_ALPHA = 7
+
+ COLOR_WRITE_ENABLE_ALL = 1 | 2 | 4 | 8
+
+ DXGI_STATUS_OCCLUDED = 0x087A0001
+ DXGI_ERROR_DEVICE_RESET = 0x887A0007
+ DXGI_ERROR_DEVICE_REMOVED = 0x887A0005
+ D3DDDIERR_DEVICEREMOVED = 1<<31 | 0x876<<16 | 2160
+
+ RLDO_SUMMARY = 1
+ RLDO_DETAIL = 2
+ RLDO_IGNORE_INTERNAL = 4
+)
+
+func CreateDevice(driverType uint32, flags uint32) (*Device, *DeviceContext, uint32, error) {
+ var (
+ dev *Device
+ ctx *DeviceContext
+ featLvl uint32
+ )
+ r, _, _ := _D3D11CreateDevice.Call(
+ 0, // pAdapter
+ uintptr(driverType), // driverType
+ 0, // Software
+ uintptr(flags), // Flags
+ 0, // pFeatureLevels
+ 0, // FeatureLevels
+ SDK_VERSION, // SDKVersion
+ uintptr(unsafe.Pointer(&dev)), // ppDevice
+ uintptr(unsafe.Pointer(&featLvl)), // pFeatureLevel
+ uintptr(unsafe.Pointer(&ctx)), // ppImmediateContext
+ )
+ if r != 0 {
+ return nil, nil, 0, ErrorCode{Name: "D3D11CreateDevice", Code: uint32(r)}
+ }
+ return dev, ctx, featLvl, nil
+}
+
+func CreateDeviceAndSwapChain(driverType uint32, flags uint32, swapDesc *DXGI_SWAP_CHAIN_DESC) (*Device, *DeviceContext, *IDXGISwapChain, uint32, error) {
+ var (
+ dev *Device
+ ctx *DeviceContext
+ swchain *IDXGISwapChain
+ featLvl uint32
+ )
+ r, _, _ := _D3D11CreateDeviceAndSwapChain.Call(
+ 0, // pAdapter
+ uintptr(driverType), // driverType
+ 0, // Software
+ uintptr(flags), // Flags
+ 0, // pFeatureLevels
+ 0, // FeatureLevels
+ SDK_VERSION, // SDKVersion
+ uintptr(unsafe.Pointer(swapDesc)), // pSwapChainDesc
+ uintptr(unsafe.Pointer(&swchain)), // ppSwapChain
+ uintptr(unsafe.Pointer(&dev)), // ppDevice
+ uintptr(unsafe.Pointer(&featLvl)), // pFeatureLevel
+ uintptr(unsafe.Pointer(&ctx)), // ppImmediateContext
+ )
+ if r != 0 {
+ return nil, nil, nil, 0, ErrorCode{Name: "D3D11CreateDeviceAndSwapChain", Code: uint32(r)}
+ }
+ return dev, ctx, swchain, featLvl, nil
+}
+
+func DXGIGetDebugInterface1() (*IDXGIDebug, error) {
+ var dbg *IDXGIDebug
+ r, _, _ := _DXGIGetDebugInterface1.Call(
+ 0, // Flags
+ uintptr(unsafe.Pointer(&IID_IDXGIDebug)),
+ uintptr(unsafe.Pointer(&dbg)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DXGIGetDebugInterface1", Code: uint32(r)}
+ }
+ return dbg, nil
+}
+
+func ReportLiveObjects() error {
+ dxgi, err := DXGIGetDebugInterface1()
+ if err != nil {
+ return err
+ }
+ defer IUnknownRelease(unsafe.Pointer(dxgi), dxgi.Vtbl.Release)
+ dxgi.ReportLiveObjects(&DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_DETAIL|DXGI_DEBUG_RLO_IGNORE_INTERNAL)
+ return nil
+}
+
+func (d *IDXGIDebug) ReportLiveObjects(guid *GUID, flags uint32) {
+ syscall.Syscall6(
+ d.Vtbl.ReportLiveObjects,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(guid)),
+ uintptr(flags),
+ 0,
+ 0,
+ 0,
+ )
+}
+
+func (d *Device) CheckFormatSupport(format uint32) (uint32, error) {
+ var support uint32
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.CheckFormatSupport,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(format),
+ uintptr(unsafe.Pointer(&support)),
+ )
+ if r != 0 {
+ return 0, ErrorCode{Name: "DeviceCheckFormatSupport", Code: uint32(r)}
+ }
+ return support, nil
+}
+
+func (d *Device) CreateBuffer(desc *BUFFER_DESC, data []byte) (*Buffer, error) {
+ var dataDesc *SUBRESOURCE_DATA
+ if len(data) > 0 {
+ dataDesc = &SUBRESOURCE_DATA{
+ pSysMem: &data[0],
+ }
+ }
+ var buf *Buffer
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateBuffer,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(dataDesc)),
+ uintptr(unsafe.Pointer(&buf)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateBuffer", Code: uint32(r)}
+ }
+ return buf, nil
+}
+
+func (d *Device) CreateDepthStencilViewTEX2D(res *Resource, desc *DEPTH_STENCIL_VIEW_DESC_TEX2D) (*DepthStencilView, error) {
+ var view *DepthStencilView
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateDepthStencilView,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(res)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&view)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateDepthStencilView", Code: uint32(r)}
+ }
+ return view, nil
+}
+
+func (d *Device) CreatePixelShader(bytecode []byte) (*PixelShader, error) {
+ var shader *PixelShader
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreatePixelShader,
+ 5,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(&bytecode[0])),
+ uintptr(len(bytecode)),
+ 0, // pClassLinkage
+ uintptr(unsafe.Pointer(&shader)),
+ 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreatePixelShader", Code: uint32(r)}
+ }
+ return shader, nil
+}
+
+func (d *Device) CreateVertexShader(bytecode []byte) (*VertexShader, error) {
+ var shader *VertexShader
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateVertexShader,
+ 5,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(&bytecode[0])),
+ uintptr(len(bytecode)),
+ 0, // pClassLinkage
+ uintptr(unsafe.Pointer(&shader)),
+ 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateVertexShader", Code: uint32(r)}
+ }
+ return shader, nil
+}
+
+func (d *Device) CreateComputeShader(bytecode []byte) (*ComputeShader, error) {
+ var shader *ComputeShader
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateComputeShader,
+ 5,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(&bytecode[0])),
+ uintptr(len(bytecode)),
+ 0, // pClassLinkage
+ uintptr(unsafe.Pointer(&shader)),
+ 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateComputeShader", Code: uint32(r)}
+ }
+ return shader, nil
+}
+
+func (d *Device) CreateShaderResourceView(res *Resource, desc unsafe.Pointer) (*ShaderResourceView, error) {
+ var resView *ShaderResourceView
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateShaderResourceView,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(res)),
+ uintptr(desc),
+ uintptr(unsafe.Pointer(&resView)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateShaderResourceView", Code: uint32(r)}
+ }
+ return resView, nil
+}
+
+func (d *Device) CreateUnorderedAccessView(res *Resource, desc unsafe.Pointer) (*UnorderedAccessView, error) {
+ var uaView *UnorderedAccessView
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateUnorderedAccessView,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(res)),
+ uintptr(desc),
+ uintptr(unsafe.Pointer(&uaView)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateUnorderedAccessView", Code: uint32(r)}
+ }
+ return uaView, nil
+}
+
+func (d *Device) CreateRasterizerState(desc *RASTERIZER_DESC) (*RasterizerState, error) {
+ var state *RasterizerState
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.CreateRasterizerState,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&state)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateRasterizerState", Code: uint32(r)}
+ }
+ return state, nil
+}
+
+func (d *Device) CreateInputLayout(descs []INPUT_ELEMENT_DESC, bytecode []byte) (*InputLayout, error) {
+ var pdesc *INPUT_ELEMENT_DESC
+ if len(descs) > 0 {
+ pdesc = &descs[0]
+ }
+ var layout *InputLayout
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateInputLayout,
+ 6,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(pdesc)),
+ uintptr(len(descs)),
+ uintptr(unsafe.Pointer(&bytecode[0])),
+ uintptr(len(bytecode)),
+ uintptr(unsafe.Pointer(&layout)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateInputLayout", Code: uint32(r)}
+ }
+ return layout, nil
+}
+
+func (d *Device) CreateSamplerState(desc *SAMPLER_DESC) (*SamplerState, error) {
+ var sampler *SamplerState
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.CreateSamplerState,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&sampler)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateSamplerState", Code: uint32(r)}
+ }
+ return sampler, nil
+}
+
+func (d *Device) CreateTexture2D(desc *TEXTURE2D_DESC) (*Texture2D, error) {
+ var tex *Texture2D
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateTexture2D,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ 0, // pInitialData
+ uintptr(unsafe.Pointer(&tex)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "CreateTexture2D", Code: uint32(r)}
+ }
+ return tex, nil
+}
+
+func (d *Device) CreateRenderTargetView(res *Resource) (*RenderTargetView, error) {
+ var target *RenderTargetView
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateRenderTargetView,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(res)),
+ 0, // pDesc
+ uintptr(unsafe.Pointer(&target)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateRenderTargetView", Code: uint32(r)}
+ }
+ return target, nil
+}
+
+func (d *Device) CreateBlendState(desc *BLEND_DESC) (*BlendState, error) {
+ var state *BlendState
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.CreateBlendState,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&state)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateBlendState", Code: uint32(r)}
+ }
+ return state, nil
+}
+
+func (d *Device) CreateDepthStencilState(desc *DEPTH_STENCIL_DESC) (*DepthStencilState, error) {
+ var state *DepthStencilState
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.CreateDepthStencilState,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&state)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "DeviceCreateDepthStencilState", Code: uint32(r)}
+ }
+ return state, nil
+}
+
+func (d *Device) GetFeatureLevel() int {
+ lvl, _, _ := syscall.Syscall(
+ d.Vtbl.GetFeatureLevel,
+ 1,
+ uintptr(unsafe.Pointer(d)),
+ 0, 0,
+ )
+ return int(lvl)
+}
+
+func (d *Device) GetImmediateContext() *DeviceContext {
+ var ctx *DeviceContext
+ syscall.Syscall(
+ d.Vtbl.GetImmediateContext,
+ 2,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(&ctx)),
+ 0,
+ )
+ return ctx
+}
+
+func (d *Device) ReportLiveDeviceObjects() error {
+ intf, err := IUnknownQueryInterface(unsafe.Pointer(d), d.Vtbl.QueryInterface, &IID_ID3D11Debug)
+ if err != nil {
+ return fmt.Errorf("ReportLiveObjects: failed to query ID3D11Debug interface: %v", err)
+ }
+ defer IUnknownRelease(unsafe.Pointer(intf), intf.Vtbl.Release)
+ dbg := (*Debug)(unsafe.Pointer(intf))
+ dbg.ReportLiveDeviceObjects(RLDO_DETAIL | RLDO_IGNORE_INTERNAL)
+ return nil
+}
+
+func (d *Debug) ReportLiveDeviceObjects(flags uint32) {
+ syscall.Syscall(
+ d.Vtbl.ReportLiveDeviceObjects,
+ 2,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(flags),
+ 0,
+ )
+}
+
+func (s *IDXGISwapChain) GetDesc() (DXGI_SWAP_CHAIN_DESC, error) {
+ var desc DXGI_SWAP_CHAIN_DESC
+ r, _, _ := syscall.Syscall(
+ s.Vtbl.GetDesc,
+ 2,
+ uintptr(unsafe.Pointer(s)),
+ uintptr(unsafe.Pointer(&desc)),
+ 0,
+ )
+ if r != 0 {
+ return DXGI_SWAP_CHAIN_DESC{}, ErrorCode{Name: "IDXGISwapChainGetDesc", Code: uint32(r)}
+ }
+ return desc, nil
+}
+
+func (s *IDXGISwapChain) ResizeBuffers(buffers, width, height, newFormat, flags uint32) error {
+ r, _, _ := syscall.Syscall6(
+ s.Vtbl.ResizeBuffers,
+ 6,
+ uintptr(unsafe.Pointer(s)),
+ uintptr(buffers),
+ uintptr(width),
+ uintptr(height),
+ uintptr(newFormat),
+ uintptr(flags),
+ )
+ if r != 0 {
+ return ErrorCode{Name: "IDXGISwapChainResizeBuffers", Code: uint32(r)}
+ }
+ return nil
+}
+
+func (s *IDXGISwapChain) Present(SyncInterval int, Flags uint32) error {
+ r, _, _ := syscall.Syscall(
+ s.Vtbl.Present,
+ 3,
+ uintptr(unsafe.Pointer(s)),
+ uintptr(SyncInterval),
+ uintptr(Flags),
+ )
+ if r != 0 {
+ return ErrorCode{Name: "IDXGISwapChainPresent", Code: uint32(r)}
+ }
+ return nil
+}
+
+func (s *IDXGISwapChain) GetBuffer(index int, riid *GUID) (*IUnknown, error) {
+ var buf *IUnknown
+ r, _, _ := syscall.Syscall6(
+ s.Vtbl.GetBuffer,
+ 4,
+ uintptr(unsafe.Pointer(s)),
+ uintptr(index),
+ uintptr(unsafe.Pointer(riid)),
+ uintptr(unsafe.Pointer(&buf)),
+ 0,
+ 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "IDXGISwapChainGetBuffer", Code: uint32(r)}
+ }
+ return buf, nil
+}
+
+func (c *DeviceContext) Unmap(resource *Resource, subResource uint32) {
+ syscall.Syscall(
+ c.Vtbl.Unmap,
+ 3,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(resource)),
+ uintptr(subResource),
+ )
+}
+
+func (c *DeviceContext) Map(resource *Resource, subResource, mapType, mapFlags uint32) (MAPPED_SUBRESOURCE, error) {
+ var resMap MAPPED_SUBRESOURCE
+ r, _, _ := syscall.Syscall6(
+ c.Vtbl.Map,
+ 6,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(resource)),
+ uintptr(subResource),
+ uintptr(mapType),
+ uintptr(mapFlags),
+ uintptr(unsafe.Pointer(&resMap)),
+ )
+ if r != 0 {
+ return resMap, ErrorCode{Name: "DeviceContextMap", Code: uint32(r)}
+ }
+ return resMap, nil
+}
+
+func (c *DeviceContext) CopySubresourceRegion(dst *Resource, dstSubresource, dstX, dstY, dstZ uint32, src *Resource, srcSubresource uint32, srcBox *BOX) {
+ syscall.Syscall9(
+ c.Vtbl.CopySubresourceRegion,
+ 9,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(dst)),
+ uintptr(dstSubresource),
+ uintptr(dstX),
+ uintptr(dstY),
+ uintptr(dstZ),
+ uintptr(unsafe.Pointer(src)),
+ uintptr(srcSubresource),
+ uintptr(unsafe.Pointer(srcBox)),
+ )
+}
+
+func (c *DeviceContext) ClearDepthStencilView(target *DepthStencilView, flags uint32, depth float32, stencil uint8) {
+ syscall.Syscall6(
+ c.Vtbl.ClearDepthStencilView,
+ 5,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(target)),
+ uintptr(flags),
+ uintptr(math.Float32bits(depth)),
+ uintptr(stencil),
+ 0,
+ )
+}
+
+func (c *DeviceContext) ClearRenderTargetView(target *RenderTargetView, color *[4]float32) {
+ syscall.Syscall(
+ c.Vtbl.ClearRenderTargetView,
+ 3,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(target)),
+ uintptr(unsafe.Pointer(color)),
+ )
+}
+
+func (c *DeviceContext) CSSetShaderResources(startSlot uint32, s *ShaderResourceView) {
+ syscall.Syscall6(
+ c.Vtbl.CSSetShaderResources,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(startSlot),
+ 1, // NumViews
+ uintptr(unsafe.Pointer(&s)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) CSSetUnorderedAccessViews(startSlot uint32, v *UnorderedAccessView) {
+ syscall.Syscall6(
+ c.Vtbl.CSSetUnorderedAccessViews,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(startSlot),
+ 1, // NumViews
+ uintptr(unsafe.Pointer(&v)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) CSSetShader(s *ComputeShader) {
+ syscall.Syscall6(
+ c.Vtbl.CSSetShader,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(s)),
+ 0, // ppClassInstances
+ 0, // NumClassInstances
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) RSSetViewports(viewport *VIEWPORT) {
+ syscall.Syscall(
+ c.Vtbl.RSSetViewports,
+ 3,
+ uintptr(unsafe.Pointer(c)),
+ 1, // NumViewports
+ uintptr(unsafe.Pointer(viewport)),
+ )
+}
+
+func (c *DeviceContext) VSSetShader(s *VertexShader) {
+ syscall.Syscall6(
+ c.Vtbl.VSSetShader,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(s)),
+ 0, // ppClassInstances
+ 0, // NumClassInstances
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) VSSetConstantBuffers(b *Buffer) {
+ syscall.Syscall6(
+ c.Vtbl.VSSetConstantBuffers,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ 0, // StartSlot
+ 1, // NumBuffers
+ uintptr(unsafe.Pointer(&b)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) PSSetConstantBuffers(b *Buffer) {
+ syscall.Syscall6(
+ c.Vtbl.PSSetConstantBuffers,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ 0, // StartSlot
+ 1, // NumBuffers
+ uintptr(unsafe.Pointer(&b)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) PSSetShaderResources(startSlot uint32, s *ShaderResourceView) {
+ syscall.Syscall6(
+ c.Vtbl.PSSetShaderResources,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(startSlot),
+ 1, // NumViews
+ uintptr(unsafe.Pointer(&s)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) PSSetSamplers(startSlot uint32, s *SamplerState) {
+ syscall.Syscall6(
+ c.Vtbl.PSSetSamplers,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(startSlot),
+ 1, // NumSamplers
+ uintptr(unsafe.Pointer(&s)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) PSSetShader(s *PixelShader) {
+ syscall.Syscall6(
+ c.Vtbl.PSSetShader,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(s)),
+ 0, // ppClassInstances
+ 0, // NumClassInstances
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) UpdateSubresource(res *Resource, dstBox *BOX, rowPitch, depthPitch uint32, data []byte) {
+ syscall.Syscall9(
+ c.Vtbl.UpdateSubresource,
+ 7,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(res)),
+ 0, // DstSubresource
+ uintptr(unsafe.Pointer(dstBox)),
+ uintptr(unsafe.Pointer(&data[0])),
+ uintptr(rowPitch),
+ uintptr(depthPitch),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) RSSetState(state *RasterizerState) {
+ syscall.Syscall(
+ c.Vtbl.RSSetState,
+ 2,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(state)),
+ 0,
+ )
+}
+
+func (c *DeviceContext) IASetInputLayout(layout *InputLayout) {
+ syscall.Syscall(
+ c.Vtbl.IASetInputLayout,
+ 2,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(layout)),
+ 0,
+ )
+}
+
+func (c *DeviceContext) IASetIndexBuffer(buf *Buffer, format, offset uint32) {
+ syscall.Syscall6(
+ c.Vtbl.IASetIndexBuffer,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(buf)),
+ uintptr(format),
+ uintptr(offset),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) IASetVertexBuffers(buf *Buffer, stride, offset uint32) {
+ syscall.Syscall6(
+ c.Vtbl.IASetVertexBuffers,
+ 6,
+ uintptr(unsafe.Pointer(c)),
+ 0, // StartSlot
+ 1, // NumBuffers,
+ uintptr(unsafe.Pointer(&buf)),
+ uintptr(unsafe.Pointer(&stride)),
+ uintptr(unsafe.Pointer(&offset)),
+ )
+}
+
+func (c *DeviceContext) IASetPrimitiveTopology(mode uint32) {
+ syscall.Syscall(
+ c.Vtbl.IASetPrimitiveTopology,
+ 2,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(mode),
+ 0,
+ )
+}
+
+func (c *DeviceContext) OMGetRenderTargets() (*RenderTargetView, *DepthStencilView) {
+ var (
+ target *RenderTargetView
+ depthStencilView *DepthStencilView
+ )
+ syscall.Syscall6(
+ c.Vtbl.OMGetRenderTargets,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ 1, // NumViews
+ uintptr(unsafe.Pointer(&target)),
+ uintptr(unsafe.Pointer(&depthStencilView)),
+ 0, 0,
+ )
+ return target, depthStencilView
+}
+
+func (c *DeviceContext) OMSetRenderTargets(target *RenderTargetView, depthStencil *DepthStencilView) {
+ syscall.Syscall6(
+ c.Vtbl.OMSetRenderTargets,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ 1, // NumViews
+ uintptr(unsafe.Pointer(&target)),
+ uintptr(unsafe.Pointer(depthStencil)),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) Draw(count, start uint32) {
+ syscall.Syscall(
+ c.Vtbl.Draw,
+ 3,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(count),
+ uintptr(start),
+ )
+}
+
+func (c *DeviceContext) DrawIndexed(count, start uint32, base int32) {
+ syscall.Syscall6(
+ c.Vtbl.DrawIndexed,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(count),
+ uintptr(start),
+ uintptr(base),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) Dispatch(x, y, z uint32) {
+ syscall.Syscall6(
+ c.Vtbl.Dispatch,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(x),
+ uintptr(y),
+ uintptr(z),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) OMSetBlendState(state *BlendState, factor *f32color.RGBA, sampleMask uint32) {
+ syscall.Syscall6(
+ c.Vtbl.OMSetBlendState,
+ 4,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(state)),
+ uintptr(unsafe.Pointer(factor)),
+ uintptr(sampleMask),
+ 0, 0,
+ )
+}
+
+func (c *DeviceContext) OMSetDepthStencilState(state *DepthStencilState, stencilRef uint32) {
+ syscall.Syscall(
+ c.Vtbl.OMSetDepthStencilState,
+ 3,
+ uintptr(unsafe.Pointer(c)),
+ uintptr(unsafe.Pointer(state)),
+ uintptr(stencilRef),
+ )
+}
+
+func (d *IDXGIObject) GetParent(guid *GUID) (*IDXGIObject, error) {
+ var parent *IDXGIObject
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.GetParent,
+ 3,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(guid)),
+ uintptr(unsafe.Pointer(&parent)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "IDXGIObjectGetParent", Code: uint32(r)}
+ }
+ return parent, nil
+}
+
+func (d *IDXGIFactory) CreateSwapChain(device *IUnknown, desc *DXGI_SWAP_CHAIN_DESC) (*IDXGISwapChain, error) {
+ var swchain *IDXGISwapChain
+ r, _, _ := syscall.Syscall6(
+ d.Vtbl.CreateSwapChain,
+ 4,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(device)),
+ uintptr(unsafe.Pointer(desc)),
+ uintptr(unsafe.Pointer(&swchain)),
+ 0, 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "IDXGIFactory", Code: uint32(r)}
+ }
+ return swchain, nil
+}
+
+func (d *IDXGIDevice) GetAdapter() (*IDXGIAdapter, error) {
+ var adapter *IDXGIAdapter
+ r, _, _ := syscall.Syscall(
+ d.Vtbl.GetAdapter,
+ 2,
+ uintptr(unsafe.Pointer(d)),
+ uintptr(unsafe.Pointer(&adapter)),
+ 0,
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "IDXGIDeviceGetAdapter", Code: uint32(r)}
+ }
+ return adapter, nil
+}
+
+func IUnknownQueryInterface(obj unsafe.Pointer, queryInterfaceMethod uintptr, guid *GUID) (*IUnknown, error) {
+ var ref *IUnknown
+ r, _, _ := syscall.Syscall(
+ queryInterfaceMethod,
+ 3,
+ uintptr(obj),
+ uintptr(unsafe.Pointer(guid)),
+ uintptr(unsafe.Pointer(&ref)),
+ )
+ if r != 0 {
+ return nil, ErrorCode{Name: "IUnknownQueryInterface", Code: uint32(r)}
+ }
+ return ref, nil
+}
+
+func IUnknownAddRef(obj unsafe.Pointer, addRefMethod uintptr) {
+ syscall.Syscall(
+ addRefMethod,
+ 1,
+ uintptr(obj),
+ 0,
+ 0,
+ )
+}
+
+func IUnknownRelease(obj unsafe.Pointer, releaseMethod uintptr) {
+ syscall.Syscall(
+ releaseMethod,
+ 1,
+ uintptr(obj),
+ 0,
+ 0,
+ )
+}
+
+func (e ErrorCode) Error() string {
+ return fmt.Sprintf("%s: %#x", e.Name, e.Code)
+}
+
+func CreateSwapChain(dev *Device, hwnd windows.Handle) (*IDXGISwapChain, error) {
+ dxgiDev, err := IUnknownQueryInterface(unsafe.Pointer(dev), dev.Vtbl.QueryInterface, &IID_IDXGIDevice)
+ if err != nil {
+ return nil, fmt.Errorf("NewContext: %v", err)
+ }
+ adapter, err := (*IDXGIDevice)(unsafe.Pointer(dxgiDev)).GetAdapter()
+ IUnknownRelease(unsafe.Pointer(dxgiDev), dxgiDev.Vtbl.Release)
+ if err != nil {
+ return nil, fmt.Errorf("NewContext: %v", err)
+ }
+ dxgiFactory, err := (*IDXGIObject)(unsafe.Pointer(adapter)).GetParent(&IID_IDXGIFactory)
+ IUnknownRelease(unsafe.Pointer(adapter), adapter.Vtbl.Release)
+ if err != nil {
+ return nil, fmt.Errorf("NewContext: %v", err)
+ }
+ swchain, err := (*IDXGIFactory)(unsafe.Pointer(dxgiFactory)).CreateSwapChain(
+ (*IUnknown)(unsafe.Pointer(dev)),
+ &DXGI_SWAP_CHAIN_DESC{
+ BufferDesc: DXGI_MODE_DESC{
+ Format: DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
+ },
+ SampleDesc: DXGI_SAMPLE_DESC{
+ Count: 1,
+ },
+ BufferUsage: DXGI_USAGE_RENDER_TARGET_OUTPUT,
+ BufferCount: 1,
+ OutputWindow: hwnd,
+ Windowed: 1,
+ SwapEffect: DXGI_SWAP_EFFECT_DISCARD,
+ },
+ )
+ IUnknownRelease(unsafe.Pointer(dxgiFactory), dxgiFactory.Vtbl.Release)
+ if err != nil {
+ return nil, fmt.Errorf("NewContext: %v", err)
+ }
+ return swchain, nil
+}
+
+func CreateDepthView(d *Device, width, height, depthBits int) (*DepthStencilView, error) {
+ depthTex, err := d.CreateTexture2D(&TEXTURE2D_DESC{
+ Width: uint32(width),
+ Height: uint32(height),
+ MipLevels: 1,
+ ArraySize: 1,
+ Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
+ SampleDesc: DXGI_SAMPLE_DESC{
+ Count: 1,
+ Quality: 0,
+ },
+ BindFlags: BIND_DEPTH_STENCIL,
+ })
+ if err != nil {
+ return nil, err
+ }
+ depthView, err := d.CreateDepthStencilViewTEX2D(
+ (*Resource)(unsafe.Pointer(depthTex)),
+ &DEPTH_STENCIL_VIEW_DESC_TEX2D{
+ Format: DXGI_FORMAT_D24_UNORM_S8_UINT,
+ ViewDimension: DSV_DIMENSION_TEXTURE2D,
+ },
+ )
+ IUnknownRelease(unsafe.Pointer(depthTex), depthTex.Vtbl.Release)
+ return depthView, err
+}
diff --git a/vendor/gioui.org/internal/egl/egl.go b/vendor/gioui.org/internal/egl/egl.go
new file mode 100644
index 0000000..7d7b551
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl.go
@@ -0,0 +1,253 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build linux || windows || freebsd || openbsd
+// +build linux windows freebsd openbsd
+
+package egl
+
+import (
+ "errors"
+ "fmt"
+ "runtime"
+ "strings"
+
+ "gioui.org/gpu"
+)
+
+type Context struct {
+ disp _EGLDisplay
+ eglCtx *eglContext
+ eglSurf _EGLSurface
+ width, height int
+}
+
+type eglContext struct {
+ config _EGLConfig
+ ctx _EGLContext
+ visualID int
+ srgb bool
+ surfaceless bool
+}
+
+var (
+ nilEGLDisplay _EGLDisplay
+ nilEGLSurface _EGLSurface
+ nilEGLContext _EGLContext
+ nilEGLConfig _EGLConfig
+ EGL_DEFAULT_DISPLAY NativeDisplayType
+)
+
+const (
+ _EGL_ALPHA_SIZE = 0x3021
+ _EGL_BLUE_SIZE = 0x3022
+ _EGL_CONFIG_CAVEAT = 0x3027
+ _EGL_CONTEXT_CLIENT_VERSION = 0x3098
+ _EGL_DEPTH_SIZE = 0x3025
+ _EGL_GL_COLORSPACE_KHR = 0x309d
+ _EGL_GL_COLORSPACE_SRGB_KHR = 0x3089
+ _EGL_GREEN_SIZE = 0x3023
+ _EGL_EXTENSIONS = 0x3055
+ _EGL_NATIVE_VISUAL_ID = 0x302e
+ _EGL_NONE = 0x3038
+ _EGL_OPENGL_ES2_BIT = 0x4
+ _EGL_RED_SIZE = 0x3024
+ _EGL_RENDERABLE_TYPE = 0x3040
+ _EGL_SURFACE_TYPE = 0x3033
+ _EGL_WINDOW_BIT = 0x4
+)
+
+func (c *Context) Release() {
+ c.ReleaseSurface()
+ if c.eglCtx != nil {
+ eglDestroyContext(c.disp, c.eglCtx.ctx)
+ c.eglCtx = nil
+ }
+ c.disp = nilEGLDisplay
+}
+
+func (c *Context) Present() error {
+ if !eglSwapBuffers(c.disp, c.eglSurf) {
+ return fmt.Errorf("eglSwapBuffers failed (%x)", eglGetError())
+ }
+ return nil
+}
+
+func NewContext(disp NativeDisplayType) (*Context, error) {
+ if err := loadEGL(); err != nil {
+ return nil, err
+ }
+ eglDisp := eglGetDisplay(disp)
+ // eglGetDisplay can return EGL_NO_DISPLAY yet no error
+ // (EGL_SUCCESS), in which case a default EGL display might be
+ // available.
+ if eglDisp == nilEGLDisplay {
+ eglDisp = eglGetDisplay(EGL_DEFAULT_DISPLAY)
+ }
+ if eglDisp == nilEGLDisplay {
+ return nil, fmt.Errorf("eglGetDisplay failed: 0x%x", eglGetError())
+ }
+ eglCtx, err := createContext(eglDisp)
+ if err != nil {
+ return nil, err
+ }
+ c := &Context{
+ disp: eglDisp,
+ eglCtx: eglCtx,
+ }
+ return c, nil
+}
+
+func (c *Context) RenderTarget() (gpu.RenderTarget, error) {
+ return gpu.OpenGLRenderTarget{}, nil
+}
+
+func (c *Context) API() gpu.API {
+ return gpu.OpenGL{}
+}
+
+func (c *Context) ReleaseSurface() {
+ if c.eglSurf == nilEGLSurface {
+ return
+ }
+ // Make sure any in-flight GL commands are complete.
+ eglWaitClient()
+ c.ReleaseCurrent()
+ eglDestroySurface(c.disp, c.eglSurf)
+ c.eglSurf = nilEGLSurface
+}
+
+func (c *Context) VisualID() int {
+ return c.eglCtx.visualID
+}
+
+func (c *Context) CreateSurface(win NativeWindowType, width, height int) error {
+ eglSurf, err := createSurface(c.disp, c.eglCtx, win)
+ c.eglSurf = eglSurf
+ c.width = width
+ c.height = height
+ return err
+}
+
+func (c *Context) ReleaseCurrent() {
+ if c.disp != nilEGLDisplay {
+ eglMakeCurrent(c.disp, nilEGLSurface, nilEGLSurface, nilEGLContext)
+ }
+}
+
+func (c *Context) MakeCurrent() error {
+ // OpenGL contexts are implicit and thread-local. Lock the OS thread.
+ runtime.LockOSThread()
+
+ if c.eglSurf == nilEGLSurface && !c.eglCtx.surfaceless {
+ return errors.New("no surface created yet EGL_KHR_surfaceless_context is not supported")
+ }
+ if !eglMakeCurrent(c.disp, c.eglSurf, c.eglSurf, c.eglCtx.ctx) {
+ return fmt.Errorf("eglMakeCurrent error 0x%x", eglGetError())
+ }
+ return nil
+}
+
+func (c *Context) EnableVSync(enable bool) {
+ if enable {
+ eglSwapInterval(c.disp, 1)
+ } else {
+ eglSwapInterval(c.disp, 0)
+ }
+}
+
+func hasExtension(exts []string, ext string) bool {
+ for _, e := range exts {
+ if ext == e {
+ return true
+ }
+ }
+ return false
+}
+
+func createContext(disp _EGLDisplay) (*eglContext, error) {
+ major, minor, ret := eglInitialize(disp)
+ if !ret {
+ return nil, fmt.Errorf("eglInitialize failed: 0x%x", eglGetError())
+ }
+ // sRGB framebuffer support on EGL 1.5 or if EGL_KHR_gl_colorspace is supported.
+ exts := strings.Split(eglQueryString(disp, _EGL_EXTENSIONS), " ")
+ srgb := major > 1 || minor >= 5 || hasExtension(exts, "EGL_KHR_gl_colorspace")
+ attribs := []_EGLint{
+ _EGL_RENDERABLE_TYPE, _EGL_OPENGL_ES2_BIT,
+ _EGL_SURFACE_TYPE, _EGL_WINDOW_BIT,
+ _EGL_BLUE_SIZE, 8,
+ _EGL_GREEN_SIZE, 8,
+ _EGL_RED_SIZE, 8,
+ _EGL_CONFIG_CAVEAT, _EGL_NONE,
+ }
+ if srgb {
+ if runtime.GOOS == "linux" || runtime.GOOS == "android" {
+ // Some Mesa drivers crash if an sRGB framebuffer is requested without alpha.
+ // https://bugs.freedesktop.org/show_bug.cgi?id=107782.
+ //
+ // Also, some Android devices (Samsung S9) need alpha for sRGB to work.
+ attribs = append(attribs, _EGL_ALPHA_SIZE, 8)
+ }
+ }
+ attribs = append(attribs, _EGL_NONE)
+ eglCfg, ret := eglChooseConfig(disp, attribs)
+ if !ret {
+ return nil, fmt.Errorf("eglChooseConfig failed: 0x%x", eglGetError())
+ }
+ if eglCfg == nilEGLConfig {
+ supportsNoCfg := hasExtension(exts, "EGL_KHR_no_config_context")
+ if !supportsNoCfg {
+ return nil, errors.New("eglChooseConfig returned no configs")
+ }
+ }
+ var visID _EGLint
+ if eglCfg != nilEGLConfig {
+ var ok bool
+ visID, ok = eglGetConfigAttrib(disp, eglCfg, _EGL_NATIVE_VISUAL_ID)
+ if !ok {
+ return nil, errors.New("newContext: eglGetConfigAttrib for _EGL_NATIVE_VISUAL_ID failed")
+ }
+ }
+ ctxAttribs := []_EGLint{
+ _EGL_CONTEXT_CLIENT_VERSION, 3,
+ _EGL_NONE,
+ }
+ eglCtx := eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
+ if eglCtx == nilEGLContext {
+ // Fall back to OpenGL ES 2 and rely on extensions.
+ ctxAttribs := []_EGLint{
+ _EGL_CONTEXT_CLIENT_VERSION, 2,
+ _EGL_NONE,
+ }
+ eglCtx = eglCreateContext(disp, eglCfg, nilEGLContext, ctxAttribs)
+ if eglCtx == nilEGLContext {
+ return nil, fmt.Errorf("eglCreateContext failed: 0x%x", eglGetError())
+ }
+ }
+ return &eglContext{
+ config: _EGLConfig(eglCfg),
+ ctx: _EGLContext(eglCtx),
+ visualID: int(visID),
+ srgb: srgb,
+ surfaceless: hasExtension(exts, "EGL_KHR_surfaceless_context"),
+ }, nil
+}
+
+func createSurface(disp _EGLDisplay, eglCtx *eglContext, win NativeWindowType) (_EGLSurface, error) {
+ var surfAttribs []_EGLint
+ if eglCtx.srgb {
+ surfAttribs = append(surfAttribs, _EGL_GL_COLORSPACE_KHR, _EGL_GL_COLORSPACE_SRGB_KHR)
+ }
+ surfAttribs = append(surfAttribs, _EGL_NONE)
+ eglSurf := eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
+ if eglSurf == nilEGLSurface && eglCtx.srgb {
+ // Try again without sRGB.
+ eglCtx.srgb = false
+ surfAttribs = []_EGLint{_EGL_NONE}
+ eglSurf = eglCreateWindowSurface(disp, eglCtx.config, win, surfAttribs)
+ }
+ if eglSurf == nilEGLSurface {
+ return nilEGLSurface, fmt.Errorf("newContext: eglCreateWindowSurface failed 0x%x (sRGB=%v)", eglGetError(), eglCtx.srgb)
+ }
+ return eglSurf, nil
+}
diff --git a/vendor/gioui.org/internal/egl/egl_unix.go b/vendor/gioui.org/internal/egl/egl_unix.go
new file mode 100644
index 0000000..bd3efa5
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl_unix.go
@@ -0,0 +1,109 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build linux || freebsd || openbsd
+// +build linux freebsd openbsd
+
+package egl
+
+/*
+#cgo linux,!android pkg-config: egl
+#cgo freebsd openbsd android LDFLAGS: -lEGL
+#cgo freebsd CFLAGS: -I/usr/local/include
+#cgo freebsd LDFLAGS: -L/usr/local/lib
+#cgo openbsd CFLAGS: -I/usr/X11R6/include
+#cgo openbsd LDFLAGS: -L/usr/X11R6/lib
+#cgo CFLAGS: -DEGL_NO_X11
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+*/
+import "C"
+
+type (
+ _EGLint = C.EGLint
+ _EGLDisplay = C.EGLDisplay
+ _EGLConfig = C.EGLConfig
+ _EGLContext = C.EGLContext
+ _EGLSurface = C.EGLSurface
+ NativeDisplayType = C.EGLNativeDisplayType
+ NativeWindowType = C.EGLNativeWindowType
+)
+
+func loadEGL() error {
+ return nil
+}
+
+func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
+ var cfg C.EGLConfig
+ var ncfg C.EGLint
+ if C.eglChooseConfig(disp, &attribs[0], &cfg, 1, &ncfg) != C.EGL_TRUE {
+ return nilEGLConfig, false
+ }
+ return _EGLConfig(cfg), true
+}
+
+func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
+ ctx := C.eglCreateContext(disp, cfg, shareCtx, &attribs[0])
+ return _EGLContext(ctx)
+}
+
+func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
+ return C.eglDestroySurface(disp, surf) == C.EGL_TRUE
+}
+
+func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
+ return C.eglDestroyContext(disp, ctx) == C.EGL_TRUE
+}
+
+func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
+ var val _EGLint
+ ret := C.eglGetConfigAttrib(disp, cfg, attr, &val)
+ return val, ret == C.EGL_TRUE
+}
+
+func eglGetError() _EGLint {
+ return C.eglGetError()
+}
+
+func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
+ var maj, min _EGLint
+ ret := C.eglInitialize(disp, &maj, &min)
+ return maj, min, ret == C.EGL_TRUE
+}
+
+func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
+ return C.eglMakeCurrent(disp, draw, read, ctx) == C.EGL_TRUE
+}
+
+func eglReleaseThread() bool {
+ return C.eglReleaseThread() == C.EGL_TRUE
+}
+
+func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
+ return C.eglSwapBuffers(disp, surf) == C.EGL_TRUE
+}
+
+func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
+ return C.eglSwapInterval(disp, interval) == C.EGL_TRUE
+}
+
+func eglTerminate(disp _EGLDisplay) bool {
+ return C.eglTerminate(disp) == C.EGL_TRUE
+}
+
+func eglQueryString(disp _EGLDisplay, name _EGLint) string {
+ return C.GoString(C.eglQueryString(disp, name))
+}
+
+func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
+ return C.eglGetDisplay(disp)
+}
+
+func eglCreateWindowSurface(disp _EGLDisplay, conf _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
+ eglSurf := C.eglCreateWindowSurface(disp, conf, win, &attribs[0])
+ return eglSurf
+}
+
+func eglWaitClient() bool {
+ return C.eglWaitClient() == C.EGL_TRUE
+}
diff --git a/vendor/gioui.org/internal/egl/egl_windows.go b/vendor/gioui.org/internal/egl/egl_windows.go
new file mode 100644
index 0000000..4433dd7
--- /dev/null
+++ b/vendor/gioui.org/internal/egl/egl_windows.go
@@ -0,0 +1,169 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package egl
+
+import (
+ "fmt"
+ "runtime"
+ "sync"
+ "unsafe"
+
+ syscall "golang.org/x/sys/windows"
+
+ "gioui.org/internal/gl"
+)
+
+type (
+ _EGLint int32
+ _EGLDisplay uintptr
+ _EGLConfig uintptr
+ _EGLContext uintptr
+ _EGLSurface uintptr
+ NativeDisplayType uintptr
+ NativeWindowType uintptr
+)
+
+var (
+ libEGL = syscall.NewLazyDLL("libEGL.dll")
+ _eglChooseConfig = libEGL.NewProc("eglChooseConfig")
+ _eglCreateContext = libEGL.NewProc("eglCreateContext")
+ _eglCreateWindowSurface = libEGL.NewProc("eglCreateWindowSurface")
+ _eglDestroyContext = libEGL.NewProc("eglDestroyContext")
+ _eglDestroySurface = libEGL.NewProc("eglDestroySurface")
+ _eglGetConfigAttrib = libEGL.NewProc("eglGetConfigAttrib")
+ _eglGetDisplay = libEGL.NewProc("eglGetDisplay")
+ _eglGetError = libEGL.NewProc("eglGetError")
+ _eglInitialize = libEGL.NewProc("eglInitialize")
+ _eglMakeCurrent = libEGL.NewProc("eglMakeCurrent")
+ _eglReleaseThread = libEGL.NewProc("eglReleaseThread")
+ _eglSwapInterval = libEGL.NewProc("eglSwapInterval")
+ _eglSwapBuffers = libEGL.NewProc("eglSwapBuffers")
+ _eglTerminate = libEGL.NewProc("eglTerminate")
+ _eglQueryString = libEGL.NewProc("eglQueryString")
+ _eglWaitClient = libEGL.NewProc("eglWaitClient")
+)
+
+var loadOnce sync.Once
+
+func loadEGL() error {
+ var err error
+ loadOnce.Do(func() {
+ err = loadDLLs()
+ })
+ return err
+}
+
+func loadDLLs() error {
+ if err := loadDLL(libEGL, "libEGL.dll"); err != nil {
+ return err
+ }
+ if err := loadDLL(gl.LibGLESv2, "libGLESv2.dll"); err != nil {
+ return err
+ }
+ // d3dcompiler_47.dll is needed internally for shader compilation to function.
+ return loadDLL(syscall.NewLazyDLL("d3dcompiler_47.dll"), "d3dcompiler_47.dll")
+}
+
+func loadDLL(dll *syscall.LazyDLL, name string) error {
+ err := dll.Load()
+ if err != nil {
+ return fmt.Errorf("egl: failed to load %s: %v", name, err)
+ }
+ return nil
+}
+
+func eglChooseConfig(disp _EGLDisplay, attribs []_EGLint) (_EGLConfig, bool) {
+ var cfg _EGLConfig
+ var ncfg _EGLint
+ a := &attribs[0]
+ r, _, _ := _eglChooseConfig.Call(uintptr(disp), uintptr(unsafe.Pointer(a)), uintptr(unsafe.Pointer(&cfg)), 1, uintptr(unsafe.Pointer(&ncfg)))
+ issue34474KeepAlive(a)
+ return cfg, r != 0
+}
+
+func eglCreateContext(disp _EGLDisplay, cfg _EGLConfig, shareCtx _EGLContext, attribs []_EGLint) _EGLContext {
+ a := &attribs[0]
+ c, _, _ := _eglCreateContext.Call(uintptr(disp), uintptr(cfg), uintptr(shareCtx), uintptr(unsafe.Pointer(a)))
+ issue34474KeepAlive(a)
+ return _EGLContext(c)
+}
+
+func eglCreateWindowSurface(disp _EGLDisplay, cfg _EGLConfig, win NativeWindowType, attribs []_EGLint) _EGLSurface {
+ a := &attribs[0]
+ s, _, _ := _eglCreateWindowSurface.Call(uintptr(disp), uintptr(cfg), uintptr(win), uintptr(unsafe.Pointer(a)))
+ issue34474KeepAlive(a)
+ return _EGLSurface(s)
+}
+
+func eglDestroySurface(disp _EGLDisplay, surf _EGLSurface) bool {
+ r, _, _ := _eglDestroySurface.Call(uintptr(disp), uintptr(surf))
+ return r != 0
+}
+
+func eglDestroyContext(disp _EGLDisplay, ctx _EGLContext) bool {
+ r, _, _ := _eglDestroyContext.Call(uintptr(disp), uintptr(ctx))
+ return r != 0
+}
+
+func eglGetConfigAttrib(disp _EGLDisplay, cfg _EGLConfig, attr _EGLint) (_EGLint, bool) {
+ var val uintptr
+ r, _, _ := _eglGetConfigAttrib.Call(uintptr(disp), uintptr(cfg), uintptr(attr), uintptr(unsafe.Pointer(&val)))
+ return _EGLint(val), r != 0
+}
+
+func eglGetDisplay(disp NativeDisplayType) _EGLDisplay {
+ d, _, _ := _eglGetDisplay.Call(uintptr(disp))
+ return _EGLDisplay(d)
+}
+
+func eglGetError() _EGLint {
+ e, _, _ := _eglGetError.Call()
+ return _EGLint(e)
+}
+
+func eglInitialize(disp _EGLDisplay) (_EGLint, _EGLint, bool) {
+ var maj, min uintptr
+ r, _, _ := _eglInitialize.Call(uintptr(disp), uintptr(unsafe.Pointer(&maj)), uintptr(unsafe.Pointer(&min)))
+ return _EGLint(maj), _EGLint(min), r != 0
+}
+
+func eglMakeCurrent(disp _EGLDisplay, draw, read _EGLSurface, ctx _EGLContext) bool {
+ r, _, _ := _eglMakeCurrent.Call(uintptr(disp), uintptr(draw), uintptr(read), uintptr(ctx))
+ return r != 0
+}
+
+func eglReleaseThread() bool {
+ r, _, _ := _eglReleaseThread.Call()
+ return r != 0
+}
+
+func eglSwapInterval(disp _EGLDisplay, interval _EGLint) bool {
+ r, _, _ := _eglSwapInterval.Call(uintptr(disp), uintptr(interval))
+ return r != 0
+}
+
+func eglSwapBuffers(disp _EGLDisplay, surf _EGLSurface) bool {
+ r, _, _ := _eglSwapBuffers.Call(uintptr(disp), uintptr(surf))
+ return r != 0
+}
+
+func eglTerminate(disp _EGLDisplay) bool {
+ r, _, _ := _eglTerminate.Call(uintptr(disp))
+ return r != 0
+}
+
+func eglQueryString(disp _EGLDisplay, name _EGLint) string {
+ r, _, _ := _eglQueryString.Call(uintptr(disp), uintptr(name))
+ return syscall.BytePtrToString((*byte)(unsafe.Pointer(r)))
+}
+
+func eglWaitClient() bool {
+ r, _, _ := _eglWaitClient.Call()
+ return r != 0
+}
+
+// issue34474KeepAlive calls runtime.KeepAlive as a
+// workaround for golang.org/issue/34474.
+func issue34474KeepAlive(v interface{}) {
+ runtime.KeepAlive(v)
+}
diff --git a/vendor/gioui.org/internal/f32color/rgba.go b/vendor/gioui.org/internal/f32color/rgba.go
index efaa1fb..eecf018 100644
--- a/vendor/gioui.org/internal/f32color/rgba.go
+++ b/vendor/gioui.org/internal/f32color/rgba.go
@@ -7,7 +7,7 @@ import (
"math"
)
-// RGBA is a 32 bit floating point linear space color.
+// RGBA is a 32 bit floating point linear premultiplied color space.
type RGBA struct {
R, G, B, A float32
}
@@ -23,30 +23,90 @@ func (col RGBA) Float32() (r, g, b, a float32) {
}
// SRGBA converts from linear to sRGB color space.
-func (col RGBA) SRGB() color.RGBA {
- return color.RGBA{
- R: uint8(linearTosRGB(col.R)*255 + .5),
- G: uint8(linearTosRGB(col.G)*255 + .5),
- B: uint8(linearTosRGB(col.B)*255 + .5),
+func (col RGBA) SRGB() color.NRGBA {
+ if col.A == 0 {
+ return color.NRGBA{}
+ }
+ return color.NRGBA{
+ R: uint8(linearTosRGB(col.R/col.A)*255 + .5),
+ G: uint8(linearTosRGB(col.G/col.A)*255 + .5),
+ B: uint8(linearTosRGB(col.B/col.A)*255 + .5),
A: uint8(col.A*255 + .5),
}
}
+// Luminance calculates the relative luminance of a linear RGBA color.
+// Normalized to 0 for black and 1 for white.
+//
+// See https://www.w3.org/TR/WCAG20/#relativeluminancedef for more details
+func (col RGBA) Luminance() float32 {
+ return 0.2126*col.R + 0.7152*col.G + 0.0722*col.B
+}
+
// Opaque returns the color without alpha component.
func (col RGBA) Opaque() RGBA {
col.A = 1.0
return col
}
-// RGBAFromSRGB converts from SRGBA to RGBA.
-func RGBAFromSRGB(col color.RGBA) RGBA {
- r, g, b, a := col.RGBA()
+// LinearFromSRGB converts from col in the sRGB colorspace to RGBA.
+func LinearFromSRGB(col color.NRGBA) RGBA {
+ af := float32(col.A) / 0xFF
return RGBA{
- R: sRGBToLinear(float32(r) / 0xffff),
- G: sRGBToLinear(float32(g) / 0xffff),
- B: sRGBToLinear(float32(b) / 0xffff),
- A: float32(a) / 0xFFFF,
+ R: sRGBToLinear(float32(col.R)/0xff) * af,
+ G: sRGBToLinear(float32(col.G)/0xff) * af,
+ B: sRGBToLinear(float32(col.B)/0xff) * af,
+ A: af,
+ }
+}
+
+// NRGBAToRGBA converts from non-premultiplied sRGB color to premultiplied sRGB color.
+//
+// Each component in the result is `sRGBToLinear(c * alpha)`, where `c`
+// is the linear color.
+func NRGBAToRGBA(col color.NRGBA) color.RGBA {
+ if col.A == 0xFF {
+ return color.RGBA(col)
+ }
+ c := LinearFromSRGB(col)
+ return color.RGBA{
+ R: uint8(linearTosRGB(c.R)*255 + .5),
+ G: uint8(linearTosRGB(c.G)*255 + .5),
+ B: uint8(linearTosRGB(c.B)*255 + .5),
+ A: col.A,
+ }
+}
+
+// NRGBAToLinearRGBA converts from non-premultiplied sRGB color to premultiplied linear RGBA color.
+//
+// Each component in the result is `c * alpha`, where `c` is the linear color.
+func NRGBAToLinearRGBA(col color.NRGBA) color.RGBA {
+ if col.A == 0xFF {
+ return color.RGBA(col)
+ }
+ c := LinearFromSRGB(col)
+ return color.RGBA{
+ R: uint8(c.R*255 + .5),
+ G: uint8(c.G*255 + .5),
+ B: uint8(c.B*255 + .5),
+ A: col.A,
+ }
+}
+
+// RGBAToNRGBA converts from premultiplied sRGB color to non-premultiplied sRGB color.
+func RGBAToNRGBA(col color.RGBA) color.NRGBA {
+ if col.A == 0xFF {
+ return color.NRGBA(col)
+ }
+
+ linear := RGBA{
+ R: sRGBToLinear(float32(col.R) / 0xff),
+ G: sRGBToLinear(float32(col.G) / 0xff),
+ B: sRGBToLinear(float32(col.B) / 0xff),
+ A: float32(col.A) / 0xff,
}
+
+ return linear.SRGB()
}
// linearTosRGB transforms color value from linear to sRGB.
@@ -73,3 +133,45 @@ func sRGBToLinear(c float32) float32 {
return float32(math.Pow(float64((c+0.055)/1.055), 2.4))
}
}
+
+// MulAlpha applies the alpha to the color.
+func MulAlpha(c color.NRGBA, alpha uint8) color.NRGBA {
+ c.A = uint8(uint32(c.A) * uint32(alpha) / 0xFF)
+ return c
+}
+
+// Disabled blends color towards the luminance and multiplies alpha.
+// Blending towards luminance will desaturate the color.
+// Multiplying alpha blends the color together more with the background.
+func Disabled(c color.NRGBA) (d color.NRGBA) {
+ const r = 80 // blend ratio
+ lum := approxLuminance(c)
+ return color.NRGBA{
+ R: byte((int(c.R)*r + int(lum)*(256-r)) / 256),
+ G: byte((int(c.G)*r + int(lum)*(256-r)) / 256),
+ B: byte((int(c.B)*r + int(lum)*(256-r)) / 256),
+ A: byte(int(c.A) * (128 + 32) / 256),
+ }
+}
+
+// Hovered blends color towards a brighter color.
+func Hovered(c color.NRGBA) (d color.NRGBA) {
+ const r = 0x20 // lighten ratio
+ return color.NRGBA{
+ R: byte(255 - int(255-c.R)*(255-r)/256),
+ G: byte(255 - int(255-c.G)*(255-r)/256),
+ B: byte(255 - int(255-c.B)*(255-r)/256),
+ A: c.A,
+ }
+}
+
+// approxLuminance is a fast approximate version of RGBA.Luminance.
+func approxLuminance(c color.NRGBA) byte {
+ const (
+ r = 13933 // 0.2126 * 256 * 256
+ g = 46871 // 0.7152 * 256 * 256
+ b = 4732 // 0.0722 * 256 * 256
+ t = r + g + b
+ )
+ return byte((r*int(c.R) + g*int(c.G) + b*int(c.B)) / t)
+}
diff --git a/vendor/gioui.org/internal/gl/gl.go b/vendor/gioui.org/internal/gl/gl.go
new file mode 100644
index 0000000..a9e378a
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/gl.go
@@ -0,0 +1,130 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package gl
+
+type (
+ Attrib uint
+ Enum uint
+)
+
+const (
+ ACTIVE_TEXTURE = 0x84E0
+ ALL_BARRIER_BITS = 0xffffffff
+ ARRAY_BUFFER = 0x8892
+ ARRAY_BUFFER_BINDING = 0x8894
+ BACK = 0x0405
+ BLEND = 0xbe2
+ BLEND_DST_RGB = 0x80C8
+ BLEND_SRC_RGB = 0x80C9
+ BLEND_DST_ALPHA = 0x80CA
+ BLEND_SRC_ALPHA = 0x80CB
+ CLAMP_TO_EDGE = 0x812f
+ COLOR_ATTACHMENT0 = 0x8ce0
+ COLOR_BUFFER_BIT = 0x4000
+ COLOR_CLEAR_VALUE = 0x0C22
+ COMPILE_STATUS = 0x8b81
+ COMPUTE_SHADER = 0x91B9
+ CURRENT_PROGRAM = 0x8B8D
+ DEPTH_ATTACHMENT = 0x8d00
+ DEPTH_BUFFER_BIT = 0x100
+ DEPTH_CLEAR_VALUE = 0x0B73
+ DEPTH_COMPONENT16 = 0x81a5
+ DEPTH_COMPONENT24 = 0x81A6
+ DEPTH_COMPONENT32F = 0x8CAC
+ DEPTH_FUNC = 0x0B74
+ DEPTH_TEST = 0xb71
+ DEPTH_WRITEMASK = 0x0B72
+ DRAW_FRAMEBUFFER = 0x8CA9
+ DST_COLOR = 0x306
+ DYNAMIC_DRAW = 0x88E8
+ DYNAMIC_READ = 0x88E9
+ ELEMENT_ARRAY_BUFFER = 0x8893
+ ELEMENT_ARRAY_BUFFER_BINDING = 0x8895
+ EXTENSIONS = 0x1f03
+ FALSE = 0
+ FLOAT = 0x1406
+ FRAGMENT_SHADER = 0x8b30
+ FRAMEBUFFER = 0x8d40
+ FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING = 0x8210
+ FRAMEBUFFER_BINDING = 0x8ca6
+ FRAMEBUFFER_COMPLETE = 0x8cd5
+ FRAMEBUFFER_SRGB = 0x8db9
+ HALF_FLOAT = 0x140b
+ HALF_FLOAT_OES = 0x8d61
+ INFO_LOG_LENGTH = 0x8B84
+ INVALID_INDEX = ^uint(0)
+ GREATER = 0x204
+ GEQUAL = 0x206
+ LINEAR = 0x2601
+ LINK_STATUS = 0x8b82
+ LUMINANCE = 0x1909
+ MAP_READ_BIT = 0x0001
+ MAX_TEXTURE_SIZE = 0xd33
+ NEAREST = 0x2600
+ NO_ERROR = 0x0
+ NUM_EXTENSIONS = 0x821D
+ ONE = 0x1
+ ONE_MINUS_SRC_ALPHA = 0x303
+ PACK_ROW_LENGTH = 0x0D02
+ PROGRAM_BINARY_LENGTH = 0x8741
+ QUERY_RESULT = 0x8866
+ QUERY_RESULT_AVAILABLE = 0x8867
+ R16F = 0x822d
+ R8 = 0x8229
+ READ_FRAMEBUFFER = 0x8ca8
+ READ_FRAMEBUFFER_BINDING = 0x8CAA
+ READ_ONLY = 0x88B8
+ READ_WRITE = 0x88BA
+ RED = 0x1903
+ RENDERER = 0x1F01
+ RENDERBUFFER = 0x8d41
+ RENDERBUFFER_BINDING = 0x8ca7
+ RENDERBUFFER_HEIGHT = 0x8d43
+ RENDERBUFFER_WIDTH = 0x8d42
+ RGB = 0x1907
+ RGBA = 0x1908
+ RGBA8 = 0x8058
+ SHADER_STORAGE_BUFFER = 0x90D2
+ SHADER_STORAGE_BUFFER_BINDING = 0x90D3
+ SHORT = 0x1402
+ SRGB = 0x8c40
+ SRGB_ALPHA_EXT = 0x8c42
+ SRGB8 = 0x8c41
+ SRGB8_ALPHA8 = 0x8c43
+ STATIC_DRAW = 0x88e4
+ STENCIL_BUFFER_BIT = 0x00000400
+ TEXTURE_2D = 0xde1
+ TEXTURE_BINDING_2D = 0x8069
+ TEXTURE_MAG_FILTER = 0x2800
+ TEXTURE_MIN_FILTER = 0x2801
+ TEXTURE_WRAP_S = 0x2802
+ TEXTURE_WRAP_T = 0x2803
+ TEXTURE0 = 0x84c0
+ TEXTURE1 = 0x84c1
+ TRIANGLE_STRIP = 0x5
+ TRIANGLES = 0x4
+ TRUE = 1
+ UNIFORM_BUFFER = 0x8A11
+ UNIFORM_BUFFER_BINDING = 0x8A28
+ UNPACK_ALIGNMENT = 0xcf5
+ UNPACK_ROW_LENGTH = 0x0CF2
+ UNSIGNED_BYTE = 0x1401
+ UNSIGNED_SHORT = 0x1403
+ VIEWPORT = 0x0BA2
+ VERSION = 0x1f02
+ VERTEX_ARRAY_BINDING = 0x85B5
+ VERTEX_SHADER = 0x8b31
+ VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F
+ VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622
+ VERTEX_ATTRIB_ARRAY_POINTER = 0x8645
+ VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A
+ VERTEX_ATTRIB_ARRAY_SIZE = 0x8623
+ VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624
+ VERTEX_ATTRIB_ARRAY_TYPE = 0x8625
+ WRITE_ONLY = 0x88B9
+ ZERO = 0x0
+
+ // EXT_disjoint_timer_query
+ TIME_ELAPSED_EXT = 0x88BF
+ GPU_DISJOINT_EXT = 0x8FBB
+)
diff --git a/vendor/gioui.org/internal/gl/gl_js.go b/vendor/gioui.org/internal/gl/gl_js.go
new file mode 100644
index 0000000..2c7976e
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/gl_js.go
@@ -0,0 +1,458 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package gl
+
+import (
+ "errors"
+ "strings"
+ "syscall/js"
+)
+
+type Functions struct {
+ Ctx js.Value
+ EXT_disjoint_timer_query js.Value
+ EXT_disjoint_timer_query_webgl2 js.Value
+
+ // Cached reference to the Uint8Array JS type.
+ uint8Array js.Value
+
+ // Cached JS arrays.
+ arrayBuf js.Value
+ int32Buf js.Value
+
+ isWebGL2 bool
+}
+
+type Context js.Value
+
+func NewFunctions(ctx Context, forceES bool) (*Functions, error) {
+ f := &Functions{
+ Ctx: js.Value(ctx),
+ uint8Array: js.Global().Get("Uint8Array"),
+ }
+ if err := f.Init(); err != nil {
+ return nil, err
+ }
+ return f, nil
+}
+
+func (f *Functions) Init() error {
+ webgl2Class := js.Global().Get("WebGL2RenderingContext")
+ f.isWebGL2 = !webgl2Class.IsUndefined() && f.Ctx.InstanceOf(webgl2Class)
+ if !f.isWebGL2 {
+ f.EXT_disjoint_timer_query = f.getExtension("EXT_disjoint_timer_query")
+ if f.getExtension("OES_texture_half_float").IsNull() && f.getExtension("OES_texture_float").IsNull() {
+ return errors.New("gl: no support for neither OES_texture_half_float nor OES_texture_float")
+ }
+ if f.getExtension("EXT_sRGB").IsNull() {
+ return errors.New("gl: EXT_sRGB not supported")
+ }
+ } else {
+ // WebGL2 extensions.
+ f.EXT_disjoint_timer_query_webgl2 = f.getExtension("EXT_disjoint_timer_query_webgl2")
+ if f.getExtension("EXT_color_buffer_half_float").IsNull() && f.getExtension("EXT_color_buffer_float").IsNull() {
+ return errors.New("gl: no support for neither EXT_color_buffer_half_float nor EXT_color_buffer_float")
+ }
+ }
+ return nil
+}
+
+func (f *Functions) getExtension(name string) js.Value {
+ return f.Ctx.Call("getExtension", name)
+}
+
+func (f *Functions) ActiveTexture(t Enum) {
+ f.Ctx.Call("activeTexture", int(t))
+}
+func (f *Functions) AttachShader(p Program, s Shader) {
+ f.Ctx.Call("attachShader", js.Value(p), js.Value(s))
+}
+func (f *Functions) BeginQuery(target Enum, query Query) {
+ if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
+ f.Ctx.Call("beginQuery", int(target), js.Value(query))
+ } else {
+ f.EXT_disjoint_timer_query.Call("beginQueryEXT", int(target), js.Value(query))
+ }
+}
+func (f *Functions) BindAttribLocation(p Program, a Attrib, name string) {
+ f.Ctx.Call("bindAttribLocation", js.Value(p), int(a), name)
+}
+func (f *Functions) BindBuffer(target Enum, b Buffer) {
+ f.Ctx.Call("bindBuffer", int(target), js.Value(b))
+}
+func (f *Functions) BindBufferBase(target Enum, index int, b Buffer) {
+ f.Ctx.Call("bindBufferBase", int(target), index, js.Value(b))
+}
+func (f *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
+ f.Ctx.Call("bindFramebuffer", int(target), js.Value(fb))
+}
+func (f *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) {
+ f.Ctx.Call("bindRenderbuffer", int(target), js.Value(rb))
+}
+func (f *Functions) BindTexture(target Enum, t Texture) {
+ f.Ctx.Call("bindTexture", int(target), js.Value(t))
+}
+func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) {
+ panic("not implemented")
+}
+func (f *Functions) BindVertexArray(a VertexArray) {
+ panic("not supported")
+}
+func (f *Functions) BlendEquation(mode Enum) {
+ f.Ctx.Call("blendEquation", int(mode))
+}
+func (f *Functions) BlendFuncSeparate(srcRGB, dstRGB, srcA, dstA Enum) {
+ f.Ctx.Call("blendFunc", int(srcRGB), int(dstRGB), int(srcA), int(dstA))
+}
+func (f *Functions) BufferData(target Enum, size int, usage Enum, data []byte) {
+ if data == nil {
+ f.Ctx.Call("bufferData", int(target), size, int(usage))
+ } else {
+ if len(data) != size {
+ panic("size mismatch")
+ }
+ f.Ctx.Call("bufferData", int(target), f.byteArrayOf(data), int(usage))
+ }
+}
+func (f *Functions) BufferSubData(target Enum, offset int, src []byte) {
+ f.Ctx.Call("bufferSubData", int(target), offset, f.byteArrayOf(src))
+}
+func (f *Functions) CheckFramebufferStatus(target Enum) Enum {
+ return Enum(f.Ctx.Call("checkFramebufferStatus", int(target)).Int())
+}
+func (f *Functions) Clear(mask Enum) {
+ f.Ctx.Call("clear", int(mask))
+}
+func (f *Functions) ClearColor(red, green, blue, alpha float32) {
+ f.Ctx.Call("clearColor", red, green, blue, alpha)
+}
+func (f *Functions) ClearDepthf(d float32) {
+ f.Ctx.Call("clearDepth", d)
+}
+func (f *Functions) CompileShader(s Shader) {
+ f.Ctx.Call("compileShader", js.Value(s))
+}
+func (f *Functions) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {
+ f.Ctx.Call("copyTexSubImage2D", int(target), level, xoffset, yoffset, x, y, width, height)
+}
+func (f *Functions) CreateBuffer() Buffer {
+ return Buffer(f.Ctx.Call("createBuffer"))
+}
+func (f *Functions) CreateFramebuffer() Framebuffer {
+ return Framebuffer(f.Ctx.Call("createFramebuffer"))
+}
+func (f *Functions) CreateProgram() Program {
+ return Program(f.Ctx.Call("createProgram"))
+}
+func (f *Functions) CreateQuery() Query {
+ return Query(f.Ctx.Call("createQuery"))
+}
+func (f *Functions) CreateRenderbuffer() Renderbuffer {
+ return Renderbuffer(f.Ctx.Call("createRenderbuffer"))
+}
+func (f *Functions) CreateShader(ty Enum) Shader {
+ return Shader(f.Ctx.Call("createShader", int(ty)))
+}
+func (f *Functions) CreateTexture() Texture {
+ return Texture(f.Ctx.Call("createTexture"))
+}
+func (f *Functions) CreateVertexArray() VertexArray {
+ panic("not supported")
+}
+func (f *Functions) DeleteBuffer(v Buffer) {
+ f.Ctx.Call("deleteBuffer", js.Value(v))
+}
+func (f *Functions) DeleteFramebuffer(v Framebuffer) {
+ f.Ctx.Call("deleteFramebuffer", js.Value(v))
+}
+func (f *Functions) DeleteProgram(p Program) {
+ f.Ctx.Call("deleteProgram", js.Value(p))
+}
+func (f *Functions) DeleteQuery(query Query) {
+ if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
+ f.Ctx.Call("deleteQuery", js.Value(query))
+ } else {
+ f.EXT_disjoint_timer_query.Call("deleteQueryEXT", js.Value(query))
+ }
+}
+func (f *Functions) DeleteShader(s Shader) {
+ f.Ctx.Call("deleteShader", js.Value(s))
+}
+func (f *Functions) DeleteRenderbuffer(v Renderbuffer) {
+ f.Ctx.Call("deleteRenderbuffer", js.Value(v))
+}
+func (f *Functions) DeleteTexture(v Texture) {
+ f.Ctx.Call("deleteTexture", js.Value(v))
+}
+func (f *Functions) DeleteVertexArray(a VertexArray) {
+ panic("not implemented")
+}
+func (f *Functions) DepthFunc(fn Enum) {
+ f.Ctx.Call("depthFunc", int(fn))
+}
+func (f *Functions) DepthMask(mask bool) {
+ f.Ctx.Call("depthMask", mask)
+}
+func (f *Functions) DisableVertexAttribArray(a Attrib) {
+ f.Ctx.Call("disableVertexAttribArray", int(a))
+}
+func (f *Functions) Disable(cap Enum) {
+ f.Ctx.Call("disable", int(cap))
+}
+func (f *Functions) DrawArrays(mode Enum, first, count int) {
+ f.Ctx.Call("drawArrays", int(mode), first, count)
+}
+func (f *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
+ f.Ctx.Call("drawElements", int(mode), count, int(ty), offset)
+}
+func (f *Functions) DispatchCompute(x, y, z int) {
+ panic("not implemented")
+}
+func (f *Functions) Enable(cap Enum) {
+ f.Ctx.Call("enable", int(cap))
+}
+func (f *Functions) EnableVertexAttribArray(a Attrib) {
+ f.Ctx.Call("enableVertexAttribArray", int(a))
+}
+func (f *Functions) EndQuery(target Enum) {
+ if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
+ f.Ctx.Call("endQuery", int(target))
+ } else {
+ f.EXT_disjoint_timer_query.Call("endQueryEXT", int(target))
+ }
+}
+func (f *Functions) Finish() {
+ f.Ctx.Call("finish")
+}
+func (f *Functions) Flush() {
+ f.Ctx.Call("flush")
+}
+func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) {
+ f.Ctx.Call("framebufferRenderbuffer", int(target), int(attachment), int(renderbuffertarget), js.Value(renderbuffer))
+}
+func (f *Functions) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {
+ f.Ctx.Call("framebufferTexture2D", int(target), int(attachment), int(texTarget), js.Value(t), level)
+}
+func (f *Functions) GetError() Enum {
+ // Avoid slow getError calls. See gio#179.
+ return 0
+}
+func (f *Functions) GetRenderbufferParameteri(target, pname Enum) int {
+ return paramVal(f.Ctx.Call("getRenderbufferParameteri", int(pname)))
+}
+func (f *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {
+ if !f.isWebGL2 && pname == FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING {
+ // FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING is only available on WebGL 2
+ return LINEAR
+ }
+ return paramVal(f.Ctx.Call("getFramebufferAttachmentParameter", int(target), int(attachment), int(pname)))
+}
+func (f *Functions) GetBinding(pname Enum) Object {
+ obj := f.Ctx.Call("getParameter", int(pname))
+ if !obj.Truthy() {
+ return Object{}
+ }
+ return Object(obj)
+}
+func (f *Functions) GetBindingi(pname Enum, idx int) Object {
+ obj := f.Ctx.Call("getIndexedParameter", int(pname), idx)
+ if !obj.Truthy() {
+ return Object{}
+ }
+ return Object(obj)
+}
+func (f *Functions) GetInteger(pname Enum) int {
+ if !f.isWebGL2 {
+ switch pname {
+ case PACK_ROW_LENGTH, UNPACK_ROW_LENGTH:
+ return 0 // PACK_ROW_LENGTH and UNPACK_ROW_LENGTH is only available on WebGL 2
+ }
+ }
+ return paramVal(f.Ctx.Call("getParameter", int(pname)))
+}
+func (f *Functions) GetFloat(pname Enum) float32 {
+ return float32(f.Ctx.Call("getParameter", int(pname)).Float())
+}
+func (f *Functions) GetInteger4(pname Enum) [4]int {
+ arr := f.Ctx.Call("getParameter", int(pname))
+ var res [4]int
+ for i := range res {
+ res[i] = arr.Index(i).Int()
+ }
+ return res
+}
+func (f *Functions) GetFloat4(pname Enum) [4]float32 {
+ arr := f.Ctx.Call("getParameter", int(pname))
+ var res [4]float32
+ for i := range res {
+ res[i] = float32(arr.Index(i).Float())
+ }
+ return res
+}
+func (f *Functions) GetProgrami(p Program, pname Enum) int {
+ return paramVal(f.Ctx.Call("getProgramParameter", js.Value(p), int(pname)))
+}
+func (f *Functions) GetProgramInfoLog(p Program) string {
+ return f.Ctx.Call("getProgramInfoLog", js.Value(p)).String()
+}
+func (f *Functions) GetQueryObjectuiv(query Query, pname Enum) uint {
+ if !f.EXT_disjoint_timer_query_webgl2.IsNull() {
+ return uint(paramVal(f.Ctx.Call("getQueryParameter", js.Value(query), int(pname))))
+ } else {
+ return uint(paramVal(f.EXT_disjoint_timer_query.Call("getQueryObjectEXT", js.Value(query), int(pname))))
+ }
+}
+func (f *Functions) GetShaderi(s Shader, pname Enum) int {
+ return paramVal(f.Ctx.Call("getShaderParameter", js.Value(s), int(pname)))
+}
+func (f *Functions) GetShaderInfoLog(s Shader) string {
+ return f.Ctx.Call("getShaderInfoLog", js.Value(s)).String()
+}
+func (f *Functions) GetString(pname Enum) string {
+ switch pname {
+ case EXTENSIONS:
+ extsjs := f.Ctx.Call("getSupportedExtensions")
+ var exts []string
+ for i := 0; i < extsjs.Length(); i++ {
+ exts = append(exts, "GL_"+extsjs.Index(i).String())
+ }
+ return strings.Join(exts, " ")
+ default:
+ return f.Ctx.Call("getParameter", int(pname)).String()
+ }
+}
+func (f *Functions) GetUniformBlockIndex(p Program, name string) uint {
+ return uint(paramVal(f.Ctx.Call("getUniformBlockIndex", js.Value(p), name)))
+}
+func (f *Functions) GetUniformLocation(p Program, name string) Uniform {
+ return Uniform(f.Ctx.Call("getUniformLocation", js.Value(p), name))
+}
+func (f *Functions) GetVertexAttrib(index int, pname Enum) int {
+ return paramVal(f.Ctx.Call("getVertexAttrib", index, int(pname)))
+}
+func (f *Functions) GetVertexAttribBinding(index int, pname Enum) Object {
+ obj := f.Ctx.Call("getVertexAttrib", index, int(pname))
+ if !obj.Truthy() {
+ return Object{}
+ }
+ return Object(obj)
+}
+func (f *Functions) GetVertexAttribPointer(index int, pname Enum) uintptr {
+ return uintptr(f.Ctx.Call("getVertexAttribOffset", index, int(pname)).Int())
+}
+func (f *Functions) InvalidateFramebuffer(target, attachment Enum) {
+ fn := f.Ctx.Get("invalidateFramebuffer")
+ if !fn.IsUndefined() {
+ if f.int32Buf.IsUndefined() {
+ f.int32Buf = js.Global().Get("Int32Array").New(1)
+ }
+ f.int32Buf.SetIndex(0, int32(attachment))
+ f.Ctx.Call("invalidateFramebuffer", int(target), f.int32Buf)
+ }
+}
+func (f *Functions) IsEnabled(cap Enum) bool {
+ return f.Ctx.Call("isEnabled", int(cap)).Truthy()
+}
+func (f *Functions) LinkProgram(p Program) {
+ f.Ctx.Call("linkProgram", js.Value(p))
+}
+func (f *Functions) PixelStorei(pname Enum, param int) {
+ f.Ctx.Call("pixelStorei", int(pname), param)
+}
+func (f *Functions) MemoryBarrier(barriers Enum) {
+ panic("not implemented")
+}
+func (f *Functions) MapBufferRange(target Enum, offset, length int, access Enum) []byte {
+ panic("not implemented")
+}
+func (f *Functions) RenderbufferStorage(target, internalformat Enum, width, height int) {
+ f.Ctx.Call("renderbufferStorage", int(target), int(internalformat), width, height)
+}
+func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
+ ba := f.byteArrayOf(data)
+ f.Ctx.Call("readPixels", x, y, width, height, int(format), int(ty), ba)
+ js.CopyBytesToGo(data, ba)
+}
+func (f *Functions) Scissor(x, y, width, height int32) {
+ f.Ctx.Call("scissor", x, y, width, height)
+}
+func (f *Functions) ShaderSource(s Shader, src string) {
+ f.Ctx.Call("shaderSource", js.Value(s), src)
+}
+func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width, height int, format, ty Enum) {
+ f.Ctx.Call("texImage2D", int(target), int(level), int(internalFormat), int(width), int(height), 0, int(format), int(ty), nil)
+}
+func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
+ f.Ctx.Call("texStorage2D", int(target), levels, int(internalFormat), width, height)
+}
+func (f *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {
+ f.Ctx.Call("texSubImage2D", int(target), level, x, y, width, height, int(format), int(ty), f.byteArrayOf(data))
+}
+func (f *Functions) TexParameteri(target, pname Enum, param int) {
+ f.Ctx.Call("texParameteri", int(target), int(pname), int(param))
+}
+func (f *Functions) UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint) {
+ f.Ctx.Call("uniformBlockBinding", js.Value(p), int(uniformBlockIndex), int(uniformBlockBinding))
+}
+func (f *Functions) Uniform1f(dst Uniform, v float32) {
+ f.Ctx.Call("uniform1f", js.Value(dst), v)
+}
+func (f *Functions) Uniform1i(dst Uniform, v int) {
+ f.Ctx.Call("uniform1i", js.Value(dst), v)
+}
+func (f *Functions) Uniform2f(dst Uniform, v0, v1 float32) {
+ f.Ctx.Call("uniform2f", js.Value(dst), v0, v1)
+}
+func (f *Functions) Uniform3f(dst Uniform, v0, v1, v2 float32) {
+ f.Ctx.Call("uniform3f", js.Value(dst), v0, v1, v2)
+}
+func (f *Functions) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {
+ f.Ctx.Call("uniform4f", js.Value(dst), v0, v1, v2, v3)
+}
+func (f *Functions) UseProgram(p Program) {
+ f.Ctx.Call("useProgram", js.Value(p))
+}
+func (f *Functions) UnmapBuffer(target Enum) bool {
+ panic("not implemented")
+}
+func (f *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {
+ f.Ctx.Call("vertexAttribPointer", int(dst), size, int(ty), normalized, stride, offset)
+}
+func (f *Functions) Viewport(x, y, width, height int) {
+ f.Ctx.Call("viewport", x, y, width, height)
+}
+
+func (f *Functions) byteArrayOf(data []byte) js.Value {
+ if len(data) == 0 {
+ return js.Null()
+ }
+ f.resizeByteBuffer(len(data))
+ ba := f.uint8Array.New(f.arrayBuf, int(0), int(len(data)))
+ js.CopyBytesToJS(ba, data)
+ return ba
+}
+
+func (f *Functions) resizeByteBuffer(n int) {
+ if n == 0 {
+ return
+ }
+ if !f.arrayBuf.IsUndefined() && f.arrayBuf.Length() >= n {
+ return
+ }
+ f.arrayBuf = js.Global().Get("ArrayBuffer").New(n)
+}
+
+func paramVal(v js.Value) int {
+ switch v.Type() {
+ case js.TypeBoolean:
+ if b := v.Bool(); b {
+ return 1
+ } else {
+ return 0
+ }
+ case js.TypeNumber:
+ return v.Int()
+ default:
+ panic("unknown parameter type")
+ }
+}
diff --git a/vendor/gioui.org/internal/gl/gl_unix.go b/vendor/gioui.org/internal/gl/gl_unix.go
new file mode 100644
index 0000000..f223ced
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/gl_unix.go
@@ -0,0 +1,1222 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build darwin || linux || freebsd || openbsd
+// +build darwin linux freebsd openbsd
+
+package gl
+
+import (
+ "fmt"
+ "runtime"
+ "strings"
+ "unsafe"
+)
+
+/*
+#cgo CFLAGS: -Werror
+#cgo linux freebsd LDFLAGS: -ldl
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#define __USE_GNU
+#include <dlfcn.h>
+
+typedef unsigned int GLenum;
+typedef unsigned int GLuint;
+typedef char GLchar;
+typedef float GLfloat;
+typedef ssize_t GLsizeiptr;
+typedef intptr_t GLintptr;
+typedef unsigned int GLbitfield;
+typedef int GLint;
+typedef unsigned char GLboolean;
+typedef int GLsizei;
+typedef uint8_t GLubyte;
+
+typedef struct {
+ void (*glActiveTexture)(GLenum texture);
+ void (*glAttachShader)(GLuint program, GLuint shader);
+ void (*glBindAttribLocation)(GLuint program, GLuint index, const GLchar *name);
+ void (*glBindBuffer)(GLenum target, GLuint buffer);
+ void (*glBindFramebuffer)(GLenum target, GLuint framebuffer);
+ void (*glBindRenderbuffer)(GLenum target, GLuint renderbuffer);
+ void (*glBindTexture)(GLenum target, GLuint texture);
+ void (*glBlendEquation)(GLenum mode);
+ void (*glBlendFuncSeparate)(GLenum srcRGB, GLenum dstRGB, GLenum srcA, GLenum dstA);
+ void (*glBufferData)(GLenum target, GLsizeiptr size, const void *data, GLenum usage);
+ void (*glBufferSubData)(GLenum target, GLintptr offset, GLsizeiptr size, const void *data);
+ GLenum (*glCheckFramebufferStatus)(GLenum target);
+ void (*glClear)(GLbitfield mask);
+ void (*glClearColor)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ void (*glClearDepthf)(GLfloat d);
+ void (*glCompileShader)(GLuint shader);
+ void (*glCopyTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ GLuint (*glCreateProgram)(void);
+ GLuint (*glCreateShader)(GLenum type);
+ void (*glDeleteBuffers)(GLsizei n, const GLuint *buffers);
+ void (*glDeleteFramebuffers)(GLsizei n, const GLuint *framebuffers);
+ void (*glDeleteProgram)(GLuint program);
+ void (*glDeleteRenderbuffers)(GLsizei n, const GLuint *renderbuffers);
+ void (*glDeleteShader)(GLuint shader);
+ void (*glDeleteTextures)(GLsizei n, const GLuint *textures);
+ void (*glDepthFunc)(GLenum func);
+ void (*glDepthMask)(GLboolean flag);
+ void (*glDisable)(GLenum cap);
+ void (*glDisableVertexAttribArray)(GLuint index);
+ void (*glDrawArrays)(GLenum mode, GLint first, GLsizei count);
+ void (*glDrawElements)(GLenum mode, GLsizei count, GLenum type, const void *indices);
+ void (*glEnable)(GLenum cap);
+ void (*glEnableVertexAttribArray)(GLuint index);
+ void (*glFinish)(void);
+ void (*glFlush)(void);
+ void (*glFramebufferRenderbuffer)(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+ void (*glFramebufferTexture2D)(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ void (*glGenBuffers)(GLsizei n, GLuint *buffers);
+ void (*glGenFramebuffers)(GLsizei n, GLuint *framebuffers);
+ void (*glGenRenderbuffers)(GLsizei n, GLuint *renderbuffers);
+ void (*glGenTextures)(GLsizei n, GLuint *textures);
+ GLenum (*glGetError)(void);
+ void (*glGetFramebufferAttachmentParameteriv)(GLenum target, GLenum attachment, GLenum pname, GLint *params);
+ void (*glGetFloatv)(GLenum pname, GLfloat *data);
+ void (*glGetIntegerv)(GLenum pname, GLint *data);
+ void (*glGetIntegeri_v)(GLenum pname, GLuint idx, GLint *data);
+ void (*glGetProgramiv)(GLuint program, GLenum pname, GLint *params);
+ void (*glGetProgramInfoLog)(GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+ void (*glGetRenderbufferParameteriv)(GLenum target, GLenum pname, GLint *params);
+ void (*glGetShaderiv)(GLuint shader, GLenum pname, GLint *params);
+ void (*glGetShaderInfoLog)(GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog);
+ const GLubyte *(*glGetString)(GLenum name);
+ GLint (*glGetUniformLocation)(GLuint program, const GLchar *name);
+ void (*glGetVertexAttribiv)(GLuint index, GLenum pname, GLint *params);
+ void (*glGetVertexAttribPointerv)(GLuint index, GLenum pname, void **params);
+ GLboolean (*glIsEnabled)(GLenum cap);
+ void (*glLinkProgram)(GLuint program);
+ void (*glPixelStorei)(GLenum pname, GLint param);
+ void (*glReadPixels)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels);
+ void (*glRenderbufferStorage)(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ void (*glScissor)(GLint x, GLint y, GLsizei width, GLsizei height);
+ void (*glShaderSource)(GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length);
+ void (*glTexImage2D)(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels);
+ void (*glTexParameteri)(GLenum target, GLenum pname, GLint param);
+ void (*glTexSubImage2D)(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels);
+ void (*glUniform1f)(GLint location, GLfloat v0);
+ void (*glUniform1i)(GLint location, GLint v0);
+ void (*glUniform2f)(GLint location, GLfloat v0, GLfloat v1);
+ void (*glUniform3f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2);
+ void (*glUniform4f)(GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3);
+ void (*glUseProgram)(GLuint program);
+ void (*glVertexAttribPointer)(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer);
+ void (*glViewport)(GLint x, GLint y, GLsizei width, GLsizei height);
+
+ void (*glBindVertexArray)(GLuint array);
+ void (*glBindBufferBase)(GLenum target, GLuint index, GLuint buffer);
+ GLuint (*glGetUniformBlockIndex)(GLuint program, const GLchar *uniformBlockName);
+ void (*glUniformBlockBinding)(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ void (*glInvalidateFramebuffer)(GLenum target, GLsizei numAttachments, const GLenum *attachments);
+ void (*glBeginQuery)(GLenum target, GLuint id);
+ void (*glDeleteQueries)(GLsizei n, const GLuint *ids);
+ void (*glDeleteVertexArrays)(GLsizei n, const GLuint *ids);
+ void (*glEndQuery)(GLenum target);
+ void (*glGenQueries)(GLsizei n, GLuint *ids);
+ void (*glGenVertexArrays)(GLsizei n, GLuint *ids);
+ void (*glGetProgramBinary)(GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary);
+ void (*glGetQueryObjectuiv)(GLuint id, GLenum pname, GLuint *params);
+ const GLubyte* (*glGetStringi)(GLenum name, GLuint index);
+ void (*glDispatchCompute)(GLuint x, GLuint y, GLuint z);
+ void (*glMemoryBarrier)(GLbitfield barriers);
+ void* (*glMapBufferRange)(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+ GLboolean (*glUnmapBuffer)(GLenum target);
+ void (*glBindImageTexture)(GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
+ void (*glTexStorage2D)(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+ void (*glBlitFramebuffer)(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+} glFunctions;
+
+static void glActiveTexture(glFunctions *f, GLenum texture) {
+ f->glActiveTexture(texture);
+}
+
+static void glAttachShader(glFunctions *f, GLuint program, GLuint shader) {
+ f->glAttachShader(program, shader);
+}
+
+static void glBindAttribLocation(glFunctions *f, GLuint program, GLuint index, const GLchar *name) {
+ f->glBindAttribLocation(program, index, name);
+}
+
+static void glBindBuffer(glFunctions *f, GLenum target, GLuint buffer) {
+ f->glBindBuffer(target, buffer);
+}
+
+static void glBindFramebuffer(glFunctions *f, GLenum target, GLuint framebuffer) {
+ f->glBindFramebuffer(target, framebuffer);
+}
+
+static void glBindRenderbuffer(glFunctions *f, GLenum target, GLuint renderbuffer) {
+ f->glBindRenderbuffer(target, renderbuffer);
+}
+
+static void glBindTexture(glFunctions *f, GLenum target, GLuint texture) {
+ f->glBindTexture(target, texture);
+}
+
+static void glBindVertexArray(glFunctions *f, GLuint array) {
+ f->glBindVertexArray(array);
+}
+
+static void glBlendEquation(glFunctions *f, GLenum mode) {
+ f->glBlendEquation(mode);
+}
+
+static void glBlendFuncSeparate(glFunctions *f, GLenum srcRGB, GLenum dstRGB, GLenum srcA, GLenum dstA) {
+ f->glBlendFuncSeparate(srcRGB, dstRGB, srcA, dstA);
+}
+
+static void glBufferData(glFunctions *f, GLenum target, GLsizeiptr size, const void *data, GLenum usage) {
+ f->glBufferData(target, size, data, usage);
+}
+
+static void glBufferSubData(glFunctions *f, GLenum target, GLintptr offset, GLsizeiptr size, const void *data) {
+ f->glBufferSubData(target, offset, size, data);
+}
+
+static GLenum glCheckFramebufferStatus(glFunctions *f, GLenum target) {
+ return f->glCheckFramebufferStatus(target);
+}
+
+static void glClear(glFunctions *f, GLbitfield mask) {
+ f->glClear(mask);
+}
+
+static void glClearColor(glFunctions *f, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) {
+ f->glClearColor(red, green, blue, alpha);
+}
+
+static void glClearDepthf(glFunctions *f, GLfloat d) {
+ f->glClearDepthf(d);
+}
+
+static void glCompileShader(glFunctions *f, GLuint shader) {
+ f->glCompileShader(shader);
+}
+
+static void glCopyTexSubImage2D(glFunctions *f, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height) {
+ f->glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
+}
+
+static GLuint glCreateProgram(glFunctions *f) {
+ return f->glCreateProgram();
+}
+
+static GLuint glCreateShader(glFunctions *f, GLenum type) {
+ return f->glCreateShader(type);
+}
+
+static void glDeleteBuffers(glFunctions *f, GLsizei n, const GLuint *buffers) {
+ f->glDeleteBuffers(n, buffers);
+}
+
+static void glDeleteFramebuffers(glFunctions *f, GLsizei n, const GLuint *framebuffers) {
+ f->glDeleteFramebuffers(n, framebuffers);
+}
+
+static void glDeleteProgram(glFunctions *f, GLuint program) {
+ f->glDeleteProgram(program);
+}
+
+static void glDeleteRenderbuffers(glFunctions *f, GLsizei n, const GLuint *renderbuffers) {
+ f->glDeleteRenderbuffers(n, renderbuffers);
+}
+
+static void glDeleteShader(glFunctions *f, GLuint shader) {
+ f->glDeleteShader(shader);
+}
+
+static void glDeleteTextures(glFunctions *f, GLsizei n, const GLuint *textures) {
+ f->glDeleteTextures(n, textures);
+}
+
+static void glDepthFunc(glFunctions *f, GLenum func) {
+ f->glDepthFunc(func);
+}
+
+static void glDepthMask(glFunctions *f, GLboolean flag) {
+ f->glDepthMask(flag);
+}
+
+static void glDisable(glFunctions *f, GLenum cap) {
+ f->glDisable(cap);
+}
+
+static void glDisableVertexAttribArray(glFunctions *f, GLuint index) {
+ f->glDisableVertexAttribArray(index);
+}
+
+static void glDrawArrays(glFunctions *f, GLenum mode, GLint first, GLsizei count) {
+ f->glDrawArrays(mode, first, count);
+}
+
+// offset is defined as an uintptr_t to omit Cgo pointer checks.
+static void glDrawElements(glFunctions *f, GLenum mode, GLsizei count, GLenum type, const uintptr_t offset) {
+ f->glDrawElements(mode, count, type, (const void *)offset);
+}
+
+static void glEnable(glFunctions *f, GLenum cap) {
+ f->glEnable(cap);
+}
+
+static void glEnableVertexAttribArray(glFunctions *f, GLuint index) {
+ f->glEnableVertexAttribArray(index);
+}
+
+static void glFinish(glFunctions *f) {
+ f->glFinish();
+}
+
+static void glFlush(glFunctions *f) {
+ f->glFlush();
+}
+
+static void glFramebufferRenderbuffer(glFunctions *f, GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer) {
+ f->glFramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
+}
+
+static void glFramebufferTexture2D(glFunctions *f, GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level) {
+ f->glFramebufferTexture2D(target, attachment, textarget, texture, level);
+}
+
+static void glGenBuffers(glFunctions *f, GLsizei n, GLuint *buffers) {
+ f->glGenBuffers(n, buffers);
+}
+
+static void glGenFramebuffers(glFunctions *f, GLsizei n, GLuint *framebuffers) {
+ f->glGenFramebuffers(n, framebuffers);
+}
+
+static void glGenRenderbuffers(glFunctions *f, GLsizei n, GLuint *renderbuffers) {
+ f->glGenRenderbuffers(n, renderbuffers);
+}
+
+static void glGenTextures(glFunctions *f, GLsizei n, GLuint *textures) {
+ f->glGenTextures(n, textures);
+}
+
+static GLenum glGetError(glFunctions *f) {
+ return f->glGetError();
+}
+
+static void glGetFramebufferAttachmentParameteriv(glFunctions *f, GLenum target, GLenum attachment, GLenum pname, GLint *params) {
+ f->glGetFramebufferAttachmentParameteriv(target, attachment, pname, params);
+}
+
+static void glGetIntegerv(glFunctions *f, GLenum pname, GLint *data) {
+ f->glGetIntegerv(pname, data);
+}
+
+static void glGetFloatv(glFunctions *f, GLenum pname, GLfloat *data) {
+ f->glGetFloatv(pname, data);
+}
+
+static void glGetIntegeri_v(glFunctions *f, GLenum pname, GLuint idx, GLint *data) {
+ f->glGetIntegeri_v(pname, idx, data);
+}
+
+static void glGetProgramiv(glFunctions *f, GLuint program, GLenum pname, GLint *params) {
+ f->glGetProgramiv(program, pname, params);
+}
+
+static void glGetProgramInfoLog(glFunctions *f, GLuint program, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ f->glGetProgramInfoLog(program, bufSize, length, infoLog);
+}
+
+static void glGetRenderbufferParameteriv(glFunctions *f, GLenum target, GLenum pname, GLint *params) {
+ f->glGetRenderbufferParameteriv(target, pname, params);
+}
+
+static void glGetShaderiv(glFunctions *f, GLuint shader, GLenum pname, GLint *params) {
+ f->glGetShaderiv(shader, pname, params);
+}
+
+static void glGetShaderInfoLog(glFunctions *f, GLuint shader, GLsizei bufSize, GLsizei *length, GLchar *infoLog) {
+ f->glGetShaderInfoLog(shader, bufSize, length, infoLog);
+}
+
+static const GLubyte *glGetString(glFunctions *f, GLenum name) {
+ return f->glGetString(name);
+}
+
+static GLint glGetUniformLocation(glFunctions *f, GLuint program, const GLchar *name) {
+ return f->glGetUniformLocation(program, name);
+}
+
+static void glGetVertexAttribiv(glFunctions *f, GLuint index, GLenum pname, GLint *data) {
+ f->glGetVertexAttribiv(index, pname, data);
+}
+
+// Return uintptr_t to avoid Cgo pointer check.
+static uintptr_t glGetVertexAttribPointerv(glFunctions *f, GLuint index, GLenum pname) {
+ void *ptrs;
+ f->glGetVertexAttribPointerv(index, pname, &ptrs);
+ return (uintptr_t)ptrs;
+}
+
+static GLboolean glIsEnabled(glFunctions *f, GLenum cap) {
+ return f->glIsEnabled(cap);
+}
+
+static void glLinkProgram(glFunctions *f, GLuint program) {
+ f->glLinkProgram(program);
+}
+
+static void glPixelStorei(glFunctions *f, GLenum pname, GLint param) {
+ f->glPixelStorei(pname, param);
+}
+
+static void glReadPixels(glFunctions *f, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, void *pixels) {
+ f->glReadPixels(x, y, width, height, format, type, pixels);
+}
+
+static void glRenderbufferStorage(glFunctions *f, GLenum target, GLenum internalformat, GLsizei width, GLsizei height) {
+ f->glRenderbufferStorage(target, internalformat, width, height);
+}
+
+static void glScissor(glFunctions *f, GLint x, GLint y, GLsizei width, GLsizei height) {
+ f->glScissor(x, y, width, height);
+}
+
+static void glShaderSource(glFunctions *f, GLuint shader, GLsizei count, const GLchar *const*string, const GLint *length) {
+ f->glShaderSource(shader, count, string, length);
+}
+
+static void glTexImage2D(glFunctions *f, GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void *pixels) {
+ f->glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
+}
+
+static void glTexParameteri(glFunctions *f, GLenum target, GLenum pname, GLint param) {
+ f->glTexParameteri(target, pname, param);
+}
+
+static void glTexSubImage2D(glFunctions *f, GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const void *pixels) {
+ f->glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
+}
+
+static void glUniform1f(glFunctions *f, GLint location, GLfloat v0) {
+ f->glUniform1f(location, v0);
+}
+
+static void glUniform1i(glFunctions *f, GLint location, GLint v0) {
+ f->glUniform1i(location, v0);
+}
+
+static void glUniform2f(glFunctions *f, GLint location, GLfloat v0, GLfloat v1) {
+ f->glUniform2f(location, v0, v1);
+}
+
+static void glUniform3f(glFunctions *f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ f->glUniform3f(location, v0, v1, v2);
+}
+
+static void glUniform4f(glFunctions *f, GLint location, GLfloat v0, GLfloat v1, GLfloat v2, GLfloat v3) {
+ f->glUniform4f(location, v0, v1, v2, v3);
+}
+
+static void glUseProgram(glFunctions *f, GLuint program) {
+ f->glUseProgram(program);
+}
+
+// offset is defined as an uintptr_t to omit Cgo pointer checks.
+static void glVertexAttribPointer(glFunctions *f, GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, uintptr_t offset) {
+ f->glVertexAttribPointer(index, size, type, normalized, stride, (const void *)offset);
+}
+
+static void glViewport(glFunctions *f, GLint x, GLint y, GLsizei width, GLsizei height) {
+ f->glViewport(x, y, width, height);
+}
+
+static void glBindBufferBase(glFunctions *f, GLenum target, GLuint index, GLuint buffer) {
+ f->glBindBufferBase(target, index, buffer);
+}
+
+static void glUniformBlockBinding(glFunctions *f, GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding) {
+ f->glUniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
+}
+
+static GLuint glGetUniformBlockIndex(glFunctions *f, GLuint program, const GLchar *uniformBlockName) {
+ return f->glGetUniformBlockIndex(program, uniformBlockName);
+}
+
+static void glInvalidateFramebuffer(glFunctions *f, GLenum target, GLenum attachment) {
+ // Framebuffer invalidation is just a hint and can safely be ignored.
+ if (f->glInvalidateFramebuffer != NULL) {
+ f->glInvalidateFramebuffer(target, 1, &attachment);
+ }
+}
+
+static void glBeginQuery(glFunctions *f, GLenum target, GLenum attachment) {
+ f->glBeginQuery(target, attachment);
+}
+
+static void glDeleteQueries(glFunctions *f, GLsizei n, const GLuint *ids) {
+ f->glDeleteQueries(n, ids);
+}
+
+static void glDeleteVertexArrays(glFunctions *f, GLsizei n, const GLuint *ids) {
+ f->glDeleteVertexArrays(n, ids);
+}
+
+static void glEndQuery(glFunctions *f, GLenum target) {
+ f->glEndQuery(target);
+}
+
+static const GLubyte* glGetStringi(glFunctions *f, GLenum name, GLuint index) {
+ return f->glGetStringi(name, index);
+}
+
+static void glGenQueries(glFunctions *f, GLsizei n, GLuint *ids) {
+ f->glGenQueries(n, ids);
+}
+
+static void glGenVertexArrays(glFunctions *f, GLsizei n, GLuint *ids) {
+ f->glGenVertexArrays(n, ids);
+}
+
+static void glGetProgramBinary(glFunctions *f, GLuint program, GLsizei bufsize, GLsizei *length, GLenum *binaryFormat, void *binary) {
+ f->glGetProgramBinary(program, bufsize, length, binaryFormat, binary);
+}
+
+static void glGetQueryObjectuiv(glFunctions *f, GLuint id, GLenum pname, GLuint *params) {
+ f->glGetQueryObjectuiv(id, pname, params);
+}
+
+static void glMemoryBarrier(glFunctions *f, GLbitfield barriers) {
+ f->glMemoryBarrier(barriers);
+}
+
+static void glDispatchCompute(glFunctions *f, GLuint x, GLuint y, GLuint z) {
+ f->glDispatchCompute(x, y, z);
+}
+
+static void *glMapBufferRange(glFunctions *f, GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access) {
+ return f->glMapBufferRange(target, offset, length, access);
+}
+
+static GLboolean glUnmapBuffer(glFunctions *f, GLenum target) {
+ return f->glUnmapBuffer(target);
+}
+
+static void glBindImageTexture(glFunctions *f, GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format) {
+ f->glBindImageTexture(unit, texture, level, layered, layer, access, format);
+}
+
+static void glTexStorage2D(glFunctions *f, GLenum target, GLsizei levels, GLenum internalFormat, GLsizei width, GLsizei height) {
+ f->glTexStorage2D(target, levels, internalFormat, width, height);
+}
+
+static void glBlitFramebuffer(glFunctions *f, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter) {
+ f->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+}
+*/
+import "C"
+
+type Context interface{}
+
+type Functions struct {
+ // Query caches.
+ uints [100]C.GLuint
+ ints [100]C.GLint
+ floats [100]C.GLfloat
+
+ f C.glFunctions
+}
+
+func NewFunctions(ctx Context, forceES bool) (*Functions, error) {
+ if ctx != nil {
+ panic("non-nil context")
+ }
+ f := new(Functions)
+ err := f.load(forceES)
+ if err != nil {
+ return nil, err
+ }
+ return f, nil
+}
+
+func dlsym(handle unsafe.Pointer, s string) unsafe.Pointer {
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+ return C.dlsym(handle, cs)
+}
+
+func dlopen(lib string) unsafe.Pointer {
+ clib := C.CString(lib)
+ defer C.free(unsafe.Pointer(clib))
+ return C.dlopen(clib, C.RTLD_NOW|C.RTLD_LOCAL)
+}
+
+func (f *Functions) load(forceES bool) error {
+ var (
+ loadErr error
+ libNames []string
+ handles []unsafe.Pointer
+ )
+ switch {
+ case runtime.GOOS == "darwin" && !forceES:
+ libNames = []string{"/System/Library/Frameworks/OpenGL.framework/OpenGL"}
+ case runtime.GOOS == "darwin" && forceES:
+ libNames = []string{"libGLESv2.dylib"}
+ case runtime.GOOS == "ios":
+ libNames = []string{"/System/Library/Frameworks/OpenGLES.framework/OpenGLES"}
+ case runtime.GOOS == "android":
+ libNames = []string{"libGLESv2.so", "libGLESv3.so"}
+ default:
+ libNames = []string{"libGLESv2.so.2"}
+ }
+ for _, lib := range libNames {
+ if h := dlopen(lib); h != nil {
+ handles = append(handles, h)
+ }
+ }
+ if len(handles) == 0 {
+ return fmt.Errorf("gl: no OpenGL implementation could be loaded (tried %q)", libNames)
+ }
+ load := func(s string) *[0]byte {
+ for _, h := range handles {
+ if f := dlsym(h, s); f != nil {
+ return (*[0]byte)(f)
+ }
+ }
+ return nil
+ }
+ must := func(s string) *[0]byte {
+ ptr := load(s)
+ if ptr == nil {
+ loadErr = fmt.Errorf("gl: failed to load symbol %q", s)
+ }
+ return ptr
+ }
+ // GL ES 2.0 functions.
+ f.f.glActiveTexture = must("glActiveTexture")
+ f.f.glAttachShader = must("glAttachShader")
+ f.f.glBindAttribLocation = must("glBindAttribLocation")
+ f.f.glBindBuffer = must("glBindBuffer")
+ f.f.glBindFramebuffer = must("glBindFramebuffer")
+ f.f.glBindRenderbuffer = must("glBindRenderbuffer")
+ f.f.glBindTexture = must("glBindTexture")
+ f.f.glBlendEquation = must("glBlendEquation")
+ f.f.glBlendFuncSeparate = must("glBlendFuncSeparate")
+ f.f.glBufferData = must("glBufferData")
+ f.f.glBufferSubData = must("glBufferSubData")
+ f.f.glCheckFramebufferStatus = must("glCheckFramebufferStatus")
+ f.f.glClear = must("glClear")
+ f.f.glClearColor = must("glClearColor")
+ f.f.glClearDepthf = must("glClearDepthf")
+ f.f.glCompileShader = must("glCompileShader")
+ f.f.glCopyTexSubImage2D = must("glCopyTexSubImage2D")
+ f.f.glCreateProgram = must("glCreateProgram")
+ f.f.glCreateShader = must("glCreateShader")
+ f.f.glDeleteBuffers = must("glDeleteBuffers")
+ f.f.glDeleteFramebuffers = must("glDeleteFramebuffers")
+ f.f.glDeleteProgram = must("glDeleteProgram")
+ f.f.glDeleteRenderbuffers = must("glDeleteRenderbuffers")
+ f.f.glDeleteShader = must("glDeleteShader")
+ f.f.glDeleteTextures = must("glDeleteTextures")
+ f.f.glDepthFunc = must("glDepthFunc")
+ f.f.glDepthMask = must("glDepthMask")
+ f.f.glDisable = must("glDisable")
+ f.f.glDisableVertexAttribArray = must("glDisableVertexAttribArray")
+ f.f.glDrawArrays = must("glDrawArrays")
+ f.f.glDrawElements = must("glDrawElements")
+ f.f.glEnable = must("glEnable")
+ f.f.glEnableVertexAttribArray = must("glEnableVertexAttribArray")
+ f.f.glFinish = must("glFinish")
+ f.f.glFlush = must("glFlush")
+ f.f.glFramebufferRenderbuffer = must("glFramebufferRenderbuffer")
+ f.f.glFramebufferTexture2D = must("glFramebufferTexture2D")
+ f.f.glGenBuffers = must("glGenBuffers")
+ f.f.glGenFramebuffers = must("glGenFramebuffers")
+ f.f.glGenRenderbuffers = must("glGenRenderbuffers")
+ f.f.glGenTextures = must("glGenTextures")
+ f.f.glGetError = must("glGetError")
+ f.f.glGetFramebufferAttachmentParameteriv = must("glGetFramebufferAttachmentParameteriv")
+ f.f.glGetIntegerv = must("glGetIntegerv")
+ f.f.glGetFloatv = must("glGetFloatv")
+ f.f.glGetProgramiv = must("glGetProgramiv")
+ f.f.glGetProgramInfoLog = must("glGetProgramInfoLog")
+ f.f.glGetRenderbufferParameteriv = must("glGetRenderbufferParameteriv")
+ f.f.glGetShaderiv = must("glGetShaderiv")
+ f.f.glGetShaderInfoLog = must("glGetShaderInfoLog")
+ f.f.glGetString = must("glGetString")
+ f.f.glGetUniformLocation = must("glGetUniformLocation")
+ f.f.glGetVertexAttribiv = must("glGetVertexAttribiv")
+ f.f.glGetVertexAttribPointerv = must("glGetVertexAttribPointerv")
+ f.f.glIsEnabled = must("glIsEnabled")
+ f.f.glLinkProgram = must("glLinkProgram")
+ f.f.glPixelStorei = must("glPixelStorei")
+ f.f.glReadPixels = must("glReadPixels")
+ f.f.glRenderbufferStorage = must("glRenderbufferStorage")
+ f.f.glScissor = must("glScissor")
+ f.f.glShaderSource = must("glShaderSource")
+ f.f.glTexImage2D = must("glTexImage2D")
+ f.f.glTexParameteri = must("glTexParameteri")
+ f.f.glTexSubImage2D = must("glTexSubImage2D")
+ f.f.glUniform1f = must("glUniform1f")
+ f.f.glUniform1i = must("glUniform1i")
+ f.f.glUniform2f = must("glUniform2f")
+ f.f.glUniform3f = must("glUniform3f")
+ f.f.glUniform4f = must("glUniform4f")
+ f.f.glUseProgram = must("glUseProgram")
+ f.f.glVertexAttribPointer = must("glVertexAttribPointer")
+ f.f.glViewport = must("glViewport")
+
+ // Extensions and GL ES 3 functions.
+ f.f.glBindBufferBase = load("glBindBufferBase")
+ f.f.glBindVertexArray = load("glBindVertexArray")
+ f.f.glGetIntegeri_v = load("glGetIntegeri_v")
+ f.f.glGetUniformBlockIndex = load("glGetUniformBlockIndex")
+ f.f.glUniformBlockBinding = load("glUniformBlockBinding")
+ f.f.glInvalidateFramebuffer = load("glInvalidateFramebuffer")
+ f.f.glGetStringi = load("glGetStringi")
+ // Fall back to EXT_invalidate_framebuffer if available.
+ if f.f.glInvalidateFramebuffer == nil {
+ f.f.glInvalidateFramebuffer = load("glDiscardFramebufferEXT")
+ }
+
+ f.f.glBeginQuery = load("glBeginQuery")
+ if f.f.glBeginQuery == nil {
+ f.f.glBeginQuery = load("glBeginQueryEXT")
+ }
+ f.f.glDeleteQueries = load("glDeleteQueries")
+ if f.f.glDeleteQueries == nil {
+ f.f.glDeleteQueries = load("glDeleteQueriesEXT")
+ }
+ f.f.glEndQuery = load("glEndQuery")
+ if f.f.glEndQuery == nil {
+ f.f.glEndQuery = load("glEndQueryEXT")
+ }
+ f.f.glGenQueries = load("glGenQueries")
+ if f.f.glGenQueries == nil {
+ f.f.glGenQueries = load("glGenQueriesEXT")
+ }
+ f.f.glGetQueryObjectuiv = load("glGetQueryObjectuiv")
+ if f.f.glGetQueryObjectuiv == nil {
+ f.f.glGetQueryObjectuiv = load("glGetQueryObjectuivEXT")
+ }
+
+ f.f.glDeleteVertexArrays = load("glDeleteVertexArrays")
+ f.f.glGenVertexArrays = load("glGenVertexArrays")
+ f.f.glMemoryBarrier = load("glMemoryBarrier")
+ f.f.glDispatchCompute = load("glDispatchCompute")
+ f.f.glMapBufferRange = load("glMapBufferRange")
+ f.f.glUnmapBuffer = load("glUnmapBuffer")
+ f.f.glBindImageTexture = load("glBindImageTexture")
+ f.f.glTexStorage2D = load("glTexStorage2D")
+ f.f.glBlitFramebuffer = load("glBlitFramebuffer")
+ f.f.glGetProgramBinary = load("glGetProgramBinary")
+
+ return loadErr
+}
+
+func (f *Functions) ActiveTexture(texture Enum) {
+ C.glActiveTexture(&f.f, C.GLenum(texture))
+}
+
+func (f *Functions) AttachShader(p Program, s Shader) {
+ C.glAttachShader(&f.f, C.GLuint(p.V), C.GLuint(s.V))
+}
+
+func (f *Functions) BeginQuery(target Enum, query Query) {
+ C.glBeginQuery(&f.f, C.GLenum(target), C.GLenum(query.V))
+}
+
+func (f *Functions) BindAttribLocation(p Program, a Attrib, name string) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+ C.glBindAttribLocation(&f.f, C.GLuint(p.V), C.GLuint(a), cname)
+}
+
+func (f *Functions) BindBufferBase(target Enum, index int, b Buffer) {
+ C.glBindBufferBase(&f.f, C.GLenum(target), C.GLuint(index), C.GLuint(b.V))
+}
+
+func (f *Functions) BindBuffer(target Enum, b Buffer) {
+ C.glBindBuffer(&f.f, C.GLenum(target), C.GLuint(b.V))
+}
+
+func (f *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
+ C.glBindFramebuffer(&f.f, C.GLenum(target), C.GLuint(fb.V))
+}
+
+func (f *Functions) BindRenderbuffer(target Enum, fb Renderbuffer) {
+ C.glBindRenderbuffer(&f.f, C.GLenum(target), C.GLuint(fb.V))
+}
+
+func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) {
+ l := C.GLboolean(FALSE)
+ if layered {
+ l = TRUE
+ }
+ C.glBindImageTexture(&f.f, C.GLuint(unit), C.GLuint(t.V), C.GLint(level), l, C.GLint(layer), C.GLenum(access), C.GLenum(format))
+}
+
+func (f *Functions) BindTexture(target Enum, t Texture) {
+ C.glBindTexture(&f.f, C.GLenum(target), C.GLuint(t.V))
+}
+
+func (f *Functions) BindVertexArray(a VertexArray) {
+ C.glBindVertexArray(&f.f, C.GLuint(a.V))
+}
+
+func (f *Functions) BlendEquation(mode Enum) {
+ C.glBlendEquation(&f.f, C.GLenum(mode))
+}
+
+func (f *Functions) BlendFuncSeparate(srcRGB, dstRGB, srcA, dstA Enum) {
+ C.glBlendFuncSeparate(&f.f, C.GLenum(srcRGB), C.GLenum(dstRGB), C.GLenum(srcA), C.GLenum(dstA))
+}
+
+func (f *Functions) BlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1 int, mask Enum, filter Enum) {
+ C.glBlitFramebuffer(&f.f,
+ C.GLint(sx0), C.GLint(sy0), C.GLint(sx1), C.GLint(sy1),
+ C.GLint(dx0), C.GLint(dy0), C.GLint(dx1), C.GLint(dy1),
+ C.GLenum(mask), C.GLenum(filter),
+ )
+}
+
+func (f *Functions) BufferData(target Enum, size int, usage Enum, data []byte) {
+ var p unsafe.Pointer
+ if len(data) > 0 {
+ p = unsafe.Pointer(&data[0])
+ }
+ C.glBufferData(&f.f, C.GLenum(target), C.GLsizeiptr(size), p, C.GLenum(usage))
+}
+
+func (f *Functions) BufferSubData(target Enum, offset int, src []byte) {
+ var p unsafe.Pointer
+ if len(src) > 0 {
+ p = unsafe.Pointer(&src[0])
+ }
+ C.glBufferSubData(&f.f, C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(len(src)), p)
+}
+
+func (f *Functions) CheckFramebufferStatus(target Enum) Enum {
+ return Enum(C.glCheckFramebufferStatus(&f.f, C.GLenum(target)))
+}
+
+func (f *Functions) Clear(mask Enum) {
+ C.glClear(&f.f, C.GLbitfield(mask))
+}
+
+func (f *Functions) ClearColor(red float32, green float32, blue float32, alpha float32) {
+ C.glClearColor(&f.f, C.GLfloat(red), C.GLfloat(green), C.GLfloat(blue), C.GLfloat(alpha))
+}
+
+func (f *Functions) ClearDepthf(d float32) {
+ C.glClearDepthf(&f.f, C.GLfloat(d))
+}
+
+func (f *Functions) CompileShader(s Shader) {
+ C.glCompileShader(&f.f, C.GLuint(s.V))
+}
+
+func (f *Functions) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {
+ C.glCopyTexSubImage2D(&f.f, C.GLenum(target), C.GLint(level), C.GLint(xoffset), C.GLint(yoffset), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
+}
+
+func (f *Functions) CreateBuffer() Buffer {
+ C.glGenBuffers(&f.f, 1, &f.uints[0])
+ return Buffer{uint(f.uints[0])}
+}
+
+func (f *Functions) CreateFramebuffer() Framebuffer {
+ C.glGenFramebuffers(&f.f, 1, &f.uints[0])
+ return Framebuffer{uint(f.uints[0])}
+}
+
+func (f *Functions) CreateProgram() Program {
+ return Program{uint(C.glCreateProgram(&f.f))}
+}
+
+func (f *Functions) CreateQuery() Query {
+ C.glGenQueries(&f.f, 1, &f.uints[0])
+ return Query{uint(f.uints[0])}
+}
+
+func (f *Functions) CreateRenderbuffer() Renderbuffer {
+ C.glGenRenderbuffers(&f.f, 1, &f.uints[0])
+ return Renderbuffer{uint(f.uints[0])}
+}
+
+func (f *Functions) CreateShader(ty Enum) Shader {
+ return Shader{uint(C.glCreateShader(&f.f, C.GLenum(ty)))}
+}
+
+func (f *Functions) CreateTexture() Texture {
+ C.glGenTextures(&f.f, 1, &f.uints[0])
+ return Texture{uint(f.uints[0])}
+}
+
+func (f *Functions) CreateVertexArray() VertexArray {
+ C.glGenVertexArrays(&f.f, 1, &f.uints[0])
+ return VertexArray{uint(f.uints[0])}
+}
+
+func (f *Functions) DeleteBuffer(v Buffer) {
+ f.uints[0] = C.GLuint(v.V)
+ C.glDeleteBuffers(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DeleteFramebuffer(v Framebuffer) {
+ f.uints[0] = C.GLuint(v.V)
+ C.glDeleteFramebuffers(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DeleteProgram(p Program) {
+ C.glDeleteProgram(&f.f, C.GLuint(p.V))
+}
+
+func (f *Functions) DeleteQuery(query Query) {
+ f.uints[0] = C.GLuint(query.V)
+ C.glDeleteQueries(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DeleteVertexArray(array VertexArray) {
+ f.uints[0] = C.GLuint(array.V)
+ C.glDeleteVertexArrays(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DeleteRenderbuffer(v Renderbuffer) {
+ f.uints[0] = C.GLuint(v.V)
+ C.glDeleteRenderbuffers(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DeleteShader(s Shader) {
+ C.glDeleteShader(&f.f, C.GLuint(s.V))
+}
+
+func (f *Functions) DeleteTexture(v Texture) {
+ f.uints[0] = C.GLuint(v.V)
+ C.glDeleteTextures(&f.f, 1, &f.uints[0])
+}
+
+func (f *Functions) DepthFunc(v Enum) {
+ C.glDepthFunc(&f.f, C.GLenum(v))
+}
+
+func (f *Functions) DepthMask(mask bool) {
+ m := C.GLboolean(FALSE)
+ if mask {
+ m = C.GLboolean(TRUE)
+ }
+ C.glDepthMask(&f.f, m)
+}
+
+func (f *Functions) DisableVertexAttribArray(a Attrib) {
+ C.glDisableVertexAttribArray(&f.f, C.GLuint(a))
+}
+
+func (f *Functions) Disable(cap Enum) {
+ C.glDisable(&f.f, C.GLenum(cap))
+}
+
+func (f *Functions) DrawArrays(mode Enum, first int, count int) {
+ C.glDrawArrays(&f.f, C.GLenum(mode), C.GLint(first), C.GLsizei(count))
+}
+
+func (f *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
+ C.glDrawElements(&f.f, C.GLenum(mode), C.GLsizei(count), C.GLenum(ty), C.uintptr_t(offset))
+}
+
+func (f *Functions) DispatchCompute(x, y, z int) {
+ C.glDispatchCompute(&f.f, C.GLuint(x), C.GLuint(y), C.GLuint(z))
+}
+
+func (f *Functions) Enable(cap Enum) {
+ C.glEnable(&f.f, C.GLenum(cap))
+}
+
+func (f *Functions) EndQuery(target Enum) {
+ C.glEndQuery(&f.f, C.GLenum(target))
+}
+
+func (f *Functions) EnableVertexAttribArray(a Attrib) {
+ C.glEnableVertexAttribArray(&f.f, C.GLuint(a))
+}
+
+func (f *Functions) Finish() {
+ C.glFinish(&f.f)
+}
+
+func (f *Functions) Flush() {
+ C.glFlush(&f.f)
+}
+
+func (f *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) {
+ C.glFramebufferRenderbuffer(&f.f, C.GLenum(target), C.GLenum(attachment), C.GLenum(renderbuffertarget), C.GLuint(renderbuffer.V))
+}
+
+func (f *Functions) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {
+ C.glFramebufferTexture2D(&f.f, C.GLenum(target), C.GLenum(attachment), C.GLenum(texTarget), C.GLuint(t.V), C.GLint(level))
+}
+
+func (c *Functions) GetBinding(pname Enum) Object {
+ return Object{uint(c.GetInteger(pname))}
+}
+
+func (c *Functions) GetBindingi(pname Enum, idx int) Object {
+ return Object{uint(c.GetIntegeri(pname, idx))}
+}
+
+func (f *Functions) GetError() Enum {
+ return Enum(C.glGetError(&f.f))
+}
+
+func (f *Functions) GetRenderbufferParameteri(target, pname Enum) int {
+ C.glGetRenderbufferParameteriv(&f.f, C.GLenum(target), C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {
+ C.glGetFramebufferAttachmentParameteriv(&f.f, C.GLenum(target), C.GLenum(attachment), C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetFloat4(pname Enum) [4]float32 {
+ C.glGetFloatv(&f.f, C.GLenum(pname), &f.floats[0])
+ var r [4]float32
+ for i := range r {
+ r[i] = float32(f.floats[i])
+ }
+ return r
+}
+
+func (f *Functions) GetFloat(pname Enum) float32 {
+ C.glGetFloatv(&f.f, C.GLenum(pname), &f.floats[0])
+ return float32(f.floats[0])
+}
+
+func (f *Functions) GetInteger4(pname Enum) [4]int {
+ C.glGetIntegerv(&f.f, C.GLenum(pname), &f.ints[0])
+ var r [4]int
+ for i := range r {
+ r[i] = int(f.ints[i])
+ }
+ return r
+}
+
+func (f *Functions) GetInteger(pname Enum) int {
+ C.glGetIntegerv(&f.f, C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetIntegeri(pname Enum, idx int) int {
+ C.glGetIntegeri_v(&f.f, C.GLenum(pname), C.GLuint(idx), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetProgrami(p Program, pname Enum) int {
+ C.glGetProgramiv(&f.f, C.GLuint(p.V), C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetProgramBinary(p Program) []byte {
+ sz := f.GetProgrami(p, PROGRAM_BINARY_LENGTH)
+ if sz == 0 {
+ return nil
+ }
+ buf := make([]byte, sz)
+ var format C.GLenum
+ C.glGetProgramBinary(&f.f, C.GLuint(p.V), C.GLsizei(sz), nil, &format, unsafe.Pointer(&buf[0]))
+ return buf
+}
+
+func (f *Functions) GetProgramInfoLog(p Program) string {
+ n := f.GetProgrami(p, INFO_LOG_LENGTH)
+ buf := make([]byte, n)
+ C.glGetProgramInfoLog(&f.f, C.GLuint(p.V), C.GLsizei(len(buf)), nil, (*C.GLchar)(unsafe.Pointer(&buf[0])))
+ return string(buf)
+}
+
+func (f *Functions) GetQueryObjectuiv(query Query, pname Enum) uint {
+ C.glGetQueryObjectuiv(&f.f, C.GLuint(query.V), C.GLenum(pname), &f.uints[0])
+ return uint(f.uints[0])
+}
+
+func (f *Functions) GetShaderi(s Shader, pname Enum) int {
+ C.glGetShaderiv(&f.f, C.GLuint(s.V), C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetShaderInfoLog(s Shader) string {
+ n := f.GetShaderi(s, INFO_LOG_LENGTH)
+ buf := make([]byte, n)
+ C.glGetShaderInfoLog(&f.f, C.GLuint(s.V), C.GLsizei(len(buf)), nil, (*C.GLchar)(unsafe.Pointer(&buf[0])))
+ return string(buf)
+}
+
+func (f *Functions) getStringi(pname Enum, index int) string {
+ str := C.glGetStringi(&f.f, C.GLenum(pname), C.GLuint(index))
+ if str == nil {
+ return ""
+ }
+ return C.GoString((*C.char)(unsafe.Pointer(str)))
+}
+
+func (f *Functions) GetString(pname Enum) string {
+ switch {
+ case runtime.GOOS == "darwin" && pname == EXTENSIONS:
+ // macOS OpenGL 3 core profile doesn't support glGetString(GL_EXTENSIONS).
+ // Use glGetStringi(GL_EXTENSIONS, <index>).
+ var exts []string
+ nexts := f.GetInteger(NUM_EXTENSIONS)
+ for i := 0; i < nexts; i++ {
+ ext := f.getStringi(EXTENSIONS, i)
+ exts = append(exts, ext)
+ }
+ return strings.Join(exts, " ")
+ default:
+ str := C.glGetString(&f.f, C.GLenum(pname))
+ return C.GoString((*C.char)(unsafe.Pointer(str)))
+ }
+}
+
+func (f *Functions) GetUniformBlockIndex(p Program, name string) uint {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+ return uint(C.glGetUniformBlockIndex(&f.f, C.GLuint(p.V), cname))
+}
+
+func (f *Functions) GetUniformLocation(p Program, name string) Uniform {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+ return Uniform{int(C.glGetUniformLocation(&f.f, C.GLuint(p.V), cname))}
+}
+
+func (f *Functions) GetVertexAttrib(index int, pname Enum) int {
+ C.glGetVertexAttribiv(&f.f, C.GLuint(index), C.GLenum(pname), &f.ints[0])
+ return int(f.ints[0])
+}
+
+func (f *Functions) GetVertexAttribBinding(index int, pname Enum) Object {
+ return Object{uint(f.GetVertexAttrib(index, pname))}
+}
+
+func (f *Functions) GetVertexAttribPointer(index int, pname Enum) uintptr {
+ ptr := C.glGetVertexAttribPointerv(&f.f, C.GLuint(index), C.GLenum(pname))
+ return uintptr(ptr)
+}
+
+func (f *Functions) InvalidateFramebuffer(target, attachment Enum) {
+ C.glInvalidateFramebuffer(&f.f, C.GLenum(target), C.GLenum(attachment))
+}
+
+func (f *Functions) IsEnabled(cap Enum) bool {
+ return C.glIsEnabled(&f.f, C.GLenum(cap)) == TRUE
+}
+
+func (f *Functions) LinkProgram(p Program) {
+ C.glLinkProgram(&f.f, C.GLuint(p.V))
+}
+
+func (f *Functions) PixelStorei(pname Enum, param int) {
+ C.glPixelStorei(&f.f, C.GLenum(pname), C.GLint(param))
+}
+
+func (f *Functions) MemoryBarrier(barriers Enum) {
+ C.glMemoryBarrier(&f.f, C.GLbitfield(barriers))
+}
+
+func (f *Functions) MapBufferRange(target Enum, offset, length int, access Enum) []byte {
+ p := C.glMapBufferRange(&f.f, C.GLenum(target), C.GLintptr(offset), C.GLsizeiptr(length), C.GLbitfield(access))
+ if p == nil {
+ return nil
+ }
+ return (*[1 << 30]byte)(p)[:length:length]
+}
+
+func (f *Functions) Scissor(x, y, width, height int32) {
+ C.glScissor(&f.f, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
+}
+
+func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
+ var p unsafe.Pointer
+ if len(data) > 0 {
+ p = unsafe.Pointer(&data[0])
+ }
+ C.glReadPixels(&f.f, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(ty), p)
+}
+
+func (f *Functions) RenderbufferStorage(target, internalformat Enum, width, height int) {
+ C.glRenderbufferStorage(&f.f, C.GLenum(target), C.GLenum(internalformat), C.GLsizei(width), C.GLsizei(height))
+}
+
+func (f *Functions) ShaderSource(s Shader, src string) {
+ csrc := C.CString(src)
+ defer C.free(unsafe.Pointer(csrc))
+ strlen := C.GLint(len(src))
+ C.glShaderSource(&f.f, C.GLuint(s.V), 1, &csrc, &strlen)
+}
+
+func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
+ C.glTexImage2D(&f.f, C.GLenum(target), C.GLint(level), C.GLint(internalFormat), C.GLsizei(width), C.GLsizei(height), 0, C.GLenum(format), C.GLenum(ty), nil)
+}
+
+func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
+ C.glTexStorage2D(&f.f, C.GLenum(target), C.GLsizei(levels), C.GLenum(internalFormat), C.GLsizei(width), C.GLsizei(height))
+}
+
+func (f *Functions) TexSubImage2D(target Enum, level int, x int, y int, width int, height int, format Enum, ty Enum, data []byte) {
+ var p unsafe.Pointer
+ if len(data) > 0 {
+ p = unsafe.Pointer(&data[0])
+ }
+ C.glTexSubImage2D(&f.f, C.GLenum(target), C.GLint(level), C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height), C.GLenum(format), C.GLenum(ty), p)
+}
+
+func (f *Functions) TexParameteri(target, pname Enum, param int) {
+ C.glTexParameteri(&f.f, C.GLenum(target), C.GLenum(pname), C.GLint(param))
+}
+
+func (f *Functions) UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint) {
+ C.glUniformBlockBinding(&f.f, C.GLuint(p.V), C.GLuint(uniformBlockIndex), C.GLuint(uniformBlockBinding))
+}
+
+func (f *Functions) Uniform1f(dst Uniform, v float32) {
+ C.glUniform1f(&f.f, C.GLint(dst.V), C.GLfloat(v))
+}
+
+func (f *Functions) Uniform1i(dst Uniform, v int) {
+ C.glUniform1i(&f.f, C.GLint(dst.V), C.GLint(v))
+}
+
+func (f *Functions) Uniform2f(dst Uniform, v0 float32, v1 float32) {
+ C.glUniform2f(&f.f, C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1))
+}
+
+func (f *Functions) Uniform3f(dst Uniform, v0 float32, v1 float32, v2 float32) {
+ C.glUniform3f(&f.f, C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2))
+}
+
+func (f *Functions) Uniform4f(dst Uniform, v0 float32, v1 float32, v2 float32, v3 float32) {
+ C.glUniform4f(&f.f, C.GLint(dst.V), C.GLfloat(v0), C.GLfloat(v1), C.GLfloat(v2), C.GLfloat(v3))
+}
+
+func (f *Functions) UseProgram(p Program) {
+ C.glUseProgram(&f.f, C.GLuint(p.V))
+}
+
+func (f *Functions) UnmapBuffer(target Enum) bool {
+ r := C.glUnmapBuffer(&f.f, C.GLenum(target))
+ return r == TRUE
+}
+
+func (f *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride int, offset int) {
+ var n C.GLboolean = FALSE
+ if normalized {
+ n = TRUE
+ }
+ C.glVertexAttribPointer(&f.f, C.GLuint(dst), C.GLint(size), C.GLenum(ty), n, C.GLsizei(stride), C.uintptr_t(offset))
+}
+
+func (f *Functions) Viewport(x int, y int, width int, height int) {
+ C.glViewport(&f.f, C.GLint(x), C.GLint(y), C.GLsizei(width), C.GLsizei(height))
+}
diff --git a/vendor/gioui.org/internal/gl/gl_windows.go b/vendor/gioui.org/internal/gl/gl_windows.go
new file mode 100644
index 0000000..99b1694
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/gl_windows.go
@@ -0,0 +1,502 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package gl
+
+import (
+ "math"
+ "runtime"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+var (
+ LibGLESv2 = windows.NewLazyDLL("libGLESv2.dll")
+ _glActiveTexture = LibGLESv2.NewProc("glActiveTexture")
+ _glAttachShader = LibGLESv2.NewProc("glAttachShader")
+ _glBeginQuery = LibGLESv2.NewProc("glBeginQuery")
+ _glBindAttribLocation = LibGLESv2.NewProc("glBindAttribLocation")
+ _glBindBuffer = LibGLESv2.NewProc("glBindBuffer")
+ _glBindBufferBase = LibGLESv2.NewProc("glBindBufferBase")
+ _glBindFramebuffer = LibGLESv2.NewProc("glBindFramebuffer")
+ _glBindRenderbuffer = LibGLESv2.NewProc("glBindRenderbuffer")
+ _glBindTexture = LibGLESv2.NewProc("glBindTexture")
+ _glBindVertexArray = LibGLESv2.NewProc("glBindVertexArray")
+ _glBlendEquation = LibGLESv2.NewProc("glBlendEquation")
+ _glBlendFuncSeparate = LibGLESv2.NewProc("glBlendFuncSeparate")
+ _glBufferData = LibGLESv2.NewProc("glBufferData")
+ _glBufferSubData = LibGLESv2.NewProc("glBufferSubData")
+ _glCheckFramebufferStatus = LibGLESv2.NewProc("glCheckFramebufferStatus")
+ _glClear = LibGLESv2.NewProc("glClear")
+ _glClearColor = LibGLESv2.NewProc("glClearColor")
+ _glClearDepthf = LibGLESv2.NewProc("glClearDepthf")
+ _glDeleteQueries = LibGLESv2.NewProc("glDeleteQueries")
+ _glDeleteVertexArrays = LibGLESv2.NewProc("glDeleteVertexArrays")
+ _glCompileShader = LibGLESv2.NewProc("glCompileShader")
+ _glCopyTexSubImage2D = LibGLESv2.NewProc("glCopyTexSubImage2D")
+ _glGenBuffers = LibGLESv2.NewProc("glGenBuffers")
+ _glGenFramebuffers = LibGLESv2.NewProc("glGenFramebuffers")
+ _glGenVertexArrays = LibGLESv2.NewProc("glGenVertexArrays")
+ _glGetUniformBlockIndex = LibGLESv2.NewProc("glGetUniformBlockIndex")
+ _glCreateProgram = LibGLESv2.NewProc("glCreateProgram")
+ _glGenRenderbuffers = LibGLESv2.NewProc("glGenRenderbuffers")
+ _glCreateShader = LibGLESv2.NewProc("glCreateShader")
+ _glGenTextures = LibGLESv2.NewProc("glGenTextures")
+ _glDeleteBuffers = LibGLESv2.NewProc("glDeleteBuffers")
+ _glDeleteFramebuffers = LibGLESv2.NewProc("glDeleteFramebuffers")
+ _glDeleteProgram = LibGLESv2.NewProc("glDeleteProgram")
+ _glDeleteShader = LibGLESv2.NewProc("glDeleteShader")
+ _glDeleteRenderbuffers = LibGLESv2.NewProc("glDeleteRenderbuffers")
+ _glDeleteTextures = LibGLESv2.NewProc("glDeleteTextures")
+ _glDepthFunc = LibGLESv2.NewProc("glDepthFunc")
+ _glDepthMask = LibGLESv2.NewProc("glDepthMask")
+ _glDisableVertexAttribArray = LibGLESv2.NewProc("glDisableVertexAttribArray")
+ _glDisable = LibGLESv2.NewProc("glDisable")
+ _glDrawArrays = LibGLESv2.NewProc("glDrawArrays")
+ _glDrawElements = LibGLESv2.NewProc("glDrawElements")
+ _glEnable = LibGLESv2.NewProc("glEnable")
+ _glEnableVertexAttribArray = LibGLESv2.NewProc("glEnableVertexAttribArray")
+ _glEndQuery = LibGLESv2.NewProc("glEndQuery")
+ _glFinish = LibGLESv2.NewProc("glFinish")
+ _glFlush = LibGLESv2.NewProc("glFlush")
+ _glFramebufferRenderbuffer = LibGLESv2.NewProc("glFramebufferRenderbuffer")
+ _glFramebufferTexture2D = LibGLESv2.NewProc("glFramebufferTexture2D")
+ _glGenQueries = LibGLESv2.NewProc("glGenQueries")
+ _glGetError = LibGLESv2.NewProc("glGetError")
+ _glGetRenderbufferParameteriv = LibGLESv2.NewProc("glGetRenderbufferParameteriv")
+ _glGetFloatv = LibGLESv2.NewProc("glGetFloatv")
+ _glGetFramebufferAttachmentParameteriv = LibGLESv2.NewProc("glGetFramebufferAttachmentParameteriv")
+ _glGetIntegerv = LibGLESv2.NewProc("glGetIntegerv")
+ _glGetIntegeri_v = LibGLESv2.NewProc("glGetIntegeri_v")
+ _glGetProgramiv = LibGLESv2.NewProc("glGetProgramiv")
+ _glGetProgramInfoLog = LibGLESv2.NewProc("glGetProgramInfoLog")
+ _glGetQueryObjectuiv = LibGLESv2.NewProc("glGetQueryObjectuiv")
+ _glGetShaderiv = LibGLESv2.NewProc("glGetShaderiv")
+ _glGetShaderInfoLog = LibGLESv2.NewProc("glGetShaderInfoLog")
+ _glGetString = LibGLESv2.NewProc("glGetString")
+ _glGetUniformLocation = LibGLESv2.NewProc("glGetUniformLocation")
+ _glGetVertexAttribiv = LibGLESv2.NewProc("glGetVertexAttribiv")
+ _glGetVertexAttribPointerv = LibGLESv2.NewProc("glGetVertexAttribPointerv")
+ _glInvalidateFramebuffer = LibGLESv2.NewProc("glInvalidateFramebuffer")
+ _glIsEnabled = LibGLESv2.NewProc("glIsEnabled")
+ _glLinkProgram = LibGLESv2.NewProc("glLinkProgram")
+ _glPixelStorei = LibGLESv2.NewProc("glPixelStorei")
+ _glReadPixels = LibGLESv2.NewProc("glReadPixels")
+ _glRenderbufferStorage = LibGLESv2.NewProc("glRenderbufferStorage")
+ _glScissor = LibGLESv2.NewProc("glScissor")
+ _glShaderSource = LibGLESv2.NewProc("glShaderSource")
+ _glTexImage2D = LibGLESv2.NewProc("glTexImage2D")
+ _glTexStorage2D = LibGLESv2.NewProc("glTexStorage2D")
+ _glTexSubImage2D = LibGLESv2.NewProc("glTexSubImage2D")
+ _glTexParameteri = LibGLESv2.NewProc("glTexParameteri")
+ _glUniformBlockBinding = LibGLESv2.NewProc("glUniformBlockBinding")
+ _glUniform1f = LibGLESv2.NewProc("glUniform1f")
+ _glUniform1i = LibGLESv2.NewProc("glUniform1i")
+ _glUniform2f = LibGLESv2.NewProc("glUniform2f")
+ _glUniform3f = LibGLESv2.NewProc("glUniform3f")
+ _glUniform4f = LibGLESv2.NewProc("glUniform4f")
+ _glUseProgram = LibGLESv2.NewProc("glUseProgram")
+ _glVertexAttribPointer = LibGLESv2.NewProc("glVertexAttribPointer")
+ _glViewport = LibGLESv2.NewProc("glViewport")
+)
+
+type Functions struct {
+ // Query caches.
+ int32s [100]int32
+ float32s [100]float32
+ uintptrs [100]uintptr
+}
+
+type Context interface{}
+
+func NewFunctions(ctx Context, forceES bool) (*Functions, error) {
+ if ctx != nil {
+ panic("non-nil context")
+ }
+ return new(Functions), nil
+}
+
+func (c *Functions) ActiveTexture(t Enum) {
+ syscall.Syscall(_glActiveTexture.Addr(), 1, uintptr(t), 0, 0)
+}
+func (c *Functions) AttachShader(p Program, s Shader) {
+ syscall.Syscall(_glAttachShader.Addr(), 2, uintptr(p.V), uintptr(s.V), 0)
+}
+func (f *Functions) BeginQuery(target Enum, query Query) {
+ syscall.Syscall(_glBeginQuery.Addr(), 2, uintptr(target), uintptr(query.V), 0)
+}
+func (c *Functions) BindAttribLocation(p Program, a Attrib, name string) {
+ cname := cString(name)
+ c0 := &cname[0]
+ syscall.Syscall(_glBindAttribLocation.Addr(), 3, uintptr(p.V), uintptr(a), uintptr(unsafe.Pointer(c0)))
+ issue34474KeepAlive(c)
+}
+func (c *Functions) BindBuffer(target Enum, b Buffer) {
+ syscall.Syscall(_glBindBuffer.Addr(), 2, uintptr(target), uintptr(b.V), 0)
+}
+func (c *Functions) BindBufferBase(target Enum, index int, b Buffer) {
+ syscall.Syscall(_glBindBufferBase.Addr(), 3, uintptr(target), uintptr(index), uintptr(b.V))
+}
+func (c *Functions) BindFramebuffer(target Enum, fb Framebuffer) {
+ syscall.Syscall(_glBindFramebuffer.Addr(), 2, uintptr(target), uintptr(fb.V), 0)
+}
+func (c *Functions) BindRenderbuffer(target Enum, rb Renderbuffer) {
+ syscall.Syscall(_glBindRenderbuffer.Addr(), 2, uintptr(target), uintptr(rb.V), 0)
+}
+func (f *Functions) BindImageTexture(unit int, t Texture, level int, layered bool, layer int, access, format Enum) {
+ panic("not implemented")
+}
+func (c *Functions) BindTexture(target Enum, t Texture) {
+ syscall.Syscall(_glBindTexture.Addr(), 2, uintptr(target), uintptr(t.V), 0)
+}
+func (c *Functions) BindVertexArray(a VertexArray) {
+ syscall.Syscall(_glBindVertexArray.Addr(), 1, uintptr(a.V), 0, 0)
+}
+func (c *Functions) BlendEquation(mode Enum) {
+ syscall.Syscall(_glBlendEquation.Addr(), 1, uintptr(mode), 0, 0)
+}
+func (c *Functions) BlendFuncSeparate(srcRGB, dstRGB, srcA, dstA Enum) {
+ syscall.Syscall6(_glBlendFuncSeparate.Addr(), 4, uintptr(srcRGB), uintptr(dstRGB), uintptr(srcA), uintptr(dstA), 0, 0)
+}
+func (c *Functions) BufferData(target Enum, size int, usage Enum, data []byte) {
+ var p unsafe.Pointer
+ if len(data) > 0 {
+ p = unsafe.Pointer(&data[0])
+ }
+ syscall.Syscall6(_glBufferData.Addr(), 4, uintptr(target), uintptr(size), uintptr(p), uintptr(usage), 0, 0)
+}
+func (f *Functions) BufferSubData(target Enum, offset int, src []byte) {
+ if n := len(src); n > 0 {
+ s0 := &src[0]
+ syscall.Syscall6(_glBufferSubData.Addr(), 4, uintptr(target), uintptr(offset), uintptr(n), uintptr(unsafe.Pointer(s0)), 0, 0)
+ issue34474KeepAlive(s0)
+ }
+}
+func (c *Functions) CheckFramebufferStatus(target Enum) Enum {
+ s, _, _ := syscall.Syscall(_glCheckFramebufferStatus.Addr(), 1, uintptr(target), 0, 0)
+ return Enum(s)
+}
+func (c *Functions) Clear(mask Enum) {
+ syscall.Syscall(_glClear.Addr(), 1, uintptr(mask), 0, 0)
+}
+func (c *Functions) ClearColor(red, green, blue, alpha float32) {
+ syscall.Syscall6(_glClearColor.Addr(), 4, uintptr(math.Float32bits(red)), uintptr(math.Float32bits(green)), uintptr(math.Float32bits(blue)), uintptr(math.Float32bits(alpha)), 0, 0)
+}
+func (c *Functions) ClearDepthf(d float32) {
+ syscall.Syscall(_glClearDepthf.Addr(), 1, uintptr(math.Float32bits(d)), 0, 0)
+}
+func (c *Functions) CompileShader(s Shader) {
+ syscall.Syscall(_glCompileShader.Addr(), 1, uintptr(s.V), 0, 0)
+}
+func (f *Functions) CopyTexSubImage2D(target Enum, level, xoffset, yoffset, x, y, width, height int) {
+ syscall.Syscall9(_glCopyTexSubImage2D.Addr(), 8, uintptr(target), uintptr(level), uintptr(xoffset), uintptr(yoffset), uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0)
+}
+func (c *Functions) CreateBuffer() Buffer {
+ var buf uintptr
+ syscall.Syscall(_glGenBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&buf)), 0)
+ return Buffer{uint(buf)}
+}
+func (c *Functions) CreateFramebuffer() Framebuffer {
+ var fb uintptr
+ syscall.Syscall(_glGenFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&fb)), 0)
+ return Framebuffer{uint(fb)}
+}
+func (c *Functions) CreateProgram() Program {
+ p, _, _ := syscall.Syscall(_glCreateProgram.Addr(), 0, 0, 0, 0)
+ return Program{uint(p)}
+}
+func (f *Functions) CreateQuery() Query {
+ var q uintptr
+ syscall.Syscall(_glGenQueries.Addr(), 2, 1, uintptr(unsafe.Pointer(&q)), 0)
+ return Query{uint(q)}
+}
+func (c *Functions) CreateRenderbuffer() Renderbuffer {
+ var rb uintptr
+ syscall.Syscall(_glGenRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&rb)), 0)
+ return Renderbuffer{uint(rb)}
+}
+func (c *Functions) CreateShader(ty Enum) Shader {
+ s, _, _ := syscall.Syscall(_glCreateShader.Addr(), 1, uintptr(ty), 0, 0)
+ return Shader{uint(s)}
+}
+func (c *Functions) CreateTexture() Texture {
+ var t uintptr
+ syscall.Syscall(_glGenTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&t)), 0)
+ return Texture{uint(t)}
+}
+func (c *Functions) CreateVertexArray() VertexArray {
+ var t uintptr
+ syscall.Syscall(_glGenVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&t)), 0)
+ return VertexArray{uint(t)}
+}
+func (c *Functions) DeleteBuffer(v Buffer) {
+ syscall.Syscall(_glDeleteBuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v)), 0)
+}
+func (c *Functions) DeleteFramebuffer(v Framebuffer) {
+ syscall.Syscall(_glDeleteFramebuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
+}
+func (c *Functions) DeleteProgram(p Program) {
+ syscall.Syscall(_glDeleteProgram.Addr(), 1, uintptr(p.V), 0, 0)
+}
+func (f *Functions) DeleteQuery(query Query) {
+ syscall.Syscall(_glDeleteQueries.Addr(), 2, 1, uintptr(unsafe.Pointer(&query.V)), 0)
+}
+func (c *Functions) DeleteShader(s Shader) {
+ syscall.Syscall(_glDeleteShader.Addr(), 1, uintptr(s.V), 0, 0)
+}
+func (c *Functions) DeleteRenderbuffer(v Renderbuffer) {
+ syscall.Syscall(_glDeleteRenderbuffers.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
+}
+func (c *Functions) DeleteTexture(v Texture) {
+ syscall.Syscall(_glDeleteTextures.Addr(), 2, 1, uintptr(unsafe.Pointer(&v.V)), 0)
+}
+func (f *Functions) DeleteVertexArray(array VertexArray) {
+ syscall.Syscall(_glDeleteVertexArrays.Addr(), 2, 1, uintptr(unsafe.Pointer(&array.V)), 0)
+}
+func (c *Functions) DepthFunc(f Enum) {
+ syscall.Syscall(_glDepthFunc.Addr(), 1, uintptr(f), 0, 0)
+}
+func (c *Functions) DepthMask(mask bool) {
+ var m uintptr
+ if mask {
+ m = 1
+ }
+ syscall.Syscall(_glDepthMask.Addr(), 1, m, 0, 0)
+}
+func (c *Functions) DisableVertexAttribArray(a Attrib) {
+ syscall.Syscall(_glDisableVertexAttribArray.Addr(), 1, uintptr(a), 0, 0)
+}
+func (c *Functions) Disable(cap Enum) {
+ syscall.Syscall(_glDisable.Addr(), 1, uintptr(cap), 0, 0)
+}
+func (c *Functions) DrawArrays(mode Enum, first, count int) {
+ syscall.Syscall(_glDrawArrays.Addr(), 3, uintptr(mode), uintptr(first), uintptr(count))
+}
+func (c *Functions) DrawElements(mode Enum, count int, ty Enum, offset int) {
+ syscall.Syscall6(_glDrawElements.Addr(), 4, uintptr(mode), uintptr(count), uintptr(ty), uintptr(offset), 0, 0)
+}
+func (f *Functions) DispatchCompute(x, y, z int) {
+ panic("not implemented")
+}
+func (c *Functions) Enable(cap Enum) {
+ syscall.Syscall(_glEnable.Addr(), 1, uintptr(cap), 0, 0)
+}
+func (c *Functions) EnableVertexAttribArray(a Attrib) {
+ syscall.Syscall(_glEnableVertexAttribArray.Addr(), 1, uintptr(a), 0, 0)
+}
+func (f *Functions) EndQuery(target Enum) {
+ syscall.Syscall(_glEndQuery.Addr(), 1, uintptr(target), 0, 0)
+}
+func (c *Functions) Finish() {
+ syscall.Syscall(_glFinish.Addr(), 0, 0, 0, 0)
+}
+func (c *Functions) Flush() {
+ syscall.Syscall(_glFlush.Addr(), 0, 0, 0, 0)
+}
+func (c *Functions) FramebufferRenderbuffer(target, attachment, renderbuffertarget Enum, renderbuffer Renderbuffer) {
+ syscall.Syscall6(_glFramebufferRenderbuffer.Addr(), 4, uintptr(target), uintptr(attachment), uintptr(renderbuffertarget), uintptr(renderbuffer.V), 0, 0)
+}
+func (c *Functions) FramebufferTexture2D(target, attachment, texTarget Enum, t Texture, level int) {
+ syscall.Syscall6(_glFramebufferTexture2D.Addr(), 5, uintptr(target), uintptr(attachment), uintptr(texTarget), uintptr(t.V), uintptr(level), 0)
+}
+func (f *Functions) GetUniformBlockIndex(p Program, name string) uint {
+ cname := cString(name)
+ c0 := &cname[0]
+ u, _, _ := syscall.Syscall(_glGetUniformBlockIndex.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(c0)), 0)
+ issue34474KeepAlive(c0)
+ return uint(u)
+}
+func (c *Functions) GetBinding(pname Enum) Object {
+ return Object{uint(c.GetInteger(pname))}
+}
+func (c *Functions) GetBindingi(pname Enum, idx int) Object {
+ return Object{uint(c.GetIntegeri(pname, idx))}
+}
+func (c *Functions) GetError() Enum {
+ e, _, _ := syscall.Syscall(_glGetError.Addr(), 0, 0, 0, 0)
+ return Enum(e)
+}
+func (c *Functions) GetRenderbufferParameteri(target, pname Enum) int {
+ syscall.Syscall(_glGetRenderbufferParameteriv.Addr(), 3, uintptr(target), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return int(c.int32s[0])
+}
+func (c *Functions) GetFramebufferAttachmentParameteri(target, attachment, pname Enum) int {
+ syscall.Syscall6(_glGetFramebufferAttachmentParameteriv.Addr(), 4, uintptr(target), uintptr(attachment), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])), 0, 0)
+ return int(c.int32s[0])
+}
+func (c *Functions) GetInteger4(pname Enum) [4]int {
+ syscall.Syscall(_glGetIntegerv.Addr(), 2, uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])), 0)
+ var r [4]int
+ for i := range r {
+ r[i] = int(c.int32s[i])
+ }
+ return r
+}
+func (c *Functions) GetInteger(pname Enum) int {
+ syscall.Syscall(_glGetIntegerv.Addr(), 2, uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])), 0)
+ return int(c.int32s[0])
+}
+func (c *Functions) GetIntegeri(pname Enum, idx int) int {
+ syscall.Syscall(_glGetIntegeri_v.Addr(), 3, uintptr(pname), uintptr(idx), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return int(c.int32s[0])
+}
+func (c *Functions) GetFloat(pname Enum) float32 {
+ syscall.Syscall(_glGetFloatv.Addr(), 2, uintptr(pname), uintptr(unsafe.Pointer(&c.float32s[0])), 0)
+ return c.float32s[0]
+}
+func (c *Functions) GetFloat4(pname Enum) [4]float32 {
+ syscall.Syscall(_glGetFloatv.Addr(), 2, uintptr(pname), uintptr(unsafe.Pointer(&c.float32s[0])), 0)
+ var r [4]float32
+ copy(r[:], c.float32s[:])
+ return r
+}
+func (c *Functions) GetProgrami(p Program, pname Enum) int {
+ syscall.Syscall(_glGetProgramiv.Addr(), 3, uintptr(p.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return int(c.int32s[0])
+}
+func (c *Functions) GetProgramInfoLog(p Program) string {
+ n := c.GetProgrami(p, INFO_LOG_LENGTH)
+ buf := make([]byte, n)
+ syscall.Syscall6(_glGetProgramInfoLog.Addr(), 4, uintptr(p.V), uintptr(len(buf)), 0, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
+ return string(buf)
+}
+func (c *Functions) GetQueryObjectuiv(query Query, pname Enum) uint {
+ syscall.Syscall(_glGetQueryObjectuiv.Addr(), 3, uintptr(query.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return uint(c.int32s[0])
+}
+func (c *Functions) GetShaderi(s Shader, pname Enum) int {
+ syscall.Syscall(_glGetShaderiv.Addr(), 3, uintptr(s.V), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return int(c.int32s[0])
+}
+func (c *Functions) GetShaderInfoLog(s Shader) string {
+ n := c.GetShaderi(s, INFO_LOG_LENGTH)
+ buf := make([]byte, n)
+ syscall.Syscall6(_glGetShaderInfoLog.Addr(), 4, uintptr(s.V), uintptr(len(buf)), 0, uintptr(unsafe.Pointer(&buf[0])), 0, 0)
+ return string(buf)
+}
+func (c *Functions) GetString(pname Enum) string {
+ s, _, _ := syscall.Syscall(_glGetString.Addr(), 1, uintptr(pname), 0, 0)
+ return windows.BytePtrToString((*byte)(unsafe.Pointer(s)))
+}
+func (c *Functions) GetUniformLocation(p Program, name string) Uniform {
+ cname := cString(name)
+ c0 := &cname[0]
+ u, _, _ := syscall.Syscall(_glGetUniformLocation.Addr(), 2, uintptr(p.V), uintptr(unsafe.Pointer(c0)), 0)
+ issue34474KeepAlive(c0)
+ return Uniform{int(u)}
+}
+func (c *Functions) GetVertexAttrib(index int, pname Enum) int {
+ syscall.Syscall(_glGetVertexAttribiv.Addr(), 3, uintptr(index), uintptr(pname), uintptr(unsafe.Pointer(&c.int32s[0])))
+ return int(c.int32s[0])
+}
+
+func (c *Functions) GetVertexAttribBinding(index int, pname Enum) Object {
+ return Object{uint(c.GetVertexAttrib(index, pname))}
+}
+
+func (c *Functions) GetVertexAttribPointer(index int, pname Enum) uintptr {
+ syscall.Syscall(_glGetVertexAttribPointerv.Addr(), 3, uintptr(index), uintptr(pname), uintptr(unsafe.Pointer(&c.uintptrs[0])))
+ return c.uintptrs[0]
+}
+func (c *Functions) InvalidateFramebuffer(target, attachment Enum) {
+ addr := _glInvalidateFramebuffer.Addr()
+ if addr == 0 {
+ // InvalidateFramebuffer is just a hint. Skip it if not supported.
+ return
+ }
+ syscall.Syscall(addr, 3, uintptr(target), 1, uintptr(unsafe.Pointer(&attachment)))
+}
+func (f *Functions) IsEnabled(cap Enum) bool {
+ u, _, _ := syscall.Syscall(_glIsEnabled.Addr(), 1, uintptr(cap), 0, 0)
+ return u == TRUE
+}
+func (c *Functions) LinkProgram(p Program) {
+ syscall.Syscall(_glLinkProgram.Addr(), 1, uintptr(p.V), 0, 0)
+}
+func (c *Functions) PixelStorei(pname Enum, param int) {
+ syscall.Syscall(_glPixelStorei.Addr(), 2, uintptr(pname), uintptr(param), 0)
+}
+func (f *Functions) MemoryBarrier(barriers Enum) {
+ panic("not implemented")
+}
+func (f *Functions) MapBufferRange(target Enum, offset, length int, access Enum) []byte {
+ panic("not implemented")
+}
+func (f *Functions) ReadPixels(x, y, width, height int, format, ty Enum, data []byte) {
+ d0 := &data[0]
+ syscall.Syscall9(_glReadPixels.Addr(), 7, uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)), 0, 0)
+ issue34474KeepAlive(d0)
+}
+func (c *Functions) RenderbufferStorage(target, internalformat Enum, width, height int) {
+ syscall.Syscall6(_glRenderbufferStorage.Addr(), 4, uintptr(target), uintptr(internalformat), uintptr(width), uintptr(height), 0, 0)
+}
+func (c *Functions) Scissor(x, y, width, height int32) {
+ syscall.Syscall6(_glScissor.Addr(), 4, uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0, 0)
+}
+func (c *Functions) ShaderSource(s Shader, src string) {
+ var n uintptr = uintptr(len(src))
+ psrc := &src
+ syscall.Syscall6(_glShaderSource.Addr(), 4, uintptr(s.V), 1, uintptr(unsafe.Pointer(psrc)), uintptr(unsafe.Pointer(&n)), 0, 0)
+ issue34474KeepAlive(psrc)
+}
+func (f *Functions) TexImage2D(target Enum, level int, internalFormat Enum, width int, height int, format Enum, ty Enum) {
+ syscall.Syscall9(_glTexImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(internalFormat), uintptr(width), uintptr(height), 0, uintptr(format), uintptr(ty), 0)
+}
+func (f *Functions) TexStorage2D(target Enum, levels int, internalFormat Enum, width, height int) {
+ syscall.Syscall6(_glTexStorage2D.Addr(), 5, uintptr(target), uintptr(levels), uintptr(internalFormat), uintptr(width), uintptr(height), 0)
+}
+func (c *Functions) TexSubImage2D(target Enum, level int, x, y, width, height int, format, ty Enum, data []byte) {
+ d0 := &data[0]
+ syscall.Syscall9(_glTexSubImage2D.Addr(), 9, uintptr(target), uintptr(level), uintptr(x), uintptr(y), uintptr(width), uintptr(height), uintptr(format), uintptr(ty), uintptr(unsafe.Pointer(d0)))
+ issue34474KeepAlive(d0)
+}
+func (c *Functions) TexParameteri(target, pname Enum, param int) {
+ syscall.Syscall(_glTexParameteri.Addr(), 3, uintptr(target), uintptr(pname), uintptr(param))
+}
+func (f *Functions) UniformBlockBinding(p Program, uniformBlockIndex uint, uniformBlockBinding uint) {
+ syscall.Syscall(_glUniformBlockBinding.Addr(), 3, uintptr(p.V), uintptr(uniformBlockIndex), uintptr(uniformBlockBinding))
+}
+func (c *Functions) Uniform1f(dst Uniform, v float32) {
+ syscall.Syscall(_glUniform1f.Addr(), 2, uintptr(dst.V), uintptr(math.Float32bits(v)), 0)
+}
+func (c *Functions) Uniform1i(dst Uniform, v int) {
+ syscall.Syscall(_glUniform1i.Addr(), 2, uintptr(dst.V), uintptr(v), 0)
+}
+func (c *Functions) Uniform2f(dst Uniform, v0, v1 float32) {
+ syscall.Syscall(_glUniform2f.Addr(), 3, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)))
+}
+func (c *Functions) Uniform3f(dst Uniform, v0, v1, v2 float32) {
+ syscall.Syscall6(_glUniform3f.Addr(), 4, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)), uintptr(math.Float32bits(v2)), 0, 0)
+}
+func (c *Functions) Uniform4f(dst Uniform, v0, v1, v2, v3 float32) {
+ syscall.Syscall6(_glUniform4f.Addr(), 5, uintptr(dst.V), uintptr(math.Float32bits(v0)), uintptr(math.Float32bits(v1)), uintptr(math.Float32bits(v2)), uintptr(math.Float32bits(v3)), 0)
+}
+func (c *Functions) UseProgram(p Program) {
+ syscall.Syscall(_glUseProgram.Addr(), 1, uintptr(p.V), 0, 0)
+}
+func (f *Functions) UnmapBuffer(target Enum) bool {
+ panic("not implemented")
+}
+func (c *Functions) VertexAttribPointer(dst Attrib, size int, ty Enum, normalized bool, stride, offset int) {
+ var norm uintptr
+ if normalized {
+ norm = 1
+ }
+ syscall.Syscall6(_glVertexAttribPointer.Addr(), 6, uintptr(dst), uintptr(size), uintptr(ty), norm, uintptr(stride), uintptr(offset))
+}
+func (c *Functions) Viewport(x, y, width, height int) {
+ syscall.Syscall6(_glViewport.Addr(), 4, uintptr(x), uintptr(y), uintptr(width), uintptr(height), 0, 0)
+}
+
+func cString(s string) []byte {
+ b := make([]byte, len(s)+1)
+ copy(b, s)
+ return b
+}
+
+// issue34474KeepAlive calls runtime.KeepAlive as a
+// workaround for golang.org/issue/34474.
+func issue34474KeepAlive(v interface{}) {
+ runtime.KeepAlive(v)
+}
diff --git a/vendor/gioui.org/internal/gl/types.go b/vendor/gioui.org/internal/gl/types.go
new file mode 100644
index 0000000..dd24963
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/types.go
@@ -0,0 +1,77 @@
+//go:build !js
+// +build !js
+
+package gl
+
+type (
+ Object struct{ V uint }
+ Buffer Object
+ Framebuffer Object
+ Program Object
+ Renderbuffer Object
+ Shader Object
+ Texture Object
+ Query Object
+ Uniform struct{ V int }
+ VertexArray Object
+)
+
+func (o Object) valid() bool {
+ return o.V != 0
+}
+
+func (o Object) equal(o2 Object) bool {
+ return o == o2
+}
+
+func (u Framebuffer) Valid() bool {
+ return Object(u).valid()
+}
+
+func (u Uniform) Valid() bool {
+ return u.V != -1
+}
+
+func (p Program) Valid() bool {
+ return Object(p).valid()
+}
+
+func (s Shader) Valid() bool {
+ return Object(s).valid()
+}
+
+func (a VertexArray) Valid() bool {
+ return Object(a).valid()
+}
+
+func (f Framebuffer) Equal(f2 Framebuffer) bool {
+ return Object(f).equal(Object(f2))
+}
+
+func (p Program) Equal(p2 Program) bool {
+ return Object(p).equal(Object(p2))
+}
+
+func (s Shader) Equal(s2 Shader) bool {
+ return Object(s).equal(Object(s2))
+}
+
+func (u Uniform) Equal(u2 Uniform) bool {
+ return u == u2
+}
+
+func (a VertexArray) Equal(a2 VertexArray) bool {
+ return Object(a).equal(Object(a2))
+}
+
+func (r Renderbuffer) Equal(r2 Renderbuffer) bool {
+ return Object(r).equal(Object(r2))
+}
+
+func (t Texture) Equal(t2 Texture) bool {
+ return Object(t).equal(Object(t2))
+}
+
+func (b Buffer) Equal(b2 Buffer) bool {
+ return Object(b).equal(Object(b2))
+}
diff --git a/vendor/gioui.org/internal/gl/types_js.go b/vendor/gioui.org/internal/gl/types_js.go
new file mode 100644
index 0000000..8d91a6b
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/types_js.go
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package gl
+
+import "syscall/js"
+
+type (
+ Object js.Value
+ Buffer Object
+ Framebuffer Object
+ Program Object
+ Renderbuffer Object
+ Shader Object
+ Texture Object
+ Query Object
+ Uniform Object
+ VertexArray Object
+)
+
+func (o Object) valid() bool {
+ return js.Value(o).Truthy()
+}
+
+func (o Object) equal(o2 Object) bool {
+ return js.Value(o).Equal(js.Value(o2))
+}
+
+func (b Buffer) Valid() bool {
+ return Object(b).valid()
+}
+
+func (f Framebuffer) Valid() bool {
+ return Object(f).valid()
+}
+
+func (p Program) Valid() bool {
+ return Object(p).valid()
+}
+
+func (r Renderbuffer) Valid() bool {
+ return Object(r).valid()
+}
+
+func (s Shader) Valid() bool {
+ return Object(s).valid()
+}
+
+func (t Texture) Valid() bool {
+ return Object(t).valid()
+}
+
+func (u Uniform) Valid() bool {
+ return Object(u).valid()
+}
+
+func (a VertexArray) Valid() bool {
+ return Object(a).valid()
+}
+
+func (f Framebuffer) Equal(f2 Framebuffer) bool {
+ return Object(f).equal(Object(f2))
+}
+
+func (p Program) Equal(p2 Program) bool {
+ return Object(p).equal(Object(p2))
+}
+
+func (s Shader) Equal(s2 Shader) bool {
+ return Object(s).equal(Object(s2))
+}
+
+func (u Uniform) Equal(u2 Uniform) bool {
+ return Object(u).equal(Object(u2))
+}
+
+func (a VertexArray) Equal(a2 VertexArray) bool {
+ return Object(a).equal(Object(a2))
+}
+
+func (r Renderbuffer) Equal(r2 Renderbuffer) bool {
+ return Object(r).equal(Object(r2))
+}
+
+func (t Texture) Equal(t2 Texture) bool {
+ return Object(t).equal(Object(t2))
+}
+
+func (b Buffer) Equal(b2 Buffer) bool {
+ return Object(b).equal(Object(b2))
+}
diff --git a/vendor/gioui.org/internal/gl/util.go b/vendor/gioui.org/internal/gl/util.go
new file mode 100644
index 0000000..c696b69
--- /dev/null
+++ b/vendor/gioui.org/internal/gl/util.go
@@ -0,0 +1,87 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+package gl
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+)
+
+func CreateProgram(ctx *Functions, vsSrc, fsSrc string, attribs []string) (Program, error) {
+ vs, err := CreateShader(ctx, VERTEX_SHADER, vsSrc)
+ if err != nil {
+ return Program{}, err
+ }
+ defer ctx.DeleteShader(vs)
+ fs, err := CreateShader(ctx, FRAGMENT_SHADER, fsSrc)
+ if err != nil {
+ return Program{}, err
+ }
+ defer ctx.DeleteShader(fs)
+ prog := ctx.CreateProgram()
+ if !prog.Valid() {
+ return Program{}, errors.New("glCreateProgram failed")
+ }
+ ctx.AttachShader(prog, vs)
+ ctx.AttachShader(prog, fs)
+ for i, a := range attribs {
+ ctx.BindAttribLocation(prog, Attrib(i), a)
+ }
+ ctx.LinkProgram(prog)
+ if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
+ log := ctx.GetProgramInfoLog(prog)
+ ctx.DeleteProgram(prog)
+ return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
+ }
+ return prog, nil
+}
+
+func CreateComputeProgram(ctx *Functions, src string) (Program, error) {
+ cs, err := CreateShader(ctx, COMPUTE_SHADER, src)
+ if err != nil {
+ return Program{}, err
+ }
+ defer ctx.DeleteShader(cs)
+ prog := ctx.CreateProgram()
+ if !prog.Valid() {
+ return Program{}, errors.New("glCreateProgram failed")
+ }
+ ctx.AttachShader(prog, cs)
+ ctx.LinkProgram(prog)
+ if ctx.GetProgrami(prog, LINK_STATUS) == 0 {
+ log := ctx.GetProgramInfoLog(prog)
+ ctx.DeleteProgram(prog)
+ return Program{}, fmt.Errorf("program link failed: %s", strings.TrimSpace(log))
+ }
+ return prog, nil
+}
+
+func CreateShader(ctx *Functions, typ Enum, src string) (Shader, error) {
+ sh := ctx.CreateShader(typ)
+ if !sh.Valid() {
+ return Shader{}, errors.New("glCreateShader failed")
+ }
+ ctx.ShaderSource(sh, src)
+ ctx.CompileShader(sh)
+ if ctx.GetShaderi(sh, COMPILE_STATUS) == 0 {
+ log := ctx.GetShaderInfoLog(sh)
+ ctx.DeleteShader(sh)
+ return Shader{}, fmt.Errorf("shader compilation failed: %s", strings.TrimSpace(log))
+ }
+ return sh, nil
+}
+
+func ParseGLVersion(glVer string) (version [2]int, gles bool, err error) {
+ var ver [2]int
+ if _, err := fmt.Sscanf(glVer, "OpenGL ES %d.%d", &ver[0], &ver[1]); err == nil {
+ return ver, true, nil
+ } else if _, err := fmt.Sscanf(glVer, "WebGL %d.%d", &ver[0], &ver[1]); err == nil {
+ // WebGL major version v corresponds to OpenGL ES version v + 1
+ ver[0]++
+ return ver, true, nil
+ } else if _, err := fmt.Sscanf(glVer, "%d.%d", &ver[0], &ver[1]); err == nil {
+ return ver, false, nil
+ }
+ return ver, false, fmt.Errorf("failed to parse OpenGL ES version (%s)", glVer)
+}
diff --git a/vendor/gioui.org/internal/opconst/ops.go b/vendor/gioui.org/internal/opconst/ops.go
deleted file mode 100644
index 62365b8..0000000
--- a/vendor/gioui.org/internal/opconst/ops.go
+++ /dev/null
@@ -1,84 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package opconst
-
-type OpType byte
-
-// Start at a high number for easier debugging.
-const firstOpIndex = 200
-
-const (
- TypeMacro OpType = iota + firstOpIndex
- TypeCall
- TypeTransform
- TypeLayer
- TypeInvalidate
- TypeImage
- TypePaint
- TypeColor
- TypeArea
- TypePointerInput
- TypePass
- TypeKeyInput
- TypeHideInput
- TypePush
- TypePop
- TypeAux
- TypeClip
- TypeProfile
-)
-
-const (
- TypeMacroLen = 1 + 4 + 4
- TypeCallLen = 1 + 4 + 4
- TypeTransformLen = 1 + 4*6
- TypeLayerLen = 1
- TypeRedrawLen = 1 + 8
- TypeImageLen = 1 + 4*4
- TypePaintLen = 1 + 4*4
- TypeColorLen = 1 + 4
- TypeAreaLen = 1 + 1 + 4*4
- TypePointerInputLen = 1 + 1 + 1
- TypePassLen = 1 + 1
- TypeKeyInputLen = 1 + 1
- TypeHideInputLen = 1
- TypePushLen = 1
- TypePopLen = 1
- TypeAuxLen = 1
- TypeClipLen = 1 + 4*4
- TypeProfileLen = 1
-)
-
-func (t OpType) Size() int {
- return [...]int{
- TypeMacroLen,
- TypeCallLen,
- TypeTransformLen,
- TypeLayerLen,
- TypeRedrawLen,
- TypeImageLen,
- TypePaintLen,
- TypeColorLen,
- TypeAreaLen,
- TypePointerInputLen,
- TypePassLen,
- TypeKeyInputLen,
- TypeHideInputLen,
- TypePushLen,
- TypePopLen,
- TypeAuxLen,
- TypeClipLen,
- TypeProfileLen,
- }[t-firstOpIndex]
-}
-
-func (t OpType) NumRefs() int {
- switch t {
- case TypeKeyInput, TypePointerInput, TypeProfile, TypeCall:
- return 1
- case TypeImage:
- return 2
- default:
- return 0
- }
-}
diff --git a/vendor/gioui.org/internal/ops/ops.go b/vendor/gioui.org/internal/ops/ops.go
index c56b9d6..fece6d6 100644
--- a/vendor/gioui.org/internal/ops/ops.go
+++ b/vendor/gioui.org/internal/ops/ops.go
@@ -4,57 +4,321 @@ package ops
import (
"encoding/binary"
+ "image"
"math"
"gioui.org/f32"
- "gioui.org/internal/opconst"
+ "gioui.org/internal/byteslice"
+ "gioui.org/internal/scene"
)
-const QuadSize = 4 * 2 * 3
+type Ops struct {
+ // version is incremented at each Reset.
+ version int
+ // data contains the serialized operations.
+ data []byte
+ // refs hold external references for operations.
+ refs []interface{}
+ // nextStateID is the id allocated for the next
+ // StateOp.
+ nextStateID int
-type Quad struct {
- From, Ctrl, To f32.Point
+ macroStack stack
+ stacks [5]stack
}
-func (q Quad) Transform(t f32.Affine2D) Quad {
- q.From = t.Transform(q.From)
- q.Ctrl = t.Transform(q.Ctrl)
- q.To = t.Transform(q.To)
- return q
+type OpType byte
+
+type Shape byte
+
+// Start at a high number for easier debugging.
+const firstOpIndex = 200
+
+const (
+ TypeMacro OpType = iota + firstOpIndex
+ TypeCall
+ TypeDefer
+ TypePushTransform
+ TypeTransform
+ TypePopTransform
+ TypeInvalidate
+ TypeImage
+ TypePaint
+ TypeColor
+ TypeLinearGradient
+ TypePass
+ TypePopPass
+ TypePointerInput
+ TypeClipboardRead
+ TypeClipboardWrite
+ TypeSource
+ TypeTarget
+ TypeOffer
+ TypeKeyInput
+ TypeKeyFocus
+ TypeKeySoftKeyboard
+ TypeSave
+ TypeLoad
+ TypeAux
+ TypeClip
+ TypePopClip
+ TypeProfile
+ TypeCursor
+ TypePath
+ TypeStroke
+ TypeSemanticLabel
+ TypeSemanticDesc
+ TypeSemanticClass
+ TypeSemanticSelected
+ TypeSemanticDisabled
+)
+
+type StackID struct {
+ id int
+ prev int
+}
+
+// StateOp represents a saved operation snapshop to be restored
+// later.
+type StateOp struct {
+ id int
+ macroID int
+ ops *Ops
+}
+
+// stack tracks the integer identities of stack operations to ensure correct
+// pairing of their push and pop methods.
+type stack struct {
+ currentID int
+ nextID int
+}
+
+type StackKind uint8
+
+// ClipOp is the shadow of clip.Op.
+type ClipOp struct {
+ Bounds image.Rectangle
+ Outline bool
+ Shape Shape
}
-func EncodeQuad(d []byte, q Quad) {
+const (
+ ClipStack StackKind = iota
+ TransStack
+ PassStack
+ MetaStack
+)
+
+const (
+ Path Shape = iota
+ Ellipse
+ Rect
+)
+
+const (
+ TypeMacroLen = 1 + 4 + 4
+ TypeCallLen = 1 + 4 + 4
+ TypeDeferLen = 1
+ TypePushTransformLen = 1 + 4*6
+ TypeTransformLen = 1 + 1 + 4*6
+ TypePopTransformLen = 1
+ TypeRedrawLen = 1 + 8
+ TypeImageLen = 1
+ TypePaintLen = 1
+ TypeColorLen = 1 + 4
+ TypeLinearGradientLen = 1 + 8*2 + 4*2
+ TypePassLen = 1
+ TypePopPassLen = 1
+ TypePointerInputLen = 1 + 1 + 1*2 + 2*4 + 2*4
+ TypeClipboardReadLen = 1
+ TypeClipboardWriteLen = 1
+ TypeSourceLen = 1
+ TypeTargetLen = 1
+ TypeOfferLen = 1
+ TypeKeyInputLen = 1 + 1
+ TypeKeyFocusLen = 1 + 1
+ TypeKeySoftKeyboardLen = 1 + 1
+ TypeSaveLen = 1 + 4
+ TypeLoadLen = 1 + 4
+ TypeAuxLen = 1
+ TypeClipLen = 1 + 4*4 + 1 + 1
+ TypePopClipLen = 1
+ TypeProfileLen = 1
+ TypeCursorLen = 1 + 1
+ TypePathLen = 8 + 1
+ TypeStrokeLen = 1 + 4
+ TypeSemanticLabelLen = 1
+ TypeSemanticDescLen = 1
+ TypeSemanticClassLen = 2
+ TypeSemanticSelectedLen = 2
+ TypeSemanticDisabledLen = 2
+)
+
+func (op *ClipOp) Decode(data []byte) {
+ if OpType(data[0]) != TypeClip {
+ panic("invalid op")
+ }
bo := binary.LittleEndian
- bo.PutUint32(d[0:], math.Float32bits(q.From.X))
- bo.PutUint32(d[4:], math.Float32bits(q.From.Y))
- bo.PutUint32(d[8:], math.Float32bits(q.Ctrl.X))
- bo.PutUint32(d[12:], math.Float32bits(q.Ctrl.Y))
- bo.PutUint32(d[16:], math.Float32bits(q.To.X))
- bo.PutUint32(d[20:], math.Float32bits(q.To.Y))
+ r := image.Rectangle{
+ Min: image.Point{
+ X: int(int32(bo.Uint32(data[1:]))),
+ Y: int(int32(bo.Uint32(data[5:]))),
+ },
+ Max: image.Point{
+ X: int(int32(bo.Uint32(data[9:]))),
+ Y: int(int32(bo.Uint32(data[13:]))),
+ },
+ }
+ *op = ClipOp{
+ Bounds: r,
+ Outline: data[17] == 1,
+ Shape: Shape(data[18]),
+ }
}
-func DecodeQuad(d []byte) (q Quad) {
+func Reset(o *Ops) {
+ o.macroStack = stack{}
+ for i := range o.stacks {
+ o.stacks[i] = stack{}
+ }
+ // Leave references to the GC.
+ for i := range o.refs {
+ o.refs[i] = nil
+ }
+ o.data = o.data[:0]
+ o.refs = o.refs[:0]
+ o.nextStateID = 0
+ o.version++
+}
+
+func Write(o *Ops, n int) []byte {
+ o.data = append(o.data, make([]byte, n)...)
+ return o.data[len(o.data)-n:]
+}
+
+func PushMacro(o *Ops) StackID {
+ return o.macroStack.push()
+}
+
+func PopMacro(o *Ops, id StackID) {
+ o.macroStack.pop(id)
+}
+
+func FillMacro(o *Ops, startPC PC) {
+ pc := PCFor(o)
+ // Fill out the macro definition reserved in Record.
+ data := o.data[startPC.data:]
+ data = data[:TypeMacroLen]
+ data[0] = byte(TypeMacro)
bo := binary.LittleEndian
- q.From.X = math.Float32frombits(bo.Uint32(d[0:]))
- q.From.Y = math.Float32frombits(bo.Uint32(d[4:]))
- q.Ctrl.X = math.Float32frombits(bo.Uint32(d[8:]))
- q.Ctrl.Y = math.Float32frombits(bo.Uint32(d[12:]))
- q.To.X = math.Float32frombits(bo.Uint32(d[16:]))
- q.To.Y = math.Float32frombits(bo.Uint32(d[20:]))
- return
+ bo.PutUint32(data[1:], uint32(pc.data))
+ bo.PutUint32(data[5:], uint32(pc.refs))
}
-func DecodeTransform(d []byte) (t f32.Affine2D) {
- if opconst.OpType(d[0]) != opconst.TypeTransform {
- panic("invalid op")
+func AddCall(o *Ops, callOps *Ops, pc PC) {
+ data := Write1(o, TypeCallLen, callOps)
+ data[0] = byte(TypeCall)
+ bo := binary.LittleEndian
+ bo.PutUint32(data[1:], uint32(pc.data))
+ bo.PutUint32(data[5:], uint32(pc.refs))
+}
+
+func PushOp(o *Ops, kind StackKind) (StackID, int) {
+ return o.stacks[kind].push(), o.macroStack.currentID
+}
+
+func PopOp(o *Ops, kind StackKind, sid StackID, macroID int) {
+ if o.macroStack.currentID != macroID {
+ panic("stack push and pop must not cross macro boundary")
}
- if len(d) < 1+6*4 {
- panic("too short buffer")
+ o.stacks[kind].pop(sid)
+}
+
+func Write1(o *Ops, n int, ref1 interface{}) []byte {
+ o.data = append(o.data, make([]byte, n)...)
+ o.refs = append(o.refs, ref1)
+ return o.data[len(o.data)-n:]
+}
+
+func Write2(o *Ops, n int, ref1, ref2 interface{}) []byte {
+ o.data = append(o.data, make([]byte, n)...)
+ o.refs = append(o.refs, ref1, ref2)
+ return o.data[len(o.data)-n:]
+}
+
+func Write3(o *Ops, n int, ref1, ref2, ref3 interface{}) []byte {
+ o.data = append(o.data, make([]byte, n)...)
+ o.refs = append(o.refs, ref1, ref2, ref3)
+ return o.data[len(o.data)-n:]
+}
+
+func PCFor(o *Ops) PC {
+ return PC{data: len(o.data), refs: len(o.refs)}
+}
+
+func (s *stack) push() StackID {
+ s.nextID++
+ sid := StackID{
+ id: s.nextID,
+ prev: s.currentID,
}
- return decodeAffine2D(d[1:])
+ s.currentID = s.nextID
+ return sid
+}
+
+func (s *stack) check(sid StackID) {
+ if s.currentID != sid.id {
+ panic("unbalanced operation")
+ }
+}
+
+func (s *stack) pop(sid StackID) {
+ s.check(sid)
+ s.currentID = sid.prev
+}
+
+// Save the effective transformation.
+func Save(o *Ops) StateOp {
+ o.nextStateID++
+ s := StateOp{
+ ops: o,
+ id: o.nextStateID,
+ macroID: o.macroStack.currentID,
+ }
+ bo := binary.LittleEndian
+ data := Write(o, TypeSaveLen)
+ data[0] = byte(TypeSave)
+ bo.PutUint32(data[1:], uint32(s.id))
+ return s
+}
+
+// Load a previously saved operations state given
+// its ID.
+func (s StateOp) Load() {
+ bo := binary.LittleEndian
+ data := Write(s.ops, TypeLoadLen)
+ data[0] = byte(TypeLoad)
+ bo.PutUint32(data[1:], uint32(s.id))
+}
+
+func DecodeCommand(d []byte) scene.Command {
+ var cmd scene.Command
+ copy(byteslice.Uint32(cmd[:]), d)
+ return cmd
+}
+
+func EncodeCommand(out []byte, cmd scene.Command) {
+ copy(out, byteslice.Uint32(cmd[:]))
}
-func decodeAffine2D(data []byte) f32.Affine2D {
+func DecodeTransform(data []byte) (t f32.Affine2D, push bool) {
+ if OpType(data[0]) != TypeTransform {
+ panic("invalid op")
+ }
+ push = data[1] != 0
+ data = data[2:]
+ data = data[:4*6]
+
bo := binary.LittleEndian
a := math.Float32frombits(bo.Uint32(data))
b := math.Float32frombits(bo.Uint32(data[4*1:]))
@@ -62,5 +326,148 @@ func decodeAffine2D(data []byte) f32.Affine2D {
d := math.Float32frombits(bo.Uint32(data[4*3:]))
e := math.Float32frombits(bo.Uint32(data[4*4:]))
f := math.Float32frombits(bo.Uint32(data[4*5:]))
- return f32.NewAffine2D(a, b, c, d, e, f)
+ return f32.NewAffine2D(a, b, c, d, e, f), push
+}
+
+// DecodeSave decodes the state id of a save op.
+func DecodeSave(data []byte) int {
+ if OpType(data[0]) != TypeSave {
+ panic("invalid op")
+ }
+ bo := binary.LittleEndian
+ return int(bo.Uint32(data[1:]))
+}
+
+// DecodeLoad decodes the state id of a load op.
+func DecodeLoad(data []byte) int {
+ if OpType(data[0]) != TypeLoad {
+ panic("invalid op")
+ }
+ bo := binary.LittleEndian
+ return int(bo.Uint32(data[1:]))
+}
+
+func (t OpType) Size() int {
+ return [...]int{
+ TypeMacroLen,
+ TypeCallLen,
+ TypeDeferLen,
+ TypePushTransformLen,
+ TypeTransformLen,
+ TypePopTransformLen,
+ TypeRedrawLen,
+ TypeImageLen,
+ TypePaintLen,
+ TypeColorLen,
+ TypeLinearGradientLen,
+ TypePassLen,
+ TypePopPassLen,
+ TypePointerInputLen,
+ TypeClipboardReadLen,
+ TypeClipboardWriteLen,
+ TypeSourceLen,
+ TypeTargetLen,
+ TypeOfferLen,
+ TypeKeyInputLen,
+ TypeKeyFocusLen,
+ TypeKeySoftKeyboardLen,
+ TypeSaveLen,
+ TypeLoadLen,
+ TypeAuxLen,
+ TypeClipLen,
+ TypePopClipLen,
+ TypeProfileLen,
+ TypeCursorLen,
+ TypePathLen,
+ TypeStrokeLen,
+ TypeSemanticLabelLen,
+ TypeSemanticDescLen,
+ TypeSemanticClassLen,
+ TypeSemanticSelectedLen,
+ TypeSemanticDisabledLen,
+ }[t-firstOpIndex]
+}
+
+func (t OpType) NumRefs() int {
+ switch t {
+ case TypeKeyInput, TypeKeyFocus, TypePointerInput, TypeProfile, TypeCall, TypeClipboardRead, TypeClipboardWrite, TypeCursor, TypeSemanticLabel, TypeSemanticDesc:
+ return 1
+ case TypeImage, TypeSource, TypeTarget:
+ return 2
+ case TypeOffer:
+ return 3
+ default:
+ return 0
+ }
+}
+
+func (t OpType) String() string {
+ switch t {
+ case TypeMacro:
+ return "Macro"
+ case TypeCall:
+ return "Call"
+ case TypeDefer:
+ return "Defer"
+ case TypePushTransform:
+ return "PushTransform"
+ case TypeTransform:
+ return "Transform"
+ case TypePopTransform:
+ return "PopTransform"
+ case TypeInvalidate:
+ return "Invalidate"
+ case TypeImage:
+ return "Image"
+ case TypePaint:
+ return "Paint"
+ case TypeColor:
+ return "Color"
+ case TypeLinearGradient:
+ return "LinearGradient"
+ case TypePass:
+ return "Pass"
+ case TypePopPass:
+ return "PopPass"
+ case TypePointerInput:
+ return "PointerInput"
+ case TypeClipboardRead:
+ return "ClipboardRead"
+ case TypeClipboardWrite:
+ return "ClipboardWrite"
+ case TypeSource:
+ return "Source"
+ case TypeTarget:
+ return "Target"
+ case TypeOffer:
+ return "Offer"
+ case TypeKeyInput:
+ return "KeyInput"
+ case TypeKeyFocus:
+ return "KeyFocus"
+ case TypeKeySoftKeyboard:
+ return "KeySoftKeyboard"
+ case TypeSave:
+ return "Save"
+ case TypeLoad:
+ return "Load"
+ case TypeAux:
+ return "Aux"
+ case TypeClip:
+ return "Clip"
+ case TypePopClip:
+ return "PopClip"
+ case TypeProfile:
+ return "Profile"
+ case TypeCursor:
+ return "Cursor"
+ case TypePath:
+ return "Path"
+ case TypeStroke:
+ return "Stroke"
+ case TypeSemanticLabel:
+ return "SemanticDescription"
+ default:
+ panic("unknown OpType")
+ }
}
diff --git a/vendor/gioui.org/internal/ops/reader.go b/vendor/gioui.org/internal/ops/reader.go
index 5d713db..99b8cb6 100644
--- a/vendor/gioui.org/internal/ops/reader.go
+++ b/vendor/gioui.org/internal/ops/reader.go
@@ -4,17 +4,15 @@ package ops
import (
"encoding/binary"
-
- "gioui.org/f32"
- "gioui.org/internal/opconst"
- "gioui.org/op"
)
// Reader parses an ops list.
type Reader struct {
- pc pc
- stack []macro
- ops *op.Ops
+ pc PC
+ stack []macro
+ ops *Ops
+ deferOps Ops
+ deferDone bool
}
// EncodedOp represents an encoded op returned by
@@ -27,53 +25,52 @@ type EncodedOp struct {
// Key is a unique key for a given op.
type Key struct {
- ops *op.Ops
- pc int
- version int
- sx, hx, sy, hy float32
+ ops *Ops
+ pc int
+ version int
}
// Shadow of op.MacroOp.
type macroOp struct {
- ops *op.Ops
- pc pc
+ ops *Ops
+ pc PC
}
-type pc struct {
+// PC is an instruction counter for an operation list.
+type PC struct {
data int
refs int
}
type macro struct {
- ops *op.Ops
- retPC pc
- endPC pc
+ ops *Ops
+ retPC PC
+ endPC PC
}
type opMacroDef struct {
- endpc pc
+ endpc PC
}
-// Reset start reading from the op list.
-func (r *Reader) Reset(ops *op.Ops) {
- r.stack = r.stack[:0]
- r.pc = pc{}
- r.ops = ops
+// Reset start reading from the beginning of ops.
+func (r *Reader) Reset(ops *Ops) {
+ r.ResetAt(ops, PC{})
}
-func (k Key) SetTransform(t f32.Affine2D) Key {
- sx, hx, _, hy, sy, _ := t.Elems()
- k.sx = sx
- k.hx = hx
- k.hy = hy
- k.sy = sy
- return k
+// ResetAt is like Reset, except it starts reading from pc.
+func (r *Reader) ResetAt(ops *Ops, pc PC) {
+ r.stack = r.stack[:0]
+ Reset(&r.deferOps)
+ r.deferDone = false
+ r.pc = pc
+ r.ops = ops
}
func (r *Reader) Decode() (EncodedOp, bool) {
if r.ops == nil {
return EncodedOp{}, false
}
+ deferring := false
for {
if len(r.stack) > 0 {
b := r.stack[len(r.stack)-1]
@@ -84,35 +81,59 @@ func (r *Reader) Decode() (EncodedOp, bool) {
continue
}
}
- data := r.ops.Data()
+ data := r.ops.data
data = data[r.pc.data:]
+ refs := r.ops.refs
if len(data) == 0 {
- return EncodedOp{}, false
+ if r.deferDone {
+ return EncodedOp{}, false
+ }
+ r.deferDone = true
+ // Execute deferred macros.
+ r.ops = &r.deferOps
+ r.pc = PC{}
+ continue
}
- key := Key{ops: r.ops, pc: r.pc.data, version: r.ops.Version()}
- t := opconst.OpType(data[0])
+ key := Key{ops: r.ops, pc: r.pc.data, version: r.ops.version}
+ t := OpType(data[0])
n := t.Size()
nrefs := t.NumRefs()
data = data[:n]
- refs := r.ops.Refs()
refs = refs[r.pc.refs:]
refs = refs[:nrefs]
switch t {
- case opconst.TypeAux:
+ case TypeDefer:
+ deferring = true
+ r.pc.data += n
+ r.pc.refs += nrefs
+ continue
+ case TypeAux:
// An Aux operations is always wrapped in a macro, and
// its length is the remaining space.
block := r.stack[len(r.stack)-1]
- n += block.endPC.data - r.pc.data - opconst.TypeAuxLen
+ n += block.endPC.data - r.pc.data - TypeAuxLen
data = data[:n]
- case opconst.TypeCall:
+ case TypeCall:
+ if deferring {
+ deferring = false
+ // Copy macro for deferred execution.
+ if t.NumRefs() != 1 {
+ panic("internal error: unexpected number of macro refs")
+ }
+ deferData := Write1(&r.deferOps, t.Size(), refs[0])
+ copy(deferData, data)
+ r.pc.data += n
+ r.pc.refs += nrefs
+ continue
+ }
var op macroOp
op.decode(data, refs)
- macroData := op.ops.Data()[op.pc.data:]
- if opconst.OpType(macroData[0]) != opconst.TypeMacro {
+ macroData := op.ops.data[op.pc.data:]
+ if OpType(macroData[0]) != TypeMacro {
panic("invalid macro reference")
}
var opDef opMacroDef
- opDef.decode(macroData[:opconst.TypeMacro.Size()])
+ opDef.decode(macroData[:TypeMacro.Size()])
retPC := r.pc
retPC.data += n
retPC.refs += nrefs
@@ -123,10 +144,10 @@ func (r *Reader) Decode() (EncodedOp, bool) {
})
r.ops = op.ops
r.pc = op.pc
- r.pc.data += opconst.TypeMacro.Size()
- r.pc.refs += opconst.TypeMacro.NumRefs()
+ r.pc.data += TypeMacro.Size()
+ r.pc.refs += TypeMacro.NumRefs()
continue
- case opconst.TypeMacro:
+ case TypeMacro:
var op opMacroDef
op.decode(data)
r.pc = op.endpc
@@ -139,14 +160,15 @@ func (r *Reader) Decode() (EncodedOp, bool) {
}
func (op *opMacroDef) decode(data []byte) {
- if opconst.OpType(data[0]) != opconst.TypeMacro {
+ if OpType(data[0]) != TypeMacro {
panic("invalid op")
}
bo := binary.LittleEndian
+ data = data[:9]
dataIdx := int(int32(bo.Uint32(data[1:])))
refsIdx := int(int32(bo.Uint32(data[5:])))
*op = opMacroDef{
- endpc: pc{
+ endpc: PC{
data: dataIdx,
refs: refsIdx,
},
@@ -154,15 +176,16 @@ func (op *opMacroDef) decode(data []byte) {
}
func (m *macroOp) decode(data []byte, refs []interface{}) {
- if opconst.OpType(data[0]) != opconst.TypeCall {
+ if OpType(data[0]) != TypeCall {
panic("invalid op")
}
+ data = data[:9]
bo := binary.LittleEndian
dataIdx := int(int32(bo.Uint32(data[1:])))
refsIdx := int(int32(bo.Uint32(data[5:])))
*m = macroOp{
- ops: refs[0].(*op.Ops),
- pc: pc{
+ ops: refs[0].(*Ops),
+ pc: PC{
data: dataIdx,
refs: refsIdx,
},
diff --git a/vendor/gioui.org/internal/scene/scene.go b/vendor/gioui.org/internal/scene/scene.go
new file mode 100644
index 0000000..0358858
--- /dev/null
+++ b/vendor/gioui.org/internal/scene/scene.go
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// Package scene encodes and decodes graphics commands in the format used by the
+// compute renderer.
+package scene
+
+import (
+ "fmt"
+ "image"
+ "image/color"
+ "math"
+ "unsafe"
+
+ "gioui.org/f32"
+)
+
+type Op uint32
+
+type Command [sceneElemSize / 4]uint32
+
+// GPU commands from piet/scene.h in package gioui.org/shaders.
+const (
+ OpNop Op = iota
+ OpLine
+ OpQuad
+ OpCubic
+ OpFillColor
+ OpLineWidth
+ OpTransform
+ OpBeginClip
+ OpEndClip
+ OpFillImage
+ OpSetFillMode
+ OpGap
+)
+
+// FillModes, from setup.h.
+type FillMode uint32
+
+const (
+ FillModeNonzero = 0
+ FillModeStroke = 1
+)
+
+const CommandSize = int(unsafe.Sizeof(Command{}))
+
+const sceneElemSize = 36
+
+func (c Command) Op() Op {
+ return Op(c[0])
+}
+
+func (c Command) String() string {
+ switch Op(c[0]) {
+ case OpNop:
+ return "nop"
+ case OpLine:
+ from, to := DecodeLine(c)
+ return fmt.Sprintf("line(%v, %v)", from, to)
+ case OpGap:
+ from, to := DecodeLine(c)
+ return fmt.Sprintf("gap(%v, %v)", from, to)
+ case OpQuad:
+ from, ctrl, to := DecodeQuad(c)
+ return fmt.Sprintf("quad(%v, %v, %v)", from, ctrl, to)
+ case OpCubic:
+ from, ctrl0, ctrl1, to := DecodeCubic(c)
+ return fmt.Sprintf("cubic(%v, %v, %v, %v)", from, ctrl0, ctrl1, to)
+ case OpFillColor:
+ return fmt.Sprintf("fillcolor %#.8x", c[1])
+ case OpLineWidth:
+ return "linewidth"
+ case OpTransform:
+ t := f32.NewAffine2D(
+ math.Float32frombits(c[1]),
+ math.Float32frombits(c[3]),
+ math.Float32frombits(c[5]),
+ math.Float32frombits(c[2]),
+ math.Float32frombits(c[4]),
+ math.Float32frombits(c[6]),
+ )
+ return fmt.Sprintf("transform (%v)", t)
+ case OpBeginClip:
+ bounds := f32.Rectangle{
+ Min: f32.Pt(math.Float32frombits(c[1]), math.Float32frombits(c[2])),
+ Max: f32.Pt(math.Float32frombits(c[3]), math.Float32frombits(c[4])),
+ }
+ return fmt.Sprintf("beginclip (%v)", bounds)
+ case OpEndClip:
+ bounds := f32.Rectangle{
+ Min: f32.Pt(math.Float32frombits(c[1]), math.Float32frombits(c[2])),
+ Max: f32.Pt(math.Float32frombits(c[3]), math.Float32frombits(c[4])),
+ }
+ return fmt.Sprintf("endclip (%v)", bounds)
+ case OpFillImage:
+ return "fillimage"
+ case OpSetFillMode:
+ return "setfillmode"
+ default:
+ panic("unreachable")
+ }
+}
+
+func Line(start, end f32.Point) Command {
+ return Command{
+ 0: uint32(OpLine),
+ 1: math.Float32bits(start.X),
+ 2: math.Float32bits(start.Y),
+ 3: math.Float32bits(end.X),
+ 4: math.Float32bits(end.Y),
+ }
+}
+
+func Gap(start, end f32.Point) Command {
+ return Command{
+ 0: uint32(OpGap),
+ 1: math.Float32bits(start.X),
+ 2: math.Float32bits(start.Y),
+ 3: math.Float32bits(end.X),
+ 4: math.Float32bits(end.Y),
+ }
+}
+
+func Cubic(start, ctrl0, ctrl1, end f32.Point) Command {
+ return Command{
+ 0: uint32(OpCubic),
+ 1: math.Float32bits(start.X),
+ 2: math.Float32bits(start.Y),
+ 3: math.Float32bits(ctrl0.X),
+ 4: math.Float32bits(ctrl0.Y),
+ 5: math.Float32bits(ctrl1.X),
+ 6: math.Float32bits(ctrl1.Y),
+ 7: math.Float32bits(end.X),
+ 8: math.Float32bits(end.Y),
+ }
+}
+
+func Quad(start, ctrl, end f32.Point) Command {
+ return Command{
+ 0: uint32(OpQuad),
+ 1: math.Float32bits(start.X),
+ 2: math.Float32bits(start.Y),
+ 3: math.Float32bits(ctrl.X),
+ 4: math.Float32bits(ctrl.Y),
+ 5: math.Float32bits(end.X),
+ 6: math.Float32bits(end.Y),
+ }
+}
+
+func Transform(m f32.Affine2D) Command {
+ sx, hx, ox, hy, sy, oy := m.Elems()
+ return Command{
+ 0: uint32(OpTransform),
+ 1: math.Float32bits(sx),
+ 2: math.Float32bits(hy),
+ 3: math.Float32bits(hx),
+ 4: math.Float32bits(sy),
+ 5: math.Float32bits(ox),
+ 6: math.Float32bits(oy),
+ }
+}
+
+func SetLineWidth(width float32) Command {
+ return Command{
+ 0: uint32(OpLineWidth),
+ 1: math.Float32bits(width),
+ }
+}
+
+func BeginClip(bbox f32.Rectangle) Command {
+ return Command{
+ 0: uint32(OpBeginClip),
+ 1: math.Float32bits(bbox.Min.X),
+ 2: math.Float32bits(bbox.Min.Y),
+ 3: math.Float32bits(bbox.Max.X),
+ 4: math.Float32bits(bbox.Max.Y),
+ }
+}
+
+func EndClip(bbox f32.Rectangle) Command {
+ return Command{
+ 0: uint32(OpEndClip),
+ 1: math.Float32bits(bbox.Min.X),
+ 2: math.Float32bits(bbox.Min.Y),
+ 3: math.Float32bits(bbox.Max.X),
+ 4: math.Float32bits(bbox.Max.Y),
+ }
+}
+
+func FillColor(col color.RGBA) Command {
+ return Command{
+ 0: uint32(OpFillColor),
+ 1: uint32(col.R)<<24 | uint32(col.G)<<16 | uint32(col.B)<<8 | uint32(col.A),
+ }
+}
+
+func FillImage(index int, offset image.Point) Command {
+ x := int16(offset.X)
+ y := int16(offset.Y)
+ return Command{
+ 0: uint32(OpFillImage),
+ 1: uint32(index),
+ 2: uint32(uint16(x)) | uint32(uint16(y))<<16,
+ }
+}
+
+func SetFillMode(mode FillMode) Command {
+ return Command{
+ 0: uint32(OpSetFillMode),
+ 1: uint32(mode),
+ }
+}
+
+func DecodeLine(cmd Command) (from, to f32.Point) {
+ if cmd[0] != uint32(OpLine) {
+ panic("invalid command")
+ }
+ from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
+ to = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
+ return
+}
+
+func DecodeGap(cmd Command) (from, to f32.Point) {
+ if cmd[0] != uint32(OpGap) {
+ panic("invalid command")
+ }
+ from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
+ to = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
+ return
+}
+
+func DecodeQuad(cmd Command) (from, ctrl, to f32.Point) {
+ if cmd[0] != uint32(OpQuad) {
+ panic("invalid command")
+ }
+ from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
+ ctrl = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
+ to = f32.Pt(math.Float32frombits(cmd[5]), math.Float32frombits(cmd[6]))
+ return
+}
+
+func DecodeCubic(cmd Command) (from, ctrl0, ctrl1, to f32.Point) {
+ if cmd[0] != uint32(OpCubic) {
+ panic("invalid command")
+ }
+ from = f32.Pt(math.Float32frombits(cmd[1]), math.Float32frombits(cmd[2]))
+ ctrl0 = f32.Pt(math.Float32frombits(cmd[3]), math.Float32frombits(cmd[4]))
+ ctrl1 = f32.Pt(math.Float32frombits(cmd[5]), math.Float32frombits(cmd[6]))
+ to = f32.Pt(math.Float32frombits(cmd[7]), math.Float32frombits(cmd[8]))
+ return
+}
diff --git a/vendor/gioui.org/internal/stroke/stroke.go b/vendor/gioui.org/internal/stroke/stroke.go
new file mode 100644
index 0000000..47db6ca
--- /dev/null
+++ b/vendor/gioui.org/internal/stroke/stroke.go
@@ -0,0 +1,742 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// Most of the algorithms to compute strokes and their offsets have been
+// extracted, adapted from (and used as a reference implementation):
+// - github.com/tdewolff/canvas (Licensed under MIT)
+//
+// These algorithms have been implemented from:
+// Fast, precise flattening of cubic Bézier path and offset curves
+// Thomas F. Hain, et al.
+//
+// An electronic version is available at:
+// https://seant23.files.wordpress.com/2010/11/fastpreciseflatteningofbeziercurve.pdf
+//
+// Possible improvements (in term of speed and/or accuracy) on these
+// algorithms are:
+//
+// - Polar Stroking: New Theory and Methods for Stroking Paths,
+// M. Kilgard
+// https://arxiv.org/pdf/2007.00308.pdf
+//
+// - https://raphlinus.github.io/graphics/curves/2019/12/23/flatten-quadbez.html
+// R. Levien
+
+// Package stroke implements conversion of strokes to filled outlines. It is used as a
+// fallback for stroke configurations not natively supported by the renderer.
+package stroke
+
+import (
+ "encoding/binary"
+ "math"
+
+ "gioui.org/f32"
+ "gioui.org/internal/ops"
+ "gioui.org/internal/scene"
+)
+
+// The following are copies of types from op/clip to avoid a circular import of
+// that package.
+// TODO: when the old renderer is gone, this package can be merged with
+// op/clip, eliminating the duplicate types.
+type StrokeStyle struct {
+ Width float32
+}
+
+// strokeTolerance is used to reconcile rounding errors arising
+// when splitting quads into smaller and smaller segments to approximate
+// them into straight lines, and when joining back segments.
+//
+// The magic value of 0.01 was found by striking a compromise between
+// aesthetic looking (curves did look like curves, even after linearization)
+// and speed.
+const strokeTolerance = 0.01
+
+type QuadSegment struct {
+ From, Ctrl, To f32.Point
+}
+
+type StrokeQuad struct {
+ Contour uint32
+ Quad QuadSegment
+}
+
+type strokeState struct {
+ p0, p1 f32.Point // p0 is the start point, p1 the end point.
+ n0, n1 f32.Point // n0 is the normal vector at the start point, n1 at the end point.
+ r0, r1 float32 // r0 is the curvature at the start point, r1 at the end point.
+ ctl f32.Point // ctl is the control point of the quadratic Bézier segment.
+}
+
+type StrokeQuads []StrokeQuad
+
+func (qs *StrokeQuads) setContour(n uint32) {
+ for i := range *qs {
+ (*qs)[i].Contour = n
+ }
+}
+
+func (qs *StrokeQuads) pen() f32.Point {
+ return (*qs)[len(*qs)-1].Quad.To
+}
+
+func (qs *StrokeQuads) lineTo(pt f32.Point) {
+ end := qs.pen()
+ *qs = append(*qs, StrokeQuad{
+ Quad: QuadSegment{
+ From: end,
+ Ctrl: end.Add(pt).Mul(0.5),
+ To: pt,
+ },
+ })
+}
+
+func (qs *StrokeQuads) arc(f1, f2 f32.Point, angle float32) {
+ const segments = 16
+ pen := qs.pen()
+ m := ArcTransform(pen, f1.Add(pen), f2.Add(pen), angle, segments)
+ for i := 0; i < segments; i++ {
+ p0 := qs.pen()
+ p1 := m.Transform(p0)
+ p2 := m.Transform(p1)
+ ctl := p1.Mul(2).Sub(p0.Add(p2).Mul(.5))
+ *qs = append(*qs, StrokeQuad{
+ Quad: QuadSegment{
+ From: p0, Ctrl: ctl, To: p2,
+ },
+ })
+ }
+}
+
+// split splits a slice of quads into slices of quads grouped
+// by contours (ie: splitted at move-to boundaries).
+func (qs StrokeQuads) split() []StrokeQuads {
+ if len(qs) == 0 {
+ return nil
+ }
+
+ var (
+ c uint32
+ o []StrokeQuads
+ i = len(o)
+ )
+ for _, q := range qs {
+ if q.Contour != c {
+ c = q.Contour
+ i = len(o)
+ o = append(o, StrokeQuads{})
+ }
+ o[i] = append(o[i], q)
+ }
+
+ return o
+}
+
+func (qs StrokeQuads) stroke(stroke StrokeStyle) StrokeQuads {
+ var (
+ o StrokeQuads
+ hw = 0.5 * stroke.Width
+ )
+
+ for _, ps := range qs.split() {
+ rhs, lhs := ps.offset(hw, stroke)
+ switch lhs {
+ case nil:
+ o = o.append(rhs)
+ default:
+ // Closed path.
+ // Inner path should go opposite direction to cancel outer path.
+ switch {
+ case ps.ccw():
+ lhs = lhs.reverse()
+ o = o.append(rhs)
+ o = o.append(lhs)
+ default:
+ rhs = rhs.reverse()
+ o = o.append(lhs)
+ o = o.append(rhs)
+ }
+ }
+ }
+
+ return o
+}
+
+// offset returns the right-hand and left-hand sides of the path, offset by
+// the half-width hw.
+// The stroke handles how segments are joined and ends are capped.
+func (qs StrokeQuads) offset(hw float32, stroke StrokeStyle) (rhs, lhs StrokeQuads) {
+ var (
+ states []strokeState
+ beg = qs[0].Quad.From
+ end = qs[len(qs)-1].Quad.To
+ closed = beg == end
+ )
+ for i := range qs {
+ q := qs[i].Quad
+
+ var (
+ n0 = strokePathNorm(q.From, q.Ctrl, q.To, 0, hw)
+ n1 = strokePathNorm(q.From, q.Ctrl, q.To, 1, hw)
+ r0 = strokePathCurv(q.From, q.Ctrl, q.To, 0)
+ r1 = strokePathCurv(q.From, q.Ctrl, q.To, 1)
+ )
+ states = append(states, strokeState{
+ p0: q.From,
+ p1: q.To,
+ n0: n0,
+ n1: n1,
+ r0: r0,
+ r1: r1,
+ ctl: q.Ctrl,
+ })
+ }
+
+ for i, state := range states {
+ rhs = rhs.append(strokeQuadBezier(state, +hw, strokeTolerance))
+ lhs = lhs.append(strokeQuadBezier(state, -hw, strokeTolerance))
+
+ // join the current and next segments
+ if hasNext := i+1 < len(states); hasNext || closed {
+ var next strokeState
+ switch {
+ case hasNext:
+ next = states[i+1]
+ case closed:
+ next = states[0]
+ }
+ if state.n1 != next.n0 {
+ strokePathJoin(stroke, &rhs, &lhs, hw, state.p1, state.n1, next.n0, state.r1, next.r0)
+ }
+ }
+ }
+
+ if closed {
+ rhs.close()
+ lhs.close()
+ return rhs, lhs
+ }
+
+ qbeg := &states[0]
+ qend := &states[len(states)-1]
+
+ // Default to counter-clockwise direction.
+ lhs = lhs.reverse()
+ strokePathCap(stroke, &rhs, hw, qend.p1, qend.n1)
+
+ rhs = rhs.append(lhs)
+ strokePathCap(stroke, &rhs, hw, qbeg.p0, qbeg.n0.Mul(-1))
+
+ rhs.close()
+
+ return rhs, nil
+}
+
+func (qs *StrokeQuads) close() {
+ p0 := (*qs)[len(*qs)-1].Quad.To
+ p1 := (*qs)[0].Quad.From
+
+ if p1 == p0 {
+ return
+ }
+
+ *qs = append(*qs, StrokeQuad{
+ Quad: QuadSegment{
+ From: p0,
+ Ctrl: p0.Add(p1).Mul(0.5),
+ To: p1,
+ },
+ })
+}
+
+// ccw returns whether the path is counter-clockwise.
+func (qs StrokeQuads) ccw() bool {
+ // Use the Shoelace formula:
+ // https://en.wikipedia.org/wiki/Shoelace_formula
+ var area float32
+ for _, ps := range qs.split() {
+ for i := 1; i < len(ps); i++ {
+ pi := ps[i].Quad.To
+ pj := ps[i-1].Quad.To
+ area += (pi.X - pj.X) * (pi.Y + pj.Y)
+ }
+ }
+ return area <= 0.0
+}
+
+func (qs StrokeQuads) reverse() StrokeQuads {
+ if len(qs) == 0 {
+ return nil
+ }
+
+ ps := make(StrokeQuads, 0, len(qs))
+ for i := range qs {
+ q := qs[len(qs)-1-i]
+ q.Quad.To, q.Quad.From = q.Quad.From, q.Quad.To
+ ps = append(ps, q)
+ }
+
+ return ps
+}
+
+func (qs StrokeQuads) append(ps StrokeQuads) StrokeQuads {
+ switch {
+ case len(ps) == 0:
+ return qs
+ case len(qs) == 0:
+ return ps
+ }
+
+ // Consolidate quads and smooth out rounding errors.
+ // We need to also check for the strokeTolerance to correctly handle
+ // join/cap points or on-purpose disjoint quads.
+ p0 := qs[len(qs)-1].Quad.To
+ p1 := ps[0].Quad.From
+ if p0 != p1 && lenPt(p0.Sub(p1)) < strokeTolerance {
+ qs = append(qs, StrokeQuad{
+ Quad: QuadSegment{
+ From: p0,
+ Ctrl: p0.Add(p1).Mul(0.5),
+ To: p1,
+ },
+ })
+ }
+ return append(qs, ps...)
+}
+
+func (q QuadSegment) Transform(t f32.Affine2D) QuadSegment {
+ q.From = t.Transform(q.From)
+ q.Ctrl = t.Transform(q.Ctrl)
+ q.To = t.Transform(q.To)
+ return q
+}
+
+// strokePathNorm returns the normal vector at t.
+func strokePathNorm(p0, p1, p2 f32.Point, t, d float32) f32.Point {
+ switch t {
+ case 0:
+ n := p1.Sub(p0)
+ if n.X == 0 && n.Y == 0 {
+ return f32.Point{}
+ }
+ n = rot90CW(n)
+ return normPt(n, d)
+ case 1:
+ n := p2.Sub(p1)
+ if n.X == 0 && n.Y == 0 {
+ return f32.Point{}
+ }
+ n = rot90CW(n)
+ return normPt(n, d)
+ }
+ panic("impossible")
+}
+
+func rot90CW(p f32.Point) f32.Point { return f32.Pt(+p.Y, -p.X) }
+func rot90CCW(p f32.Point) f32.Point { return f32.Pt(-p.Y, +p.X) }
+
+// cosPt returns the cosine of the opening angle between p and q.
+func cosPt(p, q f32.Point) float32 {
+ np := math.Hypot(float64(p.X), float64(p.Y))
+ nq := math.Hypot(float64(q.X), float64(q.Y))
+ return dotPt(p, q) / float32(np*nq)
+}
+
+func normPt(p f32.Point, l float32) f32.Point {
+ d := math.Hypot(float64(p.X), float64(p.Y))
+ l64 := float64(l)
+ if math.Abs(d-l64) < 1e-10 {
+ return f32.Point{}
+ }
+ n := float32(l64 / d)
+ return f32.Point{X: p.X * n, Y: p.Y * n}
+}
+
+func lenPt(p f32.Point) float32 {
+ return float32(math.Hypot(float64(p.X), float64(p.Y)))
+}
+
+func dotPt(p, q f32.Point) float32 {
+ return p.X*q.X + p.Y*q.Y
+}
+
+func perpDot(p, q f32.Point) float32 {
+ return p.X*q.Y - p.Y*q.X
+}
+
+// strokePathCurv returns the curvature at t, along the quadratic Bézier
+// curve defined by the triplet (beg, ctl, end).
+func strokePathCurv(beg, ctl, end f32.Point, t float32) float32 {
+ var (
+ d1p = quadBezierD1(beg, ctl, end, t)
+ d2p = quadBezierD2(beg, ctl, end, t)
+
+ // Negative when bending right, ie: the curve is CW at this point.
+ a = float64(perpDot(d1p, d2p))
+ )
+
+ // We check early that the segment isn't too line-like and
+ // save a costly call to math.Pow that will be discarded by dividing
+ // with a too small 'a'.
+ if math.Abs(a) < 1e-10 {
+ return float32(math.NaN())
+ }
+ return float32(math.Pow(float64(d1p.X*d1p.X+d1p.Y*d1p.Y), 1.5) / a)
+}
+
+// quadBezierSample returns the point on the Bézier curve at t.
+// B(t) = (1-t)^2 P0 + 2(1-t)t P1 + t^2 P2
+func quadBezierSample(p0, p1, p2 f32.Point, t float32) f32.Point {
+ t1 := 1 - t
+ c0 := t1 * t1
+ c1 := 2 * t1 * t
+ c2 := t * t
+
+ o := p0.Mul(c0)
+ o = o.Add(p1.Mul(c1))
+ o = o.Add(p2.Mul(c2))
+ return o
+}
+
+// quadBezierD1 returns the first derivative of the Bézier curve with respect to t.
+// B'(t) = 2(1-t)(P1 - P0) + 2t(P2 - P1)
+func quadBezierD1(p0, p1, p2 f32.Point, t float32) f32.Point {
+ p10 := p1.Sub(p0).Mul(2 * (1 - t))
+ p21 := p2.Sub(p1).Mul(2 * t)
+
+ return p10.Add(p21)
+}
+
+// quadBezierD2 returns the second derivative of the Bézier curve with respect to t:
+// B''(t) = 2(P2 - 2P1 + P0)
+func quadBezierD2(p0, p1, p2 f32.Point, t float32) f32.Point {
+ p := p2.Sub(p1.Mul(2)).Add(p0)
+ return p.Mul(2)
+}
+
+func strokeQuadBezier(state strokeState, d, flatness float32) StrokeQuads {
+ // Gio strokes are only quadratic Bézier curves, w/o any inflection point.
+ // So we just have to flatten them.
+ var qs StrokeQuads
+ return flattenQuadBezier(qs, state.p0, state.ctl, state.p1, d, flatness)
+}
+
+// flattenQuadBezier splits a Bézier quadratic curve into linear sub-segments,
+// themselves also encoded as Bézier (degenerate, flat) quadratic curves.
+func flattenQuadBezier(qs StrokeQuads, p0, p1, p2 f32.Point, d, flatness float32) StrokeQuads {
+ var (
+ t float32
+ flat64 = float64(flatness)
+ )
+ for t < 1 {
+ s2 := float64((p2.X-p0.X)*(p1.Y-p0.Y) - (p2.Y-p0.Y)*(p1.X-p0.X))
+ den := math.Hypot(float64(p1.X-p0.X), float64(p1.Y-p0.Y))
+ if s2*den == 0.0 {
+ break
+ }
+
+ s2 /= den
+ t = 2.0 * float32(math.Sqrt(flat64/3.0/math.Abs(s2)))
+ if t >= 1.0 {
+ break
+ }
+ var q0, q1, q2 f32.Point
+ q0, q1, q2, p0, p1, p2 = quadBezierSplit(p0, p1, p2, t)
+ qs.addLine(q0, q1, q2, 0, d)
+ }
+ qs.addLine(p0, p1, p2, 1, d)
+ return qs
+}
+
+func (qs *StrokeQuads) addLine(p0, ctrl, p1 f32.Point, t, d float32) {
+
+ switch i := len(*qs); i {
+ case 0:
+ p0 = p0.Add(strokePathNorm(p0, ctrl, p1, 0, d))
+ default:
+ // Address possible rounding errors and use previous point.
+ p0 = (*qs)[i-1].Quad.To
+ }
+
+ p1 = p1.Add(strokePathNorm(p0, ctrl, p1, 1, d))
+
+ *qs = append(*qs,
+ StrokeQuad{
+ Quad: QuadSegment{
+ From: p0,
+ Ctrl: p0.Add(p1).Mul(0.5),
+ To: p1,
+ },
+ },
+ )
+}
+
+// quadInterp returns the interpolated point at t.
+func quadInterp(p, q f32.Point, t float32) f32.Point {
+ return f32.Pt(
+ (1-t)*p.X+t*q.X,
+ (1-t)*p.Y+t*q.Y,
+ )
+}
+
+// quadBezierSplit returns the pair of triplets (from,ctrl,to) Bézier curve,
+// split before (resp. after) the provided parametric t value.
+func quadBezierSplit(p0, p1, p2 f32.Point, t float32) (f32.Point, f32.Point, f32.Point, f32.Point, f32.Point, f32.Point) {
+
+ var (
+ b0 = p0
+ b1 = quadInterp(p0, p1, t)
+ b2 = quadBezierSample(p0, p1, p2, t)
+
+ a0 = b2
+ a1 = quadInterp(p1, p2, t)
+ a2 = p2
+ )
+
+ return b0, b1, b2, a0, a1, a2
+}
+
+// strokePathJoin joins the two paths rhs and lhs, according to the provided
+// stroke operation.
+func strokePathJoin(stroke StrokeStyle, rhs, lhs *StrokeQuads, hw float32, pivot, n0, n1 f32.Point, r0, r1 float32) {
+ strokePathRoundJoin(rhs, lhs, hw, pivot, n0, n1, r0, r1)
+}
+
+func strokePathRoundJoin(rhs, lhs *StrokeQuads, hw float32, pivot, n0, n1 f32.Point, r0, r1 float32) {
+ rp := pivot.Add(n1)
+ lp := pivot.Sub(n1)
+ cw := dotPt(rot90CW(n0), n1) >= 0.0
+ switch {
+ case cw:
+ // Path bends to the right, ie. CW (or 180 degree turn).
+ c := pivot.Sub(lhs.pen())
+ angle := -math.Acos(float64(cosPt(n0, n1)))
+ lhs.arc(c, c, float32(angle))
+ lhs.lineTo(lp) // Add a line to accommodate for rounding errors.
+ rhs.lineTo(rp)
+ default:
+ // Path bends to the left, ie. CCW.
+ angle := math.Acos(float64(cosPt(n0, n1)))
+ c := pivot.Sub(rhs.pen())
+ rhs.arc(c, c, float32(angle))
+ rhs.lineTo(rp) // Add a line to accommodate for rounding errors.
+ lhs.lineTo(lp)
+ }
+}
+
+// strokePathCap caps the provided path qs, according to the provided stroke operation.
+func strokePathCap(stroke StrokeStyle, qs *StrokeQuads, hw float32, pivot, n0 f32.Point) {
+ strokePathRoundCap(qs, hw, pivot, n0)
+}
+
+// strokePathRoundCap caps the start or end of a path with a round cap.
+func strokePathRoundCap(qs *StrokeQuads, hw float32, pivot, n0 f32.Point) {
+ c := pivot.Sub(qs.pen())
+ qs.arc(c, c, math.Pi)
+}
+
+// ArcTransform computes a transformation that can be used for generating quadratic bézier
+// curve approximations for an arc.
+//
+// The math is extracted from the following paper:
+// "Drawing an elliptical arc using polylines, quadratic or
+// cubic Bezier curves", L. Maisonobe
+// An electronic version may be found at:
+// http://spaceroots.org/documents/ellipse/elliptical-arc.pdf
+func ArcTransform(p, f1, f2 f32.Point, angle float32, segments int) f32.Affine2D {
+ var rx, ry, alpha float64
+ if f1 == f2 {
+ // degenerate case of a circle.
+ rx = dist(f1, p)
+ ry = rx
+ } else {
+ // semi-major axis: 2a = |PF1| + |PF2|
+ a := 0.5 * (dist(f1, p) + dist(f2, p))
+ // semi-minor axis: c^2 = a^2 - b^2 (c: focal distance)
+ c := dist(f1, f2) * 0.5
+ b := math.Sqrt(a*a - c*c)
+ switch {
+ case a > b:
+ rx = a
+ ry = b
+ default:
+ rx = b
+ ry = a
+ }
+ if f1.X == f2.X {
+ // special case of a "vertical" ellipse.
+ alpha = math.Pi / 2
+ if f1.Y < f2.Y {
+ alpha = -alpha
+ }
+ } else {
+ x := float64(f1.X-f2.X) * 0.5
+ if x < 0 {
+ x = -x
+ }
+ alpha = math.Acos(x / c)
+ }
+ }
+
+ var (
+ θ = angle / float32(segments)
+ ref f32.Affine2D // transform from absolute frame to ellipse-based one
+ rot f32.Affine2D // rotation matrix for each segment
+ inv f32.Affine2D // transform from ellipse-based frame to absolute one
+ )
+ center := f32.Point{
+ X: 0.5 * (f1.X + f2.X),
+ Y: 0.5 * (f1.Y + f2.Y),
+ }
+ ref = ref.Offset(f32.Point{}.Sub(center))
+ ref = ref.Rotate(f32.Point{}, float32(-alpha))
+ ref = ref.Scale(f32.Point{}, f32.Point{
+ X: float32(1 / rx),
+ Y: float32(1 / ry),
+ })
+ inv = ref.Invert()
+ rot = rot.Rotate(f32.Point{}, 0.5*θ)
+
+ // Instead of invoking math.Sincos for every segment, compute a rotation
+ // matrix once and apply for each segment.
+ // Before applying the rotation matrix rot, transform the coordinates
+ // to a frame centered to the ellipse (and warped into a unit circle), then rotate.
+ // Finally, transform back into the original frame.
+ return inv.Mul(rot).Mul(ref)
+}
+
+func dist(p1, p2 f32.Point) float64 {
+ var (
+ x1 = float64(p1.X)
+ y1 = float64(p1.Y)
+ x2 = float64(p2.X)
+ y2 = float64(p2.Y)
+ dx = x2 - x1
+ dy = y2 - y1
+ )
+ return math.Hypot(dx, dy)
+}
+
+func StrokePathCommands(style StrokeStyle, scene []byte) StrokeQuads {
+ quads := decodeToStrokeQuads(scene)
+ return quads.stroke(style)
+}
+
+// decodeToStrokeQuads decodes scene commands to quads ready to stroke.
+func decodeToStrokeQuads(pathData []byte) StrokeQuads {
+ quads := make(StrokeQuads, 0, 2*len(pathData)/(scene.CommandSize+4))
+ for len(pathData) >= scene.CommandSize+4 {
+ contour := binary.LittleEndian.Uint32(pathData)
+ cmd := ops.DecodeCommand(pathData[4:])
+ switch cmd.Op() {
+ case scene.OpLine:
+ var q QuadSegment
+ q.From, q.To = scene.DecodeLine(cmd)
+ q.Ctrl = q.From.Add(q.To).Mul(.5)
+ quad := StrokeQuad{
+ Contour: contour,
+ Quad: q,
+ }
+ quads = append(quads, quad)
+ case scene.OpGap:
+ // Ignore gaps for strokes.
+ case scene.OpQuad:
+ var q QuadSegment
+ q.From, q.Ctrl, q.To = scene.DecodeQuad(cmd)
+ quad := StrokeQuad{
+ Contour: contour,
+ Quad: q,
+ }
+ quads = append(quads, quad)
+ case scene.OpCubic:
+ for _, q := range SplitCubic(scene.DecodeCubic(cmd)) {
+ quad := StrokeQuad{
+ Contour: contour,
+ Quad: q,
+ }
+ quads = append(quads, quad)
+ }
+ default:
+ panic("unsupported scene command")
+ }
+ pathData = pathData[scene.CommandSize+4:]
+ }
+ return quads
+}
+
+func SplitCubic(from, ctrl0, ctrl1, to f32.Point) []QuadSegment {
+ quads := make([]QuadSegment, 0, 10)
+ // Set the maximum distance proportionally to the longest side
+ // of the bounding rectangle.
+ hull := f32.Rectangle{
+ Min: from,
+ Max: ctrl0,
+ }.Canon().Union(f32.Rectangle{
+ Min: ctrl1,
+ Max: to,
+ }.Canon())
+ l := hull.Dx()
+ if h := hull.Dy(); h > l {
+ l = h
+ }
+ approxCubeTo(&quads, 0, l*0.001, from, ctrl0, ctrl1, to)
+ return quads
+}
+
+// approxCubeTo approximates a cubic Bézier by a series of quadratic
+// curves.
+func approxCubeTo(quads *[]QuadSegment, splits int, maxDist float32, from, ctrl0, ctrl1, to f32.Point) int {
+ // The idea is from
+ // https://caffeineowl.com/graphics/2d/vectorial/cubic2quad01.html
+ // where a quadratic approximates a cubic by eliminating its t³ term
+ // from its polynomial expression anchored at the starting point:
+ //
+ // P(t) = pen + 3t(ctrl0 - pen) + 3t²(ctrl1 - 2ctrl0 + pen) + t³(to - 3ctrl1 + 3ctrl0 - pen)
+ //
+ // The control point for the new quadratic Q1 that shares starting point, pen, with P is
+ //
+ // C1 = (3ctrl0 - pen)/2
+ //
+ // The reverse cubic anchored at the end point has the polynomial
+ //
+ // P'(t) = to + 3t(ctrl1 - to) + 3t²(ctrl0 - 2ctrl1 + to) + t³(pen - 3ctrl0 + 3ctrl1 - to)
+ //
+ // The corresponding quadratic Q2 that shares the end point, to, with P has control
+ // point
+ //
+ // C2 = (3ctrl1 - to)/2
+ //
+ // The combined quadratic Bézier, Q, shares both start and end points with its cubic
+ // and use the midpoint between the two curves Q1 and Q2 as control point:
+ //
+ // C = (3ctrl0 - pen + 3ctrl1 - to)/4
+ c := ctrl0.Mul(3).Sub(from).Add(ctrl1.Mul(3)).Sub(to).Mul(1.0 / 4.0)
+ const maxSplits = 32
+ if splits >= maxSplits {
+ *quads = append(*quads, QuadSegment{From: from, Ctrl: c, To: to})
+ return splits
+ }
+ // The maximum distance between the cubic P and its approximation Q given t
+ // can be shown to be
+ //
+ // d = sqrt(3)/36*|to - 3ctrl1 + 3ctrl0 - pen|
+ //
+ // To save a square root, compare d² with the squared tolerance.
+ v := to.Sub(ctrl1.Mul(3)).Add(ctrl0.Mul(3)).Sub(from)
+ d2 := (v.X*v.X + v.Y*v.Y) * 3 / (36 * 36)
+ if d2 <= maxDist*maxDist {
+ *quads = append(*quads, QuadSegment{From: from, Ctrl: c, To: to})
+ return splits
+ }
+ // De Casteljau split the curve and approximate the halves.
+ t := float32(0.5)
+ c0 := from.Add(ctrl0.Sub(from).Mul(t))
+ c1 := ctrl0.Add(ctrl1.Sub(ctrl0).Mul(t))
+ c2 := ctrl1.Add(to.Sub(ctrl1).Mul(t))
+ c01 := c0.Add(c1.Sub(c0).Mul(t))
+ c12 := c1.Add(c2.Sub(c1).Mul(t))
+ c0112 := c01.Add(c12.Sub(c01).Mul(t))
+ splits++
+ splits = approxCubeTo(quads, splits, maxDist, from, c0, c01, c0112)
+ splits = approxCubeTo(quads, splits, maxDist, c0112, c12, c2, to)
+ return splits
+}
diff --git a/vendor/gioui.org/internal/unsafe/unsafe.go b/vendor/gioui.org/internal/unsafe/unsafe.go
deleted file mode 100644
index 5353144..0000000
--- a/vendor/gioui.org/internal/unsafe/unsafe.go
+++ /dev/null
@@ -1,46 +0,0 @@
-// SPDX-License-Identifier: Unlicense OR MIT
-
-package unsafe
-
-import (
- "reflect"
- "unsafe"
-)
-
-// BytesView returns a byte slice view of a slice.
-func BytesView(s interface{}) []byte {
- v := reflect.ValueOf(s)
- first := v.Index(0)
- sz := int(first.Type().Size())
- return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
- Data: uintptr(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(first.UnsafeAddr())))),
- Len: v.Len() * sz,
- Cap: v.Cap() * sz,
- }))
-}
-
-// SliceOf returns a slice from a (native) pointer.
-func SliceOf(s uintptr) []byte {
- if s == 0 {
- return nil
- }
- sh := reflect.SliceHeader{
- Data: s,
- Len: 1 << 30,
- Cap: 1 << 30,
- }
- return *(*[]byte)(unsafe.Pointer(&sh))
-}
-
-// GoString convert a NUL-terminated C string
-// to a Go string.
-func GoString(s []byte) string {
- i := 0
- for {
- if s[i] == 0 {
- break
- }
- i++
- }
- return string(s[:i])
-}
diff --git a/vendor/gioui.org/internal/vk/vulkan.go b/vendor/gioui.org/internal/vk/vulkan.go
new file mode 100644
index 0000000..f210d40
--- /dev/null
+++ b/vendor/gioui.org/internal/vk/vulkan.go
@@ -0,0 +1,2081 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build linux || freebsd
+// +build linux freebsd
+
+package vk
+
+/*
+#cgo linux freebsd LDFLAGS: -ldl
+#cgo freebsd CFLAGS: -I/usr/local/include
+#cgo CFLAGS: -Werror -Werror=return-type
+
+#define VK_NO_PROTOTYPES 1
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#include <vulkan/vulkan.h>
+#define __USE_GNU
+#include <dlfcn.h>
+#include <stdlib.h>
+
+static VkResult vkCreateInstance(PFN_vkCreateInstance f, VkInstanceCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
+ return f(&pCreateInfo, pAllocator, pInstance);
+}
+
+static void vkDestroyInstance(PFN_vkDestroyInstance f, VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+ f(instance, pAllocator);
+}
+
+static VkResult vkEnumeratePhysicalDevices(PFN_vkEnumeratePhysicalDevices f, VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
+ return f(instance, pPhysicalDeviceCount, pPhysicalDevices);
+}
+
+static void vkGetPhysicalDeviceQueueFamilyProperties(PFN_vkGetPhysicalDeviceQueueFamilyProperties f, VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount, VkQueueFamilyProperties *pQueueFamilyProperties) {
+ f(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
+}
+
+static void vkGetPhysicalDeviceFormatProperties(PFN_vkGetPhysicalDeviceFormatProperties f, VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
+ f(physicalDevice, format, pFormatProperties);
+}
+
+static VkResult vkCreateDevice(PFN_vkCreateDevice f, VkPhysicalDevice physicalDevice, VkDeviceCreateInfo pCreateInfo, VkDeviceQueueCreateInfo qinf, const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+ pCreateInfo.pQueueCreateInfos = &qinf;
+ return f(physicalDevice, &pCreateInfo, pAllocator, pDevice);
+}
+
+static void vkDestroyDevice(PFN_vkDestroyDevice f, VkDevice device, const VkAllocationCallbacks *pAllocator) {
+ f(device, pAllocator);
+}
+
+static void vkGetDeviceQueue(PFN_vkGetDeviceQueue f, VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
+ f(device, queueFamilyIndex, queueIndex, pQueue);
+}
+
+static VkResult vkCreateImageView(PFN_vkCreateImageView f, VkDevice device, const VkImageViewCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
+ return f(device, pCreateInfo, pAllocator, pView);
+}
+
+static void vkDestroyImageView(PFN_vkDestroyImageView f, VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
+ f(device, imageView, pAllocator);
+}
+
+static VkResult vkCreateFramebuffer(PFN_vkCreateFramebuffer f, VkDevice device, VkFramebufferCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFramebuffer *pFramebuffer) {
+ return f(device, &pCreateInfo, pAllocator, pFramebuffer);
+}
+
+static void vkDestroyFramebuffer(PFN_vkDestroyFramebuffer f, VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
+ f(device, framebuffer, pAllocator);
+}
+
+static VkResult vkDeviceWaitIdle(PFN_vkDeviceWaitIdle f, VkDevice device) {
+ return f(device);
+}
+
+static VkResult vkQueueWaitIdle(PFN_vkQueueWaitIdle f, VkQueue queue) {
+ return f(queue);
+}
+
+static VkResult vkCreateSemaphore(PFN_vkCreateSemaphore f, VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
+ return f(device, pCreateInfo, pAllocator, pSemaphore);
+}
+
+static void vkDestroySemaphore(PFN_vkDestroySemaphore f, VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
+ f(device, semaphore, pAllocator);
+}
+
+static VkResult vkCreateRenderPass(PFN_vkCreateRenderPass f, VkDevice device, VkRenderPassCreateInfo pCreateInfo, VkSubpassDescription subpassInf, const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
+ pCreateInfo.pSubpasses = &subpassInf;
+ return f(device, &pCreateInfo, pAllocator, pRenderPass);
+}
+
+static void vkDestroyRenderPass(PFN_vkDestroyRenderPass f, VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
+ f(device, renderPass, pAllocator);
+}
+
+static VkResult vkCreateCommandPool(PFN_vkCreateCommandPool f, VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkCommandPool *pCommandPool) {
+ return f(device, pCreateInfo, pAllocator, pCommandPool);
+}
+
+static void vkDestroyCommandPool(PFN_vkDestroyCommandPool f, VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
+ f(device, commandPool, pAllocator);
+}
+
+static VkResult vkAllocateCommandBuffers(PFN_vkAllocateCommandBuffers f, VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
+ return f(device, pAllocateInfo, pCommandBuffers);
+}
+
+static void vkFreeCommandBuffers(PFN_vkFreeCommandBuffers f, VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
+ f(device, commandPool, commandBufferCount, pCommandBuffers);
+}
+
+static VkResult vkBeginCommandBuffer(PFN_vkBeginCommandBuffer f, VkCommandBuffer commandBuffer, VkCommandBufferBeginInfo pBeginInfo) {
+ return f(commandBuffer, &pBeginInfo);
+}
+
+static VkResult vkEndCommandBuffer(PFN_vkEndCommandBuffer f, VkCommandBuffer commandBuffer) {
+ return f(commandBuffer);
+}
+
+static VkResult vkQueueSubmit(PFN_vkQueueSubmit f, VkQueue queue, VkSubmitInfo pSubmits, VkFence fence) {
+ return f(queue, 1, &pSubmits, fence);
+}
+
+static void vkCmdBeginRenderPass(PFN_vkCmdBeginRenderPass f, VkCommandBuffer commandBuffer, VkRenderPassBeginInfo pRenderPassBegin, VkSubpassContents contents) {
+ f(commandBuffer, &pRenderPassBegin, contents);
+}
+
+static void vkCmdEndRenderPass(PFN_vkCmdEndRenderPass f, VkCommandBuffer commandBuffer) {
+ f(commandBuffer);
+}
+
+static void vkCmdCopyBuffer(PFN_vkCmdCopyBuffer f, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferCopy *pRegions) {
+ f(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
+}
+
+static void vkCmdCopyBufferToImage(PFN_vkCmdCopyBufferToImage f, VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
+ f(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+static void vkCmdPipelineBarrier(PFN_vkCmdPipelineBarrier f, VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers, uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers, uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
+ f(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
+}
+
+static void vkCmdPushConstants(PFN_vkCmdPushConstants f, VkCommandBuffer commandBuffer, VkPipelineLayout layout, VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size, const void *pValues) {
+ f(commandBuffer, layout, stageFlags, offset, size, pValues);
+}
+
+static void vkCmdBindPipeline(PFN_vkCmdBindPipeline f, VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+ f(commandBuffer, pipelineBindPoint, pipeline);
+}
+
+static void vkCmdBindVertexBuffers(PFN_vkCmdBindVertexBuffers f, VkCommandBuffer commandBuffer, uint32_t firstBinding, uint32_t bindingCount, const VkBuffer *pBuffers, const VkDeviceSize *pOffsets) {
+ f(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
+}
+
+static void vkCmdSetViewport(PFN_vkCmdSetViewport f, VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
+ f(commandBuffer, firstViewport, viewportCount, pViewports);
+}
+
+static void vkCmdBindIndexBuffer(PFN_vkCmdBindIndexBuffer f, VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+ f(commandBuffer, buffer, offset, indexType);
+}
+
+static void vkCmdDraw(PFN_vkCmdDraw f, VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) {
+ f(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
+}
+
+static void vkCmdDrawIndexed(PFN_vkCmdDrawIndexed f, VkCommandBuffer commandBuffer, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) {
+ f(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
+}
+
+static void vkCmdBindDescriptorSets(PFN_vkCmdBindDescriptorSets f, VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout, uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets, uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
+ f(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
+}
+
+static void vkCmdCopyImageToBuffer(PFN_vkCmdCopyImageToBuffer f, VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) {
+ f(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
+}
+
+static void vkCmdDispatch(PFN_vkCmdDispatch f, VkCommandBuffer commandBuffer, uint32_t groupCountX, uint32_t groupCountY, uint32_t groupCountZ) {
+ f(commandBuffer, groupCountX, groupCountY, groupCountZ);
+}
+
+static VkResult vkCreateImage(PFN_vkCreateImage f, VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
+ return f(device, pCreateInfo, pAllocator, pImage);
+}
+
+static void vkDestroyImage(PFN_vkDestroyImage f, VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
+ f(device, image, pAllocator);
+}
+
+static void vkGetImageMemoryRequirements(PFN_vkGetImageMemoryRequirements f, VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
+ f(device, image, pMemoryRequirements);
+}
+
+static VkResult vkAllocateMemory(PFN_vkAllocateMemory f, VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo, const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
+ return f(device, pAllocateInfo, pAllocator, pMemory);
+}
+
+static VkResult vkBindImageMemory(PFN_vkBindImageMemory f, VkDevice device, VkImage image, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+ return f(device, image, memory, memoryOffset);
+}
+
+static void vkFreeMemory(PFN_vkFreeMemory f, VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
+ f(device, memory, pAllocator);
+}
+
+static void vkGetPhysicalDeviceMemoryProperties(PFN_vkGetPhysicalDeviceMemoryProperties f, VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
+ f(physicalDevice, pMemoryProperties);
+}
+
+static VkResult vkCreateSampler(PFN_vkCreateSampler f,VkDevice device, const VkSamplerCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
+ return f(device, pCreateInfo, pAllocator, pSampler);
+}
+
+static void vkDestroySampler(PFN_vkDestroySampler f, VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
+ f(device, sampler, pAllocator);
+}
+
+static VkResult vkCreateBuffer(PFN_vkCreateBuffer f, VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
+ return f(device, pCreateInfo, pAllocator, pBuffer);
+}
+
+static void vkDestroyBuffer(PFN_vkDestroyBuffer f, VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
+ f(device, buffer, pAllocator);
+}
+
+static void vkGetBufferMemoryRequirements(PFN_vkGetBufferMemoryRequirements f, VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
+ f(device, buffer, pMemoryRequirements);
+}
+
+static VkResult vkBindBufferMemory(PFN_vkBindBufferMemory f, VkDevice device, VkBuffer buffer, VkDeviceMemory memory, VkDeviceSize memoryOffset) {
+ return f(device, buffer, memory, memoryOffset);
+}
+
+static VkResult vkCreateShaderModule(PFN_vkCreateShaderModule f, VkDevice device, VkShaderModuleCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkShaderModule *pShaderModule) {
+ return f(device, &pCreateInfo, pAllocator, pShaderModule);
+}
+
+static void vkDestroyShaderModule(PFN_vkDestroyShaderModule f, VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
+ f(device, shaderModule, pAllocator);
+}
+
+static VkResult vkCreateGraphicsPipelines(PFN_vkCreateGraphicsPipelines f, VkDevice device, VkPipelineCache pipelineCache, VkGraphicsPipelineCreateInfo pCreateInfo, VkPipelineDynamicStateCreateInfo dynInf, VkPipelineColorBlendStateCreateInfo blendInf, VkPipelineVertexInputStateCreateInfo vertexInf, VkPipelineViewportStateCreateInfo viewportInf, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
+ pCreateInfo.pDynamicState = &dynInf;
+ pCreateInfo.pViewportState = &viewportInf;
+ pCreateInfo.pColorBlendState = &blendInf;
+ pCreateInfo.pVertexInputState = &vertexInf;
+ return f(device, pipelineCache, 1, &pCreateInfo, pAllocator, pPipelines);
+}
+
+static void vkDestroyPipeline(PFN_vkDestroyPipeline f, VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
+ f(device, pipeline, pAllocator);
+}
+
+static VkResult vkCreatePipelineLayout(PFN_vkCreatePipelineLayout f, VkDevice device, VkPipelineLayoutCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkPipelineLayout *pPipelineLayout) {
+ return f(device, &pCreateInfo, pAllocator, pPipelineLayout);
+}
+
+static void vkDestroyPipelineLayout(PFN_vkDestroyPipelineLayout f, VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
+ f(device, pipelineLayout, pAllocator);
+}
+
+static VkResult vkCreateDescriptorSetLayout(PFN_vkCreateDescriptorSetLayout f, VkDevice device, VkDescriptorSetLayoutCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
+ return f(device, &pCreateInfo, pAllocator, pSetLayout);
+}
+
+static void vkDestroyDescriptorSetLayout(PFN_vkDestroyDescriptorSetLayout f, VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
+ f(device, descriptorSetLayout, pAllocator);
+}
+
+static VkResult vkMapMemory(PFN_vkMapMemory f, VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) {
+ return f(device, memory, offset, size, flags, ppData);
+}
+
+static void vkUnmapMemory(PFN_vkUnmapMemory f, VkDevice device, VkDeviceMemory memory) {
+ f(device, memory);
+}
+
+static VkResult vkResetCommandBuffer(PFN_vkResetCommandBuffer f, VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
+ return f(commandBuffer, flags);
+}
+
+static VkResult vkCreateDescriptorPool(PFN_vkCreateDescriptorPool f, VkDevice device, VkDescriptorPoolCreateInfo pCreateInfo, const VkAllocationCallbacks *pAllocator, VkDescriptorPool *pDescriptorPool) {
+ return f(device, &pCreateInfo, pAllocator, pDescriptorPool);
+}
+
+static void vkDestroyDescriptorPool(PFN_vkDestroyDescriptorPool f, VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
+ f(device, descriptorPool, pAllocator);
+}
+
+static VkResult vkAllocateDescriptorSets(PFN_vkAllocateDescriptorSets f, VkDevice device, VkDescriptorSetAllocateInfo pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
+ return f(device, &pAllocateInfo, pDescriptorSets);
+}
+
+static VkResult vkFreeDescriptorSets(PFN_vkFreeDescriptorSets f, VkDevice device, VkDescriptorPool descriptorPool, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets) {
+ return f(device, descriptorPool, descriptorSetCount, pDescriptorSets);
+}
+
+static void vkUpdateDescriptorSets(PFN_vkUpdateDescriptorSets f, VkDevice device, VkWriteDescriptorSet pDescriptorWrite, uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
+ f(device, 1, &pDescriptorWrite, descriptorCopyCount, pDescriptorCopies);
+}
+
+static VkResult vkResetDescriptorPool(PFN_vkResetDescriptorPool f, VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
+ return f(device, descriptorPool, flags);
+}
+
+static void vkCmdCopyImage(PFN_vkCmdCopyImage f, VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
+ f(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
+}
+
+static VkResult vkCreateComputePipelines(PFN_vkCreateComputePipelines f, VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount, const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator, VkPipeline *pPipelines) {
+ return f(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
+}
+
+static VkResult vkCreateFence(PFN_vkCreateFence f, VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
+ return f(device, pCreateInfo, pAllocator, pFence);
+}
+
+static void vkDestroyFence(PFN_vkDestroyFence f, VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
+ f(device, fence, pAllocator);
+}
+
+static VkResult vkWaitForFences(PFN_vkWaitForFences f, VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
+ return f(device, fenceCount, pFences, waitAll, timeout);
+}
+
+static VkResult vkResetFences(PFN_vkResetFences f, VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
+ return f(device, fenceCount, pFences);
+}
+
+static void vkGetPhysicalDeviceProperties(PFN_vkGetPhysicalDeviceProperties f, VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
+ f(physicalDevice, pProperties);
+}
+
+static VkResult vkGetPhysicalDeviceSurfaceSupportKHR(PFN_vkGetPhysicalDeviceSurfaceSupportKHR f, VkPhysicalDevice physicalDevice, uint32_t queueFamilyIndex, VkSurfaceKHR surface, VkBool32 *pSupported) {
+ return f(physicalDevice, queueFamilyIndex, surface, pSupported);
+}
+
+static void vkDestroySurfaceKHR(PFN_vkDestroySurfaceKHR f, VkInstance instance, VkSurfaceKHR surface, const VkAllocationCallbacks *pAllocator) {
+ f(instance, surface, pAllocator);
+}
+
+static VkResult vkGetPhysicalDeviceSurfaceFormatsKHR(PFN_vkGetPhysicalDeviceSurfaceFormatsKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pSurfaceFormatCount, VkSurfaceFormatKHR *pSurfaceFormats) {
+ return f(physicalDevice, surface, pSurfaceFormatCount, pSurfaceFormats);
+}
+
+static VkResult vkGetPhysicalDeviceSurfacePresentModesKHR(PFN_vkGetPhysicalDeviceSurfacePresentModesKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, uint32_t *pPresentModeCount, VkPresentModeKHR *pPresentModes) {
+ return f(physicalDevice, surface, pPresentModeCount, pPresentModes);
+}
+
+static VkResult vkGetPhysicalDeviceSurfaceCapabilitiesKHR(PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR f, VkPhysicalDevice physicalDevice, VkSurfaceKHR surface, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) {
+ return f(physicalDevice, surface, pSurfaceCapabilities);
+}
+
+static VkResult vkCreateSwapchainKHR(PFN_vkCreateSwapchainKHR f, VkDevice device, const VkSwapchainCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSwapchainKHR *pSwapchain) {
+ return f(device, pCreateInfo, pAllocator, pSwapchain);
+}
+
+static void vkDestroySwapchainKHR(PFN_vkDestroySwapchainKHR f, VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks *pAllocator) {
+ f(device, swapchain, pAllocator);
+}
+
+static VkResult vkGetSwapchainImagesKHR(PFN_vkGetSwapchainImagesKHR f, VkDevice device, VkSwapchainKHR swapchain, uint32_t *pSwapchainImageCount, VkImage *pSwapchainImages) {
+ return f(device, swapchain, pSwapchainImageCount, pSwapchainImages);
+}
+
+// indexAndResult holds both an integer and a result returned by value, to
+// avoid Go heap allocation of the integer with Vulkan's return style.
+struct intAndResult {
+ uint32_t uint;
+ VkResult res;
+};
+
+static struct intAndResult vkAcquireNextImageKHR(PFN_vkAcquireNextImageKHR f, VkDevice device, VkSwapchainKHR swapchain, uint64_t timeout, VkSemaphore semaphore, VkFence fence) {
+ struct intAndResult res;
+ res.res = f(device, swapchain, timeout, semaphore, fence, &res.uint);
+ return res;
+}
+
+static VkResult vkQueuePresentKHR(PFN_vkQueuePresentKHR f, VkQueue queue, const VkPresentInfoKHR pPresentInfo) {
+ return f(queue, &pPresentInfo);
+}
+*/
+import "C"
+import (
+ "errors"
+ "fmt"
+ "image"
+ "math"
+ "reflect"
+ "runtime"
+ "sync"
+ "unsafe"
+)
+
+type (
+ AttachmentLoadOp = C.VkAttachmentLoadOp
+ AccessFlags = C.VkAccessFlags
+ BlendFactor = C.VkBlendFactor
+ Buffer = C.VkBuffer
+ BufferImageCopy = C.VkBufferImageCopy
+ BufferMemoryBarrier = C.VkBufferMemoryBarrier
+ BufferUsageFlags = C.VkBufferUsageFlags
+ CommandPool = C.VkCommandPool
+ CommandBuffer = C.VkCommandBuffer
+ DependencyFlags = C.VkDependencyFlags
+ DescriptorPool = C.VkDescriptorPool
+ DescriptorPoolSize = C.VkDescriptorPoolSize
+ DescriptorSet = C.VkDescriptorSet
+ DescriptorSetLayout = C.VkDescriptorSetLayout
+ DescriptorType = C.VkDescriptorType
+ Device = C.VkDevice
+ DeviceMemory = C.VkDeviceMemory
+ DeviceSize = C.VkDeviceSize
+ Fence = C.VkFence
+ Queue = C.VkQueue
+ IndexType = C.VkIndexType
+ Image = C.VkImage
+ ImageCopy = C.VkImageCopy
+ ImageLayout = C.VkImageLayout
+ ImageMemoryBarrier = C.VkImageMemoryBarrier
+ ImageUsageFlags = C.VkImageUsageFlags
+ ImageView = C.VkImageView
+ Instance = C.VkInstance
+ Filter = C.VkFilter
+ Format = C.VkFormat
+ FormatFeatureFlags = C.VkFormatFeatureFlags
+ Framebuffer = C.VkFramebuffer
+ MemoryBarrier = C.VkMemoryBarrier
+ MemoryPropertyFlags = C.VkMemoryPropertyFlags
+ Pipeline = C.VkPipeline
+ PipelineBindPoint = C.VkPipelineBindPoint
+ PipelineLayout = C.VkPipelineLayout
+ PipelineStageFlags = C.VkPipelineStageFlags
+ PhysicalDevice = C.VkPhysicalDevice
+ PrimitiveTopology = C.VkPrimitiveTopology
+ PushConstantRange = C.VkPushConstantRange
+ QueueFamilyProperties = C.VkQueueFamilyProperties
+ QueueFlags = C.VkQueueFlags
+ RenderPass = C.VkRenderPass
+ Sampler = C.VkSampler
+ SamplerMipmapMode = C.VkSamplerMipmapMode
+ Semaphore = C.VkSemaphore
+ ShaderModule = C.VkShaderModule
+ ShaderStageFlags = C.VkShaderStageFlags
+ SubpassDependency = C.VkSubpassDependency
+ Viewport = C.VkViewport
+ WriteDescriptorSet = C.VkWriteDescriptorSet
+
+ Surface = C.VkSurfaceKHR
+ SurfaceCapabilities = C.VkSurfaceCapabilitiesKHR
+
+ Swapchain = C.VkSwapchainKHR
+)
+
+type VertexInputBindingDescription struct {
+ Binding int
+ Stride int
+}
+
+type VertexInputAttributeDescription struct {
+ Location int
+ Binding int
+ Format Format
+ Offset int
+}
+
+type DescriptorSetLayoutBinding struct {
+ Binding int
+ DescriptorType DescriptorType
+ StageFlags ShaderStageFlags
+}
+
+type Error C.VkResult
+
+const (
+ FORMAT_R8G8B8A8_UNORM Format = C.VK_FORMAT_R8G8B8A8_UNORM
+ FORMAT_B8G8R8A8_SRGB Format = C.VK_FORMAT_B8G8R8A8_SRGB
+ FORMAT_R8G8B8A8_SRGB Format = C.VK_FORMAT_R8G8B8A8_SRGB
+ FORMAT_R16_SFLOAT Format = C.VK_FORMAT_R16_SFLOAT
+ FORMAT_R32_SFLOAT Format = C.VK_FORMAT_R32_SFLOAT
+ FORMAT_R32G32_SFLOAT Format = C.VK_FORMAT_R32G32_SFLOAT
+ FORMAT_R32G32B32_SFLOAT Format = C.VK_FORMAT_R32G32B32_SFLOAT
+ FORMAT_R32G32B32A32_SFLOAT Format = C.VK_FORMAT_R32G32B32A32_SFLOAT
+
+ FORMAT_FEATURE_COLOR_ATTACHMENT_BIT FormatFeatureFlags = C.VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT
+ FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT FormatFeatureFlags = C.VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT
+ FORMAT_FEATURE_SAMPLED_IMAGE_BIT FormatFeatureFlags = C.VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT
+
+ IMAGE_USAGE_SAMPLED_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_SAMPLED_BIT
+ IMAGE_USAGE_COLOR_ATTACHMENT_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
+ IMAGE_USAGE_STORAGE_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_STORAGE_BIT
+ IMAGE_USAGE_TRANSFER_DST_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_TRANSFER_DST_BIT
+ IMAGE_USAGE_TRANSFER_SRC_BIT ImageUsageFlags = C.VK_IMAGE_USAGE_TRANSFER_SRC_BIT
+
+ FILTER_NEAREST Filter = C.VK_FILTER_NEAREST
+ FILTER_LINEAR Filter = C.VK_FILTER_LINEAR
+
+ ATTACHMENT_LOAD_OP_CLEAR AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_CLEAR
+ ATTACHMENT_LOAD_OP_DONT_CARE AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_DONT_CARE
+ ATTACHMENT_LOAD_OP_LOAD AttachmentLoadOp = C.VK_ATTACHMENT_LOAD_OP_LOAD
+
+ IMAGE_LAYOUT_UNDEFINED ImageLayout = C.VK_IMAGE_LAYOUT_UNDEFINED
+ IMAGE_LAYOUT_PRESENT_SRC_KHR ImageLayout = C.VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
+ IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
+ IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
+ IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL
+ IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ImageLayout = C.VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL
+ IMAGE_LAYOUT_GENERAL ImageLayout = C.VK_IMAGE_LAYOUT_GENERAL
+
+ BUFFER_USAGE_TRANSFER_DST_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_TRANSFER_DST_BIT
+ BUFFER_USAGE_TRANSFER_SRC_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_TRANSFER_SRC_BIT
+ BUFFER_USAGE_UNIFORM_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
+ BUFFER_USAGE_STORAGE_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
+ BUFFER_USAGE_INDEX_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_INDEX_BUFFER_BIT
+ BUFFER_USAGE_VERTEX_BUFFER_BIT BufferUsageFlags = C.VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
+
+ ERROR_OUT_OF_DATE_KHR = Error(C.VK_ERROR_OUT_OF_DATE_KHR)
+ ERROR_SURFACE_LOST_KHR = Error(C.VK_ERROR_SURFACE_LOST_KHR)
+ ERROR_DEVICE_LOST = Error(C.VK_ERROR_DEVICE_LOST)
+ SUBOPTIMAL_KHR = Error(C.VK_SUBOPTIMAL_KHR)
+
+ BLEND_FACTOR_ZERO BlendFactor = C.VK_BLEND_FACTOR_ZERO
+ BLEND_FACTOR_ONE BlendFactor = C.VK_BLEND_FACTOR_ONE
+ BLEND_FACTOR_ONE_MINUS_SRC_ALPHA BlendFactor = C.VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
+ BLEND_FACTOR_DST_COLOR BlendFactor = C.VK_BLEND_FACTOR_DST_COLOR
+
+ PRIMITIVE_TOPOLOGY_TRIANGLE_LIST PrimitiveTopology = C.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
+ PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP PrimitiveTopology = C.VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
+
+ SHADER_STAGE_VERTEX_BIT ShaderStageFlags = C.VK_SHADER_STAGE_VERTEX_BIT
+ SHADER_STAGE_FRAGMENT_BIT ShaderStageFlags = C.VK_SHADER_STAGE_FRAGMENT_BIT
+ SHADER_STAGE_COMPUTE_BIT ShaderStageFlags = C.VK_SHADER_STAGE_COMPUTE_BIT
+
+ DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER DescriptorType = C.VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER
+ DESCRIPTOR_TYPE_UNIFORM_BUFFER DescriptorType = C.VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
+ DESCRIPTOR_TYPE_STORAGE_BUFFER DescriptorType = C.VK_DESCRIPTOR_TYPE_STORAGE_BUFFER
+ DESCRIPTOR_TYPE_STORAGE_IMAGE DescriptorType = C.VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
+
+ MEMORY_PROPERTY_DEVICE_LOCAL_BIT MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
+ MEMORY_PROPERTY_HOST_VISIBLE_BIT MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+ MEMORY_PROPERTY_HOST_COHERENT_BIT MemoryPropertyFlags = C.VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+
+ DEPENDENCY_BY_REGION_BIT DependencyFlags = C.VK_DEPENDENCY_BY_REGION_BIT
+
+ PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
+ PIPELINE_STAGE_TRANSFER_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_TRANSFER_BIT
+ PIPELINE_STAGE_FRAGMENT_SHADER_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
+ PIPELINE_STAGE_COMPUTE_SHADER_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
+ PIPELINE_STAGE_TOP_OF_PIPE_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT
+ PIPELINE_STAGE_HOST_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_HOST_BIT
+ PIPELINE_STAGE_VERTEX_INPUT_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
+ PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT PipelineStageFlags = C.VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT
+
+ ACCESS_MEMORY_READ_BIT AccessFlags = C.VK_ACCESS_MEMORY_READ_BIT
+ ACCESS_MEMORY_WRITE_BIT AccessFlags = C.VK_ACCESS_MEMORY_WRITE_BIT
+ ACCESS_TRANSFER_READ_BIT AccessFlags = C.VK_ACCESS_TRANSFER_READ_BIT
+ ACCESS_TRANSFER_WRITE_BIT AccessFlags = C.VK_ACCESS_TRANSFER_WRITE_BIT
+ ACCESS_SHADER_READ_BIT AccessFlags = C.VK_ACCESS_SHADER_READ_BIT
+ ACCESS_SHADER_WRITE_BIT AccessFlags = C.VK_ACCESS_SHADER_WRITE_BIT
+ ACCESS_COLOR_ATTACHMENT_READ_BIT AccessFlags = C.VK_ACCESS_COLOR_ATTACHMENT_READ_BIT
+ ACCESS_COLOR_ATTACHMENT_WRITE_BIT AccessFlags = C.VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT
+ ACCESS_HOST_READ_BIT AccessFlags = C.VK_ACCESS_HOST_READ_BIT
+ ACCESS_HOST_WRITE_BIT AccessFlags = C.VK_ACCESS_HOST_WRITE_BIT
+ ACCESS_VERTEX_ATTRIBUTE_READ_BIT AccessFlags = C.VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
+ ACCESS_INDEX_READ_BIT AccessFlags = C.VK_ACCESS_INDEX_READ_BIT
+
+ PIPELINE_BIND_POINT_COMPUTE PipelineBindPoint = C.VK_PIPELINE_BIND_POINT_COMPUTE
+ PIPELINE_BIND_POINT_GRAPHICS PipelineBindPoint = C.VK_PIPELINE_BIND_POINT_GRAPHICS
+
+ INDEX_TYPE_UINT16 IndexType = C.VK_INDEX_TYPE_UINT16
+ INDEX_TYPE_UINT32 IndexType = C.VK_INDEX_TYPE_UINT32
+
+ QUEUE_GRAPHICS_BIT QueueFlags = C.VK_QUEUE_GRAPHICS_BIT
+ QUEUE_COMPUTE_BIT QueueFlags = C.VK_QUEUE_COMPUTE_BIT
+)
+
+var (
+ once sync.Once
+ loadErr error
+
+ loadFuncs []func(dlopen func(name string) *[0]byte)
+)
+
+var funcs struct {
+ vkCreateInstance C.PFN_vkCreateInstance
+ vkDestroyInstance C.PFN_vkDestroyInstance
+ vkEnumeratePhysicalDevices C.PFN_vkEnumeratePhysicalDevices
+ vkGetPhysicalDeviceQueueFamilyProperties C.PFN_vkGetPhysicalDeviceQueueFamilyProperties
+ vkGetPhysicalDeviceFormatProperties C.PFN_vkGetPhysicalDeviceFormatProperties
+ vkCreateDevice C.PFN_vkCreateDevice
+ vkDestroyDevice C.PFN_vkDestroyDevice
+ vkGetDeviceQueue C.PFN_vkGetDeviceQueue
+ vkCreateImageView C.PFN_vkCreateImageView
+ vkDestroyImageView C.PFN_vkDestroyImageView
+ vkCreateFramebuffer C.PFN_vkCreateFramebuffer
+ vkDestroyFramebuffer C.PFN_vkDestroyFramebuffer
+ vkDeviceWaitIdle C.PFN_vkDeviceWaitIdle
+ vkQueueWaitIdle C.PFN_vkQueueWaitIdle
+ vkCreateSemaphore C.PFN_vkCreateSemaphore
+ vkDestroySemaphore C.PFN_vkDestroySemaphore
+ vkCreateRenderPass C.PFN_vkCreateRenderPass
+ vkDestroyRenderPass C.PFN_vkDestroyRenderPass
+ vkCreateCommandPool C.PFN_vkCreateCommandPool
+ vkDestroyCommandPool C.PFN_vkDestroyCommandPool
+ vkAllocateCommandBuffers C.PFN_vkAllocateCommandBuffers
+ vkFreeCommandBuffers C.PFN_vkFreeCommandBuffers
+ vkBeginCommandBuffer C.PFN_vkBeginCommandBuffer
+ vkEndCommandBuffer C.PFN_vkEndCommandBuffer
+ vkQueueSubmit C.PFN_vkQueueSubmit
+ vkCmdBeginRenderPass C.PFN_vkCmdBeginRenderPass
+ vkCmdEndRenderPass C.PFN_vkCmdEndRenderPass
+ vkCmdCopyBuffer C.PFN_vkCmdCopyBuffer
+ vkCmdCopyBufferToImage C.PFN_vkCmdCopyBufferToImage
+ vkCmdPipelineBarrier C.PFN_vkCmdPipelineBarrier
+ vkCmdPushConstants C.PFN_vkCmdPushConstants
+ vkCmdBindPipeline C.PFN_vkCmdBindPipeline
+ vkCmdBindVertexBuffers C.PFN_vkCmdBindVertexBuffers
+ vkCmdSetViewport C.PFN_vkCmdSetViewport
+ vkCmdBindIndexBuffer C.PFN_vkCmdBindIndexBuffer
+ vkCmdDraw C.PFN_vkCmdDraw
+ vkCmdDrawIndexed C.PFN_vkCmdDrawIndexed
+ vkCmdBindDescriptorSets C.PFN_vkCmdBindDescriptorSets
+ vkCmdCopyImageToBuffer C.PFN_vkCmdCopyImageToBuffer
+ vkCmdDispatch C.PFN_vkCmdDispatch
+ vkCreateImage C.PFN_vkCreateImage
+ vkDestroyImage C.PFN_vkDestroyImage
+ vkGetImageMemoryRequirements C.PFN_vkGetImageMemoryRequirements
+ vkAllocateMemory C.PFN_vkAllocateMemory
+ vkBindImageMemory C.PFN_vkBindImageMemory
+ vkFreeMemory C.PFN_vkFreeMemory
+ vkGetPhysicalDeviceMemoryProperties C.PFN_vkGetPhysicalDeviceMemoryProperties
+ vkCreateSampler C.PFN_vkCreateSampler
+ vkDestroySampler C.PFN_vkDestroySampler
+ vkCreateBuffer C.PFN_vkCreateBuffer
+ vkDestroyBuffer C.PFN_vkDestroyBuffer
+ vkGetBufferMemoryRequirements C.PFN_vkGetBufferMemoryRequirements
+ vkBindBufferMemory C.PFN_vkBindBufferMemory
+ vkCreateShaderModule C.PFN_vkCreateShaderModule
+ vkDestroyShaderModule C.PFN_vkDestroyShaderModule
+ vkCreateGraphicsPipelines C.PFN_vkCreateGraphicsPipelines
+ vkDestroyPipeline C.PFN_vkDestroyPipeline
+ vkCreatePipelineLayout C.PFN_vkCreatePipelineLayout
+ vkDestroyPipelineLayout C.PFN_vkDestroyPipelineLayout
+ vkCreateDescriptorSetLayout C.PFN_vkCreateDescriptorSetLayout
+ vkDestroyDescriptorSetLayout C.PFN_vkDestroyDescriptorSetLayout
+ vkMapMemory C.PFN_vkMapMemory
+ vkUnmapMemory C.PFN_vkUnmapMemory
+ vkResetCommandBuffer C.PFN_vkResetCommandBuffer
+ vkCreateDescriptorPool C.PFN_vkCreateDescriptorPool
+ vkDestroyDescriptorPool C.PFN_vkDestroyDescriptorPool
+ vkAllocateDescriptorSets C.PFN_vkAllocateDescriptorSets
+ vkFreeDescriptorSets C.PFN_vkFreeDescriptorSets
+ vkUpdateDescriptorSets C.PFN_vkUpdateDescriptorSets
+ vkResetDescriptorPool C.PFN_vkResetDescriptorPool
+ vkCmdCopyImage C.PFN_vkCmdCopyImage
+ vkCreateComputePipelines C.PFN_vkCreateComputePipelines
+ vkCreateFence C.PFN_vkCreateFence
+ vkDestroyFence C.PFN_vkDestroyFence
+ vkWaitForFences C.PFN_vkWaitForFences
+ vkResetFences C.PFN_vkResetFences
+ vkGetPhysicalDeviceProperties C.PFN_vkGetPhysicalDeviceProperties
+
+ vkGetPhysicalDeviceSurfaceSupportKHR C.PFN_vkGetPhysicalDeviceSurfaceSupportKHR
+ vkDestroySurfaceKHR C.PFN_vkDestroySurfaceKHR
+ vkGetPhysicalDeviceSurfaceFormatsKHR C.PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
+ vkGetPhysicalDeviceSurfacePresentModesKHR C.PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR C.PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+
+ vkCreateSwapchainKHR C.PFN_vkCreateSwapchainKHR
+ vkDestroySwapchainKHR C.PFN_vkDestroySwapchainKHR
+ vkGetSwapchainImagesKHR C.PFN_vkGetSwapchainImagesKHR
+ vkAcquireNextImageKHR C.PFN_vkAcquireNextImageKHR
+ vkQueuePresentKHR C.PFN_vkQueuePresentKHR
+}
+
+var (
+ nilSurface C.VkSurfaceKHR
+ nilSwapchain C.VkSwapchainKHR
+ nilSemaphore C.VkSemaphore
+ nilImageView C.VkImageView
+ nilRenderPass C.VkRenderPass
+ nilFramebuffer C.VkFramebuffer
+ nilCommandPool C.VkCommandPool
+ nilImage C.VkImage
+ nilDeviceMemory C.VkDeviceMemory
+ nilSampler C.VkSampler
+ nilBuffer C.VkBuffer
+ nilShaderModule C.VkShaderModule
+ nilPipeline C.VkPipeline
+ nilPipelineCache C.VkPipelineCache
+ nilPipelineLayout C.VkPipelineLayout
+ nilDescriptorSetLayout C.VkDescriptorSetLayout
+ nilDescriptorPool C.VkDescriptorPool
+ nilDescriptorSet C.VkDescriptorSet
+ nilFence C.VkFence
+)
+
+func vkInit() error {
+ once.Do(func() {
+ var libName string
+ switch {
+ case runtime.GOOS == "android":
+ libName = "libvulkan.so"
+ default:
+ libName = "libvulkan.so.1"
+ }
+ lib := dlopen(libName)
+ if lib == nil {
+ loadErr = fmt.Errorf("vulkan: %s", C.GoString(C.dlerror()))
+ return
+ }
+ dlopen := func(name string) *[0]byte {
+ return (*[0]byte)(dlsym(lib, name))
+ }
+ must := func(name string) *[0]byte {
+ ptr := dlopen(name)
+ if ptr != nil {
+ return ptr
+ }
+ if loadErr == nil {
+ loadErr = fmt.Errorf("vulkan: function %q not found: %s", name, C.GoString(C.dlerror()))
+ }
+ return nil
+ }
+ funcs.vkCreateInstance = must("vkCreateInstance")
+ funcs.vkDestroyInstance = must("vkDestroyInstance")
+ funcs.vkEnumeratePhysicalDevices = must("vkEnumeratePhysicalDevices")
+ funcs.vkGetPhysicalDeviceQueueFamilyProperties = must("vkGetPhysicalDeviceQueueFamilyProperties")
+ funcs.vkGetPhysicalDeviceFormatProperties = must("vkGetPhysicalDeviceFormatProperties")
+ funcs.vkCreateDevice = must("vkCreateDevice")
+ funcs.vkDestroyDevice = must("vkDestroyDevice")
+ funcs.vkGetDeviceQueue = must("vkGetDeviceQueue")
+ funcs.vkCreateImageView = must("vkCreateImageView")
+ funcs.vkDestroyImageView = must("vkDestroyImageView")
+ funcs.vkCreateFramebuffer = must("vkCreateFramebuffer")
+ funcs.vkDestroyFramebuffer = must("vkDestroyFramebuffer")
+ funcs.vkDeviceWaitIdle = must("vkDeviceWaitIdle")
+ funcs.vkQueueWaitIdle = must("vkQueueWaitIdle")
+ funcs.vkCreateSemaphore = must("vkCreateSemaphore")
+ funcs.vkDestroySemaphore = must("vkDestroySemaphore")
+ funcs.vkCreateRenderPass = must("vkCreateRenderPass")
+ funcs.vkDestroyRenderPass = must("vkDestroyRenderPass")
+ funcs.vkCreateCommandPool = must("vkCreateCommandPool")
+ funcs.vkDestroyCommandPool = must("vkDestroyCommandPool")
+ funcs.vkAllocateCommandBuffers = must("vkAllocateCommandBuffers")
+ funcs.vkFreeCommandBuffers = must("vkFreeCommandBuffers")
+ funcs.vkBeginCommandBuffer = must("vkBeginCommandBuffer")
+ funcs.vkEndCommandBuffer = must("vkEndCommandBuffer")
+ funcs.vkQueueSubmit = must("vkQueueSubmit")
+ funcs.vkCmdBeginRenderPass = must("vkCmdBeginRenderPass")
+ funcs.vkCmdEndRenderPass = must("vkCmdEndRenderPass")
+ funcs.vkCmdCopyBuffer = must("vkCmdCopyBuffer")
+ funcs.vkCmdCopyBufferToImage = must("vkCmdCopyBufferToImage")
+ funcs.vkCmdPipelineBarrier = must("vkCmdPipelineBarrier")
+ funcs.vkCmdPushConstants = must("vkCmdPushConstants")
+ funcs.vkCmdBindPipeline = must("vkCmdBindPipeline")
+ funcs.vkCmdBindVertexBuffers = must("vkCmdBindVertexBuffers")
+ funcs.vkCmdSetViewport = must("vkCmdSetViewport")
+ funcs.vkCmdBindIndexBuffer = must("vkCmdBindIndexBuffer")
+ funcs.vkCmdDraw = must("vkCmdDraw")
+ funcs.vkCmdDrawIndexed = must("vkCmdDrawIndexed")
+ funcs.vkCmdBindDescriptorSets = must("vkCmdBindDescriptorSets")
+ funcs.vkCmdCopyImageToBuffer = must("vkCmdCopyImageToBuffer")
+ funcs.vkCmdDispatch = must("vkCmdDispatch")
+ funcs.vkCreateImage = must("vkCreateImage")
+ funcs.vkDestroyImage = must("vkDestroyImage")
+ funcs.vkGetImageMemoryRequirements = must("vkGetImageMemoryRequirements")
+ funcs.vkAllocateMemory = must("vkAllocateMemory")
+ funcs.vkBindImageMemory = must("vkBindImageMemory")
+ funcs.vkFreeMemory = must("vkFreeMemory")
+ funcs.vkGetPhysicalDeviceMemoryProperties = must("vkGetPhysicalDeviceMemoryProperties")
+ funcs.vkCreateSampler = must("vkCreateSampler")
+ funcs.vkDestroySampler = must("vkDestroySampler")
+ funcs.vkCreateBuffer = must("vkCreateBuffer")
+ funcs.vkDestroyBuffer = must("vkDestroyBuffer")
+ funcs.vkGetBufferMemoryRequirements = must("vkGetBufferMemoryRequirements")
+ funcs.vkBindBufferMemory = must("vkBindBufferMemory")
+ funcs.vkCreateShaderModule = must("vkCreateShaderModule")
+ funcs.vkDestroyShaderModule = must("vkDestroyShaderModule")
+ funcs.vkCreateGraphicsPipelines = must("vkCreateGraphicsPipelines")
+ funcs.vkDestroyPipeline = must("vkDestroyPipeline")
+ funcs.vkCreatePipelineLayout = must("vkCreatePipelineLayout")
+ funcs.vkDestroyPipelineLayout = must("vkDestroyPipelineLayout")
+ funcs.vkCreateDescriptorSetLayout = must("vkCreateDescriptorSetLayout")
+ funcs.vkDestroyDescriptorSetLayout = must("vkDestroyDescriptorSetLayout")
+ funcs.vkMapMemory = must("vkMapMemory")
+ funcs.vkUnmapMemory = must("vkUnmapMemory")
+ funcs.vkResetCommandBuffer = must("vkResetCommandBuffer")
+ funcs.vkCreateDescriptorPool = must("vkCreateDescriptorPool")
+ funcs.vkDestroyDescriptorPool = must("vkDestroyDescriptorPool")
+ funcs.vkAllocateDescriptorSets = must("vkAllocateDescriptorSets")
+ funcs.vkFreeDescriptorSets = must("vkFreeDescriptorSets")
+ funcs.vkUpdateDescriptorSets = must("vkUpdateDescriptorSets")
+ funcs.vkResetDescriptorPool = must("vkResetDescriptorPool")
+ funcs.vkCmdCopyImage = must("vkCmdCopyImage")
+ funcs.vkCreateComputePipelines = must("vkCreateComputePipelines")
+ funcs.vkCreateFence = must("vkCreateFence")
+ funcs.vkDestroyFence = must("vkDestroyFence")
+ funcs.vkWaitForFences = must("vkWaitForFences")
+ funcs.vkResetFences = must("vkResetFences")
+ funcs.vkGetPhysicalDeviceProperties = must("vkGetPhysicalDeviceProperties")
+
+ funcs.vkGetPhysicalDeviceSurfaceSupportKHR = dlopen("vkGetPhysicalDeviceSurfaceSupportKHR")
+ funcs.vkDestroySurfaceKHR = dlopen("vkDestroySurfaceKHR")
+ funcs.vkGetPhysicalDeviceSurfaceFormatsKHR = dlopen("vkGetPhysicalDeviceSurfaceFormatsKHR")
+ funcs.vkGetPhysicalDeviceSurfacePresentModesKHR = dlopen("vkGetPhysicalDeviceSurfacePresentModesKHR")
+ funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR = dlopen("vkGetPhysicalDeviceSurfaceCapabilitiesKHR")
+
+ funcs.vkCreateSwapchainKHR = dlopen("vkCreateSwapchainKHR")
+ funcs.vkDestroySwapchainKHR = dlopen("vkDestroySwapchainKHR")
+ funcs.vkGetSwapchainImagesKHR = dlopen("vkGetSwapchainImagesKHR")
+ funcs.vkAcquireNextImageKHR = dlopen("vkAcquireNextImageKHR")
+ funcs.vkQueuePresentKHR = dlopen("vkQueuePresentKHR")
+
+ for _, f := range loadFuncs {
+ f(dlopen)
+ }
+ })
+ return loadErr
+}
+
+func CreateInstance(exts ...string) (Instance, error) {
+ if err := vkInit(); err != nil {
+ return nil, err
+ }
+ inf := C.VkInstanceCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ }
+ if len(exts) > 0 {
+ cexts := mallocCStringArr(exts)
+ defer freeCStringArr(cexts)
+ inf.enabledExtensionCount = C.uint32_t(len(exts))
+ inf.ppEnabledExtensionNames = &cexts[0]
+ }
+ var inst Instance
+ if err := vkErr(C.vkCreateInstance(funcs.vkCreateInstance, inf, nil, &inst)); err != nil {
+ return nil, fmt.Errorf("vulkan: vkCreateInstance: %w", err)
+ }
+ return inst, nil
+}
+
+func mallocCStringArr(s []string) []*C.char {
+ carr := make([]*C.char, len(s))
+ for i, ext := range s {
+ carr[i] = C.CString(ext)
+ }
+ return carr
+}
+
+func freeCStringArr(s []*C.char) {
+ for i := range s {
+ C.free(unsafe.Pointer(s[i]))
+ s[i] = nil
+ }
+}
+
+func DestroyInstance(inst Instance) {
+ C.vkDestroyInstance(funcs.vkDestroyInstance, inst, nil)
+}
+
+func GetPhysicalDeviceQueueFamilyProperties(pd PhysicalDevice) []QueueFamilyProperties {
+ var count C.uint32_t
+ C.vkGetPhysicalDeviceQueueFamilyProperties(funcs.vkGetPhysicalDeviceQueueFamilyProperties, pd, &count, nil)
+ if count == 0 {
+ return nil
+ }
+ queues := make([]C.VkQueueFamilyProperties, count)
+ C.vkGetPhysicalDeviceQueueFamilyProperties(funcs.vkGetPhysicalDeviceQueueFamilyProperties, pd, &count, &queues[0])
+ return queues
+}
+
+func EnumeratePhysicalDevices(inst Instance) ([]PhysicalDevice, error) {
+ var count C.uint32_t
+ if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, nil)); err != nil {
+ return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
+ }
+ if count == 0 {
+ return nil, nil
+ }
+ devs := make([]C.VkPhysicalDevice, count)
+ if err := vkErr(C.vkEnumeratePhysicalDevices(funcs.vkEnumeratePhysicalDevices, inst, &count, &devs[0])); err != nil {
+ return nil, fmt.Errorf("vulkan: vkEnumeratePhysicalDevices: %w", err)
+ }
+ return devs, nil
+}
+
+func ChoosePhysicalDevice(inst Instance, surf Surface) (PhysicalDevice, int, error) {
+ devs, err := EnumeratePhysicalDevices(inst)
+ if err != nil {
+ return nil, 0, err
+ }
+ for _, pd := range devs {
+ var props C.VkPhysicalDeviceProperties
+ C.vkGetPhysicalDeviceProperties(funcs.vkGetPhysicalDeviceProperties, pd, &props)
+ // The lavapipe software implementation doesn't work well rendering to a surface.
+ // See https://gitlab.freedesktop.org/mesa/mesa/-/issues/5473.
+ if surf != 0 && props.deviceType == C.VK_PHYSICAL_DEVICE_TYPE_CPU {
+ continue
+ }
+ const caps = C.VK_QUEUE_GRAPHICS_BIT | C.VK_QUEUE_COMPUTE_BIT
+ queueIdx, ok, err := chooseQueue(pd, surf, caps)
+ if err != nil {
+ return nil, 0, err
+ }
+ if !ok {
+ continue
+ }
+ if surf != nilSurface {
+ _, fmtFound, err := chooseFormat(pd, surf)
+ if err != nil {
+ return nil, 0, err
+ }
+ _, modFound, err := choosePresentMode(pd, surf)
+ if err != nil {
+ return nil, 0, err
+ }
+ if !fmtFound || !modFound {
+ continue
+ }
+ }
+ return pd, queueIdx, nil
+ }
+ return nil, 0, errors.New("vulkan: no suitable device found")
+}
+
+func CreateDeviceAndQueue(pd C.VkPhysicalDevice, queueIdx int, exts ...string) (Device, error) {
+ priority := C.float(1.0)
+ qinf := C.VkDeviceQueueCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+ queueCount: 1,
+ queueFamilyIndex: C.uint32_t(queueIdx),
+ pQueuePriorities: &priority,
+ }
+ inf := C.VkDeviceCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+ queueCreateInfoCount: 1,
+ enabledExtensionCount: C.uint32_t(len(exts)),
+ }
+ if len(exts) > 0 {
+ cexts := mallocCStringArr(exts)
+ defer freeCStringArr(cexts)
+ inf.ppEnabledExtensionNames = &cexts[0]
+ }
+ var dev Device
+ if err := vkErr(C.vkCreateDevice(funcs.vkCreateDevice, pd, inf, qinf, nil, &dev)); err != nil {
+ return nil, fmt.Errorf("vulkan: vkCreateDevice: %w", err)
+ }
+ return dev, nil
+}
+
+func GetDeviceQueue(d Device, queueFamily, queueIndex int) Queue {
+ var queue Queue
+ C.vkGetDeviceQueue(funcs.vkGetDeviceQueue, d, C.uint32_t(queueFamily), C.uint32_t(queueIndex), &queue)
+ return queue
+}
+
+func GetPhysicalDeviceSurfaceCapabilities(pd PhysicalDevice, surf Surface) (SurfaceCapabilities, error) {
+ var caps C.VkSurfaceCapabilitiesKHR
+ err := vkErr(C.vkGetPhysicalDeviceSurfaceCapabilitiesKHR(funcs.vkGetPhysicalDeviceSurfaceCapabilitiesKHR, pd, surf, &caps))
+ if err != nil {
+ return SurfaceCapabilities{}, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceCapabilitiesKHR: %w", err)
+ }
+ return caps, nil
+}
+
+func CreateSwapchain(pd PhysicalDevice, d Device, surf Surface, width, height int, old Swapchain) (Swapchain, []Image, Format, error) {
+ caps, err := GetPhysicalDeviceSurfaceCapabilities(pd, surf)
+ if err != nil {
+ return nilSwapchain, nil, 0, err
+ }
+ mode, modeOK, err := choosePresentMode(pd, surf)
+ if err != nil {
+ return nilSwapchain, nil, 0, err
+ }
+ format, fmtOK, err := chooseFormat(pd, surf)
+ if err != nil {
+ return nilSwapchain, nil, 0, err
+ }
+ if !modeOK || !fmtOK {
+ // This shouldn't happen because CreateDeviceAndQueue found at least
+ // one valid format and present mode.
+ return nilSwapchain, nil, 0, errors.New("vulkan: no valid format and present mode found")
+ }
+ // Find supported alpha composite mode. It doesn't matter which one, because rendering is
+ // always opaque.
+ alphaComp := C.VkCompositeAlphaFlagBitsKHR(1)
+ for caps.supportedCompositeAlpha&C.VkCompositeAlphaFlagsKHR(alphaComp) == 0 {
+ alphaComp <<= 1
+ }
+ trans := C.VkSurfaceTransformFlagBitsKHR(C.VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR)
+ if caps.supportedTransforms&C.VkSurfaceTransformFlagsKHR(trans) == 0 {
+ return nilSwapchain, nil, 0, errors.New("vulkan: VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR not supported")
+ }
+ inf := C.VkSwapchainCreateInfoKHR{
+ sType: C.VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR,
+ surface: surf,
+ minImageCount: caps.minImageCount,
+ imageFormat: format.format,
+ imageColorSpace: format.colorSpace,
+ imageExtent: C.VkExtent2D{width: C.uint32_t(width), height: C.uint32_t(height)},
+ imageArrayLayers: 1,
+ imageUsage: C.VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
+ imageSharingMode: C.VK_SHARING_MODE_EXCLUSIVE,
+ preTransform: trans,
+ presentMode: mode,
+ compositeAlpha: C.VkCompositeAlphaFlagBitsKHR(alphaComp),
+ clipped: C.VK_TRUE,
+ oldSwapchain: old,
+ }
+ var swchain Swapchain
+ if err := vkErr(C.vkCreateSwapchainKHR(funcs.vkCreateSwapchainKHR, d, &inf, nil, &swchain)); err != nil {
+ return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkCreateSwapchainKHR: %w", err)
+ }
+ var count C.uint32_t
+ if err := vkErr(C.vkGetSwapchainImagesKHR(funcs.vkGetSwapchainImagesKHR, d, swchain, &count, nil)); err != nil {
+ DestroySwapchain(d, swchain)
+ return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkGetSwapchainImagesKHR: %w", err)
+ }
+ if count == 0 {
+ DestroySwapchain(d, swchain)
+ return nilSwapchain, nil, 0, errors.New("vulkan: vkGetSwapchainImagesKHR returned no images")
+ }
+ imgs := make([]Image, count)
+ if err := vkErr(C.vkGetSwapchainImagesKHR(funcs.vkGetSwapchainImagesKHR, d, swchain, &count, &imgs[0])); err != nil {
+ DestroySwapchain(d, swchain)
+ return nilSwapchain, nil, 0, fmt.Errorf("vulkan: vkGetSwapchainImagesKHR: %w", err)
+ }
+ return swchain, imgs, format.format, nil
+}
+
+func DestroySwapchain(d Device, swchain Swapchain) {
+ C.vkDestroySwapchainKHR(funcs.vkDestroySwapchainKHR, d, swchain, nil)
+}
+
+func AcquireNextImage(d Device, swchain Swapchain, sem Semaphore, fence Fence) (int, error) {
+ res := C.vkAcquireNextImageKHR(funcs.vkAcquireNextImageKHR, d, swchain, math.MaxUint64, sem, fence)
+ if err := vkErr(res.res); err != nil {
+ return 0, fmt.Errorf("vulkan: vkAcquireNextImageKHR: %w", err)
+ }
+ return int(res.uint), nil
+}
+
+func PresentQueue(q Queue, swchain Swapchain, sem Semaphore, imgIdx int) error {
+ cidx := C.uint32_t(imgIdx)
+ inf := C.VkPresentInfoKHR{
+ sType: C.VK_STRUCTURE_TYPE_PRESENT_INFO_KHR,
+ swapchainCount: 1,
+ pSwapchains: &swchain,
+ pImageIndices: &cidx,
+ }
+ if sem != nilSemaphore {
+ inf.waitSemaphoreCount = 1
+ inf.pWaitSemaphores = &sem
+ }
+ if err := vkErr(C.vkQueuePresentKHR(funcs.vkQueuePresentKHR, q, inf)); err != nil {
+ return fmt.Errorf("vulkan: vkQueuePresentKHR: %w", err)
+ }
+ return nil
+}
+
+func CreateImageView(d Device, img Image, format Format) (ImageView, error) {
+ inf := C.VkImageViewCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ image: img,
+ viewType: C.VK_IMAGE_VIEW_TYPE_2D,
+ format: format,
+ subresourceRange: C.VkImageSubresourceRange{
+ aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
+ levelCount: C.VK_REMAINING_MIP_LEVELS,
+ layerCount: C.VK_REMAINING_ARRAY_LAYERS,
+ },
+ }
+ var view C.VkImageView
+ if err := vkErr(C.vkCreateImageView(funcs.vkCreateImageView, d, &inf, nil, &view)); err != nil {
+ return nilImageView, fmt.Errorf("vulkan: vkCreateImageView: %w", err)
+ }
+ return view, nil
+}
+
+func DestroyImageView(d Device, view ImageView) {
+ C.vkDestroyImageView(funcs.vkDestroyImageView, d, view, nil)
+}
+
+func CreateRenderPass(d Device, format Format, loadOp AttachmentLoadOp, initialLayout, finalLayout ImageLayout, passDeps []SubpassDependency) (RenderPass, error) {
+ att := C.VkAttachmentDescription{
+ format: format,
+ samples: C.VK_SAMPLE_COUNT_1_BIT,
+ loadOp: loadOp,
+ storeOp: C.VK_ATTACHMENT_STORE_OP_STORE,
+ stencilLoadOp: C.VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ stencilStoreOp: C.VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ initialLayout: initialLayout,
+ finalLayout: finalLayout,
+ }
+
+ ref := C.VkAttachmentReference{
+ attachment: 0,
+ layout: C.VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ }
+
+ sub := C.VkSubpassDescription{
+ pipelineBindPoint: C.VK_PIPELINE_BIND_POINT_GRAPHICS,
+ colorAttachmentCount: 1,
+ pColorAttachments: &ref,
+ }
+
+ inf := C.VkRenderPassCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ attachmentCount: 1,
+ pAttachments: &att,
+ subpassCount: 1,
+ }
+ if n := len(passDeps); n > 0 {
+ inf.dependencyCount = C.uint32_t(n)
+ inf.pDependencies = &passDeps[0]
+ }
+
+ var pass RenderPass
+ if err := vkErr(C.vkCreateRenderPass(funcs.vkCreateRenderPass, d, inf, sub, nil, &pass)); err != nil {
+ return nilRenderPass, fmt.Errorf("vulkan: vkCreateRenderPass: %w", err)
+ }
+ return pass, nil
+}
+
+func DestroyRenderPass(d Device, r RenderPass) {
+ C.vkDestroyRenderPass(funcs.vkDestroyRenderPass, d, r, nil)
+}
+
+func CreateFramebuffer(d Device, rp RenderPass, view ImageView, width, height int) (Framebuffer, error) {
+ inf := C.VkFramebufferCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ renderPass: rp,
+ attachmentCount: 1,
+ pAttachments: &view,
+ width: C.uint32_t(width),
+ height: C.uint32_t(height),
+ layers: 1,
+ }
+ var fbo Framebuffer
+ if err := vkErr(C.vkCreateFramebuffer(funcs.vkCreateFramebuffer, d, inf, nil, &fbo)); err != nil {
+ return nilFramebuffer, fmt.Errorf("vulkan: vkCreateFramebuffer: %w", err)
+ }
+ return fbo, nil
+
+}
+
+func DestroyFramebuffer(d Device, f Framebuffer) {
+ C.vkDestroyFramebuffer(funcs.vkDestroyFramebuffer, d, f, nil)
+}
+
+func DeviceWaitIdle(d Device) error {
+ if err := vkErr(C.vkDeviceWaitIdle(funcs.vkDeviceWaitIdle, d)); err != nil {
+ return fmt.Errorf("vulkan: vkDeviceWaitIdle: %w", err)
+ }
+ return nil
+}
+
+func QueueWaitIdle(q Queue) error {
+ if err := vkErr(C.vkQueueWaitIdle(funcs.vkQueueWaitIdle, q)); err != nil {
+ return fmt.Errorf("vulkan: vkQueueWaitIdle: %w", err)
+ }
+ return nil
+}
+
+func CreateSemaphore(d Device) (Semaphore, error) {
+ inf := C.VkSemaphoreCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
+ }
+ var sem Semaphore
+ err := vkErr(C.vkCreateSemaphore(funcs.vkCreateSemaphore, d, &inf, nil, &sem))
+ if err != nil {
+ return nilSemaphore, fmt.Errorf("vulkan: vkCreateSemaphore: %w", err)
+ }
+ return sem, err
+}
+
+func DestroySemaphore(d Device, sem Semaphore) {
+ C.vkDestroySemaphore(funcs.vkDestroySemaphore, d, sem, nil)
+}
+
+func DestroyDevice(dev Device) {
+ C.vkDestroyDevice(funcs.vkDestroyDevice, dev, nil)
+}
+
+func DestroySurface(inst Instance, s Surface) {
+ C.vkDestroySurfaceKHR(funcs.vkDestroySurfaceKHR, inst, s, nil)
+}
+
+func CreateCommandPool(d Device, queueIndex int) (CommandPool, error) {
+ inf := C.VkCommandPoolCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO,
+ queueFamilyIndex: C.uint32_t(queueIndex),
+ flags: C.VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | C.VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT,
+ }
+
+ var pool CommandPool
+ if err := vkErr(C.vkCreateCommandPool(funcs.vkCreateCommandPool, d, &inf, nil, &pool)); err != nil {
+ return nilCommandPool, fmt.Errorf("vulkan: vkCreateCommandPool: %w", err)
+ }
+ return pool, nil
+}
+
+func DestroyCommandPool(d Device, pool CommandPool) {
+ C.vkDestroyCommandPool(funcs.vkDestroyCommandPool, d, pool, nil)
+}
+
+func AllocateCommandBuffer(d Device, pool CommandPool) (CommandBuffer, error) {
+ inf := C.VkCommandBufferAllocateInfo{
+ sType: C.VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
+ commandPool: pool,
+ level: C.VK_COMMAND_BUFFER_LEVEL_PRIMARY,
+ commandBufferCount: 1,
+ }
+
+ var buf CommandBuffer
+ if err := vkErr(C.vkAllocateCommandBuffers(funcs.vkAllocateCommandBuffers, d, &inf, &buf)); err != nil {
+ return nil, fmt.Errorf("vulkan: vkAllocateCommandBuffers: %w", err)
+ }
+ return buf, nil
+}
+
+func FreeCommandBuffers(d Device, pool CommandPool, bufs ...CommandBuffer) {
+ if len(bufs) == 0 {
+ return
+ }
+ C.vkFreeCommandBuffers(funcs.vkFreeCommandBuffers, d, pool, C.uint32_t(len(bufs)), &bufs[0])
+}
+
+func BeginCommandBuffer(buf CommandBuffer) error {
+ inf := C.VkCommandBufferBeginInfo{
+ sType: C.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
+ flags: C.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
+ }
+ if err := vkErr(C.vkBeginCommandBuffer(funcs.vkBeginCommandBuffer, buf, inf)); err != nil {
+ return fmt.Errorf("vulkan: vkBeginCommandBuffer: %w", err)
+ }
+ return nil
+}
+
+func EndCommandBuffer(buf CommandBuffer) error {
+ if err := vkErr(C.vkEndCommandBuffer(funcs.vkEndCommandBuffer, buf)); err != nil {
+ return fmt.Errorf("vulkan: vkEndCommandBuffer: %w", err)
+ }
+ return nil
+}
+
+func QueueSubmit(q Queue, buf CommandBuffer, waitSems []Semaphore, waitStages []PipelineStageFlags, sigSems []Semaphore, fence Fence) error {
+ inf := C.VkSubmitInfo{
+ sType: C.VK_STRUCTURE_TYPE_SUBMIT_INFO,
+ commandBufferCount: 1,
+ pCommandBuffers: &buf,
+ }
+ if len(waitSems) > 0 {
+ if len(waitSems) != len(waitStages) {
+ panic("len(waitSems) != len(waitStages)")
+ }
+ inf.waitSemaphoreCount = C.uint32_t(len(waitSems))
+ inf.pWaitSemaphores = &waitSems[0]
+ inf.pWaitDstStageMask = &waitStages[0]
+ }
+ if len(sigSems) > 0 {
+ inf.signalSemaphoreCount = C.uint32_t(len(sigSems))
+ inf.pSignalSemaphores = &sigSems[0]
+ }
+ if err := vkErr(C.vkQueueSubmit(funcs.vkQueueSubmit, q, inf, fence)); err != nil {
+ return fmt.Errorf("vulkan: vkQueueSubmit: %w", err)
+ }
+ return nil
+}
+
+func CmdBeginRenderPass(buf CommandBuffer, rp RenderPass, fbo Framebuffer, width, height int, clearCol [4]float32) {
+ cclearCol := [4]C.float{C.float(clearCol[0]), C.float(clearCol[1]), C.float(clearCol[2]), C.float(clearCol[3])}
+ inf := C.VkRenderPassBeginInfo{
+ sType: C.VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ renderPass: rp,
+ framebuffer: fbo,
+ renderArea: C.VkRect2D{extent: C.VkExtent2D{width: C.uint32_t(width), height: C.uint32_t(height)}},
+ clearValueCount: 1,
+ pClearValues: (*C.VkClearValue)(unsafe.Pointer(&cclearCol)),
+ }
+ C.vkCmdBeginRenderPass(funcs.vkCmdBeginRenderPass, buf, inf, C.VK_SUBPASS_CONTENTS_INLINE)
+}
+
+func CmdEndRenderPass(buf CommandBuffer) {
+ C.vkCmdEndRenderPass(funcs.vkCmdEndRenderPass, buf)
+}
+
+func CmdCopyBuffer(cmdBuf CommandBuffer, src, dst Buffer, srcOff, dstOff, size int) {
+ C.vkCmdCopyBuffer(funcs.vkCmdCopyBuffer, cmdBuf, src, dst, 1, &C.VkBufferCopy{
+ srcOffset: C.VkDeviceSize(srcOff),
+ dstOffset: C.VkDeviceSize(dstOff),
+ size: C.VkDeviceSize(size),
+ })
+}
+
+func CmdCopyBufferToImage(cmdBuf CommandBuffer, src Buffer, dst Image, layout ImageLayout, copy BufferImageCopy) {
+ C.vkCmdCopyBufferToImage(funcs.vkCmdCopyBufferToImage, cmdBuf, src, dst, layout, 1, &copy)
+}
+
+func CmdPipelineBarrier(cmdBuf CommandBuffer, srcStage, dstStage PipelineStageFlags, flags DependencyFlags, memBarriers []MemoryBarrier, bufBarriers []BufferMemoryBarrier, imgBarriers []ImageMemoryBarrier) {
+ var memPtr *MemoryBarrier
+ if len(memBarriers) > 0 {
+ memPtr = &memBarriers[0]
+ }
+ var bufPtr *BufferMemoryBarrier
+ if len(bufBarriers) > 0 {
+ bufPtr = &bufBarriers[0]
+ }
+ var imgPtr *ImageMemoryBarrier
+ if len(imgBarriers) > 0 {
+ imgPtr = &imgBarriers[0]
+ }
+ C.vkCmdPipelineBarrier(funcs.vkCmdPipelineBarrier, cmdBuf, srcStage, dstStage, flags,
+ C.uint32_t(len(memBarriers)), memPtr,
+ C.uint32_t(len(bufBarriers)), bufPtr,
+ C.uint32_t(len(imgBarriers)), imgPtr)
+}
+
+func CmdPushConstants(cmdBuf CommandBuffer, layout PipelineLayout, stages ShaderStageFlags, offset int, data []byte) {
+ if len(data) == 0 {
+ return
+ }
+ C.vkCmdPushConstants(funcs.vkCmdPushConstants, cmdBuf, layout, stages, C.uint32_t(offset), C.uint32_t(len(data)), unsafe.Pointer(&data[0]))
+}
+
+func CmdBindPipeline(cmdBuf CommandBuffer, bindPoint PipelineBindPoint, pipe Pipeline) {
+ C.vkCmdBindPipeline(funcs.vkCmdBindPipeline, cmdBuf, bindPoint, pipe)
+}
+
+func CmdBindVertexBuffers(cmdBuf CommandBuffer, first int, buffers []Buffer, sizes []DeviceSize) {
+ if len(buffers) == 0 {
+ return
+ }
+ C.vkCmdBindVertexBuffers(funcs.vkCmdBindVertexBuffers, cmdBuf, C.uint32_t(first), C.uint32_t(len(buffers)), &buffers[0], &sizes[0])
+}
+
+func CmdSetViewport(cmdBuf CommandBuffer, first int, viewports ...Viewport) {
+ if len(viewports) == 0 {
+ return
+ }
+ C.vkCmdSetViewport(funcs.vkCmdSetViewport, cmdBuf, C.uint32_t(first), C.uint32_t(len(viewports)), &viewports[0])
+}
+
+func CmdBindIndexBuffer(cmdBuf CommandBuffer, buffer Buffer, offset int, typ IndexType) {
+ C.vkCmdBindIndexBuffer(funcs.vkCmdBindIndexBuffer, cmdBuf, buffer, C.VkDeviceSize(offset), typ)
+}
+
+func CmdDraw(cmdBuf CommandBuffer, vertCount, instCount, firstVert, firstInst int) {
+ C.vkCmdDraw(funcs.vkCmdDraw, cmdBuf, C.uint32_t(vertCount), C.uint32_t(instCount), C.uint32_t(firstVert), C.uint32_t(firstInst))
+}
+
+func CmdDrawIndexed(cmdBuf CommandBuffer, idxCount, instCount, firstIdx, vertOff, firstInst int) {
+ C.vkCmdDrawIndexed(funcs.vkCmdDrawIndexed, cmdBuf, C.uint32_t(idxCount), C.uint32_t(instCount), C.uint32_t(firstIdx), C.int32_t(vertOff), C.uint32_t(firstInst))
+}
+
+func GetPhysicalDeviceFormatProperties(physDev PhysicalDevice, format Format) FormatFeatureFlags {
+ var props C.VkFormatProperties
+ C.vkGetPhysicalDeviceFormatProperties(funcs.vkGetPhysicalDeviceFormatProperties, physDev, format, &props)
+ return FormatFeatureFlags(props.optimalTilingFeatures)
+}
+
+func CmdBindDescriptorSets(cmdBuf CommandBuffer, point PipelineBindPoint, layout PipelineLayout, firstSet int, sets []DescriptorSet) {
+ C.vkCmdBindDescriptorSets(funcs.vkCmdBindDescriptorSets, cmdBuf, point, layout, C.uint32_t(firstSet), C.uint32_t(len(sets)), &sets[0], 0, nil)
+}
+
+func CmdCopyImage(cmdBuf CommandBuffer, src Image, srcLayout ImageLayout, dst Image, dstLayout ImageLayout, regions []ImageCopy) {
+ if len(regions) == 0 {
+ return
+ }
+ C.vkCmdCopyImage(funcs.vkCmdCopyImage, cmdBuf, src, srcLayout, dst, dstLayout, C.uint32_t(len(regions)), &regions[0])
+}
+
+func CmdCopyImageToBuffer(cmdBuf CommandBuffer, src Image, srcLayout ImageLayout, dst Buffer, regions []BufferImageCopy) {
+ if len(regions) == 0 {
+ return
+ }
+ C.vkCmdCopyImageToBuffer(funcs.vkCmdCopyImageToBuffer, cmdBuf, src, srcLayout, dst, C.uint32_t(len(regions)), &regions[0])
+}
+
+func CmdDispatch(cmdBuf CommandBuffer, x, y, z int) {
+ C.vkCmdDispatch(funcs.vkCmdDispatch, cmdBuf, C.uint32_t(x), C.uint32_t(y), C.uint32_t(z))
+}
+
+func CreateImage(pd PhysicalDevice, d Device, format Format, width, height int, usage ImageUsageFlags) (Image, DeviceMemory, error) {
+ inf := C.VkImageCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+ imageType: C.VK_IMAGE_TYPE_2D,
+ format: format,
+ extent: C.VkExtent3D{
+ width: C.uint32_t(width),
+ height: C.uint32_t(height),
+ depth: 1,
+ },
+ mipLevels: 1,
+ arrayLayers: 1,
+ samples: C.VK_SAMPLE_COUNT_1_BIT,
+ tiling: C.VK_IMAGE_TILING_OPTIMAL,
+ usage: usage,
+ initialLayout: C.VK_IMAGE_LAYOUT_UNDEFINED,
+ }
+ var img C.VkImage
+ if err := vkErr(C.vkCreateImage(funcs.vkCreateImage, d, &inf, nil, &img)); err != nil {
+ return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkCreateImage: %w", err)
+ }
+ var memReqs C.VkMemoryRequirements
+ C.vkGetImageMemoryRequirements(funcs.vkGetImageMemoryRequirements, d, img, &memReqs)
+
+ memIdx, found := findMemoryTypeIndex(pd, memReqs.memoryTypeBits, C.VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ if !found {
+ DestroyImage(d, img)
+ return nilImage, nilDeviceMemory, errors.New("vulkan: no memory type suitable for images found")
+ }
+
+ memInf := C.VkMemoryAllocateInfo{
+ sType: C.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ allocationSize: memReqs.size,
+ memoryTypeIndex: C.uint32_t(memIdx),
+ }
+ var imgMem C.VkDeviceMemory
+ if err := vkErr(C.vkAllocateMemory(funcs.vkAllocateMemory, d, &memInf, nil, &imgMem)); err != nil {
+ DestroyImage(d, img)
+ return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkAllocateMemory: %w", err)
+ }
+
+ if err := vkErr(C.vkBindImageMemory(funcs.vkBindImageMemory, d, img, imgMem, 0)); err != nil {
+ FreeMemory(d, imgMem)
+ DestroyImage(d, img)
+ return nilImage, nilDeviceMemory, fmt.Errorf("vulkan: vkBindImageMemory: %w", err)
+ }
+ return img, imgMem, nil
+}
+
+func DestroyImage(d Device, img Image) {
+ C.vkDestroyImage(funcs.vkDestroyImage, d, img, nil)
+}
+
+func FreeMemory(d Device, mem DeviceMemory) {
+ C.vkFreeMemory(funcs.vkFreeMemory, d, mem, nil)
+}
+
+func CreateSampler(d Device, minFilter, magFilter Filter) (Sampler, error) {
+ inf := C.VkSamplerCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
+ minFilter: minFilter,
+ magFilter: magFilter,
+ addressModeU: C.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+ addressModeV: C.VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,
+ }
+ var s C.VkSampler
+ if err := vkErr(C.vkCreateSampler(funcs.vkCreateSampler, d, &inf, nil, &s)); err != nil {
+ return nilSampler, fmt.Errorf("vulkan: vkCreateSampler: %w", err)
+ }
+ return s, nil
+}
+
+func DestroySampler(d Device, sampler Sampler) {
+ C.vkDestroySampler(funcs.vkDestroySampler, d, sampler, nil)
+}
+
+func CreateBuffer(pd PhysicalDevice, d Device, size int, usage BufferUsageFlags, props MemoryPropertyFlags) (Buffer, DeviceMemory, error) {
+ inf := C.VkBufferCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
+ size: C.VkDeviceSize(size),
+ usage: usage,
+ }
+ var buf C.VkBuffer
+ if err := vkErr(C.vkCreateBuffer(funcs.vkCreateBuffer, d, &inf, nil, &buf)); err != nil {
+ return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkCreateBuffer: %w", err)
+ }
+
+ var memReqs C.VkMemoryRequirements
+ C.vkGetBufferMemoryRequirements(funcs.vkGetBufferMemoryRequirements, d, buf, &memReqs)
+
+ memIdx, found := findMemoryTypeIndex(pd, memReqs.memoryTypeBits, props)
+ if !found {
+ DestroyBuffer(d, buf)
+ return nilBuffer, nilDeviceMemory, errors.New("vulkan: no memory suitable for buffers found")
+ }
+ memInf := C.VkMemoryAllocateInfo{
+ sType: C.VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
+ allocationSize: memReqs.size,
+ memoryTypeIndex: C.uint32_t(memIdx),
+ }
+
+ var mem C.VkDeviceMemory
+ if err := vkErr(C.vkAllocateMemory(funcs.vkAllocateMemory, d, &memInf, nil, &mem)); err != nil {
+ DestroyBuffer(d, buf)
+ return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkAllocateMemory: %w", err)
+ }
+
+ if err := vkErr(C.vkBindBufferMemory(funcs.vkBindBufferMemory, d, buf, mem, 0)); err != nil {
+ FreeMemory(d, mem)
+ DestroyBuffer(d, buf)
+ return nilBuffer, nilDeviceMemory, fmt.Errorf("vulkan: vkBindBufferMemory: %w", err)
+ }
+ return buf, mem, nil
+}
+
+func DestroyBuffer(d Device, buf Buffer) {
+ C.vkDestroyBuffer(funcs.vkDestroyBuffer, d, buf, nil)
+}
+
+func CreateShaderModule(d Device, spirv string) (ShaderModule, error) {
+ ptr := unsafe.Pointer((*reflect.StringHeader)(unsafe.Pointer(&spirv)).Data)
+ inf := C.VkShaderModuleCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO,
+ codeSize: C.size_t(len(spirv)),
+ pCode: (*C.uint32_t)(ptr),
+ }
+
+ var mod C.VkShaderModule
+ if err := vkErr(C.vkCreateShaderModule(funcs.vkCreateShaderModule, d, inf, nil, &mod)); err != nil {
+ return nilShaderModule, fmt.Errorf("vulkan: vkCreateShaderModule: %w", err)
+ }
+ return mod, nil
+}
+
+func DestroyShaderModule(d Device, mod ShaderModule) {
+ C.vkDestroyShaderModule(funcs.vkDestroyShaderModule, d, mod, nil)
+}
+
+func CreateGraphicsPipeline(d Device, pass RenderPass, vmod, fmod ShaderModule, blend bool, srcFactor, dstFactor BlendFactor, topology PrimitiveTopology, bindings []VertexInputBindingDescription, attrs []VertexInputAttributeDescription, layout PipelineLayout) (Pipeline, error) {
+ main := C.CString("main")
+ defer C.free(unsafe.Pointer(main))
+ stages := []C.VkPipelineShaderStageCreateInfo{
+ {
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ stage: C.VK_SHADER_STAGE_VERTEX_BIT,
+ module: vmod,
+ pName: main,
+ },
+ {
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ stage: C.VK_SHADER_STAGE_FRAGMENT_BIT,
+ module: fmod,
+ pName: main,
+ },
+ }
+ dynStates := []C.VkDynamicState{C.VK_DYNAMIC_STATE_VIEWPORT}
+ dynInf := C.VkPipelineDynamicStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,
+ dynamicStateCount: C.uint32_t(len(dynStates)),
+ pDynamicStates: &dynStates[0],
+ }
+ const maxDim = 0x7fffffff
+ scissors := []C.VkRect2D{{extent: C.VkExtent2D{width: maxDim, height: maxDim}}}
+ viewportInf := C.VkPipelineViewportStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,
+ viewportCount: 1,
+ scissorCount: C.uint32_t(len(scissors)),
+ pScissors: &scissors[0],
+ }
+ enable := C.VkBool32(0)
+ if blend {
+ enable = 1
+ }
+ attBlendInf := C.VkPipelineColorBlendAttachmentState{
+ blendEnable: enable,
+ srcColorBlendFactor: srcFactor,
+ srcAlphaBlendFactor: srcFactor,
+ dstColorBlendFactor: dstFactor,
+ dstAlphaBlendFactor: dstFactor,
+ colorBlendOp: C.VK_BLEND_OP_ADD,
+ alphaBlendOp: C.VK_BLEND_OP_ADD,
+ colorWriteMask: C.VK_COLOR_COMPONENT_R_BIT | C.VK_COLOR_COMPONENT_G_BIT | C.VK_COLOR_COMPONENT_B_BIT | C.VK_COLOR_COMPONENT_A_BIT,
+ }
+ blendInf := C.VkPipelineColorBlendStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
+ attachmentCount: 1,
+ pAttachments: &attBlendInf,
+ }
+ var vkBinds []C.VkVertexInputBindingDescription
+ var vkAttrs []C.VkVertexInputAttributeDescription
+ for _, b := range bindings {
+ vkBinds = append(vkBinds, C.VkVertexInputBindingDescription{
+ binding: C.uint32_t(b.Binding),
+ stride: C.uint32_t(b.Stride),
+ })
+ }
+ for _, a := range attrs {
+ vkAttrs = append(vkAttrs, C.VkVertexInputAttributeDescription{
+ location: C.uint32_t(a.Location),
+ binding: C.uint32_t(a.Binding),
+ format: a.Format,
+ offset: C.uint32_t(a.Offset),
+ })
+ }
+ vertexInf := C.VkPipelineVertexInputStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
+ }
+ if n := len(vkBinds); n > 0 {
+ vertexInf.vertexBindingDescriptionCount = C.uint32_t(n)
+ vertexInf.pVertexBindingDescriptions = &vkBinds[0]
+ }
+ if n := len(vkAttrs); n > 0 {
+ vertexInf.vertexAttributeDescriptionCount = C.uint32_t(n)
+ vertexInf.pVertexAttributeDescriptions = &vkAttrs[0]
+ }
+ inf := C.VkGraphicsPipelineCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
+ stageCount: C.uint32_t(len(stages)),
+ pStages: &stages[0],
+ renderPass: pass,
+ layout: layout,
+ pRasterizationState: &C.VkPipelineRasterizationStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
+ lineWidth: 1.0,
+ },
+ pMultisampleState: &C.VkPipelineMultisampleStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
+ rasterizationSamples: C.VK_SAMPLE_COUNT_1_BIT,
+ },
+ pInputAssemblyState: &C.VkPipelineInputAssemblyStateCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
+ topology: topology,
+ },
+ }
+
+ var pipe C.VkPipeline
+ if err := vkErr(C.vkCreateGraphicsPipelines(funcs.vkCreateGraphicsPipelines, d, nilPipelineCache, inf, dynInf, blendInf, vertexInf, viewportInf, nil, &pipe)); err != nil {
+ return nilPipeline, fmt.Errorf("vulkan: vkCreateGraphicsPipelines: %w", err)
+ }
+ return pipe, nil
+}
+
+func DestroyPipeline(d Device, p Pipeline) {
+ C.vkDestroyPipeline(funcs.vkDestroyPipeline, d, p, nil)
+}
+
+func CreatePipelineLayout(d Device, pushRanges []PushConstantRange, sets []DescriptorSetLayout) (PipelineLayout, error) {
+ inf := C.VkPipelineLayoutCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
+ }
+ if n := len(sets); n > 0 {
+ inf.setLayoutCount = C.uint32_t(n)
+ inf.pSetLayouts = &sets[0]
+ }
+ if n := len(pushRanges); n > 0 {
+ inf.pushConstantRangeCount = C.uint32_t(n)
+ inf.pPushConstantRanges = &pushRanges[0]
+ }
+ var l C.VkPipelineLayout
+ if err := vkErr(C.vkCreatePipelineLayout(funcs.vkCreatePipelineLayout, d, inf, nil, &l)); err != nil {
+ return nilPipelineLayout, fmt.Errorf("vulkan: vkCreatePipelineLayout: %w", err)
+ }
+ return l, nil
+}
+
+func DestroyPipelineLayout(d Device, l PipelineLayout) {
+ C.vkDestroyPipelineLayout(funcs.vkDestroyPipelineLayout, d, l, nil)
+}
+
+func CreateDescriptorSetLayout(d Device, bindings []DescriptorSetLayoutBinding) (DescriptorSetLayout, error) {
+ var vkbinds []C.VkDescriptorSetLayoutBinding
+ for _, b := range bindings {
+ vkbinds = append(vkbinds, C.VkDescriptorSetLayoutBinding{
+ binding: C.uint32_t(b.Binding),
+ descriptorType: b.DescriptorType,
+ descriptorCount: 1,
+ stageFlags: b.StageFlags,
+ })
+ }
+ inf := C.VkDescriptorSetLayoutCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
+ }
+ if n := len(vkbinds); n > 0 {
+ inf.bindingCount = C.uint32_t(len(vkbinds))
+ inf.pBindings = &vkbinds[0]
+ }
+ var l C.VkDescriptorSetLayout
+ if err := vkErr(C.vkCreateDescriptorSetLayout(funcs.vkCreateDescriptorSetLayout, d, inf, nil, &l)); err != nil {
+ return nilDescriptorSetLayout, fmt.Errorf("vulkan: vkCreateDescriptorSetLayout: %w", err)
+ }
+ return l, nil
+}
+
+func DestroyDescriptorSetLayout(d Device, l DescriptorSetLayout) {
+ C.vkDestroyDescriptorSetLayout(funcs.vkDestroyDescriptorSetLayout, d, l, nil)
+}
+
+func MapMemory(d Device, mem DeviceMemory, offset, size int) ([]byte, error) {
+ var ptr unsafe.Pointer
+ if err := vkErr(C.vkMapMemory(funcs.vkMapMemory, d, mem, C.VkDeviceSize(offset), C.VkDeviceSize(size), 0, &ptr)); err != nil {
+ return nil, fmt.Errorf("vulkan: vkMapMemory: %w", err)
+ }
+ return ((*[1 << 30]byte)(ptr))[:size:size], nil
+}
+
+func UnmapMemory(d Device, mem DeviceMemory) {
+ C.vkUnmapMemory(funcs.vkUnmapMemory, d, mem)
+}
+
+func ResetCommandBuffer(buf CommandBuffer) error {
+ if err := vkErr(C.vkResetCommandBuffer(funcs.vkResetCommandBuffer, buf, 0)); err != nil {
+ return fmt.Errorf("vulkan: vkResetCommandBuffer. %w", err)
+ }
+ return nil
+}
+
+func CreateDescriptorPool(d Device, maxSets int, sizes []DescriptorPoolSize) (DescriptorPool, error) {
+ inf := C.VkDescriptorPoolCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
+ maxSets: C.uint32_t(maxSets),
+ poolSizeCount: C.uint32_t(len(sizes)),
+ pPoolSizes: &sizes[0],
+ }
+ var pool C.VkDescriptorPool
+ if err := vkErr(C.vkCreateDescriptorPool(funcs.vkCreateDescriptorPool, d, inf, nil, &pool)); err != nil {
+ return nilDescriptorPool, fmt.Errorf("vulkan: vkCreateDescriptorPool: %w", err)
+ }
+ return pool, nil
+}
+
+func DestroyDescriptorPool(d Device, pool DescriptorPool) {
+ C.vkDestroyDescriptorPool(funcs.vkDestroyDescriptorPool, d, pool, nil)
+}
+
+func ResetDescriptorPool(d Device, pool DescriptorPool) error {
+ if err := vkErr(C.vkResetDescriptorPool(funcs.vkResetDescriptorPool, d, pool, 0)); err != nil {
+ return fmt.Errorf("vulkan: vkResetDescriptorPool: %w", err)
+ }
+ return nil
+}
+
+func UpdateDescriptorSet(d Device, write WriteDescriptorSet) {
+ C.vkUpdateDescriptorSets(funcs.vkUpdateDescriptorSets, d, write, 0, nil)
+}
+
+func AllocateDescriptorSet(d Device, pool DescriptorPool, layout DescriptorSetLayout) (DescriptorSet, error) {
+ inf := C.VkDescriptorSetAllocateInfo{
+ sType: C.VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
+ descriptorPool: pool,
+ descriptorSetCount: 1,
+ pSetLayouts: &layout,
+ }
+ var set C.VkDescriptorSet
+ if err := vkErr(C.vkAllocateDescriptorSets(funcs.vkAllocateDescriptorSets, d, inf, &set)); err != nil {
+ return nilDescriptorSet, fmt.Errorf("vulkan: vkAllocateDescriptorSets: %w", err)
+ }
+ return set, nil
+}
+
+func CreateComputePipeline(d Device, mod ShaderModule, layout PipelineLayout) (Pipeline, error) {
+ main := C.CString("main")
+ defer C.free(unsafe.Pointer(main))
+ inf := C.VkComputePipelineCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
+ stage: C.VkPipelineShaderStageCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
+ stage: C.VK_SHADER_STAGE_COMPUTE_BIT,
+ module: mod,
+ pName: main,
+ },
+ layout: layout,
+ }
+ var pipe C.VkPipeline
+ if err := vkErr(C.vkCreateComputePipelines(funcs.vkCreateComputePipelines, d, nilPipelineCache, 1, &inf, nil, &pipe)); err != nil {
+ return nilPipeline, fmt.Errorf("vulkan: vkCreateComputePipelines: %w", err)
+ }
+ return pipe, nil
+}
+
+func CreateFence(d Device) (Fence, error) {
+ inf := C.VkFenceCreateInfo{
+ sType: C.VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
+ }
+ var f C.VkFence
+ if err := vkErr(C.vkCreateFence(funcs.vkCreateFence, d, &inf, nil, &f)); err != nil {
+ return nilFence, fmt.Errorf("vulkan: vkCreateFence: %w", err)
+ }
+ return f, nil
+}
+
+func DestroyFence(d Device, f Fence) {
+ C.vkDestroyFence(funcs.vkDestroyFence, d, f, nil)
+}
+
+func WaitForFences(d Device, fences ...Fence) error {
+ if len(fences) == 0 {
+ return nil
+ }
+ err := vkErr(C.vkWaitForFences(funcs.vkWaitForFences, d, C.uint32_t(len(fences)), &fences[0], C.VK_TRUE, 0xffffffffffffffff))
+ if err != nil {
+ return fmt.Errorf("vulkan: vkWaitForFences: %w", err)
+ }
+ return nil
+}
+
+func ResetFences(d Device, fences ...Fence) error {
+ if len(fences) == 0 {
+ return nil
+ }
+ err := vkErr(C.vkResetFences(funcs.vkResetFences, d, C.uint32_t(len(fences)), &fences[0]))
+ if err != nil {
+ return fmt.Errorf("vulkan: vkResetFences: %w", err)
+ }
+ return nil
+}
+
+func BuildSubpassDependency(srcStage, dstStage PipelineStageFlags, srcMask, dstMask AccessFlags, flags DependencyFlags) SubpassDependency {
+ return C.VkSubpassDependency{
+ srcSubpass: C.VK_SUBPASS_EXTERNAL,
+ srcStageMask: srcStage,
+ srcAccessMask: srcMask,
+ dstSubpass: 0,
+ dstStageMask: dstStage,
+ dstAccessMask: dstMask,
+ dependencyFlags: flags,
+ }
+}
+
+func BuildPushConstantRange(stages ShaderStageFlags, offset, size int) PushConstantRange {
+ return C.VkPushConstantRange{
+ stageFlags: stages,
+ offset: C.uint32_t(offset),
+ size: C.uint32_t(size),
+ }
+}
+
+func BuildDescriptorPoolSize(typ DescriptorType, count int) DescriptorPoolSize {
+ return C.VkDescriptorPoolSize{
+ _type: typ,
+ descriptorCount: C.uint32_t(count),
+ }
+}
+
+func BuildWriteDescriptorSetImage(set DescriptorSet, binding int, typ DescriptorType, sampler Sampler, view ImageView, layout ImageLayout) WriteDescriptorSet {
+ return C.VkWriteDescriptorSet{
+ sType: C.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ dstSet: set,
+ dstBinding: C.uint32_t(binding),
+ descriptorCount: 1,
+ descriptorType: typ,
+ pImageInfo: &C.VkDescriptorImageInfo{
+ sampler: sampler,
+ imageView: view,
+ imageLayout: layout,
+ },
+ }
+}
+
+func BuildWriteDescriptorSetBuffer(set DescriptorSet, binding int, typ DescriptorType, buf Buffer) WriteDescriptorSet {
+ return C.VkWriteDescriptorSet{
+ sType: C.VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
+ dstSet: set,
+ dstBinding: C.uint32_t(binding),
+ descriptorCount: 1,
+ descriptorType: typ,
+ pBufferInfo: &C.VkDescriptorBufferInfo{
+ buffer: buf,
+ _range: C.VK_WHOLE_SIZE,
+ },
+ }
+}
+
+func (r PushConstantRange) StageFlags() ShaderStageFlags {
+ return r.stageFlags
+}
+
+func (r PushConstantRange) Offset() int {
+ return int(r.offset)
+}
+
+func (r PushConstantRange) Size() int {
+ return int(r.size)
+}
+
+func (p QueueFamilyProperties) Flags() QueueFlags {
+ return p.queueFlags
+}
+
+func (c SurfaceCapabilities) MinExtent() image.Point {
+ return image.Pt(int(c.minImageExtent.width), int(c.minImageExtent.height))
+}
+
+func (c SurfaceCapabilities) MaxExtent() image.Point {
+ return image.Pt(int(c.maxImageExtent.width), int(c.maxImageExtent.height))
+}
+
+func BuildViewport(x, y, width, height float32) Viewport {
+ return C.VkViewport{
+ x: C.float(x),
+ y: C.float(y),
+ width: C.float(width),
+ height: C.float(height),
+ maxDepth: 1.0,
+ }
+}
+
+func BuildImageMemoryBarrier(img Image, srcMask, dstMask AccessFlags, oldLayout, newLayout ImageLayout) ImageMemoryBarrier {
+ return C.VkImageMemoryBarrier{
+ sType: C.VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
+ srcAccessMask: srcMask,
+ dstAccessMask: dstMask,
+ oldLayout: oldLayout,
+ newLayout: newLayout,
+ image: img,
+ subresourceRange: C.VkImageSubresourceRange{
+ aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
+ levelCount: C.VK_REMAINING_MIP_LEVELS,
+ layerCount: C.VK_REMAINING_ARRAY_LAYERS,
+ },
+ }
+}
+
+func BuildBufferMemoryBarrier(buf Buffer, srcMask, dstMask AccessFlags) BufferMemoryBarrier {
+ return C.VkBufferMemoryBarrier{
+ sType: C.VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,
+ srcAccessMask: srcMask,
+ dstAccessMask: dstMask,
+ buffer: buf,
+ size: C.VK_WHOLE_SIZE,
+ }
+}
+
+func BuildMemoryBarrier(srcMask, dstMask AccessFlags) MemoryBarrier {
+ return C.VkMemoryBarrier{
+ sType: C.VK_STRUCTURE_TYPE_MEMORY_BARRIER,
+ srcAccessMask: srcMask,
+ dstAccessMask: dstMask,
+ }
+}
+
+func BuildBufferImageCopy(bufOff, bufStride, x, y, width, height int) BufferImageCopy {
+ return C.VkBufferImageCopy{
+ bufferOffset: C.VkDeviceSize(bufOff),
+ bufferRowLength: C.uint32_t(bufStride),
+ imageSubresource: C.VkImageSubresourceLayers{
+ aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
+ layerCount: 1,
+ },
+ imageOffset: C.VkOffset3D{
+ x: C.int32_t(x), y: C.int32_t(y), z: 0,
+ },
+ imageExtent: C.VkExtent3D{
+ width: C.uint32_t(width), height: C.uint32_t(height), depth: 1,
+ },
+ }
+}
+
+func BuildImageCopy(srcX, srcY, dstX, dstY, width, height int) ImageCopy {
+ return C.VkImageCopy{
+ srcSubresource: C.VkImageSubresourceLayers{
+ aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
+ layerCount: 1,
+ },
+ srcOffset: C.VkOffset3D{
+ x: C.int32_t(srcX),
+ y: C.int32_t(srcY),
+ },
+ dstSubresource: C.VkImageSubresourceLayers{
+ aspectMask: C.VK_IMAGE_ASPECT_COLOR_BIT,
+ layerCount: 1,
+ },
+ dstOffset: C.VkOffset3D{
+ x: C.int32_t(dstX),
+ y: C.int32_t(dstY),
+ },
+ extent: C.VkExtent3D{
+ width: C.uint32_t(width),
+ height: C.uint32_t(height),
+ depth: 1,
+ },
+ }
+}
+
+func findMemoryTypeIndex(pd C.VkPhysicalDevice, constraints C.uint32_t, wantProps C.VkMemoryPropertyFlags) (int, bool) {
+ var memProps C.VkPhysicalDeviceMemoryProperties
+ C.vkGetPhysicalDeviceMemoryProperties(funcs.vkGetPhysicalDeviceMemoryProperties, pd, &memProps)
+
+ for i := 0; i < int(memProps.memoryTypeCount); i++ {
+ if (constraints & (1 << i)) == 0 {
+ continue
+ }
+ if (memProps.memoryTypes[i].propertyFlags & wantProps) != wantProps {
+ continue
+ }
+ return i, true
+ }
+
+ return 0, false
+}
+
+func choosePresentMode(pd C.VkPhysicalDevice, surf Surface) (C.VkPresentModeKHR, bool, error) {
+ var count C.uint32_t
+ err := vkErr(C.vkGetPhysicalDeviceSurfacePresentModesKHR(funcs.vkGetPhysicalDeviceSurfacePresentModesKHR, pd, surf, &count, nil))
+ if err != nil {
+ return 0, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfacePresentModesKHR: %w", err)
+ }
+ if count == 0 {
+ return 0, false, nil
+ }
+ modes := make([]C.VkPresentModeKHR, count)
+ err = vkErr(C.vkGetPhysicalDeviceSurfacePresentModesKHR(funcs.vkGetPhysicalDeviceSurfacePresentModesKHR, pd, surf, &count, &modes[0]))
+ if err != nil {
+ return 0, false, fmt.Errorf("vulkan: kGetPhysicalDeviceSurfacePresentModesKHR: %w", err)
+ }
+ for _, m := range modes {
+ if m == C.VK_PRESENT_MODE_MAILBOX_KHR || m == C.VK_PRESENT_MODE_FIFO_KHR {
+ return m, true, nil
+ }
+ }
+ return 0, false, nil
+}
+
+func chooseFormat(pd C.VkPhysicalDevice, surf Surface) (C.VkSurfaceFormatKHR, bool, error) {
+ var count C.uint32_t
+ err := vkErr(C.vkGetPhysicalDeviceSurfaceFormatsKHR(funcs.vkGetPhysicalDeviceSurfaceFormatsKHR, pd, surf, &count, nil))
+ if err != nil {
+ return C.VkSurfaceFormatKHR{}, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceFormatsKHR: %w", err)
+ }
+ if count == 0 {
+ return C.VkSurfaceFormatKHR{}, false, nil
+ }
+ formats := make([]C.VkSurfaceFormatKHR, count)
+ err = vkErr(C.vkGetPhysicalDeviceSurfaceFormatsKHR(funcs.vkGetPhysicalDeviceSurfaceFormatsKHR, pd, surf, &count, &formats[0]))
+ if err != nil {
+ return C.VkSurfaceFormatKHR{}, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceFormatsKHR: %w", err)
+ }
+ // Query for format with sRGB support.
+ // TODO: Support devices without sRGB.
+ for _, f := range formats {
+ if f.colorSpace != C.VK_COLOR_SPACE_SRGB_NONLINEAR_KHR {
+ continue
+ }
+ switch f.format {
+ case C.VK_FORMAT_B8G8R8A8_SRGB, C.VK_FORMAT_R8G8B8A8_SRGB:
+ return f, true, nil
+ }
+ }
+ return C.VkSurfaceFormatKHR{}, false, nil
+}
+
+func chooseQueue(pd C.VkPhysicalDevice, surf Surface, flags C.VkQueueFlags) (int, bool, error) {
+ queues := GetPhysicalDeviceQueueFamilyProperties(pd)
+ for i, q := range queues {
+ // Check for presentation and feature support.
+ if q.queueFlags&flags != flags {
+ continue
+ }
+ if surf != nilSurface {
+ // Check for presentation support. It is possible that a device has no
+ // queue with both rendering and presentation support, but not in reality.
+ // See https://github.com/KhronosGroup/Vulkan-Docs/issues/1234.
+ var support C.VkBool32
+ if err := vkErr(C.vkGetPhysicalDeviceSurfaceSupportKHR(funcs.vkGetPhysicalDeviceSurfaceSupportKHR, pd, C.uint32_t(i), surf, &support)); err != nil {
+ return 0, false, fmt.Errorf("vulkan: vkGetPhysicalDeviceSurfaceSupportKHR: %w", err)
+ }
+ if support != C.VK_TRUE {
+ continue
+ }
+ }
+ return i, true, nil
+ }
+ return 0, false, nil
+}
+
+func dlsym(handle unsafe.Pointer, s string) unsafe.Pointer {
+ cs := C.CString(s)
+ defer C.free(unsafe.Pointer(cs))
+ return C.dlsym(handle, cs)
+}
+
+func dlopen(lib string) unsafe.Pointer {
+ clib := C.CString(lib)
+ defer C.free(unsafe.Pointer(clib))
+ return C.dlopen(clib, C.RTLD_NOW|C.RTLD_LOCAL)
+}
+
+func vkErr(res C.VkResult) error {
+ switch res {
+ case C.VK_SUCCESS:
+ return nil
+ default:
+ return Error(res)
+ }
+}
+
+func (e Error) Error() string {
+ return fmt.Sprintf("error %d", e)
+}
diff --git a/vendor/gioui.org/internal/vk/vulkan_android.go b/vendor/gioui.org/internal/vk/vulkan_android.go
new file mode 100644
index 0000000..143146e
--- /dev/null
+++ b/vendor/gioui.org/internal/vk/vulkan_android.go
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build !nowayland
+// +build !nowayland
+
+package vk
+
+/*
+#define VK_USE_PLATFORM_ANDROID_KHR
+#define VK_NO_PROTOTYPES 1
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#include <android/native_window.h>
+#include <vulkan/vulkan.h>
+
+static VkResult vkCreateAndroidSurfaceKHR(PFN_vkCreateAndroidSurfaceKHR f, VkInstance instance, const VkAndroidSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ return f(instance, pCreateInfo, pAllocator, pSurface);
+}
+*/
+import "C"
+import (
+ "fmt"
+ "unsafe"
+)
+
+var wlFuncs struct {
+ vkCreateAndroidSurfaceKHR C.PFN_vkCreateAndroidSurfaceKHR
+}
+
+func init() {
+ loadFuncs = append(loadFuncs, func(dlopen func(name string) *[0]byte) {
+ wlFuncs.vkCreateAndroidSurfaceKHR = dlopen("vkCreateAndroidSurfaceKHR")
+ })
+}
+
+func CreateAndroidSurface(inst Instance, window unsafe.Pointer) (Surface, error) {
+ inf := C.VkAndroidSurfaceCreateInfoKHR{
+ sType: C.VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR,
+ window: (*C.ANativeWindow)(window),
+ }
+ var surf Surface
+ if err := vkErr(C.vkCreateAndroidSurfaceKHR(wlFuncs.vkCreateAndroidSurfaceKHR, inst, &inf, nil, &surf)); err != nil {
+ return 0, fmt.Errorf("vulkan: vkCreateAndroidSurfaceKHR: %w", err)
+ }
+ return surf, nil
+}
diff --git a/vendor/gioui.org/internal/vk/vulkan_wayland.go b/vendor/gioui.org/internal/vk/vulkan_wayland.go
new file mode 100644
index 0000000..cb057bc
--- /dev/null
+++ b/vendor/gioui.org/internal/vk/vulkan_wayland.go
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build ((linux && !android) || freebsd) && !nowayland
+// +build linux,!android freebsd
+// +build !nowayland
+
+package vk
+
+/*
+#define VK_USE_PLATFORM_WAYLAND_KHR
+#define VK_NO_PROTOTYPES 1
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#include <vulkan/vulkan.h>
+
+static VkResult vkCreateWaylandSurfaceKHR(PFN_vkCreateWaylandSurfaceKHR f, VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ return f(instance, pCreateInfo, pAllocator, pSurface);
+}
+*/
+import "C"
+import (
+ "fmt"
+ "unsafe"
+)
+
+var wlFuncs struct {
+ vkCreateWaylandSurfaceKHR C.PFN_vkCreateWaylandSurfaceKHR
+}
+
+func init() {
+ loadFuncs = append(loadFuncs, func(dlopen func(name string) *[0]byte) {
+ wlFuncs.vkCreateWaylandSurfaceKHR = dlopen("vkCreateWaylandSurfaceKHR")
+ })
+}
+
+func CreateWaylandSurface(inst Instance, disp unsafe.Pointer, wlSurf unsafe.Pointer) (Surface, error) {
+ inf := C.VkWaylandSurfaceCreateInfoKHR{
+ sType: C.VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR,
+ display: (*C.struct_wl_display)(disp),
+ surface: (*C.struct_wl_surface)(wlSurf),
+ }
+ var surf Surface
+ if err := vkErr(C.vkCreateWaylandSurfaceKHR(wlFuncs.vkCreateWaylandSurfaceKHR, inst, &inf, nil, &surf)); err != nil {
+ return 0, fmt.Errorf("vulkan: vkCreateWaylandSurfaceKHR: %w", err)
+ }
+ return surf, nil
+}
diff --git a/vendor/gioui.org/internal/vk/vulkan_x11.go b/vendor/gioui.org/internal/vk/vulkan_x11.go
new file mode 100644
index 0000000..780a5d5
--- /dev/null
+++ b/vendor/gioui.org/internal/vk/vulkan_x11.go
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+//go:build ((linux && !android) || freebsd) && !nox11
+// +build linux,!android freebsd
+// +build !nox11
+
+package vk
+
+/*
+#define VK_USE_PLATFORM_XLIB_KHR
+#define VK_NO_PROTOTYPES 1
+#define VK_DEFINE_NON_DISPATCHABLE_HANDLE(object) typedef uint64_t object;
+#include <vulkan/vulkan.h>
+
+static VkResult vkCreateXlibSurfaceKHR(PFN_vkCreateXlibSurfaceKHR f, VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
+ return f(instance, pCreateInfo, pAllocator, pSurface);
+}
+*/
+import "C"
+import (
+ "fmt"
+ "unsafe"
+)
+
+var x11Funcs struct {
+ vkCreateXlibSurfaceKHR C.PFN_vkCreateXlibSurfaceKHR
+}
+
+func init() {
+ loadFuncs = append(loadFuncs, func(dlopen func(name string) *[0]byte) {
+ x11Funcs.vkCreateXlibSurfaceKHR = dlopen("vkCreateXlibSurfaceKHR")
+ })
+}
+
+func CreateXlibSurface(inst Instance, dpy unsafe.Pointer, window uintptr) (Surface, error) {
+ inf := C.VkXlibSurfaceCreateInfoKHR{
+ sType: C.VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ dpy: (*C.Display)(dpy),
+ window: (C.Window)(window),
+ }
+ var surf Surface
+ if err := vkErr(C.vkCreateXlibSurfaceKHR(x11Funcs.vkCreateXlibSurfaceKHR, inst, &inf, nil, &surf)); err != nil {
+ return 0, fmt.Errorf("vulkan: vkCreateXlibSurfaceKHR: %w", err)
+ }
+ return surf, nil
+}