Skip to content

Commit 24c8df5

Browse files
committed
fix(canvas): gl release
1 parent da0f634 commit 24c8df5

47 files changed

Lines changed: 1683 additions & 1605 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -469,17 +469,15 @@ pub extern "system" fn nativeReleaseWebGL(context: jlong) {
469469
if context == 0 {
470470
return;
471471
}
472-
let context = context as *mut WebGLState;
473-
let _ = unsafe { Box::from_raw(context) };
472+
canvas_c::canvas_native_webgl_state_destroy(context as *mut WebGLState);
474473
}
475474

476475
#[no_mangle]
477476
pub extern "system" fn nativeReleaseWebGLNormal(_env: JNIEnv, _: JClass, context: jlong) {
478477
if context == 0 {
479478
return;
480479
}
481-
let context = context as *mut WebGLState;
482-
let _ = unsafe { Box::from_raw(context) };
480+
canvas_c::canvas_native_webgl_state_destroy(context as *mut WebGLState);
483481
}
484482

485483
#[no_mangle]

crates/canvas-c/src/webgl/gl.rs

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,11 @@ use canvas_2d::utils::image::from_image_slice;
1010
use canvas_core::context_attributes::{ColorSpace, PowerPreference};
1111
use canvas_core::gpu::gl::GLContext;
1212
use canvas_webgl::prelude::WebGLVersion;
13+
use std::collections::HashSet;
1314
use std::ffi::{CStr, CString};
1415
use std::os::raw::{c_char, c_void};
1516
use std::ptr::NonNull;
17+
use std::sync::{Mutex, OnceLock};
1618

1719
/* GL */
1820

@@ -275,12 +277,41 @@ impl WebGLState {
275277
}
276278
}
277279

278-
#[no_mangle]
279-
pub extern "C" fn canvas_native_webgl_state_destroy(state: *mut WebGLState) {
280-
if state.is_null() {
280+
// keeps track of all live WebGLState handles so we can avoid double-freeing them
281+
// todo : this is a bit of a hack, but it works for now. We should probably use a more robust solution in the future.
282+
fn webgl_state_live() -> &'static Mutex<HashSet<usize>> {
283+
static LIVE: OnceLock<Mutex<HashSet<usize>>> = OnceLock::new();
284+
LIVE.get_or_init(|| Mutex::new(HashSet::new()))
285+
}
286+
287+
#[inline]
288+
fn webgl_state_register(ptr: *mut WebGLState) -> *mut WebGLState {
289+
if !ptr.is_null() {
290+
webgl_state_live()
291+
.lock()
292+
.unwrap_or_else(|e| e.into_inner())
293+
.insert(ptr as usize);
294+
}
295+
ptr
296+
}
297+
298+
299+
fn webgl_state_free(ptr: *mut WebGLState) {
300+
if ptr.is_null() {
281301
return;
282302
}
283-
let _ = unsafe { Box::from_raw(state) };
303+
let present = webgl_state_live()
304+
.lock()
305+
.unwrap_or_else(|e| e.into_inner())
306+
.remove(&(ptr as usize));
307+
if present {
308+
let _ = unsafe { Box::from_raw(ptr) };
309+
}
310+
}
311+
312+
#[no_mangle]
313+
pub extern "C" fn canvas_native_webgl_state_destroy(state: *mut WebGLState) {
314+
webgl_state_free(state);
284315
}
285316

286317
impl WebGLState {
@@ -1671,7 +1702,7 @@ pub extern "C" fn canvas_native_webgl_create(
16711702
false,
16721703
) {
16731704
None => std::ptr::null_mut(),
1674-
Some(state) => Box::into_raw(Box::new(state)),
1705+
Some(state) => webgl_state_register(Box::into_raw(Box::new(state))),
16751706
}
16761707
}
16771708
_ => std::ptr::null_mut(),
@@ -1715,7 +1746,7 @@ pub extern "C" fn canvas_native_webgl_create(
17151746
false,
17161747
) {
17171748
None => std::ptr::null_mut(),
1718-
Some(state) => Box::into_raw(Box::new(state)),
1749+
Some(state) => webgl_state_register(Box::into_raw(Box::new(state))),
17191750
}
17201751
}
17211752
_ => std::ptr::null_mut(),
@@ -1761,7 +1792,7 @@ pub extern "C" fn canvas_native_webgl_create_no_window(
17611792
is_canvas,
17621793
) {
17631794
None => std::ptr::null_mut(),
1764-
Some(state) => Box::into_raw(Box::new(state)),
1795+
Some(state) => webgl_state_register(Box::into_raw(Box::new(state))),
17651796
}
17661797
}
17671798
_ => std::ptr::null_mut(),

crates/canvas-ios/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -196,8 +196,7 @@ pub extern "C" fn canvas_native_ios_release_webgl(context: i64) {
196196
if context == 0 {
197197
return;
198198
}
199-
let context = context as *mut WebGLState;
200-
let _ = unsafe { Box::from_raw(context) };
199+
canvas_c::canvas_native_webgl_state_destroy(context as *mut WebGLState);
201200
}
202201

