mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
pixels: Ensure expected formats when accesing bytes of snapshot (#37767)
I introduced snapshot in #36119 to pack raw bytes and metadata together, now we take the next step and require for user to always specify what kind of byte data they want when calling `as_bytes` or `to_vec` (basically joining transform and data). There are also valid usages when one might require just one property of bytes (textures can generally handle both RGBA and BGRA). There are also valid usages of using just raw bytes (when cropping). This PR tries to make such usages more obvious. This will make it easier to fix stuff around 2d canvas (we do not want to assume any bytes properties in abstraction). Testing: Code is covered by WPT tests. --------- Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
e3baec4807
commit
a631b42e60
7 changed files with 142 additions and 94 deletions
|
@ -18,6 +18,33 @@ pub enum SnapshotPixelFormat {
|
|||
BGRA,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum Alpha {
|
||||
Premultiplied,
|
||||
NotPremultiplied,
|
||||
/// This is used for opaque textures for which the presence of alpha in the
|
||||
/// output data format does not matter.
|
||||
DontCare,
|
||||
}
|
||||
|
||||
impl Alpha {
|
||||
pub const fn from_premultiplied(is_premultiplied: bool) -> Self {
|
||||
if is_premultiplied {
|
||||
Self::Premultiplied
|
||||
} else {
|
||||
Self::NotPremultiplied
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn needs_alpha_multiplication(&self) -> bool {
|
||||
match self {
|
||||
Alpha::Premultiplied => false,
|
||||
Alpha::NotPremultiplied => true,
|
||||
Alpha::DontCare => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum SnapshotAlphaMode {
|
||||
/// Internal data is opaque (alpha is cleared to 1)
|
||||
|
@ -37,20 +64,17 @@ impl Default for SnapshotAlphaMode {
|
|||
}
|
||||
|
||||
impl SnapshotAlphaMode {
|
||||
pub const fn is_premultiplied(&self) -> bool {
|
||||
pub const fn alpha(&self) -> Alpha {
|
||||
match self {
|
||||
SnapshotAlphaMode::Opaque => true,
|
||||
SnapshotAlphaMode::AsOpaque { premultiplied } => *premultiplied,
|
||||
SnapshotAlphaMode::Transparent { premultiplied } => *premultiplied,
|
||||
SnapshotAlphaMode::Opaque => Alpha::DontCare,
|
||||
SnapshotAlphaMode::AsOpaque { premultiplied } => {
|
||||
Alpha::from_premultiplied(*premultiplied)
|
||||
},
|
||||
SnapshotAlphaMode::Transparent { premultiplied } => {
|
||||
Alpha::from_premultiplied(*premultiplied)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn is_opaque(&self) -> bool {
|
||||
matches!(
|
||||
self,
|
||||
SnapshotAlphaMode::Opaque | SnapshotAlphaMode::AsOpaque { .. }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
|
@ -112,14 +136,6 @@ impl<T> Snapshot<T> {
|
|||
pub const fn alpha_mode(&self) -> SnapshotAlphaMode {
|
||||
self.alpha_mode
|
||||
}
|
||||
|
||||
pub const fn is_premultiplied(&self) -> bool {
|
||||
self.alpha_mode().is_premultiplied()
|
||||
}
|
||||
|
||||
pub const fn is_opaque(&self) -> bool {
|
||||
self.alpha_mode().is_opaque()
|
||||
}
|
||||
}
|
||||
|
||||
impl Snapshot<SnapshotData> {
|
||||
|
@ -181,14 +197,6 @@ impl Snapshot<SnapshotData> {
|
|||
}
|
||||
*/
|
||||
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn data_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
/// Convert inner data of snapshot to target format and alpha mode.
|
||||
/// If data is already in target format and alpha mode no work will be done.
|
||||
pub fn transform(
|
||||
|
@ -200,7 +208,7 @@ impl Snapshot<SnapshotData> {
|
|||
let multiply = match (self.alpha_mode, target_alpha_mode) {
|
||||
(SnapshotAlphaMode::Opaque, _) => Multiply::None,
|
||||
(alpha_mode, SnapshotAlphaMode::Opaque) => {
|
||||
if alpha_mode.is_premultiplied() {
|
||||
if alpha_mode.alpha() == Alpha::Premultiplied {
|
||||
Multiply::UnMultiply
|
||||
} else {
|
||||
Multiply::None
|
||||
|
@ -232,6 +240,37 @@ impl Snapshot<SnapshotData> {
|
|||
self.format = target_format;
|
||||
}
|
||||
|
||||
pub fn as_raw_bytes(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub fn as_raw_bytes_mut(&mut self) -> &mut [u8] {
|
||||
&mut self.data
|
||||
}
|
||||
|
||||
pub fn as_bytes(
|
||||
&mut self,
|
||||
target_alpha_mode: Option<SnapshotAlphaMode>,
|
||||
target_format: Option<SnapshotPixelFormat>,
|
||||
) -> (&mut [u8], SnapshotAlphaMode, SnapshotPixelFormat) {
|
||||
let target_alpha_mode = target_alpha_mode.unwrap_or(self.alpha_mode);
|
||||
let target_format = target_format.unwrap_or(self.format);
|
||||
self.transform(target_alpha_mode, target_format);
|
||||
(&mut self.data, target_alpha_mode, target_format)
|
||||
}
|
||||
|
||||
pub fn to_vec(
|
||||
mut self,
|
||||
target_alpha_mode: Option<SnapshotAlphaMode>,
|
||||
target_format: Option<SnapshotPixelFormat>,
|
||||
) -> (Vec<u8>, SnapshotAlphaMode, SnapshotPixelFormat) {
|
||||
let target_alpha_mode = target_alpha_mode.unwrap_or(self.alpha_mode);
|
||||
let target_format = target_format.unwrap_or(self.format);
|
||||
self.transform(target_alpha_mode, target_format);
|
||||
let SnapshotData::Owned(data) = self.data;
|
||||
(data, target_alpha_mode, target_format)
|
||||
}
|
||||
|
||||
pub fn as_ipc(self) -> Snapshot<IpcSharedMemory> {
|
||||
let Snapshot {
|
||||
size,
|
||||
|
@ -250,12 +289,6 @@ impl Snapshot<SnapshotData> {
|
|||
alpha_mode,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_vec(self) -> Vec<u8> {
|
||||
match self.data {
|
||||
SnapshotData::Owned(data) => data,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Snapshot<IpcSharedMemory> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue