Skip to content

Commit

Permalink
native/wasm: optional WebGL2 support
Browse files Browse the repository at this point in the history
  • Loading branch information
not-fl3 committed Jun 4, 2024
1 parent f08f001 commit 87300b8
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 70 deletions.
1 change: 1 addition & 0 deletions examples/quad.rs
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ fn main() {
} else {
conf::AppleGfxApi::OpenGl
};
conf.platform.webgl_version = conf::WebGLVersion::WebGL2;

miniquad::start(conf, move || Box::new(Stage::new()));
}
Expand Down
139 changes: 74 additions & 65 deletions js/gl.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
const version = 1;

const canvas = document.querySelector("#glcanvas");
const gl = canvas.getContext("webgl");
if (gl === null) {
alert("Unable to initialize WebGL. Your browser or machine may not support it.");
}
var gl;

var clipboard = null;

Expand All @@ -27,6 +24,77 @@ var high_dpi = false;
// if false, requestAnimationFrame will be called at the end of each frame
var blocking_event_loop = false;

function init_webgl(version) {
if (version == 1) {
gl = canvas.getContext("webgl");

function acquireVertexArrayObjectExtension(ctx) {
// Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
var ext = ctx.getExtension('OES_vertex_array_object');
if (ext) {
ctx['createVertexArray'] = function () { return ext['createVertexArrayOES'](); };
ctx['deleteVertexArray'] = function (vao) { ext['deleteVertexArrayOES'](vao); };
ctx['bindVertexArray'] = function (vao) { ext['bindVertexArrayOES'](vao); };
ctx['isVertexArray'] = function (vao) { return ext['isVertexArrayOES'](vao); };
}
else {
alert("Unable to get OES_vertex_array_object extension");
}
}


function acquireInstancedArraysExtension(ctx) {
// Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
var ext = ctx.getExtension('ANGLE_instanced_arrays');
if (ext) {
ctx['vertexAttribDivisor'] = function (index, divisor) { ext['vertexAttribDivisorANGLE'](index, divisor); };
ctx['drawArraysInstanced'] = function (mode, first, count, primcount) { ext['drawArraysInstancedANGLE'](mode, first, count, primcount); };
ctx['drawElementsInstanced'] = function (mode, count, type, indices, primcount) { ext['drawElementsInstancedANGLE'](mode, count, type, indices, primcount); };
}
}

function acquireDisjointTimerQueryExtension(ctx) {
var ext = ctx.getExtension('EXT_disjoint_timer_query');
if (ext) {
ctx['createQuery'] = function () { return ext['createQueryEXT'](); };
ctx['beginQuery'] = function (target, query) { return ext['beginQueryEXT'](target, query); };
ctx['endQuery'] = function (target) { return ext['endQueryEXT'](target); };
ctx['deleteQuery'] = function (query) { ext['deleteQueryEXT'](query); };
ctx['getQueryObject'] = function (query, pname) { return ext['getQueryObjectEXT'](query, pname); };
}
}

function acquireDrawBuffers(ctx) {
var ext = ctx.getExtension('WEBGL_draw_buffers');
if (ext) {
ctx['drawBuffers'] = function (bufs) { return ext['drawBuffersWEBGL'](bufs); };
}
}

try {
gl.getExtension("EXT_shader_texture_lod");
gl.getExtension("OES_standard_derivatives");
} catch (e) {
console.warn(e);
}

acquireVertexArrayObjectExtension(gl);
acquireInstancedArraysExtension(gl);
acquireDisjointTimerQueryExtension(gl);
acquireDrawBuffers(gl);

// https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_depth_texture
if (gl.getExtension('WEBGL_depth_texture') == null) {
alert("Cant initialize WEBGL_depth_texture extension");
}
} else {
gl = canvas.getContext("webgl2");
}
if (gl === null) {
alert("Unable to initialize WebGL. Your browser or machine may not support it.");
}
}

canvas.focus();

canvas.requestPointerLock = canvas.requestPointerLock ||
Expand All @@ -45,66 +113,6 @@ function assert(flag, message) {
}
}

function acquireVertexArrayObjectExtension(ctx) {
// Extension available in WebGL 1 from Firefox 25 and WebKit 536.28/desktop Safari 6.0.3 onwards. Core feature in WebGL 2.
var ext = ctx.getExtension('OES_vertex_array_object');
if (ext) {
ctx['createVertexArray'] = function () { return ext['createVertexArrayOES'](); };
ctx['deleteVertexArray'] = function (vao) { ext['deleteVertexArrayOES'](vao); };
ctx['bindVertexArray'] = function (vao) { ext['bindVertexArrayOES'](vao); };
ctx['isVertexArray'] = function (vao) { return ext['isVertexArrayOES'](vao); };
}
else {
alert("Unable to get OES_vertex_array_object extension");
}
}


function acquireInstancedArraysExtension(ctx) {
// Extension available in WebGL 1 from Firefox 26 and Google Chrome 30 onwards. Core feature in WebGL 2.
var ext = ctx.getExtension('ANGLE_instanced_arrays');
if (ext) {
ctx['vertexAttribDivisor'] = function (index, divisor) { ext['vertexAttribDivisorANGLE'](index, divisor); };
ctx['drawArraysInstanced'] = function (mode, first, count, primcount) { ext['drawArraysInstancedANGLE'](mode, first, count, primcount); };
ctx['drawElementsInstanced'] = function (mode, count, type, indices, primcount) { ext['drawElementsInstancedANGLE'](mode, count, type, indices, primcount); };
}
}

