Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

native/wasm: optional WebGL2 support #444

Merged
merged 1 commit into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
141 changes: 75 additions & 66 deletions js/gl.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,10 @@

"use strict";

const version = 1;
const version = 2;

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
14 changes: 10 additions & 4 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 @@ -173,7 +180,7 @@ pub unsafe fn update_cursor() {
// "crate_version" is a misleading, but it can't be changed for legacy reasons.
#[no_mangle]
pub extern "C" fn crate_version() -> u32 {
1
2
}

#[no_mangle]
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
Loading