@lightningjs/renderer 0.8.2 → 0.8.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (153) hide show
  1. package/dist/src/core/CoreNode.d.ts +27 -1
  2. package/dist/src/core/CoreNode.js +130 -5
  3. package/dist/src/core/CoreNode.js.map +1 -1
  4. package/dist/src/core/CoreShaderManager.d.ts +2 -0
  5. package/dist/src/core/CoreShaderManager.js +9 -0
  6. package/dist/src/core/CoreShaderManager.js.map +1 -1
  7. package/dist/src/core/CoreTextNode.js +20 -1
  8. package/dist/src/core/CoreTextNode.js.map +1 -1
  9. package/dist/src/core/CoreTextureManager.d.ts +2 -0
  10. package/dist/src/core/CoreTextureManager.js +2 -0
  11. package/dist/src/core/CoreTextureManager.js.map +1 -1
  12. package/dist/src/core/Stage.d.ts +3 -2
  13. package/dist/src/core/Stage.js +36 -10
  14. package/dist/src/core/Stage.js.map +1 -1
  15. package/dist/src/core/TextureMemoryManager.d.ts +1 -0
  16. package/dist/src/core/TextureMemoryManager.js +3 -1
  17. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  18. package/dist/src/core/lib/ImageWorker.d.ts +2 -1
  19. package/dist/src/core/lib/ImageWorker.js +11 -7
  20. package/dist/src/core/lib/ImageWorker.js.map +1 -1
  21. package/dist/src/core/lib/WebGlContextWrapper.d.ts +26 -1
  22. package/dist/src/core/lib/WebGlContextWrapper.js +37 -1
  23. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  24. package/dist/src/core/renderers/CoreRenderer.d.ts +32 -3
  25. package/dist/src/core/renderers/CoreRenderer.js +14 -2
  26. package/dist/src/core/renderers/CoreRenderer.js.map +1 -1
  27. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.d.ts +22 -0
  28. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js +166 -0
  29. package/dist/src/core/renderers/canvas/CanvasCoreRenderer.js.map +1 -0
  30. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +17 -0
  31. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +124 -0
  32. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -0
  33. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.d.ts +5 -0
  34. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js +32 -0
  35. package/dist/src/core/renderers/canvas/internal/C2DShaderUtils.js.map +1 -0
  36. package/dist/src/core/renderers/canvas/internal/ColorUtils.d.ts +15 -0
  37. package/dist/src/core/renderers/canvas/internal/ColorUtils.js +45 -0
  38. package/dist/src/core/renderers/canvas/internal/ColorUtils.js.map +1 -0
  39. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.d.ts +10 -0
  40. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js +43 -0
  41. package/dist/src/core/renderers/canvas/shaders/UnsupportedShader.js.map +1 -0
  42. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.d.ts +11 -0
  43. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js +51 -0
  44. package/dist/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.js.map +1 -0
  45. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +11 -1
  46. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +22 -11
  47. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  48. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.d.ts +4 -1
  49. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js +7 -2
  50. package/dist/src/core/renderers/webgl/WebGlCoreRenderOp.js.map +1 -1
  51. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.d.ts +18 -21
  52. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js +121 -41
  53. package/dist/src/core/renderers/webgl/WebGlCoreRenderer.js.map +1 -1
  54. package/dist/src/core/renderers/webgl/WebGlCoreShader.js +19 -4
  55. package/dist/src/core/renderers/webgl/WebGlCoreShader.js.map +1 -1
  56. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js +4 -6
  57. package/dist/src/core/renderers/webgl/shaders/DefaultShader.js.map +1 -1
  58. package/dist/src/core/renderers/webgl/shaders/SdfShader.js +6 -1
  59. package/dist/src/core/renderers/webgl/shaders/SdfShader.js.map +1 -1
  60. package/dist/src/core/text-rendering/TextRenderingUtils.d.ts +12 -0
  61. package/dist/src/core/text-rendering/TextRenderingUtils.js +14 -0
  62. package/dist/src/core/text-rendering/TextRenderingUtils.js.map +1 -0
  63. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.d.ts +2 -1
  64. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +6 -3
  65. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  66. package/dist/src/core/text-rendering/renderers/TextRenderer.d.ts +2 -1
  67. package/dist/src/core/text-rendering/renderers/TextRenderer.js.map +1 -1
  68. package/dist/src/core/textures/ImageTexture.js +3 -0
  69. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  70. package/dist/src/core/textures/RenderTexture.d.ts +28 -0
  71. package/dist/src/core/textures/RenderTexture.js +52 -0
  72. package/dist/src/core/textures/RenderTexture.js.map +1 -0
  73. package/dist/src/core/utils.d.ts +6 -1
  74. package/dist/src/core/utils.js +74 -82
  75. package/dist/src/core/utils.js.map +1 -1
  76. package/dist/src/main-api/INode.d.ts +9 -0
  77. package/dist/src/main-api/Inspector.js +7 -1
  78. package/dist/src/main-api/Inspector.js.map +1 -1
  79. package/dist/src/main-api/RendererMain.d.ts +4 -0
  80. package/dist/src/main-api/RendererMain.js +2 -0
  81. package/dist/src/main-api/RendererMain.js.map +1 -1
  82. package/dist/src/render-drivers/main/MainCoreDriver.js +1 -0
  83. package/dist/src/render-drivers/main/MainCoreDriver.js.map +1 -1
  84. package/dist/src/render-drivers/main/MainOnlyNode.d.ts +3 -0
  85. package/dist/src/render-drivers/main/MainOnlyNode.js +29 -0
  86. package/dist/src/render-drivers/main/MainOnlyNode.js.map +1 -1
  87. package/dist/src/render-drivers/main/MainOnlyTextNode.js +1 -0
  88. package/dist/src/render-drivers/main/MainOnlyTextNode.js.map +1 -1
  89. package/dist/src/render-drivers/threadx/NodeStruct.d.ts +3 -0
  90. package/dist/src/render-drivers/threadx/NodeStruct.js +9 -0
  91. package/dist/src/render-drivers/threadx/NodeStruct.js.map +1 -1
  92. package/dist/src/render-drivers/threadx/SharedNode.d.ts +1 -0
  93. package/dist/src/render-drivers/threadx/SharedNode.js +1 -0
  94. package/dist/src/render-drivers/threadx/SharedNode.js.map +1 -1
  95. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js +2 -0
  96. package/dist/src/render-drivers/threadx/ThreadXCoreDriver.js.map +1 -1
  97. package/dist/src/render-drivers/threadx/ThreadXMainNode.d.ts +3 -0
  98. package/dist/src/render-drivers/threadx/ThreadXMainNode.js +7 -0
  99. package/dist/src/render-drivers/threadx/ThreadXMainNode.js.map +1 -1
  100. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js +1 -0
  101. package/dist/src/render-drivers/threadx/worker/ThreadXRendererNode.js.map +1 -1
  102. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js +1 -0
  103. package/dist/src/render-drivers/threadx/worker/ThreadXRendererTextNode.js.map +1 -1
  104. package/dist/src/render-drivers/threadx/worker/renderer.js +2 -0
  105. package/dist/src/render-drivers/threadx/worker/renderer.js.map +1 -1
  106. package/dist/src/render-drivers/utils.js +1 -1
  107. package/dist/src/render-drivers/utils.js.map +1 -1
  108. package/dist/src/utils.d.ts +12 -6
  109. package/dist/src/utils.js +19 -9
  110. package/dist/src/utils.js.map +1 -1
  111. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  112. package/package.json +1 -1
  113. package/src/core/CoreNode.ts +164 -8
  114. package/src/core/CoreShaderManager.ts +13 -0
  115. package/src/core/CoreTextNode.ts +25 -0
  116. package/src/core/CoreTextureManager.ts +3 -0
  117. package/src/core/Stage.ts +44 -10
  118. package/src/core/TextureMemoryManager.ts +3 -1
  119. package/src/core/lib/ImageWorker.ts +13 -8
  120. package/src/core/lib/WebGlContextWrapper.ts +51 -1
  121. package/src/core/renderers/CoreRenderer.ts +46 -6
  122. package/src/core/renderers/canvas/CanvasCoreRenderer.ts +223 -0
  123. package/src/core/renderers/canvas/CanvasCoreTexture.ts +144 -0
  124. package/src/core/renderers/canvas/internal/C2DShaderUtils.ts +37 -0
  125. package/src/core/renderers/canvas/internal/ColorUtils.ts +55 -0
  126. package/src/core/renderers/canvas/shaders/UnsupportedShader.ts +48 -0
  127. package/src/core/renderers/webgl/WebGlCoreCtxRenderTexture.ts +79 -0
  128. package/src/core/renderers/webgl/WebGlCoreCtxTexture.ts +26 -24
  129. package/src/core/renderers/webgl/WebGlCoreRenderOp.ts +4 -2
  130. package/src/core/renderers/webgl/WebGlCoreRenderer.ts +173 -70
  131. package/src/core/renderers/webgl/WebGlCoreShader.ts +29 -4
  132. package/src/core/renderers/webgl/shaders/DefaultShader.ts +4 -6
  133. package/src/core/renderers/webgl/shaders/SdfShader.ts +6 -1
  134. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +10 -1
  135. package/src/core/text-rendering/renderers/TextRenderer.ts +3 -0
  136. package/src/core/textures/ImageTexture.ts +3 -0
  137. package/src/core/textures/RenderTexture.ts +81 -0
  138. package/src/core/utils.ts +101 -93
  139. package/src/main-api/INode.ts +11 -0
  140. package/src/main-api/Inspector.ts +6 -1
  141. package/src/main-api/RendererMain.ts +8 -0
  142. package/src/render-drivers/main/MainCoreDriver.ts +1 -0
  143. package/src/render-drivers/main/MainOnlyNode.ts +44 -0
  144. package/src/render-drivers/main/MainOnlyTextNode.ts +1 -0
  145. package/src/render-drivers/threadx/NodeStruct.ts +10 -0
  146. package/src/render-drivers/threadx/SharedNode.ts +2 -0
  147. package/src/render-drivers/threadx/ThreadXCoreDriver.ts +2 -0
  148. package/src/render-drivers/threadx/ThreadXMainNode.ts +9 -0
  149. package/src/render-drivers/threadx/worker/ThreadXRendererNode.ts +1 -0
  150. package/src/render-drivers/threadx/worker/ThreadXRendererTextNode.ts +1 -0
  151. package/src/render-drivers/threadx/worker/renderer.ts +2 -0
  152. package/src/render-drivers/utils.ts +1 -1
  153. package/src/utils.ts +21 -9
