@swf2es/player 0.1.0 → 0.1.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/package.json +7 -7
- package/dist/audio.d.ts +0 -22
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -106
- package/dist/audio.js.map +0 -1
- package/dist/bitmap-filters.d.ts +0 -29
- package/dist/bitmap-filters.d.ts.map +0 -1
- package/dist/bitmap-filters.js +0 -906
- package/dist/bitmap-filters.js.map +0 -1
- package/dist/bitmap-ops.d.ts +0 -113
- package/dist/bitmap-ops.d.ts.map +0 -1
- package/dist/bitmap-ops.js +0 -725
- package/dist/bitmap-ops.js.map +0 -1
- package/dist/bitmap.d.ts +0 -98
- package/dist/bitmap.d.ts.map +0 -1
- package/dist/bitmap.js +0 -314
- package/dist/bitmap.js.map +0 -1
- package/dist/bounds.d.ts +0 -26
- package/dist/bounds.d.ts.map +0 -1
- package/dist/bounds.js +0 -300
- package/dist/bounds.js.map +0 -1
- package/dist/color.d.ts +0 -7
- package/dist/color.d.ts.map +0 -1
- package/dist/color.js +0 -42
- package/dist/color.js.map +0 -1
- package/dist/display.d.ts +0 -425
- package/dist/display.d.ts.map +0 -1
- package/dist/display.js +0 -1274
- package/dist/display.js.map +0 -1
- package/dist/drawing.d.ts +0 -52
- package/dist/drawing.d.ts.map +0 -1
- package/dist/drawing.js +0 -204
- package/dist/drawing.js.map +0 -1
- package/dist/filters.d.ts +0 -54
- package/dist/filters.d.ts.map +0 -1
- package/dist/filters.js +0 -155
- package/dist/filters.js.map +0 -1
- package/dist/fonts.d.ts +0 -23
- package/dist/fonts.d.ts.map +0 -1
- package/dist/fonts.js +0 -91
- package/dist/fonts.js.map +0 -1
- package/dist/geometry.d.ts +0 -21
- package/dist/geometry.d.ts.map +0 -1
- package/dist/geometry.js +0 -76
- package/dist/geometry.js.map +0 -1
- package/dist/gradients.d.ts +0 -29
- package/dist/gradients.d.ts.map +0 -1
- package/dist/gradients.js +0 -116
- package/dist/gradients.js.map +0 -1
- package/dist/images.d.ts +0 -22
- package/dist/images.d.ts.map +0 -1
- package/dist/images.js +0 -147
- package/dist/images.js.map +0 -1
- package/dist/input.d.ts +0 -79
- package/dist/input.d.ts.map +0 -1
- package/dist/input.js +0 -366
- package/dist/input.js.map +0 -1
- package/dist/keyboard.d.ts +0 -97
- package/dist/keyboard.d.ts.map +0 -1
- package/dist/keyboard.js +0 -583
- package/dist/keyboard.js.map +0 -1
- package/dist/morph.d.ts +0 -17
- package/dist/morph.d.ts.map +0 -1
- package/dist/morph.js +0 -218
- package/dist/morph.js.map +0 -1
- package/dist/pixi-blend.d.ts +0 -7
- package/dist/pixi-blend.d.ts.map +0 -1
- package/dist/pixi-blend.js +0 -253
- package/dist/pixi-blend.js.map +0 -1
- package/dist/pixi-color.d.ts +0 -54
- package/dist/pixi-color.d.ts.map +0 -1
- package/dist/pixi-color.js +0 -336
- package/dist/pixi-color.js.map +0 -1
- package/dist/pixi-filters.d.ts +0 -40
- package/dist/pixi-filters.d.ts.map +0 -1
- package/dist/pixi-filters.js +0 -953
- package/dist/pixi-filters.js.map +0 -1
- package/dist/pixi-resolve.d.ts +0 -4
- package/dist/pixi-resolve.d.ts.map +0 -1
- package/dist/pixi-resolve.js +0 -76
- package/dist/pixi-resolve.js.map +0 -1
- package/dist/pixi.d.ts +0 -219
- package/dist/pixi.d.ts.map +0 -1
- package/dist/pixi.js +0 -2169
- package/dist/pixi.js.map +0 -1
- package/dist/playerglobal/flash/filters/filters.d.ts +0 -26
- package/dist/playerglobal/flash/filters/filters.d.ts.map +0 -1
- package/dist/playerglobal/flash/filters/filters.js +0 -287
- package/dist/playerglobal/flash/filters/filters.js.map +0 -1
- package/dist/playerglobal/flash/system/FSCommand.d.ts +0 -4
- package/dist/playerglobal/flash/system/FSCommand.d.ts.map +0 -1
- package/dist/playerglobal/flash/system/FSCommand.js +0 -18
- package/dist/playerglobal/flash/system/FSCommand.js.map +0 -1
- package/dist/playerglobal/natives.d.ts +0 -10
- package/dist/playerglobal/natives.d.ts.map +0 -1
- package/dist/playerglobal/natives.js +0 -53
- package/dist/playerglobal/natives.js.map +0 -1
- package/dist/png.d.ts +0 -4
- package/dist/png.d.ts.map +0 -1
- package/dist/png.js +0 -140
- package/dist/png.js.map +0 -1
- package/dist/render/art.d.ts +0 -148
- package/dist/render/art.d.ts.map +0 -1
- package/dist/render/art.js +0 -575
- package/dist/render/art.js.map +0 -1
- package/dist/render/batchers.d.ts +0 -23
- package/dist/render/batchers.d.ts.map +0 -1
- package/dist/render/batchers.js +0 -52
- package/dist/render/batchers.js.map +0 -1
- package/dist/render/bitmaps.d.ts +0 -117
- package/dist/render/bitmaps.d.ts.map +0 -1
- package/dist/render/bitmaps.js +0 -422
- package/dist/render/bitmaps.js.map +0 -1
- package/dist/render/blend.d.ts +0 -37
- package/dist/render/blend.d.ts.map +0 -1
- package/dist/render/blend.js +0 -195
- package/dist/render/blend.js.map +0 -1
- package/dist/render/color.d.ts +0 -111
- package/dist/render/color.d.ts.map +0 -1
- package/dist/render/color.js +0 -533
- package/dist/render/color.js.map +0 -1
- package/dist/render/compositing.d.ts +0 -77
- package/dist/render/compositing.d.ts.map +0 -1
- package/dist/render/compositing.js +0 -188
- package/dist/render/compositing.js.map +0 -1
- package/dist/render/filters.d.ts +0 -98
- package/dist/render/filters.d.ts.map +0 -1
- package/dist/render/filters.js +0 -1326
- package/dist/render/filters.js.map +0 -1
- package/dist/render/hooks.d.ts +0 -4
- package/dist/render/hooks.d.ts.map +0 -1
- package/dist/render/hooks.js +0 -48
- package/dist/render/hooks.js.map +0 -1
- package/dist/render/node.d.ts +0 -139
- package/dist/render/node.d.ts.map +0 -1
- package/dist/render/node.js +0 -59
- package/dist/render/node.js.map +0 -1
- package/dist/render/patches.d.ts +0 -54
- package/dist/render/patches.d.ts.map +0 -1
- package/dist/render/patches.js +0 -154
- package/dist/render/patches.js.map +0 -1
- package/dist/render/planes.d.ts +0 -74
- package/dist/render/planes.d.ts.map +0 -1
- package/dist/render/planes.js +0 -267
- package/dist/render/planes.js.map +0 -1
- package/dist/render/pointer.d.ts +0 -5
- package/dist/render/pointer.d.ts.map +0 -1
- package/dist/render/pointer.js +0 -279
- package/dist/render/pointer.js.map +0 -1
- package/dist/render/pools.d.ts +0 -122
- package/dist/render/pools.d.ts.map +0 -1
- package/dist/render/pools.js +0 -238
- package/dist/render/pools.js.map +0 -1
- package/dist/render/resolve.d.ts +0 -4
- package/dist/render/resolve.d.ts.map +0 -1
- package/dist/render/resolve.js +0 -76
- package/dist/render/resolve.js.map +0 -1
- package/dist/render/saffron.d.ts +0 -135
- package/dist/render/saffron.d.ts.map +0 -1
- package/dist/render/saffron.js +0 -725
- package/dist/render/saffron.js.map +0 -1
- package/dist/render/settle.d.ts +0 -60
- package/dist/render/settle.d.ts.map +0 -1
- package/dist/render/settle.js +0 -128
- package/dist/render/settle.js.map +0 -1
- package/dist/render/shared.d.ts +0 -25
- package/dist/render/shared.d.ts.map +0 -1
- package/dist/render/shared.js +0 -33
- package/dist/render/shared.js.map +0 -1
- package/dist/render/snapshot.d.ts +0 -21
- package/dist/render/snapshot.d.ts.map +0 -1
- package/dist/render/snapshot.js +0 -91
- package/dist/render/snapshot.js.map +0 -1
- package/dist/render/spares.d.ts +0 -56
- package/dist/render/spares.d.ts.map +0 -1
- package/dist/render/spares.js +0 -160
- package/dist/render/spares.js.map +0 -1
- package/dist/render/strokes.d.ts +0 -107
- package/dist/render/strokes.d.ts.map +0 -1
- package/dist/render/strokes.js +0 -448
- package/dist/render/strokes.js.map +0 -1
- package/dist/render/table.d.ts +0 -213
- package/dist/render/table.d.ts.map +0 -1
- package/dist/render/table.js +0 -795
- package/dist/render/table.js.map +0 -1
- package/dist/render/tessellate.d.ts +0 -89
- package/dist/render/tessellate.d.ts.map +0 -1
- package/dist/render/tessellate.js +0 -386
- package/dist/render/tessellate.js.map +0 -1
- package/dist/render/text.d.ts +0 -40
- package/dist/render/text.d.ts.map +0 -1
- package/dist/render/text.js +0 -309
- package/dist/render/text.js.map +0 -1
- package/dist/render/three.d.ts +0 -83
- package/dist/render/three.d.ts.map +0 -1
- package/dist/render/three.js +0 -511
- package/dist/render/three.js.map +0 -1
- package/dist/render/triangles.d.ts +0 -28
- package/dist/render/triangles.d.ts.map +0 -1
- package/dist/render/triangles.js +0 -189
- package/dist/render/triangles.js.map +0 -1
- package/dist/render/view.d.ts +0 -238
- package/dist/render/view.d.ts.map +0 -1
- package/dist/render/view.js +0 -1173
- package/dist/render/view.js.map +0 -1
- package/dist/render/worker/bitmaps.d.ts +0 -43
- package/dist/render/worker/bitmaps.d.ts.map +0 -1
- package/dist/render/worker/bitmaps.js +0 -151
- package/dist/render/worker/bitmaps.js.map +0 -1
- package/dist/render/worker/drawing.d.ts +0 -21
- package/dist/render/worker/drawing.d.ts.map +0 -1
- package/dist/render/worker/drawing.js +0 -356
- package/dist/render/worker/drawing.js.map +0 -1
- package/dist/render/worker/filters.d.ts +0 -7
- package/dist/render/worker/filters.d.ts.map +0 -1
- package/dist/render/worker/filters.js +0 -125
- package/dist/render/worker/filters.js.map +0 -1
- package/dist/render/worker/frames.d.ts +0 -32
- package/dist/render/worker/frames.d.ts.map +0 -1
- package/dist/render/worker/frames.js +0 -124
- package/dist/render/worker/frames.js.map +0 -1
- package/dist/render/worker/host.d.ts +0 -60
- package/dist/render/worker/host.d.ts.map +0 -1
- package/dist/render/worker/host.js +0 -297
- package/dist/render/worker/host.js.map +0 -1
- package/dist/render/worker/libraries.d.ts +0 -36
- package/dist/render/worker/libraries.d.ts.map +0 -1
- package/dist/render/worker/libraries.js +0 -153
- package/dist/render/worker/libraries.js.map +0 -1
- package/dist/render/worker/presentation.d.ts +0 -18
- package/dist/render/worker/presentation.d.ts.map +0 -1
- package/dist/render/worker/presentation.js +0 -47
- package/dist/render/worker/presentation.js.map +0 -1
- package/dist/render/worker/renderer.d.ts +0 -4
- package/dist/render/worker/renderer.d.ts.map +0 -1
- package/dist/render/worker/renderer.js +0 -21
- package/dist/render/worker/renderer.js.map +0 -1
- package/dist/render/worker/scene.d.ts +0 -32
- package/dist/render/worker/scene.d.ts.map +0 -1
- package/dist/render/worker/scene.js +0 -611
- package/dist/render/worker/scene.js.map +0 -1
- package/dist/render/worker/text.d.ts +0 -47
- package/dist/render/worker/text.d.ts.map +0 -1
- package/dist/render/worker/text.js +0 -261
- package/dist/render/worker/text.js.map +0 -1
- package/dist/render/worker/thread.d.ts +0 -23
- package/dist/render/worker/thread.d.ts.map +0 -1
- package/dist/render/worker/thread.js +0 -107
- package/dist/render/worker/thread.js.map +0 -1
- package/dist/render/worker/values.d.ts +0 -18
- package/dist/render/worker/values.d.ts.map +0 -1
- package/dist/render/worker/values.js +0 -64
- package/dist/render/worker/values.js.map +0 -1
- package/dist/sha256.d.ts +0 -5
- package/dist/sha256.d.ts.map +0 -1
- package/dist/sha256.js +0 -96
- package/dist/sha256.js.map +0 -1
- package/dist/shapes.d.ts +0 -71
- package/dist/shapes.d.ts.map +0 -1
- package/dist/shapes.js +0 -340
- package/dist/shapes.js.map +0 -1
- package/dist/static-text.d.ts +0 -33
- package/dist/static-text.d.ts.map +0 -1
- package/dist/static-text.js +0 -105
- package/dist/static-text.js.map +0 -1
- package/dist/text-layout.d.ts +0 -66
- package/dist/text-layout.d.ts.map +0 -1
- package/dist/text-layout.js +0 -315
- package/dist/text-layout.js.map +0 -1
- package/dist/text.d.ts +0 -67
- package/dist/text.d.ts.map +0 -1
- package/dist/text.js +0 -383
- package/dist/text.js.map +0 -1
- package/dist/timeline.d.ts +0 -150
- package/dist/timeline.d.ts.map +0 -1
- package/dist/timeline.js +0 -266
- package/dist/timeline.js.map +0 -1
package/dist/render/table.js
DELETED
|
@@ -1,795 +0,0 @@
|
|
|
1
|
-
import { Buffer, BufferImageSource, BufferUsage, color32BitToUniform, ExtensionType, extensions, Geometry, GlProgram, RendererType, Shader, State, Texture, UniformGroup, } from "pixi.js";
|
|
2
|
-
const NAME = "flashTable";
|
|
3
|
-
/**
|
|
4
|
-
* Texels a row: the linear part; the translation, and whether a colour
|
|
5
|
-
* transform applies; the tint; the colour transform's multipliers and its
|
|
6
|
-
* offsets.
|
|
7
|
-
*/
|
|
8
|
-
const ROW_TEXELS = 5;
|
|
9
|
-
const ROWS_A_LINE = 256;
|
|
10
|
-
const TABLE_WIDTH = ROWS_A_LINE * ROW_TEXELS;
|
|
11
|
-
/**
|
|
12
|
-
* The fewest draws a run makes as one multi-draw; a shorter one is drawn
|
|
13
|
-
* from the atlas a call a draw. A multi-draw call costs Chrome's GPU
|
|
14
|
-
* process some 5 to 15 µs more than its draws would alone, and saves the
|
|
15
|
-
* page well under 1 µs a draw: in a crowd of filtered creatures, each
|
|
16
|
-
* filter ending a run, runs of 2 to 10 draws took a frame 1 to 5 ms longer
|
|
17
|
-
* than Pixi's draws on a GPU, and runs of 22 broke even (`bench.ts --rig
|
|
18
|
-
* 128 --filtered K --gpu`). Drawn a call a draw from the atlas, the same
|
|
19
|
-
* short runs took less than either.
|
|
20
|
-
*/
|
|
21
|
-
const MIN_RUN = 16;
|
|
22
|
-
/**
|
|
23
|
-
* The most draws a run passes in uniforms rather than through the table
|
|
24
|
-
* texture, whose upload costs Chrome a few µs more a run: 40 rows of 5
|
|
25
|
-
* vectors leave room for Pixi's, and for what a driver keeps for itself,
|
|
26
|
-
* under the 256 every WebGL 2 allows a vertex shader.
|
|
27
|
-
*/
|
|
28
|
-
const SHORT_RUN = 40;
|
|
29
|
-
/** Floats a vertex of a context's packed geometry: position, UV, colour, texture and rounding. */
|
|
30
|
-
const VERTEX_FLOATS = 6;
|
|
31
|
-
const VERTEX_BYTES = VERTEX_FLOATS * 4;
|
|
32
|
-
/** Atlas vertices dropped contexts may leave as holes before it is packed again. */
|
|
33
|
-
const ATLAS_SLACK = 1 << 16;
|
|
34
|
-
/** The fewest vertices the atlas holds room for, and its indices thrice that. */
|
|
35
|
-
const ATLAS_LEAST = 4096;
|
|
36
|
-
/**
|
|
37
|
-
* How much the atlas grows by when full, and how much room it is given
|
|
38
|
-
* over its live vertices as it starts again: doubled, and kept at its
|
|
39
|
-
* peak, a crowded room's held 96 MB of vertices and 48 MB of indices with
|
|
40
|
-
* a third and a fifth of them in use.
|
|
41
|
-
*/
|
|
42
|
-
const ATLAS_GROWTH = 1.5;
|
|
43
|
-
let enabled = true;
|
|
44
|
-
let minRun = MIN_RUN;
|
|
45
|
-
let loopShort = true;
|
|
46
|
-
/**
|
|
47
|
-
* Draw Graphics alone through the table, or not, from the next frame: a
|
|
48
|
-
* switch to time the two apart. Runs already built draw through Pixi's
|
|
49
|
-
* pipe while it is off; a group built while it was off draws alone until
|
|
50
|
-
* it is built again. `shortest` is the fewest draws a run makes as one
|
|
51
|
-
* multi-draw, MIN_RUN by default: the tests have the table draw every run
|
|
52
|
-
* so with 1, and the bench times others. A shorter run is drawn from the
|
|
53
|
-
* atlas a call a draw, its rows passed in uniforms, or with `loop` false
|
|
54
|
-
* by Pixi's pipe; so is it with `shortest` past SHORT_RUN + 1, as the
|
|
55
|
-
* uniforms hold no more rows.
|
|
56
|
-
*/
|
|
57
|
-
export function setTransformTable(on, shortest = MIN_RUN, loop = true) {
|
|
58
|
-
enabled = on;
|
|
59
|
-
minRun = shortest;
|
|
60
|
-
loopShort = loop;
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* The vertex shader, reading a draw's row from the table texture or, for a
|
|
64
|
-
* short run (SHORT_RUN), from a uniform array laid out as the table's rows.
|
|
65
|
-
* Under a Flash colour transform it passes the straight colour as the
|
|
66
|
-
* colour batcher packs it (render/color.ts, straight): the fill's times the
|
|
67
|
-
* Graphics' own tint, rounded to a byte, and its alpha truncated to one; Pixi's group
|
|
68
|
-
* colour is left out, as the transform includes every ancestor's.
|
|
69
|
-
*/
|
|
70
|
-
const vertex = (short) => `#version 300 es
|
|
71
|
-
#extension GL_ANGLE_multi_draw : require
|
|
72
|
-
in vec2 aPosition;
|
|
73
|
-
in vec4 aColor;
|
|
74
|
-
uniform mat3 uProjectionMatrix;
|
|
75
|
-
uniform mat3 uWorldTransformMatrix;
|
|
76
|
-
uniform vec4 uWorldColorAlpha;
|
|
77
|
-
uniform vec2 uResolution;
|
|
78
|
-
${short
|
|
79
|
-
? `uniform vec4 uRows[${SHORT_RUN * ROW_TEXELS}];
|
|
80
|
-
uniform int uFirst;`
|
|
81
|
-
: `uniform highp sampler2D uTable;
|
|
82
|
-
uniform float uBase;`}
|
|
83
|
-
out vec4 vColor;
|
|
84
|
-
flat out float vFlash;
|
|
85
|
-
flat out vec4 vMul;
|
|
86
|
-
flat out vec4 vAdd;
|
|
87
|
-
|
|
88
|
-
void main(void) {
|
|
89
|
-
${short
|
|
90
|
-
? ` int at = (uFirst + gl_DrawID) * ${ROW_TEXELS};
|
|
91
|
-
vec4 m = uRows[at];
|
|
92
|
-
vec4 t = uRows[at + 1];
|
|
93
|
-
vec4 tint = uRows[at + 2];
|
|
94
|
-
vec4 mul = uRows[at + 3];
|
|
95
|
-
vec4 add = uRows[at + 4];`
|
|
96
|
-
: ` int row = int(uBase) + gl_DrawID;
|
|
97
|
-
ivec2 at = ivec2((row & ${ROWS_A_LINE - 1}) * ${ROW_TEXELS}, row >> ${Math.log2(ROWS_A_LINE)});
|
|
98
|
-
vec4 m = texelFetch(uTable, at, 0);
|
|
99
|
-
vec4 t = texelFetch(uTable, at + ivec2(1, 0), 0);
|
|
100
|
-
vec4 tint = texelFetch(uTable, at + ivec2(2, 0), 0);
|
|
101
|
-
vec4 mul = texelFetch(uTable, at + ivec2(3, 0), 0);
|
|
102
|
-
vec4 add = texelFetch(uTable, at + ivec2(4, 0), 0);`}
|
|
103
|
-
mat3 modelMatrix = mat3(m.x, m.y, 0.0, m.z, m.w, 0.0, t.x, t.y, 1.0);
|
|
104
|
-
mat3 modelViewProjectionMatrix = uProjectionMatrix * uWorldTransformMatrix * modelMatrix;
|
|
105
|
-
gl_Position = vec4((modelViewProjectionMatrix * vec3(aPosition, 1.0)).xy, 0.0, 1.0);
|
|
106
|
-
vFlash = t.z;
|
|
107
|
-
vMul = mul;
|
|
108
|
-
vAdd = add;
|
|
109
|
-
if (t.z > 0.5) {
|
|
110
|
-
// A byte's product is never half way between two, so the rounding is the batcher's.
|
|
111
|
-
vColor = vec4(
|
|
112
|
-
floor(aColor.rgb * tint.rgb * 255.0 + 0.5),
|
|
113
|
-
floor(aColor.a * tint.a * 255.0 + 0.001)
|
|
114
|
-
) / 255.0;
|
|
115
|
-
} else {
|
|
116
|
-
// As Pixi's graphics shader: the premultiplied fill times the group's tint and the world's.
|
|
117
|
-
vColor = vec4(1.0);
|
|
118
|
-
vColor *= vec4(aColor.rgb * aColor.a, aColor.a);
|
|
119
|
-
vColor *= tint;
|
|
120
|
-
vColor *= uWorldColorAlpha;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
`;
|
|
124
|
-
/** Under a colour transform, as the colour batcher's shader: applied to straight colour, clamped. */
|
|
125
|
-
const fragment = `#version 300 es
|
|
126
|
-
in vec4 vColor;
|
|
127
|
-
flat in float vFlash;
|
|
128
|
-
flat in vec4 vMul;
|
|
129
|
-
flat in vec4 vAdd;
|
|
130
|
-
out vec4 finalColor;
|
|
131
|
-
|
|
132
|
-
void main(void) {
|
|
133
|
-
if (vFlash > 0.5) {
|
|
134
|
-
vec4 c = clamp(vColor * vMul + vAdd, 0.0, 1.0);
|
|
135
|
-
finalColor = vec4(c.rgb * c.a, c.a);
|
|
136
|
-
} else {
|
|
137
|
-
finalColor = vColor;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
`;
|
|
141
|
-
/** Pixi puts its precision and name first, where an extension may no longer be asked for. */
|
|
142
|
-
function tableProgram(short) {
|
|
143
|
-
const program = new GlProgram({
|
|
144
|
-
name: short ? `${NAME}-short` : NAME,
|
|
145
|
-
vertex: vertex(short),
|
|
146
|
-
fragment,
|
|
147
|
-
});
|
|
148
|
-
const directive = "#extension GL_ANGLE_multi_draw : require\n";
|
|
149
|
-
const source = (program.vertex ?? "").replace(directive, "");
|
|
150
|
-
const version = "#version 300 es\n";
|
|
151
|
-
program.vertex = source.startsWith(version)
|
|
152
|
-
? version + directive + source.slice(version.length)
|
|
153
|
-
: directive + source;
|
|
154
|
-
return program;
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* Vertices placed and not yet written are gathered in arrays of up to this
|
|
158
|
-
* many, and their indices in up to thrice as many, written in one call
|
|
159
|
-
* each: so a frame that places hundreds of contexts makes a few writes,
|
|
160
|
-
* not hundreds, and keeps no more than these on the CPU, some 2 MB at most.
|
|
161
|
-
*/
|
|
162
|
-
const STAGED_VERTICES = 1 << 16;
|
|
163
|
-
const STAGED_FLOATS = STAGED_VERTICES * VERTEX_FLOATS;
|
|
164
|
-
const STAGED_INDICES = STAGED_VERTICES * 3;
|
|
165
|
-
const atlases = new Set();
|
|
166
|
-
/**
|
|
167
|
-
* The local vertices of every context the table has drawn, in one buffer
|
|
168
|
-
* with one index buffer, absolute: each context's are copied in once, as
|
|
169
|
-
* Pixi packed them for it, and stay until it is rebuilt or destroyed. The
|
|
170
|
-
* holes those leave are reclaimed by packing again (compact). They are
|
|
171
|
-
* kept on the GPU alone: a crowded room's atlas held some 130 MB on the CPU
|
|
172
|
-
* as well, which only a lost context, after which it starts again anyway,
|
|
173
|
-
* could have used.
|
|
174
|
-
*/
|
|
175
|
-
export class Atlas {
|
|
176
|
-
/** The vertices and indices placed, which the store holds or which are staged for it. */
|
|
177
|
-
vertexCount = 0;
|
|
178
|
-
indexCount = 0;
|
|
179
|
-
/** The vertices and indices the store has room for. */
|
|
180
|
-
capacity = ATLAS_LEAST;
|
|
181
|
-
indexCapacity = ATLAS_LEAST * 3;
|
|
182
|
-
/** The vertices and indices the store holds; those placed since are staged. */
|
|
183
|
-
sentVertices = 0;
|
|
184
|
-
sentIndices = 0;
|
|
185
|
-
/** Whether the store has room made for the capacity: not as it starts, shrinks or is lost. */
|
|
186
|
-
allocated = false;
|
|
187
|
-
/** What is staged, in arrays grown as a frame places more, up to STAGED_VERTICES. */
|
|
188
|
-
staged = new Float32Array(0);
|
|
189
|
-
stagedIndices = new Uint32Array(0);
|
|
190
|
-
placed = new Map();
|
|
191
|
-
live = 0;
|
|
192
|
-
liveIndices = 0;
|
|
193
|
-
holes = 0;
|
|
194
|
-
/** The id of a texture that is no texture, which alone the table draws. */
|
|
195
|
-
white;
|
|
196
|
-
store;
|
|
197
|
-
constructor(white, store) {
|
|
198
|
-
this.white = white;
|
|
199
|
-
this.store = store;
|
|
200
|
-
atlases.add(this);
|
|
201
|
-
}
|
|
202
|
-
/** Where `key`'s batches lie: null if the table cannot draw them, undefined if not yet placed. */
|
|
203
|
-
where(key) {
|
|
204
|
-
return this.placed.get(key);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Where `key`'s batches lie, `packed` copied in first if they are not
|
|
208
|
-
* there yet; null if the table cannot draw them. What is copied in is
|
|
209
|
-
* staged, and the store has it once send is called.
|
|
210
|
-
*/
|
|
211
|
-
place(key, packed) {
|
|
212
|
-
const known = this.placed.get(key);
|
|
213
|
-
if (known !== undefined) {
|
|
214
|
-
return known;
|
|
215
|
-
}
|
|
216
|
-
const { batcher, instructions } = packed;
|
|
217
|
-
for (let i = 0; i < instructions.instructionSize; i++) {
|
|
218
|
-
const batch = instructions.instructions[i];
|
|
219
|
-
const textures = batch.textures;
|
|
220
|
-
let flat = batch.topology === "triangle-list";
|
|
221
|
-
for (let k = 0; k < textures.count; k++) {
|
|
222
|
-
flat &&= textures.textures[k].uid === this.white;
|
|
223
|
-
}
|
|
224
|
-
if (!flat) {
|
|
225
|
-
this.placed.set(key, null);
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
const vertexCount = batcher.attributeSize / VERTEX_FLOATS;
|
|
230
|
-
const indexCount = batcher.indexSize;
|
|
231
|
-
this.reserve(vertexCount, indexCount);
|
|
232
|
-
const first = this.indexCount;
|
|
233
|
-
this.copyIn(batcher.attributeBuffer.float32View, batcher.attributeSize, batcher.indexBuffer, indexCount);
|
|
234
|
-
this.live += vertexCount;
|
|
235
|
-
this.liveIndices += indexCount;
|
|
236
|
-
const placed = {
|
|
237
|
-
vertices: vertexCount,
|
|
238
|
-
indices: indexCount,
|
|
239
|
-
counts: [],
|
|
240
|
-
offsets: [],
|
|
241
|
-
};
|
|
242
|
-
for (let i = 0; i < instructions.instructionSize; i++) {
|
|
243
|
-
const batch = instructions.instructions[i];
|
|
244
|
-
if (batch.size) {
|
|
245
|
-
placed.counts.push(batch.size);
|
|
246
|
-
placed.offsets.push((first + batch.start) * 4);
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
const shown = placed.counts.length ? placed : null;
|
|
250
|
-
this.placed.set(key, shown);
|
|
251
|
-
if (!shown) {
|
|
252
|
-
this.holes += vertexCount;
|
|
253
|
-
this.live -= vertexCount;
|
|
254
|
-
this.liveIndices -= indexCount;
|
|
255
|
-
}
|
|
256
|
-
return shown;
|
|
257
|
-
}
|
|
258
|
-
/** `key`'s context rebuilt or destroyed: its vertices become a hole. */
|
|
259
|
-
release(key) {
|
|
260
|
-
const placed = this.placed.get(key);
|
|
261
|
-
if (placed === undefined) {
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
264
|
-
this.placed.delete(key);
|
|
265
|
-
if (placed) {
|
|
266
|
-
this.live -= placed.vertices;
|
|
267
|
-
this.liveIndices -= placed.indices;
|
|
268
|
-
this.holes += placed.vertices;
|
|
269
|
-
}
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Pack again from scratch if holes pass ATLAS_SLACK and the live
|
|
273
|
-
* vertices: between frames, as a run's draws read where their contexts
|
|
274
|
-
* lie until it is drawn.
|
|
275
|
-
*/
|
|
276
|
-
compact() {
|
|
277
|
-
if (this.holes > ATLAS_SLACK && this.holes > this.live) {
|
|
278
|
-
this.clear();
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Forget every context, to be copied in again as each is next drawn: in
|
|
283
|
-
* a store cut down to what was live, with room to grow, when that needs
|
|
284
|
-
* less than half its capacity. Smaller reductions would undo the next
|
|
285
|
-
* growth as animated contexts leave holes and come back again.
|
|
286
|
-
*/
|
|
287
|
-
clear() {
|
|
288
|
-
const vertices = Math.ceil(Math.max(this.live * ATLAS_GROWTH, ATLAS_LEAST));
|
|
289
|
-
const indices = Math.ceil(Math.max(this.liveIndices * ATLAS_GROWTH, ATLAS_LEAST * 3));
|
|
290
|
-
if (vertices * 2 < this.capacity) {
|
|
291
|
-
this.capacity = vertices;
|
|
292
|
-
this.allocated = false;
|
|
293
|
-
}
|
|
294
|
-
if (indices * 2 < this.indexCapacity) {
|
|
295
|
-
this.indexCapacity = indices;
|
|
296
|
-
this.allocated = false;
|
|
297
|
-
}
|
|
298
|
-
this.placed.clear();
|
|
299
|
-
this.vertexCount = 0;
|
|
300
|
-
this.indexCount = 0;
|
|
301
|
-
this.sentVertices = 0;
|
|
302
|
-
this.sentIndices = 0;
|
|
303
|
-
this.live = 0;
|
|
304
|
-
this.liveIndices = 0;
|
|
305
|
-
this.holes = 0;
|
|
306
|
-
}
|
|
307
|
-
/** The store's buffers were lost with their context: every context is copied in again as drawn. */
|
|
308
|
-
lost() {
|
|
309
|
-
this.clear();
|
|
310
|
-
this.allocated = false;
|
|
311
|
-
}
|
|
312
|
-
/** Write what was staged into the store, room made for it first if the store has none yet. */
|
|
313
|
-
send() {
|
|
314
|
-
this.allocate();
|
|
315
|
-
const vertices = this.vertexCount - this.sentVertices;
|
|
316
|
-
if (vertices > 0) {
|
|
317
|
-
this.store.writeVertices(this.sentVertices, this.staged, vertices * VERTEX_FLOATS);
|
|
318
|
-
}
|
|
319
|
-
const indices = this.indexCount - this.sentIndices;
|
|
320
|
-
if (indices > 0) {
|
|
321
|
-
this.store.writeIndices(this.sentIndices, this.stagedIndices, indices);
|
|
322
|
-
}
|
|
323
|
-
this.sentVertices = this.vertexCount;
|
|
324
|
-
this.sentIndices = this.indexCount;
|
|
325
|
-
}
|
|
326
|
-
destroy() {
|
|
327
|
-
this.clear();
|
|
328
|
-
atlases.delete(this);
|
|
329
|
-
}
|
|
330
|
-
allocate() {
|
|
331
|
-
if (!this.allocated) {
|
|
332
|
-
// Only ever with nothing sent: as the atlas starts, starts again smaller, or is lost.
|
|
333
|
-
this.store.resize(this.capacity, this.indexCapacity, 0, 0);
|
|
334
|
-
this.allocated = true;
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
/**
|
|
338
|
-
* Stage `floats` of `vertices` and `count` of `indices` after what is
|
|
339
|
-
* placed, the indices offset by the vertices before them; written
|
|
340
|
-
* straight into the store, after what was staged, if they would not fit.
|
|
341
|
-
*/
|
|
342
|
-
copyIn(vertices, floats, indices, count) {
|
|
343
|
-
const base = this.vertexCount;
|
|
344
|
-
if ((base - this.sentVertices) * VERTEX_FLOATS + floats > STAGED_FLOATS ||
|
|
345
|
-
this.indexCount - this.sentIndices + count > STAGED_INDICES) {
|
|
346
|
-
this.send();
|
|
347
|
-
}
|
|
348
|
-
if (floats > STAGED_FLOATS || count > STAGED_INDICES) {
|
|
349
|
-
// Larger than the stage alone: written as it comes, its indices offset in an array of its own.
|
|
350
|
-
const offset = new Uint32Array(count);
|
|
351
|
-
for (let i = 0; i < count; i++) {
|
|
352
|
-
offset[i] = indices[i] + base;
|
|
353
|
-
}
|
|
354
|
-
this.store.writeVertices(base, vertices, floats);
|
|
355
|
-
this.store.writeIndices(this.indexCount, offset, count);
|
|
356
|
-
this.vertexCount += floats / VERTEX_FLOATS;
|
|
357
|
-
this.indexCount += count;
|
|
358
|
-
this.sentVertices = this.vertexCount;
|
|
359
|
-
this.sentIndices = this.indexCount;
|
|
360
|
-
return;
|
|
361
|
-
}
|
|
362
|
-
const stagedFloats = (base - this.sentVertices) * VERTEX_FLOATS;
|
|
363
|
-
const at = this.indexCount - this.sentIndices;
|
|
364
|
-
this.stage(stagedFloats + floats, at + count);
|
|
365
|
-
this.staged.set(vertices.subarray(0, floats), stagedFloats);
|
|
366
|
-
for (let i = 0; i < count; i++) {
|
|
367
|
-
this.stagedIndices[at + i] = indices[i] + base;
|
|
368
|
-
}
|
|
369
|
-
this.vertexCount += floats / VERTEX_FLOATS;
|
|
370
|
-
this.indexCount += count;
|
|
371
|
-
}
|
|
372
|
-
/** Staging arrays of at least `floats` and `count`, doubled as need be, what they stage kept. */
|
|
373
|
-
stage(floats, count) {
|
|
374
|
-
if (floats > this.staged.length) {
|
|
375
|
-
const grown = new Float32Array(Math.min(STAGED_FLOATS, Math.max(floats, this.staged.length * 2, 4096 * VERTEX_FLOATS)));
|
|
376
|
-
grown.set(this.staged.subarray(0, (this.vertexCount - this.sentVertices) * VERTEX_FLOATS));
|
|
377
|
-
this.staged = grown;
|
|
378
|
-
}
|
|
379
|
-
if (count > this.stagedIndices.length) {
|
|
380
|
-
const grown = new Uint32Array(Math.min(STAGED_INDICES, Math.max(count, this.stagedIndices.length * 2, 4096 * 3)));
|
|
381
|
-
grown.set(this.stagedIndices.subarray(0, this.indexCount - this.sentIndices));
|
|
382
|
-
this.stagedIndices = grown;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
/**
|
|
386
|
-
* Room in the store for `vertexCount` and `indexCount` more, grown by
|
|
387
|
-
* half if they do not fit, what it holds kept by the GPU's own copy.
|
|
388
|
-
*/
|
|
389
|
-
reserve(vertexCount, indexCount) {
|
|
390
|
-
this.allocate();
|
|
391
|
-
const vertices = this.vertexCount + vertexCount;
|
|
392
|
-
const indices = this.indexCount + indexCount;
|
|
393
|
-
if (vertices <= this.capacity && indices <= this.indexCapacity) {
|
|
394
|
-
return;
|
|
395
|
-
}
|
|
396
|
-
this.send();
|
|
397
|
-
if (vertices > this.capacity) {
|
|
398
|
-
this.capacity = Math.max(vertices, Math.ceil(this.capacity * ATLAS_GROWTH));
|
|
399
|
-
}
|
|
400
|
-
if (indices > this.indexCapacity) {
|
|
401
|
-
this.indexCapacity = Math.max(indices, Math.ceil(this.indexCapacity * ATLAS_GROWTH));
|
|
402
|
-
}
|
|
403
|
-
this.store.resize(this.capacity, this.indexCapacity, this.vertexCount, this.indexCount);
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
/**
|
|
407
|
-
* A context's GPU data reset, as it is built again and as it is destroyed
|
|
408
|
-
* (render/hooks.ts): its place in each atlas goes then.
|
|
409
|
-
*/
|
|
410
|
-
export function releaseFromAtlases(gpu) {
|
|
411
|
-
for (const atlas of atlases) {
|
|
412
|
-
atlas.release(gpu);
|
|
413
|
-
}
|
|
414
|
-
}
|
|
415
|
-
/** Add `graphics` to the run `instructionSet` ends with, or start one: anything else ends a run. */
|
|
416
|
-
export function addToRun(graphics, instructionSet) {
|
|
417
|
-
const size = instructionSet.instructionSize;
|
|
418
|
-
const last = instructionSet.instructions[size - 1];
|
|
419
|
-
if (size > 0 && last?.renderPipeId === NAME) {
|
|
420
|
-
last.items.push(graphics);
|
|
421
|
-
return;
|
|
422
|
-
}
|
|
423
|
-
const run = { renderPipeId: NAME, canBundle: false, items: [graphics] };
|
|
424
|
-
instructionSet.add(run);
|
|
425
|
-
}
|
|
426
|
-
const tableSource = (height) => new BufferImageSource({
|
|
427
|
-
resource: new Float32Array(TABLE_WIDTH * height * 4),
|
|
428
|
-
width: TABLE_WIDTH,
|
|
429
|
-
height,
|
|
430
|
-
format: "rgba32float",
|
|
431
|
-
alphaMode: "no-premultiply-alpha",
|
|
432
|
-
scaleMode: "nearest",
|
|
433
|
-
autoGenerateMipmaps: false,
|
|
434
|
-
});
|
|
435
|
-
export class TablePipe {
|
|
436
|
-
static extension = {
|
|
437
|
-
type: [ExtensionType.WebGLPipes, ExtensionType.WebGPUPipes],
|
|
438
|
-
name: NAME,
|
|
439
|
-
};
|
|
440
|
-
renderer;
|
|
441
|
-
multi = null;
|
|
442
|
-
/** The most rows the table may hold: as many lines as a texture may be tall. */
|
|
443
|
-
maxRows = 0;
|
|
444
|
-
shader = null;
|
|
445
|
-
shortShader = null;
|
|
446
|
-
/** Where the short shader's program, as last linked, takes its rows and first row, and that row. */
|
|
447
|
-
rows = null;
|
|
448
|
-
uniforms = new UniformGroup({ uBase: { value: 0, type: "f32" } });
|
|
449
|
-
state = State.for2d();
|
|
450
|
-
/** The next row free this frame. */
|
|
451
|
-
cursor = 0;
|
|
452
|
-
// Made for WebGL alone, the only renderer that draws the table. The
|
|
453
|
-
// table never shrinks from its peak, a crowded scene's rows; the atlas
|
|
454
|
-
// shrinks when its live geometry needs substantially less room.
|
|
455
|
-
table;
|
|
456
|
-
atlas;
|
|
457
|
-
attributes;
|
|
458
|
-
indexBuffer;
|
|
459
|
-
/** The bytes the GPU's copies of the atlas' buffers were last made to hold. */
|
|
460
|
-
vertexBytes = 0;
|
|
461
|
-
indexBytes = 0;
|
|
462
|
-
geometry;
|
|
463
|
-
/** The run being gathered: its first row, blend mode, and its draws' counts and offsets. */
|
|
464
|
-
counts = new Int32Array(1024);
|
|
465
|
-
offsets = new Int32Array(1024);
|
|
466
|
-
draws = 0;
|
|
467
|
-
runBase = 0;
|
|
468
|
-
runBlend = "";
|
|
469
|
-
/**
|
|
470
|
-
* The Graphics the run gathered, for Pixi's pipe to draw if it is too
|
|
471
|
-
* short for a multi-draw and the table leaves such runs to it (loops).
|
|
472
|
-
*/
|
|
473
|
-
segment = [];
|
|
474
|
-
constructor(renderer) {
|
|
475
|
-
this.renderer = renderer;
|
|
476
|
-
if (renderer.type !== RendererType.WEBGL) {
|
|
477
|
-
return;
|
|
478
|
-
}
|
|
479
|
-
this.table = tableSource(16);
|
|
480
|
-
// Placeholders: what the buffers hold lives on the GPU alone, written there by the atlas.
|
|
481
|
-
this.attributes = new Buffer({
|
|
482
|
-
data: new Float32Array(0),
|
|
483
|
-
usage: BufferUsage.VERTEX | BufferUsage.COPY_DST,
|
|
484
|
-
shrinkToFit: false,
|
|
485
|
-
});
|
|
486
|
-
this.indexBuffer = new Buffer({
|
|
487
|
-
data: new Uint32Array(0),
|
|
488
|
-
usage: BufferUsage.INDEX | BufferUsage.COPY_DST,
|
|
489
|
-
shrinkToFit: false,
|
|
490
|
-
});
|
|
491
|
-
// Not to be collected unused for a while, as Pixi would: nothing could upload them again.
|
|
492
|
-
this.attributes.autoGarbageCollect = false;
|
|
493
|
-
this.indexBuffer.autoGarbageCollect = false;
|
|
494
|
-
this.atlas = new Atlas(Texture.WHITE.source.uid, {
|
|
495
|
-
resize: (vertices, indices, keptVertices, keptIndices) => {
|
|
496
|
-
const buffers = this.renderer.buffer;
|
|
497
|
-
if (vertices * VERTEX_BYTES !== this.vertexBytes) {
|
|
498
|
-
this.vertexBytes = vertices * VERTEX_BYTES;
|
|
499
|
-
buffers.resizeOnGpu(this.attributes, this.vertexBytes, keptVertices * VERTEX_BYTES);
|
|
500
|
-
}
|
|
501
|
-
if (indices * 4 !== this.indexBytes) {
|
|
502
|
-
this.indexBytes = indices * 4;
|
|
503
|
-
buffers.resizeOnGpu(this.indexBuffer, this.indexBytes, keptIndices * 4);
|
|
504
|
-
}
|
|
505
|
-
},
|
|
506
|
-
writeVertices: (at, data, floats) => this.renderer.buffer.writeOnGpu(this.attributes, at * VERTEX_BYTES, data, 0, floats),
|
|
507
|
-
writeIndices: (at, data, count) => this.renderer.buffer.writeOnGpu(this.indexBuffer, at * 4, data, 0, count),
|
|
508
|
-
});
|
|
509
|
-
const stride = VERTEX_FLOATS * 4;
|
|
510
|
-
this.geometry = new Geometry({
|
|
511
|
-
attributes: {
|
|
512
|
-
aPosition: { buffer: this.attributes, format: "float32x2", stride, offset: 0 },
|
|
513
|
-
aColor: { buffer: this.attributes, format: "unorm8x4", stride, offset: 4 * 4 },
|
|
514
|
-
},
|
|
515
|
-
indexBuffer: this.indexBuffer,
|
|
516
|
-
});
|
|
517
|
-
renderer.runners.contextChange.add(this);
|
|
518
|
-
renderer.runners.prerender.add(this);
|
|
519
|
-
}
|
|
520
|
-
contextChange() {
|
|
521
|
-
const gl = this.renderer.gl;
|
|
522
|
-
this.multi =
|
|
523
|
-
this.renderer.context.webGLVersion === 2
|
|
524
|
-
? gl.getExtension("WEBGL_multi_draw")
|
|
525
|
-
: null;
|
|
526
|
-
this.maxRows = gl.getParameter(gl.MAX_TEXTURE_SIZE) * ROWS_A_LINE;
|
|
527
|
-
// A lost context took the atlas' buffers: every context is copied in again as it is drawn.
|
|
528
|
-
this.vertexBytes = 0;
|
|
529
|
-
this.indexBytes = 0;
|
|
530
|
-
this.atlas.lost();
|
|
531
|
-
}
|
|
532
|
-
prerender() {
|
|
533
|
-
this.cursor = 0;
|
|
534
|
-
this.atlas.compact();
|
|
535
|
-
}
|
|
536
|
-
/** Whether the table draws for this renderer: switched on, and WebGL 2 with multi-draw. */
|
|
537
|
-
get active() {
|
|
538
|
-
return enabled && this.multi !== null;
|
|
539
|
-
}
|
|
540
|
-
/** Whether a run too short for a multi-draw is drawn from the atlas, a call a draw. */
|
|
541
|
-
get loops() {
|
|
542
|
-
return loopShort && minRun <= SHORT_RUN + 1;
|
|
543
|
-
}
|
|
544
|
-
add(graphics, instructionSet) {
|
|
545
|
-
addToRun(graphics, instructionSet);
|
|
546
|
-
}
|
|
547
|
-
execute(instruction) {
|
|
548
|
-
const renderer = this.renderer;
|
|
549
|
-
const graphicsPipe = renderer.renderPipes.graphics;
|
|
550
|
-
const contexts = renderer.graphicsContext;
|
|
551
|
-
const roundAll = renderer._roundPixels;
|
|
552
|
-
// Switched off, a context restored without the extension, or, short
|
|
553
|
-
// runs left to it, a run that cannot reach minRun draws, before a row
|
|
554
|
-
// is written: Pixi's pipe draws it.
|
|
555
|
-
if (!this.active || (!this.loops && this.mostDraws(instruction, contexts) < minRun)) {
|
|
556
|
-
for (const item of instruction.items) {
|
|
557
|
-
graphicsPipe.execute(item);
|
|
558
|
-
}
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
this.runBase = this.cursor;
|
|
562
|
-
this.draws = 0;
|
|
563
|
-
for (const item of instruction.items) {
|
|
564
|
-
const graphics = item;
|
|
565
|
-
if (!graphics.isRenderable) {
|
|
566
|
-
continue;
|
|
567
|
-
}
|
|
568
|
-
const context = graphics.context;
|
|
569
|
-
const gpu = contexts.getGpuContext(context);
|
|
570
|
-
if (!gpu.batches.length) {
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
let place = gpu.isBatchable || context.customShader || roundAll | graphics._roundPixels
|
|
574
|
-
? null
|
|
575
|
-
: this.atlas.where(gpu);
|
|
576
|
-
if (place === undefined) {
|
|
577
|
-
// What Pixi packed is read only to be copied in, packed again if it was let go of.
|
|
578
|
-
place = this.atlas.place(gpu, contexts.getContextRenderDataOnCpu(context));
|
|
579
|
-
}
|
|
580
|
-
if (!place || this.cursor + place.counts.length > this.maxRows) {
|
|
581
|
-
this.flush();
|
|
582
|
-
graphicsPipe.execute(graphics);
|
|
583
|
-
continue;
|
|
584
|
-
}
|
|
585
|
-
if (graphics.groupBlendMode !== this.runBlend) {
|
|
586
|
-
this.flush();
|
|
587
|
-
this.runBlend = graphics.groupBlendMode;
|
|
588
|
-
}
|
|
589
|
-
if (!this.loops) {
|
|
590
|
-
this.segment.push(graphics);
|
|
591
|
-
}
|
|
592
|
-
for (let i = 0; i < place.counts.length; i++) {
|
|
593
|
-
this.row(graphics);
|
|
594
|
-
this.counts[this.draws] = place.counts[i];
|
|
595
|
-
this.offsets[this.draws] = place.offsets[i];
|
|
596
|
-
this.draws++;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
599
|
-
this.flush();
|
|
600
|
-
}
|
|
601
|
-
/** The draws `instruction` makes at most: one for each batch of each Graphics' context. */
|
|
602
|
-
mostDraws(instruction, contexts) {
|
|
603
|
-
let draws = 0;
|
|
604
|
-
for (const item of instruction.items) {
|
|
605
|
-
draws += contexts.getGpuContext(item.context).batches.length;
|
|
606
|
-
if (draws >= minRun) {
|
|
607
|
-
break;
|
|
608
|
-
}
|
|
609
|
-
}
|
|
610
|
-
return draws;
|
|
611
|
-
}
|
|
612
|
-
/** Write `graphics`' transform and tint into the next row, the table and run grown to hold it. */
|
|
613
|
-
row(graphics) {
|
|
614
|
-
if (this.cursor >= this.table.height * ROWS_A_LINE) {
|
|
615
|
-
this.grow();
|
|
616
|
-
}
|
|
617
|
-
if (this.draws === this.counts.length) {
|
|
618
|
-
const counts = new Int32Array(this.draws * 2);
|
|
619
|
-
const offsets = new Int32Array(this.draws * 2);
|
|
620
|
-
counts.set(this.counts);
|
|
621
|
-
offsets.set(this.offsets);
|
|
622
|
-
this.counts = counts;
|
|
623
|
-
this.offsets = offsets;
|
|
624
|
-
}
|
|
625
|
-
const out = this.table.resource;
|
|
626
|
-
const at = this.cursor * ROW_TEXELS * 4;
|
|
627
|
-
const m = graphics.groupTransform;
|
|
628
|
-
out[at] = m.a;
|
|
629
|
-
out[at + 1] = m.b;
|
|
630
|
-
out[at + 2] = m.c;
|
|
631
|
-
out[at + 3] = m.d;
|
|
632
|
-
out[at + 4] = m.tx;
|
|
633
|
-
out[at + 5] = m.ty;
|
|
634
|
-
const ct = graphics.flashColor;
|
|
635
|
-
if (ct) {
|
|
636
|
-
// Its own tint and alpha, straight, as the colour batcher's: a glyph's colour.
|
|
637
|
-
const bgr = graphics.localColor;
|
|
638
|
-
out[at + 6] = 1;
|
|
639
|
-
out[at + 8] = (bgr & 0xff) / 255;
|
|
640
|
-
out[at + 9] = ((bgr >> 8) & 0xff) / 255;
|
|
641
|
-
out[at + 10] = ((bgr >> 16) & 0xff) / 255;
|
|
642
|
-
out[at + 11] = graphics.localAlpha;
|
|
643
|
-
out[at + 12] = ct.rMul;
|
|
644
|
-
out[at + 13] = ct.gMul;
|
|
645
|
-
out[at + 14] = ct.bMul;
|
|
646
|
-
out[at + 15] = ct.aMul;
|
|
647
|
-
out[at + 16] = ct.rAdd / 255;
|
|
648
|
-
out[at + 17] = ct.gAdd / 255;
|
|
649
|
-
out[at + 18] = ct.bAdd / 255;
|
|
650
|
-
out[at + 19] = ct.aAdd / 255;
|
|
651
|
-
}
|
|
652
|
-
else {
|
|
653
|
-
out[at + 6] = 0;
|
|
654
|
-
color32BitToUniform(graphics.groupColorAlpha, out, at + 8);
|
|
655
|
-
}
|
|
656
|
-
this.cursor++;
|
|
657
|
-
}
|
|
658
|
-
/** The table twice as tall, at most maxRows, the rows this frame wrote so far brought along. */
|
|
659
|
-
grow() {
|
|
660
|
-
const table = tableSource(Math.min(this.table.height * 2, this.maxRows / ROWS_A_LINE));
|
|
661
|
-
table.resource.set(this.table.resource);
|
|
662
|
-
this.table.destroy();
|
|
663
|
-
this.table = table;
|
|
664
|
-
if (this.shader) {
|
|
665
|
-
this.shader.resources.uTable = table;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
/**
|
|
669
|
-
* Draw the run gathered as one call, its rows passed in uniforms if few,
|
|
670
|
-
* uploaded if not. A run too short to repay a multi-draw is drawn from
|
|
671
|
-
* the atlas a call a draw, its rows passed in uniforms at once and each
|
|
672
|
-
* draw told its row: the atlas' buffers bound once, where Pixi's pipe
|
|
673
|
-
* binds each context's own and sets each Graphics' uniforms. Or, with
|
|
674
|
-
* that switched off, its Graphics go through Pixi's pipe.
|
|
675
|
-
*/
|
|
676
|
-
flush() {
|
|
677
|
-
const draws = this.draws;
|
|
678
|
-
if (draws === 0 || !this.multi) {
|
|
679
|
-
this.segment.length = 0;
|
|
680
|
-
this.draws = 0;
|
|
681
|
-
this.runBase = this.cursor;
|
|
682
|
-
return;
|
|
683
|
-
}
|
|
684
|
-
const renderer = this.renderer;
|
|
685
|
-
const loop = draws < minRun;
|
|
686
|
-
if (loop && !this.loops) {
|
|
687
|
-
const graphicsPipe = renderer.renderPipes.graphics;
|
|
688
|
-
for (const graphics of this.segment) {
|
|
689
|
-
graphicsPipe.execute(graphics);
|
|
690
|
-
}
|
|
691
|
-
this.segment.length = 0;
|
|
692
|
-
this.draws = 0;
|
|
693
|
-
// Their rows are free again for the next run's.
|
|
694
|
-
this.cursor = this.runBase;
|
|
695
|
-
return;
|
|
696
|
-
}
|
|
697
|
-
this.segment.length = 0;
|
|
698
|
-
const short = draws <= SHORT_RUN;
|
|
699
|
-
if (!short) {
|
|
700
|
-
this.upload(this.runBase, this.cursor);
|
|
701
|
-
}
|
|
702
|
-
this.atlas.send();
|
|
703
|
-
const shader = short ? this.shortRunShader() : this.tableShader();
|
|
704
|
-
shader.groups[0] = renderer.globalUniforms.bindGroup;
|
|
705
|
-
this.state.blendMode = this.runBlend;
|
|
706
|
-
renderer.state.set(this.state);
|
|
707
|
-
renderer.shader.bind(shader);
|
|
708
|
-
const rows = short ? this.passRows(shader) : null;
|
|
709
|
-
renderer.geometry.bind(this.geometry, shader.glProgram);
|
|
710
|
-
const gl = renderer.gl;
|
|
711
|
-
if (loop && rows) {
|
|
712
|
-
// gl_DrawID is 0 in a draw of its own: uFirst names its row.
|
|
713
|
-
for (let i = 0; i < draws; i++) {
|
|
714
|
-
this.first(rows, i);
|
|
715
|
-
gl.drawElements(gl.TRIANGLES, this.counts[i], gl.UNSIGNED_INT, this.offsets[i]);
|
|
716
|
-
}
|
|
717
|
-
}
|
|
718
|
-
else {
|
|
719
|
-
if (rows) {
|
|
720
|
-
this.first(rows, 0);
|
|
721
|
-
}
|
|
722
|
-
this.multi.multiDrawElementsWEBGL(gl.TRIANGLES, this.counts, 0, gl.UNSIGNED_INT, this.offsets, 0, draws);
|
|
723
|
-
}
|
|
724
|
-
this.draws = 0;
|
|
725
|
-
// Rows passed in uniforms are free again for the next run's.
|
|
726
|
-
if (short) {
|
|
727
|
-
this.cursor = this.runBase;
|
|
728
|
-
}
|
|
729
|
-
this.runBase = this.cursor;
|
|
730
|
-
}
|
|
731
|
-
tableShader() {
|
|
732
|
-
this.shader ??= new Shader({
|
|
733
|
-
glProgram: tableProgram(false),
|
|
734
|
-
resources: { tableUniforms: this.uniforms, uTable: this.table },
|
|
735
|
-
});
|
|
736
|
-
this.uniforms.uniforms.uBase = this.runBase;
|
|
737
|
-
return this.shader;
|
|
738
|
-
}
|
|
739
|
-
shortRunShader() {
|
|
740
|
-
this.shortShader ??= new Shader({ glProgram: tableProgram(true), resources: {} });
|
|
741
|
-
return this.shortShader;
|
|
742
|
-
}
|
|
743
|
-
/** Pass the run's rows to the short shader, bound: Pixi knows nothing of its uRows and uFirst. */
|
|
744
|
-
passRows(shader) {
|
|
745
|
-
const gl = this.renderer.gl;
|
|
746
|
-
const program = this.renderer.shader._getProgramData(shader.glProgram).program;
|
|
747
|
-
if (this.rows?.program !== program) {
|
|
748
|
-
this.rows = {
|
|
749
|
-
program,
|
|
750
|
-
location: gl.getUniformLocation(program, "uRows"),
|
|
751
|
-
first: gl.getUniformLocation(program, "uFirst"),
|
|
752
|
-
firstValue: 0,
|
|
753
|
-
};
|
|
754
|
-
}
|
|
755
|
-
const floats = ROW_TEXELS * 4;
|
|
756
|
-
gl.uniform4fv(this.rows.location, this.table.resource, this.runBase * floats, this.draws * floats);
|
|
757
|
-
return this.rows;
|
|
758
|
-
}
|
|
759
|
-
/** Set the short shader's first row, bound, if it is not that already. */
|
|
760
|
-
first(rows, value) {
|
|
761
|
-
if (rows.firstValue !== value) {
|
|
762
|
-
rows.firstValue = value;
|
|
763
|
-
this.renderer.gl.uniform1i(rows.first, value);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Upload rows `from` up to `to` in one call: the part of the line they
|
|
768
|
-
* lie in, or the whole lines they span. A line's other rows go up again
|
|
769
|
-
* as the CPU holds them: rows a draw already read are as they were, and
|
|
770
|
-
* no draw yet to come reads the rest before writing and uploading them.
|
|
771
|
-
*/
|
|
772
|
-
upload(from, to) {
|
|
773
|
-
const renderer = this.renderer;
|
|
774
|
-
const gl = renderer.gl;
|
|
775
|
-
// Bound as Pixi binds, a new table allocated and uploaded whole then, and to the active unit,
|
|
776
|
-
// which a render pass may have moved to unbind a back texture: the upload must go to 0.
|
|
777
|
-
renderer.texture.bindForUpload(this.table, 0);
|
|
778
|
-
const first = Math.floor(from / ROWS_A_LINE);
|
|
779
|
-
const lines = Math.floor((to - 1) / ROWS_A_LINE) - first + 1;
|
|
780
|
-
const start = lines > 1 ? first * ROWS_A_LINE : from;
|
|
781
|
-
gl.texSubImage2D(gl.TEXTURE_2D, 0, (start - first * ROWS_A_LINE) * ROW_TEXELS, first, lines > 1 ? TABLE_WIDTH : (to - from) * ROW_TEXELS, lines, gl.RGBA, gl.FLOAT, this.table.resource, start * ROW_TEXELS * 4);
|
|
782
|
-
}
|
|
783
|
-
destroy() {
|
|
784
|
-
if (this.renderer.type !== RendererType.WEBGL) {
|
|
785
|
-
return;
|
|
786
|
-
}
|
|
787
|
-
this.shader?.destroy(true);
|
|
788
|
-
this.shortShader?.destroy(true);
|
|
789
|
-
this.geometry.destroy(true);
|
|
790
|
-
this.table.destroy();
|
|
791
|
-
this.atlas.destroy();
|
|
792
|
-
}
|
|
793
|
-
}
|
|
794
|
-
extensions.add(TablePipe);
|
|
795
|
-
//# sourceMappingURL=table.js.map
|