Skip to content

DisplayComposition

Nick Andrews edited this page Oct 24, 2026 · 5 revisions

Display Composition Implementation Plan

Status: WP0-WP4 and WP5.2-5.4 landed upstream (b72155e2bb, 2026-10-24), WP5.5 landed (8ded7e1869); WP5.1, 5.6 open (see section 4 and implementation-log.md) | Scope: AROS graphics subsystem, screen and window composition | Trees: rom/hidds/gfx, rom/graphics, rom/hyperlayers, rom/intuition, display drivers

This page defines the architecture for composition in AROS, the classes and interfaces that implement it, who owns each object and decision, and the phased work. It merges the screen-level composition proposal with the composited-layers (window-level) design, which share one compositor. Sections 2 and 3 describe the code as it is in the tree (2026-10-24); where the original design differs, the difference is stated in place.


1. Goals

  1. Composition is a service of the Display. Every Hidd_Display object owns a compositor. graphics.library and Intuition never talk to a compositor directly.
  2. One compositor, two levels. The same compositor composes whole screens (ViewPorts) and composited layers (windows) inside them, through one request model.
  3. Hardware where possible, software where not. A display advertises scan-out planes with their constraints. The compositor assigns composition requests to planes and blits the remainder. The base Display is a one-plane display, so every existing driver keeps working unchanged.
  4. AmigaOS semantics are preserved. Simple, smart and super-bitmap windows behave as before. Composited and alpha windows are opt-in. The screen bitmap remains authoritative for code that addresses it directly. Classic chipset displays degrade to today's behaviour.
  5. No upward dependencies. The compositor does not open intuition.library. layers.library stays a geometry manager. Drivers never see Intuition or layers structures.

2. Final architecture

2.1 Levels and ownership

    Intuition                              policy: which screens and windows exist,
      |-- screens --> ViewPorts            their order, position, opacity, flags
      '-- windows --> Layers
            |
    layers.library                         geometry: visible/occluding shapes,
            |                              composited-layer surfaces
            v
    graphics.library                       glue: builds HIDD_ViewPortData chains per
            |                              display, carries CompositeRequests, owns
            |                              framebuffer bookkeeping
            v
   +------------------ Hidd_Display (one per output) ---------------------------------+
   |  owns: DMEnum, Compositor, framebuffer, cursor, planes                           |
   |                                                                                  |
   |   Hidd_Compositor (policy)          Planes (mechanism, part of Hidd_Display)     |
   |   base = hybrid plane/blit          GetPlaneInfo / CommitPlanes / WaitLatch      |
   |   driver may subclass               base = one primary plane (== Show)           |
   +----------------------------------------------------------------------------------+
            |
            v
    Hidd_Gfx (driver)                      blits: CopyBox, CopyBoxMasked, CopyBoxAlpha
Object / decision Owner Created by Lifetime
Hidd_Display object driver (Hidd_Gfx subclass) driver New driver
Hidd_DMEnum Display Display::New Display
Hidd_Compositor object Display Display::New (driver class via aHidd_Display_CompositorClass, else base class) Display
Framebuffer bitmap Display (attribute aHidd_Display_FrameBuffer), still created by graphics.library (display_FBCreate) when FrameBufferType != None; moving the creation into Display::New was not done graphics.library at display setup Display
Plane set and constraints Display (driver subclass) static per hardware Display
Composition policy (which request goes to which plane, what is blitted, mode policy) Compositor - -
Screen stack, screen offsets, composition flags per screen Intuition OpenScreen, ScreenPosition, RethinkDisplay -
Window stack, layer shapes, composited-layer surfaces layers.library CreateLayerTagList layer
Per-display HIDD_ViewPortData chain and its CompositeRequests graphics.library MakeVPort, LayerSurfacesChanged() from layers.library ViewPort / layer
Damage propagation graphics.library -> Hidd_Display::UpdateRect -> its compositor's BitMapRectChanged update_bitmap() -
Software cursor Display - -

Rules that follow:

  • graphics.library calls HIDD_Display_* only. compositor_LoadViewPorts, compositor_ScrollBitMap, compositor_UpdateBitMap, DF_SoftComposit, compositor_Install/Setup and the display_compositor field are removed.
  • The compositor is reached only through its Display. Nothing outside rom/hidds/gfx and driver subclasses holds a compositor pointer.
  • Drivers implement planes, not composition. A driver that composes in hardware describes planes; it does not implement ShowViewPorts any more (kept for the transition only).
  • Intuition supplies per-screen and per-window composition parameters as data (VideoControl tags on the ViewPort, LA_* tags on the layer), never by being queried.

2.2 Data model: one composition request

Terminology: a surface is the bitmap of a composited layer (a window) presented inside its screen. An overlay is only ever a hardware plane type (vHidd_Plane_Overlay), never a window; the two words are not interchangeable anywhere in this plan.

A single request structure describes anything the compositor places on a display, whether a whole screen bitmap or a composited layer surface:

/* <hidd/gfx.h> */
struct HIDD_CompositeRequest
{
    struct HIDD_CompositeRequest *Next;   /* back to front within the parent */
    OOP_Object        *BitMap;            /* HIDD bitmap object to show */
    struct Rectangle   Src;               /* source rectangle in BitMap */
    struct Rectangle   Dest;              /* destination in display pixels; != Src size = scale */
    struct Region     *Shape;             /* display relative, NULL = Dest rectangle */
    UBYTE              Opacity;           /* 0..255 constant alpha */
    UBYTE              AlphaMode;         /* vHidd_CompAlpha_None | Fixed | PerPixel */
    UWORD              Flags;             /* CRF_OPAQUE, CRF_PLANE_OK, CRF_PLANE_REQUIRED, CRF_SCALED */
    ULONG              ZOrder;
    APTR               UserData;          /* compositor private */
};

struct HIDD_ViewPortData              /* existing, extended */
{
    struct HIDD_ViewPortData     *Next;
    OOP_Object                   *Bitmap;
    struct ViewPortExtra         *vpe;
    APTR                          UserData;
    OOP_Object                   *PreviousBitmap;
    ULONG                         Flags;
    /* new */
    ULONG                         CompFlags;      /* COMPF_* for this screen, from Intuition */
    struct Hook                  *PreAlphaHook;   /* SA_AlphaPreCompositingHook */
    struct HIDD_CompositeRequest *Surfaces;       /* composited layer surfaces of this screen */
};

The screen itself is implicitly a request (Bitmap, DxOffset/DyOffset, CompFlags); surfaces (composited layers) are explicit requests relative to the screen. The compositor flattens both into one Z-ordered list per display.

2.3 Composition pipeline

  1. Collect. graphics.library builds the per-display HIDD_ViewPortData chain (MakeVPort) and attaches each screen's surface list by reference (owned by the screen's Layer_Info).
  2. Submit. LoadView -> HIDD_Display_ShowViewPorts(chain). A driver that composes in hardware itself returns TRUE; the base class returns FALSE, and graphics.library then calls HIDD_Display_ComposeViewPorts(chain), which hands the chain to the compositor (BitMapStackChanged). Position changes -> HIDD_Display_ViewPortPositionChange. Surface structure changes -> graphics' private LayerSurfacesChanged() -> HIDD_Display_SurfaceStackChanged. Content changes -> graphics' update_bitmap() -> HIDD_Display_UpdateRect (method pointer cached per display) -> the compositor's BitMapRectChanged.
  3. Decide. Screens only are candidates for planes; composited layer surfaces are always blended into the composed bitmap. The compositor gives the frontmost screens the overlay planes, highest z first, while each screen passes HIDDCompositorPlaneFits() (format, scale range, alignment, size, never the framebuffer object, never a cursor plane). Z order is kept: once a screen gets no plane, every screen behind it is composed. The backmost screen always stays on the primary. Screens without a plane are drawn into the composed bitmap on the primary; when the first of them covers the display unscaled, without offset, alpha or surfaces, it is shown directly through Show() (passthrough, zero copy). ENV:SYS/compositor.prefs NOPLANES turns plane use off.
  4. Commit. HIDD_Display_CommitPlanes(states, count, flags) programs the overlay planes; the primary is driven by Show(). The DRM drivers apply the states one plane at a time (legacy drmModeSetPlane), not atomically. A refused commit currently switches planes off for the life of the Display (HIDDCompositorDisablePlanes); the compositor does not yet use fHidd_Commit_Test to fall back screen by screen (open, section 7).
  5. Report. The compositor answers MapCoords, which DisplayToBMCoords/BMToDisplayCoords call, and reports COMPF_SCALE in its state when screens are scaled, so Intuition converts coordinates (SF_ScaledCoords).

