@babylonjs/lite-gl 1.11.0 → 1.12.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.
package/context.js CHANGED
@@ -300,6 +300,7 @@ function handleContextRestored(engine) {
300
300
  if (newHandle !== null) {
301
301
  tex.handle = newHandle;
302
302
  tex._upload(engine);
303
+ tex._initializeParameters?.(engine);
303
304
  tex.isReady = tex._wasReady;
304
305
  }
305
306
  }
package/context.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,iBAAiB,EAAgB,MAAM,YAAY,CAAC;AAyM1F;;;uCAGuC;AACvC,MAAM,UAAU,cAAc,CAAC,MAA2C,EAAE,OAAyB;IACjG,MAAM,CAAC,GAAG,OAAO,IAAI,EAAE,CAAC;IACxB,MAAM,KAAK,GAA2B;QAClC,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;QACtB,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,IAAI,IAAI;QAChD,SAAS,EAAE,CAAC,CAAC,SAAS,IAAI,KAAK;QAC/B,qBAAqB,EAAE,CAAC,CAAC,qBAAqB,IAAI,KAAK;QACvD,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,KAAK;QACvB,OAAO,EAAE,CAAC,CAAC,OAAO,IAAI,KAAK;QAC3B,eAAe,EAAE,CAAC,CAAC,eAAe,IAAI,SAAS;QAC/C,4BAA4B,EAAE,CAAC,CAAC,4BAA4B,IAAI,KAAK;KACxE,CAAC;IACF,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,KAAK,CAAkC,CAAC;IAC/E,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;QACd,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,EAAE,CAAC,CAAC;IAE3B,MAAM,MAAM,GAAoB;QAC5B,MAAM;QACN,EAAE;QACF,IAAI;QACJ,IAAI,EAAE,CAAC;QACP,MAAM,EAAE,CAAC;QACT,MAAM,EAAE,EAAE;QACV,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC;QAC3C,QAAQ,EAAE,EAAE;QACZ,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,SAAS,EAAE,EAAE;QACb,cAAc,EAAE,EAAE;QAClB,oBAAoB,EAAE,IAAI;QAC1B,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,EAAE;QACX,WAAW,EAAE,EAAE;QACf,OAAO,EAAE,KAAK;QACd,SAAS,EAAE,KAAK;QAChB,YAAY,EAAE,GAAG,EAAE,GAAE,CAAC;QACtB,gBAAgB,EAAE,GAAG,EAAE,GAAE,CAAC;QAC1B,cAAc,EAAE,KAAK;QACrB,cAAc,EAAE,IAAI;KACvB,CAAC;IAEF,MAAM,CAAC,YAAY,GAAG,CAAC,CAAQ,EAAE,EAAE,CAAC,iBAAiB,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACjE,MAAM,CAAC,gBAAgB,GAAG,GAAG,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM,CAAC,YAA6B,EAAE,KAAK,CAAC,CAAC;IACzF,MAAM,CAAC,gBAAgB,CAAC,sBAAsB,EAAE,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAEhF,OAAO,MAAM,CAAC;AAClB,CAAC;AAED;;sBAEsB;AACtB,MAAM,UAAU,eAAe,CAAC,MAAuB;IACnD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IACD,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC;IACxB,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACzB,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,MAAM,CAAC,YAA6B,EAAE,KAAK,CAAC,CAAC;IACnG,MAAM,CAAC,MAAM,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,MAAM,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAE1F,MAAM,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;IACrB,oEAAoE;IACpE,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;YACrB,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;YACpB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YAC9B,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC7B,CAAC;IACL,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAC3B,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;IAC1C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;YACrB,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACjC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC;IAC5B,6EAA6E;IAC7E,6EAA6E;IAC7E,MAAM,GAAG,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;IAC1C,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC;YAChB,EAAE,CAAC,SAAS,GAAG,IAAI,CAAC;YACpB,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACtB,CAAC;IACL,CAAC;IACD,MAAM,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC;IAEjC,2EAA2E;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;IACxC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,GAAG,CAAC,SAAS,GAAG,IAAI,CAAC;YACrB,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACvB,CAAC;IACL,CAAC;IACD,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;IAE3B,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACnC,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1B,MAAM,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,MAAM,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AAC9C,CAAC;AAED;iFACiF;AACjF,MAAM,UAAU,cAAc,CAAC,MAAuB;IAClD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,+EAA+E;IAC/E,gFAAgF;IAChF,IAAI,CAAC,CAAC,aAAa,IAAI,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO;IACX,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,WAAW,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5E,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7E,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe,CAAC,MAAuB,EAAE,KAAa,EAAE,MAAc;IAClF,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IACxD,IAAI,MAAM,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACrB,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAuB;IACpD,IAAI,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IACD,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IACjC,MAAM,YAAY,GAAG,MAAM,CAAC,uBAAuB,CAAC;IACpD,IAAI,YAAY,EAAE,CAAC;QACf,KAAK,MAAM,UAAU,IAAI,YAAY,EAAE,CAAC;YACpC,UAAU,EAAE,CAAC;QACjB,CAAC;IACL,CAAC;AACL,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,cAAc,CAAC,MAAuB;IAClD,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC;AAC/B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,eAAe,CAAC,MAAuB;IACnD,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;AAChC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,uBAAuB,CAAC,MAAuB;IAC3D,OAAO,MAAM,CAAC,IAAI,CAAC;AACvB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,uBAAuB,CAAC,MAAuB,EAAE,KAAa;IAC1E,IAAI,KAAK,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACjC,OAAO;IACX,CAAC;IACD,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;IACpB,cAAc,CAAC,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED;gCACgC;AAChC,MAAM,UAAU,kBAAkB,CAAC,MAAuB;IACtD,OAAO,MAAM,CAAC,MAAM,CAAC;AACzB,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,aAAa,CAAC,MAAuB,EAAE,EAAc;IACjE,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACpC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;AACL,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,cAAc,CAAC,MAAuB,EAAE,EAAc;IAClE,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,CAAC;AACL,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,iBAAiB,CAAC,MAAuB,EAAE,EAAc;IACrE,IAAI,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACxC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;AACL,CAAC;AAED,gEAAgE;AAChE,MAAM,UAAU,kBAAkB,CAAC,MAAuB,EAAE,EAAc;IACtE,MAAM,CAAC,GAAG,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC;QACX,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACpC,CAAC;AACL,CAAC;AAED,gFAAgF;AAEhF,SAAS,iBAAiB,CAAC,MAAuB,EAAE,CAAQ;IACxD,wEAAwE;IACxE,8BAA8B;IAC9B,CAAC,CAAC,cAAc,EAAE,CAAC;IACnB,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACrC,OAAO;IACX,CAAC;IACD,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IACtB,2EAA2E;IAC3E,qEAAqE;IACrE,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACjD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACtB,oBAAoB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACpC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC;IACtB,CAAC;IACD,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC;IACnC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;QACpB,GAAG,CAAC,iBAAiB,GAAG,KAAK,CAAC;QAC9B,GAAG,CAAC,gBAAgB,GAAG,EAAE,CAAC;QAC1B,GAAG,CAAC,kBAAkB,GAAG,EAAE,CAAC;QAC5B,iEAAiE;QACjE,iDAAiD;QACjD,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC1B,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACzB,mEAAmE;IACvE,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACjC,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC;QAC5B,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC;IACxB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;IACnC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC;YACD,EAAE,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,gCAAgC,EAAE,GAAG,CAAC,CAAC;QACzD,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,qBAAqB,CAAC,MAAuB;IAClD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO;IACX,CAAC;IACD,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IACjD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QACjC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,SAAS,GAAG,MAAM,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC;YAC5C,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;gBACrB,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC;gBACvB,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;gBACpB,GAAG,CAAC,OAAO,GAAG,GAAG,CAAC,SAAS,CAAC;YAChC,CAAC;QACL,CAAC;IACL,CAAC;IACD,wEAAwE;IACxE,6EAA6E;IAC7E,6EAA6E;IAC7E,gEAAgE;IAChE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;IACvB,4EAA4E;IAC5E,6EAA6E;IAC7E,qCAAqC;IACrC,KAAK,MAAM,EAAE,IAAI,MAAM,CAAC,cAAc,EAAE,CAAC;QACrC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC;YAChB,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACL,CAAC;IACD,wEAAwE;IACxE,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC;YACjB,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;IACL,CAAC;IACD,IAAI,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,cAAc,KAAK,IAAI,EAAE,CAAC;QACtF,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC;IAClC,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;IACvC,KAAK,MAAM,EAAE,IAAI,GAAG,EAAE,CAAC;QACnB,IAAI,CAAC;YACD,EAAE,EAAE,CAAC;QACT,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,CAAC,KAAK,CAAC,oCAAoC,EAAE,GAAG,CAAC,CAAC;QAC7D,CAAC;IACL,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,EAA0B;IACzC,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,6BAA6B,CAA6C,CAAC;IAC/G,2EAA2E;IAC3E,wEAAwE;IACxE,MAAM,gBAAgB,GAAG,EAAE,CAAC,YAAY,CAAC,wBAAwB,CAAC,KAAK,IAAI,CAAC;IAC5E,MAAM,oBAAoB,GAAG,EAAE,CAAC,YAAY,CAAC,6BAA6B,CAAC,KAAK,IAAI,CAAC;IACrF,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,0BAA0B,CAAC,KAAK,IAAI,CAAC;IACzE,OAAO;QACH,cAAc,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,gBAAgB,CAAW;QAC9D,eAAe,EAAE,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,gCAAgC,CAAW;QAC/E,qBAAqB,EAAE,WAAW;QAClC,kBAAkB,EAAE,gBAAgB;QACpC,2BAA2B,EAAE,WAAW;QACxC,sBAAsB,EAAE,gBAAgB,IAAI,oBAAoB;QAChE,+BAA+B,EAAE,IAAI;QACrC,eAAe,EAAE,KAAK;KACzB,CAAC;AACN,CAAC;AAED,SAAS,WAAW,CAAC,CAA2B;IAC5C,KAAK,MAAM,GAAG,IAAI,CAAC,EAAE,CAAC;QAClB,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC;IAClB,CAAC;AACL,CAAC","sourcesContent":["import type { GLEffect } from \"./effect.js\";\nimport type { GLTexture } from \"./texture.js\";\nimport type { GLRenderTarget } from \"./render-target.js\";\nimport { createGLState, resetGLState, resetGLStateCache, type GLState } from \"./state.js\";\n\n/**\n * Minimal shape of a context-restorable GL buffer (vertex / index), kept local\n * to this module so the public `GLEngineContext` type carries no dependency on\n * the tree-shakeable `mesh` entry. `mesh.ts`'s `GLVertexBuffer` /\n * `GLIndexBuffer` satisfy it structurally.\n * @internal\n */\nexport interface GLManagedBuffer {\n handle: WebGLBuffer;\n /** @internal */\n _disposed: boolean;\n /** @internal */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/** Constructor options forwarded to `canvas.getContext('webgl2', …)`. */\nexport interface GLEngineOptions {\n /** Default: true. */\n alpha?: boolean;\n /** Default: true. */\n premultipliedAlpha?: boolean;\n /** Default: false. */\n antialias?: boolean;\n /** Default: false. */\n preserveDrawingBuffer?: boolean;\n /** Default: false — disabled for fullscreen-quad workloads. */\n depth?: boolean;\n /** Default: false. */\n stencil?: boolean;\n /** Default: \"default\". */\n powerPreference?: WebGLPowerPreference;\n /** Default: false. */\n failIfMajorPerformanceCaveat?: boolean;\n}\n\n/** Read-only WebGL2 capability limits, queried at creation and refreshed after\n * context restoration because extension objects do not survive context loss. */\nexport interface GLEngineCaps {\n /** `gl.MAX_TEXTURE_SIZE` — largest supported texture dimension, in texels. */\n readonly maxTextureSize: number;\n /** `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` — number of sampler binding slots. */\n readonly maxTextureUnits: number;\n /** The `KHR_parallel_shader_compile` extension used for async link polling,\n * or null when unsupported — linking is then treated as synchronous. */\n readonly parallelShaderCompile: { COMPLETION_STATUS_KHR: number } | null;\n /** True when 32-bit float color attachments are renderable\n * (`EXT_color_buffer_float`). Mirrors Babylon's `caps.textureFloatRender`. */\n readonly textureFloatRender: boolean;\n /** True when 32-bit float textures support linear filtering\n * (`OES_texture_float_linear`). Mirrors `caps.textureFloatLinearFiltering`. */\n readonly textureFloatLinearFiltering: boolean;\n /** True when 16-bit half-float color attachments are renderable\n * (`EXT_color_buffer_float` or `EXT_color_buffer_half_float`). Mirrors\n * `caps.textureHalfFloatRender`. */\n readonly textureHalfFloatRender: boolean;\n /** Half-float linear filtering — always `true` in WebGL2 (it is core).\n * Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */\n readonly textureHalfFloatLinearFiltering: boolean;\n /** Whether non-power-of-two textures need POT dimensions for mips / wrap.\n * Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */\n readonly needPOTTextures: boolean;\n}\n\n/**\n * Pure-state handle for a WebGL2 canvas + its cached GL state.\n *\n * INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.\n * Doing so silently corrupts the cache in `_state`. The package owns every\n * GL call. (`engine.gl` is exposed only so downstream code that already has the\n * pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT\n * call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)\n */\nexport interface GLEngineContext {\n /** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is\n * supported for worker render paths (e.g. the Lottie player); it has no CSS\n * box, so it must be sized explicitly via `setGLEngineSize` rather than the\n * CSS-derived `resizeGLEngine`. */\n readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n /** The raw WebGL2 context. Do NOT mutate GL state through it — see the\n * type-level invariant above; the package owns every state-changing call. */\n readonly gl: WebGL2RenderingContext;\n /** Queried capability limits for this context. */\n readonly caps: GLEngineCaps;\n /**\n * Hardware-scaling-level — drawingBufferWidth = clientWidth * dpr / _hsl.\n * @internal\n */\n _hsl: number;\n /**\n * rAF id when a render loop is active, 0 otherwise.\n * @internal\n */\n _rafId: number;\n /**\n * Per-frame callbacks. `runRenderLoop` is a no-op if `fn` is already\n * registered (matches Babylon `AbstractEngine.runRenderLoop`).\n * @internal\n */\n _loops: ((dt: number) => void)[];\n /**\n * Timestamp of last frame for delta computation.\n * @internal\n */\n _prevNow: number;\n /**\n * Cached GL state. See §4 of 00-lite-gl.md.\n * @internal\n */\n _state: GLState;\n /**\n * Live effect registry — populated by `createEffect`, removed by\n * `disposeEffect`. Used by the context-restored protocol to rebuild\n * programs.\n * @internal\n */\n _effects: GLEffect[];\n /**\n * Per-engine effect cache keyed by source descriptor (vertex+fragment\n * source, defines, attribute/uniform/sampler names). `createEffect` returns\n * (and ref-counts) the cached `GLEffect` when an identical descriptor is\n * requested, so identical shaders share ONE WebGLProgram — letting\n * `useEffect`'s current-program cache elide redundant `gl.useProgram`.\n * @internal\n */\n _effectCache: Map<string, GLEffect>;\n /**\n * Live texture registry — populated by `createRawTexture` /\n * `loadTexture2D` / `createHtmlElementTexture`. Used by the\n * context-restored protocol to replay uploads.\n * @internal\n */\n _textures: GLTexture[];\n /**\n * Live render-target registry — populated by `createRenderTarget`. Used by\n * the context-restored protocol to rebuild framebuffers + attachments after\n * their color textures have been replayed. Empty (and tree-shaken) when the\n * render-target module is unused.\n * @internal\n */\n _renderTargets: GLRenderTarget[];\n /**\n * The render target currently bound for drawing (`bindRenderTarget`), or\n * `null` for the default canvas framebuffer. Tracked so that leaving a\n * mipmapped target (`bindRenderTarget(engine, null)` or switching to\n * another target) can regenerate its mip chain — mirroring Babylon's\n * auto-mipmap on `unBindFramebuffer`. Reset to `null` on context-lost.\n * @internal\n */\n _currentRenderTarget: GLRenderTarget | null;\n /**\n * Live vertex / index buffer registry — populated by `createVertexBuffer` /\n * `createIndexBuffer`. Used by the context-restored protocol to re-upload\n * the retained CPU data into fresh GL buffers. Empty (and tree-shaken) when\n * the mesh module is unused.\n * @internal\n */\n _buffers: GLManagedBuffer[];\n /** @internal */\n _onLost: (() => void)[];\n /** @internal */\n _onRestored: (() => void)[];\n /**\n * True between `webglcontextlost` and `webglcontextrestored`. While\n * true, every `setEffect*` / `bindTexture` / `drawEffect` is a no-op.\n * @internal\n */\n _isLost: boolean;\n /**\n * True once the context has been disposed; subsequent calls become no-ops.\n * @internal\n */\n _disposed: boolean;\n /**\n * DOM handlers — retained so dispose can `removeEventListener` them.\n * @internal\n */\n _lostHandler: (e: Event) => void;\n /** @internal */\n _restoredHandler: () => void;\n /**\n * True when a render loop was active at the moment of `webglcontextlost`,\n * so we can resume it from the restored handler.\n * @internal\n */\n _wasLoopActive: boolean;\n /**\n * Installed by `runRenderLoop` on first call. Lets the context-restored\n * handler resume a loop without a circular runtime import from render-loop.\n * Null if the render-loop module is tree-shaken out.\n * @internal\n */\n _scheduleFrame: ((engine: GLEngineContext) => void) | null;\n /** Optional feature-owned state-cache invalidators. Allocated lazily by the first feature that needs one.\n * @internal */\n _stateCacheInvalidators?: (() => void)[];\n}\n\n/** Acquire a WebGL2 context on the canvas and build the pure-state handle.\n * Accepts an `HTMLCanvasElement` or an `OffscreenCanvas` (worker render paths —\n * e.g. the Lottie player — which size the drawing buffer via `setGLEngineSize`).\n * Throws if WebGL2 is unsupported. */\nexport function createGLEngine(canvas: HTMLCanvasElement | OffscreenCanvas, options?: GLEngineOptions): GLEngineContext {\n const o = options ?? {};\n const attrs: WebGLContextAttributes = {\n alpha: o.alpha ?? true,\n premultipliedAlpha: o.premultipliedAlpha ?? true,\n antialias: o.antialias ?? false,\n preserveDrawingBuffer: o.preserveDrawingBuffer ?? false,\n depth: o.depth ?? false,\n stencil: o.stencil ?? false,\n powerPreference: o.powerPreference ?? \"default\",\n failIfMajorPerformanceCaveat: o.failIfMajorPerformanceCaveat ?? false,\n };\n const gl = canvas.getContext(\"webgl2\", attrs) as WebGL2RenderingContext | null;\n if (gl === null) {\n throw new Error(\"lite-gl: WebGL2 is not supported on this canvas\");\n }\n\n const caps = queryCaps(gl);\n\n const engine: GLEngineContext = {\n canvas,\n gl,\n caps,\n _hsl: 1,\n _rafId: 0,\n _loops: [],\n _prevNow: 0,\n _state: createGLState(caps.maxTextureUnits),\n _effects: [],\n _effectCache: new Map(),\n _textures: [],\n _renderTargets: [],\n _currentRenderTarget: null,\n _buffers: [],\n _onLost: [],\n _onRestored: [],\n _isLost: false,\n _disposed: false,\n _lostHandler: () => {},\n _restoredHandler: () => {},\n _wasLoopActive: false,\n _scheduleFrame: null,\n };\n\n engine._lostHandler = (e: Event) => handleContextLost(engine, e);\n engine._restoredHandler = () => handleContextRestored(engine);\n canvas.addEventListener(\"webglcontextlost\", engine._lostHandler as EventListener, false);\n canvas.addEventListener(\"webglcontextrestored\", engine._restoredHandler, false);\n\n return engine;\n}\n\n/** Stops the render loop, removes DOM listeners, releases all known effects\n * and textures, then marks the context disposed. The browser-owned canvas\n * is left intact. */\nexport function disposeGLEngine(engine: GLEngineContext): void {\n if (engine._disposed) {\n return;\n }\n engine._disposed = true;\n if (engine._rafId !== 0) {\n cancelAnimationFrame(engine._rafId);\n engine._rafId = 0;\n }\n engine._loops.length = 0;\n engine.canvas.removeEventListener(\"webglcontextlost\", engine._lostHandler as EventListener, false);\n engine.canvas.removeEventListener(\"webglcontextrestored\", engine._restoredHandler, false);\n\n const gl = engine.gl;\n // Iterate snapshots — the dispose paths splice into the registries.\n const effects = engine._effects.slice();\n for (const eff of effects) {\n if (!eff._disposed) {\n eff._disposed = true;\n eff.isReady = false;\n gl.deleteProgram(eff.program);\n gl.deleteShader(eff._vs);\n gl.deleteShader(eff._fs);\n }\n }\n engine._effects.length = 0;\n engine._effectCache.clear();\n const textures = engine._textures.slice();\n for (const tex of textures) {\n if (!tex._disposed) {\n tex._disposed = true;\n gl.deleteTexture(tex.handle);\n }\n }\n engine._textures.length = 0;\n // Render targets own their FBO + renderbuffer + color texture; free them via\n // the per-RT closure so context.ts needs no runtime import of render-target.\n const rts = engine._renderTargets.slice();\n for (const rt of rts) {\n if (!rt._disposed) {\n rt._disposed = true;\n rt._deleteGpu(gl);\n }\n }\n engine._renderTargets.length = 0;\n\n // Mesh vertex/index buffers own a single GL buffer each; free via closure.\n const buffers = engine._buffers.slice();\n for (const buf of buffers) {\n if (!buf._disposed) {\n buf._disposed = true;\n buf._deleteGpu(gl);\n }\n }\n engine._buffers.length = 0;\n\n resetGLState(engine._state);\n engine._currentRenderTarget = null;\n engine._onLost.length = 0;\n engine._onRestored.length = 0;\n engine._stateCacheInvalidators?.splice(0);\n}\n\n/** Match drawing-buffer size to (clientSize × devicePixelRatio / _hsl). No-op\n * if size already matches. Never touches viewport — `setViewport` owns that. */\nexport function resizeGLEngine(engine: GLEngineContext): void {\n if (engine._disposed || engine._isLost) {\n return;\n }\n const canvas = engine.canvas;\n // An OffscreenCanvas has no CSS box (no clientWidth/clientHeight); it is sized\n // explicitly via setGLEngineSize, so CSS-derived auto-resize is a no-op for it.\n if (!(\"clientWidth\" in canvas)) {\n return;\n }\n const dpr = typeof devicePixelRatio === \"number\" ? devicePixelRatio : 1;\n const w = Math.max(1, Math.floor((canvas.clientWidth * dpr) / engine._hsl));\n const h = Math.max(1, Math.floor((canvas.clientHeight * dpr) / engine._hsl));\n if (canvas.width !== w) {\n canvas.width = w;\n }\n if (canvas.height !== h) {\n canvas.height = h;\n }\n}\n\n/**\n * Set the drawing-buffer size to an EXPLICIT width/height in physical pixels\n * (each divided by `_hsl`), independent of the canvas client/CSS size — the\n * counterpart of Babylon's `ThinEngine.setSize`. Use when the render resolution\n * is computed directly (e.g. animation dimensions × scale × dpr) rather than\n * derived from CSS layout via {@link resizeGLEngine}. No-op on a disposed\n * engine. Never touches the viewport — `setViewport` owns that.\n *\n * @param engine - The engine to resize.\n * @param width - Target drawing-buffer width in physical pixels.\n * @param height - Target drawing-buffer height in physical pixels.\n */\nexport function setGLEngineSize(engine: GLEngineContext, width: number, height: number): void {\n if (engine._disposed) {\n return;\n }\n const canvas = engine.canvas;\n const w = Math.max(1, Math.floor(width / engine._hsl));\n const h = Math.max(1, Math.floor(height / engine._hsl));\n if (canvas.width !== w) {\n canvas.width = w;\n }\n if (canvas.height !== h) {\n canvas.height = h;\n }\n}\n\n/**\n * Invalidate lite-gl's cached GL state so the next state-setting call in each\n * category (program / buffer / texture / VAO / framebuffer bindings, blend,\n * depth, stencil, scissor, color-mask, viewport, unpack) is re-issued instead\n * of elided.\n *\n * Use this when a host application that SHARES this WebGL2 context mutates raw\n * `gl.*` state outside lite-gl — e.g. a save/restore wrapper that resets the\n * context to GL defaults around each render scope, or any interop layer that\n * issues GL calls directly. Without it, lite-gl's redundant-call elision would\n * skip the state changes needed to re-establish the scope, producing corrupted\n * output. Owned GPU resources (the shared quad, render targets, meshes,\n * effects, textures) are preserved — only the cached \"current GL state\" is\n * reset. Mirrors Babylon's `Engine.wipeCaches()`.\n *\n * No-op while the context is lost or the engine is disposed.\n */\nexport function wipeGLStateCache(engine: GLEngineContext): void {\n if (engine._disposed || engine._isLost) {\n return;\n }\n resetGLStateCache(engine._state);\n const invalidators = engine._stateCacheInvalidators;\n if (invalidators) {\n for (const invalidate of invalidators) {\n invalidate();\n }\n }\n}\n\n/** Drawing-buffer width in physical pixels (`canvas.width`). */\nexport function getRenderWidth(engine: GLEngineContext): number {\n return engine.canvas.width;\n}\n\n/** Drawing-buffer height in physical pixels (`canvas.height`). */\nexport function getRenderHeight(engine: GLEngineContext): number {\n return engine.canvas.height;\n}\n\n/** Current hardware-scaling factor — drawing-buffer = clientSize × dpr / level. */\nexport function getHardwareScalingLevel(engine: GLEngineContext): number {\n return engine._hsl;\n}\n\n/** Updates the hardware-scaling factor and triggers a resize. */\nexport function setHardwareScalingLevel(engine: GLEngineContext, level: number): void {\n if (level <= 0 || !isFinite(level)) {\n return;\n }\n engine._hsl = level;\n resizeGLEngine(engine);\n}\n\n/** The backing canvas element (an `HTMLCanvasElement`, or an `OffscreenCanvas`\n * for worker render paths). */\nexport function getRenderingCanvas(engine: GLEngineContext): HTMLCanvasElement | OffscreenCanvas {\n return engine.canvas;\n}\n\n/** Register a `webglcontextlost` callback. Duplicate registrations are ignored. */\nexport function onContextLost(engine: GLEngineContext, cb: () => void): void {\n if (engine._onLost.indexOf(cb) === -1) {\n engine._onLost.push(cb);\n }\n}\n\n/** Remove a previously-registered context-lost callback. */\nexport function offContextLost(engine: GLEngineContext, cb: () => void): void {\n const i = engine._onLost.indexOf(cb);\n if (i !== -1) {\n engine._onLost.splice(i, 1);\n }\n}\n\n/** Register a `webglcontextrestored` callback. Duplicate registrations are ignored. */\nexport function onContextRestored(engine: GLEngineContext, cb: () => void): void {\n if (engine._onRestored.indexOf(cb) === -1) {\n engine._onRestored.push(cb);\n }\n}\n\n/** Remove a previously-registered context-restored callback. */\nexport function offContextRestored(engine: GLEngineContext, cb: () => void): void {\n const i = engine._onRestored.indexOf(cb);\n if (i !== -1) {\n engine._onRestored.splice(i, 1);\n }\n}\n\n/* ───────────────────────── internal: loss / restore ───────────────────── */\n\nfunction handleContextLost(engine: GLEngineContext, e: Event): void {\n // Opt-in to restore. Without preventDefault() the browser will NOT fire\n // webglcontextrestored later.\n e.preventDefault();\n if (engine._isLost || engine._disposed) {\n return;\n }\n engine._isLost = true;\n // `tick` clears `_rafId` while callbacks run, so a loss event delivered in\n // that window still represents an active loop when callbacks remain.\n engine._wasLoopActive = engine._loops.length > 0;\n if (engine._rafId !== 0) {\n cancelAnimationFrame(engine._rafId);\n engine._rafId = 0;\n }\n resetGLState(engine._state);\n engine._currentRenderTarget = null;\n for (const eff of engine._effects) {\n eff.isReady = false;\n eff._samplersAssigned = false;\n eff.uniformLocations = {};\n eff.attributeLocations = {};\n // Clear value caches so the first frame after restore re-uploads\n // every uniform into the freshly-linked program.\n clearObject(eff._lastF1);\n clearObject(eff._lastVec);\n clearObject(eff._lastI1);\n // Do NOT gl.deleteProgram — handle is already dead per WebGL spec.\n }\n for (const tex of engine._textures) {\n tex._wasReady = tex.isReady;\n tex.isReady = false;\n }\n const cbs = engine._onLost.slice();\n for (const cb of cbs) {\n try {\n cb();\n } catch (err) {\n console.error(\"lite-gl: onLost callback threw\", err);\n }\n }\n}\n\nfunction handleContextRestored(engine: GLEngineContext): void {\n if (engine._disposed) {\n return;\n }\n Object.assign(engine.caps, queryCaps(engine.gl));\n for (const eff of engine._effects) {\n if (!eff._disposed) {\n eff._restore(engine);\n }\n }\n for (const tex of engine._textures) {\n if (!tex._disposed) {\n const newHandle = engine.gl.createTexture();\n if (newHandle !== null) {\n tex.handle = newHandle;\n tex._upload(engine);\n tex.isReady = tex._wasReady;\n }\n }\n }\n // Clear the lost flag BEFORE the render-target / buffer rebuilds: their\n // `_restore` closures route through the same guarded build/upload paths used\n // at create time (which no-op while `_isLost`), whereas the effect / texture\n // replay above is unguarded and unaffected by the flag's value.\n engine._isLost = false;\n // Render targets rebuild their own color texture + FBO + renderbuffer AFTER\n // the standalone texture replay above (an RT's color texture is owned by the\n // RT, not the `_textures` registry).\n for (const rt of engine._renderTargets) {\n if (!rt._disposed) {\n rt._restore(engine);\n }\n }\n // Mesh buffers re-upload their retained CPU data into fresh GL buffers.\n for (const buf of engine._buffers) {\n if (!buf._disposed) {\n buf._restore(engine);\n }\n }\n if (engine._wasLoopActive && engine._loops.length > 0 && engine._scheduleFrame !== null) {\n engine._scheduleFrame(engine);\n }\n const cbs = engine._onRestored.slice();\n for (const cb of cbs) {\n try {\n cb();\n } catch (err) {\n console.error(\"lite-gl: onRestored callback threw\", err);\n }\n }\n}\n\nfunction queryCaps(gl: WebGL2RenderingContext): GLEngineCaps {\n const parallelExt = gl.getExtension(\"KHR_parallel_shader_compile\") as { COMPLETION_STATUS_KHR: number } | null;\n // `getExtension` both queries and enables these capabilities, so they must\n // be reacquired after context restoration before resources are rebuilt.\n const colorBufferFloat = gl.getExtension(\"EXT_color_buffer_float\") !== null;\n const colorBufferHalfFloat = gl.getExtension(\"EXT_color_buffer_half_float\") !== null;\n const floatLinear = gl.getExtension(\"OES_texture_float_linear\") !== null;\n return {\n maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE) as number,\n maxTextureUnits: gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS) as number,\n parallelShaderCompile: parallelExt,\n textureFloatRender: colorBufferFloat,\n textureFloatLinearFiltering: floatLinear,\n textureHalfFloatRender: colorBufferFloat || colorBufferHalfFloat,\n textureHalfFloatLinearFiltering: true,\n needPOTTextures: false,\n };\n}\n\nfunction clearObject(o: { [k: string]: unknown }): void {\n for (const key in o) {\n delete o[key];\n }\n}\n"]}
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GLEffect } from \"./effect.js\";\nimport type { GLTexture } from \"./texture.js\";\nimport type { GLRenderTarget } from \"./render-target.js\";\nimport { createGLState, resetGLState, resetGLStateCache, type GLState } from \"./state.js\";\n\n/**\n * Minimal shape of a context-restorable GL buffer (vertex / index), kept local\n * to this module so the public `GLEngineContext` type carries no dependency on\n * the tree-shakeable `mesh` entry. `mesh.ts`'s `GLVertexBuffer` /\n * `GLIndexBuffer` satisfy it structurally.\n * @internal\n */\nexport interface GLManagedBuffer {\n handle: WebGLBuffer;\n /** @internal */\n _disposed: boolean;\n /** @internal */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/** Constructor options forwarded to `canvas.getContext('webgl2', …)`. */\nexport interface GLEngineOptions {\n /** Default: true. */\n alpha?: boolean;\n /** Default: true. */\n premultipliedAlpha?: boolean;\n /** Default: false. */\n antialias?: boolean;\n /** Default: false. */\n preserveDrawingBuffer?: boolean;\n /** Default: false — disabled for fullscreen-quad workloads. */\n depth?: boolean;\n /** Default: false. */\n stencil?: boolean;\n /** Default: \"default\". */\n powerPreference?: WebGLPowerPreference;\n /** Default: false. */\n failIfMajorPerformanceCaveat?: boolean;\n}\n\n/** Read-only WebGL2 capability limits, queried at creation and refreshed after\n * context restoration because extension objects do not survive context loss. */\nexport interface GLEngineCaps {\n /** `gl.MAX_TEXTURE_SIZE` — largest supported texture dimension, in texels. */\n readonly maxTextureSize: number;\n /** `gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS` — number of sampler binding slots. */\n readonly maxTextureUnits: number;\n /** The `KHR_parallel_shader_compile` extension used for async link polling,\n * or null when unsupported — linking is then treated as synchronous. */\n readonly parallelShaderCompile: { COMPLETION_STATUS_KHR: number } | null;\n /** True when 32-bit float color attachments are renderable\n * (`EXT_color_buffer_float`). Mirrors Babylon's `caps.textureFloatRender`. */\n readonly textureFloatRender: boolean;\n /** True when 32-bit float textures support linear filtering\n * (`OES_texture_float_linear`). Mirrors `caps.textureFloatLinearFiltering`. */\n readonly textureFloatLinearFiltering: boolean;\n /** True when 16-bit half-float color attachments are renderable\n * (`EXT_color_buffer_float` or `EXT_color_buffer_half_float`). Mirrors\n * `caps.textureHalfFloatRender`. */\n readonly textureHalfFloatRender: boolean;\n /** Half-float linear filtering — always `true` in WebGL2 (it is core).\n * Kept as a field to mirror Babylon's `caps.textureHalfFloatLinearFiltering`. */\n readonly textureHalfFloatLinearFiltering: boolean;\n /** Whether non-power-of-two textures need POT dimensions for mips / wrap.\n * Always `false` in WebGL2 (NPOT is core). Mirrors `engine.needPOTTextures`. */\n readonly needPOTTextures: boolean;\n}\n\n/**\n * Pure-state handle for a WebGL2 canvas + its cached GL state.\n *\n * INVARIANT: consumers MUST NOT mutate GL state directly through `engine.gl`.\n * Doing so silently corrupts the cache in `_state`. The package owns every\n * GL call. (`engine.gl` is exposed only so downstream code that already has the\n * pattern of poking `engine._gl.getExtension(...)` can do that, but must NOT\n * call `bindTexture`/`useProgram`/`bindBuffer`/`viewport`/etc.)\n */\nexport interface GLEngineContext {\n /** The canvas the WebGL2 context was acquired from. An `OffscreenCanvas` is\n * supported for worker render paths (e.g. the Lottie player); it has no CSS\n * box, so it must be sized explicitly via `setGLEngineSize` rather than the\n * CSS-derived `resizeGLEngine`. */\n readonly canvas: HTMLCanvasElement | OffscreenCanvas;\n /** The raw WebGL2 context. Do NOT mutate GL state through it — see the\n * type-level invariant above; the package owns every state-changing call. */\n readonly gl: WebGL2RenderingContext;\n /** Queried capability limits for this context. */\n readonly caps: GLEngineCaps;\n /**\n * Hardware-scaling-level — drawingBufferWidth = clientWidth * dpr / _hsl.\n * @internal\n */\n _hsl: number;\n /**\n * rAF id when a render loop is active, 0 otherwise.\n * @internal\n */\n _rafId: number;\n /**\n * Per-frame callbacks. `runRenderLoop` is a no-op if `fn` is already\n * registered (matches Babylon `AbstractEngine.runRenderLoop`).\n * @internal\n */\n _loops: ((dt: number) => void)[];\n /**\n * Timestamp of last frame for delta computation.\n * @internal\n */\n _prevNow: number;\n /**\n * Cached GL state. See §4 of 00-lite-gl.md.\n * @internal\n */\n _state: GLState;\n /**\n * Live effect registry — populated by `createEffect`, removed by\n * `disposeEffect`. Used by the context-restored protocol to rebuild\n * programs.\n * @internal\n */\n _effects: GLEffect[];\n /**\n * Per-engine effect cache keyed by source descriptor (vertex+fragment\n * source, defines, attribute/uniform/sampler names). `createEffect` returns\n * (and ref-counts) the cached `GLEffect` when an identical descriptor is\n * requested, so identical shaders share ONE WebGLProgram — letting\n * `useEffect`'s current-program cache elide redundant `gl.useProgram`.\n * @internal\n */\n _effectCache: Map<string, GLEffect>;\n /**\n * Live texture registry — populated by `createRawTexture` /\n * `loadTexture2D` / `createHtmlElementTexture`. Used by the\n * context-restored protocol to replay uploads.\n * @internal\n */\n _textures: GLTexture[];\n /**\n * Live render-target registry — populated by `createRenderTarget`. Used by\n * the context-restored protocol to rebuild framebuffers + attachments after\n * their color textures have been replayed. Empty (and tree-shaken) when the\n * render-target module is unused.\n * @internal\n */\n _renderTargets: GLRenderTarget[];\n /**\n * The render target currently bound for drawing (`bindRenderTarget`), or\n * `null` for the default canvas framebuffer. Tracked so that leaving a\n * mipmapped target (`bindRenderTarget(engine, null)` or switching to\n * another target) can regenerate its mip chain — mirroring Babylon's\n * auto-mipmap on `unBindFramebuffer`. Reset to `null` on context-lost.\n * @internal\n */\n _currentRenderTarget: GLRenderTarget | null;\n /**\n * Live vertex / index buffer registry — populated by `createVertexBuffer` /\n * `createIndexBuffer`. Used by the context-restored protocol to re-upload\n * the retained CPU data into fresh GL buffers. Empty (and tree-shaken) when\n * the mesh module is unused.\n * @internal\n */\n _buffers: GLManagedBuffer[];\n /** @internal */\n _onLost: (() => void)[];\n /** @internal */\n _onRestored: (() => void)[];\n /**\n * True between `webglcontextlost` and `webglcontextrestored`. While\n * true, every `setEffect*` / `bindTexture` / `drawEffect` is a no-op.\n * @internal\n */\n _isLost: boolean;\n /**\n * True once the context has been disposed; subsequent calls become no-ops.\n * @internal\n */\n _disposed: boolean;\n /**\n * DOM handlers — retained so dispose can `removeEventListener` them.\n * @internal\n */\n _lostHandler: (e: Event) => void;\n /** @internal */\n _restoredHandler: () => void;\n /**\n * True when a render loop was active at the moment of `webglcontextlost`,\n * so we can resume it from the restored handler.\n * @internal\n */\n _wasLoopActive: boolean;\n /**\n * Installed by `runRenderLoop` on first call. Lets the context-restored\n * handler resume a loop without a circular runtime import from render-loop.\n * Null if the render-loop module is tree-shaken out.\n * @internal\n */\n _scheduleFrame: ((engine: GLEngineContext) => void) | null;\n /** Optional feature-owned state-cache invalidators. Allocated lazily by the first feature that needs one.\n * @internal */\n _stateCacheInvalidators?: (() => void)[];\n}\n\n/** Acquire a WebGL2 context on the canvas and build the pure-state handle.\n * Accepts an `HTMLCanvasElement` or an `OffscreenCanvas` (worker render paths —\n * e.g. the Lottie player — which size the drawing buffer via `setGLEngineSize`).\n * Throws if WebGL2 is unsupported. */\nexport function createGLEngine(canvas: HTMLCanvasElement | OffscreenCanvas, options?: GLEngineOptions): GLEngineContext {\n const o = options ?? {};\n const attrs: WebGLContextAttributes = {\n alpha: o.alpha ?? true,\n premultipliedAlpha: o.premultipliedAlpha ?? true,\n antialias: o.antialias ?? false,\n preserveDrawingBuffer: o.preserveDrawingBuffer ?? false,\n depth: o.depth ?? false,\n stencil: o.stencil ?? false,\n powerPreference: o.powerPreference ?? \"default\",\n failIfMajorPerformanceCaveat: o.failIfMajorPerformanceCaveat ?? false,\n };\n const gl = canvas.getContext(\"webgl2\", attrs) as WebGL2RenderingContext | null;\n if (gl === null) {\n throw new Error(\"lite-gl: WebGL2 is not supported on this canvas\");\n }\n\n const caps = queryCaps(gl);\n\n const engine: GLEngineContext = {\n canvas,\n gl,\n caps,\n _hsl: 1,\n _rafId: 0,\n _loops: [],\n _prevNow: 0,\n _state: createGLState(caps.maxTextureUnits),\n _effects: [],\n _effectCache: new Map(),\n _textures: [],\n _renderTargets: [],\n _currentRenderTarget: null,\n _buffers: [],\n _onLost: [],\n _onRestored: [],\n _isLost: false,\n _disposed: false,\n _lostHandler: () => {},\n _restoredHandler: () => {},\n _wasLoopActive: false,\n _scheduleFrame: null,\n };\n\n engine._lostHandler = (e: Event) => handleContextLost(engine, e);\n engine._restoredHandler = () => handleContextRestored(engine);\n canvas.addEventListener(\"webglcontextlost\", engine._lostHandler as EventListener, false);\n canvas.addEventListener(\"webglcontextrestored\", engine._restoredHandler, false);\n\n return engine;\n}\n\n/** Stops the render loop, removes DOM listeners, releases all known effects\n * and textures, then marks the context disposed. The browser-owned canvas\n * is left intact. */\nexport function disposeGLEngine(engine: GLEngineContext): void {\n if (engine._disposed) {\n return;\n }\n engine._disposed = true;\n if (engine._rafId !== 0) {\n cancelAnimationFrame(engine._rafId);\n engine._rafId = 0;\n }\n engine._loops.length = 0;\n engine.canvas.removeEventListener(\"webglcontextlost\", engine._lostHandler as EventListener, false);\n engine.canvas.removeEventListener(\"webglcontextrestored\", engine._restoredHandler, false);\n\n const gl = engine.gl;\n // Iterate snapshots — the dispose paths splice into the registries.\n const effects = engine._effects.slice();\n for (const eff of effects) {\n if (!eff._disposed) {\n eff._disposed = true;\n eff.isReady = false;\n gl.deleteProgram(eff.program);\n gl.deleteShader(eff._vs);\n gl.deleteShader(eff._fs);\n }\n }\n engine._effects.length = 0;\n engine._effectCache.clear();\n const textures = engine._textures.slice();\n for (const tex of textures) {\n if (!tex._disposed) {\n tex._disposed = true;\n gl.deleteTexture(tex.handle);\n }\n }\n engine._textures.length = 0;\n // Render targets own their FBO + renderbuffer + color texture; free them via\n // the per-RT closure so context.ts needs no runtime import of render-target.\n const rts = engine._renderTargets.slice();\n for (const rt of rts) {\n if (!rt._disposed) {\n rt._disposed = true;\n rt._deleteGpu(gl);\n }\n }\n engine._renderTargets.length = 0;\n\n // Mesh vertex/index buffers own a single GL buffer each; free via closure.\n const buffers = engine._buffers.slice();\n for (const buf of buffers) {\n if (!buf._disposed) {\n buf._disposed = true;\n buf._deleteGpu(gl);\n }\n }\n engine._buffers.length = 0;\n\n resetGLState(engine._state);\n engine._currentRenderTarget = null;\n engine._onLost.length = 0;\n engine._onRestored.length = 0;\n engine._stateCacheInvalidators?.splice(0);\n}\n\n/** Match drawing-buffer size to (clientSize × devicePixelRatio / _hsl). No-op\n * if size already matches. Never touches viewport — `setViewport` owns that. */\nexport function resizeGLEngine(engine: GLEngineContext): void {\n if (engine._disposed || engine._isLost) {\n return;\n }\n const canvas = engine.canvas;\n // An OffscreenCanvas has no CSS box (no clientWidth/clientHeight); it is sized\n // explicitly via setGLEngineSize, so CSS-derived auto-resize is a no-op for it.\n if (!(\"clientWidth\" in canvas)) {\n return;\n }\n const dpr = typeof devicePixelRatio === \"number\" ? devicePixelRatio : 1;\n const w = Math.max(1, Math.floor((canvas.clientWidth * dpr) / engine._hsl));\n const h = Math.max(1, Math.floor((canvas.clientHeight * dpr) / engine._hsl));\n if (canvas.width !== w) {\n canvas.width = w;\n }\n if (canvas.height !== h) {\n canvas.height = h;\n }\n}\n\n/**\n * Set the drawing-buffer size to an EXPLICIT width/height in physical pixels\n * (each divided by `_hsl`), independent of the canvas client/CSS size — the\n * counterpart of Babylon's `ThinEngine.setSize`. Use when the render resolution\n * is computed directly (e.g. animation dimensions × scale × dpr) rather than\n * derived from CSS layout via {@link resizeGLEngine}. No-op on a disposed\n * engine. Never touches the viewport — `setViewport` owns that.\n *\n * @param engine - The engine to resize.\n * @param width - Target drawing-buffer width in physical pixels.\n * @param height - Target drawing-buffer height in physical pixels.\n */\nexport function setGLEngineSize(engine: GLEngineContext, width: number, height: number): void {\n if (engine._disposed) {\n return;\n }\n const canvas = engine.canvas;\n const w = Math.max(1, Math.floor(width / engine._hsl));\n const h = Math.max(1, Math.floor(height / engine._hsl));\n if (canvas.width !== w) {\n canvas.width = w;\n }\n if (canvas.height !== h) {\n canvas.height = h;\n }\n}\n\n/**\n * Invalidate lite-gl's cached GL state so the next state-setting call in each\n * category (program / buffer / texture / VAO / framebuffer bindings, blend,\n * depth, stencil, scissor, color-mask, viewport, unpack) is re-issued instead\n * of elided.\n *\n * Use this when a host application that SHARES this WebGL2 context mutates raw\n * `gl.*` state outside lite-gl — e.g. a save/restore wrapper that resets the\n * context to GL defaults around each render scope, or any interop layer that\n * issues GL calls directly. Without it, lite-gl's redundant-call elision would\n * skip the state changes needed to re-establish the scope, producing corrupted\n * output. Owned GPU resources (the shared quad, render targets, meshes,\n * effects, textures) are preserved — only the cached \"current GL state\" is\n * reset. Mirrors Babylon's `Engine.wipeCaches()`.\n *\n * No-op while the context is lost or the engine is disposed.\n */\nexport function wipeGLStateCache(engine: GLEngineContext): void {\n if (engine._disposed || engine._isLost) {\n return;\n }\n resetGLStateCache(engine._state);\n const invalidators = engine._stateCacheInvalidators;\n if (invalidators) {\n for (const invalidate of invalidators) {\n invalidate();\n }\n }\n}\n\n/** Drawing-buffer width in physical pixels (`canvas.width`). */\nexport function getRenderWidth(engine: GLEngineContext): number {\n return engine.canvas.width;\n}\n\n/** Drawing-buffer height in physical pixels (`canvas.height`). */\nexport function getRenderHeight(engine: GLEngineContext): number {\n return engine.canvas.height;\n}\n\n/** Current hardware-scaling factor — drawing-buffer = clientSize × dpr / level. */\nexport function getHardwareScalingLevel(engine: GLEngineContext): number {\n return engine._hsl;\n}\n\n/** Updates the hardware-scaling factor and triggers a resize. */\nexport function setHardwareScalingLevel(engine: GLEngineContext, level: number): void {\n if (level <= 0 || !isFinite(level)) {\n return;\n }\n engine._hsl = level;\n resizeGLEngine(engine);\n}\n\n/** The backing canvas element (an `HTMLCanvasElement`, or an `OffscreenCanvas`\n * for worker render paths). */\nexport function getRenderingCanvas(engine: GLEngineContext): HTMLCanvasElement | OffscreenCanvas {\n return engine.canvas;\n}\n\n/** Register a `webglcontextlost` callback. Duplicate registrations are ignored. */\nexport function onContextLost(engine: GLEngineContext, cb: () => void): void {\n if (engine._onLost.indexOf(cb) === -1) {\n engine._onLost.push(cb);\n }\n}\n\n/** Remove a previously-registered context-lost callback. */\nexport function offContextLost(engine: GLEngineContext, cb: () => void): void {\n const i = engine._onLost.indexOf(cb);\n if (i !== -1) {\n engine._onLost.splice(i, 1);\n }\n}\n\n/** Register a `webglcontextrestored` callback. Duplicate registrations are ignored. */\nexport function onContextRestored(engine: GLEngineContext, cb: () => void): void {\n if (engine._onRestored.indexOf(cb) === -1) {\n engine._onRestored.push(cb);\n }\n}\n\n/** Remove a previously-registered context-restored callback. */\nexport function offContextRestored(engine: GLEngineContext, cb: () => void): void {\n const i = engine._onRestored.indexOf(cb);\n if (i !== -1) {\n engine._onRestored.splice(i, 1);\n }\n}\n\n/* ───────────────────────── internal: loss / restore ───────────────────── */\n\nfunction handleContextLost(engine: GLEngineContext, e: Event): void {\n // Opt-in to restore. Without preventDefault() the browser will NOT fire\n // webglcontextrestored later.\n e.preventDefault();\n if (engine._isLost || engine._disposed) {\n return;\n }\n engine._isLost = true;\n // `tick` clears `_rafId` while callbacks run, so a loss event delivered in\n // that window still represents an active loop when callbacks remain.\n engine._wasLoopActive = engine._loops.length > 0;\n if (engine._rafId !== 0) {\n cancelAnimationFrame(engine._rafId);\n engine._rafId = 0;\n }\n resetGLState(engine._state);\n engine._currentRenderTarget = null;\n for (const eff of engine._effects) {\n eff.isReady = false;\n eff._samplersAssigned = false;\n eff.uniformLocations = {};\n eff.attributeLocations = {};\n // Clear value caches so the first frame after restore re-uploads\n // every uniform into the freshly-linked program.\n clearObject(eff._lastF1);\n clearObject(eff._lastVec);\n clearObject(eff._lastI1);\n // Do NOT gl.deleteProgram — handle is already dead per WebGL spec.\n }\n for (const tex of engine._textures) {\n tex._wasReady = tex.isReady;\n tex.isReady = false;\n }\n const cbs = engine._onLost.slice();\n for (const cb of cbs) {\n try {\n cb();\n } catch (err) {\n console.error(\"lite-gl: onLost callback threw\", err);\n }\n }\n}\n\nfunction handleContextRestored(engine: GLEngineContext): void {\n if (engine._disposed) {\n return;\n }\n Object.assign(engine.caps, queryCaps(engine.gl));\n for (const eff of engine._effects) {\n if (!eff._disposed) {\n eff._restore(engine);\n }\n }\n for (const tex of engine._textures) {\n if (!tex._disposed) {\n const newHandle = engine.gl.createTexture();\n if (newHandle !== null) {\n tex.handle = newHandle;\n tex._upload(engine);\n tex._initializeParameters?.(engine);\n tex.isReady = tex._wasReady;\n }\n }\n }\n // Clear the lost flag BEFORE the render-target / buffer rebuilds: their\n // `_restore` closures route through the same guarded build/upload paths used\n // at create time (which no-op while `_isLost`), whereas the effect / texture\n // replay above is unguarded and unaffected by the flag's value.\n engine._isLost = false;\n // Render targets rebuild their own color texture + FBO + renderbuffer AFTER\n // the standalone texture replay above (an RT's color texture is owned by the\n // RT, not the `_textures` registry).\n for (const rt of engine._renderTargets) {\n if (!rt._disposed) {\n rt._restore(engine);\n }\n }\n // Mesh buffers re-upload their retained CPU data into fresh GL buffers.\n for (const buf of engine._buffers) {\n if (!buf._disposed) {\n buf._restore(engine);\n }\n }\n if (engine._wasLoopActive && engine._loops.length > 0 && engine._scheduleFrame !== null) {\n engine._scheduleFrame(engine);\n }\n const cbs = engine._onRestored.slice();\n for (const cb of cbs) {\n try {\n cb();\n } catch (err) {\n console.error(\"lite-gl: onRestored callback threw\", err);\n }\n }\n}\n\nfunction queryCaps(gl: WebGL2RenderingContext): GLEngineCaps {\n const parallelExt = gl.getExtension(\"KHR_parallel_shader_compile\") as { COMPLETION_STATUS_KHR: number } | null;\n // `getExtension` both queries and enables these capabilities, so they must\n // be reacquired after context restoration before resources are rebuilt.\n const colorBufferFloat = gl.getExtension(\"EXT_color_buffer_float\") !== null;\n const colorBufferHalfFloat = gl.getExtension(\"EXT_color_buffer_half_float\") !== null;\n const floatLinear = gl.getExtension(\"OES_texture_float_linear\") !== null;\n return {\n maxTextureSize: gl.getParameter(gl.MAX_TEXTURE_SIZE) as number,\n maxTextureUnits: gl.getParameter(gl.MAX_COMBINED_TEXTURE_IMAGE_UNITS) as number,\n parallelShaderCompile: parallelExt,\n textureFloatRender: colorBufferFloat,\n textureFloatLinearFiltering: floatLinear,\n textureHalfFloatRender: colorBufferFloat || colorBufferHalfFloat,\n textureHalfFloatLinearFiltering: true,\n needPOTTextures: false,\n };\n}\n\nfunction clearObject(o: { [k: string]: unknown }): void {\n for (const key in o) {\n delete o[key];\n }\n}\n"]}
@@ -12,7 +12,7 @@
12
12
  * internally and replayed into the fresh handle on `webglcontextrestored` by the
