Skip to content

Commit 8847dae

Browse files
committed
fix(canvas): copyExternalImageToTexture pixel format
1 parent 46f97f1 commit 8847dae

File tree

5 files changed

+63
-8
lines changed

5 files changed

+63
-8
lines changed

crates/canvas-2d/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ gl-bindings = { workspace = true }
1919
csscolorparser = { git = "https://github.com/triniwiz/csscolorparser-rs.git", rev = "c8c7e86", features = ["named-colors"] }
2020
log.workspace = true
2121
skia-safe = { workspace = true, features = ["textlayout"] }
22-
bytes = "1.6.1"
22+
bytes = "1.7.2"
2323
env_logger = "0.11.2"
2424
ash = { version = "0.38.0", optional = true, features = ["libloading"] }
2525
raw-window-handle.workspace = true

crates/canvas-2d/src/context/mod.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use base64::Engine;
55
use regex::bytes::Replacer;
66
use skia_safe::image::CachingHint;
77
use skia_safe::BlendMode;
8-
use skia_safe::{AlphaType, Color, ColorType, EncodedImageFormat, IPoint, ISize, Image, ImageInfo, Point, Surface};
8+
pub use skia_safe::ColorType;
9+
use skia_safe::{AlphaType, Color, EncodedImageFormat, IPoint, ISize, Image, ImageInfo, Point, Surface};
910

1011
use compositing::composite_operation_type::CompositeOperationType;
1112
use fill_and_stroke_styles::paint::Paint;
@@ -20,6 +21,7 @@ use text_styles::{
2021

2122
use crate::context::drawing_text::typography::Font;
2223

24+
2325
use bitflags::bitflags;
2426
use bytes::Buf;
2527

@@ -226,6 +228,18 @@ impl Context {
226228
}
227229

228230

231+
pub fn get_pixels_format(&mut self, buffer: &mut [u8], origin: impl Into<IPoint>, size: impl Into<ISize>, color_type: ColorType) {
232+
let origin = origin.into();
233+
let size = size.into();
234+
let mut info = ImageInfo::new(size, color_type, AlphaType::Unpremul, None);
235+
236+
if let Some(img) = self.get_image() {
237+
let row_bytes = (info.width() * 4) as usize;
238+
img.read_pixels(&info, buffer, row_bytes, origin, CachingHint::Allow);
239+
}
240+
}
241+
242+
229243
pub fn submit(&mut self) {
230244
#[cfg(any(feature = "gl", feature = "vulkan", feature = "metal"))]
231245
match self.direct_context.as_mut() {

crates/canvas-android/src/jni_compat/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,4 @@ pub mod org_nativescript_canvas_NSCCanvas;
44
pub mod org_nativescript_canvas_NSCCanvasRenderingContext2D;
55
pub mod org_nativescript_canvas_NSCImageAsset;
66
pub mod org_nativescript_canvas_NSCWebGLRenderingContext;
7-
87
pub mod org_nativescript_canvas_NSCImageBitmap;

crates/canvas-c/src/webgpu/gpu_queue.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use super::{
55
gpu_command_encoder::CanvasImageCopyTexture,
66
structs::{CanvasExtent3d, CanvasImageCopyExternalImage, CanvasImageDataLayout},
77
};
8+
use crate::webgpu::enums::CanvasGPUTextureFormat;
89
//use wgpu_core::gfx_select;
910
use crate::webgpu::error::{handle_error, handle_error_fatal};
1011
use crate::webgpu::prelude::label_to_ptr;
@@ -144,6 +145,17 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_copy_webgl_to_texture(
144145
);
145146
}
146147

148+
{
149+
let destination = &*destination;
150+
let texture = &*destination.texture;
151+
match texture.format {
152+
CanvasGPUTextureFormat::Bgra8Unorm | CanvasGPUTextureFormat::Bgra8UnormSrgb => {
153+
canvas_core::image_asset::ImageAsset::rgba_to_bgra_in_place(bytes.as_mut_slice())
154+
}
155+
_ => {}
156+
}
157+
}
158+
147159

148160
let ext_source = CanvasImageCopyExternalImage {
149161
source: bytes.as_ptr(),
@@ -179,9 +191,6 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_copy_context_to_texture(
179191

180192
let (width, height) = context.context.dimensions();
181193

182-
let mut data = vec![0u8; (width * height * 4.) as usize];
183-
184-
context.context.get_pixels(data.as_mut_slice(), (0, 0), (width as i32, height as i32));
185194

186195
let queue = &*queue;
187196
let queue_id = queue.queue.id;
@@ -190,6 +199,17 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_copy_context_to_texture(
190199

191200
let destination_texture = &*destination.texture;
192201

202+
let mut data = vec![0u8; (width * height * 4.) as usize];
203+
204+
match destination_texture.format {
205+
CanvasGPUTextureFormat::Bgra8Unorm | CanvasGPUTextureFormat::Bgra8UnormSrgb => {
206+
context.context.get_pixels_format(data.as_mut_slice(), (0, 0), (width as i32, height as i32), canvas_2d::context::ColorType::BGRA8888);
207+
}
208+
_ => {
209+
context.context.get_pixels(data.as_mut_slice(), (0, 0), (width as i32, height as i32));
210+
}
211+
}
212+
193213
let destination_texture_id = destination_texture.texture;
194214

195215
let size = *size;
@@ -265,7 +285,7 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_copy_image_asset_to_texture(
265285
}
266286
let image_asset = &*source.source;
267287
image_asset.with_bytes_dimension(|bytes, dimension| {
268-
let ext_source = CanvasImageCopyExternalImage {
288+
let mut ext_source = CanvasImageCopyExternalImage {
269289
source: bytes.as_ptr(),
270290
source_size: bytes.len(),
271291
origin: source.origin,
@@ -274,7 +294,23 @@ pub unsafe extern "C" fn canvas_native_webgpu_queue_copy_image_asset_to_texture(
274294
height: dimension.1,
275295
};
276296

277-
canvas_native_webgpu_queue_copy_external_image_to_texture(queue, &ext_source, destination, size);
297+
{
298+
let destination = &*destination;
299+
let texture = &*destination.texture;
300+
match texture.format {
301+
CanvasGPUTextureFormat::Bgra8Unorm | CanvasGPUTextureFormat::Bgra8UnormSrgb => {
302+
let mut bytes = bytes.to_vec();
303+
canvas_core::image_asset::ImageAsset::rgba_to_bgra_in_place(bytes.as_mut_slice());
304+
305+
ext_source.source = bytes.as_ptr();
306+
307+
canvas_native_webgpu_queue_copy_external_image_to_texture(queue, &ext_source, destination, size);
308+
}
309+
_ => {
310+
canvas_native_webgpu_queue_copy_external_image_to_texture(queue, &ext_source, destination, size);
311+
}
312+
}
313+
}
278314
});
279315
}
280316

crates/canvas-core/src/image_asset.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -977,6 +977,12 @@ use core_foundation::string::CFString;
977977
}
978978
}
979979

980+
pub fn rgba_to_bgra_in_place(data: &mut [u8]) {
981+
for chunk in data.chunks_exact_mut(4) {
982+
chunk.swap(0, 2);
983+
}
984+
}
985+
980986

981987
pub fn rgb565_to_rgba8888(data: &[u8]) -> Vec<u8> {
982988
let mut rgba_data = Vec::with_capacity(data.len() * 2);

0 commit comments

Comments
 (0)