Implement present_with_damage for Web (#101)
This commit is contained in:
parent
29b3f4a978
commit
d7888ef806
1 changed files with 80 additions and 44 deletions
124
src/web.rs
124
src/web.rs
|
|
@ -107,6 +107,69 @@ impl WebImpl {
|
||||||
pub(crate) fn buffer_mut(&mut self) -> Result<BufferImpl, SoftBufferError> {
|
pub(crate) fn buffer_mut(&mut self) -> Result<BufferImpl, SoftBufferError> {
|
||||||
Ok(BufferImpl { imp: self })
|
Ok(BufferImpl { imp: self })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn present_with_damage(&mut self, damage: &[Rect]) -> Result<(), SoftBufferError> {
|
||||||
|
// Create a bitmap from the buffer.
|
||||||
|
let bitmap: Vec<_> = self
|
||||||
|
.buffer
|
||||||
|
.iter()
|
||||||
|
.copied()
|
||||||
|
.flat_map(|pixel| [(pixel >> 16) as u8, (pixel >> 8) as u8, pixel as u8, 255])
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
#[cfg(target_feature = "atomics")]
|
||||||
|
let result = {
|
||||||
|
use js_sys::{Uint8Array, Uint8ClampedArray};
|
||||||
|
use wasm_bindgen::prelude::wasm_bindgen;
|
||||||
|
use wasm_bindgen::JsValue;
|
||||||
|
|
||||||
|
#[wasm_bindgen]
|
||||||
|
extern "C" {
|
||||||
|
#[wasm_bindgen(js_name = ImageData)]
|
||||||
|
type ImageDataExt;
|
||||||
|
|
||||||
|
#[wasm_bindgen(catch, constructor, js_class = ImageData)]
|
||||||
|
fn new(array: Uint8ClampedArray, sw: u32) -> Result<ImageDataExt, JsValue>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let array = Uint8Array::new_with_length(bitmap.len() as u32);
|
||||||
|
array.copy_from(&bitmap);
|
||||||
|
let array = Uint8ClampedArray::new(&array);
|
||||||
|
ImageDataExt::new(array, self.width)
|
||||||
|
.map(JsValue::from)
|
||||||
|
.map(ImageData::unchecked_from_js)
|
||||||
|
};
|
||||||
|
#[cfg(not(target_feature = "atomics"))]
|
||||||
|
let result =
|
||||||
|
ImageData::new_with_u8_clamped_array(wasm_bindgen::Clamped(&bitmap), self.width);
|
||||||
|
// This should only throw an error if the buffer we pass's size is incorrect.
|
||||||
|
let image_data = result.unwrap();
|
||||||
|
|
||||||
|
for Rect {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
} in damage
|
||||||
|
{
|
||||||
|
// This can only throw an error if `data` is detached, which is impossible.
|
||||||
|
self.ctx
|
||||||
|
.put_image_data_with_dirty_x_and_dirty_y_and_dirty_width_and_dirty_height(
|
||||||
|
&image_data,
|
||||||
|
(*x).into(),
|
||||||
|
(*y).into(),
|
||||||
|
(*x).into(),
|
||||||
|
(*y).into(),
|
||||||
|
(*width).into(),
|
||||||
|
(*height).into(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
self.buffer_presented = true;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct BufferImpl<'a> {
|
pub struct BufferImpl<'a> {
|
||||||
|
|
@ -132,53 +195,26 @@ impl<'a> BufferImpl<'a> {
|
||||||
|
|
||||||
/// Push the buffer to the canvas.
|
/// Push the buffer to the canvas.
|
||||||
pub fn present(self) -> Result<(), SoftBufferError> {
|
pub fn present(self) -> Result<(), SoftBufferError> {
|
||||||
// Create a bitmap from the buffer.
|
let (width, height) = (|| {
|
||||||
let bitmap: Vec<_> = self
|
let width = i32::try_from(self.imp.width).ok()?;
|
||||||
.imp
|
let height = i32::try_from(self.imp.height).ok()?;
|
||||||
.buffer
|
Some((width, height))
|
||||||
.iter()
|
})()
|
||||||
.copied()
|
.ok_or(SoftBufferError::SizeOutOfRange {
|
||||||
.flat_map(|pixel| [(pixel >> 16) as u8, (pixel >> 8) as u8, pixel as u8, 255])
|
width: NonZeroU32::new(self.imp.width).unwrap(),
|
||||||
.collect();
|
height: NonZeroU32::new(self.imp.height).unwrap(),
|
||||||
|
})?;
|
||||||
|
|
||||||
#[cfg(target_feature = "atomics")]
|
self.imp.present_with_damage(&[Rect {
|
||||||
let result = {
|
x: 0,
|
||||||
use js_sys::{Uint8Array, Uint8ClampedArray};
|
y: 0,
|
||||||
use wasm_bindgen::prelude::wasm_bindgen;
|
width,
|
||||||
use wasm_bindgen::JsValue;
|
height,
|
||||||
|
}])
|
||||||
#[wasm_bindgen]
|
|
||||||
extern "C" {
|
|
||||||
#[wasm_bindgen(js_name = ImageData)]
|
|
||||||
type ImageDataExt;
|
|
||||||
|
|
||||||
#[wasm_bindgen(catch, constructor, js_class = ImageData)]
|
|
||||||
fn new(array: Uint8ClampedArray, sw: u32) -> Result<ImageDataExt, JsValue>;
|
|
||||||
}
|
|
||||||
|
|
||||||
let array = Uint8Array::new_with_length(bitmap.len() as u32);
|
|
||||||
array.copy_from(&bitmap);
|
|
||||||
let array = Uint8ClampedArray::new(&array);
|
|
||||||
ImageDataExt::new(array, self.imp.width)
|
|
||||||
.map(JsValue::from)
|
|
||||||
.map(ImageData::unchecked_from_js)
|
|
||||||
};
|
|
||||||
#[cfg(not(target_feature = "atomics"))]
|
|
||||||
let result =
|
|
||||||
ImageData::new_with_u8_clamped_array(wasm_bindgen::Clamped(&bitmap), self.imp.width);
|
|
||||||
// This should only throw an error if the buffer we pass's size is incorrect.
|
|
||||||
let image_data = result.unwrap();
|
|
||||||
|
|
||||||
// This can only throw an error if `data` is detached, which is impossible.
|
|
||||||
self.imp.ctx.put_image_data(&image_data, 0.0, 0.0).unwrap();
|
|
||||||
|
|
||||||
self.imp.buffer_presented = true;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn present_with_damage(self, _damage: &[Rect]) -> Result<(), SoftBufferError> {
|
pub fn present_with_damage(self, damage: &[Rect]) -> Result<(), SoftBufferError> {
|
||||||
self.present()
|
self.imp.present_with_damage(damage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue