@lightningjs/renderer 2.16.0 → 2.18.0

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 (257) hide show
  1. package/dist/src/core/CoreNode.js +7 -5
  2. package/dist/src/core/CoreNode.js.map +1 -1
  3. package/dist/src/core/CoreTextureManager.d.ts +14 -8
  4. package/dist/src/core/CoreTextureManager.js +33 -59
  5. package/dist/src/core/CoreTextureManager.js.map +1 -1
  6. package/dist/src/core/Stage.d.ts +3 -3
  7. package/dist/src/core/Stage.js +9 -14
  8. package/dist/src/core/Stage.js.map +1 -1
  9. package/dist/src/core/TextureMemoryManager.d.ts +21 -17
  10. package/dist/src/core/TextureMemoryManager.js +99 -124
  11. package/dist/src/core/TextureMemoryManager.js.map +1 -1
  12. package/dist/src/core/lib/WebGlContextWrapper.d.ts +10 -0
  13. package/dist/src/core/lib/WebGlContextWrapper.js +32 -0
  14. package/dist/src/core/lib/WebGlContextWrapper.js.map +1 -1
  15. package/dist/src/core/lib/textureCompression.js +13 -6
  16. package/dist/src/core/lib/textureCompression.js.map +1 -1
  17. package/dist/src/core/platform.js +4 -1
  18. package/dist/src/core/platform.js.map +1 -1
  19. package/dist/src/core/renderers/CoreContextTexture.d.ts +1 -0
  20. package/dist/src/core/renderers/CoreContextTexture.js.map +1 -1
  21. package/dist/src/core/renderers/canvas/CanvasCoreTexture.d.ts +1 -0
  22. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js +4 -3
  23. package/dist/src/core/renderers/canvas/CanvasCoreTexture.js.map +1 -1
  24. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.d.ts +9 -0
  25. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js +59 -29
  26. package/dist/src/core/renderers/webgl/WebGlCoreCtxTexture.js.map +1 -1
  27. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js +4 -4
  28. package/dist/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.js.map +1 -1
  29. package/dist/src/core/textures/ColorTexture.d.ts +2 -2
  30. package/dist/src/core/textures/ColorTexture.js +1 -2
  31. package/dist/src/core/textures/ColorTexture.js.map +1 -1
  32. package/dist/src/core/textures/ImageTexture.d.ts +7 -1
  33. package/dist/src/core/textures/ImageTexture.js +55 -39
  34. package/dist/src/core/textures/ImageTexture.js.map +1 -1
  35. package/dist/src/core/textures/NoiseTexture.js +1 -1
  36. package/dist/src/core/textures/NoiseTexture.js.map +1 -1
  37. package/dist/src/core/textures/RenderTexture.js +1 -1
  38. package/dist/src/core/textures/RenderTexture.js.map +1 -1
  39. package/dist/src/core/textures/SubTexture.d.ts +1 -2
  40. package/dist/src/core/textures/SubTexture.js +11 -29
  41. package/dist/src/core/textures/SubTexture.js.map +1 -1
  42. package/dist/src/core/textures/Texture.d.ts +51 -7
  43. package/dist/src/core/textures/Texture.js +127 -15
  44. package/dist/src/core/textures/Texture.js.map +1 -1
  45. package/dist/src/main-api/Inspector.d.ts +3 -0
  46. package/dist/src/main-api/Inspector.js +156 -0
  47. package/dist/src/main-api/Inspector.js.map +1 -1
  48. package/dist/src/main-api/Renderer.d.ts +1 -3
  49. package/dist/src/main-api/Renderer.js +2 -4
  50. package/dist/src/main-api/Renderer.js.map +1 -1
  51. package/dist/tsconfig.dist.tsbuildinfo +1 -1
  52. package/package.json +1 -1
  53. package/src/core/CoreNode.ts +8 -4
  54. package/src/core/CoreTextureManager.ts +59 -65
  55. package/src/core/Stage.ts +10 -16
  56. package/src/core/TextureMemoryManager.ts +118 -148
  57. package/src/core/lib/WebGlContextWrapper.ts +38 -0
  58. package/src/core/lib/textureCompression.ts +18 -7
  59. package/src/core/platform.ts +5 -1
  60. package/src/core/renderers/CoreContextTexture.ts +1 -0
  61. package/src/core/renderers/canvas/CanvasCoreTexture.ts +5 -3
  62. package/src/core/renderers/webgl/WebGlCoreCtxTexture.ts +78 -40
  63. package/src/core/text-rendering/renderers/SdfTextRenderer/SdfTextRenderer.ts +10 -4
  64. package/src/core/textures/ColorTexture.ts +4 -7
  65. package/src/core/textures/ImageTexture.ts +66 -51
  66. package/src/core/textures/NoiseTexture.ts +1 -1
  67. package/src/core/textures/RenderTexture.ts +1 -1
  68. package/src/core/textures/SubTexture.ts +14 -31
  69. package/src/core/textures/Texture.ts +150 -21
  70. package/src/main-api/Inspector.ts +203 -0
  71. package/src/main-api/Renderer.ts +2 -4
  72. package/dist/exports/canvas-shaders.d.ts +0 -10
  73. package/dist/exports/canvas-shaders.js +0 -27
  74. package/dist/exports/canvas-shaders.js.map +0 -1
  75. package/dist/exports/webgl-shaders.d.ts +0 -11
  76. package/dist/exports/webgl-shaders.js +0 -28
  77. package/dist/exports/webgl-shaders.js.map +0 -1
  78. package/dist/src/core/platforms/Platform.d.ts +0 -37
  79. package/dist/src/core/platforms/Platform.js +0 -22
  80. package/dist/src/core/platforms/Platform.js.map +0 -1
  81. package/dist/src/core/platforms/web/WebPlatform.d.ts +0 -9
  82. package/dist/src/core/platforms/web/WebPlatform.js +0 -58
  83. package/dist/src/core/platforms/web/WebPlatform.js.map +0 -1
  84. package/dist/src/core/renderers/CoreShaderNode.d.ts +0 -59
  85. package/dist/src/core/renderers/CoreShaderNode.js +0 -113
  86. package/dist/src/core/renderers/CoreShaderNode.js.map +0 -1
  87. package/dist/src/core/renderers/CoreShaderProgram.d.ts +0 -4
  88. package/dist/src/core/renderers/CoreShaderProgram.js +0 -20
  89. package/dist/src/core/renderers/CoreShaderProgram.js.map +0 -1
  90. package/dist/src/core/renderers/canvas/CanvasRenderer.d.ts +0 -37
  91. package/dist/src/core/renderers/canvas/CanvasRenderer.js +0 -215
  92. package/dist/src/core/renderers/canvas/CanvasRenderer.js.map +0 -1
  93. package/dist/src/core/renderers/canvas/CanvasShaderNode.d.ts +0 -21
  94. package/dist/src/core/renderers/canvas/CanvasShaderNode.js +0 -57
  95. package/dist/src/core/renderers/canvas/CanvasShaderNode.js.map +0 -1
  96. package/dist/src/core/renderers/canvas/CanvasTexture.d.ts +0 -16
  97. package/dist/src/core/renderers/canvas/CanvasTexture.js +0 -124
  98. package/dist/src/core/renderers/canvas/CanvasTexture.js.map +0 -1
  99. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.d.ts +0 -12
  100. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js +0 -55
  101. package/dist/src/core/renderers/webgl/WebGlCtxRenderTexture.js.map +0 -1
  102. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.d.ts +0 -9
  103. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js +0 -38
  104. package/dist/src/core/renderers/webgl/WebGlCtxSubTexture.js.map +0 -1
  105. package/dist/src/core/renderers/webgl/WebGlCtxTexture.d.ts +0 -57
  106. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js +0 -224
  107. package/dist/src/core/renderers/webgl/WebGlCtxTexture.js.map +0 -1
  108. package/dist/src/core/renderers/webgl/WebGlRenderOp.d.ts +0 -44
  109. package/dist/src/core/renderers/webgl/WebGlRenderOp.js +0 -125
  110. package/dist/src/core/renderers/webgl/WebGlRenderOp.js.map +0 -1
  111. package/dist/src/core/renderers/webgl/WebGlRenderer.d.ts +0 -136
  112. package/dist/src/core/renderers/webgl/WebGlRenderer.js +0 -573
  113. package/dist/src/core/renderers/webgl/WebGlRenderer.js.map +0 -1
  114. package/dist/src/core/renderers/webgl/WebGlShaderNode.d.ts +0 -222
  115. package/dist/src/core/renderers/webgl/WebGlShaderNode.js +0 -331
  116. package/dist/src/core/renderers/webgl/WebGlShaderNode.js.map +0 -1
  117. package/dist/src/core/renderers/webgl/WebGlShaderProgram.d.ts +0 -35
  118. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js +0 -201
  119. package/dist/src/core/renderers/webgl/WebGlShaderProgram.js.map +0 -1
  120. package/dist/src/core/shaders/canvas/Border.d.ts +0 -9
  121. package/dist/src/core/shaders/canvas/Border.js +0 -57
  122. package/dist/src/core/shaders/canvas/Border.js.map +0 -1
  123. package/dist/src/core/shaders/canvas/HolePunch.d.ts +0 -7
  124. package/dist/src/core/shaders/canvas/HolePunch.js +0 -38
  125. package/dist/src/core/shaders/canvas/HolePunch.js.map +0 -1
  126. package/dist/src/core/shaders/canvas/LinearGradient.d.ts +0 -10
  127. package/dist/src/core/shaders/canvas/LinearGradient.js +0 -48
  128. package/dist/src/core/shaders/canvas/LinearGradient.js.map +0 -1
  129. package/dist/src/core/shaders/canvas/RadialGradient.d.ts +0 -11
  130. package/dist/src/core/shaders/canvas/RadialGradient.js +0 -70
  131. package/dist/src/core/shaders/canvas/RadialGradient.js.map +0 -1
  132. package/dist/src/core/shaders/canvas/Rounded.d.ts +0 -7
  133. package/dist/src/core/shaders/canvas/Rounded.js +0 -33
  134. package/dist/src/core/shaders/canvas/Rounded.js.map +0 -1
  135. package/dist/src/core/shaders/canvas/RoundedWithBorder.d.ts +0 -7
  136. package/dist/src/core/shaders/canvas/RoundedWithBorder.js +0 -43
  137. package/dist/src/core/shaders/canvas/RoundedWithBorder.js.map +0 -1
  138. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.d.ts +0 -8
  139. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js +0 -41
  140. package/dist/src/core/shaders/canvas/RoundedWithBorderAndShadow.js.map +0 -1
  141. package/dist/src/core/shaders/canvas/RoundedWithShadow.d.ts +0 -7
  142. package/dist/src/core/shaders/canvas/RoundedWithShadow.js +0 -40
  143. package/dist/src/core/shaders/canvas/RoundedWithShadow.js.map +0 -1
  144. package/dist/src/core/shaders/canvas/Shadow.d.ts +0 -8
  145. package/dist/src/core/shaders/canvas/Shadow.js +0 -31
  146. package/dist/src/core/shaders/canvas/Shadow.js.map +0 -1
  147. package/dist/src/core/shaders/canvas/utils/render.d.ts +0 -5
  148. package/dist/src/core/shaders/canvas/utils/render.js +0 -84
  149. package/dist/src/core/shaders/canvas/utils/render.js.map +0 -1
  150. package/dist/src/core/shaders/templates/BorderTemplate.d.ts +0 -37
  151. package/dist/src/core/shaders/templates/BorderTemplate.js +0 -73
  152. package/dist/src/core/shaders/templates/BorderTemplate.js.map +0 -1
  153. package/dist/src/core/shaders/templates/HolePunchTemplate.d.ts +0 -46
  154. package/dist/src/core/shaders/templates/HolePunchTemplate.js +0 -35
  155. package/dist/src/core/shaders/templates/HolePunchTemplate.js.map +0 -1
  156. package/dist/src/core/shaders/templates/LinearGradientTemplate.d.ts +0 -23
  157. package/dist/src/core/shaders/templates/LinearGradientTemplate.js +0 -47
  158. package/dist/src/core/shaders/templates/LinearGradientTemplate.js.map +0 -1
  159. package/dist/src/core/shaders/templates/RadialGradientTemplate.d.ts +0 -31
  160. package/dist/src/core/shaders/templates/RadialGradientTemplate.js +0 -49
  161. package/dist/src/core/shaders/templates/RadialGradientTemplate.js.map +0 -1
  162. package/dist/src/core/shaders/templates/RoundedTemplate.d.ts +0 -29
  163. package/dist/src/core/shaders/templates/RoundedTemplate.js +0 -67
  164. package/dist/src/core/shaders/templates/RoundedTemplate.js.map +0 -1
  165. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.d.ts +0 -7
  166. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js +0 -24
  167. package/dist/src/core/shaders/templates/RoundedWithBorderAndShadowTemplate.js.map +0 -1
  168. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.d.ts +0 -6
  169. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js +0 -23
  170. package/dist/src/core/shaders/templates/RoundedWithBorderTemplate.js.map +0 -1
  171. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.d.ts +0 -6
  172. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js +0 -23
  173. package/dist/src/core/shaders/templates/RoundedWithShadowTemplate.js.map +0 -1
  174. package/dist/src/core/shaders/templates/ShadowTemplate.d.ts +0 -34
  175. package/dist/src/core/shaders/templates/ShadowTemplate.js +0 -66
  176. package/dist/src/core/shaders/templates/ShadowTemplate.js.map +0 -1
  177. package/dist/src/core/shaders/templates/shaderUtils.d.ts +0 -5
  178. package/dist/src/core/shaders/templates/shaderUtils.js +0 -41
  179. package/dist/src/core/shaders/templates/shaderUtils.js.map +0 -1
  180. package/dist/src/core/shaders/utils.d.ts +0 -5
  181. package/dist/src/core/shaders/utils.js +0 -41
  182. package/dist/src/core/shaders/utils.js.map +0 -1
  183. package/dist/src/core/shaders/webgl/Border.d.ts +0 -3
  184. package/dist/src/core/shaders/webgl/Border.js +0 -110
  185. package/dist/src/core/shaders/webgl/Border.js.map +0 -1
  186. package/dist/src/core/shaders/webgl/Default.d.ts +0 -2
  187. package/dist/src/core/shaders/webgl/Default.js +0 -86
  188. package/dist/src/core/shaders/webgl/Default.js.map +0 -1
  189. package/dist/src/core/shaders/webgl/DefaultBatched.d.ts +0 -2
  190. package/dist/src/core/shaders/webgl/DefaultBatched.js +0 -104
  191. package/dist/src/core/shaders/webgl/DefaultBatched.js.map +0 -1
  192. package/dist/src/core/shaders/webgl/HolePunch.d.ts +0 -3
  193. package/dist/src/core/shaders/webgl/HolePunch.js +0 -65
  194. package/dist/src/core/shaders/webgl/HolePunch.js.map +0 -1
  195. package/dist/src/core/shaders/webgl/LinearGradient.d.ts +0 -3
  196. package/dist/src/core/shaders/webgl/LinearGradient.js +0 -76
  197. package/dist/src/core/shaders/webgl/LinearGradient.js.map +0 -1
  198. package/dist/src/core/shaders/webgl/RadialGradient.d.ts +0 -3
  199. package/dist/src/core/shaders/webgl/RadialGradient.js +0 -74
  200. package/dist/src/core/shaders/webgl/RadialGradient.js.map +0 -1
  201. package/dist/src/core/shaders/webgl/Rounded.d.ts +0 -7
  202. package/dist/src/core/shaders/webgl/Rounded.js +0 -86
  203. package/dist/src/core/shaders/webgl/Rounded.js.map +0 -1
  204. package/dist/src/core/shaders/webgl/RoundedWithBorder.d.ts +0 -3
  205. package/dist/src/core/shaders/webgl/RoundedWithBorder.js +0 -140
  206. package/dist/src/core/shaders/webgl/RoundedWithBorder.js.map +0 -1
  207. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.d.ts +0 -3
  208. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js +0 -162
  209. package/dist/src/core/shaders/webgl/RoundedWithBorderAndShadow.js.map +0 -1
  210. package/dist/src/core/shaders/webgl/RoundedWithShadow.d.ts +0 -3
  211. package/dist/src/core/shaders/webgl/RoundedWithShadow.js +0 -84
  212. package/dist/src/core/shaders/webgl/RoundedWithShadow.js.map +0 -1
  213. package/dist/src/core/shaders/webgl/SdfShader.d.ts +0 -32
  214. package/dist/src/core/shaders/webgl/SdfShader.js +0 -116
  215. package/dist/src/core/shaders/webgl/SdfShader.js.map +0 -1
  216. package/dist/src/core/shaders/webgl/Shadow.d.ts +0 -3
  217. package/dist/src/core/shaders/webgl/Shadow.js +0 -110
  218. package/dist/src/core/shaders/webgl/Shadow.js.map +0 -1
  219. package/dist/src/core/shaders/webgl/Spinner.d.ts +0 -1
  220. package/dist/src/core/shaders/webgl/Spinner.js +0 -2
  221. package/dist/src/core/shaders/webgl/Spinner.js.map +0 -1
  222. package/dist/src/core/text-rendering/CanvasFontHandler.d.ts +0 -25
  223. package/dist/src/core/text-rendering/CanvasFontHandler.js +0 -117
  224. package/dist/src/core/text-rendering/CanvasFontHandler.js.map +0 -1
  225. package/dist/src/core/text-rendering/CanvasTextRenderer.d.ts +0 -6
  226. package/dist/src/core/text-rendering/CanvasTextRenderer.js +0 -139
  227. package/dist/src/core/text-rendering/CanvasTextRenderer.js.map +0 -1
  228. package/dist/src/core/text-rendering/SdfFontHandler.d.ts +0 -137
  229. package/dist/src/core/text-rendering/SdfFontHandler.js +0 -336
  230. package/dist/src/core/text-rendering/SdfFontHandler.js.map +0 -1
  231. package/dist/src/core/text-rendering/SdfTextRenderer.d.ts +0 -21
  232. package/dist/src/core/text-rendering/SdfTextRenderer.js +0 -324
  233. package/dist/src/core/text-rendering/SdfTextRenderer.js.map +0 -1
  234. package/dist/src/core/text-rendering/TextRenderer.d.ts +0 -425
  235. package/dist/src/core/text-rendering/TextRenderer.js +0 -70
  236. package/dist/src/core/text-rendering/TextRenderer.js.map +0 -1
  237. package/dist/src/core/text-rendering/Utils.d.ts +0 -71
  238. package/dist/src/core/text-rendering/Utils.js +0 -212
  239. package/dist/src/core/text-rendering/Utils.js.map +0 -1
  240. package/dist/src/core/text-rendering/canvas/Settings.d.ts +0 -53
  241. package/dist/src/core/text-rendering/canvas/Settings.js +0 -20
  242. package/dist/src/core/text-rendering/canvas/Settings.js.map +0 -1
  243. package/dist/src/core/text-rendering/canvas/Utils.d.ts +0 -19
  244. package/dist/src/core/text-rendering/canvas/Utils.js +0 -139
  245. package/dist/src/core/text-rendering/canvas/Utils.js.map +0 -1
  246. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.d.ts +0 -37
  247. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js +0 -188
  248. package/dist/src/core/text-rendering/canvas/calculateRenderInfo.js.map +0 -1
  249. package/dist/src/core/text-rendering/canvas/draw.d.ts +0 -12
  250. package/dist/src/core/text-rendering/canvas/draw.js +0 -133
  251. package/dist/src/core/text-rendering/canvas/draw.js.map +0 -1
  252. package/dist/src/core/text-rendering/sdf/PeekableGenerator.d.ts +0 -12
  253. package/dist/src/core/text-rendering/sdf/PeekableGenerator.js +0 -61
  254. package/dist/src/core/text-rendering/sdf/PeekableGenerator.js.map +0 -1
  255. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.d.ts +0 -45
  256. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js +0 -69
  257. package/dist/src/core/text-rendering/sdf/SimpleFontShaper.js.map +0 -1
@@ -22,7 +22,6 @@ import { assertTruthy } from '../../../utils.js';
22
22
  import type { TextureMemoryManager } from '../../TextureMemoryManager.js';
23
23
  import type { WebGlContextWrapper } from '../../lib/WebGlContextWrapper.js';
24
24
  import type { Texture } from '../../textures/Texture.js';
25
- import { isPowerOfTwo } from '../../utils.js';
26
25
  import { CoreContextTexture } from '../CoreContextTexture.js';
27
26
  import { isHTMLImageElement } from './internal/RendererUtils.js';
28
27
 
@@ -52,6 +51,25 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
52
51
  super(memManager, textureSource);
53
52
  }
54
53
 
54
+ /**
55
+ * GL error check with direct state marking
56
+ * Uses cached error result to minimize function calls
57
+ */
58
+ private checkGLError(): boolean {
59
+ // Skip if already failed to prevent double-processing
60
+ if (this.state === 'failed') {
61
+ return true;
62
+ }
63
+
64
+ const error = this.glw.getError();
65
+ if (error !== 0) {
66
+ this.state = 'failed';
67
+ this.textureSource.setState('failed', new Error(`WebGL Error: ${error}`));
68
+ return true;
69
+ }
70
+ return false;
71
+ }
72
+
55
73
  get ctxTexture(): WebGLTexture | null {
56
74
  if (this.state === 'freed') {
57
75
  this.load();
@@ -92,10 +110,11 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
92
110
 
93
111
  if (this._nativeCtxTexture === null) {
94
112
  this.state = 'failed';
95
- const error = new Error('Could not create WebGL Texture');
96
- this.textureSource.setState('failed', error);
97
- console.error('Could not create WebGL Texture');
98
- throw error;
113
+ this.textureSource.setState(
114
+ 'failed',
115
+ new Error('WebGL Texture creation failed'),
116
+ );
117
+ return;
99
118
  }
100
119
 
101
120
  try {
@@ -113,16 +132,7 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
113
132
  // Update the texture source's width and height so that it can be used
114
133
  // for rendering.
115
134
  this.textureSource.setState('loaded', { width, height });
116
-
117
- // cleanup source texture data next tick
118
- // This is done using queueMicrotask to ensure it runs after the current
119
- // event loop tick, allowing the texture to be fully loaded and bound
120
- // to the GL context before freeing the source data.
121
- // This is important to avoid issues with the texture data being
122
- // freed while the texture is still being loaded or used.
123
- queueMicrotask(() => {
124
- this.textureSource.freeTextureData();
125
- });
135
+ this.textureSource.freeTextureData();
126
136
  } catch (err: unknown) {
127
137
  // If the texture has been freed while loading, return early.
128
138
  // Type assertion needed because state could change during async operations
@@ -130,12 +140,9 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
130
140
  return;
131
141
  }
132
142
 
143
+ // Ensure texture is marked as failed
133
144
  this.state = 'failed';
134
- const error = err instanceof Error ? err : new Error(String(err));
135
- this.textureSource.setState('failed', error);
136
- this.textureSource.freeTextureData();
137
- console.error(err);
138
- throw error; // Re-throw to propagate the error
145
+ this.textureSource.setState('failed');
139
146
  }
140
147
  }