203202
#[no_mangle]

crates/canvas-webgl/src/prelude.rs

Lines changed: 54 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![allow(dead_code)]
22
#![allow(non_snake_case)]
33
#![allow(non_camel_case_types)]
4+
#![allow(clippy::too_many_arguments)]
45

56
use std::cell::{Ref, RefCell, RefMut};
67
use std::collections::HashMap;
@@ -9,8 +10,8 @@ use std::os::raw::c_void;
910
use std::ptr::NonNull;
1011
use std::rc::Rc;
1112

12-
use canvas_core::context_attributes::{ColorSpace, ContextAttributes};
1313
use canvas_core::context_attributes::PowerPreference;
14+
use canvas_core::context_attributes::{ColorSpace, ContextAttributes};
1415

1516
pub fn get_sdk_version() -> i32 {
1617
18
@@ -143,19 +144,19 @@ impl WebGLState {
143144
//state.gl_context = GLContext::get_current();
144145
}
145146

146-
fn get_state(&self) -> Ref<WebGLStateInner> {
147+
fn get_state(&'_ self) -> Ref<'_, WebGLStateInner> {
147148
Ref::map(self.state.borrow(), |v| v)
148149
}
149150

150-
fn get_state_mut(&self) -> RefMut<WebGLStateInner> {
151+
fn get_state_mut(&'_ self) -> RefMut<'_, WebGLStateInner> {
151152
RefMut::map(self.state.borrow_mut(), |v| v)
152153
}
153154

154-
fn get_attributes(&self) -> Ref<ContextAttributes> {
155+
fn get_attributes(&'_ self) -> Ref<'_, ContextAttributes> {
155156
Ref::map(self.attributes.borrow(), |v| v)
156157
}
157158

158-
fn get_attributes_mut(&self) -> RefMut<ContextAttributes> {
159+
fn get_attributes_mut(&'_ self) -> RefMut<'_, ContextAttributes> {
159160
RefMut::map(self.attributes.borrow_mut(), |v| v)
160161
}
161162

@@ -220,7 +221,7 @@ impl WebGLState {
220221
false,
221222
false,
222223
version == WebGLVersion::V1,
223-
ColorSpace::Srgb
224+
ColorSpace::Srgb,
224225
))),
225226
state: Rc::new(RefCell::new(WebGLStateInner {
226227
version,
@@ -285,7 +286,7 @@ impl WebGLState {
285286
xr_compatible,
286287
is_canvas,
287288
gl_legacy,
288-
ColorSpace::Srgb
289+
ColorSpace::Srgb,
289290
))),
290291
state: Rc::new(RefCell::new(WebGLStateInner {
291292
version,
@@ -509,28 +510,44 @@ impl WebGLState {
509510

510511
// MAX_COMBINED_TEXTURE_IMAGE_UNITS is available in GLES2 and GLES3
511512
let mut max_units: i32 = 0;
512-
unsafe { gl_bindings::GetIntegerv(gl_bindings::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mut max_units) }
513+
unsafe {
514+
gl_bindings::GetIntegerv(
515+
gl_bindings::MAX_COMBINED_TEXTURE_IMAGE_UNITS,
516+
&mut max_units,
517+
)
518+
}
513519
self.state.borrow_mut().max_combined_texture_image_units = max_units;
514520

515521
if self.get_version() == WebGLVersion::V2 {
516522
let mut max_ub: i32 = 0;
517-
unsafe { gl_bindings::GetIntegerv(gl_bindings::MAX_UNIFORM_BUFFER_BINDINGS, &mut max_ub) }
523+
unsafe {
524+
gl_bindings::GetIntegerv(gl_bindings::MAX_UNIFORM_BUFFER_BINDINGS, &mut max_ub)
525+
}
518526
self.state.borrow_mut().max_uniform_buffer_bindings = max_ub;
519527

520528
let mut max_vub: i32 = 0;
521-
unsafe { gl_bindings::GetIntegerv(gl_bindings::MAX_VERTEX_UNIFORM_BLOCKS, &mut max_vub) }
529+
unsafe {
530+
gl_bindings::GetIntegerv(gl_bindings::MAX_VERTEX_UNIFORM_BLOCKS, &mut max_vub)
531+
}
522532
self.state.borrow_mut().max_vertex_uniform_blocks = max_vub;
523533

524534
let mut max_fub: i32 = 0;
525-
unsafe { gl_bindings::GetIntegerv(gl_bindings::MAX_FRAGMENT_UNIFORM_BLOCKS, &mut max_fub) }
535+
unsafe {
536+
gl_bindings::GetIntegerv(gl_bindings::MAX_FRAGMENT_UNIFORM_BLOCKS, &mut max_fub)
537+
}
526538
self.state.borrow_mut().max_fragment_uniform_blocks = max_fub;
527539

528540
// Quick runtime UBO smoke-test: create a small UBO, bind base, check for GL errors
529541
let mut buf: u32 = 0;
530542
unsafe {
531543
gl_bindings::GenBuffers(1, &mut buf);
532544
gl_bindings::BindBuffer(gl_bindings::UNIFORM_BUFFER, buf);
533-
gl_bindings::BufferData(gl_bindings::UNIFORM_BUFFER, 16, std::ptr::null(), gl_bindings::DYNAMIC_DRAW);
545+
gl_bindings::BufferData(
546+
gl_bindings::UNIFORM_BUFFER,
547+
16,
548+
std::ptr::null(),
549+
gl_bindings::DYNAMIC_DRAW,
550+
);
534551
gl_bindings::BindBufferBase(gl_bindings::UNIFORM_BUFFER, 0, buf);
535552
}
536553
let err = unsafe { gl_bindings::GetError() };
@@ -542,7 +559,10 @@ impl WebGLState {
542559
}
543560
self.state.borrow_mut().gpu_safe = err == gl_bindings::NO_ERROR;
544561
if !self.state.borrow().gpu_safe {
545-
log::warn!("GPU safety probe failed (GetError = {}). Disabling GPU-only paths.", err);
562+
log::warn!(
563+
"GPU safety probe failed (GetError = {}). Disabling GPU-only paths.",
564+
err
565+
);
546566
}
547567
}
548568
}
@@ -565,30 +585,46 @@ impl WebGLState {
565585
/// Get cached active uniform-block count for a program. If not cached and
566586
/// the context is WebGL2, the value is queried from GL and cached.
567587
pub fn get_program_active_uniform_blocks(&self, program: u32) -> Option<i32> {
568-
if let Some(v) = self.state.borrow().program_active_uniform_blocks.get(&program) {
588+
if let Some(v) = self
589+
.state
590+
.borrow()
591+
.program_active_uniform_blocks
592+
.get(&program)
593+
{
569594
return Some(*v);
570595
}
571596
if self.get_version() != WebGLVersion::V2 {
572597
return None;
573598
}
574599
self.context.make_current();
575600
let mut active_blocks: i32 = 0;
576-
unsafe { gl_bindings::GetProgramiv(program, gl_bindings::ACTIVE_UNIFORM_BLOCKS, &mut active_blocks) }
577-
self.state.borrow_mut().program_active_uniform_blocks.insert(program, active_blocks);
601+
unsafe {
602+
gl_bindings::GetProgramiv(
603+
program,
604+
gl_bindings::ACTIVE_UNIFORM_BLOCKS,
605+
&mut active_blocks,
606+
)
607+
}
608+
self.state
609+
.borrow_mut()
610+
.program_active_uniform_blocks
611+
.insert(program, active_blocks);
578612
Some(active_blocks)
579613
}
580614

581615
/// Set the cached active uniform-block count for a program (used after linking)
582616
pub fn set_program_active_uniform_blocks(&mut self, program: u32, count: i32) {
583-
self.state.borrow_mut().program_active_uniform_blocks.insert(program, count);
617+
self.state
618+
.borrow_mut()
619+
.program_active_uniform_blocks
620+
.insert(program, count);
584621
}
585622

586623
/// Remove the current context if it's the stored context. Returns true if it was removed.
587624
pub fn remove_if_current(&mut self) -> bool {
588625
// Delegate to the GLContext's portable helper which returns a bool consistently
589626
self.context.remove_if_current()
590627
}
591-
592628
}
593629

594630
#[derive(Clone)]

packages/canvas/platforms/ios/CanvasNative.xcframework/Info.plist

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,34 @@
4444
<key>DebugSymbolsPath</key>
4545
<string>dSYMs</string>
4646
<key>LibraryIdentifier</key>
47-
<string>ios-arm64</string>
47+
<string>ios-arm64_x86_64-simulator</string>
4848
<key>LibraryPath</key>
4949
<string>CanvasNative.framework</string>
5050
<key>SupportedArchitectures</key>
5151
<array>
5252
<string>arm64</string>
53+
<string>x86_64</string>
5354
</array>
5455
<key>SupportedPlatform</key>
5556
<string>ios</string>
57+
<key>SupportedPlatformVariant</key>
58+
<string>simulator</string>
5659
</dict>
5760
<dict>
5861
<key>BinaryPath</key>
5962
<string>CanvasNative.framework/CanvasNative</string>
6063
<key>DebugSymbolsPath</key>
6164
<string>dSYMs</string>
6265
<key>LibraryIdentifier</key>
63-
<string>ios-arm64_x86_64-simulator</string>
66+
<string>ios-arm64</string>
6467
<key>LibraryPath</key>
6568
<string>CanvasNative.framework</string>
6669
<key>SupportedArchitectures</key>
6770
<array>
6871
<string>arm64</string>
69-
<string>x86_64</string>
7072
</array>
7173
<key>SupportedPlatform</key>
7274
<string>ios</string>
73-
<key>SupportedPlatformVariant</key>
74-
<string>simulator</string>
7575
</dict>
7676
</array>
7777
<key>CFBundlePackageType</key>

0 commit comments

Comments
 (0)