Skip to content

Conversation

@madsmtm
Copy link
Member

@madsmtm madsmtm commented Jan 23, 2026

Add:

impl<D, W> Surface<D, W> {
    pub fn alpha_mode(&self) -> AlphaMode { ... }
    pub fn supports_alpha_mode(&self, alpha_mode: AlphaMode) -> bool { ... }

    // `resize` now calls `configure`:
    pub fn resize(&mut self, width: NonZeroU32, height: NonZeroU32) -> Result<(), SoftBufferError> {
        self.configure(width, height, self.alpha_mode())
    }

    pub fn configure(
        &mut self,
        width: NonZeroU32,
        height: NonZeroU32,
        alpha_mode: AlphaMode,
    ) -> Result<(), SoftBufferError> { ... }
}

#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
pub enum AlphaMode {
    #[default]
    Opaque,
    Ignored,
    Premultiplied,
    Postmultiplied,
}

This fixes #17 and prepares for #98 / #317.

As noted in the transparency issue, it is important to make a distinction between straight and premultiplied alpha. The former can be easier to work with, but the latter is often what's actually supported by compositors.

One mode that is a bit odd here is Opaque, but it's necessary for the Web backend, because that platform doesn't support zero-copy RGBX, the alpha channel is always read (at least from what I could figure out). Adding this mode (and requiring that alpha channel to be 255) fixes #207.

The implementation of these modes for each platform is as follows (I have tested all these):

  • Android: Transparency doesn't seem to be supported by Winit, so I haven't enabled transparency in Softbuffer yet either (since I couldn't test it).
  • CoreGraphics: Opaque, Ignored, Premultiplied and Postmultiplied enabled. Premultiplied clamps the additive variants, but this might change with the IOSurface impl.
  • Wayland: Opaque, Ignored, Premultiplied.
  • Web: Opaque and Postmultiplied. Premultiplied can be supported in the future with ImageBitmap IIUC.
  • Win32: I think it could support Premultiplied, but I couldn't get it to work properly, so only did part of it, I'm not too familiar with Windows. I suspect it might also need something like fixed window transparency winit#2503.
  • X11: Transparency not yet implemented, but pretty sure that Premultiplied could be supported.

We could fairly easily implement a conversion step to support postmultiplied alpha when premultiplied is supported by the backend, but I'd like to migrate towards a more efficient design where each backend always do zero-copying, so I haven't done that.

Expected behaviour

I've created an example transparency.rs, which renders a few different shades of orange and yellow. The expected result are as follows:

Opaque / Ignored

opaque

Premultiplied

premultiplied

Postmultiplied

postmultiplied

@madsmtm madsmtm added this to the Softbuffer v0.5 milestone Jan 23, 2026
@madsmtm madsmtm added enhancement New feature or request DS - CoreGraphics macOS/iOS/tvOS/watchOS/visionOS backend DS - Wayland DS - Web WebAssembly / WASM backend labels Jan 23, 2026
Comment on lines +547 to +548
/// - macOS/iOS: Supported, but currently doesn't work with additive values (maybe only as the
/// root layer?). Make sure that components are `<= alpha` if you want to be cross-platform.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like this currently:

macos-premultiplied

I suspect that this may be an intentional limitation of transparency in the "root" / that goes through the top-level layer, perhaps as a form of security measure to avoid users reading contents of contents below the window in a shader or smth? But I'll need to investigate this further, might be possible to fix with IOSurface.

Comment on lines +552 to +564
/// The non-alpha channels are not expected to already be multiplied by the alpha channel;
/// instead, the compositor will multiply the non-alpha channels by the alpha channel during
/// compositing.
///
/// Also known as "straight alpha".
///
/// ## Platform Dependent Behavior
///
/// - Web and macOS/iOS: Supported.
/// - Android, KMS/DRM, Orbital, Windows, X11: Not yet supported.
#[doc(alias = "Straight")]
#[doc(alias = "Unassociated")]
Postmultiplied,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// root layer?). Make sure that components are `<= alpha` if you want to be cross-platform.
/// - Android, Orbital, Web, Windows and X11: Not yet supported.
#[doc(alias = "Associated")]
Premultiplied,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I elected to call this Premultiplied instead of PreMultiplied (not camel casing), because most of the references I could find on the interwebs seemed to prefer to write it in one word instead of hyphenating as "pre-multiplied".

@madsmtm madsmtm force-pushed the madsmtm/alpha-mode branch from 4dd27ed to 304f431 Compare January 24, 2026 00:11
This was linked to issues Jan 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

DS - CoreGraphics macOS/iOS/tvOS/watchOS/visionOS backend DS - Wayland DS - Web WebAssembly / WASM backend enhancement New feature or request

Development

Successfully merging this pull request may close these issues.

Drawing on the web is very slow Transparency

2 participants