-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes for handling base64 src strings on Chrome v38, rework Image texture fallback & detection. This PR includes: * Using a 1x1 PNG pixel to determine which `createImageBitmap` signature is supported on the browser * Fallback the image worker and main thread `ImageTexture` handling according to the detected signature * Support for base64 `src` on Chrome v38 * Support for `createImageBitmap(blob)` without a config object for Chrome v50 (linked to #454) * Support for ES5 legacy output of the `examples` directory (will be published on https://lightning-js.github.io/renderer/ automatically) * Upgrade `vite` and `vitest` to 2.x devDependencies, pin to TS 5.6.x for now (as 5.7.x has issues with other dependencies) * Upgrade Playwright 1.39 to 1.49 for automated tests * Refactor Visual Regression test pixel matching and snapshot handling by using [pixelmatch](https://www.npmjs.com/package/pixelmatch) and [pngjs](https://www.npmjs.com/package/pngjs) over a homebrew detection + upng (which is stale). * SDF font initialization waits for image support detection before uploading the SDF texture atlas. * Added documentation on the fallback process and references to chrome versions in `BROWSERS.md`
- Loading branch information
Showing
22 changed files
with
3,757 additions
and
1,674 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,100 @@ | ||
# Browser Support | ||
|
||
LightningJS is designed with legacy devices in mind, ensuring compatibility with a wide variety of browsers. From **Chrome v38**, released in late 2014, to the latest modern browsers, LightningJS provides a reliable and efficient rendering experience. | ||
|
||
## WebGL Compatibility | ||
|
||
LightningJS relies on **WebGL 1.x** (based on OpenGL ES 2.0) or newer for its rendering capabilities. If WebGL 1.x is supported in the browser, LightningJS will run without issues. Here are some key points about our WebGL implementation: | ||
|
||
- **Independent Rendering**: LightningJS is a contained renderer that uses WebGL, giving us full pixel-for-pixel control over the output. | ||
- **No CSS Dependency**: Unlike traditional DOM/CSS rendering, LightningJS avoids reliance on CSS features, extensions, or browser-specific CSS implementations. | ||
- **Consistency**: In our experience, WebGL support is consistent across browsers. Once LightningJS is confirmed to work in a browser, it will deliver uniform output. | ||
|
||
## Supported Browsers and Quirks | ||
|
||
Below is a detailed breakdown of confirmed browsers that work with LightningJS, along with the quirks or features specific to their versions: | ||
|
||
| **Browser** | **Version** | **Quirks / Features** | | ||
| ------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | | ||
| **Chrome** | v38 | Bottom line for support; introduces Promises. Lacks `createImageBitmap`, iterable `UInt8Array/UInt8ClampedArray`. `ImageData` is mostly broken. | | ||
| | v48 | Adds support for `Blob:` and `Data:` in the Fetch API. | | ||
| | v49 | Introduces Proxies, improving reactive property handling in Blits. Not used in the Renderer. | | ||
| | v50 | Adds `createImageBitmap` (without options object). Enables Image Worker in a web worker. | | ||
| | v52 | Adds `config` for `createImageBitmap`, including support for alpha channel. | | ||
| | v54 | Enables resizing in `createImageBitmap`. | | ||
| | v63 | Adds support for dynamic imports. | | ||
| | v71 | Introduces `globalThis`. | | ||
| **WPEWebKit** | 2017 | Adds support for Image Worker and `createImageBitmap`. | | ||
| | 2.22 | Full support, including Lightning Native mode (disables DOM/CSS compositing except for `<canvas>`, `<video>`, `<audio>` tags). | | ||
| | 2.28 | Full support. | | ||
| | 2.36 | Adds offscreen canvas and shared array buffers with await support for multithreading. | | ||
| | 2.46 | (Upcoming) Adds FTL support for 32-bit devices and offscreen rendering support for Lightning Native. | | ||
|
||
For createImageBitmap the Lightning 3 renderer will use a 1x1 PNG Pixel to validate whether the createImageBitmap API is available and which version can be used. | ||
If the createImageBitmap API is not available it will gracefully fallback to `new Image()` with a performance decrease. | ||
|
||
Lightning 3 prefers to run on **WPEWebKit** with `Lightning Native` (also known as nonCompositedWebGL) enabled for maximum performance! | ||
For more information please see (https://wpewebkit.org/)[https://wpewebkit.org/] | ||
|
||
## Running Lightning in older Browsers | ||
|
||
To run LightningJS in older browsers, you can use **Vite's legacy plugin** and specific polyfills. | ||
|
||
### Installation | ||
|
||
Install the required dependencies: | ||
|
||
```bash | ||
pnpm i -D @vitejs/plugin-legacy whatwg-fetch | ||
``` | ||
|
||
### Configuration | ||
|
||
Add the following to your \`vite.config.js\`: | ||
|
||
```javascript | ||
import legacy from '@vitejs/plugin-legacy'; | ||
|
||
export default { | ||
plugins: [ | ||
legacy({ | ||
targets: ['chrome>=38'], | ||
modernPolyfills: true, | ||
additionalLegacyPolyfills: ['whatwg-fetch'], | ||
}), | ||
], | ||
}; | ||
``` | ||
|
||
### Adjusting Targets | ||
|
||
Modify the \`chrome>=38\` target to match the browser version you need to support. If the target version is **Chrome v71** or higher, or **WPEWebKit 2.22** or newer, the legacy plugin is not required. You can adjust the target in your build configuration: | ||
|
||
```javascript | ||
build: { | ||
target: prodTarget, | ||
}, | ||
esbuild: { | ||
target: devTarget, | ||
}, | ||
``` | ||
|
||
Define the respective targets as follows: | ||
|
||
```javascript | ||
const devTarget = 'es2020'; | ||
const prodTarget = 'es2019'; | ||
``` | ||
|
||
For newer browsers, you can specify a higher target to reduce the use of polyfills and leverage native browser APIs for better performance. | ||
|
||
--- | ||
|
||
## Performance Considerations | ||
|
||
When evaluating performance, it is essential to understand the context of your development and target devices: | ||
|
||
- **64-bit vs. 32-bit**: Your development browser on a PC/Mac runs in 64-bit mode, utilizing higher JIT tiers than the SmartTV/STB devices targeted by LightningJS. | ||
- **Browser Age**: Development browsers are often much newer than the browsers found on Smart TVs or set-top boxes. | ||
- **Targeted Output**: Align your build output with the legacy plugin/targets in Vite to match the browser version for deployment. Minimizing polyfills and leveraging native browser APIs will improve performance. | ||
- **Device Testing**: Always test on target devices early and frequently. An **RPI3b+ with WPEWebKit** or similar ([WPE](https://github.com/webplatformforembedded/buildroot)) can be a great tool for replicating target environments. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import eslintPluginTs from '@typescript-eslint/eslint-plugin'; | ||
import tsParser from '@typescript-eslint/parser'; | ||
|
||
export default [ | ||
{ | ||
files: ['**/*.ts'], | ||
languageOptions: { | ||
parser: tsParser, | ||
parserOptions: { | ||
ecmaVersion: 2022, | ||
sourceType: 'module', | ||
project: [ | ||
'./tsconfig.json', | ||
'./tsconfig.vitest.json', | ||
'./tsconfig.cfg.json', | ||
'./examples/tsconfig.json', | ||
'./visual-regression/tsconfig.json', | ||
'./performance/tsconfig.json', | ||
], | ||
}, | ||
}, | ||
plugins: { | ||
'@typescript-eslint': eslintPluginTs, | ||
}, | ||
rules: { | ||
...eslintPluginTs.configs.recommended.rules, | ||
'@typescript-eslint/no-unsafe-argument': 'warn', | ||
'@typescript-eslint/no-unsafe-assignment': 'warn', | ||
'@typescript-eslint/no-unsafe-return': 'warn', | ||
'@typescript-eslint/no-unsafe-call': 'warn', | ||
'@typescript-eslint/no-non-null-assertion': 'warn', | ||
'@typescript-eslint/no-unsafe-member-access': 'warn', | ||
'@typescript-eslint/ban-ts-comment': 'warn', | ||
'@typescript-eslint/no-explicit-any': 'warn', | ||
'@typescript-eslint/no-unused-vars': 'warn', | ||
'@typescript-eslint/no-empty-object-type': 'warn', | ||
'@typescript-eslint/no-unused-expressions': 'warn', | ||
}, | ||
}, | ||
{ | ||
ignores: [ | ||
'**/dist/**', | ||
'node_modules', | ||
'**config**.ts', | ||
'**/docs/**', | ||
'dist-vitest', | ||
'dist-cfg', | ||
], | ||
}, | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export async function setupMathRandom() { | ||
const mt19937 = await import('@stdlib/random-base-mt19937'); | ||
|
||
const factory = mt19937.factory || mt19937.default.factory; | ||
const rand = factory({ seed: 1234 }); | ||
Math.random = function () { | ||
return rand() / rand.MAX; | ||
}; | ||
console.log('Math.random overridden with mt19937'); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
/* | ||
* If not stated otherwise in this file or this component's LICENSE file the | ||
* following copyright and licenses apply: | ||
* | ||
* Copyright 2023 Comcast Cable Communications Management, LLC. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the License); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
import type { ExampleSettings } from '../common/ExampleSettings.js'; | ||
|
||
export async function automation(settings: ExampleSettings) { | ||
await test(settings); | ||
await settings.snapshot(); | ||
} | ||
|
||
/** | ||
* Load a texture from a base64 encoded string. | ||
* @param settings | ||
*/ | ||
export default async function test(settings: ExampleSettings) { | ||
const { renderer, testRoot } = settings; | ||
const node = renderer.createNode({ | ||
x: 400, | ||
y: 200, | ||
width: 228, | ||
height: 228, | ||
parent: testRoot, | ||
src: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAIAAAB7GkOtAAANHUlEQVR4nOzXjdcWdH3HcW69UcdUsnK4JWtNfDh3SDkyBfF0TM9Ec2SajJwPcE5LDQmtOSNTO5ajURZuuq2EwdZtDxsHXA0EVmFio81QGg3xgIZLGBJYaE+guf0Vn3M65/N6/QGf332u67rP+3wHL7/wqhFJd+76RnT/stPnRPePf35CdH/XTeui+0sueCa6v/srH4zu33LFwuj+2humRfcP2/bT6P6o18+L7o/76NTo/ozr3hDdv/WXn4zur7n/Q9H9J487NLp/SHQdgF9bAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACg1OCW0S9FHxg3tCy6v27WlOj+D097Lrp/246To/vjLz8Y3b/8qs3R/aPPfF90f9EJK6L7+07N/n7WXropuv/ak+ZE96eNfjG6//Kl347uH33vs9H9Y/dkv18XAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQauA3fjAh+sCOd58c3R9/5vui+88MPxTdP+Glg9H9t45aHt1ffdym6P55n/pWdP/p88+J7k/726Ho/uvueiy6f8Zp46P7P9y6Mbo/5bbjovvbNn4kuj970cvRfRcAQCkBACglAAClBACglAAAlBIAgFICAFBKAABKCQBAKQEAKCUAAKUEAKCUAACUEgCAUgIAUEoAAEoJAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBqYMTMN0cfmPp4tjEzvjsrur9o6e7o/sH/fkN0/6wl66P7v/XdTdH9kY/eGd1/6pj90f2HZvxndP8dK2+J7p/xtiej+/M+9IXo/qS5S6P7570/+/nc9M6J0X0XAEApAQAoJQAApQQAoJQAAJQSAIBSAgBQSgAASgkAQCkBACglAAClBACglAAAlBIAgFICAFBK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', | ||
}); | ||
} |
Oops, something went wrong.