Mode policy is a compositor attribute (aHidd_Compositor_ModePolicy), selected by the prefs: FollowTop (default, the display switches to the frontmost screen's mode), ScaleLargest (prefs SCALE: the display takes the mode of the largest screen shown and smaller screens are scaled up to it) and Native (prefs SCALE NATIVEMODE: the display keeps its own highest mode and every screen is scaled).


3. Class specifications

Interface and attribute names follow the existing gfx.conf conventions. New marks additions; Moved marks items relocated from elsewhere; Removed marks deletions.

3.1 Hidd_Display (CLID_Hidd_Display, rom/hidds/gfx/gfx_displayclass.c)

Owner of composition for one output.

Attributes

Attribute Access Status Meaning
aHidd_Display_Compositor .SG in gfx.conf existing the compositor object, created by New; Display::Set ignores it (owned by the display)
aHidd_Display_CompositorClass I.. New driver supplies a compositor subclass; default base class
aHidd_Display_PlaneCount ..G New number of scan-out planes; base = 1
aHidd_Display_VBlankCount ..G New frame counter, 0 if unknown
aHidd_Display_DisplayID .SG New public display ID base, set by graphics.library at registration (the compositor reads it)
aHidd_Display_CompositionCapabilities, CompositionState ..G, .SG New the compositor's Capabilities/State, for graphics.library (getdisplayinfodata.c)
aHidd_Display_FrameBuffer .SG existing unchanged
aHidd_Display_DMEnumerator, GfxHidd, SpriteTypes, DPMSLevel, ConnectorType/ID, ... existing unchanged

Methods

Method Status Base implementation
ShowViewPorts(data) existing base returns FALSE (does not compose in hardware); drivers that do return TRUE
ComposeViewPorts(data, BOOL *composing) New called by graphics.library when ShowViewPorts returned FALSE: the compositor's BitMapStackChanged
UpdateRect(bm, x, y, w, h) New damage from graphics.library, forwarded to the compositor's BitMapRectChanged
ViewPortPositionChange(vpd, SIPTR *x, SIPTR *y) New compositor validates and applies; returns TRUE if composing
SurfaceStackChanged(vpd) New compositor re-flattens that screen's surfaces
GetPlaneInfo(ULONG idx, struct HIDD_PlaneInfo *, ULONG len) New one primary plane: any displayable format, unity scale, opaque only
CommitPlanes(struct HIDD_PlaneState *, ULONG count, ULONG flags) New one plane: equivalent to Show(state[0].BitMap)
WaitLatch() New returns immediately
DisplayToBMCoords / BMToDisplayCoords existing the compositor's MapCoords (scaled screens), identity otherwise
ModeProperties existing CompositionFlags filled from the compositor's capabilities
Show(bitmap, flags) existing kept as the one-plane commit primitive; drivers still override it
SetCursorShape/Pos/Visible existing base: software cursor in the Display; drivers with a hardware cursor override them and report it as a Cursor plane in GetPlaneInfo (never given to screens)
MakeViewPort, InitViewPorts, DeinitViewPort existing unchanged (copper-list style hooks)

Removed: the cached mid_CompositorSetCursorShape/Visible/Pos fields in HIDDDisplayData (gfx_display.h). They date from the 2026 split design, in which the Display was to delegate the software mouse pointer to its compositor and Display::Set cached the compositor's three cursor method IDs for the hot path. That delegation was never implemented: the merged tree renders the software cursor inside the Display class itself (the cursor_* functions in gfx_displayclass.c), the compositor interface has no cursor methods, and nothing reads the fields. The final architecture keeps the cursor a Display responsibility, backed by a Cursor plane where the hardware offers one, so the compositor will not own it later either. The fields are dead by design, not merely unused.

struct HIDD_PlaneInfo
{
    ULONG   Type;          /* vHidd_Plane_Primary | vHidd_Plane_Overlay | vHidd_Plane_Cursor */
    ULONG   ZMin, ZMax;
    ULONG   PixFmtMask;    /* bit per vHidd_StdPixFmt_* */
    ULONG   ScaleMin, ScaleMax;   /* 16.16; 0x10000/0x10000 = unity only */
    ULONG   AlphaModes;    /* bit per vHidd_CompAlpha_* */
    UWORD   PosAlignX, PosAlignY;
    UWORD   MaxWidth, MaxHeight;
    ULONG   Flags;         /* PIF_NEEDS_DISPLAYMEM, PIF_FULL_WIDTH_ONLY, PIF_VSPLIT_ONLY */
};

struct HIDD_PlaneState
{
    ULONG            Plane;
    OOP_Object      *BitMap;        /* NULL = disable */
    struct Rectangle Src, Dest;
    UBYTE            Opacity;
    UBYTE            AlphaMode;
    ULONG            ZOrder;
};
/* CommitPlanes flags */
#define fHidd_Commit_NoWait   (1 << 0)
#define fHidd_Commit_Test     (1 << 1)   /* validate only */

3.2 Hidd_Compositor (CLID_Hidd_Compositor, Moved to rom/hidds/gfx/gfx_compositorclass.c)

The policy object. Base class is the hybrid plane/blit compositor: the former software compositor (Devs/Monitors/Compositor, now deleted) with its intuition.library dependency removed and plane assignment, scaling and composited-layer surfaces added. Drivers may subclass to override policy (planned for amigavideo's copper-list stacking, WP5.6).

Interface: hidd.gfx.compositor (IID_Hidd_Compositor) is kept. The single definition is the system header; the driver-private copies of the interface in nouveau, IntelGMA and amigavideo, which carried an older and incompatible method table under the same string, are gone: nouveau's and IntelGMA's private compositors are deleted (WP0.7, WP5.5), amigavideo's uses its own private interface name until WP5.6, so one IID means one method table.

Attributes

Attribute Access Meaning
aHidd_Compositor_DisplayHidd I.G owning Display
aHidd_Compositor_DisplayID, FrameBuffer ..G read from the Display (no longer init tags)
aHidd_Compositor_Capabilities ..G COMPF_* the implementation can honour on this display (derived from planes + blit ability)
aHidd_Compositor_State ISG enabled subset (prefs)
aHidd_Compositor_ModePolicy ISG FollowTop / Native / ScaleLargest
aHidd_Compositor_BackFillHook ISG void-area fill
aHidd_Compositor_Active ..G TRUE when more than passthrough is in effect
aHidd_Compositor_ComposedBitMap ..G the blit target occupying the lowest plane, or NULL

Methods

Method Role
BitMapStackChanged(struct HIDD_ViewPortData *, BOOL *active) new chain; assign planes, redraw, commit
SurfaceStackChanged(struct HIDD_ViewPortData *) surfaces of one screen changed
BitMapPositionChange(OOP_Object *bm, SIPTR *x, SIPTR *y) validate/apply a screen offset
BitMapRectChanged(OOP_Object *bm, x, y, w, h) damage on a bitmap; no-op for plane-scanned screens
BitMapValidate(struct BitMap *), BitMapEnable(struct BitMap *) custom screen bitmaps (existing)
DisplayRectChanged(struct Rectangle *) kept as a mode-reselect hook (the planned DisplayChanged() rename was not done)
MapCoords(OOP_Object *bm, BOOL toDisplay, LONG *x, LONG *y) New: display <-> screen coordinates for scaled screens

Removed, and why:

  • aHidd_Compositor_DisplayID and aHidd_Compositor_FrameBuffer as init tags (done: both are now read-only and read from the Display). Before, graphics.library passes these because it creates the compositor and is the only party that knows the display's ID base and framebuffer object (compositor_Setup, graphics_compositor.c). Once the Display creates its own compositor (section 3.1), both values are the Display's own state: the framebuffer is aHidd_Display_FrameBuffer, and the ID base is needed only to allocate the composed bitmap with a valid DisplayID, which the compositor can request from its Display. Keeping them as tags would leave two sources of truth for values the Display already owns.
  • GetAttr(SA_CompositingFlags, screen) and GetAttr(SA_AlphaPreCompositingHook, screen) in StackChanged. The compositor currently finds the Intuition Screen behind each bitmap and asks it for the per-screen flags and hook. That is an upward dependency from a HIDD onto Intuition, it only works for bitmaps that belong to a screen, and it is why the compositor has to open intuition.library at all. In the final model those values arrive as data in HIDD_ViewPortData.CompFlags and PreAlphaHook, filled by graphics.library from the ViewPort (section 3.6), so any client that builds a View gets the same behaviour whether or not Intuition is involved.
  • OpenLibrary("intuition.library"). With the two queries above gone, the compositor has no remaining use for Intuition. Dropping the open removes the only upward link from gfx.hidd to Intuition, which is required for the class to live in ROM alongside graphics.library and to initialise before Intuition does (gfx.hidd resident priority 66 against Intuition's 15).

3.3 Hidd_BitMap (rom/hidds/gfx/gfx_bitmapclass.c)

Item Status Change
UpdateRect existing, unchanged damage reaches the compositor through Hidd_Display::UpdateRect (graphics.library calls the display, not the bitmap); the compositor calls the bitmap's UpdateRect where it shows the bitmap itself
aHidd_BitMap_LeftEdge/TopEdge existing remain the screen offset store
aHidd_BitMap_Compositable, Displayable existing unchanged

3.4 Hidd_Gfx (rom/hidds/gfx/gfx_hiddclass.c)

Method Status
CopyBox, CopyBoxMasked existing
CopyBoxAlpha(src, sx, sy, dst, dx, dy, w, h, opacity, gc) Done (landed 2026-09). Correct source-over including destination alpha; drivers with accelerated PutAlphaImage get it for free

3.5 layers.library (rom/hyperlayers)

A fourth layer kind, composited, alongside SIMPLE/SMART/SUPER. Private data:

struct IntLayer {
    struct Layer    lay;
    struct Hook    *shapehook;
    IPTR            window;
    ULONG           intflags;        /* + INTFLAG_TRANSLUCENT (composited and blended: occludes nothing) */
    struct RastPort rp;
    struct BitMap  *surface;         /* composited surface, or LAYERS_BACKING_SURFACE backing store */
    WORD            surfw, surfh;
    struct Region  *occludeshape;    /* what this layer hides from layers behind */
    struct HIDD_CompositeRequest request;  /* this layer's entry in the screen's surface list */
    struct Region  *compshape;       /* request.Shape when the visible part is not the whole rectangle */
    UBYTE           opacity;         /* 255 = opaque */
    BOOL            alphasurface;
    ULONG           alphaformat;     /* PIXFMT_* of an alpha surface */
    ULONG           surfbytes;       /* counted in the screen's surface budget */
};
Item Status Change
LAYERS_BACKING_SURFACE Done (commit d37d20f52c, default off) one layer-sized bitmap per smart layer; hidden ClipRects are views (CR_SHAREDBITMAP, CR_BMOFFX/Y)
LAYERCOMPOSITED flag bit (Layer.Flags bit 3) New, public (graphics/clip.h) graphics.library needs it to pick the offset formula
Tags LA_Composited, LA_Opacity, LA_AlphaSurface Done (graphics/layersext.h, LA_AROS + 5..7) LA_SurfaceBitMap (caller-supplied surface) was not implemented
SHAPEHOOKACTION_OPAQUEREGION not implemented shape hook would declare the opaque sub-region of a translucent layer; translucent layers occlude nothing
IsLayerHitAt(layer, x, y) LVO Done (layers 50.7) (after the six reserved MorphOS V52 slots that follow CollectPixelsLayer; MorphOS's own IsLayerHitable(layer) has a different signature and keeps its slot) alpha-aware hit test, also applied by WhichLayer()
ClipRect contract for composited layers New exactly one hidden ClipRect covering bounds, BitMap = surface
occludeshape in the seven Z-walks New translucent layers do not occlude
Presenter notifications Done UPDATE_SURFACES() at the end of Create/Delete/MoveSize/MoveLayerZ/ChangeVisibility/ChangeShape rebuilds the screen's surface list and calls graphics' private LayerSurfacesChanged(screenbm, list); composited layers skip _BackupPartsOfLayer/_ShowPartsOfLayer pixel shuffling
Fallback Done display that cannot present surfaces (CompositeLayersSupported() FALSE), surface budget exceeded (4 x screen bitmap, 4 MB free floor) or allocation failure -> SMART at creation; growth that does not fit converts the layer in place (_UncompositeLayer)

3.6 graphics.library (rom/graphics)

Item Status Change
display_LoadViewPorts shrink HIDD_Display_ShowViewPorts + framebuffer bookkeeping only
ScrollVPort change HIDD_Display_ViewPortPositionChange
update_bitmap() shrink HIDD_BM_UpdateRect only
graphics_compositor.c/.h, DF_SoftComposit, compositorClass, display_compositor Removed ownership moves to Display
getdisplayinfodata.c DimensionInfo.reserved[0] change capabilities/state from aHidd_Compositor_Capabilities/State of the display's compositor, always
VideoControl() Done VTAG_COMPOSITING_SET/GET, VTAG_ALPHAHOOK_SET/GET stored in ViewPortExtra, copied into HIDD_ViewPortData (CompFlags, PreAlphaHook, Surfaces) by MakeVPort
Private LVOs for layers.library Done (graphics 45.20) CompositeLayersSupported() (202), LayerSurfacesChanged() (203: stores the screen's surface list, HIDD_Display_SurfaceStackChanged), LayerSurfaceAlpha() (204: alpha of a surface pixel for hit tests)
do_render_with_gc, do_pixel_func, MoveRaster, BltRastPortBitMap change layer-relative offset formula when LAYERCOMPOSITED
BltBitMapAlpha() Done public LVO 205 application access to CopyBoxAlpha
MakeVPort unchanged

3.7 Intuition (rom/intuition)

Item Change
OpenScreen writes SA_CompositingFlags/SA_AlphaPreCompositingHook to the ViewPort via VideoControl; SpecialFlags widened to ULONG so COMPF_SAME and future bits fit
OpenWindow WA_Opaqueness (AmigaOS 4 name), WA_AlphaSurface -> LA_Opacity, LA_AlphaSurface, LA_Composited; composited windows report smart-refresh semantics for IDCMP_REFRESHWINDOW
Hit testing WhichLayer applies the IsLayerHitAt policy for alpha-surface windows (transparent pixels fall through)
SA_CompositingLayers, SA_OpacitySupport, SA_SourceAlphaSupport DONE: report real values (CompositeLayersSupported(); source alpha only on 32-bit screens)
Monitor class DisplayToBMCoords/BMToDisplayCoords stay as the single coordinate path (PR 1639 COMPF_SCALE handling unchanged)
Appearance prefs SCALE and NATIVEMODE checkmarks (ENV:SYS/compositor.prefs template ABOVE/S,BELOW/S,LEFT/S,RIGHT/S,ALPHA/S,SCALE/S,NATIVEMODE/S,NOPLANES/S); absent variable = the AmigaOS default (ABOVE), an empty value disables composition

3.8 Drivers

Driver Final shape
All Hidd_Display subclass describes planes (default: none, base one-plane). ShowViewPorts overrides removed once the compositor is in place.
vcgfx (Pi, HVS) (PR #1738 is the transitional ShowViewPorts form of this; see WP5.1) planes: primary (XRGB/RGB565, unity or upscale), overlay (32bpp, upscale, fixed/per-pixel alpha on HVS5+), cursor. CommitPlanes -> display-list author (hvs_build_list) + DISPLIST repoint; WaitLatch -> vc4_hvs_latch_wait. Private aHidd_VideoCoreGfxBitMap_Overlay retired; vc4gallium requests a plane through the public API.
vmwaresvga / amdgpu / nouveau (DRM) overlay planes from drmModeGetPlaneResources; CommitPlanes -> legacy drmModeSetPlane per plane (atomic DRM_IOCTL_MODE_ATOMIC is routed in arosdrm.c but not used yet); cursor reported as a Cursor plane. nouveau's private compositor deleted. drm-aros enables universal planes for every client, so plane enumeration must filter on the plane type property (done in nouveau, still needed in amdgpu and vmwaresvga).
IntelGMA private compositor retired onto the base hybrid (done: flip when the front screen covers the display, blit otherwise, through Show()). Planes (sprite/overlay per pipe, cursor) not yet described.
amigavideo Hidd_Compositor subclass keeps the copper-list stacking; planes report `PIF_VSPLIT_ONLY
Hosted X11 Done: two emulated overlay planes (child windows with the bitmap pixmap as background, XRender scaling up to 16x); --noplanes disables them. The SDL HIDD is SDL 1.2 based and not built.
vesagfx, vgagfx, efifb, fbgfx, p96gfx, sagagfx, sm502, linuxfb, wingdi no changes; base one-plane display, software composition as today.

Landed upstream 2026-10-24 as b72155e2bb (WP0-WP4, WP5.2-5.4 and the nouveau GB20x fixes; m68k ROM room made in aaab1ff30d); WP5.5 (IntelGMA) as 8ded7e1869. The m68k ROM-size measurement switches (GFX_COMPOSITOR_STUB, AROS_NO_COMPOSITED_LAYERS) have been removed upstream as well.

4. Work packages

Status key: DONE, WIP (in progress), TODO. Each package should leave both pc-x86_64 and linux-x86_64 building and the desktop smoke test passing.

WP0 - Prerequisites and hygiene

# Task Status
0.1 Hidd_Gfx::CopyBoxAlpha with correct destination alpha; PutAlphaImage destination-alpha fix DONE
0.2 Software compositor blends via CopyBoxAlpha; ARGB custom screen bitmaps stamped in BitMapEnable DONE
0.3 nouveau composes through the system compositor (NOUVEAU_PRIVATE_COMPOSITOR 0); verified on hardware DONE
0.4 OOP metaclass dispatch bounds-checks method IDs DONE
0.5 layers: ClipRect content offsets, shared views, LAYERS_BACKING_SURFACE DONE
0.6 Intuition COMPF_SCALE / SF_ScaledCoords coordinate conversion (PR 1639) DONE
0.7 Delete nouveau's private compositor source; rebase the IntelGMA and amigavideo compositor classes onto the system interface definition and make them non-public, so hidd.gfx.compositor has exactly one method table DONE (nouveau deleted; IntelGMA/amigavideo renamed to private interfaces hidd.gfx.compositor.intelgma / .amigavideo; IntelGMA's deleted in WP5.5)
0.8 compositor_startup.c: test for the system class identity, not any class of that name (m68k double-start bug) DONE (program removed; AddDisplayDriverA() accepts and ignores an old binary)
0.9 Remove dead mid_CompositorSetCursor*; drop or implement DisplayRectChanged DONE (fields removed; DisplayRectChanged kept as a mode-reselect hook)
0.10 IntScreen.SpecialFlags -> ULONG; prefs: SCALE in mask, absent variable = off DONE: absent variable keeps the AmigaOS default (ABOVE); Appearance prefs writes an explicit empty value to disable; SCALE and NATIVEMODE checkmarks select the scaling policies (WP4.3)
0.11 Fix the layers defects listed in the study section 5 that touch this path (SA_BackFill never reaching the root layer, BeginRefresh EndUpdate on failure, CollectPixelsLayer slips) DONE (most were already fixed in HEAD; CollectPixelsLayer and a second ScreenDepth slip fixed)

WP1 - Display owns the compositor (behaviour neutral) - DONE, runtime verified on pc-x86_64

# Task
1.1 Display::New attaches a compositor (aHidd_Display_CompositorClass / base class); aHidd_Display_Compositor read-only
1.2 Base ShowViewPorts routes to the compositor; passthrough -> Show
1.3 HIDD_Display_ViewPortPositionChange; ScrollVPort uses it
1.4 Damage goes to the Display's compositor (update_bitmap() -> Hidd_Display::UpdateRect); update_bitmap() reduced
1.5 Remove graphics_compositor.c/.h, DF_SoftComposit, compositor_Install/Setup; AddDisplayDriverA compositor magic removed; Devs/Monitors/Compositor deleted (AddDisplayDriverA and AROSMonDrvs ignore an old binary)
1.6 getdisplayinfodata.c reads capabilities/state from the display's compositor
Acceptance identical behaviour on VESA, VMware SVGA, nouveau, hosted X11; alphascreen and wpaaglobal pass; screen drag works

WP2 - Compositor into gfx.hidd, no Intuition dependency - DONE (compositor class in gfx.hidd, VideoControl tags, no intuition.library)

# Task
2.1 Move compositor_class.c/displaymode.c to rom/hidds/gfx/gfx_compositorclass.c, genmodule class in gfx.conf
2.2 VideoControl tags for composition flags and pre-alpha hook; MakeVPort fills HIDD_ViewPortData.CompFlags/PreAlphaHook; compositor reads them instead of GetAttr(SA_*); drop intuition.library
2.3 aHidd_Compositor_ModePolicy (FollowTop only at this stage)
Acceptance compositor builds in ROM for pc-x86_64; no intuition.library reference in gfx.hidd

WP3 - Composited layers (window level) - DONE including 3.3-3.6 (layers 50.7, graphics 45.20, intuition 50.19; runtime verified on pc-x86_64 and hosted X11; see implementation-log.md and wp3-remaining-notes.md)

# Task
3.1 Opaque composited layers: LAYERCOMPOSITED, single-ClipRect contract, graphics offset formula, LA_Composited; LayerSurfacesChanged() -> HIDD_Display_SurfaceStackChanged; surface nodes in the compositor drawn like alpha screens (opaque fast path: CopyBox + subtract from base redraw)
3.2 Test: CreateUpfrontLayerTagList composited layer on a screen, render, move, reorder. Criterion: MoveLayer performs zero BltBitMap in hyperlayers
3.3 Occlusion split (occludeshape), LA_Opacity, LA_AlphaSurface (screen-layout alpha surface, pens render transparent), IsLayerHitAt + WhichLayer policy
3.4 Intuition tags WA_Opaqueness, WA_AlphaSurface; SA_OpacitySupport etc.; refresh semantics
3.5 Memory budget per screen (4 x screen bitmap, 4 MB free floor) with automatic SMART fallback at creation and in-place conversion on growth
3.6 BltBitMapAlpha() public API (graphics.library 45.20, LVO 205, AROS extension)
Acceptance translucent window over a repainting window renders correctly; moving it generates no damage below; VESA, VMware, nouveau

WP4 - Plane API and hybrid compositor - DONE (4.1-4.5; runtime verified on hosted X11 with two emulated, scaling overlay planes, see implementation-log.md)

# Task
4.1 HIDD_PlaneInfo/HIDD_PlaneState, GetPlaneInfo, CommitPlanes, WaitLatch, aHidd_Display_PlaneCount/VBlankCount; base = one primary plane implemented via Show
4.2 Hybrid assignment in the base compositor: frontmost screens on overlay planes by constraints, backmost screen always on the primary, the rest blitted into ComposedBitMap; BitMapRectChanged no-op for plane-scanned screens. Surfaces are not plane candidates. A refused commit disables planes for the Display (test-commit fallback open, section 7)
4.3 Scaling policies: prefs SCALE = display takes the largest shown screen's mode and smaller screens scale up to it (default scaling behaviour); SCALE NATIVEMODE = display keeps its own highest mode and every screen scales (user option). Scaling on planes or through the row-by-row software path; DisplayToBMCoords/BMToDisplayCoords answered by the compositor (MapCoords); COMPF_SCALE reported so Intuition converts coordinates
4.4 Cursor planes: drivers with a hardware cursor report it as a Cursor plane and keep driving it from their SetCursor* overrides; the base Display keeps the software cursor; the compositor never assigns screens to a cursor plane
4.5 Hosted plane emulation for validation: done in the X11 driver (child windows with the bitmap as background pixmap; the SDL HIDD is SDL 1.2 based and not built). --noplanes disables it
Acceptance met with the X11 emulation: two screens -> two planes, third screen blitted; drag with scaling; existing tests unchanged on one-plane drivers

WP5 - Driver bring-up - 5.2, 5.3, 5.4 landed (5.2 and 5.4 tested on hardware; see implementation-log.md "WP5" and "Hardware result 1-4"); 5.5 landed (8ded7e1869), not yet tested on hardware; 5.1, 5.6 open

# Driver Task
5.1 vcgfx WIP: PR #1738 (open, depends on #1725) already composes screens as HVS planes on VideoCore IV, HVS5 and HVS6 through ShowViewPorts, with scanout-memory screen bitmaps, vblank-latched commits, pointer-only flips, COMPF_SCALE and the coordinate hooks. Remaining for this plan: move the policy in vcgfx_planes.c/hvs_emit_planes (occlusion, backdrop, mode-follow-when-alone, 4-plane cap) into the compositor; expose the mechanism as GetPlaneInfo/CommitPlanes/WaitLatch; retire the private Overlay/VBlank/Flip bitmap attributes (vc4gallium via the public API); let screens beyond the plane budget and non-32bpp screens fall back to blit instead of being skipped
5.2 vmwaresvga IMPLEMENTED: KMS plane layer (libdrm plane/flip/vblank wrappers, overlay enumeration, legacy SetPlane commits, vblank latch and counter), cursor plane, GetPlaneInfo/CommitPlanes/WaitLatch; vmwgfx has no overlay planes, so screens stay composed; scan-out screens behind VMWSVGA_PLANE_SCREENS. Hardware test (2026-10-22): works, planescreens PASS
5.3 amdgpu IMPLEMENTED (builds, not tested on hardware): same KMS path as 5.2; overlay use needs screens in scan-out memory (AMDGPU_PLANE_SCREENS in amdgpu_kms.h, 0). Before turning it on, plane enumeration must keep overlay planes only (the plane type property, as in nouveau): with universal planes on, it would also take the primary and cursor planes. No vblank yet (DRM vblank code not built in this port)
5.4 nouveau LANDED: screens are scanned out from their own buffer objects (HIDDNouveauEnsureFB), overlay planes (filtered by the plane type property) take the frontmost screens (drmModeSetPlane), cursor plane, real vblank (drm_vblank.c built; CommitPlanes waits a vblank only when it reprogrammed an overlay); nv04 YUV overlays excluded. GB207 (Blackwell, GSP, riscv64) verified with planescreens: overlay window, vblank and mode changes work after the riscv-nouveau session's fixes (window ownership on a live head with phywins, GB20x vblank enable and retrigger, CA7E colour defaults, opaque blending of XRGB, compat wait-entry init). NOUVEAU_WINDOW_PLANES=0 / NOUVEAU_WNDW_LIVE_OWNER=0 turn the Volta+ overlay windows off. Open: Xid 56 and GFW boot timeout at init. Pre-Volta overlays untested
5.5 IntelGMA LANDED (8ded7e1869; builds and boots in QEMU without the card, not tested on Intel hardware): private compositor deleted. The Display no longer overrides ShowViewPorts, so the base compositor composes; Show() flips the plane base (SetFramebuffer) for a bitmap in the shown mode and loads the pipe timing (SwitchToVideoMode) otherwise. ModeProperties reports no hardware composition. A directly shown, scrolled oversized screen gets its new offsets in the plane base from BitMap::Set. Damage reaches the compositor through the display (graphics, cybergraphics), not through the bitmap class. No planes described yet (PlaneCount 1)
5.6 amigavideo TODO: compositor subclass over copper lists; planes VSPLIT_ONLY; UAE testing

5. Verification

Test Covers Status
Tests/graphics/alphascreen alpha screen composition, pixel-exact DONE exists
Tests/graphics/wpaaglobal WritePixelArrayAlpha global alpha DONE exists
Tests/benchmarks/graphics/layerops, Tests/layers/newlayer layers behaviour and performance DONE exist
Tests/layers/complayer, Tests/intuition/compwindow (WP3.2) surface rendering, zero-blit moves, opacity, per-pixel alpha DONE exist
Tests/layers/complayerhit, Tests/layers/compbudget, Tests/graphics/bltbitmapalpha, Tests/intuition/screendrag alpha hit testing, surface budget and fallback, BltBitMapAlpha, screen dragging DONE exist
Tests/intuition/planescreens + harness/hosted/xplanes (WP4) screen->plane mapping, fallback to blit, update through a plane DONE exist; passes on hosted X11, QEMU VESA, VMware SVGA and the GB207 (nouveau, overlay window)
Tests/intuition/pointerpos + harness/hosted/xpointer COMPF_SCALE pointer coordinates on a scaled display DONE exists (hosted X11); drag bounds covered by planescreens under SCALE

Targets: VESA (QEMU), VMware SVGA, hosted X11, nouveau and amdgpu hardware, Raspberry Pi 3/4/5, UAE for amigavideo. Tested so far: QEMU VESA, hosted X11, VMware SVGA, nouveau GB207; amdgpu, Pi and UAE pending.


6. Risks and open questions

  • Memory. A composited window holds its surface while visible. Handled by the budget with fallback (WP3.5); LAYERS_BACKING_SURFACE surfaces are not budgeted.
  • Direct screen-bitmap access. Programs drawing into Screen->RastPort or locking the screen bitmap keep working because the screen bitmap remains the opaque base request. They cannot draw over composited layers; document this.
  • Code that walks Layer.ClipRect. Composited layers present one hidden ClipRect, the same view a fully obscured smart window gives today. Audit the few external users (muimaster, asl, gadtools).
  • Plane counts and scaler limits on HVS (display-list RAM, line-buffer memory, Pi 5 UPM) and in KMS drivers are not static, but PlaneFits() only checks the static HIDD_PlaneInfo limits, and a refused commit switches planes off for good. A fHidd_Commit_Test loop that moves the backmost overlay screen into composition until the set is accepted is needed (section 7).
  • Lock ordering. The presenter must never be entered with a layer lock held while the compositor may call back into graphics; the compositor calls only Hidd_Gfx blits, which keeps this safe, but it must be stated as a rule.
  • Classic chipset. Composited layers are refused where the screen bitmap is the scan-out and no planes exist; the design degrades to today's behaviour.
  • m68k ROM size. Resolved: with the compositor and composited layers enabled on every platform, the ROM fits after aaab1ff30d (genmodule startup helpers, string pools, packed boot image and more); GCC 6.5 leaves about 4.4 KB free in the main bank and 5.2 KB in the expansion bank. Further growth in either bank needs trimming or module moves.
  • Double/triple-buffered surfaces (MorphOS LT_AllowDoubleBuffered) are a follow-on, not part of this plan.
  • Client overlays (GL, video). The plane API covers screens only. vcgfx keeps its client overlay pool driver-private for now and must count it when answering a test commit. The preferred public route is a composited layer whose surface is a scan-out buffer, which the compositor may promote to a plane; not decided.

7. Contributing

Work that is open and self-contained: a fHidd_Commit_Test fallback loop in the compositor (after AssignPlanes, before ToggleCompositing; demote the backmost overlay screen until the set is accepted, keep DisablePlanes for real failures); atomic (property based) plane commits and page flips in the DRM drivers; overlay-only plane enumeration in amdgpu and vmwaresvga, then overlay scan-out of screens on amdgpu (AMDGPU_PLANE_SCREENS) on hardware; aspect-preserving (letterbox) scaling and a driver-declared preferred mode for the NATIVEMODE policy; budgeting LAYERS_BACKING_SURFACE smart-layer surfaces; ScaleLayer() for composited layers; describing IntelGMA's per-pipe sprite/overlay and cursor planes (GetPlaneInfo/CommitPlanes) and testing WP5.5 on Intel hardware.

Rules for contributions in this area:

  1. The presenter lives in the compositor, never in layers.library or Intuition.
  2. Hardware is reached only through Hidd_Display planes; no driver-specific code above the Display.
  3. Composited and alpha windows are opt-in; simple/smart/super semantics and memory footprint are unchanged unless asked for.
  4. Every change keeps pc-x86_64 and linux-x86_64 building and the existing graphics and layers tests passing.
  5. AROS is a multi-architecture system. Anything that is not hardware register programming (plane assignment, scaling and mode policy, coordinate conversion, overflow fallback, vblank bookkeeping) is written once in gfx.hidd or the compositor and must work for every architecture and driver: x86 and RISC-V PCI drivers, m68k Amiga, ARM and AArch64 boards, hosted targets. A driver contributes only the mechanism for its hardware, and that mechanism must not be gated on one CPU architecture when the hardware exists on more than one (the Pi 1-3 are 32-bit ARM and 64-bit AArch64 builds of the same VideoCore IV).

8. References

  • rom/hidds/gfx/gfx.conf, gfx_displayclass.c, gfx_display.h, include/gfx.h
  • rom/hidds/gfx/gfx_compositorclass.c, gfx_compositor.h (the compositor, formerly workbench/devs/monitors/Compositor/)
  • rom/graphics/graphics_display.c, getdisplayinfodata.c, scrollvport.c, updatebitmap.c, makevport.c, gfxfuncsupport.c, compositelayerssupported.c, layersurfaceschanged.c, layersurfacealpha.c, bltbitmapalpha.c
  • rom/hyperlayers/layers_intern.h, basicfuncs.c, createlayertaglist.c, islayerhitat.c (surfaces, budget, hit test)
  • arch/arm-native/soc/broadcom/2708/hidd/vcgfx/vcgfx_hvs*.{c,h} (HVS display lists)
  • workbench/hidds/{vmwaresvga,amdgpu,nouveau}/libdrm/arosdrm.c, arosdrmmode.c (plane, flip and vblank wrappers); *_displayclass.c (GetPlaneInfo/CommitPlanes/WaitLatch)
  • arch/all-hosted/hidd/x11/x11gfx_displayclass.c (plane emulation)
  • Commits: d37d20f52c (layers backing surface), 8a16cdb769 (nouveau on the system compositor), aaab1ff30d (m68k ROM room), b72155e2bb (this plan's WP0-WP5.4), 8ded7e1869 (WP5.5 IntelGMA); PR #1639 (COMPF_SCALE)
  • Design notes: gfx HIDD Display/DMEnum split (2026-06), hyperlayers composition study (2026-09/10), display composition analysis (2026-10-18)

Clone this wiki locally