13
13
  * engine's standard context-restore protocol.
14
14
  */
15
- import { bindTextureForUpload, setUnpackState } from "./texture.js";
15
+ import { bindTextureForUpload, setBoundTextureParams, setUnpackState } from "./texture.js";
16
16
  /** Create a texture backed by an empty (blank) `width × height` RGBA8
17
17
  * allocation, whose pixels are pushed on demand with
18
18
  * {@link updateDynamicTexture} — the WebGL counterpart of Babylon's
@@ -66,10 +66,7 @@ export function createDynamicTexture(engine, width, height, options) {
66
66
  g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);
67
67
  }
68
68
  if (tex._dynParamsHandle !== tex.handle) {
69
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
70
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
71
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
72
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
69
+ setBoundTextureParams(g, minFilter, magFilter, wrapS, wrapT);
73
70
  tex._dynParamsHandle = tex.handle;
74
71
  }
75
72
  if (generateMipMaps && src !== null && src !== undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"dynamic-texture.js","sourceRoot":"","sources":["../src/dynamic-texture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Dynamic (canvas-/bitmap-backed) textures.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that never push 2D pixel sources into a\n * texture tree-shake this code out.\n *\n * The WebGL counterpart of Babylon's `ThinEngine.createDynamicTexture` +\n * `updateDynamicTexture`. A dynamic texture is a blank RGBA8 allocation whose\n * pixels are pushed on demand from a canvas / `OffscreenCanvas` / image / video\n * / `ImageBitmap` / `ImageData` source. The most recent source is retained\n * internally and replayed into the fresh handle on `webglcontextrestored` by the\n * engine's standard context-restore protocol.\n */\nimport { bindTextureForUpload, setUnpackState, type GLTexture, type GLTextureOptions } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** Create a texture backed by an empty (blank) `width × height` RGBA8\n * allocation, whose pixels are pushed on demand with\n * {@link updateDynamicTexture} — the WebGL counterpart of Babylon's\n * `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.\n *\n * The texture is immediately sampleable (reads as transparent black until the\n * first update). It is context-restore-safe: the most recent source pushed via\n * {@link updateDynamicTexture} is replayed into the fresh handle on\n * `webglcontextrestored` (and re-blanked if no update happened yet).\n *\n * `options.invertY` is ignored here (the blank allocation is flip-invariant);\n * per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.\n *\n * @param engine - The engine to create GL resources on.\n * @param width - Texture width in texels (clamped to ≥ 1).\n * @param height - Texture height in texels (clamped to ≥ 1).\n * @param options - Optional sampling/wrap config (see {@link GLTextureOptions})\n * plus this factory's own `generateMipMaps` flag (mipmaps are built after an\n * update when a source is present; defaults to `false`).\n * @returns The new {@link GLTexture}. */\nexport function createDynamicTexture(engine: GLEngineContext, width: number, height: number, options?: GLTextureOptions & { generateMipMaps?: boolean }): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const w = Math.max(1, width | 0);\n const h = Math.max(1, height | 0);\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const generateMipMaps = opts.generateMipMaps ?? false;\n\n // Single `_upload` closure used for both the initial allocation AND every\n // `webglcontextrestored` replay AND every `updateDynamicTexture`. The pixel\n // upload runs every time; the four `texParameteri` calls run ONLY when the\n // handle changed (initial create + restore install a fresh, GL-default\n // handle) — a per-frame pixel update keeps the same handle, whose filter/wrap\n // GL retains, so re-applying them would be a pure redundant cost.\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n bindTextureForUpload(target, tex.handle);\n const src = tex._dynSource;\n if (src !== null && src !== undefined) {\n setUnpackState(target, tex._dynInvertY === true, tex._dynPremultiplyAlpha === true);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, src);\n } else {\n setUnpackState(target, false, false);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);\n }\n if (tex._dynParamsHandle !== tex.handle) {\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);\n tex._dynParamsHandle = tex.handle;\n }\n if (generateMipMaps && src !== null && src !== undefined) {\n g.generateMipmap(g.TEXTURE_2D);\n }\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: w,\n height: h,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: true,\n _dynSource: null,\n _dynInvertY: false,\n _dynPremultiplyAlpha: false,\n };\n upload(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /\n * `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the\n * WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source\n * is retained on the texture so it is replayed on `webglcontextrestored`.\n * No-op when the context is lost/disposed or the texture is disposed.\n *\n * @param engine - The engine that owns the texture.\n * @param tex - A texture created by {@link createDynamicTexture}.\n * @param source - The 2D pixel source to upload.\n * @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.\n * @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).\n * Default `false`, matching Babylon's `updateDynamicTexture` default. */\nexport function updateDynamicTexture(engine: GLEngineContext, tex: GLTexture, source: TexImageSource, invertY = false, premultiplyAlpha = false): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n tex._dynSource = source;\n tex._dynInvertY = invertY;\n tex._dynPremultiplyAlpha = premultiplyAlpha;\n tex._upload(engine);\n}\n\n/** Forget the source a dynamic texture retained for context-restore replay.\n * The current GPU pixels are kept (no re-upload), but the source reference is\n * dropped so it can be garbage-collected — and a subsequent\n * `webglcontextrestored` will re-blank the texture instead of replaying. Use\n * after the final {@link updateDynamicTexture} once the source (e.g. a large\n * atlas canvas) is no longer needed. No-op on a non-dynamic texture. */\nexport function clearDynamicTextureSource(tex: GLTexture): void {\n tex._dynSource = null;\n}\n"]}
