awsm/core/webgl/
context.rs1use wasm_bindgen::prelude::*;
2use wasm_bindgen::JsCast;
3use web_sys::HtmlCanvasElement;
4
5use web_sys::{WebGl2RenderingContext, WebGlRenderingContext};
6
7use super::attributes::PartialWebGlAttribute;
8use super::buffers::PartialWebGlBuffer;
9use super::drawing::PartialWebGlDrawing;
10use super::enums::WebGlVersion;
11use super::extensions::PartialWebGlExtensions;
12use super::funcs::PartialWebGlFuncs;
13use super::misc::PartialWebGlMisc;
14use super::query::PartialWebGlQueries;
15use super::shader::PartialWebGlShaders;
16use super::textures::PartialWebGlTextures;
17use super::toggles::PartialWebGlToggle;
18use super::uniforms::PartialWebGlUniforms;
19use super::viewport::PartialWebGlViewport;
20use crate::errors::{Error, NativeError};
21use log::info;
22use serde::Serialize;
23
24pub trait PartialWebGlVersion {
25 fn awsm_get_version(&self) -> WebGlVersion;
26}
27impl PartialWebGlVersion for WebGlRenderingContext {
28 fn awsm_get_version(&self) -> WebGlVersion {
29 WebGlVersion::One
30 }
31}
32
33impl PartialWebGlVersion for WebGl2RenderingContext {
34 fn awsm_get_version(&self) -> WebGlVersion {
35 WebGlVersion::Two
36 }
37}
38
39pub trait PartialWebGlCanvas {
40 fn awsm_get_canvas(&self) -> Result<HtmlCanvasElement, Error>;
41}
42impl PartialWebGlCanvas for WebGlRenderingContext {
43 fn awsm_get_canvas(&self) -> Result<HtmlCanvasElement, Error> {
44 self.canvas()
45 .ok_or(Error::from(NativeError::WebGlCanvas))?
46 .dyn_into::<HtmlCanvasElement>()
47 .map_err(|err| Error::from(NativeError::WebGlCanvas))
48 }
49}
50
51impl PartialWebGlCanvas for WebGl2RenderingContext {
52 fn awsm_get_canvas(&self) -> Result<HtmlCanvasElement, Error> {
53 self.canvas()
54 .ok_or(Error::from(NativeError::WebGlCanvas))?
55 .dyn_into::<HtmlCanvasElement>()
56 .map_err(|err| Error::from(NativeError::WebGlCanvas))
57 }
58}
59pub trait WebGlCommon:
60 PartialWebGlVersion
61 + PartialWebGlCanvas
62 + PartialWebGlAttribute
63 + PartialWebGlQueries
64 + PartialWebGlBuffer
65 + PartialWebGlDrawing
66 + PartialWebGlExtensions
67 + PartialWebGlFuncs
68 + PartialWebGlMisc
69 + PartialWebGlShaders
70 + PartialWebGlTextures
71 + PartialWebGlToggle
72 + PartialWebGlUniforms
73 + PartialWebGlViewport
74{
75}
76
77impl WebGlCommon for WebGlRenderingContext {}
78
79impl WebGlCommon for WebGl2RenderingContext {}
80
81pub struct WebGlContextOptions {
83 pub alpha: bool,
84 pub depth: bool,
85 pub stencil: bool,
86 pub antialias: bool,
87 pub premultiplied_alpha: bool,
88 pub preserve_drawing_buffer: bool,
89 pub power_preference: PowerPreference,
90 pub fail_if_major_performance_caveat: bool,
91 pub desynchronized: bool,
92}
93
94pub enum PowerPreference {
95 Default,
96 HighPerformance,
97 LowPower,
98}
99
100impl Default for WebGlContextOptions {
101 fn default() -> Self {
102 Self {
103 alpha: true,
104 depth: true,
105 stencil: false,
106 antialias: true,
107 premultiplied_alpha: true,
108 preserve_drawing_buffer: false,
109 power_preference: PowerPreference::Default,
110 fail_if_major_performance_caveat: false,
111 desynchronized: false,
112 }
113 }
114}
115
116impl WebGlContextOptions {
117 pub fn to_js_value(&self) -> JsValue {
118 let power_preference = match self.power_preference {
119 PowerPreference::LowPower => "low-power",
120 PowerPreference::HighPerformance => "high-performance",
121 _ => "default",
122 };
123
124 let sanitized = _WebGlContextOptions {
125 alpha: self.alpha,
126 depth: self.depth,
127 stencil: self.stencil,
128 antialias: self.antialias,
129 premultiplied_alpha: self.premultiplied_alpha,
130 preserve_drawing_buffer: self.preserve_drawing_buffer,
131 power_preference,
132 fail_if_major_performance_caveat: self.fail_if_major_performance_caveat,
133 desynchronized: self.desynchronized,
134 };
135
136 serde_wasm_bindgen::to_value(&sanitized).unwrap()
137 }
138}
139
140#[derive(Serialize)]
141#[serde(rename_all = "camelCase")]
142struct _WebGlContextOptions {
143 alpha: bool,
144 depth: bool,
145 stencil: bool,
146 antialias: bool,
147 premultiplied_alpha: bool,
148 preserve_drawing_buffer: bool,
149 power_preference: &'static str,
150 fail_if_major_performance_caveat: bool,
151 desynchronized: bool,
152}
153
154pub fn get_webgl_context_1(
155 canvas: &HtmlCanvasElement,
156 opts: Option<&WebGlContextOptions>,
157) -> Result<WebGlRenderingContext, Error> {
158 info!("Webgl version 1");
159
160 let context = match opts {
161 Some(opts) => canvas.get_context_with_context_options("webgl", &opts.to_js_value()),
162 None => canvas.get_context("webgl"),
163 };
164
165 context
166 .and_then(|obj| match obj {
167 None => Err(Error::Empty.into()),
168 Some(ctx) => ctx
169 .dyn_into::<web_sys::WebGlRenderingContext>()
170 .map_err(|err| err.into()),
171 })
172 .map_err(|_| Error::Native(NativeError::WebGlContext))
173}
174pub fn get_webgl_context_2(
175 canvas: &HtmlCanvasElement,
176 opts: Option<&WebGlContextOptions>,
177) -> Result<WebGl2RenderingContext, Error> {
178 info!("Webgl version 2");
179
180 let context = match opts {
181 Some(opts) => canvas.get_context_with_context_options("webgl2", &opts.to_js_value()),
182 None => canvas.get_context("webgl2"),
183 };
184
185 context
186 .and_then(|obj| match obj {
187 None => Err(Error::Empty.into()),
188 Some(ctx) => ctx
189 .dyn_into::<web_sys::WebGl2RenderingContext>()
190 .map_err(|err| err.into()),
191 })
192 .map_err(|_| Error::Native(NativeError::WebGlContext))
193}