surface/registry.go

Functions Structs

Functions

func Available

Available returns names of all available backends sorted by priority.

func (r *Registry) Available() []string {
	r.mu.RLock()
	defer r.mu.RUnlock()

	return r.sortedNames(true)
}

func Available

Available returns names of all available backends sorted by priority.

func Available() []string {
	return globalRegistry.Available()
}

func Error

func (e *BackendUnavailableError) Error() string {
	return "surface: backend unavailable: " + e.Name
}

func Error

func (e *BackendNotFoundError) Error() string {
	return "surface: backend not found: " + e.Name
}

func Get

Get returns information about a specific backend.

func (r *Registry) Get(name string) (*RegistryEntry, bool) {
	r.mu.RLock()
	defer r.mu.RUnlock()

	entry, ok := r.entries[name]
	if !ok {
		return nil, false
	}

	// Return a copy to prevent modification
	entryCopy := *entry
	return &entryCopy, true
}

func Get

Get returns information about a specific backend.

func Get(name string) (*RegistryEntry, bool) {
	return globalRegistry.Get(name)
}

func List

List returns all registered backend names sorted by priority.

func (r *Registry) List() []string {
	r.mu.RLock()
	defer r.mu.RUnlock()

	return r.sortedNames(false)
}

func List

List returns all registered backend names sorted by priority (highest first).

func List() []string {
	return globalRegistry.List()
}

func NewRegistry

NewRegistry creates a new empty registry.

Most code should use the global registry via Register and NewSurface.

func NewRegistry() *Registry {
	return &Registry{
		entries: make(map[string]*RegistryEntry),
	}
}

func NewSurface

NewSurface creates a surface using the best available backend.

Returns an error if no backends are available.

func NewSurface(width, height int) (Surface, error) {
	return globalRegistry.NewSurface(Options{Width: width, Height: height})
}

func NewSurface

NewSurface creates a surface using the best available backend.

func (r *Registry) NewSurface(opts Options) (Surface, error) {
	r.mu.RLock()
	available := r.sortedNames(true)
	r.mu.RUnlock()

	if len(available) == 0 {
		return nil, ErrNoBackendAvailable
	}

	// Try each available backend in priority order
	var lastErr error
	for _, name := range available {
		s, err := r.NewSurfaceByName(name, opts)
		if err == nil {
			return s, nil
		}
		lastErr = err
	}

	if lastErr != nil {
		return nil, lastErr
	}
	return nil, ErrNoBackendAvailable
}

func NewSurfaceByName

NewSurfaceByName creates a surface using a specific named backend.

func NewSurfaceByName(name string, width, height int) (Surface, error) {
	return globalRegistry.NewSurfaceByName(name, Options{Width: width, Height: height})
}

func NewSurfaceByName

NewSurfaceByName creates a surface using a specific backend.

func (r *Registry) NewSurfaceByName(name string, opts Options) (Surface, error) {
	r.mu.RLock()
	entry, ok := r.entries[name]
	r.mu.RUnlock()

	if !ok {
		return nil, &BackendNotFoundError{Name: name}
	}

	if !entry.Available() {
		return nil, &BackendUnavailableError{Name: name}
	}

	return entry.Factory(opts)
}

func NewSurfaceByNameWithOptions

NewSurfaceByNameWithOptions creates a surface using a specific backend.

func NewSurfaceByNameWithOptions(name string, opts Options) (Surface, error) {
	return globalRegistry.NewSurfaceByName(name, opts)
}

func NewSurfaceWithOptions

NewSurfaceWithOptions creates a surface using the best available backend.

func NewSurfaceWithOptions(opts Options) (Surface, error) {
	return globalRegistry.NewSurface(opts)
}

func Register

Register adds a backend to this registry.

func (r *Registry) Register(name string, priority int, factory SurfaceFactory, available func() bool) {
	r.mu.Lock()
	defer r.mu.Unlock()

	if r.entries == nil {
		r.entries = make(map[string]*RegistryEntry)
	}

	if available == nil {
		available = func() bool { return true }
	}

	r.entries[name] = &RegistryEntry{
		Name:		name,
		Priority:	priority,
		Factory:	factory,
		Available:	available,
	}
}

func Register

Register adds a backend to the global registry.

 

Parameters:

- name: unique identifier (e.g., "vulkan", "metal", "software")

- priority: selection priority (higher = preferred)

- factory: function to create surface instances

- available: function to check if backend is available

 

If available is nil, the backend is assumed always available.

Registering a name that already exists replaces the previous entry.

func Register(name string, priority int, factory SurfaceFactory, available func() bool) {
	globalRegistry.Register(name, priority, factory, available)
}

func Unregister

Unregister removes a backend from this registry.

func (r *Registry) Unregister(name string) {
	r.mu.Lock()
	defer r.mu.Unlock()

	delete(r.entries, name)
}

func Unregister

Unregister removes a backend from the global registry.

func Unregister(name string) {
	globalRegistry.Unregister(name)
}

Structs

type RegistryEntry struct

RegistryEntry represents a registered surface backend.

type RegistryEntry struct {
	// Name is the unique identifier for this backend.
	Name	string

	// Priority determines selection order (higher = preferred).
	// Standard priorities:
	//   - 100: GPU backends (Vulkan, Metal, D3D12)
	//   - 50: Hardware-accelerated software (WARP)
	//   - 10: Pure software backends
	Priority	int

	// Factory creates surface instances.
	Factory	SurfaceFactory

	// Available reports if the backend is available on this system.
	// This is called during registration and cached.
	Available	func() bool
}

type Registry struct

Registry manages registered surface backends.

 

The registry enables third-party backends to register themselves

without requiring changes to the core library (RFC #46).

 

Example registration:

 

func init() {

surface.Register("vulkan", 100, vulkanFactory, vulkanAvailable)

}

 

Example usage:

 

s, err := surface.NewSurfaceByName("vulkan", 800, 600)

// or auto-select best available:

s, err := surface.NewSurface(800, 600)

type Registry struct {
	mu	sync.RWMutex
	entries	map[string]*RegistryEntry
}

type BackendNotFoundError struct

BackendNotFoundError indicates a named backend is not registered.

type BackendNotFoundError struct {
	Name string
}

type BackendUnavailableError struct

BackendUnavailableError indicates a backend exists but is not available.

type BackendUnavailableError struct {
	Name string
}