1
+ {"version":3,"file":"dynamic-texture.js","sourceRoot":"","sources":["../src/dynamic-texture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Dynamic (canvas-/bitmap-backed) textures.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that never push 2D pixel sources into a\n * texture tree-shake this code out.\n *\n * The WebGL counterpart of Babylon's `ThinEngine.createDynamicTexture` +\n * `updateDynamicTexture`. A dynamic texture is a blank RGBA8 allocation whose\n * pixels are pushed on demand from a canvas / `OffscreenCanvas` / image / video\n * / `ImageBitmap` / `ImageData` source. The most recent source is retained\n * internally and replayed into the fresh handle on `webglcontextrestored` by the\n * engine's standard context-restore protocol.\n */\nimport { bindTextureForUpload, setBoundTextureParams, setUnpackState, type GLTexture, type GLTextureOptions } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** Create a texture backed by an empty (blank) `width × height` RGBA8\n * allocation, whose pixels are pushed on demand with\n * {@link updateDynamicTexture} — the WebGL counterpart of Babylon's\n * `ThinEngine.createDynamicTexture` + `ThinTexture` wrapper.\n *\n * The texture is immediately sampleable (reads as transparent black until the\n * first update). It is context-restore-safe: the most recent source pushed via\n * {@link updateDynamicTexture} is replayed into the fresh handle on\n * `webglcontextrestored` (and re-blanked if no update happened yet).\n *\n * `options.invertY` is ignored here (the blank allocation is flip-invariant);\n * per-update flip is controlled by {@link updateDynamicTexture}'s `invertY`.\n *\n * @param engine - The engine to create GL resources on.\n * @param width - Texture width in texels (clamped to ≥ 1).\n * @param height - Texture height in texels (clamped to ≥ 1).\n * @param options - Optional sampling/wrap config (see {@link GLTextureOptions})\n * plus this factory's own `generateMipMaps` flag (mipmaps are built after an\n * update when a source is present; defaults to `false`).\n * @returns The new {@link GLTexture}. */\nexport function createDynamicTexture(engine: GLEngineContext, width: number, height: number, options?: GLTextureOptions & { generateMipMaps?: boolean }): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const w = Math.max(1, width | 0);\n const h = Math.max(1, height | 0);\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const generateMipMaps = opts.generateMipMaps ?? false;\n\n // Single `_upload` closure used for both the initial allocation AND every\n // `webglcontextrestored` replay AND every `updateDynamicTexture`. The pixel\n // upload runs every time; the four `texParameteri` calls run ONLY when the\n // handle changed (initial create + restore install a fresh, GL-default\n // handle) — a per-frame pixel update keeps the same handle, whose filter/wrap\n // GL retains, so re-applying them would be a pure redundant cost.\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n bindTextureForUpload(target, tex.handle);\n const src = tex._dynSource;\n if (src !== null && src !== undefined) {\n setUnpackState(target, tex._dynInvertY === true, tex._dynPremultiplyAlpha === true);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, src);\n } else {\n setUnpackState(target, false, false);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, w, h, 0, g.RGBA, g.UNSIGNED_BYTE, null);\n }\n if (tex._dynParamsHandle !== tex.handle) {\n setBoundTextureParams(g, minFilter, magFilter, wrapS, wrapT);\n tex._dynParamsHandle = tex.handle;\n }\n if (generateMipMaps && src !== null && src !== undefined) {\n g.generateMipmap(g.TEXTURE_2D);\n }\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: w,\n height: h,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: true,\n _dynSource: null,\n _dynInvertY: false,\n _dynPremultiplyAlpha: false,\n };\n upload(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Push 2D pixels into a {@link createDynamicTexture} texture from a canvas /\n * `OffscreenCanvas` / image / video / `ImageBitmap` / `ImageData` source — the\n * WebGL counterpart of Babylon's `ThinEngine.updateDynamicTexture`. The source\n * is retained on the texture so it is replayed on `webglcontextrestored`.\n * No-op when the context is lost/disposed or the texture is disposed.\n *\n * @param engine - The engine that owns the texture.\n * @param tex - A texture created by {@link createDynamicTexture}.\n * @param source - The 2D pixel source to upload.\n * @param invertY - Flip vertically on upload (`UNPACK_FLIP_Y_WEBGL`). Default `false`.\n * @param premultiplyAlpha - Premultiply on upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`).\n * Default `false`, matching Babylon's `updateDynamicTexture` default. */\nexport function updateDynamicTexture(engine: GLEngineContext, tex: GLTexture, source: TexImageSource, invertY = false, premultiplyAlpha = false): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n tex._dynSource = source;\n tex._dynInvertY = invertY;\n tex._dynPremultiplyAlpha = premultiplyAlpha;\n tex._upload(engine);\n}\n\n/** Forget the source a dynamic texture retained for context-restore replay.\n * The current GPU pixels are kept (no re-upload), but the source reference is\n * dropped so it can be garbage-collected — and a subsequent\n * `webglcontextrestored` will re-blank the texture instead of replaying. Use\n * after the final {@link updateDynamicTexture} once the source (e.g. a large\n * atlas canvas) is no longer needed. No-op on a non-dynamic texture. */\nexport function clearDynamicTextureSource(tex: GLTexture): void {\n tex._dynSource = null;\n}\n"]}
package/html-texture.js CHANGED
@@ -1,4 +1,4 @@
1
- import { bindTextureForUpload, setUnpackState } from "./texture.js";
1
+ import { bindTextureForUpload, setBoundTextureParams, setUnpackState } from "./texture.js";
2
2
  /** High-level sampling presets, mirroring Babylon's `Texture.*_SAMPLINGMODE`
3
3
  * numeric constants. Each resolves to GL min/mag filters (and mip generation
4
4
  * for `TRILINEAR`). */