@@ -115,29 +115,8 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
115
115
  async onLoadRequest(): Promise<Dimensions> {
116
116
  const { glw, memManager } = this;
117
117
 
118
- // On initial load request, create a 1x1 transparent texture to use until
119
- // the texture data is finally loaded.
120
- glw.activeTexture(0);
121
- glw.bindTexture(this._nativeCtxTexture);
122
-
123
- // linear texture filtering
124
- glw.texParameteri(glw.TEXTURE_MAG_FILTER, glw.LINEAR);
125
- glw.texParameteri(glw.TEXTURE_MIN_FILTER, glw.LINEAR);
126
-
127
- // texture wrapping method
128
- glw.texParameteri(glw.TEXTURE_WRAP_S, glw.CLAMP_TO_EDGE);
129
- glw.texParameteri(glw.TEXTURE_WRAP_T, glw.CLAMP_TO_EDGE);
130
-
131
- glw.texImage2D(
132
- 0,
133
- glw.RGBA,
134
- 1,
135
- 1,
136
- 0,
137
- glw.RGBA,
138
- glw.UNSIGNED_BYTE,
139
- TRANSPARENT_TEXTURE_DATA,
140
- );
118
+ // Set to a 1x1 transparent texture
119
+ glw.texImage2D(0, glw.RGBA, 1, 1, 0, glw.RGBA, glw.UNSIGNED_BYTE, null);
141
120
  memManager.setTextureMemUse(this, TRANSPARENT_TEXTURE_DATA.byteLength);
142
121
 
143
122
  const textureData = await this.textureSource?.getTextureData();
@@ -250,12 +229,35 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
250
229
  this._nativeCtxTexture = null;
251
230
  }
