|
| 1 | +// Copyright (C) 2023-2025 Lightpanda (Selecy SAS) |
| 2 | +// |
| 3 | +// Francis Bouvier <[email protected]> |
| 4 | +// Pierre Tachoire <[email protected]> |
| 5 | +// |
| 6 | +// This program is free software: you can redistribute it and/or modify |
| 7 | +// it under the terms of the GNU Affero General Public License as |
| 8 | +// published by the Free Software Foundation, either version 3 of the |
| 9 | +// License, or (at your option) any later version. |
| 10 | +// |
| 11 | +// This program is distributed in the hope that it will be useful, |
| 12 | +// but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 | +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 14 | +// GNU Affero General Public License for more details. |
| 15 | +// |
| 16 | +// You should have received a copy of the GNU Affero General Public License |
| 17 | +// along with this program. If not, see <https://www.gnu.org/licenses/>. |
| 18 | + |
| 19 | +const std = @import("std"); |
| 20 | + |
| 21 | +const WebGLRenderingContext = @This(); |
| 22 | +_: u8 = 0, |
| 23 | + |
| 24 | +/// On Chrome and Safari, a call to `getSupportedExtensions` returns total of 39. |
| 25 | +/// The reference for it lists lesser number of extensions: |
| 26 | +/// https://developer.mozilla.org/en-US/docs/Web/API/WebGL_API/Using_Extensions#extension_list |
| 27 | +pub const Extension = union(enum) { |
| 28 | + ANGLE_instanced_arrays: void, |
| 29 | + EXT_blend_minmax: void, |
| 30 | + EXT_clip_control: void, |
| 31 | + EXT_color_buffer_half_float: void, |
| 32 | + EXT_depth_clamp: void, |
| 33 | + EXT_disjoint_timer_query: void, |
| 34 | + EXT_float_blend: void, |
| 35 | + EXT_frag_depth: void, |
| 36 | + EXT_polygon_offset_clamp: void, |
| 37 | + EXT_shader_texture_lod: void, |
| 38 | + EXT_texture_compression_bptc: void, |
| 39 | + EXT_texture_compression_rgtc: void, |
| 40 | + EXT_texture_filter_anisotropic: void, |
| 41 | + EXT_texture_mirror_clamp_to_edge: void, |
| 42 | + EXT_sRGB: void, |
| 43 | + KHR_parallel_shader_compile: void, |
| 44 | + OES_element_index_uint: void, |
| 45 | + OES_fbo_render_mipmap: void, |
| 46 | + OES_standard_derivatives: void, |
| 47 | + OES_texture_float: void, |
| 48 | + OES_texture_float_linear: void, |
| 49 | + OES_texture_half_float: void, |
| 50 | + OES_texture_half_float_linear: void, |
| 51 | + OES_vertex_array_object: void, |
| 52 | + WEBGL_blend_func_extended: void, |
| 53 | + WEBGL_color_buffer_float: void, |
| 54 | + WEBGL_compressed_texture_astc: void, |
| 55 | + WEBGL_compressed_texture_etc: void, |
| 56 | + WEBGL_compressed_texture_etc1: void, |
| 57 | + WEBGL_compressed_texture_pvrtc: void, |
| 58 | + WEBGL_compressed_texture_s3tc: void, |
| 59 | + WEBGL_compressed_texture_s3tc_srgb: void, |
| 60 | + WEBGL_debug_renderer_info: Type.WEBGL_debug_renderer_info, |
| 61 | + WEBGL_debug_shaders: void, |
| 62 | + WEBGL_depth_texture: void, |
| 63 | + WEBGL_draw_buffers: void, |
| 64 | + WEBGL_lose_context: Type.WEBGL_lose_context, |
| 65 | + WEBGL_multi_draw: void, |
| 66 | + WEBGL_polygon_mode: void, |
| 67 | + |
| 68 | + /// Reified enum type from the fields of this union. |
| 69 | + const Kind = blk: { |
| 70 | + const info = @typeInfo(Extension).@"union"; |
| 71 | + const fields = info.fields; |
| 72 | + var items: [fields.len]std.builtin.Type.EnumField = undefined; |
| 73 | + for (fields, 0..) |field, i| { |
| 74 | + items[i] = .{ .name = field.name, .value = i }; |
| 75 | + } |
| 76 | + |
| 77 | + break :blk @Type(.{ |
| 78 | + .@"enum" = .{ |
| 79 | + .tag_type = std.math.IntFittingRange(0, if (fields.len == 0) 0 else fields.len - 1), |
| 80 | + .fields = &items, |
| 81 | + .decls = &.{}, |
| 82 | + .is_exhaustive = true, |
| 83 | + }, |
| 84 | + }); |
| 85 | + }; |
| 86 | + |
| 87 | + /// Returns the `Extension.Kind` by its name. |
| 88 | + fn find(name: []const u8) ?Kind { |
| 89 | + // Just to make you really sad, this function has to be case-insensitive. |
| 90 | + // So here we copy what's being done in `std.meta.stringToEnum` but replace |
| 91 | + // the comparison function. |
| 92 | + const kvs = comptime build_kvs: { |
| 93 | + const T = Extension.Kind; |
| 94 | + const EnumKV = struct { []const u8, T }; |
| 95 | + var kvs_array: [@typeInfo(T).@"enum".fields.len]EnumKV = undefined; |
| 96 | + for (@typeInfo(T).@"enum".fields, 0..) |enumField, i| { |
| 97 | + kvs_array[i] = .{ enumField.name, @field(T, enumField.name) }; |
| 98 | + } |
| 99 | + break :build_kvs kvs_array[0..]; |
| 100 | + }; |
| 101 | + const Map = std.StaticStringMapWithEql(Extension.Kind, std.static_string_map.eqlAsciiIgnoreCase); |
| 102 | + const map = Map.initComptime(kvs); |
| 103 | + return map.get(name); |
| 104 | + } |
| 105 | + |
| 106 | + /// Extension types. |
| 107 | + pub const Type = struct { |
| 108 | + pub const WEBGL_debug_renderer_info = struct { |
| 109 | + pub const UNMASKED_VENDOR_WEBGL: u64 = 0x9245; |
| 110 | + pub const UNMASKED_RENDERER_WEBGL: u64 = 0x9246; |
| 111 | + |
| 112 | + pub fn get_UNMASKED_VENDOR_WEBGL() u64 { |
| 113 | + return UNMASKED_VENDOR_WEBGL; |
| 114 | + } |
| 115 | + |
| 116 | + pub fn get_UNMASKED_RENDERER_WEBGL() u64 { |
| 117 | + return UNMASKED_RENDERER_WEBGL; |
| 118 | + } |
| 119 | + }; |
| 120 | + |
| 121 | + pub const WEBGL_lose_context = struct { |
| 122 | + _: u8 = 0, |
| 123 | + pub fn _loseContext(_: *const WEBGL_lose_context) void {} |
| 124 | + pub fn _restoreContext(_: *const WEBGL_lose_context) void {} |
| 125 | + }; |
| 126 | + }; |
| 127 | +}; |
| 128 | + |
| 129 | +/// Enables a WebGL extension. |
| 130 | +pub fn _getExtension(self: *const WebGLRenderingContext, name: []const u8) ?Extension { |
| 131 | + _ = self; |
| 132 | + |
| 133 | + const tag = Extension.find(name) orelse return null; |
| 134 | + |
| 135 | + return switch (tag) { |
| 136 | + .WEBGL_debug_renderer_info => @unionInit(Extension, "WEBGL_debug_renderer_info", .{}), |
| 137 | + .WEBGL_lose_context => @unionInit(Extension, "WEBGL_lose_context", .{}), |
| 138 | + inline else => |comptime_enum| @unionInit(Extension, @tagName(comptime_enum), {}), |
| 139 | + }; |
| 140 | +} |
| 141 | + |
| 142 | +/// Returns a list of all the supported WebGL extensions. |
| 143 | +pub fn _getSupportedExtensions(_: *const WebGLRenderingContext) []const []const u8 { |
| 144 | + return std.meta.fieldNames(Extension.Kind); |
| 145 | +} |
0 commit comments