diff --git a/CHANGELOG.md b/CHANGELOG.md index 7686e90..47ffe17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ 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.27.0] - 2026-08-10 + +### Added + +- **`SurfaceCompositor` interface** (ADR-067) — compositor-level bridge between gogpu and content renderers (gg, g3d). 4 methods: `ShouldPreserveContent()`, `DamageRects()`, `MarkContentRendered()`, `CompositeMSAAOverlay()`. Enables drawing library to delegate surface-level decisions (LoadOp, damage scissoring, MSAA overlay compositing) to the compositor without importing gogpu directly. Enterprise pattern validated by Chromium cc/Skia, GTK4 GSK, Flutter flow/ source code. + ## [0.26.0] - 2026-08-10 ### Changed diff --git a/compositor.go b/compositor.go new file mode 100644 index 0000000..8d6c1a4 --- /dev/null +++ b/compositor.go @@ -0,0 +1,49 @@ +// Copyright 2026 The gogpu Authors +// SPDX-License-Identifier: MIT + +package gpucontext + +import "image" + +// SurfaceCompositor is the interface for compositor-level decisions about +// surface rendering. The compositor (gogpu) owns the surface lifecycle +// and makes decisions about LoadOp, damage scissoring, and swapchain +// presentation. Content renderers (gg, g3d) use this interface to query +// compositor state when recording render passes. +// +// This cleanly separates compositor concerns (gogpu) from content rendering +// (gg). Before this interface, gg made compositor decisions internally +// (LoadOp, damage scissoring, MSAA overlay compositing). Now gogpu provides +// these decisions through the compositor, and gg records draws accordingly. +// +// ADR-067: surface composition architecture. +type SurfaceCompositor interface { + // ShouldPreserveContent reports whether the current render pass should + // use LoadOpLoad to preserve existing surface content. True when: + // - An earlier renderer already drew to the surface this frame + // - External content (g3d) has been rendered to the surface + // Content renderers use this to decide between LoadOpClear and LoadOpLoad. + ShouldPreserveContent() bool + + // DamageRects returns the damage rectangles for the current frame. + // When non-empty, the compositor has determined that only these regions + // need re-rendering. Content renderers should apply scissor rects + // accordingly. Empty means full-surface render. + DamageRects() []image.Rectangle + + // MarkContentRendered signals that a content renderer has drawn to the + // surface in the current frame. Subsequent renderers will see + // ShouldPreserveContent() == true. + MarkContentRendered() + + // CompositeMSAAOverlay requests the compositor to alpha-blend an MSAA + // overlay resolve texture onto the surface. The compositeView is the + // single-sample texture containing the resolved MSAA overlay. + // The compositor uses its own blit pipeline (independent of gg's pipelines) + // to prevent bind group lifetime conflicts. + // + // encoder is the shared frame encoder. view is the swapchain target. + // compositeView is the resolved MSAA overlay source. + // w, h are surface dimensions. + CompositeMSAAOverlay(encoder CommandEncoder, view TextureView, compositeView TextureView, w, h uint32) error +}