141
148
 
@@ -145,10 +152,19 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
145
152
  async onLoadRequest(): Promise<Dimensions> {
146
153
  const { glw } = this;
147
154
  const textureData = this.textureSource.textureData;
155
+
156
+ // Early return if texture is already failed
157
+ if (this.state === 'failed') {
158
+ return { width: 0, height: 0 };
159
+ }
160
+
148
161
  if (textureData === null || this._nativeCtxTexture === null) {
149
- throw new Error(
150
- 'Texture data or native texture is null ' + this.textureSource.type,
162
+ this.state = 'failed';
163
+ this.textureSource.setState(
164
+ 'failed',
165
+ new Error('No texture data available'),
151
166
  );
167
+ return { width: 0, height: 0 };
152
168
  }
153
169
 
154
170
  // Set to a 1x1 transparent texture
@@ -160,6 +176,11 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
160
176
 
161
177
  glw.activeTexture(0);
162
178
 
179
+ // High-performance error check - single call, direct state marking
180
+ if (this.checkGLError() === true) {
181
+ return { width: 0, height: 0 };
182
+ }
183
+
163
184
  const tdata = textureData.data;
164
185
  const format = glw.RGBA;
165
186
  const formatBytes = 4;
@@ -183,25 +204,13 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
183
204
 
184
205
  glw.texImage2D(0, format, format, glw.UNSIGNED_BYTE, tdata);
185
206
 
186
- this.setTextureMemUse(height * width * formatBytes * memoryPadding);
187
- } else if (tdata === null) {
188
- width = 0;
189
- height = 0;
190
- // Reset to a 1x1 transparent texture
191
- glw.bindTexture(this._nativeCtxTexture);
207
+ // Check for errors after image upload operations
208
+ if (this.checkGLError() === true) {
209
+ return { width: 0, height: 0 };
210
+ }
192
211
 
193
- glw.texImage2D(
194
- 0,
195
- format,
196
- 1,
197
- 1,
198
- 0,
199
- format,
200
- glw.UNSIGNED_BYTE,
201
- TRANSPARENT_TEXTURE_DATA,
202
- );
203
- this.setTextureMemUse(TRANSPARENT_TEXTURE_DATA.byteLength);
204
- } else if ('mipmaps' in tdata && tdata.mipmaps) {
212
+ this.setTextureMemUse(height * width * formatBytes * memoryPadding);
213
+ } else if (tdata && 'mipmaps' in tdata && tdata.mipmaps) {
205
214
  const { mipmaps, width = 0, height = 0, type, glInternalFormat } = tdata;
206
215
  const view =
207
216
  type === 'ktx'
@@ -216,6 +225,11 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
216
225
  glw.texParameteri(glw.TEXTURE_MAG_FILTER, glw.LINEAR);
217
226
  glw.texParameteri(glw.TEXTURE_MIN_FILTER, glw.LINEAR);
218
227
 
228
+ // Check for errors after compressed texture operations
229
+ if (this.checkGLError() === true) {
230
+ return { width: 0, height: 0 };
231
+ }
232
+
219
233
  this.setTextureMemUse(view.byteLength);
220
234
  } else if (tdata && tdata instanceof Uint8Array) {
221
235
  // Color Texture
@@ -239,12 +253,24 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
239
253
  tdata,
240
254
  );
241
255
 
256
+ // Check for errors after color texture operations
257
+ if (this.checkGLError() === true) {
258
+ return { width: 0, height: 0 };
259
+ }
260
+
242
261
  this.setTextureMemUse(width * height * formatBytes);
243
262
  } else {
244
263
  console.error(
245
264
  `WebGlCoreCtxTexture.onLoadRequest: Unexpected textureData returned`,
246
265
  textureData,
247
266
  );
267
+
268
+ this.state = 'failed';
269
+ this.textureSource.setState(
270
+ 'failed',
271
+ new Error('Unexpected texture data'),
272
+ );
273
+ return { width: 0, height: 0 };
248
274
  }
