Skip to content

Commit

Permalink
perf: avoid memcpy while drawing canvas on canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn committed Feb 2, 2025
1 parent 1eb5c8c commit e9cd123
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 17 deletions.
23 changes: 13 additions & 10 deletions skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -293,14 +293,10 @@ extern "C"

void skiac_surface_get_bitmap(skiac_surface *c_surface, skiac_bitmap_info *info)
{
auto image = SURFACE_CAST->makeImageSnapshot();
auto bitmap = new SkBitmap();
auto image_info = image->imageInfo();
bitmap->allocPixels(image_info);
image->readPixels(image_info, bitmap->getPixels(), bitmap->rowBytes(), 0, 0);
info->bitmap = reinterpret_cast<skiac_bitmap *>(bitmap);
info->width = (size_t)image_info.width();
info->height = (size_t)image_info.height();
info->is_canvas = true;
info->bitmap = reinterpret_cast<skiac_bitmap *>(c_surface);
info->width = (size_t)SURFACE_CAST->width();
info->height = (size_t)SURFACE_CAST->height();
}

// Canvas
Expand Down Expand Up @@ -354,6 +350,7 @@ extern "C"
void skiac_canvas_draw_image(
skiac_canvas *c_canvas,
skiac_bitmap *c_bitmap,
bool is_canvas,
float sx,
float sy,
float s_width,
Expand All @@ -368,11 +365,17 @@ extern "C"
{
const auto src_rect = SkRect::MakeXYWH(sx, sy, s_width, s_height);
const auto dst_rect = SkRect::MakeXYWH(dx, dy, d_width, d_height);
auto sk_image = SkImages::RasterFromBitmap(*BITMAP_CAST);
auto fq = enable_smoothing ? filter_quality : 0;
const auto sampling = SamplingOptionsFromFQ(fq);
auto paint = reinterpret_cast<const SkPaint *>(c_paint);
CANVAS_CAST->drawImageRect(sk_image, src_rect, dst_rect, sampling, paint, SkCanvas::kFast_SrcRectConstraint);
if (is_canvas) {
auto surface = reinterpret_cast<SkSurface *>(c_bitmap);
auto rect = SkIRect::MakeXYWH(sx, sy, s_width, s_height);
auto image = surface->makeImageSnapshot(rect);
CANVAS_CAST->drawImageRect(image, dst_rect, sampling, paint);
} else {
CANVAS_CAST->drawImageRect(SkImages::RasterFromBitmap(*BITMAP_CAST), src_rect, dst_rect, sampling, paint, SkCanvas::kFast_SrcRectConstraint);
}
}

void skiac_canvas_draw_path(skiac_canvas *c_canvas, skiac_path *c_path, skiac_paint *c_paint)
Expand Down
2 changes: 2 additions & 0 deletions skia-c/skia_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ struct skiac_bitmap_info
skiac_bitmap *bitmap;
int width;
int height;
bool is_canvas;
};

struct skiac_string
Expand Down Expand Up @@ -294,6 +295,7 @@ extern "C"
void skiac_canvas_draw_image(
skiac_canvas *c_canvas,
skiac_bitmap *c_bitmap,
bool is_canvas,
float sx,
float sy,
float s_width,
Expand Down
5 changes: 2 additions & 3 deletions src/ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -712,7 +712,6 @@ impl Context {
d_width: f32,
d_height: f32,
) -> Result<()> {
let bitmap = bitmap.0.bitmap;
let mut paint: Paint = self.fill_paint()?;
paint.set_alpha((self.state.global_alpha * 255.0).round() as u8);
Self::render_canvas(
Expand All @@ -724,7 +723,7 @@ impl Context {
|canvas: &mut Canvas, paint| {
if let Some(drop_shadow_paint) = Self::drop_shadow_paint(&self.state, paint) {
canvas.draw_image(
bitmap,
&bitmap,
sx,
sy,
s_width,
Expand All @@ -739,7 +738,7 @@ impl Context {
);
}
canvas.draw_image(
bitmap,
&bitmap,
sx,
sy,
s_width,
Expand Down
18 changes: 14 additions & 4 deletions src/sk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub mod ffi {
pub bitmap: *mut skiac_bitmap,
pub width: i32,
pub height: i32,
pub is_canvas: bool,
}

#[repr(C)]
Expand Down Expand Up @@ -373,6 +374,7 @@ pub mod ffi {
pub fn skiac_canvas_draw_image(
canvas: *mut skiac_canvas,
bitmap: *mut skiac_bitmap,
is_image: bool,
sx: f32,
sy: f32,
s_width: f32,
Expand Down Expand Up @@ -1822,6 +1824,7 @@ impl Surface {
bitmap: ptr::null_mut(),
width: 0,
height: 0,
is_canvas: true,
};
unsafe { ffi::skiac_surface_get_bitmap(self.ptr, &mut bitmap_info) };
Bitmap(bitmap_info)
Expand Down Expand Up @@ -2068,7 +2071,7 @@ impl Canvas {

pub fn draw_image(
&mut self,
image: *mut ffi::skiac_bitmap,
image: &Bitmap,
sx: f32,
sy: f32,
s_width: f32,
Expand All @@ -2084,7 +2087,8 @@ impl Canvas {
unsafe {
ffi::skiac_canvas_draw_image(
self.0,
image,
image.0.bitmap,
image.0.is_canvas,
sx,
sy,
s_width,
Expand Down Expand Up @@ -3439,7 +3443,7 @@ impl Drop for ImageFilter {

#[repr(transparent)]
#[derive(Debug)]
pub(crate) struct Bitmap(pub(crate) ffi::skiac_bitmap_info);
pub struct Bitmap(pub(crate) ffi::skiac_bitmap_info);

unsafe impl Send for Bitmap {}
unsafe impl Sync for Bitmap {}
Expand All @@ -3450,6 +3454,7 @@ impl Bitmap {
bitmap: ptr::null_mut(),
width: 0,
height: 0,
is_canvas: false,
};
unsafe {
ffi::skiac_bitmap_make_from_buffer(ptr, size, &mut bitmap_info);
Expand All @@ -3467,6 +3472,7 @@ impl Bitmap {
bitmap: ptr::null_mut(),
width: 0,
height: 0,
is_canvas: false,
};
unsafe {
let is_valid = ffi::skiac_bitmap_make_from_svg(
Expand Down Expand Up @@ -3502,6 +3508,7 @@ impl Bitmap {
bitmap: ptr::null_mut(),
width: 0,
height: 0,
is_canvas: false,
};
unsafe {
ffi::skiac_bitmap_make_from_svg(
Expand Down Expand Up @@ -3545,14 +3552,17 @@ impl Bitmap {
bitmap,
width: row_bytes as i32,
height: (size / row_bytes / 4) as i32,
is_canvas: false,
})
}
}

impl Drop for Bitmap {
fn drop(&mut self) {
unsafe {
ffi::skiac_bitmap_destroy(self.0.bitmap);
if !self.0.is_canvas {
ffi::skiac_bitmap_destroy(self.0.bitmap);
}
}
}
}
Expand Down

0 comments on commit e9cd123

Please sign in to comment.