@@ -41,18 +41,17 @@ export function createHtmlElementTexture(engine, element, options) {
41
41
  const g = target.gl;
42
42
  setUnpackState(target, invertY, false);
43
43
  bindTextureForUpload(target, tex.handle);
44
- g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, element);
44
+ g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, g.RGBA, g.UNSIGNED_BYTE, element);
45
45
  const [w, h] = sizeOf();
46
46
  tex.width = w;
47
47
  tex.height = h;
48
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
49
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
50
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
51
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
52
48
  if (generateMipMaps) {
53
49
  g.generateMipmap(g.TEXTURE_2D);
54
50
  }
55
51
  };
52
+ const initializeParameters = (target) => {
53
+ setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);
54
+ };
56
55
  const [w0, h0] = sizeOf();
57
56
  const tex = {
58
57
  handle,
@@ -63,9 +62,11 @@ export function createHtmlElementTexture(engine, element, options) {
63
62
  _disposed: false,
64
63
  _refCount: 1,
65
64
  _upload: upload,
65
+ _initializeParameters: initializeParameters,
66
66
  _wasReady: true,
67
67
  };
68
68
  upload(engine);
69
+ initializeParameters(engine);
69
70
  engine._textures.push(tex);
70
71
  return tex;
71
72
  }
@@ -1 +1 @@
1
- {"version":3,"file":"html-texture.js","sourceRoot":"","sources":["../src/html-texture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTML element textures.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that don't need it (everything except\n * NeonBrush's `InputGlow`) tree-shake it out.\n */\nimport type { GLEngineContext } from \"./context.js\";\nimport { bindTextureForUpload, setUnpackState, type GLTexture, type GLTextureOptions } from \"./texture.js\";\n\n/** High-level sampling presets, mirroring Babylon's `Texture.*_SAMPLINGMODE`\n * numeric constants. Each resolves to GL min/mag filters (and mip generation\n * for `TRILINEAR`). */\nexport const GLSamplingMode = {\n /** Nearest min + mag, no mipmaps. (`Texture.NEAREST_SAMPLINGMODE`) */\n NEAREST: 1,\n /** Linear min + mag, no mipmaps. (`Texture.BILINEAR_SAMPLINGMODE`) */\n BILINEAR: 2,\n /** Linear mag + linear-mipmap-linear min, mipmaps generated.\n * (`Texture.TRILINEAR_SAMPLINGMODE`) */\n TRILINEAR: 3,\n} as const;\n\n/** One of the {@link GLSamplingMode} preset values (`1`, `2` or `3`). */\nexport type GLSamplingMode = (typeof GLSamplingMode)[keyof typeof GLSamplingMode];\n\n/** Options for `createHtmlElementTexture` — the base texture options plus\n * HTML-source-specific settings. */\nexport interface GLHtmlElementTextureOptions extends GLTextureOptions {\n /** High-level sampling preset. When set, derives `minFilter`/`magFilter`\n * (and `generateMipMaps` for `TRILINEAR`). Explicit `minFilter` /\n * `magFilter` / `generateMipMaps` options still take precedence. Omit for\n * the GL defaults (linear min + mag, no mipmaps). */\n samplingMode?: GLSamplingMode;\n /** Build a full mip chain after each upload. Independent of the core\n * texture options (this factory's mip behavior is sampling-mode-driven):\n * defaults to `true` only when `samplingMode` is `TRILINEAR`, otherwise\n * `false`. */\n generateMipMaps?: boolean;\n}\n\n/** Create a texture backed by an `<canvas>` / `<img>` / `<video>` element.\n * The initial upload is performed immediately; call `updateHtmlElementTexture`\n * to re-upload after the source has changed. */\nexport function createHtmlElementTexture(\n engine: GLEngineContext,\n element: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement,\n options?: GLHtmlElementTextureOptions\n): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const sm = opts.samplingMode;\n const minFilter = opts.minFilter ?? samplingMinFilter(gl, sm);\n const magFilter = opts.magFilter ?? samplingMagFilter(gl, sm);\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n const generateMipMaps = opts.generateMipMaps ?? sm === GLSamplingMode.TRILINEAR;\n\n const sizeOf = (): [number, number] => {\n if (element instanceof HTMLVideoElement) {\n return [element.videoWidth || 1, element.videoHeight || 1];\n }\n if (element instanceof HTMLImageElement) {\n return [element.naturalWidth || 1, element.naturalHeight || 1];\n }\n return [element.width || 1, element.height || 1];\n };\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n setUnpackState(target, invertY, false);\n bindTextureForUpload(target, tex.handle);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, element);\n const [w, h] = sizeOf();\n tex.width = w;\n tex.height = h;\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);\n if (generateMipMaps) {\n g.generateMipmap(g.TEXTURE_2D);\n }\n };\n\n const [w0, h0] = sizeOf();\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: w0,\n height: h0,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: true,\n };\n upload(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Re-upload the texture from its source element. No-op when the context is\n * lost/disposed or the texture is disposed. */\nexport function updateHtmlElementTexture(engine: GLEngineContext, tex: GLTexture): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n tex._upload(engine);\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Resolve a sampling preset to a GL min filter. Defaults to `gl.LINEAR`. */\nfunction samplingMinFilter(gl: WebGL2RenderingContext, mode: GLSamplingMode | undefined): GLenum {\n if (mode === GLSamplingMode.NEAREST) {\n return gl.NEAREST;\n }\n if (mode === GLSamplingMode.TRILINEAR) {\n return gl.LINEAR_MIPMAP_LINEAR;\n }\n return gl.LINEAR;\n}\n\n/** Resolve a sampling preset to a GL mag filter. Defaults to `gl.LINEAR`. */\nfunction samplingMagFilter(gl: WebGL2RenderingContext, mode: GLSamplingMode | undefined): GLenum {\n return mode === GLSamplingMode.NEAREST ? gl.NEAREST : gl.LINEAR;\n}\n"]}
1
+ {"version":3,"file":"html-texture.js","sourceRoot":"","sources":["../src/html-texture.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * HTML element textures.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that don't need it (everything except\n * NeonBrush's `InputGlow`) tree-shake it out.\n */\nimport type { GLEngineContext } from \"./context.js\";\nimport { bindTextureForUpload, setBoundTextureParams, setUnpackState, type GLTexture, type GLTextureOptions } from \"./texture.js\";\n\n/** High-level sampling presets, mirroring Babylon's `Texture.*_SAMPLINGMODE`\n * numeric constants. Each resolves to GL min/mag filters (and mip generation\n * for `TRILINEAR`). */\nexport const GLSamplingMode = {\n /** Nearest min + mag, no mipmaps. (`Texture.NEAREST_SAMPLINGMODE`) */\n NEAREST: 1,\n /** Linear min + mag, no mipmaps. (`Texture.BILINEAR_SAMPLINGMODE`) */\n BILINEAR: 2,\n /** Linear mag + linear-mipmap-linear min, mipmaps generated.\n * (`Texture.TRILINEAR_SAMPLINGMODE`) */\n TRILINEAR: 3,\n} as const;\n\n/** One of the {@link GLSamplingMode} preset values (`1`, `2` or `3`). */\nexport type GLSamplingMode = (typeof GLSamplingMode)[keyof typeof GLSamplingMode];\n\n/** Options for `createHtmlElementTexture` — the base texture options plus\n * HTML-source-specific settings. */\nexport interface GLHtmlElementTextureOptions extends GLTextureOptions {\n /** High-level sampling preset. When set, derives `minFilter`/`magFilter`\n * (and `generateMipMaps` for `TRILINEAR`). Explicit `minFilter` /\n * `magFilter` / `generateMipMaps` options still take precedence. Omit for\n * the GL defaults (linear min + mag, no mipmaps). */\n samplingMode?: GLSamplingMode;\n /** Build a full mip chain after each upload. Independent of the core\n * texture options (this factory's mip behavior is sampling-mode-driven):\n * defaults to `true` only when `samplingMode` is `TRILINEAR`, otherwise\n * `false`. */\n generateMipMaps?: boolean;\n}\n\n/** Create a texture backed by an `<canvas>` / `<img>` / `<video>` element.\n * The initial upload is performed immediately; call `updateHtmlElementTexture`\n * to re-upload after the source has changed. */\nexport function createHtmlElementTexture(\n engine: GLEngineContext,\n element: HTMLCanvasElement | HTMLImageElement | HTMLVideoElement,\n options?: GLHtmlElementTextureOptions\n): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const sm = opts.samplingMode;\n const minFilter = opts.minFilter ?? samplingMinFilter(gl, sm);\n const magFilter = opts.magFilter ?? samplingMagFilter(gl, sm);\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n const generateMipMaps = opts.generateMipMaps ?? sm === GLSamplingMode.TRILINEAR;\n\n const sizeOf = (): [number, number] => {\n if (element instanceof HTMLVideoElement) {\n return [element.videoWidth || 1, element.videoHeight || 1];\n }\n if (element instanceof HTMLImageElement) {\n return [element.naturalWidth || 1, element.naturalHeight || 1];\n }\n return [element.width || 1, element.height || 1];\n };\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n setUnpackState(target, invertY, false);\n bindTextureForUpload(target, tex.handle);\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA8, g.RGBA, g.UNSIGNED_BYTE, element);\n const [w, h] = sizeOf();\n tex.width = w;\n tex.height = h;\n if (generateMipMaps) {\n g.generateMipmap(g.TEXTURE_2D);\n }\n };\n\n const initializeParameters = (target: GLEngineContext): void => {\n setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);\n };\n\n const [w0, h0] = sizeOf();\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: w0,\n height: h0,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _initializeParameters: initializeParameters,\n _wasReady: true,\n };\n upload(engine);\n initializeParameters(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Re-upload the texture from its source element. No-op when the context is\n * lost/disposed or the texture is disposed. */\nexport function updateHtmlElementTexture(engine: GLEngineContext, tex: GLTexture): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n tex._upload(engine);\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Resolve a sampling preset to a GL min filter. Defaults to `gl.LINEAR`. */\nfunction samplingMinFilter(gl: WebGL2RenderingContext, mode: GLSamplingMode | undefined): GLenum {\n if (mode === GLSamplingMode.NEAREST) {\n return gl.NEAREST;\n }\n if (mode === GLSamplingMode.TRILINEAR) {\n return gl.LINEAR_MIPMAP_LINEAR;\n }\n return gl.LINEAR;\n}\n\n/** Resolve a sampling preset to a GL mag filter. Defaults to `gl.LINEAR`. */\nfunction samplingMagFilter(gl: WebGL2RenderingContext, mode: GLSamplingMode | undefined): GLenum {\n return mode === GLSamplingMode.NEAREST ? gl.NEAREST : gl.LINEAR;\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjs/lite-gl",
3
- "version": "1.11.0",
3
+ "version": "1.12.0",
4
4
  "description": "Function-based, tree-shakeable WebGL2 micro-engine for fullscreen effects, sprites and dynamic textures — the WebGL counterpart of @babylonjs/lite.",
5
5
  "keywords": [
6
6
  "babylon",
@@ -32,7 +32,7 @@
32
32
  }
33
33
  },
34
34
  "babylonLiteRelease": {
35
- "azureBuildId": "59363",
36
- "sourceVersion": "fbbf158d48f07b5b3e278e62616d2c463e5df609"
35
+ "azureBuildId": "59903",
36
+ "sourceVersion": "3ce8ae6d34945f4c32c73e357714ffa43be41584"
37
37
  }
38
38
  }
package/render-target.js CHANGED
@@ -25,7 +25,7 @@
25
25
  * (BYO) color texture lives in the engine's `_textures` registry and is restored
26
26
  * there first; the RT then re-attaches its freshly-swapped handle.
27
27
  */
28
- import { bindTextureForUpload, pickSizedInternalFormat } from "./texture.js";
28
+ import { bindTextureForUpload, pickSizedInternalFormat, setBoundTextureParams } from "./texture.js";
29
29
  /** GL `gl.UNSIGNED_BYTE` — the default (RGBA8) color attachment type. */
30
30
  const UNSIGNED_BYTE = 0x1401;
31
31
  /** GL `gl.HALF_FLOAT`. */
@@ -395,10 +395,7 @@ function allocateRenderTargetGpu(engine, rt) {
395
395
  rt.texture.handle = texHandle;
396
396
  bindTextureForUpload(engine, texHandle);
397
397
  gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);
398
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, c.minFilter);
399
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, c.magFilter);
400
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, c.wrapS);
401
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, c.wrapT);
398
+ setBoundTextureParams(gl, c.minFilter, c.magFilter, c.wrapS, c.wrapT);
402
399
  rt.texture.isReady = true;
403
400
  rt.texture._wasReady = true;
404
401
  }
@@ -1 +1 @@
1
- {"version":3,"file":"render-target.js","sourceRoot":"","sources":["../src/render-target.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Render-to-texture (offscreen framebuffer) support.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that only render fullscreen effects to the\n * canvas tree-shake the FBO code out.\n *\n * This is the lite-gl equivalent of Babylon's `RenderTargetWrapper` +\n * `ThinEngine.createRenderTargetTexture` / `bindFramebuffer` /\n * `restoreDefaultFramebuffer` / `_readTexturePixelsSync`. A render target owns a\n * color {@link GLTexture} (or attaches a caller-supplied one) plus an optional\n * depth and/or stencil renderbuffer, all wrapped in a single\n * `WebGLFramebuffer`.\n *\n * The default {@link createRenderTarget} makes an **RGBA8** color target and\n * ships none of the HDR sized-format knowledge; {@link createFloatRenderTarget}\n * is the separate opt-in for float / half-float color attachments (it alone\n * carries the `RGBA16F` / `RGBA32F` table, so RGBA8 consumers tree-shake it\n * away).\n *\n * The full color/depth/stencil GPU set is rebuilt automatically on\n * `webglcontextrestored` — the render target registers itself with the engine's\n * `_renderTargets` registry, and the context-restore protocol calls its\n * `_restore` closure AFTER the standalone texture replay. A caller-supplied\n * (BYO) color texture lives in the engine's `_textures` registry and is restored\n * there first; the RT then re-attaches its freshly-swapped handle.\n */\nimport { bindTextureForUpload, pickSizedInternalFormat, type GLTexture } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.UNSIGNED_BYTE` — the default (RGBA8) color attachment type. */\nconst UNSIGNED_BYTE = 0x1401;\n/** GL `gl.HALF_FLOAT`. */\nconst HALF_FLOAT = 0x140b;\n/** GL `gl.FLOAT`. */\nconst FLOAT = 0x1406;\n/** GL `gl.RGBA`. */\nconst RGBA = 0x1908;\n/** GL `gl.RGBA8` — the default sized internalFormat. */\nconst RGBA8 = 0x8058;\n/** GL `gl.LINEAR`. */\nconst LINEAR = 0x2601;\n/** GL `gl.CLAMP_TO_EDGE`. */\nconst CLAMP_TO_EDGE = 0x812f;\n\n/** Options for {@link createRenderTarget}. `width`/`height` are required; every\n * other field has a Babylon-matching default. The bare\n * `createRenderTarget(engine, { width, height })` makes an RGBA8 color-only\n * target with linear filtering and clamp wrapping. */\nexport interface GLRenderTargetOptions {\n /** Color attachment width in texels. Must be a positive integer. */\n width: number;\n /** Color attachment height in texels. Must be a positive integer. */\n height: number;\n /** Allocate a depth renderbuffer (`DEPTH_COMPONENT16`). Default `false`.\n * Stencil is NOT a create option — opt in (packed depth+stencil, or\n * stencil-only) via `generateRenderTargetStencil`\n * (`@babylonjs/lite-gl`), which keeps the stencil/packed\n * renderbuffer code out of the render-target core bundle. */\n generateDepthBuffer?: boolean;\n /** Color texture minification filter. Default `gl.LINEAR`. */\n minFilter?: GLenum;\n /** Color texture magnification filter. Default `gl.LINEAR`. */\n magFilter?: GLenum;\n /** Color texture S wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapS?: GLenum;\n /** Color texture T wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapT?: GLenum;\n /** Attach a caller-supplied (BYO) color {@link GLTexture} instead of creating\n * one. When supplied the render target does NOT own or restore it — the\n * texture is engine-managed (restored by the standard texture-restore path\n * first) and the RT re-attaches its swapped handle afterwards. The caller is\n * responsible for sizing it to `width`×`height` and for disposing it. */\n colorTexture?: GLTexture;\n}\n\n/** Options for {@link createFloatRenderTarget} — {@link GLRenderTargetOptions}\n * plus the float color `type`. */\nexport interface GLFloatRenderTargetOptions extends GLRenderTargetOptions {\n /** Float color attachment type. Default `gl.HALF_FLOAT`. Pass `gl.FLOAT` for\n * full 32-bit. Downgraded to the best renderable type the engine supports\n * (`caps.textureFloatRender` / `caps.textureHalfFloatRender`), mirroring\n * Babylon's `getTextureType`. */\n type?: GLenum;\n}\n\n/** Resolved (defaults-applied) attachment description, retained on the render\n * target so `webglcontextrestored` can rebuild the exact same GPU set. */\ninterface ResolvedRTConfig {\n internalFormat: GLenum;\n format: GLenum;\n type: GLenum;\n hasDepth: boolean;\n minFilter: GLenum;\n magFilter: GLenum;\n wrapS: GLenum;\n wrapT: GLenum;\n /** True when the RT created (and therefore owns/restores/deletes) its color\n * texture; false for a BYO {@link GLRenderTargetOptions.colorTexture}. */\n ownsColorTexture: boolean;\n}\n\n/**\n * An offscreen render target — a `WebGLFramebuffer` wrapping a color\n * {@link GLTexture} and an optional depth / stencil renderbuffer. The lite-gl\n * counterpart of Babylon's `RenderTargetWrapper`.\n */\nexport interface GLRenderTarget {\n /** The color attachment, sampleable like any other {@link GLTexture}\n * (`setEffectTexture` / `bindTexture`). For an owned attachment its handle\n * is swapped on `webglcontextrestored` while consumers keep this same\n * reference. */\n texture: GLTexture;\n /** Color attachment width in texels. */\n width: number;\n /** Color attachment height in texels. */\n height: number;\n /** True once the color attachment + framebuffer are allocated. */\n isReady: boolean;\n /** @internal The framebuffer object. Swapped on context-restore. */\n _framebuffer: WebGLFramebuffer | null;\n /** @internal Depth-only (`DEPTH_COMPONENT16`) renderbuffer built by the core,\n * OR the packed/stencil renderbuffer installed by `generateRenderTargetStencil`\n * — a single field either way. Null when neither depth nor stencil is used. */\n _depthStencil: WebGLRenderbuffer | null;\n /**\n * @internal Optional stencil rebuild hook installed by\n * `generateRenderTargetStencil` (`@babylonjs/lite-gl`). When\n * present it OWNS the depth/stencil renderbuffer (replacing the core\n * depth-only buffer) and is re-invoked after every FBO rebuild\n * (create-via-helper, resize, context-restore) so the attachment survives.\n */\n _rebuildDepthStencil?: (engine: GLEngineContext) => void;\n /** @internal Resolved attachment config, for context-restore rebuild. */\n _config: ResolvedRTConfig;\n /** @internal */\n _disposed: boolean;\n /** @internal Delete every GPU object the target owns (FBO, renderbuffer, and\n * the color texture iff owned). Resets the bound-framebuffer cache if it\n * pointed at this target. Called by `disposeRenderTarget`, `resizeRenderTarget`\n * and engine dispose. */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal Rebuild the FBO + renderbuffer (+ owned color texture) into\n * fresh handles after `webglcontextrestored`. */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/**\n * Create an offscreen **RGBA8** render target.\n *\n * The color attachment is an owned {@link GLTexture} (rebuilt by this target's\n * own restore hook), unless {@link GLRenderTargetOptions.colorTexture} supplies a\n * caller-managed (BYO) one. Mirrors Babylon's `createRenderTargetTexture`.\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLRenderTargetOptions} (`width`/`height` required).\n * @returns The new {@link GLRenderTarget}.\n * @throws If `width`/`height` are not positive integers, a GL handle could not\n * be allocated, or the resulting framebuffer is not complete. On failure every\n * partial GPU object (including an owned color texture) is released first.\n */\nexport function createRenderTarget(engine: GLEngineContext, options: GLRenderTargetOptions): GLRenderTarget {\n return buildRT(engine, options, RGBA8, RGBA, UNSIGNED_BYTE);\n}\n\n/**\n * Create an offscreen **float / half-float** render target — the HDR opt-in\n * counterpart of {@link createRenderTarget}. This is the only render-target\n * factory that references the `RGBA16F` / `RGBA32F` sized-format table, so RGBA8\n * consumers ship none of it.\n *\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The requested type is downgraded to the best renderable type the engine\n * supports (mirroring Babylon's `getTextureType`).\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLFloatRenderTargetOptions}.\n * @returns The new {@link GLRenderTarget}.\n * @throws As {@link createRenderTarget}.\n */\nexport function createFloatRenderTarget(engine: GLEngineContext, options: GLFloatRenderTargetOptions): GLRenderTarget {\n const type = resolveColorType(engine, options.type ?? HALF_FLOAT);\n const internalFormat = pickSizedInternalFormat(engine.gl, RGBA, type);\n return buildRT(engine, options, internalFormat, RGBA, type);\n}\n\n/**\n * Bind the render target's framebuffer as the draw target and set the viewport\n * to cover it. `rt = null` binds the default (canvas) framebuffer and resets the\n * viewport to the full canvas — the counterpart of Babylon's\n * `restoreDefaultFramebuffer`. Subsequent `drawEffect` / `drawIndexed` /\n * `clearEngine` calls write into the bound target.\n *\n * Cached. No-op on a lost/disposed context or a disposed `rt`. Mipmaps are NOT\n * regenerated here — refresh a target's mip chain explicitly via\n * {@link generateRenderTargetMipMaps} after rendering into it.\n *\n * @param engine - The engine.\n * @param rt - The render target to draw into, or `null` for the canvas.\n */\nexport function bindRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (rt !== null && rt._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const fb = rt === null ? null : rt._framebuffer;\n if (s.boundFramebuffer !== fb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n }\n engine._currentRenderTarget = rt;\n if (rt === null) {\n setViewportCached(engine, 0, 0, engine.canvas.width, engine.canvas.height);\n } else {\n setViewportCached(engine, 0, 0, rt.width, rt.height);\n }\n}\n\n/** Regenerate a render target's color-attachment mip chain from its (freshly\n * rendered) level-0 — mipmaps for render targets are a pure manual opt-in\n * (call this after rendering into the target). No-op for a disposed target, a\n * handle-less color attachment, or a lost/disposed context. */\nexport function generateRenderTargetMipMaps(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed || rt._disposed || rt.texture.handle === null) {\n return;\n }\n bindTextureForUpload(engine, rt.texture.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Resize the render target's color attachment (and depth/stencil renderbuffer).\n * Reallocates storage at the new size; the contents are discarded. The\n * `GLRenderTarget` / `GLTexture` identity is preserved, so consumers and\n * effect-sampler bindings holding the reference stay valid. If this target was\n * the live draw target, it is rebound (with the new-size viewport) afterwards.\n *\n * No-op when the size is unchanged or `rt` is disposed. While the context is\n * lost the new size is recorded but the GL reallocation is deferred to the\n * restore hook.\n *\n * @param engine - The engine.\n * @param rt - The render target to resize.\n * @param width - New width in texels (≥ 1).\n * @param height - New height in texels (≥ 1).\n */\nexport function resizeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget, width: number, height: number): void {\n if (rt._disposed) {\n return;\n }\n validateSize(width, height);\n if (rt.width === width && rt.height === height) {\n return;\n }\n rt.width = width;\n rt.height = height;\n rt.texture.width = width;\n rt.texture.height = height;\n if (engine._isLost || engine._disposed) {\n return;\n }\n // Capture the live binding BEFORE we delete the old FBO so we can restore it.\n const wasBound = engine._state.boundFramebuffer === rt._framebuffer && rt._framebuffer !== null;\n // For a BYO color texture, re-specify the caller's storage at the new size\n // (contents discarded, like the owned path). `_updateRaw` updates the\n // texture's tracked dims AND re-runs its upload closure — `_upload` alone\n // would re-upload at the stale ORIGINAL size, leaving the attachment a\n // different size than the FBO. An external handle without `_updateRaw` must\n // be resized by its owner; we then just rebuild the FBO around it. An owned\n // texture is recreated wholesale by allocateRenderTargetGpu.\n if (!rt._config.ownsColorTexture) {\n rt.texture._updateRaw?.(engine, null, width, height, 4);\n }\n rt._deleteGpu(engine.gl);\n allocateRenderTargetGpu(engine, rt);\n if (wasBound) {\n bindRenderTarget(engine, rt);\n }\n}\n\n/**\n * Synchronously read back a rectangle of the render target's color attachment\n * via `gl.readPixels` — the lite-gl equivalent of Babylon's\n * `_readTexturePixelsSync`. Binds the target's framebuffer (leaving it bound,\n * matching Babylon).\n *\n * The returned array element type follows the color attachment type:\n * `Uint8Array` for `UNSIGNED_BYTE`, `Float32Array` for `FLOAT`, `Uint16Array`\n * for `HALF_FLOAT`. Origin is GL bottom-left.\n *\n * @param engine - The engine.\n * @param rt - The render target to read from.\n * @param x - Lower-left X of the read rectangle, in texels.\n * @param y - Lower-left Y of the read rectangle, in texels.\n * @param width - Read rectangle width in texels.\n * @param height - Read rectangle height in texels.\n * @param into - Optional preallocated buffer (`width*height*4` elements of the\n * matching type). Reused to avoid per-call allocation.\n * @returns The pixel buffer (the provided `into`, or a freshly allocated one).\n * Empty buffer on a lost/disposed context.\n */\nexport function readRenderTargetPixels(engine: GLEngineContext, rt: GLRenderTarget, x: number, y: number, width: number, height: number, into?: ArrayBufferView): ArrayBufferView {\n const elements = width * height * 4;\n if (engine._isLost || engine._disposed || rt._disposed) {\n return into ?? new Uint8Array(0);\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.boundFramebuffer !== rt._framebuffer) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, rt._framebuffer);\n s.boundFramebuffer = rt._framebuffer;\n }\n const type = rt._config.type;\n let buffer = into;\n if (buffer === undefined) {\n buffer = type === gl.FLOAT ? new Float32Array(elements) : type === gl.HALF_FLOAT ? new Uint16Array(elements) : new Uint8Array(elements);\n }\n gl.readPixels(x, y, width, height, gl.RGBA, type, buffer);\n return buffer;\n}\n\n/**\n * Release the render target's framebuffer, depth/stencil renderbuffer and (iff\n * owned) color texture, and unregister it from the engine. Idempotent, and a\n * no-op for `null`/`undefined` (so an optional target can be released\n * unconditionally). Clears the bound-framebuffer cache if it pointed at this\n * target, and any sampler slot that held the color texture handle.\n *\n * A BYO {@link GLRenderTargetOptions.colorTexture} is NOT disposed here — it is\n * engine-managed and the caller owns its lifetime.\n *\n * @param engine - The engine.\n * @param rt - The render target to dispose, or `null`/`undefined` for a no-op.\n */\nexport function disposeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null | undefined): void {\n if (rt === null || rt === undefined || rt._disposed) {\n return;\n }\n rt._disposed = true;\n // Only the owned color texture is marked disposed here; a BYO texture stays\n // live for its caller-owner.\n if (rt._config.ownsColorTexture) {\n rt.texture._disposed = true;\n }\n if (engine._currentRenderTarget === rt) {\n engine._currentRenderTarget = null;\n }\n const i = engine._renderTargets.indexOf(rt);\n if (i !== -1) {\n engine._renderTargets.splice(i, 1);\n }\n // Capture the handle before _deleteGpu nulls it (owned case).\n const handle = rt.texture.handle;\n if (!engine._isLost && !engine._disposed) {\n rt._deleteGpu(engine.gl);\n } else {\n rt._framebuffer = null;\n rt._depthStencil = null;\n }\n if (handle !== null) {\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === handle) {\n bound[u] = null;\n }\n }\n }\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Shared private constructor. Validates size, resolves the config (given the\n * exact sized `internalFormat` by the caller — NO format-table lookup), wires\n * the owned-or-BYO color texture, allocates the GPU set atomically, and\n * registers the target. */\nfunction buildRT(engine: GLEngineContext, options: GLRenderTargetOptions, internalFormat: GLenum, format: GLenum, type: GLenum): GLRenderTarget {\n const width = options.width;\n const height = options.height;\n validateSize(width, height);\n const gl = engine.gl;\n const byo = options.colorTexture;\n const config: ResolvedRTConfig = {\n internalFormat,\n format,\n type,\n hasDepth: options.generateDepthBuffer ?? false,\n minFilter: options.minFilter ?? LINEAR,\n magFilter: options.magFilter ?? LINEAR,\n wrapS: options.wrapS ?? CLAMP_TO_EDGE,\n wrapT: options.wrapT ?? CLAMP_TO_EDGE,\n ownsColorTexture: byo === undefined,\n };\n\n const texture: GLTexture = byo ?? {\n handle: null as unknown as WebGLTexture,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n // Owned-by-RT: its storage is (re)allocated by allocateRenderTargetGpu,\n // never via the engine `_textures` replay (it is NOT registered there).\n _upload: () => {},\n _wasReady: false,\n };\n\n const rt: GLRenderTarget = {\n texture,\n width,\n height,\n isReady: false,\n _framebuffer: null,\n _depthStencil: null,\n _rebuildDepthStencil: undefined,\n _config: config,\n _disposed: false,\n _deleteGpu: () => {},\n _restore: () => {},\n };\n\n rt._deleteGpu = (glc: WebGL2RenderingContext): void => {\n const s = engine._state;\n if (rt._framebuffer !== null) {\n // Deleting the bound FBO reverts GL to framebuffer 0 (spec) — just\n // reset the cache, no explicit rebind needed.\n if (s.boundFramebuffer === rt._framebuffer) {\n s.boundFramebuffer = null;\n }\n glc.deleteFramebuffer(rt._framebuffer);\n rt._framebuffer = null;\n }\n if (rt._depthStencil !== null) {\n glc.deleteRenderbuffer(rt._depthStencil);\n rt._depthStencil = null;\n }\n // Never delete a BYO color texture — the caller-owner manages it.\n if (config.ownsColorTexture && rt.texture.handle !== null) {\n glc.deleteTexture(rt.texture.handle);\n rt.texture.handle = null as unknown as WebGLTexture;\n }\n rt.texture.isReady = false;\n rt.isReady = false;\n };\n\n rt._restore = (target: GLEngineContext): void => {\n // Resilient: a restore failure must not break the engine's restore loop.\n try {\n allocateRenderTargetGpu(target, rt);\n } catch (err) {\n console.error(\"lite-gl: render target restore failed\", err);\n }\n };\n\n allocateRenderTargetGpu(engine, rt);\n engine._renderTargets.push(rt);\n return rt;\n}\n\n/** Downgrade a requested float/half-float color type to the best renderable\n * type the engine supports, mirroring Babylon's `getTextureType`. */\nfunction resolveColorType(engine: GLEngineContext, type: GLenum): GLenum {\n const gl = engine.gl;\n if (type === FLOAT && !engine.caps.textureFloatRender) {\n return engine.caps.textureHalfFloatRender ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n }\n if (type === HALF_FLOAT && !engine.caps.textureHalfFloatRender) {\n return gl.UNSIGNED_BYTE;\n }\n return type;\n}\n\n/** Validate a render-target size is a pair of positive integers. */\nfunction validateSize(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1) {\n throw new Error(`lite-gl: render target size must be positive integers, got ${width}x${height}`);\n }\n}\n\n/**\n * (Re)allocate the color texture (iff owned), framebuffer and depth/stencil\n * renderbuffer into fresh handles, attach them, and validate completeness.\n * Shared by create / resize / context-restore. No-op on a lost/disposed context.\n *\n * ATOMIC: captures the previously-bound framebuffer and restores it in a\n * `finally`; on any failure deletes the partial FBO / renderbuffer (and the\n * owned color texture it created), nulls the fields, and rethrows — so a failed\n * build never leaks a GPU handle nor leaves a half-attached framebuffer bound.\n */\nfunction allocateRenderTargetGpu(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const c = rt._config;\n const prevFb = s.boundFramebuffer;\n let createdTexture: WebGLTexture | null = null;\n let fb: WebGLFramebuffer | null = null;\n let rb: WebGLRenderbuffer | null = null;\n try {\n // ── Color texture (owned only) ───────────────────────────────────────\n if (c.ownsColorTexture) {\n const texHandle = gl.createTexture();\n if (texHandle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null (render target color)\");\n }\n createdTexture = texHandle;\n rt.texture.handle = texHandle;\n bindTextureForUpload(engine, texHandle);\n gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, c.minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, c.magFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, c.wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, c.wrapT);\n rt.texture.isReady = true;\n rt.texture._wasReady = true;\n }\n\n // ── Framebuffer + attachments ────────────────────────────────────────\n fb = gl.createFramebuffer();\n if (fb === null) {\n throw new Error(\"lite-gl: gl.createFramebuffer returned null\");\n }\n rt._framebuffer = fb;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rt.texture.handle, 0);\n\n // ── Depth (core, DEPTH-ONLY) ─────────────────────────────────────────\n // The core only ever builds a DEPTH_COMPONENT16 depth buffer. Stencil /\n // packed depth-stencil is an opt-in installed by\n // `generateRenderTargetStencil` (`@babylonjs/lite-gl`),\n // which sets `_rebuildDepthStencil` to a closure that REPLACES the\n // depth-only buffer below with its own packed/stencil renderbuffer. That\n // hook is re-run here on every rebuild (create / resize / context-restore)\n // so a helper-added stencil attachment survives at the new size.\n rt._depthStencil = null;\n if (c.hasDepth) {\n rb = gl.createRenderbuffer();\n if (rb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null\");\n }\n gl.bindRenderbuffer(gl.RENDERBUFFER, rb);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rt.width, rt.height);\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);\n gl.bindRenderbuffer(gl.RENDERBUFFER, null);\n rt._depthStencil = rb;\n }\n // A helper-attached stencil replaces/augments the depth-only buffer.\n rt._rebuildDepthStencil?.(engine);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete (status 0x${status.toString(16)})`);\n }\n rt.isReady = true;\n } catch (e) {\n // Free whatever depth/stencil renderbuffer is currently attached. After a\n // `_rebuildDepthStencil` hook ran, `rt._depthStencil` may be a packed buffer\n // the hook swapped in (it deletes the core `rb` itself on success), so free\n // the live `rt._depthStencil` rather than the stale local `rb`.\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = null;\n if (fb !== null) {\n gl.deleteFramebuffer(fb);\n }\n rt._framebuffer = null;\n // Delete ONLY a texture we created here (owned). Never a BYO texture.\n if (createdTexture !== null) {\n gl.deleteTexture(createdTexture);\n rt.texture.handle = null as unknown as WebGLTexture;\n rt.texture.isReady = false;\n }\n rt.isReady = false;\n throw e;\n } finally {\n // Restore the previously-bound draw target — creation/restore must not\n // silently redirect subsequent draws.\n if (s.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFb);\n s.boundFramebuffer = prevFb;\n }\n }\n}\n\n/** Inline cached `gl.viewport` — kept local so the render-target module has\n * no runtime dependency on the effect-renderer module. */\nfunction setViewportCached(engine: GLEngineContext, x: number, y: number, w: number, h: number): void {\n const s = engine._state;\n if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {\n return;\n }\n s.viewportX = x;\n s.viewportY = y;\n s.viewportW = w;\n s.viewportH = h;\n engine.gl.viewport(x, y, w, h);\n}\n"]}
1
+ {"version":3,"file":"render-target.js","sourceRoot":"","sources":["../src/render-target.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Render-to-texture (offscreen framebuffer) support.\n *\n * Part of the public API via the `@babylonjs/lite-gl` barrel. The package is\n * `sideEffects: false`, so consumers that only render fullscreen effects to the\n * canvas tree-shake the FBO code out.\n *\n * This is the lite-gl equivalent of Babylon's `RenderTargetWrapper` +\n * `ThinEngine.createRenderTargetTexture` / `bindFramebuffer` /\n * `restoreDefaultFramebuffer` / `_readTexturePixelsSync`. A render target owns a\n * color {@link GLTexture} (or attaches a caller-supplied one) plus an optional\n * depth and/or stencil renderbuffer, all wrapped in a single\n * `WebGLFramebuffer`.\n *\n * The default {@link createRenderTarget} makes an **RGBA8** color target and\n * ships none of the HDR sized-format knowledge; {@link createFloatRenderTarget}\n * is the separate opt-in for float / half-float color attachments (it alone\n * carries the `RGBA16F` / `RGBA32F` table, so RGBA8 consumers tree-shake it\n * away).\n *\n * The full color/depth/stencil GPU set is rebuilt automatically on\n * `webglcontextrestored` — the render target registers itself with the engine's\n * `_renderTargets` registry, and the context-restore protocol calls its\n * `_restore` closure AFTER the standalone texture replay. A caller-supplied\n * (BYO) color texture lives in the engine's `_textures` registry and is restored\n * there first; the RT then re-attaches its freshly-swapped handle.\n */\nimport { bindTextureForUpload, pickSizedInternalFormat, setBoundTextureParams, type GLTexture } from \"./texture.js\";\nimport type { GLEngineContext } from \"./context.js\";\n\n/** GL `gl.UNSIGNED_BYTE` — the default (RGBA8) color attachment type. */\nconst UNSIGNED_BYTE = 0x1401;\n/** GL `gl.HALF_FLOAT`. */\nconst HALF_FLOAT = 0x140b;\n/** GL `gl.FLOAT`. */\nconst FLOAT = 0x1406;\n/** GL `gl.RGBA`. */\nconst RGBA = 0x1908;\n/** GL `gl.RGBA8` — the default sized internalFormat. */\nconst RGBA8 = 0x8058;\n/** GL `gl.LINEAR`. */\nconst LINEAR = 0x2601;\n/** GL `gl.CLAMP_TO_EDGE`. */\nconst CLAMP_TO_EDGE = 0x812f;\n\n/** Options for {@link createRenderTarget}. `width`/`height` are required; every\n * other field has a Babylon-matching default. The bare\n * `createRenderTarget(engine, { width, height })` makes an RGBA8 color-only\n * target with linear filtering and clamp wrapping. */\nexport interface GLRenderTargetOptions {\n /** Color attachment width in texels. Must be a positive integer. */\n width: number;\n /** Color attachment height in texels. Must be a positive integer. */\n height: number;\n /** Allocate a depth renderbuffer (`DEPTH_COMPONENT16`). Default `false`.\n * Stencil is NOT a create option — opt in (packed depth+stencil, or\n * stencil-only) via `generateRenderTargetStencil`\n * (`@babylonjs/lite-gl`), which keeps the stencil/packed\n * renderbuffer code out of the render-target core bundle. */\n generateDepthBuffer?: boolean;\n /** Color texture minification filter. Default `gl.LINEAR`. */\n minFilter?: GLenum;\n /** Color texture magnification filter. Default `gl.LINEAR`. */\n magFilter?: GLenum;\n /** Color texture S wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapS?: GLenum;\n /** Color texture T wrap. Default `gl.CLAMP_TO_EDGE`. */\n wrapT?: GLenum;\n /** Attach a caller-supplied (BYO) color {@link GLTexture} instead of creating\n * one. When supplied the render target does NOT own or restore it — the\n * texture is engine-managed (restored by the standard texture-restore path\n * first) and the RT re-attaches its swapped handle afterwards. The caller is\n * responsible for sizing it to `width`×`height` and for disposing it. */\n colorTexture?: GLTexture;\n}\n\n/** Options for {@link createFloatRenderTarget} — {@link GLRenderTargetOptions}\n * plus the float color `type`. */\nexport interface GLFloatRenderTargetOptions extends GLRenderTargetOptions {\n /** Float color attachment type. Default `gl.HALF_FLOAT`. Pass `gl.FLOAT` for\n * full 32-bit. Downgraded to the best renderable type the engine supports\n * (`caps.textureFloatRender` / `caps.textureHalfFloatRender`), mirroring\n * Babylon's `getTextureType`. */\n type?: GLenum;\n}\n\n/** Resolved (defaults-applied) attachment description, retained on the render\n * target so `webglcontextrestored` can rebuild the exact same GPU set. */\ninterface ResolvedRTConfig {\n internalFormat: GLenum;\n format: GLenum;\n type: GLenum;\n hasDepth: boolean;\n minFilter: GLenum;\n magFilter: GLenum;\n wrapS: GLenum;\n wrapT: GLenum;\n /** True when the RT created (and therefore owns/restores/deletes) its color\n * texture; false for a BYO {@link GLRenderTargetOptions.colorTexture}. */\n ownsColorTexture: boolean;\n}\n\n/**\n * An offscreen render target — a `WebGLFramebuffer` wrapping a color\n * {@link GLTexture} and an optional depth / stencil renderbuffer. The lite-gl\n * counterpart of Babylon's `RenderTargetWrapper`.\n */\nexport interface GLRenderTarget {\n /** The color attachment, sampleable like any other {@link GLTexture}\n * (`setEffectTexture` / `bindTexture`). For an owned attachment its handle\n * is swapped on `webglcontextrestored` while consumers keep this same\n * reference. */\n texture: GLTexture;\n /** Color attachment width in texels. */\n width: number;\n /** Color attachment height in texels. */\n height: number;\n /** True once the color attachment + framebuffer are allocated. */\n isReady: boolean;\n /** @internal The framebuffer object. Swapped on context-restore. */\n _framebuffer: WebGLFramebuffer | null;\n /** @internal Depth-only (`DEPTH_COMPONENT16`) renderbuffer built by the core,\n * OR the packed/stencil renderbuffer installed by `generateRenderTargetStencil`\n * — a single field either way. Null when neither depth nor stencil is used. */\n _depthStencil: WebGLRenderbuffer | null;\n /**\n * @internal Optional stencil rebuild hook installed by\n * `generateRenderTargetStencil` (`@babylonjs/lite-gl`). When\n * present it OWNS the depth/stencil renderbuffer (replacing the core\n * depth-only buffer) and is re-invoked after every FBO rebuild\n * (create-via-helper, resize, context-restore) so the attachment survives.\n */\n _rebuildDepthStencil?: (engine: GLEngineContext) => void;\n /** @internal Resolved attachment config, for context-restore rebuild. */\n _config: ResolvedRTConfig;\n /** @internal */\n _disposed: boolean;\n /** @internal Delete every GPU object the target owns (FBO, renderbuffer, and\n * the color texture iff owned). Resets the bound-framebuffer cache if it\n * pointed at this target. Called by `disposeRenderTarget`, `resizeRenderTarget`\n * and engine dispose. */\n _deleteGpu: (gl: WebGL2RenderingContext) => void;\n /** @internal Rebuild the FBO + renderbuffer (+ owned color texture) into\n * fresh handles after `webglcontextrestored`. */\n _restore: (engine: GLEngineContext) => void;\n}\n\n/**\n * Create an offscreen **RGBA8** render target.\n *\n * The color attachment is an owned {@link GLTexture} (rebuilt by this target's\n * own restore hook), unless {@link GLRenderTargetOptions.colorTexture} supplies a\n * caller-managed (BYO) one. Mirrors Babylon's `createRenderTargetTexture`.\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLRenderTargetOptions} (`width`/`height` required).\n * @returns The new {@link GLRenderTarget}.\n * @throws If `width`/`height` are not positive integers, a GL handle could not\n * be allocated, or the resulting framebuffer is not complete. On failure every\n * partial GPU object (including an owned color texture) is released first.\n */\nexport function createRenderTarget(engine: GLEngineContext, options: GLRenderTargetOptions): GLRenderTarget {\n return buildRT(engine, options, RGBA8, RGBA, UNSIGNED_BYTE);\n}\n\n/**\n * Create an offscreen **float / half-float** render target — the HDR opt-in\n * counterpart of {@link createRenderTarget}. This is the only render-target\n * factory that references the `RGBA16F` / `RGBA32F` sized-format table, so RGBA8\n * consumers ship none of it.\n *\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The requested type is downgraded to the best renderable type the engine\n * supports (mirroring Babylon's `getTextureType`).\n *\n * @param engine - The engine to allocate GL resources on.\n * @param options - See {@link GLFloatRenderTargetOptions}.\n * @returns The new {@link GLRenderTarget}.\n * @throws As {@link createRenderTarget}.\n */\nexport function createFloatRenderTarget(engine: GLEngineContext, options: GLFloatRenderTargetOptions): GLRenderTarget {\n const type = resolveColorType(engine, options.type ?? HALF_FLOAT);\n const internalFormat = pickSizedInternalFormat(engine.gl, RGBA, type);\n return buildRT(engine, options, internalFormat, RGBA, type);\n}\n\n/**\n * Bind the render target's framebuffer as the draw target and set the viewport\n * to cover it. `rt = null` binds the default (canvas) framebuffer and resets the\n * viewport to the full canvas — the counterpart of Babylon's\n * `restoreDefaultFramebuffer`. Subsequent `drawEffect` / `drawIndexed` /\n * `clearEngine` calls write into the bound target.\n *\n * Cached. No-op on a lost/disposed context or a disposed `rt`. Mipmaps are NOT\n * regenerated here — refresh a target's mip chain explicitly via\n * {@link generateRenderTargetMipMaps} after rendering into it.\n *\n * @param engine - The engine.\n * @param rt - The render target to draw into, or `null` for the canvas.\n */\nexport function bindRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (rt !== null && rt._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const fb = rt === null ? null : rt._framebuffer;\n if (s.boundFramebuffer !== fb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n }\n engine._currentRenderTarget = rt;\n if (rt === null) {\n setViewportCached(engine, 0, 0, engine.canvas.width, engine.canvas.height);\n } else {\n setViewportCached(engine, 0, 0, rt.width, rt.height);\n }\n}\n\n/** Regenerate a render target's color-attachment mip chain from its (freshly\n * rendered) level-0 — mipmaps for render targets are a pure manual opt-in\n * (call this after rendering into the target). No-op for a disposed target, a\n * handle-less color attachment, or a lost/disposed context. */\nexport function generateRenderTargetMipMaps(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed || rt._disposed || rt.texture.handle === null) {\n return;\n }\n bindTextureForUpload(engine, rt.texture.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Resize the render target's color attachment (and depth/stencil renderbuffer).\n * Reallocates storage at the new size; the contents are discarded. The\n * `GLRenderTarget` / `GLTexture` identity is preserved, so consumers and\n * effect-sampler bindings holding the reference stay valid. If this target was\n * the live draw target, it is rebound (with the new-size viewport) afterwards.\n *\n * No-op when the size is unchanged or `rt` is disposed. While the context is\n * lost the new size is recorded but the GL reallocation is deferred to the\n * restore hook.\n *\n * @param engine - The engine.\n * @param rt - The render target to resize.\n * @param width - New width in texels (≥ 1).\n * @param height - New height in texels (≥ 1).\n */\nexport function resizeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget, width: number, height: number): void {\n if (rt._disposed) {\n return;\n }\n validateSize(width, height);\n if (rt.width === width && rt.height === height) {\n return;\n }\n rt.width = width;\n rt.height = height;\n rt.texture.width = width;\n rt.texture.height = height;\n if (engine._isLost || engine._disposed) {\n return;\n }\n // Capture the live binding BEFORE we delete the old FBO so we can restore it.\n const wasBound = engine._state.boundFramebuffer === rt._framebuffer && rt._framebuffer !== null;\n // For a BYO color texture, re-specify the caller's storage at the new size\n // (contents discarded, like the owned path). `_updateRaw` updates the\n // texture's tracked dims AND re-runs its upload closure — `_upload` alone\n // would re-upload at the stale ORIGINAL size, leaving the attachment a\n // different size than the FBO. An external handle without `_updateRaw` must\n // be resized by its owner; we then just rebuild the FBO around it. An owned\n // texture is recreated wholesale by allocateRenderTargetGpu.\n if (!rt._config.ownsColorTexture) {\n rt.texture._updateRaw?.(engine, null, width, height, 4);\n }\n rt._deleteGpu(engine.gl);\n allocateRenderTargetGpu(engine, rt);\n if (wasBound) {\n bindRenderTarget(engine, rt);\n }\n}\n\n/**\n * Synchronously read back a rectangle of the render target's color attachment\n * via `gl.readPixels` — the lite-gl equivalent of Babylon's\n * `_readTexturePixelsSync`. Binds the target's framebuffer (leaving it bound,\n * matching Babylon).\n *\n * The returned array element type follows the color attachment type:\n * `Uint8Array` for `UNSIGNED_BYTE`, `Float32Array` for `FLOAT`, `Uint16Array`\n * for `HALF_FLOAT`. Origin is GL bottom-left.\n *\n * @param engine - The engine.\n * @param rt - The render target to read from.\n * @param x - Lower-left X of the read rectangle, in texels.\n * @param y - Lower-left Y of the read rectangle, in texels.\n * @param width - Read rectangle width in texels.\n * @param height - Read rectangle height in texels.\n * @param into - Optional preallocated buffer (`width*height*4` elements of the\n * matching type). Reused to avoid per-call allocation.\n * @returns The pixel buffer (the provided `into`, or a freshly allocated one).\n * Empty buffer on a lost/disposed context.\n */\nexport function readRenderTargetPixels(engine: GLEngineContext, rt: GLRenderTarget, x: number, y: number, width: number, height: number, into?: ArrayBufferView): ArrayBufferView {\n const elements = width * height * 4;\n if (engine._isLost || engine._disposed || rt._disposed) {\n return into ?? new Uint8Array(0);\n }\n const gl = engine.gl;\n const s = engine._state;\n if (s.boundFramebuffer !== rt._framebuffer) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, rt._framebuffer);\n s.boundFramebuffer = rt._framebuffer;\n }\n const type = rt._config.type;\n let buffer = into;\n if (buffer === undefined) {\n buffer = type === gl.FLOAT ? new Float32Array(elements) : type === gl.HALF_FLOAT ? new Uint16Array(elements) : new Uint8Array(elements);\n }\n gl.readPixels(x, y, width, height, gl.RGBA, type, buffer);\n return buffer;\n}\n\n/**\n * Release the render target's framebuffer, depth/stencil renderbuffer and (iff\n * owned) color texture, and unregister it from the engine. Idempotent, and a\n * no-op for `null`/`undefined` (so an optional target can be released\n * unconditionally). Clears the bound-framebuffer cache if it pointed at this\n * target, and any sampler slot that held the color texture handle.\n *\n * A BYO {@link GLRenderTargetOptions.colorTexture} is NOT disposed here — it is\n * engine-managed and the caller owns its lifetime.\n *\n * @param engine - The engine.\n * @param rt - The render target to dispose, or `null`/`undefined` for a no-op.\n */\nexport function disposeRenderTarget(engine: GLEngineContext, rt: GLRenderTarget | null | undefined): void {\n if (rt === null || rt === undefined || rt._disposed) {\n return;\n }\n rt._disposed = true;\n // Only the owned color texture is marked disposed here; a BYO texture stays\n // live for its caller-owner.\n if (rt._config.ownsColorTexture) {\n rt.texture._disposed = true;\n }\n if (engine._currentRenderTarget === rt) {\n engine._currentRenderTarget = null;\n }\n const i = engine._renderTargets.indexOf(rt);\n if (i !== -1) {\n engine._renderTargets.splice(i, 1);\n }\n // Capture the handle before _deleteGpu nulls it (owned case).\n const handle = rt.texture.handle;\n if (!engine._isLost && !engine._disposed) {\n rt._deleteGpu(engine.gl);\n } else {\n rt._framebuffer = null;\n rt._depthStencil = null;\n }\n if (handle !== null) {\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === handle) {\n bound[u] = null;\n }\n }\n }\n}\n\n/* ──────────────────────────── internal helpers ──────────────────────────── */\n\n/** Shared private constructor. Validates size, resolves the config (given the\n * exact sized `internalFormat` by the caller — NO format-table lookup), wires\n * the owned-or-BYO color texture, allocates the GPU set atomically, and\n * registers the target. */\nfunction buildRT(engine: GLEngineContext, options: GLRenderTargetOptions, internalFormat: GLenum, format: GLenum, type: GLenum): GLRenderTarget {\n const width = options.width;\n const height = options.height;\n validateSize(width, height);\n const gl = engine.gl;\n const byo = options.colorTexture;\n const config: ResolvedRTConfig = {\n internalFormat,\n format,\n type,\n hasDepth: options.generateDepthBuffer ?? false,\n minFilter: options.minFilter ?? LINEAR,\n magFilter: options.magFilter ?? LINEAR,\n wrapS: options.wrapS ?? CLAMP_TO_EDGE,\n wrapT: options.wrapT ?? CLAMP_TO_EDGE,\n ownsColorTexture: byo === undefined,\n };\n\n const texture: GLTexture = byo ?? {\n handle: null as unknown as WebGLTexture,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n // Owned-by-RT: its storage is (re)allocated by allocateRenderTargetGpu,\n // never via the engine `_textures` replay (it is NOT registered there).\n _upload: () => {},\n _wasReady: false,\n };\n\n const rt: GLRenderTarget = {\n texture,\n width,\n height,\n isReady: false,\n _framebuffer: null,\n _depthStencil: null,\n _rebuildDepthStencil: undefined,\n _config: config,\n _disposed: false,\n _deleteGpu: () => {},\n _restore: () => {},\n };\n\n rt._deleteGpu = (glc: WebGL2RenderingContext): void => {\n const s = engine._state;\n if (rt._framebuffer !== null) {\n // Deleting the bound FBO reverts GL to framebuffer 0 (spec) — just\n // reset the cache, no explicit rebind needed.\n if (s.boundFramebuffer === rt._framebuffer) {\n s.boundFramebuffer = null;\n }\n glc.deleteFramebuffer(rt._framebuffer);\n rt._framebuffer = null;\n }\n if (rt._depthStencil !== null) {\n glc.deleteRenderbuffer(rt._depthStencil);\n rt._depthStencil = null;\n }\n // Never delete a BYO color texture — the caller-owner manages it.\n if (config.ownsColorTexture && rt.texture.handle !== null) {\n glc.deleteTexture(rt.texture.handle);\n rt.texture.handle = null as unknown as WebGLTexture;\n }\n rt.texture.isReady = false;\n rt.isReady = false;\n };\n\n rt._restore = (target: GLEngineContext): void => {\n // Resilient: a restore failure must not break the engine's restore loop.\n try {\n allocateRenderTargetGpu(target, rt);\n } catch (err) {\n console.error(\"lite-gl: render target restore failed\", err);\n }\n };\n\n allocateRenderTargetGpu(engine, rt);\n engine._renderTargets.push(rt);\n return rt;\n}\n\n/** Downgrade a requested float/half-float color type to the best renderable\n * type the engine supports, mirroring Babylon's `getTextureType`. */\nfunction resolveColorType(engine: GLEngineContext, type: GLenum): GLenum {\n const gl = engine.gl;\n if (type === FLOAT && !engine.caps.textureFloatRender) {\n return engine.caps.textureHalfFloatRender ? gl.HALF_FLOAT : gl.UNSIGNED_BYTE;\n }\n if (type === HALF_FLOAT && !engine.caps.textureHalfFloatRender) {\n return gl.UNSIGNED_BYTE;\n }\n return type;\n}\n\n/** Validate a render-target size is a pair of positive integers. */\nfunction validateSize(width: number, height: number): void {\n if (!Number.isInteger(width) || !Number.isInteger(height) || width < 1 || height < 1) {\n throw new Error(`lite-gl: render target size must be positive integers, got ${width}x${height}`);\n }\n}\n\n/**\n * (Re)allocate the color texture (iff owned), framebuffer and depth/stencil\n * renderbuffer into fresh handles, attach them, and validate completeness.\n * Shared by create / resize / context-restore. No-op on a lost/disposed context.\n *\n * ATOMIC: captures the previously-bound framebuffer and restores it in a\n * `finally`; on any failure deletes the partial FBO / renderbuffer (and the\n * owned color texture it created), nulls the fields, and rethrows — so a failed\n * build never leaks a GPU handle nor leaves a half-attached framebuffer bound.\n */\nfunction allocateRenderTargetGpu(engine: GLEngineContext, rt: GLRenderTarget): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n const gl = engine.gl;\n const s = engine._state;\n const c = rt._config;\n const prevFb = s.boundFramebuffer;\n let createdTexture: WebGLTexture | null = null;\n let fb: WebGLFramebuffer | null = null;\n let rb: WebGLRenderbuffer | null = null;\n try {\n // ── Color texture (owned only) ───────────────────────────────────────\n if (c.ownsColorTexture) {\n const texHandle = gl.createTexture();\n if (texHandle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null (render target color)\");\n }\n createdTexture = texHandle;\n rt.texture.handle = texHandle;\n bindTextureForUpload(engine, texHandle);\n gl.texImage2D(gl.TEXTURE_2D, 0, c.internalFormat, rt.width, rt.height, 0, c.format, c.type, null);\n setBoundTextureParams(gl, c.minFilter, c.magFilter, c.wrapS, c.wrapT);\n rt.texture.isReady = true;\n rt.texture._wasReady = true;\n }\n\n // ── Framebuffer + attachments ────────────────────────────────────────\n fb = gl.createFramebuffer();\n if (fb === null) {\n throw new Error(\"lite-gl: gl.createFramebuffer returned null\");\n }\n rt._framebuffer = fb;\n gl.bindFramebuffer(gl.FRAMEBUFFER, fb);\n s.boundFramebuffer = fb;\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, rt.texture.handle, 0);\n\n // ── Depth (core, DEPTH-ONLY) ─────────────────────────────────────────\n // The core only ever builds a DEPTH_COMPONENT16 depth buffer. Stencil /\n // packed depth-stencil is an opt-in installed by\n // `generateRenderTargetStencil` (`@babylonjs/lite-gl`),\n // which sets `_rebuildDepthStencil` to a closure that REPLACES the\n // depth-only buffer below with its own packed/stencil renderbuffer. That\n // hook is re-run here on every rebuild (create / resize / context-restore)\n // so a helper-added stencil attachment survives at the new size.\n rt._depthStencil = null;\n if (c.hasDepth) {\n rb = gl.createRenderbuffer();\n if (rb === null) {\n throw new Error(\"lite-gl: gl.createRenderbuffer returned null\");\n }\n gl.bindRenderbuffer(gl.RENDERBUFFER, rb);\n gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, rt.width, rt.height);\n gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);\n gl.bindRenderbuffer(gl.RENDERBUFFER, null);\n rt._depthStencil = rb;\n }\n // A helper-attached stencil replaces/augments the depth-only buffer.\n rt._rebuildDepthStencil?.(engine);\n\n const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);\n if (status !== gl.FRAMEBUFFER_COMPLETE) {\n throw new Error(`lite-gl: render target framebuffer incomplete (status 0x${status.toString(16)})`);\n }\n rt.isReady = true;\n } catch (e) {\n // Free whatever depth/stencil renderbuffer is currently attached. After a\n // `_rebuildDepthStencil` hook ran, `rt._depthStencil` may be a packed buffer\n // the hook swapped in (it deletes the core `rb` itself on success), so free\n // the live `rt._depthStencil` rather than the stale local `rb`.\n if (rt._depthStencil !== null) {\n gl.deleteRenderbuffer(rt._depthStencil);\n }\n rt._depthStencil = null;\n if (fb !== null) {\n gl.deleteFramebuffer(fb);\n }\n rt._framebuffer = null;\n // Delete ONLY a texture we created here (owned). Never a BYO texture.\n if (createdTexture !== null) {\n gl.deleteTexture(createdTexture);\n rt.texture.handle = null as unknown as WebGLTexture;\n rt.texture.isReady = false;\n }\n rt.isReady = false;\n throw e;\n } finally {\n // Restore the previously-bound draw target — creation/restore must not\n // silently redirect subsequent draws.\n if (s.boundFramebuffer !== prevFb) {\n gl.bindFramebuffer(gl.FRAMEBUFFER, prevFb);\n s.boundFramebuffer = prevFb;\n }\n }\n}\n\n/** Inline cached `gl.viewport` — kept local so the render-target module has\n * no runtime dependency on the effect-renderer module. */\nfunction setViewportCached(engine: GLEngineContext, x: number, y: number, w: number, h: number): void {\n const s = engine._state;\n if (s.viewportX === x && s.viewportY === y && s.viewportW === w && s.viewportH === h) {\n return;\n }\n s.viewportX = x;\n s.viewportY = y;\n s.viewportW = w;\n s.viewportH = h;\n engine.gl.viewport(x, y, w, h);\n}\n"]}
package/texture.js CHANGED
@@ -23,6 +23,13 @@ export function setUnpackState(engine, flipY, premultiplyAlpha, alignment = 4) {
23
23
  s.unpackAlignment = alignment;
24
24
  }