252
231
 
253
- private createNativeCtxTexture() {
232
+ /**
233
+ * Create native context texture
234
+ *
235
+ * @remarks
236
+ * When this method returns the returned texture will be bound to the GL context state.
237
+ *
238
+ * @param width
239
+ * @param height
240
+ * @returns
241
+ */
242
+ protected createNativeCtxTexture() {
254
243
  const { glw } = this;
255
244
  const nativeTexture = glw.createTexture();
256
245
  if (!nativeTexture) {
257
246
  throw new Error('Could not create WebGL Texture');
258
247
  }
248
+
249
+ // On initial load request, create a 1x1 transparent texture to use until
250
+ // the texture data is finally loaded.
251
+ glw.activeTexture(0);
252
+ glw.bindTexture(nativeTexture);
253
+
254
+ // linear texture filtering
255
+ glw.texParameteri(glw.TEXTURE_MAG_FILTER, glw.LINEAR);
256
+ glw.texParameteri(glw.TEXTURE_MIN_FILTER, glw.LINEAR);
257
+
258
+ // texture wrapping method
259
+ glw.texParameteri(glw.TEXTURE_WRAP_S, glw.CLAMP_TO_EDGE);
260
+ glw.texParameteri(glw.TEXTURE_WRAP_T, glw.CLAMP_TO_EDGE);
259
261
  return nativeTexture;
260
262
  }
261
263
  }
