@@ -33,32 +33,53 @@ impl Instance {
33
33
& self ,
34
34
canvas : & web_sys:: HtmlCanvasElement ,
35
35
) -> Result < Surface , crate :: InstanceError > {
36
- let webgl2_context = canvas
37
- . get_context_with_context_options ( "webgl2" , & Self :: create_context_options ( ) )
38
- . expect ( "Cannot create WebGL2 context" )
39
- . and_then ( |context| context. dyn_into :: < web_sys:: WebGl2RenderingContext > ( ) . ok ( ) )
40
- . expect ( "Cannot convert into WebGL2 context" ) ;
41
-
42
- * self . webgl2_context . lock ( ) = Some ( webgl2_context. clone ( ) ) ;
43
-
44
- Ok ( Surface {
45
- webgl2_context,
46
- srgb_present_program : None ,
47
- swapchain : None ,
48
- texture : None ,
49
- presentable : true ,
50
- } )
36
+ self . create_surface_from_context (
37
+ canvas. get_context_with_context_options ( "webgl2" , & Self :: create_context_options ( ) ) ,
38
+ )
51
39
}
52
40
53
41
pub fn create_surface_from_offscreen_canvas (
54
42
& self ,
55
43
canvas : & web_sys:: OffscreenCanvas ,
56
44
) -> Result < Surface , crate :: InstanceError > {
57
- let webgl2_context = canvas
58
- . get_context_with_context_options ( "webgl2" , & Self :: create_context_options ( ) )
59
- . expect ( "Cannot create WebGL2 context" )
60
- . and_then ( |context| context. dyn_into :: < web_sys:: WebGl2RenderingContext > ( ) . ok ( ) )
61
- . expect ( "Cannot convert into WebGL2 context" ) ;
45
+ self . create_surface_from_context (
46
+ canvas. get_context_with_context_options ( "webgl2" , & Self :: create_context_options ( ) ) ,
47
+ )
48
+ }
49
+
50
+ /// Common portion of public `create_surface_from_*` functions.
51
+ ///
52
+ /// Note: Analogous code also exists in the WebGPU backend at
53
+ /// `wgpu::backend::web::Context`.
54
+ fn create_surface_from_context (
55
+ & self ,
56
+ context_result : Result < Option < js_sys:: Object > , wasm_bindgen:: JsValue > ,
57
+ ) -> Result < Surface , crate :: InstanceError > {
58
+ let context_object: js_sys:: Object = match context_result {
59
+ Ok ( Some ( context) ) => context,
60
+ Ok ( None ) => {
61
+ // <https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-getcontext-dev>
62
+ // A getContext() call “returns null if contextId is not supported, or if the
63
+ // canvas has already been initialized with another context type”. Additionally,
64
+ // “not supported” could include “insufficient GPU resources” or “the GPU process
65
+ // previously crashed”. So, we must return it as an `Err` since it could occur
66
+ // for circumstances outside the application author's control.
67
+ return Err ( crate :: InstanceError ) ;
68
+ }
69
+ Err ( js_error) => {
70
+ // <https://html.spec.whatwg.org/multipage/canvas.html#dom-canvas-getcontext>
71
+ // A thrown exception indicates misuse of the canvas state. Ideally we wouldn't
72
+ // panic in this case, but for now, `InstanceError` conveys no detail, so it
73
+ // is more informative to panic with a specific message.
74
+ panic ! ( "canvas.getContext() threw {js_error:?}" )
75
+ }
76
+ } ;
77
+
78
+ // Not returning this error because it is a type error that shouldn't happen unless
79
+ // the browser, JS builtin objects, or wasm bindings are misbehaving somehow.
80
+ let webgl2_context: web_sys:: WebGl2RenderingContext = context_object
81
+ . dyn_into ( )
82
+ . expect ( "canvas context is not a WebGl2RenderingContext" ) ;
62
83
63
84
* self . webgl2_context . lock ( ) = Some ( webgl2_context. clone ( ) ) ;
64
85
0 commit comments