249
275
 
250
276
  return {
@@ -265,6 +291,13 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
265
291
 
266
292
  this.state = 'freed';
267
293
  this.textureSource.setState('freed');
294
+ this.release();
295
+ }
296
+
297
+ /**
298
+ * Release the WebGLTexture from the GPU without changing state
299
+ */
300
+ release(): void {
268
301
  this._w = 0;
269
302
  this._h = 0;
270
303
 
@@ -308,6 +341,11 @@ export class WebGlCoreCtxTexture extends CoreContextTexture {
308
341
  glw.texParameteri(glw.TEXTURE_WRAP_S, glw.CLAMP_TO_EDGE);
309
342
  glw.texParameteri(glw.TEXTURE_WRAP_T, glw.CLAMP_TO_EDGE);
310
343
 
344
+ const error = glw.getError();
345
+ if (error !== 0) {
346
+ return null;
347
+ }
348
+
311
349
  return nativeTexture;
312
350
  }
313
351
  }
@@ -412,7 +412,7 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
412
412
  this.setStatus(state, 'failed', new Error(msg));
413
413
  return;
414
414
  }
415
- trFontFace.texture.setRenderableOwner(state, true);
415
+ trFontFace.texture.setRenderableOwner(state.props.fontFamily, true);
416
416
  }
