Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.18.0] - 2026-05-09

### Added

- **SubpixelLayout on PlatformProvider** (ADR-024) — `SubpixelLayout()` method returns display subpixel arrangement (`SubpixelNone`, `SubpixelRGB`, `SubpixelBGR`, `SubpixelVRGB`, `SubpixelVBGR`). Enables LCD/ClearType font rendering in gg. Follows Qt6 `QPlatformScreen::SubpixelAntialiasingType` pattern — subpixel is a display/OS property, not GPU. `NullPlatformProvider` returns `SubpixelNone` (grayscale AA). Researched Qt6, GTK4/Wayland, FreeType, DRM/KMS — all treat subpixel as platform property.

### Fixed

- **Lint:** extracted `stringNone` reuse for SubpixelLayout.String().

## [0.17.0] - 2026-05-06

### Added
Expand Down
4 changes: 3 additions & 1 deletion ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

`gpucontext` is the shared foundation for the [gogpu](https://github.com/gogpu) ecosystem, providing interfaces and utilities for GPU resource sharing without circular dependencies.

## Current: v0.16.0
## Current: v0.18.0

- SubpixelLayout on PlatformProvider (ADR-024, LCD/ClearType auto-detection)
- AdapterInfo on DeviceProvider (ADR-020, render mode auto-selection)
- WindowChrome.SetFullscreen / IsFullscreen (ADR-018, runtime fullscreen toggle)
- CursorMode (Locked/Confined/Normal) for mouse grab / pointer lock
- PointerEvent.DeltaX/DeltaY for relative mouse movement
Expand Down
52 changes: 52 additions & 0 deletions platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,55 @@ type PlatformProvider interface {
// FontScale returns the user's font size preference multiplier.
// 1.0 = default system font size. Used to scale Sp (scale-independent pixels).
FontScale() float32

// SubpixelLayout returns the display's subpixel arrangement for LCD text rendering.
// Used by 2D graphics libraries (gg) to enable ClearType-quality font rendering.
// Returns SubpixelNone when subpixel info is unavailable or on HiDPI displays
// where subpixels are too small to be visible.
SubpixelLayout() SubpixelLayout
}

// SubpixelLayout describes the physical arrangement of RGB subpixels on a display.
// Used for LCD/ClearType font rendering to achieve sharper text by exploiting
// the subpixel structure. Qt6 (QPlatformScreen), Wayland (wl_output.geometry),
// and DRM/KMS (drmModeConnector) all expose this as a display property.
type SubpixelLayout int

const (
// SubpixelNone means no subpixel information is available or applicable.
// Text rendering falls back to grayscale anti-aliasing.
// Used on HiDPI displays where subpixels are too small to exploit.
SubpixelNone SubpixelLayout = iota

// SubpixelRGB is horizontal RGB ordering (most common: Windows LCD, most external monitors).
SubpixelRGB

// SubpixelBGR is horizontal BGR ordering (some Samsung and older displays).
SubpixelBGR

// SubpixelVRGB is vertical RGB ordering (rare, some rotated displays).
SubpixelVRGB

// SubpixelVBGR is vertical BGR ordering (rare).
SubpixelVBGR
)

// String returns the subpixel layout name for debugging.
func (s SubpixelLayout) String() string {
switch s {
case SubpixelNone:
return stringNone
case SubpixelRGB:
return "RGB"
case SubpixelBGR:
return "BGR"
case SubpixelVRGB:
return "VRGB"
case SubpixelVBGR:
return "VBGR"
default:
return "Unknown"
}
}

// CursorShape represents the mouse cursor shape.
Expand Down Expand Up @@ -205,5 +254,8 @@ func (NullPlatformProvider) HighContrast() bool { return false }
// FontScale returns 1.0.
func (NullPlatformProvider) FontScale() float32 { return 1.0 }

// SubpixelLayout returns SubpixelNone (grayscale AA).
func (NullPlatformProvider) SubpixelLayout() SubpixelLayout { return SubpixelNone }

// Ensure NullPlatformProvider implements PlatformProvider.
var _ PlatformProvider = NullPlatformProvider{}
11 changes: 6 additions & 5 deletions platform_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,12 @@ func (m *mockPlatformProvider) ClipboardWrite(text string) error {
m.clipboard = text
return nil
}
func (m *mockPlatformProvider) SetCursor(cursor CursorShape) { m.cursor = cursor }
func (m *mockPlatformProvider) DarkMode() bool { return m.darkMode }
func (m *mockPlatformProvider) ReduceMotion() bool { return m.reduceMotion }
func (m *mockPlatformProvider) HighContrast() bool { return m.highContrast }
func (m *mockPlatformProvider) FontScale() float32 { return m.fontScale }
func (m *mockPlatformProvider) SetCursor(cursor CursorShape) { m.cursor = cursor }
func (m *mockPlatformProvider) DarkMode() bool { return m.darkMode }
func (m *mockPlatformProvider) ReduceMotion() bool { return m.reduceMotion }
func (m *mockPlatformProvider) HighContrast() bool { return m.highContrast }
func (m *mockPlatformProvider) FontScale() float32 { return m.fontScale }
func (m *mockPlatformProvider) SubpixelLayout() SubpixelLayout { return SubpixelRGB }

// Ensure mockPlatformProvider implements PlatformProvider.
var _ PlatformProvider = &mockPlatformProvider{}
Expand Down
Loading