25
25
  }
26
+ /** Apply sampling and wrap state to the texture currently bound for upload. @internal */
27
+ export function setBoundTextureParams(gl, minFilter, magFilter, wrapS, wrapT) {
28
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
29
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);
30
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);
31
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);
32
+ }
26
33
  /** Uint8 / float raw texture upload. The pixel data can be replaced later via
27
34
  * {@link updateRawTexture}; the sampling and wrap can be changed via
28
35
  * {@link updateTextureSamplingMode} / {@link updateTextureWrapMode}. */
@@ -56,10 +63,9 @@ export function createRawTexture(engine, data, width, height, format, type, opti
56
63
  setUnpackState(target, invertY, premultiply, curAlign);
57
64
  bindTextureForUpload(target, tex.handle);
58
65
  g.texImage2D(g.TEXTURE_2D, 0, internalFormat, curWidth, curHeight, 0, format, type, curData);
59
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
60
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
61
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
62
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
66
+ };
67
+ const initializeParameters = (target) => {
68
+ setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);
63
69
  };
64
70
  const tex = {
65
71
  handle,
@@ -70,6 +76,7 @@ export function createRawTexture(engine, data, width, height, format, type, opti
70
76
  _disposed: false,
71
77
  _refCount: 1,
72
78
  _upload: upload,
79
+ _initializeParameters: initializeParameters,
73
80
  _wasReady: true,
74
81
  };
75
82
  tex._updateRaw = (target, newData, newWidth, newHeight, unpackAlignment) => {
@@ -82,6 +89,7 @@ export function createRawTexture(engine, data, width, height, format, type, opti
82
89
  upload(target);
83
90
  };
84
91
  upload(engine);
92
+ initializeParameters(engine);
85
93
  engine._textures.push(tex);
86
94
  return tex;
87
95
  }
@@ -200,10 +208,7 @@ export function createTextureFromHandle(engine, handle, width, height, options)
200
208
  if (options !== undefined) {
201
209
  const gl = engine.gl;
202
210
  bindTextureForUpload(engine, handle);
203
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, options.minFilter ?? gl.LINEAR);
204
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, options.magFilter ?? gl.LINEAR);
205
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, options.wrapS ?? gl.CLAMP_TO_EDGE);
206
- gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, options.wrapT ?? gl.CLAMP_TO_EDGE);
211
+ setBoundTextureParams(gl, options.minFilter ?? gl.LINEAR, options.magFilter ?? gl.LINEAR, options.wrapS ?? gl.CLAMP_TO_EDGE, options.wrapT ?? gl.CLAMP_TO_EDGE);
207
212
  }
208
213
  return tex;
209
214
  }
@@ -240,10 +245,9 @@ export function loadTexture2D(engine, url, options, onLoad, onError) {
240
245
  else {
241
246
  g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, 1, 1, 0, g.RGBA, g.UNSIGNED_BYTE, placeholderPixels);
242
247
  }
243
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);
244
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);
245
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);
246
- g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);
248
+ };
249
+ const initializeParameters = (target) => {
250
+ setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);
247
251
  };
