Skip to main content

PixelFormat

Enum PixelFormat 

Source
pub enum PixelFormat {
    Rgba8Unorm,
    Rgba8UnormSrgb,
    Bgra8Unorm,
    Bgra8UnormSrgb,
    Rgb10A2Unorm,
    Rgba16Float,
    R8Unorm,
}
Expand description

Pixel formats the renderer can target.

Color is sRGB-encoded f32 internally; these describe storage at the API boundary and at target write, and no transfer function sits between the two.

Variants§

§

Rgba8Unorm

8-bit RGBA, unsigned normalized.

§

Rgba8UnormSrgb

8-bit RGBA with sRGB transfer on write.

§

Bgra8Unorm

8-bit BGRA, the common scanout order.

§

Bgra8UnormSrgb

8-bit BGRA with sRGB transfer on write.

§

Rgb10A2Unorm

10-bit color with 2-bit alpha, preferred when the pipeline is HDR-aware.

§

Rgba16Float

16-bit float per channel, for intermediate targets.

§

R8Unorm

One 8-bit channel, unsigned normalized.

For data that is coverage rather than color — a glyph atlas is the case — where storing the same byte four times costs four times the memory and four times the bandwidth to sample it.

Implementations§

Source§

impl PixelFormat

Source

pub const fn bytes_per_pixel(self) -> u32

Source

pub const fn intermediate(self) -> Self

The format an offscreen layer takes when the frame lands in this one.

Following the root is what keeps the cost where the choice was made: a caller who asks for a floating-point surface gets layers that can hold what it holds, and a caller who does not pays nothing. A layer is an intermediate of this frame, so it should carry at least what the frame it composites into can carry.

Stated as a match rather than as identity because two formats here would make bad layers. A single-channel one has nowhere to put color at all. And ten-bit color with two-bit alpha is worse for a layer than the eight-bit target it would replace, because a layer’s alpha is group opacity – a value that gets composited – rather than a scanout channel nothing reads back.

Never an sRGB format, whatever the root is. The pipeline carries encoded components, so a target that encodes on write would encode them a second time and a layer would come back paler than the same content drawn straight onto the frame.

This followed the root for a while, and was right to: color was light then, eight bits of linear color band visibly in the darks, and a dark ramp resolving forty distinct tones drawn straight into an sRGB frame came back as six through a layer holding linear eight-bit color. Neither half of that can happen now – a layer’s eight bits are spaced by the transfer function because the values arriving already are.

Source

pub const fn quantization_step(self) -> f32

How far apart two representable values are in this format’s storage, or zero where the question does not apply.

The distance a dither has to bridge. It is stated in storage units rather than in light, which for Self::Rgba8UnormSrgb and its sibling is not the same thing: the hardware encodes on write, so a step there is a step of the encoded value and the light it stands for varies across the range by a factor of about thirty. Anything acting on this number therefore has to know which space it is in, which is what Self::is_srgb answers.

Zero for Self::Rgba16Float, where there is no fixed quantum to bridge – half’s precision is relative, so a step near black is minute and a dither sized for one near white would swamp it. Zero for Self::R8Unorm as well, which holds coverage rather than color.

Source

pub const fn is_drawable(self) -> bool

Whether the renderer can draw into this format.

It cannot draw into one that encodes on write. The pipeline carries sRGB-encoded components from the API boundary onward, so a target applying the transfer function would apply it a second time and the picture would come back over a third too bright at mid gray.

Stated once and consulted from three places, because it has been got wrong at two of them and neither showed up in a test that renders pixels. The swapchain preferred an sRGB surface format and DRM scanout rendered through an sRGB image view, both for the same reason – they were written while the pipeline carried light, where encoding on write was exactly what was wanted. A rule that lives in one place can be re-read; three copies of an argument get updated one at a time.

Source

pub const fn is_srgb(self) -> bool

Whether writes to this format apply an sRGB transfer function.

Source

pub const fn fourcc(self) -> Option<Fourcc>

The DRM fourcc this format scans out as, if any.

Intermediate formats have no scanout representation and return None, which is what keeps them out of negotiation.

Trait Implementations§

Source§

impl Clone for PixelFormat

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for PixelFormat

Source§

impl Debug for PixelFormat

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Eq for PixelFormat

Source§

impl Hash for PixelFormat

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl PartialEq for PixelFormat

Source§

fn eq(&self, other: &Self) -> bool

Equality operator ==. Read more
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Inequality operator !=. Read more
Source§

impl StructuralPartialEq for PixelFormat

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.