Skip to content

Commit 8f00680

Browse files
authored
perf: avoid memcpy while drawing canvas on canvas (#984)
1 parent 967bddf commit 8f00680

File tree

6 files changed

+35
-35
lines changed

6 files changed

+35
-35
lines changed

.github/workflows/CI.yaml

+3-19
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ jobs:
448448
fail-fast: false
449449
matrix:
450450
node: ['20', '22']
451-
runs-on: ubuntu-latest
451+
runs-on: ubuntu-24.04-arm
452452

453453
steps:
454454
- uses: actions/checkout@v4
@@ -473,16 +473,7 @@ jobs:
473473
shell: bash
474474

475475
- name: Install dependencies
476-
run: |
477-
yarn config set supportedArchitectures.cpu "arm64"
478-
yarn config set supportedArchitectures.libc "glibc"
479-
yarn install --immutable --mode=skip-build
480-
- name: Set up QEMU
481-
uses: docker/setup-qemu-action@v3
482-
with:
483-
platforms: arm64
484-
485-
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
476+
run: yarn install --immutable --mode=skip-build
486477

487478
- name: Setup and run tests
488479
uses: addnab/docker-run-action@v3
@@ -506,7 +497,7 @@ jobs:
506497
needs:
507498
- build
508499

509-
runs-on: ubuntu-latest
500+
runs-on: ubuntu-24.04-arm
510501

511502
steps:
512503
- uses: actions/checkout@v4
@@ -536,13 +527,6 @@ jobs:
536527
yarn config set supportedArchitectures.libc "musl"
537528
yarn install --immutable --mode=skip-build
538529
539-
- name: Set up QEMU
540-
uses: docker/setup-qemu-action@v3
541-
with:
542-
platforms: arm64
543-
544-
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
545-
546530
- name: Setup and run tests
547531
uses: addnab/docker-run-action@v3
548532
with:

build.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ fn main() {
164164
.cpp_set_stdlib("stdc++")
165165
.flag("-static")
166166
.include("/usr/arm-linux-gnueabihf/include")
167-
.include(format!("/usr/arm-linux-gnueabihf/include/c++/8"));
167+
.include("/usr/arm-linux-gnueabihf/include/c++/8");
168168
println!("cargo:rustc-link-lib=static=stdc++");
169169
println!("cargo:rustc-link-search=/usr/lib/gcc-cross/arm-linux-gnueabihf/8");
170170
}

skia-c/skia_c.cpp

+15-10
Original file line numberDiff line numberDiff line change
@@ -293,14 +293,10 @@ extern "C"
293293

294294
void skiac_surface_get_bitmap(skiac_surface *c_surface, skiac_bitmap_info *info)
295295
{
296-
auto image = SURFACE_CAST->makeImageSnapshot();
297-
auto bitmap = new SkBitmap();
298-
auto image_info = image->imageInfo();
299-
bitmap->allocPixels(image_info);
300-
image->readPixels(image_info, bitmap->getPixels(), bitmap->rowBytes(), 0, 0);
301-
info->bitmap = reinterpret_cast<skiac_bitmap *>(bitmap);
302-
info->width = (size_t)image_info.width();
303-
info->height = (size_t)image_info.height();
296+
info->is_canvas = true;
297+
info->bitmap = reinterpret_cast<skiac_bitmap *>(c_surface);
298+
info->width = (size_t)SURFACE_CAST->width();
299+
info->height = (size_t)SURFACE_CAST->height();
304300
}
305301

306302
// Canvas
@@ -354,6 +350,7 @@ extern "C"
354350
void skiac_canvas_draw_image(
355351
skiac_canvas *c_canvas,
356352
skiac_bitmap *c_bitmap,
353+
bool is_canvas,
357354
float sx,
358355
float sy,
359356
float s_width,
@@ -368,11 +365,19 @@ extern "C"
368365
{
369366
const auto src_rect = SkRect::MakeXYWH(sx, sy, s_width, s_height);
370367
const auto dst_rect = SkRect::MakeXYWH(dx, dy, d_width, d_height);
371-
auto sk_image = SkImages::RasterFromBitmap(*BITMAP_CAST);
372368
auto fq = enable_smoothing ? filter_quality : 0;
373369
const auto sampling = SamplingOptionsFromFQ(fq);
374370
auto paint = reinterpret_cast<const SkPaint *>(c_paint);
375-
CANVAS_CAST->drawImageRect(sk_image, src_rect, dst_rect, sampling, paint, SkCanvas::kFast_SrcRectConstraint);
371+
if (is_canvas) {
372+
auto srcSurface = reinterpret_cast<SkSurface *>(c_bitmap);
373+
CANVAS_CAST->save();
374+
CANVAS_CAST->translate(dx, dy);
375+
CANVAS_CAST->clipRect(SkRect::MakeWH(d_width, d_height));
376+
srcSurface->draw(CANVAS_CAST, -sx, -sy, sampling, paint);
377+
CANVAS_CAST->restore();
378+
} else {
379+
CANVAS_CAST->drawImageRect(SkImages::RasterFromBitmap(*BITMAP_CAST), src_rect, dst_rect, sampling, paint, SkCanvas::kFast_SrcRectConstraint);
380+
}
376381
}
377382

378383
void skiac_canvas_draw_path(skiac_canvas *c_canvas, skiac_path *c_path, skiac_paint *c_paint)

skia-c/skia_c.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,7 @@ struct skiac_bitmap_info
224224
skiac_bitmap *bitmap;
225225
int width;
226226
int height;
227+
bool is_canvas;
227228
};
228229

229230
struct skiac_string
@@ -294,6 +295,7 @@ extern "C"
294295
void skiac_canvas_draw_image(
295296
skiac_canvas *c_canvas,
296297
skiac_bitmap *c_bitmap,
298+
bool is_canvas,
297299
float sx,
298300
float sy,
299301
float s_width,

src/ctx.rs

-1
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,6 @@ impl Context {
712712
d_width: f32,
713713
d_height: f32,
714714
) -> Result<()> {
715-
let bitmap = bitmap.0.bitmap;
716715
let mut paint: Paint = self.fill_paint()?;
717716
paint.set_alpha((self.state.global_alpha * 255.0).round() as u8);
718717
Self::render_canvas(

src/sk.rs

+14-4
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ pub mod ffi {
111111
pub bitmap: *mut skiac_bitmap,
112112
pub width: i32,
113113
pub height: i32,
114+
pub is_canvas: bool,
114115
}
115116

116117
#[repr(C)]
@@ -373,6 +374,7 @@ pub mod ffi {
373374
pub fn skiac_canvas_draw_image(
374375
canvas: *mut skiac_canvas,
375376
bitmap: *mut skiac_bitmap,
377+
is_image: bool,
376378
sx: f32,
377379
sy: f32,
378380
s_width: f32,
@@ -1822,6 +1824,7 @@ impl Surface {
18221824
bitmap: ptr::null_mut(),
18231825
width: 0,
18241826
height: 0,
1827+
is_canvas: true,
18251828
};
18261829
unsafe { ffi::skiac_surface_get_bitmap(self.ptr, &mut bitmap_info) };
18271830
Bitmap(bitmap_info)
@@ -2068,7 +2071,7 @@ impl Canvas {
20682071

20692072
pub fn draw_image(
20702073
&mut self,
2071-
image: *mut ffi::skiac_bitmap,
2074+
image: &Bitmap,
20722075
sx: f32,
20732076
sy: f32,
20742077
s_width: f32,
@@ -2084,7 +2087,8 @@ impl Canvas {
20842087
unsafe {
20852088
ffi::skiac_canvas_draw_image(
20862089
self.0,
2087-
image,
2090+
image.0.bitmap,
2091+
image.0.is_canvas,
20882092
sx,
20892093
sy,
20902094
s_width,
@@ -3439,7 +3443,7 @@ impl Drop for ImageFilter {
34393443

34403444
#[repr(transparent)]
34413445
#[derive(Debug)]
3442-
pub(crate) struct Bitmap(pub(crate) ffi::skiac_bitmap_info);
3446+
pub struct Bitmap(pub(crate) ffi::skiac_bitmap_info);
34433447

34443448
unsafe impl Send for Bitmap {}
34453449
unsafe impl Sync for Bitmap {}
@@ -3450,6 +3454,7 @@ impl Bitmap {
34503454
bitmap: ptr::null_mut(),
34513455
width: 0,
34523456
height: 0,
3457+
is_canvas: false,
34533458
};
34543459
unsafe {
34553460
ffi::skiac_bitmap_make_from_buffer(ptr, size, &mut bitmap_info);
@@ -3467,6 +3472,7 @@ impl Bitmap {
34673472
bitmap: ptr::null_mut(),
34683473
width: 0,
34693474
height: 0,
3475+
is_canvas: false,
34703476
};
34713477
unsafe {
34723478
let is_valid = ffi::skiac_bitmap_make_from_svg(
@@ -3502,6 +3508,7 @@ impl Bitmap {
35023508
bitmap: ptr::null_mut(),
35033509
width: 0,
35043510
height: 0,
3511+
is_canvas: false,
35053512
};
35063513
unsafe {
35073514
ffi::skiac_bitmap_make_from_svg(
@@ -3545,14 +3552,17 @@ impl Bitmap {
35453552
bitmap,
35463553
width: row_bytes as i32,
35473554
height: (size / row_bytes / 4) as i32,
3555+
is_canvas: false,
35483556
})
35493557
}
35503558
}
35513559

35523560
impl Drop for Bitmap {
35533561
fn drop(&mut self) {
35543562
unsafe {
3555-
ffi::skiac_bitmap_destroy(self.0.bitmap);
3563+
if !self.0.is_canvas {
3564+
ffi::skiac_bitmap_destroy(self.0.bitmap);
3565+
}
35563566
}
35573567
}
35583568
}

0 commit comments

Comments
 (0)