code review feedback

 - Add warning if both webgl features are active.
 - Add todos
 - Add new example to CI.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index f90d276..0580808 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -329,10 +329,14 @@
         with:
           tool: wasm-pack
 
-      - name: check vello_hybrid is webgl compatible
+      - name: check vello_hybrid is wgpu webgl compatible
         run: wasm-pack test --headless --chrome
         working-directory: sparse_strips/vello_hybrid/examples/wgpu_webgl
 
+      - name: check vello_hybrid is native webgl compatible
+        run: wasm-pack test --headless --chrome
+        working-directory: sparse_strips/vello_hybrid/examples/native_webgl
+
 
   check-stable-android:
     name: cargo check (aarch64-android)
diff --git a/Cargo.lock b/Cargo.lock
index d2e2f18..ca88018 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3245,6 +3245,7 @@
 dependencies = [
  "bytemuck",
  "js-sys",
+ "log",
  "png",
  "pollster",
  "roxmltree",
diff --git a/sparse_strips/vello_hybrid/Cargo.toml b/sparse_strips/vello_hybrid/Cargo.toml
index 34d332e..d2d6836 100644
--- a/sparse_strips/vello_hybrid/Cargo.toml
+++ b/sparse_strips/vello_hybrid/Cargo.toml
@@ -20,6 +20,7 @@
 vello_common = { workspace = true, features = ["std"] }
 wgpu = { workspace = true, optional = true }
 vello_sparse_shaders = { workspace = true, optional = true }
+log = { workspace = true }
 
 
 [target.'cfg(target_arch = "wasm32")'.dependencies]
diff --git a/sparse_strips/vello_hybrid/src/render/common.rs b/sparse_strips/vello_hybrid/src/render/common.rs
index 164120a..ea5503b 100644
--- a/sparse_strips/vello_hybrid/src/render/common.rs
+++ b/sparse_strips/vello_hybrid/src/render/common.rs
@@ -48,3 +48,24 @@
     /// RGBA color value
     pub rgba: u32,
 }
+
+#[cfg(all(target_arch = "wasm32", feature = "webgl", feature = "wgpu"))]
+pub(crate) fn maybe_warn_about_webgl_feature_conflict() {
+    use core::sync::atomic::{AtomicBool, Ordering};
+    static HAS_WARNED: AtomicBool = AtomicBool::new(false);
+
+    if !HAS_WARNED.swap(true, Ordering::Release)
+        && wgpu::Backends::all().contains(wgpu::Backends::GL)
+    {
+        log::warn!(
+            r#"Both WebGL and wgpu with the \"webgl\" feature are enabled.
+For optimal performance and binary size on web targets, use only the dedicated WebGL renderer."#
+        );
+    }
+}
+
+#[cfg(all(
+    any(all(target_arch = "wasm32", feature = "webgl"), feature = "wgpu"),
+    not(all(target_arch = "wasm32", feature = "webgl", feature = "wgpu"))
+))]
+pub(crate) fn maybe_warn_about_webgl_feature_conflict() {}
diff --git a/sparse_strips/vello_hybrid/src/render/webgl.rs b/sparse_strips/vello_hybrid/src/render/webgl.rs
index 023495e..0b14876 100644
--- a/sparse_strips/vello_hybrid/src/render/webgl.rs
+++ b/sparse_strips/vello_hybrid/src/render/webgl.rs
@@ -57,6 +57,8 @@
 impl WebGlRenderer {
     /// Creates a new WebGL2 renderer
     pub fn new(canvas: &web_sys::HtmlCanvasElement) -> Self {
+        super::common::maybe_warn_about_webgl_feature_conflict();
+
         // The WebGL context must be created with anti-aliasing disabled such that we can blit the
         // view framebuffer onto the default framebuffer. This technique is required for the code
         // that converts the WebGPU coordinate system into the WebGL coordinate system, adapted from
@@ -817,6 +819,9 @@
 }
 
 /// Context for WebGL rendering operations.
+// TODO: Improve buffer management. Currently a single buffer is used per resource, which means that
+// the GPU must finish drawing before the next `upload_strips` can be executed (effectively pausing
+// execution). Investigate a buffer pool or creating a new buffer per pass.
 struct WebGlRendererContext<'a> {
     programs: &'a mut WebGlPrograms,
     gl: &'a WebGl2RenderingContext,
diff --git a/sparse_strips/vello_hybrid/src/render/wgpu.rs b/sparse_strips/vello_hybrid/src/render/wgpu.rs
index 7bd994d..aaa5ebe 100644
--- a/sparse_strips/vello_hybrid/src/render/wgpu.rs
+++ b/sparse_strips/vello_hybrid/src/render/wgpu.rs
@@ -58,6 +58,8 @@
 impl Renderer {
     /// Creates a new renderer.
     pub fn new(device: &Device, render_target_config: &RenderTargetConfig) -> Self {
+        super::common::maybe_warn_about_webgl_feature_conflict();
+
         let total_slots =
             (device.limits().max_texture_dimension_2d / u32::from(Tile::HEIGHT)) as usize;