@swf2es/context3d 0.1.19 → 0.1.21

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 (56) hide show
  1. package/README.md +120 -27
  2. package/dist/agal.d.ts +11 -2
  3. package/dist/agal.d.ts.map +1 -1
  4. package/dist/agal.js +318 -47
  5. package/dist/agal.js.map +1 -1
  6. package/dist/backend.d.ts +50 -3
  7. package/dist/backend.d.ts.map +1 -1
  8. package/dist/backend.js +74 -2
  9. package/dist/backend.js.map +1 -1
  10. package/dist/errors.d.ts +1 -1
  11. package/dist/errors.d.ts.map +1 -1
  12. package/dist/errors.js.map +1 -1
  13. package/dist/index.d.ts +2 -2
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +2 -2
  16. package/dist/index.js.map +1 -1
  17. package/dist/webgl/back-buffer.d.ts +6 -0
  18. package/dist/webgl/back-buffer.d.ts.map +1 -0
  19. package/dist/webgl/back-buffer.js +197 -0
  20. package/dist/webgl/back-buffer.js.map +1 -0
  21. package/dist/webgl/buffers.d.ts +2 -2
  22. package/dist/webgl/buffers.d.ts.map +1 -1
  23. package/dist/webgl/buffers.js +105 -2
  24. package/dist/webgl/buffers.js.map +1 -1
  25. package/dist/webgl/context.d.ts +29 -48
  26. package/dist/webgl/context.d.ts.map +1 -1
  27. package/dist/webgl/context.js +227 -364
  28. package/dist/webgl/context.js.map +1 -1
  29. package/dist/webgl/programs.d.ts +4 -1
  30. package/dist/webgl/programs.d.ts.map +1 -1
  31. package/dist/webgl/programs.js +7 -6
  32. package/dist/webgl/programs.js.map +1 -1
  33. package/dist/webgl/readback.d.ts +3 -0
  34. package/dist/webgl/readback.d.ts.map +1 -0
  35. package/dist/webgl/readback.js +40 -0
  36. package/dist/webgl/readback.js.map +1 -0
  37. package/dist/webgl/targets.d.ts +3 -1
  38. package/dist/webgl/targets.d.ts.map +1 -1
  39. package/dist/webgl/targets.js +5 -3
  40. package/dist/webgl/targets.js.map +1 -1
  41. package/dist/webgl/textures.d.ts +9 -1
  42. package/dist/webgl/textures.d.ts.map +1 -1
  43. package/dist/webgl/textures.js +161 -7
  44. package/dist/webgl/textures.js.map +1 -1
  45. package/package.json +1 -1
  46. package/src/agal.ts +375 -51
  47. package/src/backend.ts +113 -3
  48. package/src/errors.ts +27 -1
  49. package/src/index.ts +12 -1
  50. package/src/webgl/back-buffer.ts +287 -0
  51. package/src/webgl/buffers.ts +114 -2
  52. package/src/webgl/context.ts +291 -489
  53. package/src/webgl/programs.ts +10 -5
  54. package/src/webgl/readback.ts +54 -0
  55. package/src/webgl/targets.ts +4 -2
  56. package/src/webgl/textures.ts +183 -9
package/README.md CHANGED
@@ -1,20 +1,23 @@
1
- # Experimental Context3D backend
1
+ # Context3D backend
2
2
 
3
- `@swf2es/context3d` provides resource/lifecycle contracts and AGAL v1 to GLSL
4
- translation. Its core has no dependencies or browser types. The optional
3
+ `@swf2es/context3d` provides resource/lifecycle contracts and AGAL 1, 2 and 3 to
4
+ GLSL ES 3.00 translation, for every Stage3D profile. Its core has no dependencies or browser types. The optional
5
5
  `@swf2es/context3d/webgl` entry exports `WebGLContext3D`, which owns the supplied
6
6
  WebGL2 context exclusively. It does not share GL state or resources with the
7
7
  display list's renderer.
8
8
 
9
9
  The WebGL entry re-exports the context owner from `webgl/context.ts`. That owner