248
252
  const tex = {
249
253
  handle,
@@ -254,10 +258,12 @@ export function loadTexture2D(engine, url, options, onLoad, onError) {
254
258
  _disposed: false,
255
259
  _refCount: 1,
256
260
  _upload: upload,
261
+ _initializeParameters: initializeParameters,
257
262
  _wasReady: false,
258
263
  };
259
264
  // Placeholder upload — makes the texture sampleable before the real image arrives.
260
265
  upload(engine);
266
+ initializeParameters(engine);
261
267
  engine._textures.push(tex);
262
268
  // Fetch + decode the real image. Re-uploads via the same closure once the
263
269
  // bitmap is in hand (so context-restore replay sees the real image too).
package/texture.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"texture.js","sourceRoot":"","sources":["../src/texture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GLEngineContext } from \"./context.js\";\n\n/** Texture sampling / wrap options. All have GL-spec defaults. Mipmaps are NOT\n * a create option — generate the chain explicitly via {@link generateTextureMipMaps}. */\nexport interface GLTextureOptions {\n /** Default: false (matches Babylon's default raw-texture behaviour). */\n invertY?: boolean;\n /** Default: gl.LINEAR. */\n minFilter?: GLenum;\n /** Default: gl.LINEAR. */\n magFilter?: GLenum;\n /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`\n * (NPOT-safe in WebGL2). */\n wrapS?: GLenum;\n /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`. */\n wrapT?: GLenum;\n /** `gl.pixelStorei(UNPACK_ALIGNMENT)` for the upload (1/2/4/8). Default 4.\n * Use 1 for tightly-packed non-RGBA rows. */\n unpackAlignment?: number;\n /** Premultiply alpha at upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`). Default\n * false. */\n premultiplyAlpha?: boolean;\n /** Explicit sized internalFormat for `texImage2D`. When provided it is used\n * verbatim and the inline LDR resolver is bypassed — this is how\n * {@link createFloatTexture} injects its `RGBA16F` / `RGBA32F` choice\n * without the byte path ever referencing the float-format table (keeping it\n * tree-shakeable out of RGBA8-only bundles). Default: derived from\n * `format`/`type` via the LDR resolver. */\n internalFormat?: GLenum;\n}\n\n/**\n * Pure-state texture handle. The `handle` field is MUTABLE so the same logical\n * texture survives a `webglcontextrestored` event — every consumer keeps the\n * same `GLTexture` reference; only the internal `WebGLTexture` is swapped.\n *\n * `loadTexture2D` also uses the same handle for the 1×1 placeholder upload AND\n * the final image upload — so a `bindTexture(engine, unit, tex)` made before the\n * image has decoded remains valid once the image arrives.\n */\nexport interface GLTexture {\n /** The live `WebGLTexture`. MUTABLE — swapped for a fresh handle on\n * `webglcontextrestored` while consumers keep the same `GLTexture` reference. */\n handle: WebGLTexture;\n /** GL texture target (always `gl.TEXTURE_2D` for this package). */\n readonly target: GLenum;\n /** Texture width in texels. Updated once an async upload resolves. */\n width: number;\n /** Texture height in texels. Updated once an async upload resolves. */\n height: number;\n /** True when the texture is safe to sample with final content (placeholders\n * read as not-ready until their image/upload completes). */\n isReady: boolean;\n /** @internal */\n _disposed: boolean;\n /** @internal */\n _refCount: number;\n /**\n * Replay closure for context-restore (§4.7 of 00-lite-gl.md). Captures the\n * original upload arguments and re-issues the `gl.texImage2D` /\n * `texParameteri` sequence into the freshly-allocated `handle`. After\n * the upload completes the texture is ready iff `_isReadyAfterUpload`.\n * @internal\n */\n _upload: (engine: GLEngineContext) => void;\n /**\n * Snapshot of `isReady` captured on `webglcontextlost` so the restore\n * handler knows whether to flip it back on after `_upload`. Textures\n * that were still mid-load (e.g. `loadTexture2D` whose bitmap hadn't\n * arrived) stay not-ready; the async path will set `isReady=true` once\n * the bitmap finishes decoding into the new handle.\n * @internal\n */\n _wasReady: boolean;\n /**\n * Live re-upload hook installed by `createRawTexture` — lets\n * `updateRawTexture` replace the pixel data (and optionally the size)\n * through the same closure that the context-restore replay uses, keeping\n * restore correct. Absent on image / HTML-element / external textures.\n * @internal\n */\n _updateRaw?: (engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, unpackAlignment: number) => void;\n /**\n * Dynamic-texture source captured by `updateDynamicTexture`\n * (`@babylonjs/lite-gl`) and replayed into the fresh handle\n * on `webglcontextrestored`. Null/absent on non-dynamic textures.\n * @internal\n */\n _dynSource?: TexImageSource | null;\n /** UNPACK_FLIP_Y applied when replaying {@link GLTexture._dynSource}. @internal */\n _dynInvertY?: boolean;\n /** UNPACK_PREMULTIPLY_ALPHA applied when replaying {@link GLTexture._dynSource}. @internal */\n _dynPremultiplyAlpha?: boolean;\n /**\n * The `handle` the dynamic texture's `texParameteri` filter/wrap state was\n * last applied to. `texParameteri` is per-texture GL state that survives pixel\n * re-uploads, so the dynamic-texture `_upload` re-applies it ONLY when this no\n * longer matches `handle` — i.e. at creation and after `webglcontextrestored`\n * installs a fresh handle — not on every per-frame `updateDynamicTexture`.\n * @internal\n */\n _dynParamsHandle?: WebGLTexture | null;\n}\n\n/**\n * Apply the three `UNPACK_*` pixel-store flags through the GL-state cache,\n * eliding redundant `pixelStorei` calls. Centralising this guarantees EVERY\n * upload path sets all three explicitly, so a premultiplying / flipping upload\n * never leaks its flag into a later upload that forgot to set it.\n * @internal\n */\nexport function setUnpackState(engine: GLEngineContext, flipY: boolean, premultiplyAlpha: boolean, alignment = 4): void {\n const gl = engine.gl;\n const s = engine._state;\n const fy = flipY ? 1 : 0;\n if (s.unpackFlipY !== fy) {\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, fy);\n s.unpackFlipY = fy;\n }\n const pm = premultiplyAlpha ? 1 : 0;\n if (s.unpackPremultiplyAlpha !== pm) {\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, pm);\n s.unpackPremultiplyAlpha = pm;\n }\n if (s.unpackAlignment !== alignment) {\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);\n s.unpackAlignment = alignment;\n }\n}\n\n/** Uint8 / float raw texture upload. The pixel data can be replaced later via\n * {@link updateRawTexture}; the sampling and wrap can be changed via\n * {@link updateTextureSamplingMode} / {@link updateTextureWrapMode}. */\nexport function createRawTexture(\n engine: GLEngineContext,\n data: ArrayBufferView | null,\n width: number,\n height: number,\n format: GLenum,\n type: GLenum,\n options?: GLTextureOptions\n): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n const premultiply = opts.premultiplyAlpha ?? false;\n // LDR byte formats are resolved INLINE here; the float-format table in\n // `pickSizedInternalFormat` is deliberately NOT referenced from this path so\n // it tree-shakes out of byte-only bundles. `createFloatTexture` injects its\n // sized float format via `opts.internalFormat`.\n const internalFormat = opts.internalFormat ?? resolveLdrInternalFormat(gl, format, type);\n\n // Mutable upload state — `updateRawTexture` mutates these and re-runs\n // `upload`, so the context-restore replay (which calls the same `upload`)\n // always reproduces the latest contents.\n let curData = data;\n let curWidth = width;\n let curHeight = height;\n let curAlign = opts.unpackAlignment ?? 4;\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n setUnpackState(target, invertY, premultiply, curAlign);\n bindTextureForUpload(target, tex.handle);\n g.texImage2D(g.TEXTURE_2D, 0, internalFormat, curWidth, curHeight, 0, format, type, curData);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: true,\n };\n tex._updateRaw = (target: GLEngineContext, newData: ArrayBufferView | null, newWidth: number, newHeight: number, unpackAlignment: number): void => {\n curData = newData;\n curWidth = newWidth;\n curHeight = newHeight;\n curAlign = unpackAlignment;\n tex.width = newWidth;\n tex.height = newHeight;\n upload(target);\n };\n upload(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Options for {@link createFloatTexture} — the shared {@link GLTextureOptions}\n * plus the float-specific `type` / `format`. */\nexport interface GLFloatTextureOptions extends GLTextureOptions {\n /** Float texel type — `gl.HALF_FLOAT` (default) or `gl.FLOAT`. */\n type?: GLenum;\n /** Color format. Default `gl.RGBA`. */\n format?: GLenum;\n}\n\n/**\n * Create a float / half-float raw texture — the HDR counterpart of\n * {@link createRawTexture}. This is the ONLY texture factory that carries the\n * `RGBA16F` / `RGBA32F` sized-format knowledge (via {@link pickSizedInternalFormat}),\n * so byte-only consumers calling {@link createRawTexture} ship none of it.\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The caller is responsible for the matching engine cap (e.g.\n * `caps.textureFloatLinearFiltering`) when sampling these with `LINEAR`.\n *\n * @param engine - The engine.\n * @param data - Initial pixels (`Float32Array` for FLOAT, `Uint16Array` for\n * HALF_FLOAT), or `null` for an uninitialised allocation.\n * @param width - Texture width in texels (≥ 1).\n * @param height - Texture height in texels (≥ 1).\n * @param options - See {@link GLFloatTextureOptions}.\n * @returns The new {@link GLTexture}.\n */\nexport function createFloatTexture(engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, options?: GLFloatTextureOptions): GLTexture {\n const gl = engine.gl;\n const o = options ?? {};\n const format = o.format ?? gl.RGBA;\n const type = o.type ?? gl.HALF_FLOAT;\n // Precompute the sized float internalFormat HERE and pass it through, so\n // `createRawTexture`'s inline LDR resolver is bypassed and the float table\n // stays out of byte-only bundles.\n const internalFormat = pickSizedInternalFormat(gl, format, type);\n return createRawTexture(engine, data, width, height, format, type, { ...o, internalFormat });\n}\n\n/** Generate the mip chain for a texture from its level-0 contents — mipmaps as\n * an explicit opt-in function rather than baked into the create path. Binds for\n * upload (unit 0). No-op on a lost/disposed context or a handle-less texture. */\nexport function generateTextureMipMaps(engine: GLEngineContext, tex: GLTexture): void {\n if (engine._isLost || engine._disposed || tex._disposed || tex.handle === null) {\n return;\n }\n bindTextureForUpload(engine, tex.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Re-upload the pixel data (and optionally resize) of a texture created by\n * {@link createRawTexture} — the lite-gl equivalent of Babylon's\n * `updateRawTexture` / `_uploadDataToTextureDirectly`. Goes through the same\n * upload closure used by context-restore, so the new contents survive a context\n * loss. No-op on a lost/disposed/non-raw texture.\n *\n * @param engine - The engine.\n * @param tex - The raw texture to update.\n * @param data - New pixel data (must match the original `format`/`type`).\n * @param options - Optional new `width`/`height` (default: unchanged) and\n * `unpackAlignment` (default 4).\n */\nexport function updateRawTexture(\n engine: GLEngineContext,\n tex: GLTexture,\n data: ArrayBufferView | null,\n options?: { width?: number; height?: number; unpackAlignment?: number }\n): void {\n if (engine._isLost || engine._disposed || tex._disposed || tex._updateRaw === undefined) {\n return;\n }\n const o = options ?? {};\n tex._updateRaw(engine, data, o.width ?? tex.width, o.height ?? tex.height, o.unpackAlignment ?? 4);\n}\n\n/** Update a texture's min/mag sampling filters — the lite-gl equivalent of\n * Babylon's `updateTextureSamplingMode`. Binds for upload (unit 0) so the\n * `texParameteri` lands on this texture. No-op on a lost/disposed context. */\nexport function updateTextureSamplingMode(engine: GLEngineContext, tex: GLTexture, minFilter: GLenum, magFilter: GLenum): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n const gl = engine.gl;\n bindTextureForUpload(engine, tex.handle);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);\n}\n\n/** Update a texture's S/T wrap modes (`gl.CLAMP_TO_EDGE` / `gl.REPEAT` /\n * `gl.MIRRORED_REPEAT`) — the lite-gl equivalent of Babylon's\n * `updateTextureWrappingMode`. No-op on a lost/disposed context. */\nexport function updateTextureWrapMode(engine: GLEngineContext, tex: GLTexture, wrapS: GLenum, wrapT: GLenum): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n const gl = engine.gl;\n bindTextureForUpload(engine, tex.handle);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n}\n\n/**\n * Wrap an existing raw `WebGLTexture` (e.g. one created by a host renderer or a\n * previous engine) as a {@link GLTexture} — the lite-gl equivalent of\n * ShapeBuilder's `createTextureGraphicsResourceFromExternalWebGLTexture`.\n *\n * The wrapper does NOT own the underlying handle's upload — it is NOT registered\n * for context-restore replay (the external owner is responsible for that) and is\n * marked ready immediately. `disposeTexture` will still `gl.deleteTexture` it, so\n * only wrap a handle whose deletion you intend lite-gl to manage.\n *\n * @param engine - The engine.\n * @param handle - The external `WebGLTexture`.\n * @param width - Texture width in texels.\n * @param height - Texture height in texels.\n * @param options - Optional sampling/wrap to apply once (min/mag/wrapS/wrapT).\n * @returns A {@link GLTexture} wrapping the handle.\n */\nexport function createTextureFromHandle(engine: GLEngineContext, handle: WebGLTexture, width: number, height: number, options?: GLTextureOptions): GLTexture {\n const tex: GLTexture = {\n handle,\n target: engine.gl.TEXTURE_2D,\n width,\n height,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n // External handle — restore replay is the external owner's job.\n _upload: () => {},\n _wasReady: true,\n };\n if (options !== undefined) {\n const gl = engine.gl;\n bindTextureForUpload(engine, handle);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, options.minFilter ?? gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, options.magFilter ?? gl.LINEAR);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, options.wrapS ?? gl.CLAMP_TO_EDGE);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, options.wrapT ?? gl.CLAMP_TO_EDGE);\n }\n return tex;\n}\n\n/** Asynchronous image upload.The returned texture is immediately usable (1×1\n * transparent placeholder); `isReady` flips true once the image has been\n * decoded and uploaded. The decoded `ImageBitmap` is retained on the texture\n * for offline-safe `webglcontextrestored` replay. */\nexport function loadTexture2D(engine: GLEngineContext, url: string, options?: GLTextureOptions, onLoad?: (tex: GLTexture) => void, onError?: (err: Error) => void): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n\n let bitmap: ImageBitmap | null = null;\n const placeholderPixels = new Uint8Array([0, 0, 0, 0]);\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n // invertY is applied at decode time via createImageBitmap({ imageOrientation })\n // because UNPACK_FLIP_Y_WEBGL is IGNORED for ImageBitmap sources (and the 1×1\n // placeholder is flip-invariant), so keep flip + premultiply off here.\n setUnpackState(target, false, false);\n bindTextureForUpload(target, tex.handle);\n if (bitmap !== null) {\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, bitmap);\n tex.width = bitmap.width;\n tex.height = bitmap.height;\n } else {\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, 1, 1, 0, g.RGBA, g.UNSIGNED_BYTE, placeholderPixels);\n }\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MIN_FILTER, minFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_MAG_FILTER, magFilter);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_S, wrapS);\n g.texParameteri(g.TEXTURE_2D, g.TEXTURE_WRAP_T, wrapT);\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: 1,\n height: 1,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _wasReady: false,\n };\n // Placeholder upload — makes the texture sampleable before the real image arrives.\n upload(engine);\n engine._textures.push(tex);\n\n // Fetch + decode the real image. Re-uploads via the same closure once the\n // bitmap is in hand (so context-restore replay sees the real image too).\n fetch(url)\n .then((r) => {\n if (!r.ok) {\n throw new Error(`lite-gl: fetch ${url} -> HTTP ${r.status}`);\n }\n return r.blob();\n })\n .then((blob) => createImageBitmap(blob, { premultiplyAlpha: \"none\", imageOrientation: invertY ? \"flipY\" : \"none\" }))\n .then((bm) => {\n if (tex._disposed) {\n bm.close();\n return;\n }\n bitmap = bm;\n // If the context is lost mid-flight, defer the upload — the restore\n // handler will call _upload again, which will then see `bitmap !== null`\n // and replay the real image.\n if (!engine._isLost) {\n upload(engine);\n tex.isReady = true;\n }\n tex._wasReady = true;\n if (onLoad !== undefined) {\n onLoad(tex);\n }\n })\n .catch((err: unknown) => {\n const e = err instanceof Error ? err : new Error(String(err));\n if (onError !== undefined) {\n onError(e);\n } else {\n console.error(\"lite-gl: loadTexture2D failed\", e);\n }\n });\n\n return tex;\n}\n\n/** Cached bind. Skips `gl.activeTexture` and/or `gl.bindTexture` when nothing\n * changes. No-op when `tex._disposed` or `engine._isLost`. */\nexport function bindTexture(engine: GLEngineContext, unit: number, tex: GLTexture | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (tex !== null && tex._disposed) {\n return;\n }\n bindTextureRaw(engine, unit, tex === null ? null : tex.handle);\n}\n\n/** @internal — for callers that already hold a raw `WebGLTexture`. Not part of\n * the public API: `bindTexture` (public) and the texture `_upload` closures bind\n * through the cache, so consumers never call this directly. */\nexport function bindTextureRaw(engine: GLEngineContext, unit: number, handle: WebGLTexture | null): void {\n const s = engine._state;\n const gl = engine.gl;\n if (s.boundTextures[unit] === handle) {\n return;\n }\n if (s.activeTextureUnit !== unit) {\n gl.activeTexture(gl.TEXTURE0 + unit);\n s.activeTextureUnit = unit;\n }\n gl.bindTexture(gl.TEXTURE_2D, handle);\n s.boundTextures[unit] = handle;\n}\n\n/** @internal Bind `handle` on texture unit 0 **for an upload** (`texImage2D`).\n * Unlike {@link bindTextureRaw} — which elides the entire bind when the handle is\n * already bound on the unit (correct for *sampling*, where the active unit is\n * irrelevant) — an upload writes into the texture on the ACTIVE unit. A prior\n * multi-sampler draw may have left a non-zero unit active while this handle is\n * still bound on unit 0, so we must force unit 0 active even on a bind cache-hit,\n * keeping the `_state` cache coherent. */\nexport function bindTextureForUpload(engine: GLEngineContext, handle: WebGLTexture): void {\n const s = engine._state;\n const gl = engine.gl;\n if (s.activeTextureUnit !== 0) {\n gl.activeTexture(gl.TEXTURE0);\n s.activeTextureUnit = 0;\n }\n if (s.boundTextures[0] !== handle) {\n gl.bindTexture(gl.TEXTURE_2D, handle);\n s.boundTextures[0] = handle;\n }\n}\n\n/** Disposes the texture. Walks `_state.boundTextures` and clears every slot\n * that still references the handle — otherwise a later `bindTexture(unit, B)`\n * to the same unit would be wrongly elided when slot still showed handle A. */\nexport function disposeTexture(engine: GLEngineContext, tex: GLTexture): void {\n if (tex._disposed) {\n return;\n }\n if (tex._refCount > 1) {\n tex._refCount--;\n return;\n }\n tex._disposed = true;\n const i = engine._textures.indexOf(tex);\n if (i !== -1) {\n engine._textures.splice(i, 1);\n }\n if (!engine._isLost && !engine._disposed) {\n engine.gl.deleteTexture(tex.handle);\n }\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === tex.handle) {\n bound[u] = null;\n }\n }\n}\n\n/** Internal — resolve the sized internalFormat for the LDR (byte) `texImage2D`\n * paths ONLY: RGBA→RGBA8, RGB→RGB8, RG→RG8, RED→R8, LUMINANCE passthrough.\n * Deliberately knows nothing about FLOAT / HALF_FLOAT so the float-format table\n * in {@link pickSizedInternalFormat} tree-shakes out of byte-only bundles.\n * @internal */\nfunction resolveLdrInternalFormat(gl: WebGL2RenderingContext, format: GLenum, type: GLenum): GLenum {\n if (type === gl.UNSIGNED_BYTE) {\n if (format === gl.RGBA) {\n return gl.RGBA8;\n }\n if (format === gl.RGB) {\n return gl.RGB8;\n }\n if (format === gl.RG) {\n return gl.RG8;\n }\n if (format === gl.RED) {\n return gl.R8;\n }\n if (format === gl.LUMINANCE) {\n return gl.LUMINANCE;\n }\n }\n return format;\n}\n\n/** Internal — pick a sized internalFormat for `texImage2D`. WebGL2 prefers\n * sized formats for non-color-renderable / non-readback paths; for the\n * NeonBrush use cases (sample-only) the unsized format works too, but sized\n * is more portable. Shared with the render-target module.\n * @internal */\nexport function pickSizedInternalFormat(gl: WebGL2RenderingContext, format: GLenum, type: GLenum): GLenum {\n if (type === gl.UNSIGNED_BYTE) {\n if (format === gl.RGBA) {\n return gl.RGBA8;\n }\n if (format === gl.RGB) {\n return gl.RGB8;\n }\n if (format === gl.LUMINANCE) {\n return gl.LUMINANCE;\n }\n }\n if (type === gl.FLOAT) {\n if (format === gl.RGBA) {\n return gl.RGBA32F;\n }\n if (format === gl.RGB) {\n return gl.RGB32F;\n }\n }\n if (type === gl.HALF_FLOAT) {\n if (format === gl.RGBA) {\n return gl.RGBA16F;\n }\n if (format === gl.RGB) {\n return gl.RGB16F;\n }\n }\n return format;\n}\n"]}
1
+ {"version":3,"file":"texture.js","sourceRoot":"","sources":["../src/texture.ts"],"names":[],"mappings":"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","sourcesContent":["import type { GLEngineContext } from \"./context.js\";\n\n/** Texture sampling / wrap options. All have GL-spec defaults. Mipmaps are NOT\n * a create option — generate the chain explicitly via {@link generateTextureMipMaps}. */\nexport interface GLTextureOptions {\n /** Default: false (matches Babylon's default raw-texture behaviour). */\n invertY?: boolean;\n /** Default: gl.LINEAR. */\n minFilter?: GLenum;\n /** Default: gl.LINEAR. */\n magFilter?: GLenum;\n /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`\n * (NPOT-safe in WebGL2). */\n wrapS?: GLenum;\n /** Default: gl.CLAMP_TO_EDGE. May be `gl.REPEAT` / `gl.MIRRORED_REPEAT`. */\n wrapT?: GLenum;\n /** `gl.pixelStorei(UNPACK_ALIGNMENT)` for the upload (1/2/4/8). Default 4.\n * Use 1 for tightly-packed non-RGBA rows. */\n unpackAlignment?: number;\n /** Premultiply alpha at upload (`UNPACK_PREMULTIPLY_ALPHA_WEBGL`). Default\n * false. */\n premultiplyAlpha?: boolean;\n /** Explicit sized internalFormat for `texImage2D`. When provided it is used\n * verbatim and the inline LDR resolver is bypassed — this is how\n * {@link createFloatTexture} injects its `RGBA16F` / `RGBA32F` choice\n * without the byte path ever referencing the float-format table (keeping it\n * tree-shakeable out of RGBA8-only bundles). Default: derived from\n * `format`/`type` via the LDR resolver. */\n internalFormat?: GLenum;\n}\n\n/**\n * Pure-state texture handle. The `handle` field is MUTABLE so the same logical\n * texture survives a `webglcontextrestored` event — every consumer keeps the\n * same `GLTexture` reference; only the internal `WebGLTexture` is swapped.\n *\n * `loadTexture2D` also uses the same handle for the 1×1 placeholder upload AND\n * the final image upload — so a `bindTexture(engine, unit, tex)` made before the\n * image has decoded remains valid once the image arrives.\n */\nexport interface GLTexture {\n /** The live `WebGLTexture`. MUTABLE — swapped for a fresh handle on\n * `webglcontextrestored` while consumers keep the same `GLTexture` reference. */\n handle: WebGLTexture;\n /** GL texture target (always `gl.TEXTURE_2D` for this package). */\n readonly target: GLenum;\n /** Texture width in texels. Updated once an async upload resolves. */\n width: number;\n /** Texture height in texels. Updated once an async upload resolves. */\n height: number;\n /** True when the texture is safe to sample with final content (placeholders\n * read as not-ready until their image/upload completes). */\n isReady: boolean;\n /** @internal */\n _disposed: boolean;\n /** @internal */\n _refCount: number;\n /** Replays the latest pixel content into the currently bound texture handle. @internal */\n _upload: (engine: GLEngineContext) => void;\n /** Initializes creation-time sampling state on the bound texture handle. @internal */\n _initializeParameters?: (engine: GLEngineContext) => void;\n /**\n * Snapshot of `isReady` captured on `webglcontextlost` so the restore\n * handler knows whether to flip it back on after `_upload`. Textures\n * that were still mid-load (e.g. `loadTexture2D` whose bitmap hadn't\n * arrived) stay not-ready; the async path will set `isReady=true` once\n * the bitmap finishes decoding into the new handle.\n * @internal\n */\n _wasReady: boolean;\n /**\n * Live re-upload hook installed by `createRawTexture` — lets\n * `updateRawTexture` replace the pixel data (and optionally the size)\n * through the same closure that the context-restore replay uses, keeping\n * restore correct. Absent on image / HTML-element / external textures.\n * @internal\n */\n _updateRaw?: (engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, unpackAlignment: number) => void;\n /**\n * Dynamic-texture source captured by `updateDynamicTexture`\n * (`@babylonjs/lite-gl`) and replayed into the fresh handle\n * on `webglcontextrestored`. Null/absent on non-dynamic textures.\n * @internal\n */\n _dynSource?: TexImageSource | null;\n /** UNPACK_FLIP_Y applied when replaying {@link GLTexture._dynSource}. @internal */\n _dynInvertY?: boolean;\n /** UNPACK_PREMULTIPLY_ALPHA applied when replaying {@link GLTexture._dynSource}. @internal */\n _dynPremultiplyAlpha?: boolean;\n /**\n * The `handle` the dynamic texture's `texParameteri` filter/wrap state was\n * last applied to. `texParameteri` is per-texture GL state that survives pixel\n * re-uploads, so the dynamic-texture `_upload` re-applies it ONLY when this no\n * longer matches `handle` — i.e. at creation and after `webglcontextrestored`\n * installs a fresh handle — not on every per-frame `updateDynamicTexture`.\n * @internal\n */\n _dynParamsHandle?: WebGLTexture | null;\n}\n\n/**\n * Apply the three `UNPACK_*` pixel-store flags through the GL-state cache,\n * eliding redundant `pixelStorei` calls. Centralising this guarantees EVERY\n * upload path sets all three explicitly, so a premultiplying / flipping upload\n * never leaks its flag into a later upload that forgot to set it.\n * @internal\n */\nexport function setUnpackState(engine: GLEngineContext, flipY: boolean, premultiplyAlpha: boolean, alignment = 4): void {\n const gl = engine.gl;\n const s = engine._state;\n const fy = flipY ? 1 : 0;\n if (s.unpackFlipY !== fy) {\n gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, fy);\n s.unpackFlipY = fy;\n }\n const pm = premultiplyAlpha ? 1 : 0;\n if (s.unpackPremultiplyAlpha !== pm) {\n gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, pm);\n s.unpackPremultiplyAlpha = pm;\n }\n if (s.unpackAlignment !== alignment) {\n gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment);\n s.unpackAlignment = alignment;\n }\n}\n\n/** Apply sampling and wrap state to the texture currently bound for upload. @internal */\nexport function setBoundTextureParams(gl: WebGL2RenderingContext, minFilter: GLenum, magFilter: GLenum, wrapS: GLenum, wrapT: GLenum): void {\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n}\n\n/** Uint8 / float raw texture upload. The pixel data can be replaced later via\n * {@link updateRawTexture}; the sampling and wrap can be changed via\n * {@link updateTextureSamplingMode} / {@link updateTextureWrapMode}. */\nexport function createRawTexture(\n engine: GLEngineContext,\n data: ArrayBufferView | null,\n width: number,\n height: number,\n format: GLenum,\n type: GLenum,\n options?: GLTextureOptions\n): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n const premultiply = opts.premultiplyAlpha ?? false;\n // LDR byte formats are resolved INLINE here; the float-format table in\n // `pickSizedInternalFormat` is deliberately NOT referenced from this path so\n // it tree-shakes out of byte-only bundles. `createFloatTexture` injects its\n // sized float format via `opts.internalFormat`.\n const internalFormat = opts.internalFormat ?? resolveLdrInternalFormat(gl, format, type);\n\n // Mutable upload state — `updateRawTexture` mutates these and re-runs\n // `upload`, so the context-restore replay (which calls the same `upload`)\n // always reproduces the latest contents.\n let curData = data;\n let curWidth = width;\n let curHeight = height;\n let curAlign = opts.unpackAlignment ?? 4;\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n setUnpackState(target, invertY, premultiply, curAlign);\n bindTextureForUpload(target, tex.handle);\n g.texImage2D(g.TEXTURE_2D, 0, internalFormat, curWidth, curHeight, 0, format, type, curData);\n };\n\n const initializeParameters = (target: GLEngineContext): void => {\n setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width,\n height,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _initializeParameters: initializeParameters,\n _wasReady: true,\n };\n tex._updateRaw = (target: GLEngineContext, newData: ArrayBufferView | null, newWidth: number, newHeight: number, unpackAlignment: number): void => {\n curData = newData;\n curWidth = newWidth;\n curHeight = newHeight;\n curAlign = unpackAlignment;\n tex.width = newWidth;\n tex.height = newHeight;\n upload(target);\n };\n upload(engine);\n initializeParameters(engine);\n engine._textures.push(tex);\n return tex;\n}\n\n/** Options for {@link createFloatTexture} — the shared {@link GLTextureOptions}\n * plus the float-specific `type` / `format`. */\nexport interface GLFloatTextureOptions extends GLTextureOptions {\n /** Float texel type — `gl.HALF_FLOAT` (default) or `gl.FLOAT`. */\n type?: GLenum;\n /** Color format. Default `gl.RGBA`. */\n format?: GLenum;\n}\n\n/**\n * Create a float / half-float raw texture — the HDR counterpart of\n * {@link createRawTexture}. This is the ONLY texture factory that carries the\n * `RGBA16F` / `RGBA32F` sized-format knowledge (via {@link pickSizedInternalFormat}),\n * so byte-only consumers calling {@link createRawTexture} ship none of it.\n * Defaults to `gl.HALF_FLOAT`; pass `options.type = gl.FLOAT` for full 32-bit.\n * The caller is responsible for the matching engine cap (e.g.\n * `caps.textureFloatLinearFiltering`) when sampling these with `LINEAR`.\n *\n * @param engine - The engine.\n * @param data - Initial pixels (`Float32Array` for FLOAT, `Uint16Array` for\n * HALF_FLOAT), or `null` for an uninitialised allocation.\n * @param width - Texture width in texels (≥ 1).\n * @param height - Texture height in texels (≥ 1).\n * @param options - See {@link GLFloatTextureOptions}.\n * @returns The new {@link GLTexture}.\n */\nexport function createFloatTexture(engine: GLEngineContext, data: ArrayBufferView | null, width: number, height: number, options?: GLFloatTextureOptions): GLTexture {\n const gl = engine.gl;\n const o = options ?? {};\n const format = o.format ?? gl.RGBA;\n const type = o.type ?? gl.HALF_FLOAT;\n // Precompute the sized float internalFormat HERE and pass it through, so\n // `createRawTexture`'s inline LDR resolver is bypassed and the float table\n // stays out of byte-only bundles.\n const internalFormat = pickSizedInternalFormat(gl, format, type);\n return createRawTexture(engine, data, width, height, format, type, { ...o, internalFormat });\n}\n\n/** Generate the mip chain for a texture from its level-0 contents — mipmaps as\n * an explicit opt-in function rather than baked into the create path. Binds for\n * upload (unit 0). No-op on a lost/disposed context or a handle-less texture. */\nexport function generateTextureMipMaps(engine: GLEngineContext, tex: GLTexture): void {\n if (engine._isLost || engine._disposed || tex._disposed || tex.handle === null) {\n return;\n }\n bindTextureForUpload(engine, tex.handle);\n engine.gl.generateMipmap(engine.gl.TEXTURE_2D);\n}\n\n/**\n * Re-upload the pixel data (and optionally resize) of a texture created by\n * {@link createRawTexture} — the lite-gl equivalent of Babylon's\n * `updateRawTexture` / `_uploadDataToTextureDirectly`. Goes through the same\n * upload closure used by context-restore, so the new contents survive a context\n * loss. No-op on a lost/disposed/non-raw texture.\n *\n * @param engine - The engine.\n * @param tex - The raw texture to update.\n * @param data - New pixel data (must match the original `format`/`type`).\n * @param options - Optional new `width`/`height` (default: unchanged) and\n * `unpackAlignment` (default 4).\n */\nexport function updateRawTexture(\n engine: GLEngineContext,\n tex: GLTexture,\n data: ArrayBufferView | null,\n options?: { width?: number; height?: number; unpackAlignment?: number }\n): void {\n if (engine._isLost || engine._disposed || tex._disposed || tex._updateRaw === undefined) {\n return;\n }\n const o = options ?? {};\n tex._updateRaw(engine, data, o.width ?? tex.width, o.height ?? tex.height, o.unpackAlignment ?? 4);\n}\n\n/** Update a texture's min/mag sampling filters — the lite-gl equivalent of\n * Babylon's `updateTextureSamplingMode`. Binds for upload (unit 0) so the\n * `texParameteri` lands on this texture. No-op on a lost/disposed context. */\nexport function updateTextureSamplingMode(engine: GLEngineContext, tex: GLTexture, minFilter: GLenum, magFilter: GLenum): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n const gl = engine.gl;\n bindTextureForUpload(engine, tex.handle);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, magFilter);\n}\n\n/** Update a texture's S/T wrap modes (`gl.CLAMP_TO_EDGE` / `gl.REPEAT` /\n * `gl.MIRRORED_REPEAT`) — the lite-gl equivalent of Babylon's\n * `updateTextureWrappingMode`. No-op on a lost/disposed context. */\nexport function updateTextureWrapMode(engine: GLEngineContext, tex: GLTexture, wrapS: GLenum, wrapT: GLenum): void {\n if (engine._isLost || engine._disposed || tex._disposed) {\n return;\n }\n const gl = engine.gl;\n bindTextureForUpload(engine, tex.handle);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, wrapS);\n gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, wrapT);\n}\n\n/**\n * Wrap an existing raw `WebGLTexture` (e.g. one created by a host renderer or a\n * previous engine) as a {@link GLTexture} — the lite-gl equivalent of\n * ShapeBuilder's `createTextureGraphicsResourceFromExternalWebGLTexture`.\n *\n * The wrapper does NOT own the underlying handle's upload — it is NOT registered\n * for context-restore replay (the external owner is responsible for that) and is\n * marked ready immediately. `disposeTexture` will still `gl.deleteTexture` it, so\n * only wrap a handle whose deletion you intend lite-gl to manage.\n *\n * @param engine - The engine.\n * @param handle - The external `WebGLTexture`.\n * @param width - Texture width in texels.\n * @param height - Texture height in texels.\n * @param options - Optional sampling/wrap to apply once (min/mag/wrapS/wrapT).\n * @returns A {@link GLTexture} wrapping the handle.\n */\nexport function createTextureFromHandle(engine: GLEngineContext, handle: WebGLTexture, width: number, height: number, options?: GLTextureOptions): GLTexture {\n const tex: GLTexture = {\n handle,\n target: engine.gl.TEXTURE_2D,\n width,\n height,\n isReady: true,\n _disposed: false,\n _refCount: 1,\n // External handle — restore replay is the external owner's job.\n _upload: () => {},\n _wasReady: true,\n };\n if (options !== undefined) {\n const gl = engine.gl;\n bindTextureForUpload(engine, handle);\n setBoundTextureParams(gl, options.minFilter ?? gl.LINEAR, options.magFilter ?? gl.LINEAR, options.wrapS ?? gl.CLAMP_TO_EDGE, options.wrapT ?? gl.CLAMP_TO_EDGE);\n }\n return tex;\n}\n\n/** Asynchronous image upload.The returned texture is immediately usable (1×1\n * transparent placeholder); `isReady` flips true once the image has been\n * decoded and uploaded. The decoded `ImageBitmap` is retained on the texture\n * for offline-safe `webglcontextrestored` replay. */\nexport function loadTexture2D(engine: GLEngineContext, url: string, options?: GLTextureOptions, onLoad?: (tex: GLTexture) => void, onError?: (err: Error) => void): GLTexture {\n const gl = engine.gl;\n const handle = gl.createTexture();\n if (handle === null) {\n throw new Error(\"lite-gl: gl.createTexture returned null\");\n }\n const opts = options ?? {};\n const minFilter = opts.minFilter ?? gl.LINEAR;\n const magFilter = opts.magFilter ?? gl.LINEAR;\n const wrapS = opts.wrapS ?? gl.CLAMP_TO_EDGE;\n const wrapT = opts.wrapT ?? gl.CLAMP_TO_EDGE;\n const invertY = opts.invertY ?? false;\n\n let bitmap: ImageBitmap | null = null;\n const placeholderPixels = new Uint8Array([0, 0, 0, 0]);\n\n const upload = (target: GLEngineContext): void => {\n const g = target.gl;\n // invertY is applied at decode time via createImageBitmap({ imageOrientation })\n // because UNPACK_FLIP_Y_WEBGL is IGNORED for ImageBitmap sources (and the 1×1\n // placeholder is flip-invariant), so keep flip + premultiply off here.\n setUnpackState(target, false, false);\n bindTextureForUpload(target, tex.handle);\n if (bitmap !== null) {\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, g.RGBA, g.UNSIGNED_BYTE, bitmap);\n tex.width = bitmap.width;\n tex.height = bitmap.height;\n } else {\n g.texImage2D(g.TEXTURE_2D, 0, g.RGBA, 1, 1, 0, g.RGBA, g.UNSIGNED_BYTE, placeholderPixels);\n }\n };\n\n const initializeParameters = (target: GLEngineContext): void => {\n setBoundTextureParams(target.gl, minFilter, magFilter, wrapS, wrapT);\n };\n\n const tex: GLTexture = {\n handle,\n target: gl.TEXTURE_2D,\n width: 1,\n height: 1,\n isReady: false,\n _disposed: false,\n _refCount: 1,\n _upload: upload,\n _initializeParameters: initializeParameters,\n _wasReady: false,\n };\n // Placeholder upload — makes the texture sampleable before the real image arrives.\n upload(engine);\n initializeParameters(engine);\n engine._textures.push(tex);\n\n // Fetch + decode the real image. Re-uploads via the same closure once the\n // bitmap is in hand (so context-restore replay sees the real image too).\n fetch(url)\n .then((r) => {\n if (!r.ok) {\n throw new Error(`lite-gl: fetch ${url} -> HTTP ${r.status}`);\n }\n return r.blob();\n })\n .then((blob) => createImageBitmap(blob, { premultiplyAlpha: \"none\", imageOrientation: invertY ? \"flipY\" : \"none\" }))\n .then((bm) => {\n if (tex._disposed) {\n bm.close();\n return;\n }\n bitmap = bm;\n // If the context is lost mid-flight, defer the upload — the restore\n // handler will call _upload again, which will then see `bitmap !== null`\n // and replay the real image.\n if (!engine._isLost) {\n upload(engine);\n tex.isReady = true;\n }\n tex._wasReady = true;\n if (onLoad !== undefined) {\n onLoad(tex);\n }\n })\n .catch((err: unknown) => {\n const e = err instanceof Error ? err : new Error(String(err));\n if (onError !== undefined) {\n onError(e);\n } else {\n console.error(\"lite-gl: loadTexture2D failed\", e);\n }\n });\n\n return tex;\n}\n\n/** Cached bind. Skips `gl.activeTexture` and/or `gl.bindTexture` when nothing\n * changes. No-op when `tex._disposed` or `engine._isLost`. */\nexport function bindTexture(engine: GLEngineContext, unit: number, tex: GLTexture | null): void {\n if (engine._isLost || engine._disposed) {\n return;\n }\n if (tex !== null && tex._disposed) {\n return;\n }\n bindTextureRaw(engine, unit, tex === null ? null : tex.handle);\n}\n\n/** @internal — for callers that already hold a raw `WebGLTexture`. Not part of\n * the public API: `bindTexture` (public) and the texture `_upload` closures bind\n * through the cache, so consumers never call this directly. */\nexport function bindTextureRaw(engine: GLEngineContext, unit: number, handle: WebGLTexture | null): void {\n const s = engine._state;\n const gl = engine.gl;\n if (s.boundTextures[unit] === handle) {\n return;\n }\n if (s.activeTextureUnit !== unit) {\n gl.activeTexture(gl.TEXTURE0 + unit);\n s.activeTextureUnit = unit;\n }\n gl.bindTexture(gl.TEXTURE_2D, handle);\n s.boundTextures[unit] = handle;\n}\n\n/** @internal Bind `handle` on texture unit 0 **for an upload** (`texImage2D`).\n * Unlike {@link bindTextureRaw} — which elides the entire bind when the handle is\n * already bound on the unit (correct for *sampling*, where the active unit is\n * irrelevant) — an upload writes into the texture on the ACTIVE unit. A prior\n * multi-sampler draw may have left a non-zero unit active while this handle is\n * still bound on unit 0, so we must force unit 0 active even on a bind cache-hit,\n * keeping the `_state` cache coherent. */\nexport function bindTextureForUpload(engine: GLEngineContext, handle: WebGLTexture): void {\n const s = engine._state;\n const gl = engine.gl;\n if (s.activeTextureUnit !== 0) {\n gl.activeTexture(gl.TEXTURE0);\n s.activeTextureUnit = 0;\n }\n if (s.boundTextures[0] !== handle) {\n gl.bindTexture(gl.TEXTURE_2D, handle);\n s.boundTextures[0] = handle;\n }\n}\n\n/** Disposes the texture. Walks `_state.boundTextures` and clears every slot\n * that still references the handle — otherwise a later `bindTexture(unit, B)`\n * to the same unit would be wrongly elided when slot still showed handle A. */\nexport function disposeTexture(engine: GLEngineContext, tex: GLTexture): void {\n if (tex._disposed) {\n return;\n }\n if (tex._refCount > 1) {\n tex._refCount--;\n return;\n }\n tex._disposed = true;\n const i = engine._textures.indexOf(tex);\n if (i !== -1) {\n engine._textures.splice(i, 1);\n }\n if (!engine._isLost && !engine._disposed) {\n engine.gl.deleteTexture(tex.handle);\n }\n const bound = engine._state.boundTextures;\n for (let u = 0; u < bound.length; u++) {\n if (bound[u] === tex.handle) {\n bound[u] = null;\n }\n }\n}\n\n/** Internal — resolve the sized internalFormat for the LDR (byte) `texImage2D`\n * paths ONLY: RGBA→RGBA8, RGB→RGB8, RG→RG8, RED→R8, LUMINANCE passthrough.\n * Deliberately knows nothing about FLOAT / HALF_FLOAT so the float-format table\n * in {@link pickSizedInternalFormat} tree-shakes out of byte-only bundles.\n * @internal */\nfunction resolveLdrInternalFormat(gl: WebGL2RenderingContext, format: GLenum, type: GLenum): GLenum {\n if (type === gl.UNSIGNED_BYTE) {\n if (format === gl.RGBA) {\n return gl.RGBA8;\n }\n if (format === gl.RGB) {\n return gl.RGB8;\n }\n if (format === gl.RG) {\n return gl.RG8;\n }\n if (format === gl.RED) {\n return gl.R8;\n }\n if (format === gl.LUMINANCE) {\n return gl.LUMINANCE;\n }\n }\n return format;\n}\n\n/** Internal — pick a sized internalFormat for `texImage2D`. WebGL2 prefers\n * sized formats for non-color-renderable / non-readback paths; for the\n * NeonBrush use cases (sample-only) the unsized format works too, but sized\n * is more portable. Shared with the render-target module.\n * @internal */\nexport function pickSizedInternalFormat(gl: WebGL2RenderingContext, format: GLenum, type: GLenum): GLenum {\n if (type === gl.UNSIGNED_BYTE) {\n if (format === gl.RGBA) {\n return gl.RGBA8;\n }\n if (format === gl.RGB) {\n return gl.RGB8;\n }\n if (format === gl.LUMINANCE) {\n return gl.LUMINANCE;\n }\n }\n if (type === gl.FLOAT) {\n if (format === gl.RGBA) {\n return gl.RGBA32F;\n }\n if (format === gl.RGB) {\n return gl.RGB32F;\n }\n }\n if (type === gl.HALF_FLOAT) {\n if (format === gl.RGBA) {\n return gl.RGBA16F;\n }\n if (format === gl.RGB) {\n return gl.RGB16F;\n }\n }\n return format;\n}\n"]}