webgl: Fall back to canvas if not using hardware acceleration

Display WebGL driver info, detect whether hardware acceleration
is enabled, and fall back to the canvas backend in this case.
This commit is contained in:
Mike Welsh 2020-09-23 14:41:27 -07:00
parent b908b027a9
commit 313b02d24f
3 changed files with 23 additions and 8 deletions

View File

@ -25,6 +25,6 @@ default-features = false
[dependencies.web-sys] [dependencies.web-sys]
version = "0.3.45" version = "0.3.45"
features = ["HtmlCanvasElement", "HtmlElement", "Node", "OesVertexArrayObject", "WebGlBuffer", "WebGlFramebuffer", "WebGlProgram", features = ["HtmlCanvasElement", "HtmlElement", "Node", "OesVertexArrayObject", "WebGlBuffer", "WebglDebugRendererInfo",
"WebGlRenderbuffer", "WebGlRenderingContext", "WebGl2RenderingContext", "WebGlShader", "WebGlTexture", "WebGlUniformLocation", "WebGlFramebuffer", "WebGlProgram", "WebGlRenderbuffer", "WebGlRenderingContext", "WebGl2RenderingContext",
"WebGlVertexArrayObject"] "WebGlShader", "WebGlTexture", "WebGlUniformLocation", "WebGlVertexArrayObject"]

View File

@ -11,7 +11,7 @@ use wasm_bindgen::{JsCast, JsValue};
use web_sys::{ use web_sys::{
HtmlCanvasElement, OesVertexArrayObject, WebGl2RenderingContext as Gl2, WebGlBuffer, HtmlCanvasElement, OesVertexArrayObject, WebGl2RenderingContext as Gl2, WebGlBuffer,
WebGlFramebuffer, WebGlProgram, WebGlRenderbuffer, WebGlRenderingContext as Gl, WebGlShader, WebGlFramebuffer, WebGlProgram, WebGlRenderbuffer, WebGlRenderingContext as Gl, WebGlShader,
WebGlTexture, WebGlUniformLocation, WebGlVertexArrayObject, WebGlTexture, WebGlUniformLocation, WebGlVertexArrayObject, WebglDebugRendererInfo,
}; };
type Error = Box<dyn std::error::Error>; type Error = Box<dyn std::error::Error>;
@ -76,6 +76,7 @@ impl WebGlRenderBackend {
("alpha", JsValue::FALSE), ("alpha", JsValue::FALSE),
("antialias", JsValue::FALSE), ("antialias", JsValue::FALSE),
("depth", JsValue::FALSE), ("depth", JsValue::FALSE),
("failIfMajorPerformanceCaveat", JsValue::TRUE), // fail if no GPU available
]; ];
let context_options = js_sys::Object::new(); let context_options = js_sys::Object::new();
for (name, value) in options.iter() { for (name, value) in options.iter() {
@ -141,6 +142,18 @@ impl WebGlRenderBackend {
} }
}; };
// Get WebGL driver info.
let driver_info = if gl.get_extension("WEBGL_debug_renderer_info").is_ok() {
gl.get_parameter(WebglDebugRendererInfo::UNMASKED_RENDERER_WEBGL)
.ok()
.and_then(|val| val.as_string())
.unwrap_or_else(|| "<unknown>".to_string())
} else {
"<unknown>".to_string()
};
log::info!("WebGL graphics driver: {}", driver_info);
let color_vertex = Self::compile_shader(&gl, Gl::VERTEX_SHADER, COLOR_VERTEX_GLSL)?; let color_vertex = Self::compile_shader(&gl, Gl::VERTEX_SHADER, COLOR_VERTEX_GLSL)?;
let texture_vertex = Self::compile_shader(&gl, Gl::VERTEX_SHADER, TEXTURE_VERTEX_GLSL)?; let texture_vertex = Self::compile_shader(&gl, Gl::VERTEX_SHADER, TEXTURE_VERTEX_GLSL)?;
let color_fragment = Self::compile_shader(&gl, Gl::FRAGMENT_SHADER, COLOR_FRAGMENT_GLSL)?; let color_fragment = Self::compile_shader(&gl, Gl::FRAGMENT_SHADER, COLOR_FRAGMENT_GLSL)?;

View File

@ -835,8 +835,9 @@ fn create_renderer(
.into_js_result()? .into_js_result()?
.dyn_into() .dyn_into()
.map_err(|_| "Expected HtmlCanvasElement")?; .map_err(|_| "Expected HtmlCanvasElement")?;
if let Ok(renderer) = ruffle_render_webgl::WebGlRenderBackend::new(&canvas) { match ruffle_render_webgl::WebGlRenderBackend::new(&canvas) {
return Ok((canvas, Box::new(renderer))); Ok(renderer) => return Ok((canvas, Box::new(renderer))),
Err(error) => log::error!("Error creating WebGL renderer: {}", error),
} }
} }
@ -848,8 +849,9 @@ fn create_renderer(
.into_js_result()? .into_js_result()?
.dyn_into() .dyn_into()
.map_err(|_| "Expected HtmlCanvasElement")?; .map_err(|_| "Expected HtmlCanvasElement")?;
if let Ok(renderer) = ruffle_render_canvas::WebCanvasRenderBackend::new(&canvas) { match ruffle_render_canvas::WebCanvasRenderBackend::new(&canvas) {
return Ok((canvas, Box::new(renderer))); Ok(renderer) => return Ok((canvas, Box::new(renderer))),
Err(error) => log::error!("Error creating canvas renderer: {}", error),
} }
} }