10
- keeps resource maps, byte accounting, bindings and draw/present ordering together.
11
- `buffers.ts` and `textures.ts` handle uploads; `programs.ts` handles shader linking
12
- and uniform locations; `targets.ts` handles framebuffer allocation and resolves. Limits
13
- and render-state constants live beside those modules. These are internal splits;
14
- the package entries and ownership contracts stay the same.
10
+ keeps resource maps, byte accounting, bindings, state and draws together.
11
+ `buffers.ts` creates buffers and handles their uploads, and `textures.ts` texture
12
+ uploads; `programs.ts` handles shader linking and uniform locations; `targets.ts`
13
+ handles framebuffer allocation and resolves; `back-buffer.ts` configures the back
14
+ buffer, resolves and presents it, and `readback.ts` reads it back. Limits and
15
+ render-state constants live beside those modules. These are internal splits, the
16
+ moved parts functions over the context: the package entries and ownership contracts
17
+ stay the same.
15
18
 
16
19
  This package does not enable Stage3D playback. The separate
17
- `@swf2es/player/context3d` entry installs experimental Flash bindings, and
20
+ `@swf2es/player/context3d` entry installs the Flash bindings, and
18
21
  `@swf2es/player-hosts/stage3d` places canvases and attaches browser loss/restoration
19
22
  listeners. Install the bindings before loading playerglobal, and call their
20
23
  returned teardown before destroying Scripting. Default playback still reports
@@ -81,13 +84,101 @@ through is made at its first pixel upload or CPU decoding, so compressed
81
84
  textures uploaded as blocks on S3TC have none. Samplers must
82
85
  read a texture as what it is, AGAL's format DXT1 or DXT5 for a compressed one