@@ -49,6 +49,9 @@ export class WebGlCoreRenderOp extends CoreRenderOp {
49
49
  readonly dimensions: Dimensions,
50
50
  readonly bufferIdx: number,
51
51
  readonly zIndex: number,
52
+ readonly renderToTexture: boolean | undefined,
53
+ readonly parentHasRenderTexture: boolean | undefined,
54
+ readonly framebufferDimensions: Dimensions | undefined,
52
55
  ) {
53
56
  super();
54
57
  this.maxTextures = shader.supportsIndexedTextures
@@ -72,9 +75,8 @@ export class WebGlCoreRenderOp extends CoreRenderOp {
72
75
 
73
76
  draw() {
74
77
  const { glw, shader, shaderProps, options } = this;
75
- // shaderOp.draw(this);
76
-
77
78
  const { shManager } = options;
79
+
78
80
  shManager.useShader(shader);
79
81
  shader.bindRenderOp(this, shaderProps);
80
82
 
@@ -17,13 +17,12 @@
17
17
  * limitations under the License.
18
18
  */
19
19
 
20
+ import { assertTruthy, createWebGLContext, hasOwn } from '../../../utils.js';
20
21
  import {
21
- assertTruthy,
22
- createWebGLContext,
23
- hasOwn,
24
- mergeColorAlphaPremultiplied,
25
- } from '../../../utils.js';
26
- import { CoreRenderer, type QuadOptions } from '../CoreRenderer.js';
22
+ CoreRenderer,
23
+ type CoreRendererOptions,
24
+ type QuadOptions,
25
+ } from '../CoreRenderer.js';
27
26
  import { WebGlCoreRenderOp } from './WebGlCoreRenderOp.js';
28
27
  import type { CoreContextTexture } from '../CoreContextTexture.js';
29
28
  import {
@@ -36,43 +35,26 @@ import {
36
35
  import { WebGlCoreCtxTexture } from './WebGlCoreCtxTexture.js';
37
36
  import { Texture } from '../../textures/Texture.js';
38
37
  import { ColorTexture } from '../../textures/ColorTexture.js';
39
- import type { Stage } from '../../Stage.js';
40
38
  import { SubTexture } from '../../textures/SubTexture.js';
41
39
  import { WebGlCoreCtxSubTexture } from './WebGlCoreCtxSubTexture.js';
42
- import type {
43
- CoreTextureManager,
44
- TextureOptions,
45
- } from '../../CoreTextureManager.js';
46
40
  import { CoreShaderManager } from '../../CoreShaderManager.js';
47
- import type { CoreShader } from '../CoreShader.js';
48
41
  import { BufferCollection } from './internal/BufferCollection.js';
49
42
  import {
50
43
  compareRect,
51
44
  getNormalizedRgbaComponents,
52
- type Rect,
53
45
  type RectWithValid,
54
46
  } from '../../lib/utils.js';
55
47
  import type { Dimensions } from '../../../common/CommonTypes.js';
56
48
  import { WebGlCoreShader } from './WebGlCoreShader.js';
57
- import { RoundedRectangle } from './shaders/RoundedRectangle.js';
58
- import { ContextSpy } from '../../lib/ContextSpy.js';
59
49
  import { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
60
- import type { TextureMemoryManager } from '../../TextureMemoryManager.js';
50
+ import { RenderTexture } from '../../textures/RenderTexture.js';
51
+ import type { CoreNode } from '../../CoreNode.js';
52
+ import { WebGlCoreCtxRenderTexture } from './WebGlCoreCtxRenderTexture.js';
61
53
 
62
54
  const WORDS_PER_QUAD = 24;
63
- const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
64
-
65
- export interface WebGlCoreRendererOptions {
66
- stage: Stage;
67
- canvas: HTMLCanvasElement | OffscreenCanvas;
68
- pixelRatio: number;
69
- txManager: CoreTextureManager;
70
- txMemManager: TextureMemoryManager;
71
- shManager: CoreShaderManager;
72
- clearColor: number;
73
- bufferMemory: number;
74
- contextSpy: ContextSpy | null;
75
- }
55
+ // const BYTES_PER_QUAD = WORDS_PER_QUAD * 4;
56
+
57
+ export type WebGlCoreRendererOptions = CoreRendererOptions;
76
58
 
77
59
  interface CoreWebGlSystem {
78
60
  parameters: CoreWebGlParameters;
@@ -84,14 +66,6 @@ export class WebGlCoreRenderer extends CoreRenderer {
84
66
  glw: WebGlContextWrapper;
85
67
  system: CoreWebGlSystem;
86
68
 
87
- //// Core Managers
88
- txManager: CoreTextureManager;
89
- txMemManager: TextureMemoryManager;
90
- shManager: CoreShaderManager;
91
-
92
- //// Options
93
- options: Required<WebGlCoreRendererOptions>;
94
-
95
69
  //// Persistent data
96
70
  quadBuffer: ArrayBuffer = new ArrayBuffer(1024 * 1024 * 4);
97
71
  fQuadBuffer: Float32Array = new Float32Array(this.quadBuffer);
@@ -101,7 +75,8 @@ export class WebGlCoreRenderer extends CoreRenderer {
101
75
  //// Render Op / Buffer Filling State
102
76
  curBufferIdx = 0;
103
77
  curRenderOp: WebGlCoreRenderOp | null = null;
104
- renderables: Array<QuadOptions | WebGlCoreRenderOp> = [];
78
+ override rttNodes: CoreNode[] = [];
79
+ activeRttNode: CoreNode | null = null;
105
80
 
106
81
  //// Default Shader
107
82
  defaultShader: WebGlCoreShader;
@@ -112,14 +87,24 @@ export class WebGlCoreRenderer extends CoreRenderer {
112
87
  */
113
88
  defaultTexture: Texture;
114
89
 
90
+ /**
91
+ * Whether the renderer is currently rendering to a texture.
92
+ */
93
+ public renderToTextureActive = false;
94
+
115
95
  constructor(options: WebGlCoreRendererOptions) {
116
- super(options.stage);
96
+ super(options);
97
+ this.mode = 'webgl';
98
+
117
99
  const { canvas, clearColor, bufferMemory } = options;
118
- this.options = options;
119
- this.txManager = options.txManager;
120
- this.txMemManager = options.txMemManager;
121
- this.shManager = options.shManager;
100
+
122
101
  this.defaultTexture = new ColorTexture(this.txManager);
102
+
103
+ // Mark the default texture as ALWAYS renderable
104
+ // This prevents it from ever being garbage collected.
105
+ // Fixes https://github.com/lightning-js/renderer/issues/262
106
+ this.defaultTexture.setRenderableOwner(this, true);
107
+
123
108
  // When the default texture is loaded, request a render in case the
124
109
  // RAF is paused. Fixes: https://github.com/lightning-js/renderer/issues/123
125
110
  this.defaultTexture.once('loaded', () => {
@@ -207,6 +192,12 @@ export class WebGlCoreRenderer extends CoreRenderer {
207
192
  this.txMemManager,
208
193
  textureSource,
209
194
  );
195
+ } else if (textureSource instanceof RenderTexture) {
196
+ return new WebGlCoreCtxRenderTexture(
197
+ this.glw,
198
+ this.txMemManager,
199
+ textureSource,
200
+ );
210
201
  }
211
202
  return new WebGlCoreCtxTexture(this.glw, this.txMemManager, textureSource);
212
203
  }
@@ -243,6 +234,9 @@ export class WebGlCoreRenderer extends CoreRenderer {
243
234
  tb,
244
235
  tc,
245
236
  td,
237
+ rtt: renderToTexture,
238
+ parentHasRenderTexture,
239
+ framebufferDimensions,
246
240
  } = params;
247
241
  let { texture } = params;
248
242
 
@@ -264,39 +258,22 @@ export class WebGlCoreRenderer extends CoreRenderer {
264
258
  const targetDims = {
265
259
  width,
266
260
  height,
267
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
268
261
  };
269
262
  const targetShader = shader || this.defaultShader;
270
263
  assertTruthy(targetShader instanceof WebGlCoreShader);
271
- if (curRenderOp) {
272
- // If the current render op is not the same shader, create a new one
273
- // If the current render op's shader props are not compatible with the
274
- // the new shader props, create a new one render op.
275
- if (
276
- curRenderOp.shader !== targetShader ||
277
- !compareRect(curRenderOp.clippingRect, clippingRect) ||
278
- (curRenderOp.shader !== this.defaultShader &&
279
- (!shaderProps ||
280
- !curRenderOp.shader.canBatchShaderProps(
281
- curRenderOp.shaderProps,
282
- shaderProps,
283
- )))
284
- ) {
285
- curRenderOp = null;
286
- }
287
- }
288
- assertTruthy(targetShader instanceof WebGlCoreShader);
289
264
 
290
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
291
- if (!curRenderOp) {
265
+ if (!this.reuseRenderOp(params)) {
292
266
  // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
293
267
  this.newRenderOp(
294
268
  targetShader,
295
- shaderProps as any,
269
+ shaderProps as Record<string, unknown>,
296
270
  alpha,
297
271
  targetDims,
298
272
  clippingRect,
299
273
  bufferIdx,
274
+ renderToTexture,
275
+ parentHasRenderTexture,
276
+ framebufferDimensions,
300
277
  );
301
278
  curRenderOp = this.curRenderOp;
302
279
  assertTruthy(curRenderOp);
@@ -333,6 +310,7 @@ export class WebGlCoreRenderer extends CoreRenderer {
333
310
  const ctxTexture = txManager.getCtxTexture(texture);
334
311
  assertTruthy(ctxTexture instanceof WebGlCoreCtxTexture);
335
312
  const textureIdx = this.addTexture(ctxTexture, bufferIdx);
313
+
336
314
  curRenderOp = this.curRenderOp;
337
315
  assertTruthy(curRenderOp);
338
316
 
@@ -428,6 +406,9 @@ export class WebGlCoreRenderer extends CoreRenderer {
428
406
  dimensions: Dimensions,
429
407
  clippingRect: RectWithValid,
430
408
  bufferIdx: number,
409
+ renderToTexture?: boolean,
410
+ parentHasRenderTexture?: boolean,
411
+ framebufferDimensions?: Dimensions,
431
412
  ) {
432
413
  const curRenderOp = new WebGlCoreRenderOp(
433
414
  this.glw,
@@ -440,6 +421,9 @@ export class WebGlCoreRenderer extends CoreRenderer {
440
421
  dimensions,
441
422
  bufferIdx,
442
423
  0, // Z-Index is only used for explictly added Render Ops
424
+ renderToTexture,
425
+ parentHasRenderTexture,
426
+ framebufferDimensions,
443
427
  );
444
428
  this.curRenderOp = curRenderOp;
445
429
  this.renderOps.push(curRenderOp);
@@ -486,6 +470,50 @@ export class WebGlCoreRenderer extends CoreRenderer {
486
470
  return textureIdx;
487
471
  }
488
472
 
473
+ /**
474
+ * Test if the current Render operation can be reused for the specified parameters.
475
+ * @param params
476
+ * @returns
477
+ */
478
+ reuseRenderOp(params: QuadOptions) {
479
+ const { shader, shaderProps, parentHasRenderTexture, rtt, clippingRect } =
480
+ params;
481
+
482
+ const targetShader = shader || this.defaultShader;
483
+
484
+ // Switching shader program will require a new render operation
485
+ if (this.curRenderOp?.shader !== targetShader) {
486
+ return false;
487
+ }
488
+
489
+ // Switching clipping rect will require a new render operation
490
+ if (!compareRect(this.curRenderOp.clippingRect, clippingRect)) {
491
+ return false;
492
+ }
493
+
494
+ // Force new render operation if rendering to texture
495
+ // @todo: This needs to be improved, render operations could also be reused
496
+ // for rendering to texture
497
+ if (parentHasRenderTexture || rtt) {
498
+ return false;
499
+ }
500
+
501
+ // Check if the shader can batch the shader properties
502
+ if (
503
+ this.curRenderOp.shader !== this.defaultShader &&
504
+ (!shaderProps ||
505
+ !this.curRenderOp.shader.canBatchShaderProps(
506
+ this.curRenderOp.shaderProps,
507
+ shaderProps,
508
+ ))
509
+ ) {
510
+ return false;
511
+ }
512
+
513
+ // Render operation can be reused
514
+ return true;
515
+ }
516
+
489
517
  /**
490
518
  * add RenderOp to the render pipeline
491
519
  */
@@ -513,16 +541,91 @@ export class WebGlCoreRenderer extends CoreRenderer {
513
541
  if (doLog) {
514
542
  console.log('renderOps', this.renderOps.length);
515
543
  }
544
+
516
545
  this.renderOps.forEach((renderOp, i) => {
517
546
  if (doLog) {
518
- console.log('renderOp', i, renderOp.numQuads);
547
+ console.log('Quads per operation', renderOp.numQuads);
519
548
  }
520
549
  renderOp.draw();
521
550
  });
551
+ }
552
+
553
+ renderToTexture(node: CoreNode) {
554
+ for (let i = 0; i < this.rttNodes.length; i++) {
555
+ if (this.rttNodes[i] === node) {
556
+ return;
557
+ }
558
+ }
522
559
 
523
- // clean up
524
- this.renderables = [];
560
+ // @todo: Better bottom up rendering order
561
+ this.rttNodes.unshift(node);
562
+ }
563
+
564
+ renderRTTNodes() {
565
+ const { glw } = this;
566
+ const { txManager } = this.stage;
567
+ // Render all associated RTT nodes to their textures
568
+ for (let i = 0; i < this.rttNodes.length; i++) {
569
+ const node = this.rttNodes[i];
570
+
571
+ // Skip nodes that don't have RTT updates
572
+ if (!node || !node.hasRTTupdates) {
573
+ continue;
574
+ }
575
+
576
+ // Set the active RTT node to the current node
577
+ // So we can prevent rendering children of nested RTT nodes
578
+ this.activeRttNode = node;
579
+
580
+ assertTruthy(node.texture, 'RTT node missing texture');
581
+ const ctxTexture = txManager.getCtxTexture(node.texture);
582
+ assertTruthy(ctxTexture instanceof WebGlCoreCtxRenderTexture);
583
+ this.renderToTextureActive = true;
584
+
585
+ // Bind the the texture's framebuffer
586
+ glw.bindFramebuffer(ctxTexture.framebuffer);
587
+
588
+ glw.viewport(0, 0, ctxTexture.w, ctxTexture.h);
589
+ glw.clear();
590
+
591
+ // Render all associated quads to the texture
592
+ for (let i = 0; i < node.children.length; i++) {
593
+ const child = node.children[i];
594
+ if (!child) {
595
+ continue;
596
+ }
597
+ child.update(this.stage.deltaTime, {
598
+ x: 0,
599
+ y: 0,
600
+ width: 0,
601
+ height: 0,
602
+ valid: false,
603
+ });
604
+
605
+ this.stage.addQuads(child);
606
+ child.hasRTTupdates = false;
607
+ }
608
+
609
+ // Render all associated quads to the texture
610
+ this.render();
611
+
612
+ // Reset render operations
613
+ this.renderOps.length = 0;
614
+ node.hasRTTupdates = false;
615
+ }
616
+
617
+ // Bind the default framebuffer
618
+ glw.bindFramebuffer(null);
619
+
620
+ glw.viewport(0, 0, this.glw.canvas.width, this.glw.canvas.height);
621
+ this.renderToTextureActive = false;
525
622
  }
526
- }
527
623
 
528
- const idx = 0;
624
+ removeRTTNode(node: CoreNode) {
625
+ const index = this.rttNodes.indexOf(node);
626
+ if (index === -1) {
627
+ return;
628
+ }
629
+ this.rttNodes.splice(index, 1);
630
+ }
631
+ }
@@ -261,10 +261,35 @@ export abstract class WebGlCoreShader extends CoreShader {
261
261
  if (renderOp.textures.length > 0) {
262
262
  this.bindTextures(renderOp.textures);
263
263
  }
264
- const { glw } = renderOp;
265
- // Bind standard automatic uniforms
266
- this.setUniform('u_resolution', [glw.canvas.width, glw.canvas.height]);
267
- this.setUniform('u_pixelRatio', renderOp.options.pixelRatio);
264
+
265
+ const { glw, parentHasRenderTexture, renderToTexture } = renderOp;
266
+
267
+ // Skip if the parent and current operation both have render textures
268
+ if (renderToTexture && parentHasRenderTexture) {
269
+ return;
270
+ }
271
+
272
+ // Bind render texture framebuffer dimensions as resolution
273
+ // if the parent has a render texture
274
+ if (parentHasRenderTexture) {
275
+ const { width, height } = renderOp.framebufferDimensions || {};
276
+ // Force pixel ratio to 1.0 for render textures since they are always 1:1
277
+ // the final render texture will be rendered to the screen with the correct pixel ratio
278
+ this.setUniform('u_pixelRatio', 1.0);
279
+
280
+ // Set resolution to the framebuffer dimensions
281
+ this.setUniform(
282
+ 'u_resolution',
283
+ new Float32Array([width ?? 0, height ?? 0]),
284
+ );
285
+ } else {
286
+ this.setUniform('u_pixelRatio', renderOp.options.pixelRatio);
287
+ this.setUniform(
288
+ 'u_resolution',
289
+ new Float32Array([glw.canvas.width, glw.canvas.height]),
290
+ );
291
+ }
292
+
268
293
  if (props) {
269
294
  // Bind optional automatic uniforms
270
295
  // These are only bound if their keys are present in the props.
@@ -61,16 +61,14 @@ export class DefaultShader extends WebGlCoreShader {
61
61
  varying vec2 v_textureCoordinate;
62
62
 
63
63
  void main() {
64
- vec2 normalized = a_position * u_pixelRatio / u_resolution;
65
- vec2 zero_two = normalized * 2.0;
66
- vec2 clip_space = zero_two - 1.0;
64
+ vec2 normalized = a_position * u_pixelRatio;
65
+ vec2 screenSpace = vec2(2.0 / u_resolution.x, -2.0 / u_resolution.y);
67
66
 
68
- // pass to fragment
69
67
  v_color = a_color;
70
68
  v_textureCoordinate = a_textureCoordinate;
71
69
 
72
- // flip y
73
- gl_Position = vec4(clip_space * vec2(1.0, -1.0), 0, 1);
70
+ gl_Position = vec4(normalized.x * screenSpace.x - 1.0, normalized.y * -abs(screenSpace.y) + 1.0, 0.0, 1.0);
71
+ gl_Position.y = -sign(screenSpace.y) * gl_Position.y;
74
72
  }
75
73
  `,
76
74
  fragment: `
@@ -136,8 +136,13 @@ export class SdfShader extends WebGlCoreShader {
136
136
  void main() {
137
137
  vec2 scrolledPosition = a_position * u_size - vec2(0, u_scrollY);
138
138
  vec2 transformedPosition = (u_transform * vec3(scrolledPosition, 1)).xy;
139
- gl_Position = vec4((transformedPosition * u_pixelRatio / u_resolution * 2.0 - 1.0) * vec2(1, -1), 0, 1);
139
+
140
+ // Calculate screen space with pixel ratio
141
+ vec2 screenSpace = (transformedPosition * u_pixelRatio / u_resolution * 2.0 - 1.0) * vec2(1, -1);
142
+
143
+ gl_Position = vec4(screenSpace, 0.0, 1.0);
140
144
  v_texcoord = a_textureCoordinate;
145
+
141
146
  }
142
147
  `,
143
148
  fragment: `
@@ -56,6 +56,8 @@ import type {
56
56
  import type { WebGlCoreCtxTexture } from '../../../renderers/webgl/WebGlCoreCtxTexture.js';
57
57
  import { EventEmitter } from '../../../../common/EventEmitter.js';
58
58
  import type { Matrix3d } from '../../../lib/Matrix3d.js';
59
+ import type { Dimensions } from '../../../../common/CommonTypes.js';
60
+ import { WebGlCoreRenderer } from '../../../renderers/webgl/WebGlCoreRenderer.js';
59
61
 
60
62
  declare module '../TextRenderer.js' {
61
63
  interface TextRendererMap {
@@ -574,13 +576,17 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
574
576
  transform: Matrix3d,
575
577
  clippingRect: Readonly<RectWithValid>,
576
578
  alpha: number,
579
+ parentHasRenderTexture: boolean,
580
+ framebufferDimensions: Dimensions,
577
581
  ): void {
578
582
  if (!state.vertexBuffer) {
579
583
  // Nothing to draw
580
584
  return;
581
585
  }
582
586
 
583
- const { renderer } = this.stage;
587
+ const renderer: WebGlCoreRenderer = this.stage
588
+ .renderer as WebGlCoreRenderer;
589
+ assertTruthy(renderer instanceof WebGlCoreRenderer);
584
590
 
585
591
  const { fontSize, color, contain, scrollable, zIndex, debug } = state.props;
586
592
 
@@ -679,6 +685,9 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
679
685
  { height: textH, width: textW },
680
686
  0,
681
687
  zIndex,
688
+ false,
689
+ parentHasRenderTexture,
690
+ framebufferDimensions,
682
691
  );
683
692
 
684
693
  const texture = state.trFontFace?.texture;
@@ -17,6 +17,7 @@
17
17
  * limitations under the License.
18
18
  */
19
19
 
20
+ import type { Dimensions } from '../../../common/CommonTypes.js';
20
21
  import type { EventEmitter } from '../../../common/EventEmitter.js';
21
22
  import type { Stage } from '../../Stage.js';
22
23
  import type { Matrix3d } from '../../lib/Matrix3d.js';
@@ -544,5 +545,7 @@ export abstract class TextRenderer<
544
545
  transform: Matrix3d,
545
546
  clippingRect: RectWithValid,
546
547
  alpha: number,
548
+ parentHasRenderTexture: boolean,
549
+ framebufferDimensions: Dimensions | undefined,
547
550
  ): void;
548
551
  }
@@ -117,6 +117,9 @@ export class ImageTexture extends Texture {
117
117
  };
118
118
  } else {
119
119
  const img = new Image();
120
+ if (!(src.substr(0, 5) === 'data:')) {
121
+ img.crossOrigin = 'Anonymous';
122
+ }
120
123
  img.src = src;
121
124
  await new Promise<void>((resolve, reject) => {
122
125
  img.onload = () => resolve();
@@ -0,0 +1,81 @@
1
+ /*
2
+ * If not stated otherwise in this file or this component's LICENSE file the
3
+ * following copyright and licenses apply:
4
+ *
5
+ * Copyright 2023 Comcast Cable Communications Management, LLC.
6
+ *
7
+ * Licensed under the Apache License, Version 2.0 (the License);
8
+ * you may not use this file except in compliance with the License.
9
+ * You may obtain a copy of the License at
10
+ *
11
+ * http://www.apache.org/licenses/LICENSE-2.0
12
+ *
13
+ * Unless required by applicable law or agreed to in writing, software
14
+ * distributed under the License is distributed on an "AS IS" BASIS,
15
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ * See the License for the specific language governing permissions and
17
+ * limitations under the License.
18
+ */
19
+
20
+ import type { CoreTextureManager } from '../CoreTextureManager.js';
21
+ import { Texture, type TextureData } from './Texture.js';
22
+
23
+ /**
24
+ * Properties of the {@link RenderTexture}
25
+ */
26
+ export interface RenderTextureProps {
27
+ /**
28
+ * WebGL Texture width
29
+ * @default 256
30
+ */
31
+ width?: number;
32
+
33
+ /**
34
+ * WebGL Texture height
35
+ * @default 256
36
+ */
37
+ height?: number;
38
+ }
39
+
40
+ export class RenderTexture extends Texture {
41
+ props: Required<RenderTextureProps>;
42
+
43
+ constructor(txManager: CoreTextureManager, props?: RenderTextureProps) {
44
+ super(txManager);
45
+ this.props = RenderTexture.resolveDefaults(props || {});
46
+ }
47
+
48
+ get width() {
49
+ return this.props.width;
50
+ }
51
+
52
+ set width(value: number) {
53
+ this.props.width = value;
54
+ }
55
+
56
+ get height() {
57
+ return this.props.height;
58
+ }
59
+
60
+ set height(value: number) {
61
+ this.props.height = value;
62
+ }
63
+
64
+ override async getTextureData(): Promise<TextureData> {
65
+ return {
66
+ data: null,
67
+ premultiplyAlpha: null,
68
+ };
69
+ }
70
+
71
+ static override resolveDefaults(
72
+ props: RenderTextureProps,
73
+ ): Required<RenderTextureProps> {
74
+ return {
75
+ width: props.width || 256,
76
+ height: props.height || 256,
77
+ };
78
+ }
79
+
80
+ static z$__type__Props: RenderTextureProps;
81
+ }