function acquireDisjointTimerQueryExtension(ctx) {
var ext = ctx.getExtension('EXT_disjoint_timer_query');
if (ext) {
ctx['createQuery'] = function () { return ext['createQueryEXT'](); };
ctx['beginQuery'] = function (target, query) { return ext['beginQueryEXT'](target, query); };
ctx['endQuery'] = function (target) { return ext['endQueryEXT'](target); };
ctx['deleteQuery'] = function (query) { ext['deleteQueryEXT'](query); };
ctx['getQueryObject'] = function (query, pname) { return ext['getQueryObjectEXT'](query, pname); };
}
}

function acquireDrawBuffers(ctx) {
var ext = ctx.getExtension('WEBGL_draw_buffers');
if (ext) {
ctx['drawBuffers'] = function (bufs) { return ext['drawBuffersWEBGL'](bufs); };
}
}

try {
gl.getExtension("EXT_shader_texture_lod");
gl.getExtension("OES_standard_derivatives");
} catch (e) {
console.warn(e);
}

acquireVertexArrayObjectExtension(gl);
acquireInstancedArraysExtension(gl);
acquireDisjointTimerQueryExtension(gl);
acquireDrawBuffers(gl);

// https://developer.mozilla.org/en-US/docs/Web/API/WEBGL_depth_texture
if (gl.getExtension('WEBGL_depth_texture') == null) {
alert("Cant initialize WEBGL_depth_texture extension");
}

function getArray(ptr, arr, n) {
return new arr(wasm_memory.buffer, ptr, n);
}
Expand Down Expand Up @@ -1403,7 +1411,8 @@ var importObject = {
window.cancelAnimationFrame(animation_frame_timeout);
}
animation_frame_timeout = window.requestAnimationFrame(animation);
}
},
init_webgl
}
};

Expand Down
13 changes: 13 additions & 0 deletions src/conf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,12 @@ pub enum AppleGfxApi {
Metal,
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum WebGLVersion {
WebGL1,
WebGL2
}

/// Platform specific settings.
#[derive(Debug)]
pub struct Platform {
Expand All @@ -84,6 +90,12 @@ pub struct Platform {
/// Defaults to X11Only. Wayland implementation is way too unstable right now.
pub linux_backend: LinuxBackend,

/// While miniquad itself only use webgl1 features, withing webgl2 context it
/// is possible to:
/// - use gles3 shaders
/// - do raw webgl2 opengl calls
pub webgl_version: WebGLVersion,

/// Which rendering context to create, Metal or OpenGL.
/// Miniquad always links with Metal.framework (assuming it is always present)
/// but it links with OpenGL dynamically and only if required.
Expand Down Expand Up @@ -122,6 +134,7 @@ impl Default for Platform {
linux_x11_gl: LinuxX11Gl::GLXWithEGLFallback,
linux_backend: LinuxBackend::X11Only,
apple_gfx_api: AppleGfxApi::OpenGl,
webgl_version: WebGLVersion::WebGL1,
blocking_event_loop: false,
swap_interval: None,
framebuffer_alpha: false,
Expand Down
10 changes: 8 additions & 2 deletions src/graphics/gl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -745,7 +745,6 @@ impl RenderingBackend for GlContext {
.to_str()
.unwrap()
.to_string();
let gles3 = gl_version_string.contains("OpenGL ES 3");
//let gles2 = !gles3 && gl_version_string.contains("OpenGL ES");

let mut glsl_support = GlslSupport::default();
Expand All @@ -760,10 +759,17 @@ impl RenderingBackend for GlContext {
{
// on web, miniquad always loads EXT_shader_texture_lod and OES_standard_derivatives
glsl_support.v100_ext = true;

let webgl2 = gl_version_string.contains("WebGL 2.0");
if webgl2 {
glsl_support.v300es = true;
}
}

#[cfg(not(target_arch = "wasm32"))]
{
let gles3 = gl_version_string.contains("OpenGL ES 3");

if gles3 {
glsl_support.v300es = true;
}
Expand Down Expand Up @@ -810,7 +816,7 @@ impl RenderingBackend for GlContext {
}

fn delete_texture(&mut self, texture: TextureId) {
self.cache.clear_texture_bindings();
//self.cache.clear_texture_bindings();

let t = self.textures.get(texture);
unsafe {
Expand Down
12 changes: 9 additions & 3 deletions src/native/wasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ pub mod webgl;

mod keycodes;

pub use webgl::*;

use std::{
cell::RefCell,
path::PathBuf,
Expand Down Expand Up @@ -67,6 +65,14 @@ where
}));
}

let version = match conf.platform.webgl_version {
crate::conf::WebGLVersion::WebGL1 => 1,
crate::conf::WebGLVersion::WebGL2 => 2,
};
unsafe {
init_webgl(version);
}

// setup initial canvas size
unsafe {
setup_canvas_size(conf.high_dpi);
Expand Down Expand Up @@ -128,6 +134,7 @@ extern "C" {
pub fn sapp_is_fullscreen() -> bool;
pub fn sapp_set_window_size(new_width: u32, new_height: u32);
pub fn sapp_schedule_update();
pub fn init_webgl(version: i32);
pub fn now() -> f64;
}

Expand Down Expand Up @@ -213,7 +220,6 @@ pub extern "C" fn on_clipboard_paste(msg: *mut u8, len: usize) {
pub extern "C" fn frame() {
REQUESTS.with(|r| {
while let Ok(request) = r.borrow_mut().as_mut().unwrap().try_recv() {
use Request::*;
match request {
Request::SetCursorGrab(grab) => unsafe { sapp_set_cursor_grab(grab) },
Request::ShowMouse(show) => unsafe { show_mouse(show) },
Expand Down

0 comments on commit 87300b8

Please sign in to comment.