83
86
  (#3763), where `samplerFormats` is set, as the player sets it for content from
84
- SWF 17 on. `rgbaHalfFloat` and the packed formats remain unsupported and return
85
- Error #3708 before backend allocation.
87
+ SWF 17 on, or RGBA for the packed and half-float formats.
88
+
89
+ `bgrPacked565` and `bgraPacked4444` are stored at 8 bits a channel (RGB8 and
90
+ RGBA8), as AIR draws into them: an upload keeps each channel's high bits and
91
+ widens them back as Direct3D reads them (`0x12` becomes `0x10` in 5:6:5), from a
92
+ BitmapData's premultiplied pixels or from little-endian words (5:6:5 red high,
93
+ 4:4:4:4 alpha, red, green, blue from the high nibble), two bytes a texel. 5:6:5
94
+ reads alpha 1. `rgbaHalfFloat` is RGBA16F, eight bytes a texel in R, G, B, A
95
+ order; a bitmap goes up as its bytes over 255. Drawing into one keeps values past
96
+ 1, and needs `EXT_color_buffer_float`, which every desktop WebGL 2 has. A clear's
97
+ colour is cut to 8 bits a channel on every target, as AIR clears through
98
+ Direct3D's 8-bit colour, by truncation: 0.5 clears to 127, and a half-float
99
+ target within 0 to 1.
100
+
101
+ ## Profiles
102
+
103
+ `Context3D.profile` sets what a context's programs, textures and targets may be
104
+ (`profileLimits`), as AIR 51.3 grants them under Wine, where it serves every
105
+ profile on Direct3D 9Ex (`tests/context3d`'s `Profiles.as`, `AGALProfiles.as`,
106
+ `AGALStandard.as`, `TextureFormats.as` and `MultipleTargets.as` hold the
107
+ references). Every profile has 16
108
+ sampler and vertex-stream slots, 250 vertex and 200 fragment constants for the
109
+ setters, cube faces up to 1024 and back buffers up to 16384. A constant setter
110
+ whose registers start or end past 250 or 200 is #2006 in every profile, a
111
+ matrix's four too; one within them writes them all, though an AGAL 1 program
112
+ reads only the first 128 and 28, and AGAL 2 the first 250 and 64:
113
+
114
+ | Profile | AGAL | Texture | RectangleTexture | rgbaHalfFloat | Colour outputs |
115
+ | --- | --- | --- | --- | --- | --- |
116
+ | `baselineConstrained` | 1 | 2048 | none (#3782) | no (#3759) | 1 |
117
+ | `baseline` | 1 | 2048 | 2048 | no | 1 |
118
+ | `baselineExtended` | 1 | 4096 | 4096 | no | 1 |
119
+ | `standardConstrained` | 1, 2 | 4096 | 4096 | yes | 1 |
120
+ | `standard` | 1, 2 | 4096 | 4096 | yes | 4 |
121
+ | `standardExtended` | 1, 2, 3 | 4096 | 4096 | yes | 4 |
122
+
123
+ What each AGAL version's programs may use (version 0 is 1; a version past the
124
+ profile's is #3725):
125
+
126
+ | | AGAL 1 | AGAL 2 | AGAL 3 |
127
+ | --- | --- | --- | --- |
128
+ | Tokens a program | 200 | 1024 | 2048 |
129
+ | `va` | 8 | 8 | 16 |
130
+ | `vc` / `fc` | 128 / 28 | 250 / 64 | 250 / 200 |
131
+ | `vt`, `ft` | 8 (7 in `baselineConstrained`) | 26 | 26 |
132
+ | `v` | 8 | 10 (8 in `standardConstrained`) | 10 |
133
+ | `fs` | 8 | 16 (8 in `standardConstrained`) | 16 |
134
+ | `oc` | 1 | 4 (1 in `standardConstrained`) | 4 |
135
+ | `od` | — | `od.x` (none in `standardConstrained`) | `od.x` |
136
+
137
+ AGAL 2 adds `ddx` and `ddy` (fragment programs, not in conditionals; `ddy` grows
138
+ down the target, as AIR's), and the conditionals `ife`, `ine`, `ifg` and `ifl`
139
+ (scalar operands, compared as `==`, `!=`, `>` and `<`), `els` and `eif`, at most
140
+ four deep. Both branches run for every pixel and only their writes are
141
+ predicated, as Direct3D's predication runs them, so derivatives stay defined:
142
+ nothing branches in GLSL. AIR's rules hold: no output written in a conditional
143
+ (#3751), no empty branch (#3748), a texture read in one takes a varying alone
144
+ (#3741), and after `eif` a temporary counts as written where the `els` branch
145
+ wrote it, or, with no `els`, where it was before the `if`. `od` writes the
146
+ depth, clamped by the depth buffer. AIR's indirect reads reach the first 128
147
+ vertex constants in every version and read 0 past them, so a program's bank
148
+ stays `vc[128]`, indexed as AGAL 1's is; constants past it are uniforms of their
149
+ own. Fragment programs have no indirect reads (#3639). AIR reads `iid` from
150
+ vertex stream 15. In every version `sne` compares, two constant operands are
151
+ refused (#3625, as are `kil`, `ddx` and `ddy` of a constant), each colour output
152
+ is written once (#3744) from `oc0` up without gaps (#3775), and samplers take
153
+ the four wraps and any format, which a draw then checks.
154
+
155
+ Colour outputs 1 to 3 (`setColorOutput`) draw beside the target: the player
156
+ binds them for `setRenderToTexture`'s `colorOutputIndex`, refuses them beside the
157
+ back buffer (#3728) or unlike the target in size, format, depth or antialiasing
158
+ (#3729), and a draw whose program writes another number of outputs (#3774).
159
+ `setRenderToBackBuffer` and `present` unbind them. The backend attaches them to
160
+ the target's framebuffer only while they are bound, so a target drawn alone
161
+ pays nothing.
162
+
163
+ Left out, and why:
164
+
165
+ - `drawTrianglesInstanced` and `createVertexBufferForInstances`, which AIR has
166
+ and Flash Player 32's playerglobal does not; `iid` reads stream 15 meanwhile.
167
+ - Colour outputs on an antialiased target (#3708): AIR takes them.
168
+ - The same texture bound to two outputs, which AIR draws into with the later one.
169
+ - `baselineConstrained` fragment programs are held to 96 instructions (#3715),
170
+ ps_2_0's 64 arithmetic and 32 texture ones, counted as AGAL's: AIR counts
171
+ Direct3D's, of which a matrix, `nrm` or a comparison takes several.
172
+ - A RectangleTexture as large as the back buffer where that is larger than the
173
+ profile's size, which AIR's message names but no test has checked.
174
+ - Conditionals in vertex programs: AIR's validation takes them, then under Wine
175
+ its Direct3D 9 compile fails (#3613), so no reference shows what they draw;
176
+ swf2es runs them as it runs a fragment program's.
86
177
 
87
178
  Core failures carry typed reasons. The Flash adapter maps them to catchable AS3
88
179
  errors, including resource limits (#3691), disposed objects (#3694), draw bounds
89
- and AGAL validation/linkage. Known unavailable modes or profiles report an
90
- asynchronous ErrorEvent #3702 so content can retry baseline. Concurrent requests
180
+ and AGAL validation/linkage. Every profile is served; the software render mode
181
+ reports an asynchronous ErrorEvent #3702 so content can retry. Concurrent requests
91
182
  coalesce; requesting again after creation retires the preceding context and
92
183
  creates a new one. Broader unchecked-error precedence remains experimental.
93
184
  The constructor rejects antialiased host contexts before allocating GPU handles:
@@ -129,10 +220,11 @@ not prompt or guaranteed; explicit disposal remains preferable, and the hard
129
220
  resource budgets still apply. Direct backend callers own their resources and
130
221
  must dispose them or the context.
131
222
 
132
- The current API and validation are experimental. Supported operations, AIR
223
+ Supported operations, AIR
133
224
  references, unsupported formats/profiles and lifecycle stress tests are tracked
134
- in [tests/context3d](../../tests/context3d/README.md). Stage3D playback remains off
135
- by default. A web host can explicitly opt in before loading its first player:
225
+ in [tests/context3d](../../tests/context3d/README.md). Stage3D playback is off by
226
+ default in the web element, and on in the desktop app, whose View menu turns it
227
+ off. A web host can explicitly opt in before loading its first player:
136
228
 
137
229
  ```ts
138
230
  import { configure } from "@swf2es/web";
@@ -163,8 +255,11 @@ configure({
163
255
  });
164
256
  ```
165
257
 
166
- Each requested slot needs a fresh surface. `configure({ stage3D: null })` disables
167
- the experiment for subsequent loads. The web element owns native installation,
258
+ Each requested slot needs a fresh surface. In place of the factory, `stage3D` takes
259
+ a loader, `{ load: () => import("./my-stage3d.js").then((m) => m.create) }`, which
260
+ the element calls at a SWF's first `requestContext3D`: a SWF that never asks loads
261
+ no backend, and one whose load fails gets #3702. `configure({ stage3D: null })` disables
262
+ Stage3D for subsequent loads. The web element owns native installation,
168
263
  composition, cancellation, restoration and teardown for each load. GPU backend
169
264
  selection stays with the host; the default web entry does not eagerly import
170
265
  the optional bindings or a backend. No new dependencies are required by `web`.
@@ -176,28 +271,26 @@ they are host policy, not AIR limits or a guarantee against context loss. Tune
176
271
  them for the workload and account for concurrent slots and players. The limits
177
272
  exclude driver overhead and back-buffer attachments, so the browser can still
178
273
  lose a context before a logical allocation limit is reached. The public demo
179
- keeps Stage3D off by default; its experimental checkbox opts in with these lower budgets.
274
+ keeps Stage3D off by default; its checkbox opts in with these lower budgets.
180
275
 
181
276
  Stage3D positions follow the embedding's `scale`/`salign` placement. Configured
182
277
  buffer sizes remain in pixels; resizing or changing device pixel ratio never
183
278
  implicitly reallocates them. The host clips the viewports, makes the display
184
279
  list transparent while contexts exist, and keeps overlapping players' canvases
185
280
  in separate stacks. The web host honors ActionScript changes to
186
- `Stage.scaleMode` and `Stage.align`, with Stage3D opted in or not; only the
187
- opt-in gives the top and left edges precedence when an alignment names both
281
+ `Stage.scaleMode` and `Stage.align`, with Stage3D configured or not; only with it configured do the top and left edges take precedence when an alignment names both
188
282
  opposite edges. In `noScale`, Stage dimensions follow the
189
283
  embedding's CSS size and resize events are synchronous after placement updates;
190
284
  other modes report the authored dimensions. Display-list pixels and input use
191
285
  the same viewport, including coordinates outside the authored rectangle.
192
286
  A DPR change affects display-list resolution without changing Stage dimensions
193
287
  or reallocating Stage3D buffers. Script settings override embedding defaults
194
- independently. The desktop app offers the same host through View › Stage3D
195
- (Experimental), off by default, with a remembered choice that restarts the
196
- movie when changed. It uses the backend's per-type resource count limits and
288
+ independently. The desktop app uses the same host, on by default; View › Stage3D turns it
289
+ off and on, with a remembered choice that restarts the movie when changed. It uses the backend's per-type resource count limits and
197
290
  byte budgets. The public demo lazily loads the backend when Stage3D is selected
198
291
  and restarts the current SWF when the option changes. Its Restart and Close
199
- controls release the preceding contexts. Best-resolution buffers remain later
200
- work. None of this changes the ActionScript Worker API.
292
+ controls release the preceding contexts. `wantsBestResolution` back buffers are drawn at the screen's pixels
293
+ (see tests/context3d). None of this changes the ActionScript Worker API.
201
294
 
202
295
  A future WebGPU backend can reuse the Flash adapter, resource contracts and AIR
203
296
  fixtures. It still needs AGAL-to-WGSL translation, GPU resource/binding handling,
@@ -209,7 +302,7 @@ Flash execution would need validation before full compatibility could be claimed
209
302
 
210
303
  The display list and Stage3D use separate canvases. Display-list blend effects
211
304
  sample the transparent 2D back buffer rather than Stage3D color, so blending
212
- across those layers is an experimental limitation. `Playback.destroy()` disposes
305
+ across those layers is a known limitation. `Playback.destroy()` disposes
213
306
  the display-list scene before the renderer on ordinary loads as well as Stage3D
214
307
  loads; this intentional shared cleanup releases cached text-style listeners.
215
308
 
package/dist/agal.d.ts CHANGED
@@ -1,10 +1,12 @@
1
+ import { type Profile } from "./backend.js";
1
2
  export type ProgramType = "vertex" | "fragment";
2
3
  export interface SamplerSource {
3
4
  index: number;
4
5
  /** What the sampler reads: 0 RGBA, 1 DXT1 ("compressed"), 2 DXT5 ("compressedAlpha"). */
5
6
  format: number;
6
7
  filter: number;
7
- repeat: boolean;
8
+ /** AGAL's wrap: 0 clamp, 1 repeat, 2 clamp_u_repeat_v, 3 repeat_u_clamp_v. */
9
+ wrap: number;
8
10
  mip: number;
9
11
  cube: boolean;
10
12
  ignore: boolean;
@@ -18,6 +20,13 @@ export interface ShaderSource {
18
20
  constants: number[];
19
21
  indirect: boolean;
20
22
  samplers: SamplerSource[];
23
+ /** Colour outputs a fragment program writes, oc0 up: 1 to 4. */
24
+ outputs: number;
21
25
  }
22
- export declare function translate(bytes: Uint8Array, stage: ProgramType): ShaderSource;
26
+ /**
27
+ * The vertex constants an indirect read reaches: AIR's reach the first 128 in AGAL 2 and 3
28
+ * too, and read 0 past them; the rest only direct reads reach.
29
+ */
30
+ export declare const INDIRECT_BANK = 128;
31
+ export declare function translate(bytes: Uint8Array, stage: ProgramType, profile?: Profile): ShaderSource;
23
32
  //# sourceMappingURL=agal.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"agal.d.ts","sourceRoot":"","sources":["../src/agal.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,aAAa,EAAE,CAAC;CAC3B;AAQD,wBAAgB,SAAS,CAAC,KAAK,EAAE,UAAU,EAAE,KAAK,EAAE,WAAW,GAAG,YAAY,CA4c7E"}
1
+ {"version":3,"file":"agal.d.ts","sourceRoot":"","sources":["../src/agal.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,OAAO,EAAmC,MAAM,cAAc,CAAC;AAG7E,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,yFAAyF;IACzF,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,2EAA2E;IAC3E,QAAQ,EAAE,UAAU,CAAC;IACrB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,gEAAgE;IAChE,OAAO,EAAE,MAAM,CAAC;CACjB;AAsDD;;;GAGG;AACH,eAAO,MAAM,aAAa,MAAM,CAAC;AAiBjC,wBAAgB,SAAS,CACvB,KAAK,EAAE,UAAU,EACjB,KAAK,EAAE,WAAW,EAClB,OAAO,GAAE,OAAoB,GAC5B,YAAY,CAqsBd"}