Skip to content

Commit

Permalink
perf: avoid memcpy while drawing canvas on canvas (#984)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brooooooklyn authored Feb 2, 2025
1 parent 967bddf commit 8f00680
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 35 deletions.
22 changes: 3 additions & 19 deletions .github/workflows/CI.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ jobs:
fail-fast: false
matrix:
node: ['20', '22']
runs-on: ubuntu-latest
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@v4
Expand All @@ -473,16 +473,7 @@ jobs:
shell: bash

- name: Install dependencies
run: |
yarn config set supportedArchitectures.cpu "arm64"
yarn config set supportedArchitectures.libc "glibc"
yarn install --immutable --mode=skip-build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64

- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
run: yarn install --immutable --mode=skip-build

- name: Setup and run tests
uses: addnab/docker-run-action@v3
Expand All @@ -506,7 +497,7 @@ jobs:
needs:
- build

runs-on: ubuntu-latest
runs-on: ubuntu-24.04-arm

steps:
- uses: actions/checkout@v4
Expand Down Expand Up @@ -536,13 +527,6 @@ jobs:
yarn config set supportedArchitectures.libc "musl"
yarn install --immutable --mode=skip-build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: arm64

- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes

- name: Setup and run tests
uses: addnab/docker-run-action@v3
with:
Expand Down
2 changes: 1 addition & 1 deletion build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ fn main() {
.cpp_set_stdlib("stdc++")
.flag("-static")
.include("/usr/arm-linux-gnueabihf/include")
.include(format!("/usr/arm-linux-gnueabihf/include/c++/8"));
.include("/usr/arm-linux-gnueabihf/include/c++/8");
println!("cargo:rustc-link-lib=static=stdc++");
println!("cargo:rustc-link-search=/usr/lib/gcc-cross/arm-linux-gnueabihf/8");
}
Expand Down
25 changes: 15 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,19 @@ 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 srcSurface = reinterpret_cast<SkSurface *>(c_bitmap);
CANVAS_CAST->save();
CANVAS_CAST->translate(dx, dy);
CANVAS_CAST->clipRect(SkRect::MakeWH(d_width, d_height));
srcSurface->draw(CANVAS_CAST, -sx, -sy, sampling, paint);
CANVAS_CAST->restore();
} 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
1 change: 0 additions & 1 deletion 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 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 8f00680

Please sign in to comment.