canvasframework 0.6.3 → 0.7.1
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.
- package/components/AppBar.js +159 -99
- package/components/Avatar.js +142 -143
- package/components/BottomSheet.js +124 -106
- package/components/Button.js +207 -254
- package/components/Checkbox.js +98 -91
- package/components/Chip.js +137 -106
- package/components/Dialog.js +161 -146
- package/components/FAB.js +122 -195
- package/components/Switch.js +146 -112
- package/components/Text.js +104 -103
- package/components/Toast.js +132 -156
- package/components/VirtualList.js +88 -59
- package/core/CanvasFramework.js +115 -44
- package/core/CanvasUtils.js +141 -0
- package/core/Component.js +124 -66
- package/core/ThemeManager.js +162 -176
- package/core/WebGLCanvasAdapter.js +88 -39
- package/package.json +1 -1
|
@@ -89,6 +89,12 @@ class WebGLCanvasAdapter {
|
|
|
89
89
|
// ── Stats ─────────────────────────────────────────────────────────
|
|
90
90
|
this.stats = { drawCalls: 0, glyphsCached: 0, culled: 0, instancesDrawn: 0 };
|
|
91
91
|
|
|
92
|
+
// ── Cache couleurs (initialisé ici pour éviter la création lazy dans _parseColor) ──
|
|
93
|
+
this._colorCache = new Map();
|
|
94
|
+
|
|
95
|
+
// ── Flag anti-récursion pour _rebuildAtlas ─────────────────────────
|
|
96
|
+
this._rebuilding = false;
|
|
97
|
+
|
|
92
98
|
// Nettoyage périodique de l'atlas si saturation
|
|
93
99
|
this._cleanupTimer = setInterval(() => this._maybeRebuildAtlas(), 30000);
|
|
94
100
|
}
|
|
@@ -108,14 +114,17 @@ class WebGLCanvasAdapter {
|
|
|
108
114
|
alpha: true,
|
|
109
115
|
premultipliedAlpha: false,
|
|
110
116
|
antialias: false,
|
|
111
|
-
preserveDrawingBuffer:
|
|
117
|
+
// preserveDrawingBuffer: false (défaut) — le résultat est copié via drawImage()
|
|
118
|
+
// immédiatement après chaque draw call, donc pas besoin de préserver le buffer.
|
|
119
|
+
// Laisser à false permet au driver GPU d'utiliser le double-buffering natif.
|
|
120
|
+
preserveDrawingBuffer: false,
|
|
112
121
|
powerPreference: 'high-performance'
|
|
113
122
|
});
|
|
114
123
|
|
|
115
124
|
// Fallback WebGL1 si WebGL2 indispo
|
|
116
125
|
this.gl = gl || this._glCanvas.getContext('webgl', {
|
|
117
126
|
alpha: true, premultipliedAlpha: false,
|
|
118
|
-
antialias: false, preserveDrawingBuffer:
|
|
127
|
+
antialias: false, preserveDrawingBuffer: false
|
|
119
128
|
});
|
|
120
129
|
|
|
121
130
|
if (!this.gl) throw new Error('WebGL non disponible');
|
|
@@ -265,6 +274,54 @@ class WebGLCanvasAdapter {
|
|
|
265
274
|
this._instanceData.byteLength,
|
|
266
275
|
gl.DYNAMIC_DRAW
|
|
267
276
|
);
|
|
277
|
+
|
|
278
|
+
// VAO WebGL2 : enregistre le layout des attributs une seule fois.
|
|
279
|
+
// Évite de rebinder chaque attribut à chaque draw call (gain CPU mesurable).
|
|
280
|
+
if (this._isWebGL2) {
|
|
281
|
+
this._vao = gl.createVertexArray();
|
|
282
|
+
gl.bindVertexArray(this._vao);
|
|
283
|
+
this._setupAttribPointers();
|
|
284
|
+
gl.bindVertexArray(null);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Configure les pointeurs d'attributs vertex (appelé une fois dans le VAO,
|
|
290
|
+
* ou à chaque draw call en WebGL1).
|
|
291
|
+
* @private
|
|
292
|
+
*/
|
|
293
|
+
_setupAttribPointers() {
|
|
294
|
+
const gl = this.gl;
|
|
295
|
+
const loc = this._loc;
|
|
296
|
+
const ext = this._ext;
|
|
297
|
+
const stride = this._FLOATS_PER_INSTANCE * 4;
|
|
298
|
+
|
|
299
|
+
// Quad (diviseur 0 = même valeur pour toutes les instances)
|
|
300
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuf);
|
|
301
|
+
gl.enableVertexAttribArray(loc.quad);
|
|
302
|
+
gl.vertexAttribPointer(loc.quad, 2, gl.FLOAT, false, 0, 0);
|
|
303
|
+
if (ext) ext.vertexAttribDivisorANGLE(loc.quad, 0);
|
|
304
|
+
else gl.vertexAttribDivisor(loc.quad, 0);
|
|
305
|
+
|
|
306
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._instanceBuf);
|
|
307
|
+
|
|
308
|
+
// a_dst : vec4 @ offset 0
|
|
309
|
+
gl.enableVertexAttribArray(loc.dst);
|
|
310
|
+
gl.vertexAttribPointer(loc.dst, 4, gl.FLOAT, false, stride, 0);
|
|
311
|
+
if (ext) ext.vertexAttribDivisorANGLE(loc.dst, 1);
|
|
312
|
+
else gl.vertexAttribDivisor(loc.dst, 1);
|
|
313
|
+
|
|
314
|
+
// a_uv : vec4 @ offset 16
|
|
315
|
+
gl.enableVertexAttribArray(loc.uv);
|
|
316
|
+
gl.vertexAttribPointer(loc.uv, 4, gl.FLOAT, false, stride, 16);
|
|
317
|
+
if (ext) ext.vertexAttribDivisorANGLE(loc.uv, 1);
|
|
318
|
+
else gl.vertexAttribDivisor(loc.uv, 1);
|
|
319
|
+
|
|
320
|
+
// a_color : vec4 @ offset 32
|
|
321
|
+
gl.enableVertexAttribArray(loc.color);
|
|
322
|
+
gl.vertexAttribPointer(loc.color, 4, gl.FLOAT, false, stride, 32);
|
|
323
|
+
if (ext) ext.vertexAttribDivisorANGLE(loc.color, 1);
|
|
324
|
+
else gl.vertexAttribDivisor(loc.color, 1);
|
|
268
325
|
}
|
|
269
326
|
|
|
270
327
|
_setupAtlasTexture() {
|
|
@@ -373,8 +430,12 @@ class WebGLCanvasAdapter {
|
|
|
373
430
|
/**
|
|
374
431
|
* Reconstruit l'atlas depuis zéro avec uniquement les glyphes actuels.
|
|
375
432
|
* Appelé quand l'atlas est saturé.
|
|
433
|
+
* Protégé contre la réentrance par _rebuilding.
|
|
376
434
|
*/
|
|
377
435
|
_rebuildAtlas() {
|
|
436
|
+
if (this._rebuilding) return; // évite la récursion infinie
|
|
437
|
+
this._rebuilding = true;
|
|
438
|
+
|
|
378
439
|
const ctx = this._atlasCtx;
|
|
379
440
|
ctx.clearRect(0, 0, this.atlasSize, this.atlasSize);
|
|
380
441
|
|
|
@@ -391,7 +452,8 @@ class WebGLCanvasAdapter {
|
|
|
391
452
|
if (char && font) this._getGlyph(char, font);
|
|
392
453
|
}
|
|
393
454
|
|
|
394
|
-
this._atlasDirty
|
|
455
|
+
this._atlasDirty = true;
|
|
456
|
+
this._rebuilding = false;
|
|
395
457
|
}
|
|
396
458
|
|
|
397
459
|
_maybeRebuildAtlas() {
|
|
@@ -403,14 +465,18 @@ class WebGLCanvasAdapter {
|
|
|
403
465
|
|
|
404
466
|
/**
|
|
405
467
|
* Upload la texture atlas vers le GPU si elle a changé.
|
|
468
|
+
* Utilise texSubImage2D (mise à jour partielle) plutôt que texImage2D (ré-allocation
|
|
469
|
+
* complète) pour éviter un round-trip mémoire GPU inutile à chaque modification.
|
|
406
470
|
* Appelé UNE seule fois par frame, juste avant le draw call.
|
|
407
471
|
*/
|
|
408
472
|
_uploadAtlasIfDirty() {
|
|
409
473
|
if (!this._atlasDirty) return;
|
|
410
474
|
const gl = this.gl;
|
|
411
475
|
gl.bindTexture(gl.TEXTURE_2D, this._atlasTex);
|
|
412
|
-
|
|
413
|
-
|
|
476
|
+
// texSubImage2D met à jour les données sans réallouer le stockage GPU
|
|
477
|
+
gl.texSubImage2D(
|
|
478
|
+
gl.TEXTURE_2D, 0,
|
|
479
|
+
0, 0, // offset x, y dans la texture
|
|
414
480
|
gl.RGBA, gl.UNSIGNED_BYTE,
|
|
415
481
|
this._atlasCanvas
|
|
416
482
|
);
|
|
@@ -558,43 +624,29 @@ class WebGLCanvasAdapter {
|
|
|
558
624
|
gl.bindTexture(gl.TEXTURE_2D, this._atlasTex);
|
|
559
625
|
gl.uniform1i(loc.atlas, 0);
|
|
560
626
|
|
|
561
|
-
// 6.
|
|
562
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuf);
|
|
563
|
-
gl.enableVertexAttribArray(loc.quad);
|
|
564
|
-
gl.vertexAttribPointer(loc.quad, 2, gl.FLOAT, false, 0, 0);
|
|
565
|
-
if (ext) ext.vertexAttribDivisorANGLE(loc.quad, 0);
|
|
566
|
-
else gl.vertexAttribDivisor(loc.quad, 0);
|
|
567
|
-
|
|
568
|
-
// 7. Buffer instances — upload uniquement les instances actives
|
|
569
|
-
const stride = this._FLOATS_PER_INSTANCE * 4; // bytes
|
|
627
|
+
// 6. Upload uniquement les instances actives dans le buffer GPU
|
|
570
628
|
gl.bindBuffer(gl.ARRAY_BUFFER, this._instanceBuf);
|
|
571
629
|
gl.bufferSubData(
|
|
572
630
|
gl.ARRAY_BUFFER, 0,
|
|
573
631
|
this._instanceData.subarray(0, this._instanceCount * this._FLOATS_PER_INSTANCE)
|
|
574
632
|
);
|
|
575
633
|
|
|
576
|
-
//
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
else
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
gl.vertexAttribPointer(loc.uv, 4, gl.FLOAT, false, stride, 16);
|
|
585
|
-
if (ext) ext.vertexAttribDivisorANGLE(loc.uv, 1);
|
|
586
|
-
else gl.vertexAttribDivisor(loc.uv, 1);
|
|
587
|
-
|
|
588
|
-
// a_color : vec4 @ offset 32
|
|
589
|
-
gl.enableVertexAttribArray(loc.color);
|
|
590
|
-
gl.vertexAttribPointer(loc.color, 4, gl.FLOAT, false, stride, 32);
|
|
591
|
-
if (ext) ext.vertexAttribDivisorANGLE(loc.color, 1);
|
|
592
|
-
else gl.vertexAttribDivisor(loc.color, 1);
|
|
634
|
+
// 7. Lier les attributs vertex
|
|
635
|
+
if (this._vao) {
|
|
636
|
+
// WebGL2 : le VAO a déjà mémorisé le layout — un seul bind suffit
|
|
637
|
+
gl.bindVertexArray(this._vao);
|
|
638
|
+
} else {
|
|
639
|
+
// WebGL1 : rebinder les attributs manuellement à chaque draw call
|
|
640
|
+
this._setupAttribPointers();
|
|
641
|
+
}
|
|
593
642
|
|
|
594
643
|
// 8. LE draw call unique — dessine N instances du quad unitaire
|
|
595
644
|
if (ext) ext.drawArraysInstancedANGLE(gl.TRIANGLES, 0, 6, this._instanceCount);
|
|
596
645
|
else gl.drawArraysInstanced(gl.TRIANGLES, 0, 6, this._instanceCount);
|
|
597
646
|
|
|
647
|
+
// Libérer le VAO après usage
|
|
648
|
+
if (this._vao) gl.bindVertexArray(null);
|
|
649
|
+
|
|
598
650
|
// 9. Copier le résultat WebGL sur le canvas 2D principal
|
|
599
651
|
this.ctx.drawImage(this._glCanvas, 0, 0);
|
|
600
652
|
|
|
@@ -632,18 +684,14 @@ class WebGLCanvasAdapter {
|
|
|
632
684
|
|
|
633
685
|
/**
|
|
634
686
|
* Parse une couleur CSS → [r, g, b, a] normalisés [0..1]
|
|
635
|
-
* Supporte : #rgb #rrggbb rgba() rgb() et les couleurs nommées communes
|
|
687
|
+
* Supporte : #rgb #rrggbb #rrggbbaa rgba() rgb() et les couleurs nommées communes.
|
|
688
|
+
* Le cache (_colorCache) est initialisé dans le constructeur.
|
|
636
689
|
*/
|
|
637
690
|
_parseColor(color) {
|
|
638
691
|
if (!color) return [0, 0, 0, 1];
|
|
639
692
|
|
|
640
|
-
|
|
641
|
-
if (
|
|
642
|
-
const cached = this._colorCache.get(color);
|
|
643
|
-
if (cached) return cached;
|
|
644
|
-
} else {
|
|
645
|
-
this._colorCache = new Map();
|
|
646
|
-
}
|
|
693
|
+
const cached = this._colorCache.get(color);
|
|
694
|
+
if (cached) return cached;
|
|
647
695
|
|
|
648
696
|
let r = 0, g = 0, b = 0, a = 1;
|
|
649
697
|
|
|
@@ -769,6 +817,7 @@ class WebGLCanvasAdapter {
|
|
|
769
817
|
gl.deleteTexture(this._atlasTex);
|
|
770
818
|
gl.deleteBuffer(this._quadBuf);
|
|
771
819
|
gl.deleteBuffer(this._instanceBuf);
|
|
820
|
+
if (this._vao) gl.deleteVertexArray(this._vao);
|
|
772
821
|
gl.deleteProgram(this._program);
|
|
773
822
|
}
|
|
774
823
|
|