417
417
 
418
418
  // If the font hasn't been loaded yet, stop here.
@@ -787,13 +787,16 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
787
787
  renderable: boolean,
788
788
  ): void {
789
789
  super.setIsRenderable(state, renderable);
790
- state.trFontFace?.texture.setRenderableOwner(state, renderable);
790
+ state.trFontFace?.texture.setRenderableOwner(
791
+ state.props.fontFamily,
792
+ renderable,
793
+ );
791
794
  }
792
795
 
793
796
  override destroyState(state: SdfTextRendererState): void {
794
797
  super.destroyState(state);
795
798
  // If there's a Font Face assigned we must free the owner relation to its texture
796
- state.trFontFace?.texture.setRenderableOwner(state, false);
799
+ state.trFontFace?.texture.setRenderableOwner(state.props.fontFamily, false);
797
800
  }
798
801
  //#endregion Overrides
799
802
 
@@ -813,7 +816,10 @@ export class SdfTextRenderer extends TextRenderer<SdfTextRendererState> {
813
816
  protected releaseFontFace(state: SdfTextRendererState) {
814
817
  state.resLineHeight = undefined;
815
818
  if (state.trFontFace) {
816
- state.trFontFace.texture.setRenderableOwner(state, false);
819
+ state.trFontFace.texture.setRenderableOwner(
820
+ state.props.fontFamily,
821
+ false,
822
+ );
817
823
  state.trFontFace = undefined;
818
824
  }
819
825
  }
@@ -45,13 +45,12 @@ export interface ColorTextureProps {
45
45
  * a Node are.
46
46
  */
47
47
  export class ColorTexture extends Texture {
48
- public override type: TextureType = TextureType.color;
48
+ override readonly type = TextureType.color as const;
49
+ public props: Required<ColorTextureProps>;
49
50
 
50
- props: Required<ColorTextureProps>;
51
-
52
- constructor(txManager: CoreTextureManager, props?: ColorTextureProps) {
51
+ constructor(txManager: CoreTextureManager, props: ColorTextureProps) {
53
52
  super(txManager);
54
- this.props = ColorTexture.resolveDefaults(props || {});
53
+ this.props = ColorTexture.resolveDefaults(props);
55
54
  }
56
55
 
57
56
  get color() {
@@ -77,8 +76,6 @@ export class ColorTexture extends Texture {
77
76
  pixelData[3] = (this.color >>> 24) & 0xff; // Alpha
78
77
  }
79
78
 
80
- this.setState('fetched', { width: 1, height: 1 });
81
-
82
79
  return {
83
80
  data: pixelData,
84
81
  premultiplyAlpha: true,
@@ -107,6 +107,13 @@ export interface ImageTextureProps {
107
107
  * @default null
108
108
  */
109
109
  sy?: number | null;
110
+
111
+ /**
112
+ * Maximum number of times to retry loading the image if it fails.
113
+ *
114
+ * @default 5
115
+ */
116
+ maxRetryCount?: number | null;
110
117
  }
111
118
 
112
119
  /**
@@ -124,13 +131,14 @@ export interface ImageTextureProps {
124
131
  * {@link ImageTextureProps.premultiplyAlpha} prop to `false`.
125
132
  */
126
133
  export class ImageTexture extends Texture {
134
+ override readonly type = TextureType.image as const;
127
135
  public props: Required<ImageTextureProps>;
128
136
 
129
- public override type: TextureType = TextureType.image;
130
-
131
137
  constructor(txManager: CoreTextureManager, props: ImageTextureProps) {
138
+ const resolvedProps = ImageTexture.resolveDefaults(props);
132
139
  super(txManager);
133
- this.props = ImageTexture.resolveDefaults(props);
140
+ this.props = resolvedProps;
141
+ this.maxRetryCount = props.maxRetryCount as number;
134
142
  }
135
143
 
136
144
  hasAlphaChannel(mimeType: string) {
@@ -147,14 +155,19 @@ export class ImageTexture extends Texture {
147
155
  return new Promise<{
148
156
  data: HTMLImageElement | null;
149
157
  premultiplyAlpha: boolean;
150
- }>((resolve) => {
158
+ }>((resolve, reject) => {
151
159
  img.onload = () => {
152
160
  resolve({ data: img, premultiplyAlpha: hasAlpha });
153
161
  };
154
162
 
155
- img.onerror = () => {
156
- console.warn('Image loading failed, returning fallback object.');
157
- resolve({ data: null, premultiplyAlpha: hasAlpha });
163
+ img.onerror = (err) => {
164
+ const errorMessage =
165
+ err instanceof Error
166
+ ? err.message
167
+ : err instanceof Event
168
+ ? `Image loading failed for ${img.src}`
169
+ : 'Unknown image loading error';
170
+ reject(new Error(`Image loading failed: ${errorMessage}`));
158
171
  };
159
172
 
160
173
  if (src instanceof Blob) {
@@ -181,28 +194,40 @@ export class ImageTexture extends Texture {
181
194
 
182
195
  if (imageBitmapSupported.full === true && sw !== null && sh !== null) {
183
196
  // createImageBitmap with crop
184
- const bitmap = await createImageBitmap(blob, sx || 0, sy || 0, sw, sh, {
185
- premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
186
- colorSpaceConversion: 'none',
187
- imageOrientation: 'none',
188
- });
189
- return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
197
+ try {
198
+ const bitmap = await createImageBitmap(blob, sx || 0, sy || 0, sw, sh, {
199
+ premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
200
+ colorSpaceConversion: 'none',
201
+ imageOrientation: 'none',
202
+ });
203
+ return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
204
+ } catch (error) {
205
+ throw new Error(`Failed to create image bitmap with crop: ${error}`);
206
+ }
190
207
  } else if (imageBitmapSupported.basic === true) {
191
208
  // basic createImageBitmap without options or crop
192
209
  // this is supported for Chrome v50 to v52/54 that doesn't support options
193
- return {
194
- data: await createImageBitmap(blob),
195
- premultiplyAlpha: hasAlphaChannel,
196
- };
210
+ try {
211
+ return {
212
+ data: await createImageBitmap(blob),
213
+ premultiplyAlpha: hasAlphaChannel,
214
+ };
215
+ } catch (error) {
216
+ throw new Error(`Failed to create basic image bitmap: ${error}`);
217
+ }
197
218
  }
198
219
 
199
220
  // default createImageBitmap without crop but with options
200
- const bitmap = await createImageBitmap(blob, {
201
- premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
202
- colorSpaceConversion: 'none',
203
- imageOrientation: 'none',
204
- });
205
- return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
221
+ try {
222
+ const bitmap = await createImageBitmap(blob, {
223
+ premultiplyAlpha: hasAlphaChannel ? 'premultiply' : 'none',
224
+ colorSpaceConversion: 'none',
225
+ imageOrientation: 'none',
226
+ });
227
+ return { data: bitmap, premultiplyAlpha: hasAlphaChannel };
228
+ } catch (error) {
229
+ throw new Error(`Failed to create image bitmap with options: ${error}`);
230
+ }
206
231
  }
207
232
 
208
233
  async loadImage(src: string) {
@@ -214,14 +239,18 @@ export class ImageTexture extends Texture {
214
239
  this.txManager.hasWorker === true &&
215
240
  this.txManager.imageWorkerManager !== null
216
241
  ) {
217
- return this.txManager.imageWorkerManager.getImage(
218
- src,
219
- premultiplyAlpha,
220
- sx,
221
- sy,
222
- sw,
223
- sh,
224
- );
242
+ try {
243
+ return this.txManager.imageWorkerManager.getImage(
244
+ src,
245
+ premultiplyAlpha,
246
+ sx,
247
+ sy,
248
+ sw,
249
+ sh,
250
+ );
251
+ } catch (error) {
252
+ throw new Error(`Failed to load image via worker: ${error}`);
253
+ }
225
254
  }
226
255
 
227
256
  let blob;
@@ -229,9 +258,11 @@ export class ImageTexture extends Texture {
229
258
  if (isBase64Image(src) === true) {
230
259
  blob = dataURIToBlob(src);
231
260
  } else {
232
- blob = await fetchJson(src, 'blob').then(
233
- (response) => response as Blob,
234
- );
261
+ try {
262
+ blob = (await fetchJson(src, 'blob')) as Blob;
263
+ } catch (error) {
264
+ throw new Error(`Failed to fetch image blob from ${src}: ${error}`);
265
+ }
235
266
  }
236
267
 
237
268
  return this.createImageBitmap(blob, premultiplyAlpha, sx, sy, sw, sh);
@@ -258,23 +289,6 @@ export class ImageTexture extends Texture {
258
289
  };
259
290
  }
260
291
 
261
- let width, height;
262
- // check if resp.data is typeof Uint8ClampedArray else
263
- // use resp.data.width and resp.data.height
264
- if (resp.data instanceof Uint8Array) {
265
- width = this.props.width ?? 0;
266
- height = this.props.height ?? 0;
267
- } else {
268
- width = resp.data?.width ?? (this.props.width || 0);
269
- height = resp.data?.height ?? (this.props.height || 0);
270
- }
271
-
272
- // we're loaded!
273
- this.setState('fetched', {
274
- width,
275
- height,
276
- });
277
-
278
292
  return {
279
293
  data: resp.data,
280
294
  premultiplyAlpha: this.props.premultiplyAlpha ?? true,
@@ -393,6 +407,7 @@ export class ImageTexture extends Texture {
393
407
  sy: props.sy ?? null,
394
408
  sw: props.sw ?? null,
395
409
  sh: props.sh ?? null,
410
+ maxRetryCount: props.maxRetryCount ?? 5,
396
411
  };
397
412
  }
398
413
 
@@ -75,7 +75,7 @@ export class NoiseTexture extends Texture {
75
75
  pixelData8[i + 3] = 255;
76
76
  }
77
77
 
78
- this.setState('fetched');
78
+ // Noise texture data ready - dimensions will be set during upload
79
79
 
80
80
  return {
81
81
  data: new ImageData(pixelData8, width, height),
@@ -64,7 +64,7 @@ export class RenderTexture extends Texture {
64
64
  }
65
65
 
66
66
  override async getTextureSource(): Promise<TextureData> {
67
- this.setState('fetched');
67
+ // Render texture data ready - dimensions will be set during upload
68
68
 
69
69
  return {
70
70
  data: null,
@@ -30,6 +30,8 @@ import {
30
30
  type TextureState,
31
31
  } from './Texture.js';
32
32
 
33
+ let subTextureId = 0;
34
+
33
35
  /**
34
36
  * Properties of the {@link SubTexture}
35
37
  */
@@ -83,6 +85,7 @@ export class SubTexture extends Texture {
83
85
  parentTexture: Texture;
84
86
 
85
87
  public override type: TextureType = TextureType.subTexture;
88
+ public subtextureId = `subtexture-${subTextureId++}`;
86
89
 
87
90
  constructor(txManager: CoreTextureManager, props: SubTextureProps) {
88
91
  super(txManager);
@@ -97,8 +100,8 @@ export class SubTexture extends Texture {
97
100
  // Resolve parent texture from cache or fallback to provided texture
98
101
  this.parentTexture = txManager.resolveParentTexture(this.props.texture);
99
102
 
100
- if (this.renderableOwners.size > 0) {
101
- this.parentTexture.setRenderableOwner(this, true);
103
+ if (this.renderableOwners.length > 0) {
104
+ this.parentTexture.setRenderableOwner(this.subtextureId, true);
102
105
  }
103
106
 
104
107
  // If parent texture is already loaded / failed, trigger loaded event manually
@@ -107,23 +110,17 @@ export class SubTexture extends Texture {
107
110
  // synchronous task after calling loadTexture()
108
111
  queueMicrotask(() => {
109
112
  const parentTx = this.parentTexture;
110
- if (parentTx.state === 'loaded') {
111
- this.onParentTxLoaded(parentTx, parentTx.dimensions!);
112
- } else if (parentTx.state === 'fetching') {
113
- this.onParentTxFetching();
114
- } else if (parentTx.state === 'fetched') {
115
- this.onParentTxFetched();
113
+ if (parentTx.state === 'loaded' && parentTx.dimensions) {
114
+ this.onParentTxLoaded(parentTx, parentTx.dimensions);
116
115
  } else if (parentTx.state === 'loading') {
117
116
  this.onParentTxLoading();
118
- } else if (parentTx.state === 'failed') {
119
- this.onParentTxFailed(parentTx, parentTx.error!);
117
+ } else if (parentTx.state === 'failed' && parentTx.error) {
118
+ this.onParentTxFailed(parentTx, parentTx.error);
120
119
  } else if (parentTx.state === 'freed') {
121
120
  this.onParentTxFreed();
122
121
  }
123
122
 
124
- parentTx.on('fetched', this.onParentTxFetched);
125
123
  parentTx.on('loading', this.onParentTxLoading);
126
- parentTx.on('fetching', this.onParentTxFetching);
127
124
  parentTx.on('loaded', this.onParentTxLoaded);
128
125
  parentTx.on('failed', this.onParentTxFailed);
129
126
  parentTx.on('freed', this.onParentTxFreed);
@@ -143,17 +140,6 @@ export class SubTexture extends Texture {
143
140
  this.forwardParentTxState('failed', error);
144
141
  };
145
142
 
146
- private onParentTxFetched = () => {
147
- this.forwardParentTxState('fetched', {
148
- width: this.props.width,
149
- height: this.props.height,
150
- });
151
- };
152
-
153
- private onParentTxFetching = () => {
154
- this.forwardParentTxState('fetching');
155
- };
156
-
157
143
  private onParentTxLoading = () => {
158
144
  this.forwardParentTxState('loading');
159
145
  };
@@ -171,17 +157,14 @@ export class SubTexture extends Texture {
171
157
 
172
158
  override onChangeIsRenderable(isRenderable: boolean): void {
173
159
  // Propagate the renderable owner change to the parent texture
174
- this.parentTexture.setRenderableOwner(this, isRenderable);
160
+ this.parentTexture.setRenderableOwner(this.subtextureId, isRenderable);
175
161
  }
176
162
 
177
163
  override async getTextureSource(): Promise<TextureData> {
178
- // Check if parent texture is loaded
179
- return new Promise((resolve, reject) => {
180
- this.setState('fetched');
181
- resolve({
182
- data: this.props,
183
- });
184
- });
164
+ // SubTexture data ready - dimensions will be set during upload
165
+ return {
166
+ data: this.props,
167
+ };
185
168
  }
186
169
 
187
170
  // eslint-disable-next-line @typescript-eslint/no-unused-vars