@luma.gl/webgl 9.1.0-alpha.14 → 9.1.0-alpha.15

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/dist/index.cjs CHANGED
@@ -1406,1755 +1406,1756 @@ var WebGLDeviceLimits = class extends import_core3.DeviceLimits {
1406
1406
  };
1407
1407
 
1408
1408
  // dist/adapter/webgl-canvas-context.js
1409
- var import_core10 = require("@luma.gl/core");
1409
+ var import_core5 = require("@luma.gl/core");
1410
1410
 
1411
1411
  // dist/adapter/resources/webgl-framebuffer.js
1412
- var import_core9 = require("@luma.gl/core");
1413
- var import_constants13 = require("@luma.gl/constants");
1414
-
1415
- // dist/adapter/resources/webgl-texture.js
1416
- var import_core8 = require("@luma.gl/core");
1417
- var import_constants12 = require("@luma.gl/constants");
1418
-
1419
- // dist/context/state-tracker/with-parameters.js
1420
- function withGLParameters(gl, parameters, func) {
1421
- if (isObjectEmpty2(parameters)) {
1422
- return func(gl);
1423
- }
1424
- const { nocatch = true } = parameters;
1425
- const webglState = WebGLStateTracker.get(gl);
1426
- webglState.push();
1427
- setGLParameters(gl, parameters);
1428
- let value;
1429
- if (nocatch) {
1430
- value = func(gl);
1431
- webglState.pop();
1432
- } else {
1433
- try {
1434
- value = func(gl);
1435
- } finally {
1436
- webglState.pop();
1437
- }
1438
- }
1439
- return value;
1440
- }
1441
- function isObjectEmpty2(object) {
1442
- for (const key in object) {
1443
- return false;
1444
- }
1445
- return true;
1446
- }
1447
-
1448
- // dist/adapter/converters/sampler-parameters.js
1449
- var import_constants7 = require("@luma.gl/constants");
1450
-
1451
- // dist/adapter/converters/device-parameters.js
1452
1412
  var import_core4 = require("@luma.gl/core");
1453
1413
  var import_constants6 = require("@luma.gl/constants");
1454
- function withDeviceAndGLParameters(device, parameters, glParameters, func) {
1455
- if (isObjectEmpty3(parameters)) {
1456
- return func(device);
1457
- }
1458
- const webglDevice = device;
1459
- webglDevice.pushState();
1460
- try {
1461
- setDeviceParameters(device, parameters);
1462
- setGLParameters(webglDevice.gl, glParameters);
1463
- return func(device);
1464
- } finally {
1465
- webglDevice.popState();
1414
+ var WEBGLFramebuffer = class extends import_core4.Framebuffer {
1415
+ device;
1416
+ gl;
1417
+ handle;
1418
+ colorAttachments = [];
1419
+ depthStencilAttachment = null;
1420
+ constructor(device, props) {
1421
+ super(device, props);
1422
+ const isDefaultFramebuffer = props.handle === null;
1423
+ this.device = device;
1424
+ this.gl = device.gl;
1425
+ this.handle = this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
1426
+ if (!isDefaultFramebuffer) {
1427
+ device.setSpectorMetadata(this.handle, { id: this.props.id, props: this.props });
1428
+ this.autoCreateAttachmentTextures();
1429
+ this.updateAttachments();
1430
+ }
1466
1431
  }
1467
- }
1468
- function withDeviceParameters(device, parameters, func) {
1469
- if (isObjectEmpty3(parameters)) {
1470
- return func(device);
1432
+ /** destroys any auto created resources etc. */
1433
+ destroy() {
1434
+ super.destroy();
1435
+ if (!this.destroyed && this.handle !== null) {
1436
+ this.gl.deleteFramebuffer(this.handle);
1437
+ }
1471
1438
  }
1472
- const webglDevice = device;
1473
- webglDevice.pushState();
1474
- try {
1475
- setDeviceParameters(device, parameters);
1476
- return func(device);
1477
- } finally {
1478
- webglDevice.popState();
1439
+ updateAttachments() {
1440
+ const prevHandle = this.gl.bindFramebuffer(36160, this.handle);
1441
+ for (let i = 0; i < this.colorAttachments.length; ++i) {
1442
+ const attachment = this.colorAttachments[i];
1443
+ if (attachment) {
1444
+ const attachmentPoint = 36064 + i;
1445
+ this._attachTextureView(attachmentPoint, attachment);
1446
+ }
1447
+ }
1448
+ if (this.depthStencilAttachment) {
1449
+ const attachmentPoint = getDepthStencilAttachmentWebGL(this.depthStencilAttachment.props.format);
1450
+ this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
1451
+ }
1452
+ if (this.props.check !== false) {
1453
+ const status = this.gl.checkFramebufferStatus(36160);
1454
+ if (status !== 36053) {
1455
+ throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
1456
+ }
1457
+ }
1458
+ this.gl.bindFramebuffer(36160, prevHandle);
1479
1459
  }
1480
- }
1481
- function setDeviceParameters(device, parameters) {
1482
- const webglDevice = device;
1483
- const { gl } = webglDevice;
1484
- if (parameters.cullMode) {
1485
- switch (parameters.cullMode) {
1486
- case "none":
1487
- gl.disable(2884);
1460
+ // PRIVATE
1461
+ /** In WebGL we must use renderbuffers for depth/stencil attachments (unless we have extensions) */
1462
+ // protected override createDepthStencilTexture(format: TextureFormat): Texture {
1463
+ // // return new WEBGLRenderbuffer(this.device, {
1464
+ // return new WEBGLTexture(this.device, {
1465
+ // id: `${this.id}-depth-stencil`,
1466
+ // format,
1467
+ // width: this.width,
1468
+ // height: this.height,
1469
+ // mipmaps: false
1470
+ // });
1471
+ // }
1472
+ /**
1473
+ * @param attachment
1474
+ * @param texture
1475
+ * @param layer = 0 - index into WEBGLTextureArray and Texture3D or face for `TextureCubeMap`
1476
+ * @param level = 0 - mipmapLevel
1477
+ */
1478
+ _attachTextureView(attachment, textureView) {
1479
+ const { gl } = this.device;
1480
+ const { texture } = textureView;
1481
+ const level = textureView.props.baseMipLevel;
1482
+ const layer = textureView.props.baseArrayLayer;
1483
+ gl.bindTexture(texture.glTarget, texture.handle);
1484
+ switch (texture.glTarget) {
1485
+ case 35866:
1486
+ case 32879:
1487
+ gl.framebufferTextureLayer(36160, attachment, texture.handle, level, layer);
1488
1488
  break;
1489
- case "front":
1490
- gl.enable(2884);
1491
- gl.cullFace(1028);
1489
+ case 34067:
1490
+ const face = mapIndexToCubeMapFace(layer);
1491
+ gl.framebufferTexture2D(36160, attachment, face, texture.handle, level);
1492
1492
  break;
1493
- case "back":
1494
- gl.enable(2884);
1495
- gl.cullFace(1029);
1493
+ case 3553:
1494
+ gl.framebufferTexture2D(36160, attachment, 3553, texture.handle, level);
1496
1495
  break;
1496
+ default:
1497
+ throw new Error("Illegal texture type");
1497
1498
  }
1499
+ gl.bindTexture(texture.glTarget, null);
1498
1500
  }
1499
- if (parameters.frontFace) {
1500
- gl.frontFace(map("frontFace", parameters.frontFace, {
1501
- ccw: 2305,
1502
- cw: 2304
1503
- }));
1501
+ };
1502
+ function mapIndexToCubeMapFace(layer) {
1503
+ return layer < 34069 ? layer + 34069 : layer;
1504
+ }
1505
+ function _getFrameBufferStatus(status) {
1506
+ switch (status) {
1507
+ case 36053:
1508
+ return "success";
1509
+ case 36054:
1510
+ return "Mismatched attachments";
1511
+ case 36055:
1512
+ return "No attachments";
1513
+ case 36057:
1514
+ return "Height/width mismatch";
1515
+ case 36061:
1516
+ return "Unsupported or split attachments";
1517
+ case 36182:
1518
+ return "Samples mismatch";
1519
+ default:
1520
+ return `${status}`;
1504
1521
  }
1505
- if (parameters.unclippedDepth) {
1506
- if (device.features.has("depth-clip-control")) {
1507
- gl.enable(34383);
1508
- }
1522
+ }
1523
+
1524
+ // dist/adapter/webgl-canvas-context.js
1525
+ var WebGLCanvasContext = class extends import_core5.CanvasContext {
1526
+ device;
1527
+ format = "rgba8unorm";
1528
+ depthStencilFormat = "depth24plus";
1529
+ presentationSize;
1530
+ _framebuffer = null;
1531
+ constructor(device, props) {
1532
+ super(props);
1533
+ this.device = device;
1534
+ this.presentationSize = [-1, -1];
1535
+ this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
1536
+ this.update();
1509
1537
  }
1510
- if (parameters.depthBias !== void 0) {
1511
- gl.enable(32823);
1512
- gl.polygonOffset(parameters.depthBias, parameters.depthBiasSlopeScale || 0);
1538
+ getCurrentFramebuffer() {
1539
+ this.update();
1540
+ this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
1541
+ return this._framebuffer;
1513
1542
  }
1514
- if (parameters.provokingVertex) {
1515
- if (device.features.has("provoking-vertex-webgl")) {
1516
- const extensions = webglDevice.getExtension("WEBGL_provoking_vertex");
1517
- const ext = extensions.WEBGL_provoking_vertex;
1518
- const vertex = map("provokingVertex", parameters.provokingVertex, {
1519
- first: 36429,
1520
- last: 36430
1521
- });
1522
- ext == null ? void 0 : ext.provokingVertexWEBGL(vertex);
1543
+ /** Resizes and updates render targets if necessary */
1544
+ update() {
1545
+ const size = this.getPixelSize();
1546
+ const sizeChanged = size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
1547
+ if (sizeChanged) {
1548
+ this.presentationSize = size;
1549
+ this.resize();
1523
1550
  }
1524
1551
  }
1525
- if (parameters.polygonMode || parameters.polygonOffsetLine) {
1526
- if (device.features.has("polygon-mode-webgl")) {
1527
- if (parameters.polygonMode) {
1528
- const extensions = webglDevice.getExtension("WEBGL_polygon_mode");
1529
- const ext = extensions.WEBGL_polygon_mode;
1530
- const mode = map("polygonMode", parameters.polygonMode, {
1531
- fill: 6914,
1532
- line: 6913
1533
- });
1534
- ext == null ? void 0 : ext.polygonModeWEBGL(1028, mode);
1535
- ext == null ? void 0 : ext.polygonModeWEBGL(1029, mode);
1536
- }
1537
- if (parameters.polygonOffsetLine) {
1538
- gl.enable(10754);
1539
- }
1552
+ /**
1553
+ * Resize the canvas' drawing buffer.
1554
+ *
1555
+ * Can match the canvas CSS size, and optionally also consider devicePixelRatio
1556
+ * Can be called every frame
1557
+ *
1558
+ * Regardless of size, the drawing buffer will always be scaled to the viewport, but
1559
+ * for best visual results, usually set to either:
1560
+ * canvas CSS width x canvas CSS height
1561
+ * canvas CSS width * devicePixelRatio x canvas CSS height * devicePixelRatio
1562
+ * See http://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
1563
+ */
1564
+ resize(options) {
1565
+ if (!this.device.gl)
1566
+ return;
1567
+ if (this.canvas) {
1568
+ const devicePixelRatio = this.getDevicePixelRatio(options == null ? void 0 : options.useDevicePixels);
1569
+ this.setDevicePixelRatio(devicePixelRatio, options);
1570
+ return;
1540
1571
  }
1541
1572
  }
1542
- if (device.features.has("shader-clip-cull-distance-webgl")) {
1543
- if (parameters.clipDistance0) {
1544
- gl.enable(12288);
1545
- }
1546
- if (parameters.clipDistance1) {
1547
- gl.enable(12289);
1548
- }
1549
- if (parameters.clipDistance2) {
1550
- gl.enable(12290);
1551
- }
1552
- if (parameters.clipDistance3) {
1553
- gl.enable(12291);
1554
- }
1555
- if (parameters.clipDistance4) {
1556
- gl.enable(12292);
1557
- }
1558
- if (parameters.clipDistance5) {
1559
- gl.enable(12293);
1560
- }
1561
- if (parameters.clipDistance6) {
1562
- gl.enable(12294);
1563
- }
1564
- if (parameters.clipDistance7) {
1565
- gl.enable(12295);
1566
- }
1573
+ commit() {
1567
1574
  }
1568
- if (parameters.depthWriteEnabled !== void 0) {
1569
- gl.depthMask(mapBoolean("depthWriteEnabled", parameters.depthWriteEnabled));
1575
+ };
1576
+
1577
+ // dist/context/debug/spector.js
1578
+ var import_core6 = require("@luma.gl/core");
1579
+
1580
+ // dist/utils/load-script.js
1581
+ async function loadScript(scriptUrl, scriptId) {
1582
+ const head = document.getElementsByTagName("head")[0];
1583
+ if (!head) {
1584
+ throw new Error("loadScript");
1570
1585
  }
1571
- if (parameters.depthCompare) {
1572
- parameters.depthCompare !== "always" ? gl.enable(2929) : gl.disable(2929);
1573
- gl.depthFunc(convertCompareFunction("depthCompare", parameters.depthCompare));
1586
+ const script = document.createElement("script");
1587
+ script.setAttribute("type", "text/javascript");
1588
+ script.setAttribute("src", scriptUrl);
1589
+ if (scriptId) {
1590
+ script.id = scriptId;
1574
1591
  }
1575
- if (parameters.stencilWriteMask) {
1576
- const mask = parameters.stencilWriteMask;
1577
- gl.stencilMaskSeparate(1028, mask);
1578
- gl.stencilMaskSeparate(1029, mask);
1592
+ return new Promise((resolve, reject) => {
1593
+ script.onload = resolve;
1594
+ script.onerror = (error) => reject(new Error(`Unable to load script '${scriptUrl}': ${error}`));
1595
+ head.appendChild(script);
1596
+ });
1597
+ }
1598
+
1599
+ // dist/context/debug/spector.js
1600
+ var LOG_LEVEL = 1;
1601
+ var spector = null;
1602
+ var initialized = false;
1603
+ var DEFAULT_SPECTOR_PROPS = {
1604
+ debugWithSpectorJS: import_core6.log.get("spector") || import_core6.log.get("spectorjs"),
1605
+ // https://github.com/BabylonJS/Spector.js#basic-usage
1606
+ // https://forum.babylonjs.com/t/spectorcdn-is-temporarily-off/48241
1607
+ // spectorUrl: 'https://spectorcdn.babylonjs.com/spector.bundle.js';
1608
+ spectorUrl: "https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js",
1609
+ gl: void 0
1610
+ };
1611
+ async function loadSpectorJS(props) {
1612
+ if (!globalThis.SPECTOR) {
1613
+ try {
1614
+ await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
1615
+ } catch (error) {
1616
+ import_core6.log.warn(String(error));
1617
+ }
1579
1618
  }
1580
- if (parameters.stencilReadMask) {
1581
- import_core4.log.warn("stencilReadMask not supported under WebGL");
1619
+ }
1620
+ function initializeSpectorJS(props) {
1621
+ var _a;
1622
+ props = { ...DEFAULT_SPECTOR_PROPS, ...props };
1623
+ if (!props.debugWithSpectorJS) {
1624
+ return null;
1582
1625
  }
1583
- if (parameters.stencilCompare) {
1584
- const mask = parameters.stencilReadMask || 4294967295;
1585
- const glValue = convertCompareFunction("depthCompare", parameters.stencilCompare);
1586
- parameters.stencilCompare !== "always" ? gl.enable(2960) : gl.disable(2960);
1587
- gl.stencilFuncSeparate(1028, glValue, 0, mask);
1588
- gl.stencilFuncSeparate(1029, glValue, 0, mask);
1626
+ if (!spector && globalThis.SPECTOR && !((_a = globalThis.luma) == null ? void 0 : _a.spector)) {
1627
+ import_core6.log.probe(LOG_LEVEL, "SPECTOR found and initialized. Start with `luma.spector.displayUI()`")();
1628
+ const { Spector } = globalThis.SPECTOR;
1629
+ spector = new Spector();
1630
+ if (globalThis.luma) {
1631
+ globalThis.luma.spector = spector;
1632
+ }
1589
1633
  }
1590
- if (parameters.stencilPassOperation && parameters.stencilFailOperation && parameters.stencilDepthFailOperation) {
1591
- const dppass = convertStencilOperation("stencilPassOperation", parameters.stencilPassOperation);
1592
- const sfail = convertStencilOperation("stencilFailOperation", parameters.stencilFailOperation);
1593
- const dpfail = convertStencilOperation("stencilDepthFailOperation", parameters.stencilDepthFailOperation);
1594
- gl.stencilOpSeparate(1028, sfail, dpfail, dppass);
1595
- gl.stencilOpSeparate(1029, sfail, dpfail, dppass);
1634
+ if (!spector) {
1635
+ return null;
1596
1636
  }
1597
- switch (parameters.blend) {
1598
- case true:
1599
- gl.enable(3042);
1600
- break;
1601
- case false:
1602
- gl.disable(3042);
1603
- break;
1604
- default:
1637
+ if (!initialized) {
1638
+ initialized = true;
1639
+ spector.spyCanvases();
1640
+ spector == null ? void 0 : spector.onCaptureStarted.add((capture) => import_core6.log.info("Spector capture started:", capture)());
1641
+ spector == null ? void 0 : spector.onCapture.add((capture) => {
1642
+ import_core6.log.info("Spector capture complete:", capture)();
1643
+ spector == null ? void 0 : spector.getResultUI();
1644
+ spector == null ? void 0 : spector.resultView.display();
1645
+ spector == null ? void 0 : spector.resultView.addCapture(capture);
1646
+ });
1605
1647
  }
1606
- if (parameters.blendColorOperation || parameters.blendAlphaOperation) {
1607
- const colorEquation = convertBlendOperationToEquation("blendColorOperation", parameters.blendColorOperation || "add");
1608
- const alphaEquation = convertBlendOperationToEquation("blendAlphaOperation", parameters.blendAlphaOperation || "add");
1609
- gl.blendEquationSeparate(colorEquation, alphaEquation);
1610
- const colorSrcFactor = convertBlendFactorToFunction("blendColorSrcFactor", parameters.blendColorSrcFactor || "one");
1611
- const colorDstFactor = convertBlendFactorToFunction("blendColorDstFactor", parameters.blendColorDstFactor || "zero");
1612
- const alphaSrcFactor = convertBlendFactorToFunction("blendAlphaSrcFactor", parameters.blendAlphaSrcFactor || "one");
1613
- const alphaDstFactor = convertBlendFactorToFunction("blendAlphaDstFactor", parameters.blendAlphaDstFactor || "zero");
1614
- gl.blendFuncSeparate(colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor);
1648
+ if (props.gl) {
1649
+ const gl = props.gl;
1650
+ const device = gl.device;
1651
+ spector == null ? void 0 : spector.startCapture(props.gl, 500);
1652
+ gl.device = device;
1653
+ new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
1654
+ import_core6.log.info("Spector capture stopped after 2 seconds")();
1655
+ spector == null ? void 0 : spector.stopCapture();
1656
+ });
1615
1657
  }
1658
+ return spector;
1616
1659
  }
1617
- function convertCompareFunction(parameter, value) {
1618
- return map(parameter, value, {
1619
- never: 512,
1620
- less: 513,
1621
- equal: 514,
1622
- "less-equal": 515,
1623
- greater: 516,
1624
- "not-equal": 517,
1625
- "greater-equal": 518,
1626
- always: 519
1627
- });
1628
- }
1629
- function convertStencilOperation(parameter, value) {
1630
- return map(parameter, value, {
1631
- keep: 7680,
1632
- zero: 0,
1633
- replace: 7681,
1634
- invert: 5386,
1635
- "increment-clamp": 7682,
1636
- "decrement-clamp": 7683,
1637
- "increment-wrap": 34055,
1638
- "decrement-wrap": 34056
1639
- });
1640
- }
1641
- function convertBlendOperationToEquation(parameter, value) {
1642
- return map(parameter, value, {
1643
- add: 32774,
1644
- subtract: 32778,
1645
- "reverse-subtract": 32779,
1646
- min: 32775,
1647
- max: 32776
1648
- });
1649
- }
1650
- function convertBlendFactorToFunction(parameter, value) {
1651
- return map(parameter, value, {
1652
- one: 1,
1653
- zero: 0,
1654
- "src-color": 768,
1655
- "one-minus-src-color": 769,
1656
- "dst-color": 774,
1657
- "one-minus-dst-color": 775,
1658
- "src-alpha": 770,
1659
- "one-minus-src-alpha": 771,
1660
- "dst-alpha": 772,
1661
- "one-minus-dst-alpha": 773,
1662
- "src-alpha-saturated": 776,
1663
- "constant-color": 32769,
1664
- "one-minus-constant-color": 32770,
1665
- "constant-alpha": 32771,
1666
- "one-minus-constant-alpha": 32772
1667
- });
1668
- }
1669
- function message(parameter, value) {
1670
- return `Illegal parameter ${value} for ${parameter}`;
1660
+
1661
+ // dist/context/debug/webgl-developer-tools.js
1662
+ var import_core7 = require("@luma.gl/core");
1663
+ var import_constants7 = require("@luma.gl/constants");
1664
+ var import_env = require("@probe.gl/env");
1665
+ var WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
1666
+ function getWebGLContextData(gl) {
1667
+ gl.luma = gl.luma || {};
1668
+ return gl.luma;
1671
1669
  }
1672
- function map(parameter, value, valueMap) {
1673
- if (!(value in valueMap)) {
1674
- throw new Error(message(parameter, value));
1670
+ async function loadWebGLDeveloperTools() {
1671
+ if ((0, import_env.isBrowser)() && !globalThis.WebGLDebugUtils) {
1672
+ globalThis.global = globalThis.global || globalThis;
1673
+ globalThis.global.module = {};
1674
+ await loadScript(WEBGL_DEBUG_CDN_URL);
1675
1675
  }
1676
- return valueMap[value];
1677
1676
  }
1678
- function mapBoolean(parameter, value) {
1679
- return value;
1677
+ function makeDebugContext(gl, props = {}) {
1678
+ return props.debug ? getDebugContext(gl, props) : getRealContext(gl);
1680
1679
  }
1681
- function isObjectEmpty3(obj) {
1682
- let isEmpty = true;
1683
- for (const key in obj) {
1684
- isEmpty = false;
1685
- break;
1686
- }
1687
- return isEmpty;
1680
+ function getRealContext(gl) {
1681
+ const data = getWebGLContextData(gl);
1682
+ return data.realContext ? data.realContext : gl;
1688
1683
  }
1689
-
1690
- // dist/adapter/converters/sampler-parameters.js
1691
- function convertSamplerParametersToWebGL(props) {
1692
- const params = {};
1693
- if (props.addressModeU) {
1694
- params[10242] = convertAddressMode(props.addressModeU);
1684
+ function getDebugContext(gl, props) {
1685
+ if (!globalThis.WebGLDebugUtils) {
1686
+ import_core7.log.warn("webgl-debug not loaded")();
1687
+ return gl;
1695
1688
  }
1696
- if (props.addressModeV) {
1697
- params[10243] = convertAddressMode(props.addressModeV);
1689
+ const data = getWebGLContextData(gl);
1690
+ if (data.debugContext) {
1691
+ return data.debugContext;
1698
1692
  }
1699
- if (props.addressModeW) {
1700
- params[32882] = convertAddressMode(props.addressModeW);
1693
+ globalThis.WebGLDebugUtils.init({ ...import_constants7.GL, ...gl });
1694
+ const glDebug = globalThis.WebGLDebugUtils.makeDebugContext(gl, onGLError.bind(null, props), onValidateGLFunc.bind(null, props));
1695
+ for (const key in import_constants7.GL) {
1696
+ if (!(key in glDebug) && typeof import_constants7.GL[key] === "number") {
1697
+ glDebug[key] = import_constants7.GL[key];
1698
+ }
1701
1699
  }
1702
- if (props.magFilter) {
1703
- params[10240] = convertMaxFilterMode(props.magFilter);
1700
+ class WebGLDebugContext {
1704
1701
  }
1705
- if (props.minFilter || props.mipmapFilter) {
1706
- params[10241] = convertMinFilterMode(props.minFilter || "linear", props.mipmapFilter);
1702
+ Object.setPrototypeOf(glDebug, Object.getPrototypeOf(gl));
1703
+ Object.setPrototypeOf(WebGLDebugContext, glDebug);
1704
+ const debugContext = Object.create(WebGLDebugContext);
1705
+ data.realContext = gl;
1706
+ data.debugContext = debugContext;
1707
+ debugContext.debug = true;
1708
+ return debugContext;
1709
+ }
1710
+ function getFunctionString(functionName, functionArgs) {
1711
+ functionArgs = Array.from(functionArgs).map((arg) => arg === void 0 ? "undefined" : arg);
1712
+ let args = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, functionArgs);
1713
+ args = `${args.slice(0, 100)}${args.length > 100 ? "..." : ""}`;
1714
+ return `gl.${functionName}(${args})`;
1715
+ }
1716
+ function onGLError(props, err, functionName, args) {
1717
+ args = Array.from(args).map((arg) => arg === void 0 ? "undefined" : arg);
1718
+ const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
1719
+ const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
1720
+ const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
1721
+ import_core7.log.error(message2)();
1722
+ debugger;
1723
+ if (props.throwOnError) {
1724
+ throw new Error(message2);
1707
1725
  }
1708
- if (props.lodMinClamp !== void 0) {
1709
- params[33082] = props.lodMinClamp;
1710
- }
1711
- if (props.lodMaxClamp !== void 0) {
1712
- params[33083] = props.lodMaxClamp;
1713
- }
1714
- if (props.type === "comparison-sampler") {
1715
- params[34892] = 34894;
1716
- }
1717
- if (props.compare) {
1718
- params[34893] = convertCompareFunction("compare", props.compare);
1719
- }
1720
- if (props.maxAnisotropy) {
1721
- params[34046] = props.maxAnisotropy;
1722
- }
1723
- return params;
1724
1726
  }
1725
- function convertAddressMode(addressMode) {
1726
- switch (addressMode) {
1727
- case "clamp-to-edge":
1728
- return 33071;
1729
- case "repeat":
1730
- return 10497;
1731
- case "mirror-repeat":
1732
- return 33648;
1733
- }
1734
- }
1735
- function convertMaxFilterMode(maxFilter) {
1736
- switch (maxFilter) {
1737
- case "nearest":
1738
- return 9728;
1739
- case "linear":
1740
- return 9729;
1727
+ function onValidateGLFunc(props, functionName, functionArgs) {
1728
+ let functionString = "";
1729
+ if (import_core7.log.level >= 1) {
1730
+ functionString = getFunctionString(functionName, functionArgs);
1731
+ import_core7.log.log(1, functionString)();
1741
1732
  }
1742
- }
1743
- function convertMinFilterMode(minFilter, mipmapFilter) {
1744
- if (!mipmapFilter) {
1745
- return convertMaxFilterMode(minFilter);
1733
+ if (props.break && props.break.length > 0) {
1734
+ functionString = functionString || getFunctionString(functionName, functionArgs);
1735
+ const isBreakpoint = props.break.every((breakOn) => functionString.indexOf(breakOn) !== -1);
1736
+ if (isBreakpoint) {
1737
+ debugger;
1738
+ }
1746
1739
  }
1747
- switch (minFilter) {
1748
- case "nearest":
1749
- return mipmapFilter === "nearest" ? 9984 : 9986;
1750
- case "linear":
1751
- return mipmapFilter === "nearest" ? 9985 : 9987;
1740
+ for (const arg of functionArgs) {
1741
+ if (arg === void 0) {
1742
+ functionString = functionString || getFunctionString(functionName, functionArgs);
1743
+ if (props.throwOnError) {
1744
+ throw new Error(`Undefined argument: ${functionString}`);
1745
+ } else {
1746
+ import_core7.log.error(`Undefined argument: ${functionString}`)();
1747
+ debugger;
1748
+ }
1749
+ }
1752
1750
  }
1753
1751
  }
1754
1752
 
1755
- // dist/adapter/resources/webgl-sampler.js
1756
- var import_core5 = require("@luma.gl/core");
1753
+ // dist/utils/uid.js
1754
+ var uidCounters = {};
1755
+ function uid(id = "id") {
1756
+ uidCounters[id] = uidCounters[id] || 1;
1757
+ const count = uidCounters[id]++;
1758
+ return `${id}-${count}`;
1759
+ }
1760
+
1761
+ // dist/adapter/resources/webgl-buffer.js
1762
+ var import_core8 = require("@luma.gl/core");
1757
1763
  var import_constants8 = require("@luma.gl/constants");
1758
- var WEBGLSampler = class extends import_core5.Sampler {
1764
+ var WEBGLBuffer = class extends import_core8.Buffer {
1759
1765
  device;
1766
+ gl;
1760
1767
  handle;
1761
- parameters;
1762
- constructor(device, props) {
1768
+ /** Target in OpenGL defines the type of buffer */
1769
+ glTarget;
1770
+ /** Usage is a hint on how frequently the buffer will be updates */
1771
+ glUsage;
1772
+ /** Index type is needed when issuing draw calls, so we pre-compute it */
1773
+ glIndexType = 5123;
1774
+ /** Number of bytes allocated on the GPU for this buffer */
1775
+ byteLength;
1776
+ /** Number of bytes used */
1777
+ bytesUsed;
1778
+ constructor(device, props = {}) {
1763
1779
  super(device, props);
1764
1780
  this.device = device;
1765
- this.parameters = convertSamplerParametersToWebGL(props);
1766
- this.handle = this.handle || this.device.gl.createSampler();
1767
- this._setSamplerParameters(this.parameters);
1781
+ this.gl = this.device.gl;
1782
+ const handle = typeof props === "object" ? props.handle : void 0;
1783
+ this.handle = handle || this.gl.createBuffer();
1784
+ device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
1785
+ this.glTarget = getWebGLTarget(this.props.usage);
1786
+ this.glUsage = getWebGLUsage(this.props.usage);
1787
+ this.glIndexType = this.props.indexType === "uint32" ? 5125 : 5123;
1788
+ if (props.data) {
1789
+ this._initWithData(props.data, props.byteOffset, props.byteLength);
1790
+ } else {
1791
+ this._initWithByteLength(props.byteLength || 0);
1792
+ }
1768
1793
  }
1769
- destroy() {
1770
- if (this.handle) {
1771
- this.device.gl.deleteSampler(this.handle);
1772
- this.handle = void 0;
1794
+ // PRIVATE METHODS
1795
+ /** Allocate a new buffer and initialize to contents of typed array */
1796
+ _initWithData(data, byteOffset = 0, byteLength = data.byteLength + byteOffset) {
1797
+ const glTarget = this.glTarget;
1798
+ this.gl.bindBuffer(glTarget, this.handle);
1799
+ this.gl.bufferData(glTarget, byteLength, this.glUsage);
1800
+ this.gl.bufferSubData(glTarget, byteOffset, data);
1801
+ this.gl.bindBuffer(glTarget, null);
1802
+ this.bytesUsed = byteLength;
1803
+ this.byteLength = byteLength;
1804
+ this._setDebugData(data, byteOffset, byteLength);
1805
+ this.trackAllocatedMemory(byteLength);
1806
+ }
1807
+ // Allocate a GPU buffer of specified size.
1808
+ _initWithByteLength(byteLength) {
1809
+ let data = byteLength;
1810
+ if (byteLength === 0) {
1811
+ data = new Float32Array(0);
1773
1812
  }
1813
+ const glTarget = this.glTarget;
1814
+ this.gl.bindBuffer(glTarget, this.handle);
1815
+ this.gl.bufferData(glTarget, data, this.glUsage);
1816
+ this.gl.bindBuffer(glTarget, null);
1817
+ this.bytesUsed = byteLength;
1818
+ this.byteLength = byteLength;
1819
+ this._setDebugData(null, 0, byteLength);
1820
+ this.trackAllocatedMemory(byteLength);
1821
+ return this;
1774
1822
  }
1775
- toString() {
1776
- return `Sampler(${this.id},${JSON.stringify(this.props)})`;
1823
+ destroy() {
1824
+ if (!this.destroyed && this.handle) {
1825
+ this.removeStats();
1826
+ this.trackDeallocatedMemory();
1827
+ this.gl.deleteBuffer(this.handle);
1828
+ this.destroyed = true;
1829
+ this.handle = null;
1830
+ }
1777
1831
  }
1778
- /** Set sampler parameters on the sampler */
1779
- _setSamplerParameters(parameters) {
1780
- for (const [pname, value] of Object.entries(parameters)) {
1781
- const param = Number(pname);
1782
- switch (param) {
1783
- case 33082:
1784
- case 33083:
1785
- this.device.gl.samplerParameterf(this.handle, param, value);
1786
- break;
1787
- default:
1788
- this.device.gl.samplerParameteri(this.handle, param, value);
1789
- break;
1790
- }
1832
+ write(data, byteOffset = 0) {
1833
+ const srcOffset = 0;
1834
+ const byteLength = void 0;
1835
+ const glTarget = 36663;
1836
+ this.gl.bindBuffer(glTarget, this.handle);
1837
+ if (srcOffset !== 0 || byteLength !== void 0) {
1838
+ this.gl.bufferSubData(glTarget, byteOffset, data, srcOffset, byteLength);
1839
+ } else {
1840
+ this.gl.bufferSubData(glTarget, byteOffset, data);
1791
1841
  }
1842
+ this.gl.bindBuffer(glTarget, null);
1843
+ this._setDebugData(data, byteOffset, data.byteLength);
1844
+ }
1845
+ /** Asynchronously read data from the buffer */
1846
+ async readAsync(byteOffset = 0, byteLength) {
1847
+ return this.readSyncWebGL(byteOffset, byteLength);
1848
+ }
1849
+ /** Synchronously read data from the buffer. WebGL only. */
1850
+ readSyncWebGL(byteOffset = 0, byteLength) {
1851
+ byteLength = byteLength ?? this.byteLength - byteOffset;
1852
+ const data = new Uint8Array(byteLength);
1853
+ const dstOffset = 0;
1854
+ this.gl.bindBuffer(36662, this.handle);
1855
+ this.gl.getBufferSubData(36662, byteOffset, data, dstOffset, byteLength);
1856
+ this.gl.bindBuffer(36662, null);
1857
+ this._setDebugData(data, byteOffset, byteLength);
1858
+ return data;
1792
1859
  }
1793
1860
  };
1861
+ function getWebGLTarget(usage) {
1862
+ if (usage & import_core8.Buffer.INDEX) {
1863
+ return 34963;
1864
+ }
1865
+ if (usage & import_core8.Buffer.VERTEX) {
1866
+ return 34962;
1867
+ }
1868
+ if (usage & import_core8.Buffer.UNIFORM) {
1869
+ return 35345;
1870
+ }
1871
+ return 34962;
1872
+ }
1873
+ function getWebGLUsage(usage) {
1874
+ if (usage & import_core8.Buffer.INDEX) {
1875
+ return 35044;
1876
+ }
1877
+ if (usage & import_core8.Buffer.VERTEX) {
1878
+ return 35044;
1879
+ }
1880
+ if (usage & import_core8.Buffer.UNIFORM) {
1881
+ return 35048;
1882
+ }
1883
+ return 35044;
1884
+ }
1794
1885
 
1795
- // dist/adapter/resources/webgl-texture-view.js
1796
- var import_core6 = require("@luma.gl/core");
1797
- var WEBGLTextureView = class extends import_core6.TextureView {
1886
+ // dist/adapter/resources/webgl-shader.js
1887
+ var import_core9 = require("@luma.gl/core");
1888
+ var import_constants9 = require("@luma.gl/constants");
1889
+
1890
+ // dist/adapter/helpers/parse-shader-compiler-log.js
1891
+ function parseShaderCompilerLog(errLog) {
1892
+ const lines = errLog.split(/\r?\n/);
1893
+ const messages = [];
1894
+ for (const line of lines) {
1895
+ if (line.length <= 1) {
1896
+ continue;
1897
+ }
1898
+ const segments = line.split(":");
1899
+ if (segments.length === 2) {
1900
+ const [messageType2, message2] = segments;
1901
+ messages.push({
1902
+ message: message2.trim(),
1903
+ type: getMessageType(messageType2),
1904
+ lineNum: 0,
1905
+ linePos: 0
1906
+ });
1907
+ continue;
1908
+ }
1909
+ const [messageType, linePosition, lineNumber, ...rest] = segments;
1910
+ let lineNum = parseInt(lineNumber, 10);
1911
+ if (isNaN(lineNum)) {
1912
+ lineNum = 0;
1913
+ }
1914
+ let linePos = parseInt(linePosition, 10);
1915
+ if (isNaN(linePos)) {
1916
+ linePos = 0;
1917
+ }
1918
+ messages.push({
1919
+ message: rest.join(":").trim(),
1920
+ type: getMessageType(messageType),
1921
+ lineNum,
1922
+ linePos
1923
+ // TODO
1924
+ });
1925
+ }
1926
+ return messages;
1927
+ }
1928
+ function getMessageType(messageType) {
1929
+ const MESSAGE_TYPES = ["warning", "error", "info"];
1930
+ const lowerCaseType = messageType.toLowerCase();
1931
+ return MESSAGE_TYPES.includes(lowerCaseType) ? lowerCaseType : "info";
1932
+ }
1933
+
1934
+ // dist/adapter/resources/webgl-shader.js
1935
+ var WEBGLShader = class extends import_core9.Shader {
1798
1936
  device;
1799
- gl;
1800
1937
  handle;
1801
- // Does not have a WebGL representation
1802
- texture;
1803
1938
  constructor(device, props) {
1804
- super(device, { ...import_core6.Texture.defaultProps, ...props });
1939
+ super(device, props);
1805
1940
  this.device = device;
1806
- this.gl = this.device.gl;
1807
- this.handle = null;
1808
- this.texture = props.texture;
1941
+ switch (this.props.stage) {
1942
+ case "vertex":
1943
+ this.handle = this.props.handle || this.device.gl.createShader(35633);
1944
+ break;
1945
+ case "fragment":
1946
+ this.handle = this.props.handle || this.device.gl.createShader(35632);
1947
+ break;
1948
+ default:
1949
+ throw new Error(this.props.stage);
1950
+ }
1951
+ this._compile(this.source);
1952
+ }
1953
+ destroy() {
1954
+ if (this.handle) {
1955
+ this.removeStats();
1956
+ this.device.gl.deleteShader(this.handle);
1957
+ this.destroyed = true;
1958
+ }
1959
+ }
1960
+ async getCompilationInfo() {
1961
+ await this._waitForCompilationComplete();
1962
+ return this.getCompilationInfoSync();
1963
+ }
1964
+ getCompilationInfoSync() {
1965
+ const log12 = this.device.gl.getShaderInfoLog(this.handle);
1966
+ return log12 ? parseShaderCompilerLog(log12) : [];
1967
+ }
1968
+ getTranslatedSource() {
1969
+ const extensions = this.device.getExtension("WEBGL_debug_shaders");
1970
+ const ext = extensions.WEBGL_debug_shaders;
1971
+ return (ext == null ? void 0 : ext.getTranslatedShaderSource(this.handle)) || null;
1972
+ }
1973
+ // PRIVATE METHODS
1974
+ /** Compile a shader and get compilation status */
1975
+ async _compile(source) {
1976
+ const addGLSLVersion = (source2) => source2.startsWith("#version ") ? source2 : `#version 300 es
1977
+ ${source2}`;
1978
+ source = addGLSLVersion(source);
1979
+ const { gl } = this.device;
1980
+ gl.shaderSource(this.handle, source);
1981
+ gl.compileShader(this.handle);
1982
+ if (import_core9.log.level === 0) {
1983
+ this.compilationStatus = "pending";
1984
+ return;
1985
+ }
1986
+ if (!this.device.features.has("compilation-status-async-webgl")) {
1987
+ this._getCompilationStatus();
1988
+ this.debugShader();
1989
+ if (this.compilationStatus === "error") {
1990
+ throw new Error(`GLSL compilation errors in ${this.props.stage} shader ${this.props.id}`);
1991
+ }
1992
+ return;
1993
+ }
1994
+ import_core9.log.once(1, "Shader compilation is asynchronous")();
1995
+ await this._waitForCompilationComplete();
1996
+ import_core9.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
1997
+ this._getCompilationStatus();
1998
+ this.debugShader();
1999
+ }
2000
+ /** Use KHR_parallel_shader_compile extension if available */
2001
+ async _waitForCompilationComplete() {
2002
+ const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
2003
+ const DELAY_MS = 10;
2004
+ if (!this.device.features.has("compilation-status-async-webgl")) {
2005
+ await waitMs(DELAY_MS);
2006
+ return;
2007
+ }
2008
+ const { gl } = this.device;
2009
+ for (; ; ) {
2010
+ const complete = gl.getShaderParameter(this.handle, 37297);
2011
+ if (complete) {
2012
+ return;
2013
+ }
2014
+ await waitMs(DELAY_MS);
2015
+ }
2016
+ }
2017
+ /**
2018
+ * Get the shader compilation status
2019
+ * TODO - Load log even when no error reported, to catch warnings?
2020
+ * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
2021
+ */
2022
+ _getCompilationStatus() {
2023
+ this.compilationStatus = this.device.gl.getShaderParameter(this.handle, 35713) ? "success" : "error";
1809
2024
  }
1810
2025
  };
1811
2026
 
1812
- // dist/adapter/helpers/webgl-texture-utils.js
1813
- var import_core7 = require("@luma.gl/core");
2027
+ // dist/adapter/resources/webgl-sampler.js
2028
+ var import_core11 = require("@luma.gl/core");
2029
+ var import_constants12 = require("@luma.gl/constants");
2030
+
2031
+ // dist/adapter/converters/sampler-parameters.js
1814
2032
  var import_constants11 = require("@luma.gl/constants");
1815
2033
 
1816
- // dist/adapter/helpers/typed-array-utils.js
1817
- var import_constants9 = require("@luma.gl/constants");
1818
- var ERR_TYPE_DEDUCTION = "Failed to deduce GL constant from typed array";
1819
- function getGLTypeFromTypedArray(arrayOrType) {
1820
- const type = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
1821
- switch (type) {
1822
- case Float32Array:
1823
- return 5126;
1824
- case Uint16Array:
1825
- return 5123;
1826
- case Uint32Array:
1827
- return 5125;
1828
- case Uint8Array:
1829
- return 5121;
1830
- case Uint8ClampedArray:
1831
- return 5121;
1832
- case Int8Array:
1833
- return 5120;
1834
- case Int16Array:
1835
- return 5122;
1836
- case Int32Array:
1837
- return 5124;
1838
- default:
1839
- throw new Error(ERR_TYPE_DEDUCTION);
2034
+ // dist/adapter/converters/device-parameters.js
2035
+ var import_core10 = require("@luma.gl/core");
2036
+ var import_constants10 = require("@luma.gl/constants");
2037
+ function withDeviceAndGLParameters(device, parameters, glParameters, func) {
2038
+ if (isObjectEmpty2(parameters)) {
2039
+ return func(device);
1840
2040
  }
1841
- }
1842
- function getTypedArrayFromGLType(glType, options) {
1843
- const { clamped = true } = options || {};
1844
- switch (glType) {
1845
- case 5126:
1846
- return Float32Array;
1847
- case 5123:
1848
- case 33635:
1849
- case 32819:
1850
- case 32820:
1851
- return Uint16Array;
1852
- case 5125:
1853
- return Uint32Array;
1854
- case 5121:
1855
- return clamped ? Uint8ClampedArray : Uint8Array;
1856
- case 5120:
1857
- return Int8Array;
1858
- case 5122:
1859
- return Int16Array;
1860
- case 5124:
1861
- return Int32Array;
1862
- default:
1863
- throw new Error("Failed to deduce typed array type from GL constant");
2041
+ const webglDevice = device;
2042
+ webglDevice.pushState();
2043
+ try {
2044
+ setDeviceParameters(device, parameters);
2045
+ setGLParameters(webglDevice.gl, glParameters);
2046
+ return func(device);
2047
+ } finally {
2048
+ webglDevice.popState();
1864
2049
  }
1865
2050
  }
1866
-
1867
- // dist/adapter/helpers/format-utils.js
1868
- var import_constants10 = require("@luma.gl/constants");
1869
- function glFormatToComponents(format) {
1870
- switch (format) {
1871
- case 6406:
1872
- case 33326:
1873
- case 6403:
1874
- return 1;
1875
- case 33328:
1876
- case 33319:
1877
- return 2;
1878
- case 6407:
1879
- case 34837:
1880
- return 3;
1881
- case 6408:
1882
- case 34836:
1883
- return 4;
1884
- default:
1885
- return 0;
2051
+ function withDeviceParameters(device, parameters, func) {
2052
+ if (isObjectEmpty2(parameters)) {
2053
+ return func(device);
1886
2054
  }
1887
- }
1888
- function glTypeToBytes(type) {
1889
- switch (type) {
1890
- case 5121:
1891
- return 1;
1892
- case 33635:
1893
- case 32819:
1894
- case 32820:
1895
- return 2;
1896
- case 5126:
1897
- return 4;
1898
- default:
1899
- return 0;
2055
+ const webglDevice = device;
2056
+ webglDevice.pushState();
2057
+ try {
2058
+ setDeviceParameters(device, parameters);
2059
+ return func(device);
2060
+ } finally {
2061
+ webglDevice.popState();
1900
2062
  }
1901
2063
  }
1902
-
1903
- // dist/adapter/helpers/webgl-texture-utils.js
1904
- function initializeTextureStorage(gl, levels, options) {
1905
- const { dimension, width, height, depth = 0 } = options;
1906
- const { glInternalFormat } = options;
1907
- const glTarget = options.glTarget;
1908
- switch (dimension) {
1909
- case "2d-array":
1910
- case "3d":
1911
- gl.texStorage3D(glTarget, levels, glInternalFormat, width, height, depth);
1912
- break;
1913
- default:
1914
- gl.texStorage2D(glTarget, levels, glInternalFormat, width, height);
2064
+ function setDeviceParameters(device, parameters) {
2065
+ const webglDevice = device;
2066
+ const { gl } = webglDevice;
2067
+ if (parameters.cullMode) {
2068
+ switch (parameters.cullMode) {
2069
+ case "none":
2070
+ gl.disable(2884);
2071
+ break;
2072
+ case "front":
2073
+ gl.enable(2884);
2074
+ gl.cullFace(1028);
2075
+ break;
2076
+ case "back":
2077
+ gl.enable(2884);
2078
+ gl.cullFace(1029);
2079
+ break;
2080
+ }
1915
2081
  }
1916
- }
1917
- function copyExternalImageToMipLevel(gl, handle, image, options) {
1918
- const { width, height } = options;
1919
- const { dimension, depth = 0, mipLevel = 0 } = options;
1920
- const { x = 0, y = 0, z = 0 } = options;
1921
- const { glFormat, glType } = options;
1922
- const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
1923
- switch (dimension) {
1924
- case "2d-array":
1925
- case "3d":
1926
- gl.bindTexture(glTarget, handle);
1927
- gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
1928
- gl.bindTexture(glTarget, null);
1929
- break;
1930
- case "2d":
1931
- case "cube":
1932
- gl.bindTexture(glTarget, handle);
1933
- gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
1934
- gl.bindTexture(glTarget, null);
1935
- break;
1936
- default:
1937
- throw new Error(dimension);
2082
+ if (parameters.frontFace) {
2083
+ gl.frontFace(map("frontFace", parameters.frontFace, {
2084
+ ccw: 2305,
2085
+ cw: 2304
2086
+ }));
1938
2087
  }
1939
- }
1940
- function copyCPUDataToMipLevel(gl, typedArray, options) {
1941
- const { dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0 } = options;
1942
- const { x = 0, y = 0, z = 0 } = options;
1943
- const { glFormat, glType, compressed } = options;
1944
- const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
1945
- switch (dimension) {
1946
- case "2d-array":
1947
- case "3d":
1948
- if (compressed) {
1949
- gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
1950
- } else {
1951
- gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
2088
+ if (parameters.unclippedDepth) {
2089
+ if (device.features.has("depth-clip-control")) {
2090
+ gl.enable(34383);
2091
+ }
2092
+ }
2093
+ if (parameters.depthBias !== void 0) {
2094
+ gl.enable(32823);
2095
+ gl.polygonOffset(parameters.depthBias, parameters.depthBiasSlopeScale || 0);
2096
+ }
2097
+ if (parameters.provokingVertex) {
2098
+ if (device.features.has("provoking-vertex-webgl")) {
2099
+ const extensions = webglDevice.getExtension("WEBGL_provoking_vertex");
2100
+ const ext = extensions.WEBGL_provoking_vertex;
2101
+ const vertex = map("provokingVertex", parameters.provokingVertex, {
2102
+ first: 36429,
2103
+ last: 36430
2104
+ });
2105
+ ext == null ? void 0 : ext.provokingVertexWEBGL(vertex);
2106
+ }
2107
+ }
2108
+ if (parameters.polygonMode || parameters.polygonOffsetLine) {
2109
+ if (device.features.has("polygon-mode-webgl")) {
2110
+ if (parameters.polygonMode) {
2111
+ const extensions = webglDevice.getExtension("WEBGL_polygon_mode");
2112
+ const ext = extensions.WEBGL_polygon_mode;
2113
+ const mode = map("polygonMode", parameters.polygonMode, {
2114
+ fill: 6914,
2115
+ line: 6913
2116
+ });
2117
+ ext == null ? void 0 : ext.polygonModeWEBGL(1028, mode);
2118
+ ext == null ? void 0 : ext.polygonModeWEBGL(1029, mode);
1952
2119
  }
1953
- break;
1954
- case "2d":
1955
- case "cube":
1956
- if (compressed) {
1957
- gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
1958
- } else {
1959
- gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
2120
+ if (parameters.polygonOffsetLine) {
2121
+ gl.enable(10754);
1960
2122
  }
1961
- break;
1962
- default:
1963
- throw new Error(dimension);
2123
+ }
1964
2124
  }
1965
- }
1966
- function getWebGLTextureTarget(dimension) {
1967
- switch (dimension) {
1968
- case "1d":
2125
+ if (device.features.has("shader-clip-cull-distance-webgl")) {
2126
+ if (parameters.clipDistance0) {
2127
+ gl.enable(12288);
2128
+ }
2129
+ if (parameters.clipDistance1) {
2130
+ gl.enable(12289);
2131
+ }
2132
+ if (parameters.clipDistance2) {
2133
+ gl.enable(12290);
2134
+ }
2135
+ if (parameters.clipDistance3) {
2136
+ gl.enable(12291);
2137
+ }
2138
+ if (parameters.clipDistance4) {
2139
+ gl.enable(12292);
2140
+ }
2141
+ if (parameters.clipDistance5) {
2142
+ gl.enable(12293);
2143
+ }
2144
+ if (parameters.clipDistance6) {
2145
+ gl.enable(12294);
2146
+ }
2147
+ if (parameters.clipDistance7) {
2148
+ gl.enable(12295);
2149
+ }
2150
+ }
2151
+ if (parameters.depthWriteEnabled !== void 0) {
2152
+ gl.depthMask(mapBoolean("depthWriteEnabled", parameters.depthWriteEnabled));
2153
+ }
2154
+ if (parameters.depthCompare) {
2155
+ parameters.depthCompare !== "always" ? gl.enable(2929) : gl.disable(2929);
2156
+ gl.depthFunc(convertCompareFunction("depthCompare", parameters.depthCompare));
2157
+ }
2158
+ if (parameters.stencilWriteMask) {
2159
+ const mask = parameters.stencilWriteMask;
2160
+ gl.stencilMaskSeparate(1028, mask);
2161
+ gl.stencilMaskSeparate(1029, mask);
2162
+ }
2163
+ if (parameters.stencilReadMask) {
2164
+ import_core10.log.warn("stencilReadMask not supported under WebGL");
2165
+ }
2166
+ if (parameters.stencilCompare) {
2167
+ const mask = parameters.stencilReadMask || 4294967295;
2168
+ const glValue = convertCompareFunction("depthCompare", parameters.stencilCompare);
2169
+ parameters.stencilCompare !== "always" ? gl.enable(2960) : gl.disable(2960);
2170
+ gl.stencilFuncSeparate(1028, glValue, 0, mask);
2171
+ gl.stencilFuncSeparate(1029, glValue, 0, mask);
2172
+ }
2173
+ if (parameters.stencilPassOperation && parameters.stencilFailOperation && parameters.stencilDepthFailOperation) {
2174
+ const dppass = convertStencilOperation("stencilPassOperation", parameters.stencilPassOperation);
2175
+ const sfail = convertStencilOperation("stencilFailOperation", parameters.stencilFailOperation);
2176
+ const dpfail = convertStencilOperation("stencilDepthFailOperation", parameters.stencilDepthFailOperation);
2177
+ gl.stencilOpSeparate(1028, sfail, dpfail, dppass);
2178
+ gl.stencilOpSeparate(1029, sfail, dpfail, dppass);
2179
+ }
2180
+ switch (parameters.blend) {
2181
+ case true:
2182
+ gl.enable(3042);
1969
2183
  break;
1970
- case "2d":
1971
- return 3553;
1972
- case "3d":
1973
- return 32879;
1974
- case "cube":
1975
- return 34067;
1976
- case "2d-array":
1977
- return 35866;
1978
- case "cube-array":
2184
+ case false:
2185
+ gl.disable(3042);
1979
2186
  break;
2187
+ default:
1980
2188
  }
1981
- throw new Error(dimension);
1982
- }
1983
- function getWebGLCubeFaceTarget(glTarget, dimension, level) {
1984
- return dimension === "cube" ? 34069 + level : glTarget;
1985
- }
1986
- function readPixelsToArray(source, options) {
1987
- var _a, _b, _c, _d, _e, _f;
1988
- const {
1989
- sourceX = 0,
1990
- sourceY = 0,
1991
- sourceAttachment = 36064
1992
- // TODO - support gl.readBuffer
1993
- } = options || {};
1994
- let {
1995
- target = null,
1996
- // following parameters are auto deduced if not provided
1997
- sourceWidth,
1998
- sourceHeight,
1999
- sourceDepth,
2000
- sourceFormat,
2001
- sourceType
2002
- } = options || {};
2003
- const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
2004
- const { gl, handle } = framebuffer;
2005
- const attachment = sourceAttachment - 36064;
2006
- sourceWidth ||= framebuffer.width;
2007
- sourceHeight ||= framebuffer.height;
2008
- sourceDepth = ((_b = (_a = framebuffer.colorAttachments[attachment]) == null ? void 0 : _a.texture) == null ? void 0 : _b.depth) || 1;
2009
- sourceFormat ||= ((_d = (_c = framebuffer.colorAttachments[attachment]) == null ? void 0 : _c.texture) == null ? void 0 : _d.glFormat) || 6408;
2010
- sourceType ||= ((_f = (_e = framebuffer.colorAttachments[attachment]) == null ? void 0 : _e.texture) == null ? void 0 : _f.glType) || 5121;
2011
- target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
2012
- sourceType = sourceType || getGLTypeFromTypedArray(target);
2013
- const prevHandle = gl.bindFramebuffer(36160, handle);
2014
- gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
2015
- gl.bindFramebuffer(36160, prevHandle || null);
2016
- if (deleteFramebuffer) {
2017
- framebuffer.destroy();
2189
+ if (parameters.blendColorOperation || parameters.blendAlphaOperation) {
2190
+ const colorEquation = convertBlendOperationToEquation("blendColorOperation", parameters.blendColorOperation || "add");
2191
+ const alphaEquation = convertBlendOperationToEquation("blendAlphaOperation", parameters.blendAlphaOperation || "add");
2192
+ gl.blendEquationSeparate(colorEquation, alphaEquation);
2193
+ const colorSrcFactor = convertBlendFactorToFunction("blendColorSrcFactor", parameters.blendColorSrcFactor || "one");
2194
+ const colorDstFactor = convertBlendFactorToFunction("blendColorDstFactor", parameters.blendColorDstFactor || "zero");
2195
+ const alphaSrcFactor = convertBlendFactorToFunction("blendAlphaSrcFactor", parameters.blendAlphaSrcFactor || "one");
2196
+ const alphaDstFactor = convertBlendFactorToFunction("blendAlphaDstFactor", parameters.blendAlphaDstFactor || "zero");
2197
+ gl.blendFuncSeparate(colorSrcFactor, colorDstFactor, alphaSrcFactor, alphaDstFactor);
2018
2198
  }
2019
- return target;
2020
2199
  }
2021
- function readPixelsToBuffer(source, options) {
2022
- const { target, sourceX = 0, sourceY = 0, sourceFormat = 6408, targetByteOffset = 0 } = options || {};
2023
- let { sourceWidth, sourceHeight, sourceType } = options || {};
2024
- const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
2025
- sourceWidth = sourceWidth || framebuffer.width;
2026
- sourceHeight = sourceHeight || framebuffer.height;
2027
- const webglFramebuffer = framebuffer;
2028
- sourceType = sourceType || 5121;
2029
- let webglBufferTarget = target;
2030
- if (!webglBufferTarget) {
2031
- const components = glFormatToComponents(sourceFormat);
2032
- const byteCount = glTypeToBytes(sourceType);
2033
- const byteLength = targetByteOffset + sourceWidth * sourceHeight * components * byteCount;
2034
- webglBufferTarget = webglFramebuffer.device.createBuffer({ byteLength });
2035
- }
2036
- const commandEncoder = source.device.createCommandEncoder();
2037
- commandEncoder.copyTextureToBuffer({
2038
- source,
2039
- width: sourceWidth,
2040
- height: sourceHeight,
2041
- origin: [sourceX, sourceY],
2042
- destination: webglBufferTarget,
2043
- byteOffset: targetByteOffset
2200
+ function convertCompareFunction(parameter, value) {
2201
+ return map(parameter, value, {
2202
+ never: 512,
2203
+ less: 513,
2204
+ equal: 514,
2205
+ "less-equal": 515,
2206
+ greater: 516,
2207
+ "not-equal": 517,
2208
+ "greater-equal": 518,
2209
+ always: 519
2044
2210
  });
2045
- commandEncoder.destroy();
2046
- if (deleteFramebuffer) {
2047
- framebuffer.destroy();
2048
- }
2049
- return webglBufferTarget;
2050
- }
2051
- function getFramebuffer(source) {
2052
- if (!(source instanceof import_core7.Framebuffer)) {
2053
- return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
2054
- }
2055
- return { framebuffer: source, deleteFramebuffer: false };
2056
2211
  }
2057
- function toFramebuffer(texture, props) {
2058
- const { device, width, height, id } = texture;
2059
- const framebuffer = device.createFramebuffer({
2060
- ...props,
2061
- id: `framebuffer-for-${id}`,
2062
- width,
2063
- height,
2064
- colorAttachments: [texture]
2212
+ function convertStencilOperation(parameter, value) {
2213
+ return map(parameter, value, {
2214
+ keep: 7680,
2215
+ zero: 0,
2216
+ replace: 7681,
2217
+ invert: 5386,
2218
+ "increment-clamp": 7682,
2219
+ "decrement-clamp": 7683,
2220
+ "increment-wrap": 34055,
2221
+ "decrement-wrap": 34056
2065
2222
  });
2066
- return framebuffer;
2067
2223
  }
2068
- function getPixelArray(pixelArray, type, format, width, height, depth) {
2069
- if (pixelArray) {
2070
- return pixelArray;
2071
- }
2072
- type = type || 5121;
2073
- const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
2074
- const components = glFormatToComponents(format);
2075
- return new ArrayType(width * height * components);
2224
+ function convertBlendOperationToEquation(parameter, value) {
2225
+ return map(parameter, value, {
2226
+ add: 32774,
2227
+ subtract: 32778,
2228
+ "reverse-subtract": 32779,
2229
+ min: 32775,
2230
+ max: 32776
2231
+ });
2076
2232
  }
2077
-
2078
- // dist/adapter/resources/webgl-texture.js
2079
- function normalizeTextureData(data, options) {
2080
- let lodArray;
2081
- if (ArrayBuffer.isView(data)) {
2082
- lodArray = [
2083
- {
2084
- // ts-expect-error does data really need to be Uint8ClampedArray?
2085
- data,
2086
- width: options.width,
2087
- height: options.height
2088
- // depth: options.depth
2089
- }
2090
- ];
2091
- } else if (!Array.isArray(data)) {
2092
- lodArray = [data];
2093
- } else {
2094
- lodArray = data;
2095
- }
2096
- return lodArray;
2233
+ function convertBlendFactorToFunction(parameter, value) {
2234
+ return map(parameter, value, {
2235
+ one: 1,
2236
+ zero: 0,
2237
+ "src-color": 768,
2238
+ "one-minus-src-color": 769,
2239
+ "dst-color": 774,
2240
+ "one-minus-dst-color": 775,
2241
+ "src-alpha": 770,
2242
+ "one-minus-src-alpha": 771,
2243
+ "dst-alpha": 772,
2244
+ "one-minus-dst-alpha": 773,
2245
+ "src-alpha-saturated": 776,
2246
+ "constant-color": 32769,
2247
+ "one-minus-constant-color": 32770,
2248
+ "constant-alpha": 32771,
2249
+ "one-minus-constant-alpha": 32772
2250
+ });
2097
2251
  }
2098
- var WEBGLTexture = class extends import_core8.Texture {
2099
- MAX_ATTRIBUTES;
2100
- device;
2101
- gl;
2102
- handle;
2103
- sampler = void 0;
2104
- // TODO - currently unused in WebGL. Create dummy sampler?
2105
- view = void 0;
2106
- // TODO - currently unused in WebGL. Create dummy view?
2107
- mipmaps = false;
2108
- /**
2109
- * @note `target` cannot be modified by bind:
2110
- * textures are special because when you first bind them to a target,
2111
- * When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
2112
- * And it will always be a 2D texture; this state cannot be changed ever.
2113
- * A texture that was first bound as a GL_TEXTURE_2D, must always be bound as a GL_TEXTURE_2D;
2114
- * attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
2115
- */
2116
- glTarget;
2117
- // Texture type
2118
- /** The WebGL format - essentially channel structure */
2119
- glFormat;
2120
- /** The WebGL data format - the type of each channel */
2121
- glType;
2122
- /** The WebGL constant corresponding to the WebGPU style constant in format */
2123
- glInternalFormat;
2124
- /** Whether the internal format is compressed */
2125
- compressed;
2126
- // data;
2127
- // inherited props
2128
- // dimension: ...
2129
- // format: GLTextureTarget;
2130
- // width: number = undefined;
2131
- // height: number = undefined;
2132
- // depth: number = undefined;
2133
- // state
2134
- /** Texture binding slot */
2135
- textureUnit = 0;
2136
- /** For automatically updating video */
2137
- _video = null;
2138
- constructor(device, props) {
2139
- props = import_core8.Texture._fixProps(props);
2140
- super(device, { ...import_core8.Texture.defaultProps, ...props, data: void 0 });
2141
- this.device = device;
2142
- this.gl = this.device.gl;
2143
- this.glTarget = getWebGLTextureTarget(this.props.dimension);
2144
- const format = getTextureFormatWebGL(this.props.format);
2145
- this.glInternalFormat = format.internalFormat;
2146
- this.glFormat = format.format;
2147
- this.glType = format.type;
2148
- this.compressed = format.compressed;
2149
- if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
2150
- props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
2151
- const video = props.data;
2152
- this._video = null;
2153
- video.addEventListener("loadeddata", () => this.initialize(props));
2154
- }
2155
- this.initialize({ ...this.props, data: props.data });
2156
- Object.seal(this);
2157
- }
2158
- /**
2159
- * Initialize texture with supplied props
2160
- */
2161
- // eslint-disable-next-line max-statements
2162
- initialize(props = {}) {
2163
- this.handle = this.props.handle || this.gl.createTexture();
2164
- this.device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
2165
- const data = props.data;
2166
- let { width, height } = props;
2167
- if (!width || !height) {
2168
- const textureSize = import_core8.Texture.getTextureDataSize(data);
2169
- width = (textureSize == null ? void 0 : textureSize.width) || 1;
2170
- height = (textureSize == null ? void 0 : textureSize.height) || 1;
2171
- }
2172
- this.width = width;
2173
- this.height = height;
2174
- this.depth = props.depth;
2175
- this.setSampler(props.sampler);
2176
- this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
2177
- this.bind();
2178
- if (!this.props.data) {
2179
- initializeTextureStorage(this.gl, this.mipLevels, this);
2180
- }
2181
- if (props.data) {
2182
- switch (props.dimension) {
2183
- case "1d":
2184
- this.setTexture1DData(props.data);
2185
- break;
2186
- case "2d":
2187
- this.setTexture2DData(props.data);
2188
- break;
2189
- case "3d":
2190
- this.setTexture3DData(props.data);
2191
- break;
2192
- case "cube":
2193
- this.setTextureCubeData(props.data);
2194
- break;
2195
- case "2d-array":
2196
- this.setTextureArrayData(props.data);
2197
- break;
2198
- case "cube-array":
2199
- this.setTextureCubeArrayData(props.data);
2200
- break;
2201
- default:
2202
- throw new Error(props.dimension);
2203
- }
2204
- }
2205
- this.mipmaps = Boolean(props.mipmaps);
2206
- if (this.mipmaps) {
2207
- this.generateMipmap();
2208
- }
2209
- }
2210
- /*
2211
- initializeCube(props?: TextureProps): void {
2212
- const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
2213
-
2214
- // Store props for accessors
2215
- // this.props = props;
2216
-
2217
- // @ts-expect-error
2218
- this.setCubeMapData(props).then(() => {
2219
- // TODO - should genMipmap() be called on the cubemap or on the faces?
2220
- // TODO - without generateMipmap() cube textures do not work at all!!! Why?
2221
- if (mipmaps) {
2222
- this.generateMipmap(props);
2223
- }
2224
-
2225
- this.setSampler(props.sampler);
2226
-
2227
- // v8 compatibility?
2228
- // const {parameters = {} as Record<GL, any>} = props;
2229
- // this._setSamplerParameters(parameters);
2230
- });
2231
- }
2232
- */
2233
- destroy() {
2234
- if (this.handle) {
2235
- this.gl.deleteTexture(this.handle);
2236
- this.removeStats();
2237
- this.trackDeallocatedMemory("Texture");
2238
- this.destroyed = true;
2239
- }
2240
- }
2241
- toString() {
2242
- return `Texture(${this.id},${this.width}x${this.height})`;
2243
- }
2244
- createView(props) {
2245
- return new WEBGLTextureView(this.device, { ...props, texture: this });
2246
- }
2247
- setSampler(sampler = {}) {
2248
- let samplerProps;
2249
- if (sampler instanceof WEBGLSampler) {
2250
- this.sampler = sampler;
2251
- samplerProps = sampler.props;
2252
- } else {
2253
- this.sampler = new WEBGLSampler(this.device, sampler);
2254
- samplerProps = sampler;
2255
- }
2256
- const parameters = convertSamplerParametersToWebGL(samplerProps);
2257
- this._setSamplerParameters(parameters);
2258
- }
2259
- /** Update external texture (video frame or canvas) */
2260
- update() {
2261
- import_core8.log.warn("Texture.update() not implemented");
2262
- }
2263
- // Call to regenerate mipmaps after modifying texture(s)
2264
- generateMipmap(params = {}) {
2265
- if (!this.props.data) {
2266
- return;
2267
- }
2268
- this.mipmaps = true;
2269
- this.gl.bindTexture(this.glTarget, this.handle);
2270
- withGLParameters(this.gl, params, () => {
2271
- this.gl.generateMipmap(this.glTarget);
2272
- });
2273
- this.gl.bindTexture(this.glTarget, null);
2274
- }
2275
- // Image Data Setters
2276
- copyExternalImage(options) {
2277
- const size = import_core8.Texture.getExternalImageSize(options.image);
2278
- const opts = { ...import_core8.Texture.defaultCopyExternalImageOptions, ...size, ...options };
2279
- const { image, depth, mipLevel, x, y, z } = opts;
2280
- let { width, height } = opts;
2281
- const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
2282
- width = Math.min(width, size.width - x);
2283
- height = Math.min(height, size.height - y);
2284
- if (options.sourceX || options.sourceY) {
2285
- throw new Error("WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer");
2286
- }
2287
- copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
2288
- dimension,
2289
- mipLevel,
2290
- x,
2291
- y,
2292
- z,
2293
- width,
2294
- height,
2295
- depth,
2296
- glFormat,
2297
- glInternalFormat,
2298
- glType,
2299
- glTarget
2300
- });
2301
- return { width: opts.width, height: opts.height };
2302
- }
2303
- setTexture1DData(data) {
2304
- throw new Error("setTexture1DData not supported in WebGL.");
2305
- }
2306
- /** Set a simple texture */
2307
- setTexture2DData(lodData, depth = 0) {
2308
- this.bind();
2309
- const lodArray = normalizeTextureData(lodData, this);
2310
- if (lodArray.length > 1 && this.props.mipmaps !== false) {
2311
- import_core8.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
2312
- }
2313
- for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
2314
- const imageData = lodArray[lodLevel];
2315
- this._setMipLevel(depth, lodLevel, imageData);
2316
- }
2317
- this.unbind();
2318
- }
2319
- /**
2320
- * Sets a 3D texture
2321
- * @param data
2322
- */
2323
- setTexture3DData(data) {
2324
- if (this.props.dimension !== "3d") {
2325
- throw new Error(this.id);
2326
- }
2327
- if (ArrayBuffer.isView(data)) {
2328
- this.bind();
2329
- copyCPUDataToMipLevel(this.device.gl, data, this);
2330
- this.unbind();
2331
- }
2332
- }
2333
- /**
2334
- * Set a Texture Cube Data
2335
- * @todo - could support TextureCubeArray with depth
2336
- * @param data
2337
- * @param index
2338
- */
2339
- setTextureCubeData(data, depth = 0) {
2340
- if (this.props.dimension !== "cube") {
2341
- throw new Error(this.id);
2342
- }
2343
- for (const face of import_core8.Texture.CubeFaces) {
2344
- this.setTextureCubeFaceData(data[face], face);
2345
- }
2346
- }
2347
- /**
2348
- * Sets an entire texture array
2349
- * @param data
2350
- */
2351
- setTextureArrayData(data) {
2352
- if (this.props.dimension !== "2d-array") {
2353
- throw new Error(this.id);
2354
- }
2355
- throw new Error("setTextureArrayData not implemented.");
2356
- }
2357
- /**
2358
- * Sets an entire texture cube array
2359
- * @param data
2360
- */
2361
- setTextureCubeArrayData(data) {
2362
- throw new Error("setTextureCubeArrayData not supported in WebGL2.");
2363
- }
2364
- setTextureCubeFaceData(lodData, face, depth = 0) {
2365
- if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
2366
- import_core8.log.warn(`${this.id} has mipmap and multiple LODs.`)();
2367
- }
2368
- const faceDepth = import_core8.Texture.CubeFaces.indexOf(face);
2369
- this.setTexture2DData(lodData, faceDepth);
2370
- }
2371
- // INTERNAL METHODS
2372
- /** @todo update this method to accept LODs */
2373
- setImageDataForFace(options) {
2374
- const {
2375
- face,
2376
- width,
2377
- height,
2378
- pixels,
2379
- data,
2380
- format = 6408,
2381
- type = 5121
2382
- // generateMipmap = false // TODO
2383
- } = options;
2384
- const { gl } = this;
2385
- const imageData = pixels || data;
2386
- this.bind();
2387
- if (imageData instanceof Promise) {
2388
- imageData.then((resolvedImageData) => this.setImageDataForFace(Object.assign({}, options, {
2389
- face,
2390
- data: resolvedImageData,
2391
- pixels: resolvedImageData
2392
- })));
2393
- } else if (this.width || this.height) {
2394
- gl.texImage2D(face, 0, format, width, height, 0, format, type, imageData);
2395
- } else {
2396
- gl.texImage2D(face, 0, format, format, type, imageData);
2397
- }
2398
- }
2399
- _getImageDataMap(faceData) {
2400
- for (let i = 0; i < import_core8.Texture.CubeFaces.length; ++i) {
2401
- const faceName = import_core8.Texture.CubeFaces[i];
2402
- if (faceData[faceName]) {
2403
- faceData[34069 + i] = faceData[faceName];
2404
- delete faceData[faceName];
2405
- }
2406
- }
2407
- return faceData;
2252
+ function message(parameter, value) {
2253
+ return `Illegal parameter ${value} for ${parameter}`;
2254
+ }
2255
+ function map(parameter, value, valueMap) {
2256
+ if (!(value in valueMap)) {
2257
+ throw new Error(message(parameter, value));
2408
2258
  }
2409
- // RESOURCE METHODS
2410
- /**
2411
- * Sets sampler parameters on texture
2412
- */
2413
- _setSamplerParameters(parameters) {
2414
- import_core8.log.log(1, "texture sampler parameters", parameters)();
2415
- this.gl.bindTexture(this.glTarget, this.handle);
2416
- for (const [pname, pvalue] of Object.entries(parameters)) {
2417
- const param = Number(pname);
2418
- const value = pvalue;
2419
- switch (param) {
2420
- case 33082:
2421
- case 33083:
2422
- this.gl.texParameterf(this.glTarget, param, value);
2423
- break;
2424
- case 10241:
2425
- this.gl.texParameteri(this.glTarget, param, value);
2426
- break;
2427
- case 10242:
2428
- case 10243:
2429
- this.gl.texParameteri(this.glTarget, param, value);
2430
- break;
2431
- case 34046:
2432
- if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
2433
- this.gl.texParameteri(this.glTarget, param, value);
2434
- }
2435
- break;
2436
- default:
2437
- this.gl.texParameteri(this.glTarget, param, value);
2438
- break;
2439
- }
2440
- }
2441
- this.gl.bindTexture(this.glTarget, null);
2259
+ return valueMap[value];
2260
+ }
2261
+ function mapBoolean(parameter, value) {
2262
+ return value;
2263
+ }
2264
+ function isObjectEmpty2(obj) {
2265
+ let isEmpty = true;
2266
+ for (const key in obj) {
2267
+ isEmpty = false;
2268
+ break;
2442
2269
  }
2443
- // CLASSIC
2444
- /*
2445
- setCubeMapData(options: {
2446
- width: number;
2447
- height: number;
2448
- data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
2449
- format?: any;
2450
- type?: any;
2451
- /** @deprecated Use .data *
2452
- pixels: any;
2453
- }): void {
2454
- const {gl} = this;
2455
-
2456
- const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
2457
-
2458
- // pixel data (imageDataMap) is an Object from Face to Image or Promise.
2459
- // For example:
2460
- // {
2461
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
2462
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
2463
- // ... }
2464
- // To provide multiple level-of-details (LODs) this can be Face to Array
2465
- // of Image or Promise, like this
2466
- // {
2467
- // GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
2468
- // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
2469
- // ... }
2470
-
2471
- const imageDataMap = this._getImageDataMap(pixels || data);
2472
-
2473
- const resolvedFaces = WEBGLTexture.FACES.map(face => {
2474
- const facePixels = imageDataMap[face];
2475
- return Array.isArray(facePixels) ? facePixels : [facePixels];
2476
- });
2477
- this.bind();
2478
-
2479
- WEBGLTexture.FACES.forEach((face, index) => {
2480
- if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
2481
- // If the user provides multiple LODs, then automatic mipmap
2482
- // generation generateMipmap() should be disabled to avoid overwritting them.
2483
- log.warn(`${this.id} has mipmap and multiple LODs.`)();
2484
- }
2485
- resolvedFaces[index].forEach((image, lodLevel) => {
2486
- // TODO: adjust width & height for LOD!
2487
- if (width && height) {
2488
- gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
2489
- } else {
2490
- gl.texImage2D(face, lodLevel, format, format, type, image);
2491
- }
2492
- });
2493
- });
2494
-
2495
- this.unbind();
2496
- }
2497
- */
2498
- // INTERNAL SETTERS
2499
- /**
2500
- * Copy a region of data from a CPU memory buffer into this texture.
2501
- * @todo - GLUnpackParameters parameters
2502
- */
2503
- _setMipLevel(depth, mipLevel, textureData, glTarget = this.glTarget) {
2504
- if (import_core8.Texture.isExternalImage(textureData)) {
2505
- copyExternalImageToMipLevel(this.device.gl, this.handle, textureData, {
2506
- ...this,
2507
- depth,
2508
- mipLevel,
2509
- glTarget
2510
- });
2511
- return;
2512
- }
2513
- if (import_core8.Texture.isTextureLevelData(textureData)) {
2514
- copyCPUDataToMipLevel(this.device.gl, textureData.data, {
2515
- ...this,
2516
- depth,
2517
- mipLevel,
2518
- glTarget
2519
- });
2520
- return;
2521
- }
2522
- throw new Error("Texture: invalid image data");
2270
+ return isEmpty;
2271
+ }
2272
+
2273
+ // dist/adapter/converters/sampler-parameters.js
2274
+ function convertSamplerParametersToWebGL(props) {
2275
+ const params = {};
2276
+ if (props.addressModeU) {
2277
+ params[10242] = convertAddressMode(props.addressModeU);
2523
2278
  }
2524
- // HELPERS
2525
- getActiveUnit() {
2526
- return this.gl.getParameter(34016) - 33984;
2279
+ if (props.addressModeV) {
2280
+ params[10243] = convertAddressMode(props.addressModeV);
2527
2281
  }
2528
- bind(textureUnit) {
2529
- const { gl } = this;
2530
- if (textureUnit !== void 0) {
2531
- this.textureUnit = textureUnit;
2532
- gl.activeTexture(33984 + textureUnit);
2533
- }
2534
- gl.bindTexture(this.glTarget, this.handle);
2535
- return textureUnit;
2282
+ if (props.addressModeW) {
2283
+ params[32882] = convertAddressMode(props.addressModeW);
2536
2284
  }
2537
- unbind(textureUnit) {
2538
- const { gl } = this;
2539
- if (textureUnit !== void 0) {
2540
- this.textureUnit = textureUnit;
2541
- gl.activeTexture(33984 + textureUnit);
2542
- }
2543
- gl.bindTexture(this.glTarget, null);
2544
- return textureUnit;
2285
+ if (props.magFilter) {
2286
+ params[10240] = convertMaxFilterMode(props.magFilter);
2545
2287
  }
2546
- };
2547
-
2548
- // dist/adapter/resources/webgl-framebuffer.js
2549
- var WEBGLFramebuffer = class extends import_core9.Framebuffer {
2550
- device;
2551
- gl;
2552
- handle;
2553
- colorAttachments = [];
2554
- depthStencilAttachment = null;
2555
- constructor(device, props) {
2556
- super(device, props);
2557
- const isDefaultFramebuffer = props.handle === null;
2558
- this.device = device;
2559
- this.gl = device.gl;
2560
- this.handle = this.props.handle || isDefaultFramebuffer ? this.props.handle : this.gl.createFramebuffer();
2561
- if (!isDefaultFramebuffer) {
2562
- device.setSpectorMetadata(this.handle, { id: this.props.id, props: this.props });
2563
- this.autoCreateAttachmentTextures();
2564
- this.updateAttachments();
2565
- }
2288
+ if (props.minFilter || props.mipmapFilter) {
2289
+ params[10241] = convertMinFilterMode(props.minFilter || "linear", props.mipmapFilter);
2566
2290
  }
2567
- /** destroys any auto created resources etc. */
2568
- destroy() {
2569
- super.destroy();
2570
- if (!this.destroyed && this.handle !== null) {
2571
- this.gl.deleteFramebuffer(this.handle);
2572
- }
2291
+ if (props.lodMinClamp !== void 0) {
2292
+ params[33082] = props.lodMinClamp;
2573
2293
  }
2574
- updateAttachments() {
2575
- const prevHandle = this.gl.bindFramebuffer(36160, this.handle);
2576
- for (let i = 0; i < this.colorAttachments.length; ++i) {
2577
- const attachment = this.colorAttachments[i];
2578
- if (attachment) {
2579
- const attachmentPoint = 36064 + i;
2580
- this._attachTextureView(attachmentPoint, attachment);
2581
- }
2582
- }
2583
- if (this.depthStencilAttachment) {
2584
- const attachmentPoint = getDepthStencilAttachmentWebGL(this.depthStencilAttachment.props.format);
2585
- this._attachTextureView(attachmentPoint, this.depthStencilAttachment);
2586
- }
2587
- if (this.props.check !== false) {
2588
- const status = this.gl.checkFramebufferStatus(36160);
2589
- if (status !== 36053) {
2590
- throw new Error(`Framebuffer ${_getFrameBufferStatus(status)}`);
2591
- }
2592
- }
2593
- this.gl.bindFramebuffer(36160, prevHandle);
2294
+ if (props.lodMaxClamp !== void 0) {
2295
+ params[33083] = props.lodMaxClamp;
2594
2296
  }
2595
- // PRIVATE
2596
- /** In WebGL we must use renderbuffers for depth/stencil attachments (unless we have extensions) */
2597
- createDepthStencilTexture(format) {
2598
- return new WEBGLTexture(this.device, {
2599
- id: `${this.id}-depth-stencil`,
2600
- format,
2601
- width: this.width,
2602
- height: this.height,
2603
- mipmaps: false
2604
- });
2297
+ if (props.type === "comparison-sampler") {
2298
+ params[34892] = 34894;
2605
2299
  }
2606
- /**
2607
- * @param attachment
2608
- * @param texture
2609
- * @param layer = 0 - index into WEBGLTextureArray and Texture3D or face for `TextureCubeMap`
2610
- * @param level = 0 - mipmapLevel
2611
- */
2612
- _attachTextureView(attachment, textureView) {
2613
- const { gl } = this.device;
2614
- const { texture } = textureView;
2615
- const level = textureView.props.baseMipLevel;
2616
- const layer = textureView.props.baseArrayLayer;
2617
- gl.bindTexture(texture.glTarget, texture.handle);
2618
- switch (texture.glTarget) {
2619
- case 35866:
2620
- case 32879:
2621
- gl.framebufferTextureLayer(36160, attachment, texture.handle, level, layer);
2622
- break;
2623
- case 34067:
2624
- const face = mapIndexToCubeMapFace(layer);
2625
- gl.framebufferTexture2D(36160, attachment, face, texture.handle, level);
2626
- break;
2627
- case 3553:
2628
- gl.framebufferTexture2D(36160, attachment, 3553, texture.handle, level);
2629
- break;
2630
- default:
2631
- throw new Error("Illegal texture type");
2632
- }
2633
- gl.bindTexture(texture.glTarget, null);
2300
+ if (props.compare) {
2301
+ params[34893] = convertCompareFunction("compare", props.compare);
2634
2302
  }
2635
- };
2636
- function mapIndexToCubeMapFace(layer) {
2637
- return layer < 34069 ? layer + 34069 : layer;
2303
+ if (props.maxAnisotropy) {
2304
+ params[34046] = props.maxAnisotropy;
2305
+ }
2306
+ return params;
2638
2307
  }
2639
- function _getFrameBufferStatus(status) {
2640
- switch (status) {
2641
- case 36053:
2642
- return "success";
2643
- case 36054:
2644
- return "Mismatched attachments";
2645
- case 36055:
2646
- return "No attachments";
2647
- case 36057:
2648
- return "Height/width mismatch";
2649
- case 36061:
2650
- return "Unsupported or split attachments";
2651
- case 36182:
2652
- return "Samples mismatch";
2653
- default:
2654
- return `${status}`;
2308
+ function convertAddressMode(addressMode) {
2309
+ switch (addressMode) {
2310
+ case "clamp-to-edge":
2311
+ return 33071;
2312
+ case "repeat":
2313
+ return 10497;
2314
+ case "mirror-repeat":
2315
+ return 33648;
2316
+ }
2317
+ }
2318
+ function convertMaxFilterMode(maxFilter) {
2319
+ switch (maxFilter) {
2320
+ case "nearest":
2321
+ return 9728;
2322
+ case "linear":
2323
+ return 9729;
2324
+ }
2325
+ }
2326
+ function convertMinFilterMode(minFilter, mipmapFilter) {
2327
+ if (!mipmapFilter) {
2328
+ return convertMaxFilterMode(minFilter);
2329
+ }
2330
+ switch (minFilter) {
2331
+ case "nearest":
2332
+ return mipmapFilter === "nearest" ? 9984 : 9986;
2333
+ case "linear":
2334
+ return mipmapFilter === "nearest" ? 9985 : 9987;
2655
2335
  }
2656
2336
  }
2657
2337
 
2658
- // dist/adapter/webgl-canvas-context.js
2659
- var WebGLCanvasContext = class extends import_core10.CanvasContext {
2338
+ // dist/adapter/resources/webgl-sampler.js
2339
+ var WEBGLSampler = class extends import_core11.Sampler {
2660
2340
  device;
2661
- format = "rgba8unorm";
2662
- depthStencilFormat = "depth24plus";
2663
- presentationSize;
2664
- _framebuffer = null;
2341
+ handle;
2342
+ parameters;
2665
2343
  constructor(device, props) {
2666
- super(props);
2344
+ super(device, props);
2667
2345
  this.device = device;
2668
- this.presentationSize = [-1, -1];
2669
- this._setAutoCreatedCanvasId(`${this.device.id}-canvas`);
2670
- this.update();
2346
+ this.parameters = convertSamplerParametersToWebGL(props);
2347
+ this.handle = this.handle || this.device.gl.createSampler();
2348
+ this._setSamplerParameters(this.parameters);
2671
2349
  }
2672
- getCurrentFramebuffer() {
2673
- this.update();
2674
- this._framebuffer = this._framebuffer || new WEBGLFramebuffer(this.device, { handle: null });
2675
- return this._framebuffer;
2350
+ destroy() {
2351
+ if (this.handle) {
2352
+ this.device.gl.deleteSampler(this.handle);
2353
+ this.handle = void 0;
2354
+ }
2676
2355
  }
2677
- /** Resizes and updates render targets if necessary */
2678
- update() {
2679
- const size = this.getPixelSize();
2680
- const sizeChanged = size[0] !== this.presentationSize[0] || size[1] !== this.presentationSize[1];
2681
- if (sizeChanged) {
2682
- this.presentationSize = size;
2683
- this.resize();
2356
+ toString() {
2357
+ return `Sampler(${this.id},${JSON.stringify(this.props)})`;
2358
+ }
2359
+ /** Set sampler parameters on the sampler */
2360
+ _setSamplerParameters(parameters) {
2361
+ for (const [pname, value] of Object.entries(parameters)) {
2362
+ const param = Number(pname);
2363
+ switch (param) {
2364
+ case 33082:
2365
+ case 33083:
2366
+ this.device.gl.samplerParameterf(this.handle, param, value);
2367
+ break;
2368
+ default:
2369
+ this.device.gl.samplerParameteri(this.handle, param, value);
2370
+ break;
2371
+ }
2684
2372
  }
2685
2373
  }
2686
- /**
2687
- * Resize the canvas' drawing buffer.
2688
- *
2689
- * Can match the canvas CSS size, and optionally also consider devicePixelRatio
2690
- * Can be called every frame
2691
- *
2692
- * Regardless of size, the drawing buffer will always be scaled to the viewport, but
2693
- * for best visual results, usually set to either:
2694
- * canvas CSS width x canvas CSS height
2695
- * canvas CSS width * devicePixelRatio x canvas CSS height * devicePixelRatio
2696
- * See http://webgl2fundamentals.org/webgl/lessons/webgl-resizing-the-canvas.html
2697
- */
2698
- resize(options) {
2699
- if (!this.device.gl)
2700
- return;
2701
- if (this.canvas) {
2702
- const devicePixelRatio = this.getDevicePixelRatio(options == null ? void 0 : options.useDevicePixels);
2703
- this.setDevicePixelRatio(devicePixelRatio, options);
2704
- return;
2374
+ };
2375
+
2376
+ // dist/adapter/resources/webgl-texture.js
2377
+ var import_core14 = require("@luma.gl/core");
2378
+ var import_constants16 = require("@luma.gl/constants");
2379
+
2380
+ // dist/context/state-tracker/with-parameters.js
2381
+ function withGLParameters(gl, parameters, func) {
2382
+ if (isObjectEmpty3(parameters)) {
2383
+ return func(gl);
2384
+ }
2385
+ const { nocatch = true } = parameters;
2386
+ const webglState = WebGLStateTracker.get(gl);
2387
+ webglState.push();
2388
+ setGLParameters(gl, parameters);
2389
+ let value;
2390
+ if (nocatch) {
2391
+ value = func(gl);
2392
+ webglState.pop();
2393
+ } else {
2394
+ try {
2395
+ value = func(gl);
2396
+ } finally {
2397
+ webglState.pop();
2705
2398
  }
2706
2399
  }
2707
- commit() {
2400
+ return value;
2401
+ }
2402
+ function isObjectEmpty3(object) {
2403
+ for (const key in object) {
2404
+ return false;
2405
+ }
2406
+ return true;
2407
+ }
2408
+
2409
+ // dist/adapter/resources/webgl-texture-view.js
2410
+ var import_core12 = require("@luma.gl/core");
2411
+ var WEBGLTextureView = class extends import_core12.TextureView {
2412
+ device;
2413
+ gl;
2414
+ handle;
2415
+ // Does not have a WebGL representation
2416
+ texture;
2417
+ constructor(device, props) {
2418
+ super(device, { ...import_core12.Texture.defaultProps, ...props });
2419
+ this.device = device;
2420
+ this.gl = this.device.gl;
2421
+ this.handle = null;
2422
+ this.texture = props.texture;
2708
2423
  }
2709
2424
  };
2710
2425
 
2711
- // dist/context/debug/spector.js
2712
- var import_core11 = require("@luma.gl/core");
2426
+ // dist/adapter/helpers/webgl-texture-utils.js
2427
+ var import_core13 = require("@luma.gl/core");
2428
+ var import_constants15 = require("@luma.gl/constants");
2713
2429
 
2714
- // dist/utils/load-script.js
2715
- async function loadScript(scriptUrl, scriptId) {
2716
- const head = document.getElementsByTagName("head")[0];
2717
- if (!head) {
2718
- throw new Error("loadScript");
2430
+ // dist/adapter/helpers/typed-array-utils.js
2431
+ var import_constants13 = require("@luma.gl/constants");
2432
+ var ERR_TYPE_DEDUCTION = "Failed to deduce GL constant from typed array";
2433
+ function getGLTypeFromTypedArray(arrayOrType) {
2434
+ const type = ArrayBuffer.isView(arrayOrType) ? arrayOrType.constructor : arrayOrType;
2435
+ switch (type) {
2436
+ case Float32Array:
2437
+ return 5126;
2438
+ case Uint16Array:
2439
+ return 5123;
2440
+ case Uint32Array:
2441
+ return 5125;
2442
+ case Uint8Array:
2443
+ return 5121;
2444
+ case Uint8ClampedArray:
2445
+ return 5121;
2446
+ case Int8Array:
2447
+ return 5120;
2448
+ case Int16Array:
2449
+ return 5122;
2450
+ case Int32Array:
2451
+ return 5124;
2452
+ default:
2453
+ throw new Error(ERR_TYPE_DEDUCTION);
2719
2454
  }
2720
- const script = document.createElement("script");
2721
- script.setAttribute("type", "text/javascript");
2722
- script.setAttribute("src", scriptUrl);
2723
- if (scriptId) {
2724
- script.id = scriptId;
2455
+ }
2456
+ function getTypedArrayFromGLType(glType, options) {
2457
+ const { clamped = true } = options || {};
2458
+ switch (glType) {
2459
+ case 5126:
2460
+ return Float32Array;
2461
+ case 5123:
2462
+ case 33635:
2463
+ case 32819:
2464
+ case 32820:
2465
+ return Uint16Array;
2466
+ case 5125:
2467
+ return Uint32Array;
2468
+ case 5121:
2469
+ return clamped ? Uint8ClampedArray : Uint8Array;
2470
+ case 5120:
2471
+ return Int8Array;
2472
+ case 5122:
2473
+ return Int16Array;
2474
+ case 5124:
2475
+ return Int32Array;
2476
+ default:
2477
+ throw new Error("Failed to deduce typed array type from GL constant");
2725
2478
  }
2726
- return new Promise((resolve, reject) => {
2727
- script.onload = resolve;
2728
- script.onerror = (error) => reject(new Error(`Unable to load script '${scriptUrl}': ${error}`));
2729
- head.appendChild(script);
2730
- });
2731
2479
  }
2732
2480
 
2733
- // dist/context/debug/spector.js
2734
- var LOG_LEVEL = 1;
2735
- var spector = null;
2736
- var initialized = false;
2737
- var DEFAULT_SPECTOR_PROPS = {
2738
- debugWithSpectorJS: import_core11.log.get("spector") || import_core11.log.get("spectorjs"),
2739
- // https://github.com/BabylonJS/Spector.js#basic-usage
2740
- // https://forum.babylonjs.com/t/spectorcdn-is-temporarily-off/48241
2741
- // spectorUrl: 'https://spectorcdn.babylonjs.com/spector.bundle.js';
2742
- spectorUrl: "https://cdn.jsdelivr.net/npm/spectorjs@0.9.30/dist/spector.bundle.js",
2743
- gl: void 0
2744
- };
2745
- async function loadSpectorJS(props) {
2746
- if (!globalThis.SPECTOR) {
2747
- try {
2748
- await loadScript(props.spectorUrl || DEFAULT_SPECTOR_PROPS.spectorUrl);
2749
- } catch (error) {
2750
- import_core11.log.warn(String(error));
2751
- }
2481
+ // dist/adapter/helpers/format-utils.js
2482
+ var import_constants14 = require("@luma.gl/constants");
2483
+ function glFormatToComponents(format) {
2484
+ switch (format) {
2485
+ case 6406:
2486
+ case 33326:
2487
+ case 6403:
2488
+ return 1;
2489
+ case 33328:
2490
+ case 33319:
2491
+ return 2;
2492
+ case 6407:
2493
+ case 34837:
2494
+ return 3;
2495
+ case 6408:
2496
+ case 34836:
2497
+ return 4;
2498
+ default:
2499
+ return 0;
2752
2500
  }
2753
2501
  }
2754
- function initializeSpectorJS(props) {
2755
- var _a;
2756
- props = { ...DEFAULT_SPECTOR_PROPS, ...props };
2757
- if (!props.debugWithSpectorJS) {
2758
- return null;
2759
- }
2760
- if (!spector && globalThis.SPECTOR && !((_a = globalThis.luma) == null ? void 0 : _a.spector)) {
2761
- import_core11.log.probe(LOG_LEVEL, "SPECTOR found and initialized. Start with `luma.spector.displayUI()`")();
2762
- const { Spector } = globalThis.SPECTOR;
2763
- spector = new Spector();
2764
- if (globalThis.luma) {
2765
- globalThis.luma.spector = spector;
2766
- }
2767
- }
2768
- if (!spector) {
2769
- return null;
2502
+ function glTypeToBytes(type) {
2503
+ switch (type) {
2504
+ case 5121:
2505
+ return 1;
2506
+ case 33635:
2507
+ case 32819:
2508
+ case 32820:
2509
+ return 2;
2510
+ case 5126:
2511
+ return 4;
2512
+ default:
2513
+ return 0;
2770
2514
  }
2771
- if (!initialized) {
2772
- initialized = true;
2773
- spector.spyCanvases();
2774
- spector == null ? void 0 : spector.onCaptureStarted.add((capture) => import_core11.log.info("Spector capture started:", capture)());
2775
- spector == null ? void 0 : spector.onCapture.add((capture) => {
2776
- import_core11.log.info("Spector capture complete:", capture)();
2777
- spector == null ? void 0 : spector.getResultUI();
2778
- spector == null ? void 0 : spector.resultView.display();
2779
- spector == null ? void 0 : spector.resultView.addCapture(capture);
2780
- });
2515
+ }
2516
+
2517
+ // dist/adapter/helpers/webgl-texture-utils.js
2518
+ function initializeTextureStorage(gl, levels, options) {
2519
+ const { dimension, width, height, depth = 0 } = options;
2520
+ const { glInternalFormat } = options;
2521
+ const glTarget = options.glTarget;
2522
+ switch (dimension) {
2523
+ case "2d-array":
2524
+ case "3d":
2525
+ gl.texStorage3D(glTarget, levels, glInternalFormat, width, height, depth);
2526
+ break;
2527
+ default:
2528
+ gl.texStorage2D(glTarget, levels, glInternalFormat, width, height);
2781
2529
  }
2782
- if (props.gl) {
2783
- const gl = props.gl;
2784
- const device = gl.device;
2785
- spector == null ? void 0 : spector.startCapture(props.gl, 500);
2786
- gl.device = device;
2787
- new Promise((resolve) => setTimeout(resolve, 2e3)).then((_) => {
2788
- import_core11.log.info("Spector capture stopped after 2 seconds")();
2789
- spector == null ? void 0 : spector.stopCapture();
2790
- });
2530
+ }
2531
+ function copyExternalImageToMipLevel(gl, handle, image, options) {
2532
+ const { width, height } = options;
2533
+ const { dimension, depth = 0, mipLevel = 0 } = options;
2534
+ const { x = 0, y = 0, z = 0 } = options;
2535
+ const { glFormat, glType } = options;
2536
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
2537
+ switch (dimension) {
2538
+ case "2d-array":
2539
+ case "3d":
2540
+ gl.bindTexture(glTarget, handle);
2541
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, image);
2542
+ gl.bindTexture(glTarget, null);
2543
+ break;
2544
+ case "2d":
2545
+ case "cube":
2546
+ gl.bindTexture(glTarget, handle);
2547
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, image);
2548
+ gl.bindTexture(glTarget, null);
2549
+ break;
2550
+ default:
2551
+ throw new Error(dimension);
2791
2552
  }
2792
- return spector;
2793
2553
  }
2794
-
2795
- // dist/context/debug/webgl-developer-tools.js
2796
- var import_core12 = require("@luma.gl/core");
2797
- var import_constants14 = require("@luma.gl/constants");
2798
- var import_env = require("@probe.gl/env");
2799
- var WEBGL_DEBUG_CDN_URL = "https://unpkg.com/webgl-debug@2.0.1/index.js";
2800
- function getWebGLContextData(gl) {
2801
- gl.luma = gl.luma || {};
2802
- return gl.luma;
2554
+ function copyCPUDataToMipLevel(gl, typedArray, options) {
2555
+ const { dimension, width, height, depth = 0, mipLevel = 0, byteOffset = 0 } = options;
2556
+ const { x = 0, y = 0, z = 0 } = options;
2557
+ const { glFormat, glType, compressed } = options;
2558
+ const glTarget = getWebGLCubeFaceTarget(options.glTarget, dimension, depth);
2559
+ switch (dimension) {
2560
+ case "2d-array":
2561
+ case "3d":
2562
+ if (compressed) {
2563
+ gl.compressedTexSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, typedArray, byteOffset);
2564
+ } else {
2565
+ gl.texSubImage3D(glTarget, mipLevel, x, y, z, width, height, depth, glFormat, glType, typedArray, byteOffset);
2566
+ }
2567
+ break;
2568
+ case "2d":
2569
+ case "cube":
2570
+ if (compressed) {
2571
+ gl.compressedTexSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, typedArray, byteOffset);
2572
+ } else {
2573
+ gl.texSubImage2D(glTarget, mipLevel, x, y, width, height, glFormat, glType, typedArray, byteOffset);
2574
+ }
2575
+ break;
2576
+ default:
2577
+ throw new Error(dimension);
2578
+ }
2803
2579
  }
2804
- async function loadWebGLDeveloperTools() {
2805
- if ((0, import_env.isBrowser)() && !globalThis.WebGLDebugUtils) {
2806
- globalThis.global = globalThis.global || globalThis;
2807
- globalThis.global.module = {};
2808
- await loadScript(WEBGL_DEBUG_CDN_URL);
2580
+ function getWebGLTextureTarget(dimension) {
2581
+ switch (dimension) {
2582
+ case "1d":
2583
+ break;
2584
+ case "2d":
2585
+ return 3553;
2586
+ case "3d":
2587
+ return 32879;
2588
+ case "cube":
2589
+ return 34067;
2590
+ case "2d-array":
2591
+ return 35866;
2592
+ case "cube-array":
2593
+ break;
2809
2594
  }
2595
+ throw new Error(dimension);
2810
2596
  }
2811
- function makeDebugContext(gl, props = {}) {
2812
- return props.debug ? getDebugContext(gl, props) : getRealContext(gl);
2813
- }
2814
- function getRealContext(gl) {
2815
- const data = getWebGLContextData(gl);
2816
- return data.realContext ? data.realContext : gl;
2597
+ function getWebGLCubeFaceTarget(glTarget, dimension, level) {
2598
+ return dimension === "cube" ? 34069 + level : glTarget;
2817
2599
  }
2818
- function getDebugContext(gl, props) {
2819
- if (!globalThis.WebGLDebugUtils) {
2820
- import_core12.log.warn("webgl-debug not loaded")();
2821
- return gl;
2600
+ function readPixelsToArray(source, options) {
2601
+ var _a, _b, _c, _d, _e, _f;
2602
+ const {
2603
+ sourceX = 0,
2604
+ sourceY = 0,
2605
+ sourceAttachment = 36064
2606
+ // TODO - support gl.readBuffer
2607
+ } = options || {};
2608
+ let {
2609
+ target = null,
2610
+ // following parameters are auto deduced if not provided
2611
+ sourceWidth,
2612
+ sourceHeight,
2613
+ sourceDepth,
2614
+ sourceFormat,
2615
+ sourceType
2616
+ } = options || {};
2617
+ const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
2618
+ const { gl, handle } = framebuffer;
2619
+ const attachment = sourceAttachment - 36064;
2620
+ sourceWidth ||= framebuffer.width;
2621
+ sourceHeight ||= framebuffer.height;
2622
+ sourceDepth = ((_b = (_a = framebuffer.colorAttachments[attachment]) == null ? void 0 : _a.texture) == null ? void 0 : _b.depth) || 1;
2623
+ sourceFormat ||= ((_d = (_c = framebuffer.colorAttachments[attachment]) == null ? void 0 : _c.texture) == null ? void 0 : _d.glFormat) || 6408;
2624
+ sourceType ||= ((_f = (_e = framebuffer.colorAttachments[attachment]) == null ? void 0 : _e.texture) == null ? void 0 : _f.glType) || 5121;
2625
+ target = getPixelArray(target, sourceType, sourceFormat, sourceWidth, sourceHeight, sourceDepth);
2626
+ sourceType = sourceType || getGLTypeFromTypedArray(target);
2627
+ const prevHandle = gl.bindFramebuffer(36160, handle);
2628
+ gl.readPixels(sourceX, sourceY, sourceWidth, sourceHeight, sourceFormat, sourceType, target);
2629
+ gl.bindFramebuffer(36160, prevHandle || null);
2630
+ if (deleteFramebuffer) {
2631
+ framebuffer.destroy();
2822
2632
  }
2823
- const data = getWebGLContextData(gl);
2824
- if (data.debugContext) {
2825
- return data.debugContext;
2633
+ return target;
2634
+ }
2635
+ function readPixelsToBuffer(source, options) {
2636
+ const { target, sourceX = 0, sourceY = 0, sourceFormat = 6408, targetByteOffset = 0 } = options || {};
2637
+ let { sourceWidth, sourceHeight, sourceType } = options || {};
2638
+ const { framebuffer, deleteFramebuffer } = getFramebuffer(source);
2639
+ sourceWidth = sourceWidth || framebuffer.width;
2640
+ sourceHeight = sourceHeight || framebuffer.height;
2641
+ const webglFramebuffer = framebuffer;
2642
+ sourceType = sourceType || 5121;
2643
+ let webglBufferTarget = target;
2644
+ if (!webglBufferTarget) {
2645
+ const components = glFormatToComponents(sourceFormat);
2646
+ const byteCount = glTypeToBytes(sourceType);
2647
+ const byteLength = targetByteOffset + sourceWidth * sourceHeight * components * byteCount;
2648
+ webglBufferTarget = webglFramebuffer.device.createBuffer({ byteLength });
2826
2649
  }
2827
- globalThis.WebGLDebugUtils.init({ ...import_constants14.GL, ...gl });
2828
- const glDebug = globalThis.WebGLDebugUtils.makeDebugContext(gl, onGLError.bind(null, props), onValidateGLFunc.bind(null, props));
2829
- for (const key in import_constants14.GL) {
2830
- if (!(key in glDebug) && typeof import_constants14.GL[key] === "number") {
2831
- glDebug[key] = import_constants14.GL[key];
2832
- }
2650
+ const commandEncoder = source.device.createCommandEncoder();
2651
+ commandEncoder.copyTextureToBuffer({
2652
+ source,
2653
+ width: sourceWidth,
2654
+ height: sourceHeight,
2655
+ origin: [sourceX, sourceY],
2656
+ destination: webglBufferTarget,
2657
+ byteOffset: targetByteOffset
2658
+ });
2659
+ commandEncoder.destroy();
2660
+ if (deleteFramebuffer) {
2661
+ framebuffer.destroy();
2833
2662
  }
2834
- class WebGLDebugContext {
2663
+ return webglBufferTarget;
2664
+ }
2665
+ function getFramebuffer(source) {
2666
+ if (!(source instanceof import_core13.Framebuffer)) {
2667
+ return { framebuffer: toFramebuffer(source), deleteFramebuffer: true };
2835
2668
  }
2836
- Object.setPrototypeOf(glDebug, Object.getPrototypeOf(gl));
2837
- Object.setPrototypeOf(WebGLDebugContext, glDebug);
2838
- const debugContext = Object.create(WebGLDebugContext);
2839
- data.realContext = gl;
2840
- data.debugContext = debugContext;
2841
- debugContext.debug = true;
2842
- return debugContext;
2669
+ return { framebuffer: source, deleteFramebuffer: false };
2843
2670
  }
2844
- function getFunctionString(functionName, functionArgs) {
2845
- functionArgs = Array.from(functionArgs).map((arg) => arg === void 0 ? "undefined" : arg);
2846
- let args = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, functionArgs);
2847
- args = `${args.slice(0, 100)}${args.length > 100 ? "..." : ""}`;
2848
- return `gl.${functionName}(${args})`;
2671
+ function toFramebuffer(texture, props) {
2672
+ const { device, width, height, id } = texture;
2673
+ const framebuffer = device.createFramebuffer({
2674
+ ...props,
2675
+ id: `framebuffer-for-${id}`,
2676
+ width,
2677
+ height,
2678
+ colorAttachments: [texture]
2679
+ });
2680
+ return framebuffer;
2849
2681
  }
2850
- function onGLError(props, err, functionName, args) {
2851
- args = Array.from(args).map((arg) => arg === void 0 ? "undefined" : arg);
2852
- const errorMessage = globalThis.WebGLDebugUtils.glEnumToString(err);
2853
- const functionArgs = globalThis.WebGLDebugUtils.glFunctionArgsToString(functionName, args);
2854
- const message2 = `${errorMessage} in gl.${functionName}(${functionArgs})`;
2855
- import_core12.log.error(message2)();
2856
- debugger;
2857
- if (props.throwOnError) {
2858
- throw new Error(message2);
2682
+ function getPixelArray(pixelArray, type, format, width, height, depth) {
2683
+ if (pixelArray) {
2684
+ return pixelArray;
2859
2685
  }
2686
+ type = type || 5121;
2687
+ const ArrayType = getTypedArrayFromGLType(type, { clamped: false });
2688
+ const components = glFormatToComponents(format);
2689
+ return new ArrayType(width * height * components);
2860
2690
  }
2861
- function onValidateGLFunc(props, functionName, functionArgs) {
2862
- let functionString = "";
2863
- if (import_core12.log.level >= 1) {
2864
- functionString = getFunctionString(functionName, functionArgs);
2865
- import_core12.log.log(1, functionString)();
2866
- }
2867
- if (props.break && props.break.length > 0) {
2868
- functionString = functionString || getFunctionString(functionName, functionArgs);
2869
- const isBreakpoint = props.break.every((breakOn) => functionString.indexOf(breakOn) !== -1);
2870
- if (isBreakpoint) {
2871
- debugger;
2872
- }
2873
- }
2874
- for (const arg of functionArgs) {
2875
- if (arg === void 0) {
2876
- functionString = functionString || getFunctionString(functionName, functionArgs);
2877
- if (props.throwOnError) {
2878
- throw new Error(`Undefined argument: ${functionString}`);
2879
- } else {
2880
- import_core12.log.error(`Undefined argument: ${functionString}`)();
2881
- debugger;
2691
+
2692
+ // dist/adapter/resources/webgl-texture.js
2693
+ function normalizeTextureData(data, options) {
2694
+ let lodArray;
2695
+ if (ArrayBuffer.isView(data)) {
2696
+ lodArray = [
2697
+ {
2698
+ // ts-expect-error does data really need to be Uint8ClampedArray?
2699
+ data,
2700
+ width: options.width,
2701
+ height: options.height
2702
+ // depth: options.depth
2882
2703
  }
2883
- }
2704
+ ];
2705
+ } else if (!Array.isArray(data)) {
2706
+ lodArray = [data];
2707
+ } else {
2708
+ lodArray = data;
2884
2709
  }
2710
+ return lodArray;
2885
2711
  }
2886
-
2887
- // dist/utils/uid.js
2888
- var uidCounters = {};
2889
- function uid(id = "id") {
2890
- uidCounters[id] = uidCounters[id] || 1;
2891
- const count = uidCounters[id]++;
2892
- return `${id}-${count}`;
2893
- }
2894
-
2895
- // dist/adapter/resources/webgl-buffer.js
2896
- var import_core13 = require("@luma.gl/core");
2897
- var import_constants15 = require("@luma.gl/constants");
2898
- var WEBGLBuffer = class extends import_core13.Buffer {
2712
+ var WEBGLTexture = class extends import_core14.Texture {
2713
+ MAX_ATTRIBUTES;
2899
2714
  device;
2900
2715
  gl;
2901
2716
  handle;
2902
- /** Target in OpenGL defines the type of buffer */
2717
+ sampler = void 0;
2718
+ // TODO - currently unused in WebGL. Create dummy sampler?
2719
+ view = void 0;
2720
+ // TODO - currently unused in WebGL. Create dummy view?
2721
+ mipmaps = false;
2722
+ /**
2723
+ * @note `target` cannot be modified by bind:
2724
+ * textures are special because when you first bind them to a target,
2725
+ * When you first bind a texture as a GL_TEXTURE_2D, you are saying that this texture is a 2D texture.
2726
+ * And it will always be a 2D texture; this state cannot be changed ever.
2727
+ * A texture that was first bound as a GL_TEXTURE_2D, must always be bound as a GL_TEXTURE_2D;
2728
+ * attempting to bind it as GL_TEXTURE_3D will give rise to a run-time error
2729
+ */
2903
2730
  glTarget;
2904
- /** Usage is a hint on how frequently the buffer will be updates */
2905
- glUsage;
2906
- /** Index type is needed when issuing draw calls, so we pre-compute it */
2907
- glIndexType = 5123;
2908
- /** Number of bytes allocated on the GPU for this buffer */
2909
- byteLength;
2910
- /** Number of bytes used */
2911
- bytesUsed;
2912
- constructor(device, props = {}) {
2913
- super(device, props);
2731
+ // Texture type
2732
+ /** The WebGL format - essentially channel structure */
2733
+ glFormat;
2734
+ /** The WebGL data format - the type of each channel */
2735
+ glType;
2736
+ /** The WebGL constant corresponding to the WebGPU style constant in format */
2737
+ glInternalFormat;
2738
+ /** Whether the internal format is compressed */
2739
+ compressed;
2740
+ // data;
2741
+ // inherited props
2742
+ // dimension: ...
2743
+ // format: GLTextureTarget;
2744
+ // width: number = undefined;
2745
+ // height: number = undefined;
2746
+ // depth: number = undefined;
2747
+ // state
2748
+ /** Texture binding slot */
2749
+ textureUnit = 0;
2750
+ /** For automatically updating video */
2751
+ _video = null;
2752
+ constructor(device, props) {
2753
+ props = import_core14.Texture._fixProps(props);
2754
+ super(device, { ...import_core14.Texture.defaultProps, ...props, data: void 0 });
2914
2755
  this.device = device;
2915
2756
  this.gl = this.device.gl;
2916
- const handle = typeof props === "object" ? props.handle : void 0;
2917
- this.handle = handle || this.gl.createBuffer();
2918
- device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
2919
- this.glTarget = getWebGLTarget(this.props.usage);
2920
- this.glUsage = getWebGLUsage(this.props.usage);
2921
- this.glIndexType = this.props.indexType === "uint32" ? 5125 : 5123;
2757
+ this.glTarget = getWebGLTextureTarget(this.props.dimension);
2758
+ const format = getTextureFormatWebGL(this.props.format);
2759
+ this.glInternalFormat = format.internalFormat;
2760
+ this.glFormat = format.format;
2761
+ this.glType = format.type;
2762
+ this.compressed = format.compressed;
2763
+ if (typeof HTMLVideoElement !== "undefined" && props.data instanceof HTMLVideoElement && // @ts-expect-error
2764
+ props.data.readyState < HTMLVideoElement.HAVE_METADATA) {
2765
+ const video = props.data;
2766
+ this._video = null;
2767
+ video.addEventListener("loadeddata", () => this.initialize(props));
2768
+ }
2769
+ this.initialize({ ...this.props, data: props.data });
2770
+ Object.seal(this);
2771
+ }
2772
+ /**
2773
+ * Initialize texture with supplied props
2774
+ */
2775
+ // eslint-disable-next-line max-statements
2776
+ initialize(props = {}) {
2777
+ this.handle = this.props.handle || this.gl.createTexture();
2778
+ this.device.setSpectorMetadata(this.handle, { ...this.props, data: typeof this.props.data });
2779
+ const data = props.data;
2780
+ let { width, height } = props;
2781
+ if (!width || !height) {
2782
+ const textureSize = import_core14.Texture.getTextureDataSize(data);
2783
+ width = (textureSize == null ? void 0 : textureSize.width) || 1;
2784
+ height = (textureSize == null ? void 0 : textureSize.height) || 1;
2785
+ }
2786
+ this.width = width;
2787
+ this.height = height;
2788
+ this.depth = props.depth;
2789
+ this.setSampler(props.sampler);
2790
+ this.view = new WEBGLTextureView(this.device, { ...this.props, texture: this });
2791
+ this.bind();
2792
+ if (!this.props.data) {
2793
+ initializeTextureStorage(this.gl, this.mipLevels, this);
2794
+ }
2922
2795
  if (props.data) {
2923
- this._initWithData(props.data, props.byteOffset, props.byteLength);
2924
- } else {
2925
- this._initWithByteLength(props.byteLength || 0);
2796
+ switch (props.dimension) {
2797
+ case "1d":
2798
+ this.setTexture1DData(props.data);
2799
+ break;
2800
+ case "2d":
2801
+ this.setTexture2DData(props.data);
2802
+ break;
2803
+ case "3d":
2804
+ this.setTexture3DData(props.data);
2805
+ break;
2806
+ case "cube":
2807
+ this.setTextureCubeData(props.data);
2808
+ break;
2809
+ case "2d-array":
2810
+ this.setTextureArrayData(props.data);
2811
+ break;
2812
+ case "cube-array":
2813
+ this.setTextureCubeArrayData(props.data);
2814
+ break;
2815
+ default:
2816
+ throw new Error(props.dimension);
2817
+ }
2926
2818
  }
2927
- }
2928
- // PRIVATE METHODS
2929
- /** Allocate a new buffer and initialize to contents of typed array */
2930
- _initWithData(data, byteOffset = 0, byteLength = data.byteLength + byteOffset) {
2931
- const glTarget = this.glTarget;
2932
- this.gl.bindBuffer(glTarget, this.handle);
2933
- this.gl.bufferData(glTarget, byteLength, this.glUsage);
2934
- this.gl.bufferSubData(glTarget, byteOffset, data);
2935
- this.gl.bindBuffer(glTarget, null);
2936
- this.bytesUsed = byteLength;
2937
- this.byteLength = byteLength;
2938
- this._setDebugData(data, byteOffset, byteLength);
2939
- this.trackAllocatedMemory(byteLength);
2940
- }
2941
- // Allocate a GPU buffer of specified size.
2942
- _initWithByteLength(byteLength) {
2943
- let data = byteLength;
2944
- if (byteLength === 0) {
2945
- data = new Float32Array(0);
2819
+ this.mipmaps = Boolean(props.mipmaps);
2820
+ if (this.mipmaps) {
2821
+ this.generateMipmap();
2946
2822
  }
2947
- const glTarget = this.glTarget;
2948
- this.gl.bindBuffer(glTarget, this.handle);
2949
- this.gl.bufferData(glTarget, data, this.glUsage);
2950
- this.gl.bindBuffer(glTarget, null);
2951
- this.bytesUsed = byteLength;
2952
- this.byteLength = byteLength;
2953
- this._setDebugData(null, 0, byteLength);
2954
- this.trackAllocatedMemory(byteLength);
2955
- return this;
2956
2823
  }
2824
+ /*
2825
+ initializeCube(props?: TextureProps): void {
2826
+ const {mipmaps = true} = props; // , parameters = {} as Record<GL, any>} = props;
2827
+
2828
+ // Store props for accessors
2829
+ // this.props = props;
2830
+
2831
+ // @ts-expect-error
2832
+ this.setCubeMapData(props).then(() => {
2833
+ // TODO - should genMipmap() be called on the cubemap or on the faces?
2834
+ // TODO - without generateMipmap() cube textures do not work at all!!! Why?
2835
+ if (mipmaps) {
2836
+ this.generateMipmap(props);
2837
+ }
2838
+
2839
+ this.setSampler(props.sampler);
2840
+
2841
+ // v8 compatibility?
2842
+ // const {parameters = {} as Record<GL, any>} = props;
2843
+ // this._setSamplerParameters(parameters);
2844
+ });
2845
+ }
2846
+ */
2957
2847
  destroy() {
2958
- if (!this.destroyed && this.handle) {
2848
+ if (this.handle) {
2849
+ this.gl.deleteTexture(this.handle);
2959
2850
  this.removeStats();
2960
- this.trackDeallocatedMemory();
2961
- this.gl.deleteBuffer(this.handle);
2851
+ this.trackDeallocatedMemory("Texture");
2962
2852
  this.destroyed = true;
2963
- this.handle = null;
2964
- }
2965
- }
2966
- write(data, byteOffset = 0) {
2967
- const srcOffset = 0;
2968
- const byteLength = void 0;
2969
- const glTarget = 36663;
2970
- this.gl.bindBuffer(glTarget, this.handle);
2971
- if (srcOffset !== 0 || byteLength !== void 0) {
2972
- this.gl.bufferSubData(glTarget, byteOffset, data, srcOffset, byteLength);
2973
- } else {
2974
- this.gl.bufferSubData(glTarget, byteOffset, data);
2975
2853
  }
2976
- this.gl.bindBuffer(glTarget, null);
2977
- this._setDebugData(data, byteOffset, data.byteLength);
2978
- }
2979
- /** Asynchronously read data from the buffer */
2980
- async readAsync(byteOffset = 0, byteLength) {
2981
- return this.readSyncWebGL(byteOffset, byteLength);
2982
2854
  }
2983
- /** Synchronously read data from the buffer. WebGL only. */
2984
- readSyncWebGL(byteOffset = 0, byteLength) {
2985
- byteLength = byteLength ?? this.byteLength - byteOffset;
2986
- const data = new Uint8Array(byteLength);
2987
- const dstOffset = 0;
2988
- this.gl.bindBuffer(36662, this.handle);
2989
- this.gl.getBufferSubData(36662, byteOffset, data, dstOffset, byteLength);
2990
- this.gl.bindBuffer(36662, null);
2991
- this._setDebugData(data, byteOffset, byteLength);
2992
- return data;
2855
+ toString() {
2856
+ return `Texture(${this.id},${this.width}x${this.height})`;
2993
2857
  }
2994
- };
2995
- function getWebGLTarget(usage) {
2996
- if (usage & import_core13.Buffer.INDEX) {
2997
- return 34963;
2858
+ createView(props) {
2859
+ return new WEBGLTextureView(this.device, { ...props, texture: this });
2998
2860
  }
2999
- if (usage & import_core13.Buffer.VERTEX) {
3000
- return 34962;
2861
+ setSampler(sampler = {}) {
2862
+ let samplerProps;
2863
+ if (sampler instanceof WEBGLSampler) {
2864
+ this.sampler = sampler;
2865
+ samplerProps = sampler.props;
2866
+ } else {
2867
+ this.sampler = new WEBGLSampler(this.device, sampler);
2868
+ samplerProps = sampler;
2869
+ }
2870
+ const parameters = convertSamplerParametersToWebGL(samplerProps);
2871
+ this._setSamplerParameters(parameters);
3001
2872
  }
3002
- if (usage & import_core13.Buffer.UNIFORM) {
3003
- return 35345;
2873
+ /** Update external texture (video frame or canvas) */
2874
+ update() {
2875
+ import_core14.log.warn("Texture.update() not implemented");
3004
2876
  }
3005
- return 34962;
3006
- }
3007
- function getWebGLUsage(usage) {
3008
- if (usage & import_core13.Buffer.INDEX) {
3009
- return 35044;
2877
+ // Call to regenerate mipmaps after modifying texture(s)
2878
+ generateMipmap(params = {}) {
2879
+ if (!this.props.data) {
2880
+ return;
2881
+ }
2882
+ this.mipmaps = true;
2883
+ this.gl.bindTexture(this.glTarget, this.handle);
2884
+ withGLParameters(this.gl, params, () => {
2885
+ this.gl.generateMipmap(this.glTarget);
2886
+ });
2887
+ this.gl.bindTexture(this.glTarget, null);
3010
2888
  }
3011
- if (usage & import_core13.Buffer.VERTEX) {
3012
- return 35044;
2889
+ // Image Data Setters
2890
+ copyExternalImage(options) {
2891
+ const size = import_core14.Texture.getExternalImageSize(options.image);
2892
+ const opts = { ...import_core14.Texture.defaultCopyExternalImageOptions, ...size, ...options };
2893
+ const { image, depth, mipLevel, x, y, z } = opts;
2894
+ let { width, height } = opts;
2895
+ const { dimension, glTarget, glFormat, glInternalFormat, glType } = this;
2896
+ width = Math.min(width, size.width - x);
2897
+ height = Math.min(height, size.height - y);
2898
+ if (options.sourceX || options.sourceY) {
2899
+ throw new Error("WebGL does not yet support sourceX/sourceY in copyExternalImage; requires copyTexSubImage2D from a framebuffer");
2900
+ }
2901
+ copyExternalImageToMipLevel(this.device.gl, this.handle, image, {
2902
+ dimension,
2903
+ mipLevel,
2904
+ x,
2905
+ y,
2906
+ z,
2907
+ width,
2908
+ height,
2909
+ depth,
2910
+ glFormat,
2911
+ glInternalFormat,
2912
+ glType,
2913
+ glTarget
2914
+ });
2915
+ return { width: opts.width, height: opts.height };
3013
2916
  }
3014
- if (usage & import_core13.Buffer.UNIFORM) {
3015
- return 35048;
2917
+ setTexture1DData(data) {
2918
+ throw new Error("setTexture1DData not supported in WebGL.");
3016
2919
  }
3017
- return 35044;
3018
- }
3019
-
3020
- // dist/adapter/resources/webgl-shader.js
3021
- var import_core14 = require("@luma.gl/core");
3022
- var import_constants16 = require("@luma.gl/constants");
3023
-
3024
- // dist/adapter/helpers/parse-shader-compiler-log.js
3025
- function parseShaderCompilerLog(errLog) {
3026
- const lines = errLog.split(/\r?\n/);
3027
- const messages = [];
3028
- for (const line of lines) {
3029
- if (line.length <= 1) {
3030
- continue;
3031
- }
3032
- const segments = line.split(":");
3033
- if (segments.length === 2) {
3034
- const [messageType2, message2] = segments;
3035
- messages.push({
3036
- message: message2.trim(),
3037
- type: getMessageType(messageType2),
3038
- lineNum: 0,
3039
- linePos: 0
3040
- });
3041
- continue;
3042
- }
3043
- const [messageType, linePosition, lineNumber, ...rest] = segments;
3044
- let lineNum = parseInt(lineNumber, 10);
3045
- if (isNaN(lineNum)) {
3046
- lineNum = 0;
2920
+ /** Set a simple texture */
2921
+ setTexture2DData(lodData, depth = 0) {
2922
+ this.bind();
2923
+ const lodArray = normalizeTextureData(lodData, this);
2924
+ if (lodArray.length > 1 && this.props.mipmaps !== false) {
2925
+ import_core14.log.warn(`Texture ${this.id} mipmap and multiple LODs.`)();
3047
2926
  }
3048
- let linePos = parseInt(linePosition, 10);
3049
- if (isNaN(linePos)) {
3050
- linePos = 0;
2927
+ for (let lodLevel = 0; lodLevel < lodArray.length; lodLevel++) {
2928
+ const imageData = lodArray[lodLevel];
2929
+ this._setMipLevel(depth, lodLevel, imageData);
3051
2930
  }
3052
- messages.push({
3053
- message: rest.join(":").trim(),
3054
- type: getMessageType(messageType),
3055
- lineNum,
3056
- linePos
3057
- // TODO
3058
- });
2931
+ this.unbind();
3059
2932
  }
3060
- return messages;
3061
- }
3062
- function getMessageType(messageType) {
3063
- const MESSAGE_TYPES = ["warning", "error", "info"];
3064
- const lowerCaseType = messageType.toLowerCase();
3065
- return MESSAGE_TYPES.includes(lowerCaseType) ? lowerCaseType : "info";
3066
- }
3067
-
3068
- // dist/adapter/resources/webgl-shader.js
3069
- var WEBGLShader = class extends import_core14.Shader {
3070
- device;
3071
- handle;
3072
- constructor(device, props) {
3073
- super(device, props);
3074
- this.device = device;
3075
- switch (this.props.stage) {
3076
- case "vertex":
3077
- this.handle = this.props.handle || this.device.gl.createShader(35633);
3078
- break;
3079
- case "fragment":
3080
- this.handle = this.props.handle || this.device.gl.createShader(35632);
3081
- break;
3082
- default:
3083
- throw new Error(this.props.stage);
2933
+ /**
2934
+ * Sets a 3D texture
2935
+ * @param data
2936
+ */
2937
+ setTexture3DData(data) {
2938
+ if (this.props.dimension !== "3d") {
2939
+ throw new Error(this.id);
2940
+ }
2941
+ if (ArrayBuffer.isView(data)) {
2942
+ this.bind();
2943
+ copyCPUDataToMipLevel(this.device.gl, data, this);
2944
+ this.unbind();
3084
2945
  }
3085
- this._compile(this.source);
3086
2946
  }
3087
- destroy() {
3088
- if (this.handle) {
3089
- this.removeStats();
3090
- this.device.gl.deleteShader(this.handle);
3091
- this.destroyed = true;
2947
+ /**
2948
+ * Set a Texture Cube Data
2949
+ * @todo - could support TextureCubeArray with depth
2950
+ * @param data
2951
+ * @param index
2952
+ */
2953
+ setTextureCubeData(data, depth = 0) {
2954
+ if (this.props.dimension !== "cube") {
2955
+ throw new Error(this.id);
2956
+ }
2957
+ for (const face of import_core14.Texture.CubeFaces) {
2958
+ this.setTextureCubeFaceData(data[face], face);
3092
2959
  }
3093
2960
  }
3094
- async getCompilationInfo() {
3095
- await this._waitForCompilationComplete();
3096
- return this.getCompilationInfoSync();
2961
+ /**
2962
+ * Sets an entire texture array
2963
+ * @param data
2964
+ */
2965
+ setTextureArrayData(data) {
2966
+ if (this.props.dimension !== "2d-array") {
2967
+ throw new Error(this.id);
2968
+ }
2969
+ throw new Error("setTextureArrayData not implemented.");
3097
2970
  }
3098
- getCompilationInfoSync() {
3099
- const log12 = this.device.gl.getShaderInfoLog(this.handle);
3100
- return log12 ? parseShaderCompilerLog(log12) : [];
2971
+ /**
2972
+ * Sets an entire texture cube array
2973
+ * @param data
2974
+ */
2975
+ setTextureCubeArrayData(data) {
2976
+ throw new Error("setTextureCubeArrayData not supported in WebGL2.");
3101
2977
  }
3102
- getTranslatedSource() {
3103
- const extensions = this.device.getExtension("WEBGL_debug_shaders");
3104
- const ext = extensions.WEBGL_debug_shaders;
3105
- return (ext == null ? void 0 : ext.getTranslatedShaderSource(this.handle)) || null;
2978
+ setTextureCubeFaceData(lodData, face, depth = 0) {
2979
+ if (Array.isArray(lodData) && lodData.length > 1 && this.props.mipmaps !== false) {
2980
+ import_core14.log.warn(`${this.id} has mipmap and multiple LODs.`)();
2981
+ }
2982
+ const faceDepth = import_core14.Texture.CubeFaces.indexOf(face);
2983
+ this.setTexture2DData(lodData, faceDepth);
3106
2984
  }
3107
- // PRIVATE METHODS
3108
- /** Compile a shader and get compilation status */
3109
- async _compile(source) {
3110
- const addGLSLVersion = (source2) => source2.startsWith("#version ") ? source2 : `#version 300 es
3111
- ${source2}`;
3112
- source = addGLSLVersion(source);
3113
- const { gl } = this.device;
3114
- gl.shaderSource(this.handle, source);
3115
- gl.compileShader(this.handle);
3116
- if (import_core14.log.level === 0) {
3117
- this.compilationStatus = "pending";
3118
- return;
2985
+ // INTERNAL METHODS
2986
+ /** @todo update this method to accept LODs */
2987
+ setImageDataForFace(options) {
2988
+ const {
2989
+ face,
2990
+ width,
2991
+ height,
2992
+ pixels,
2993
+ data,
2994
+ format = 6408,
2995
+ type = 5121
2996
+ // generateMipmap = false // TODO
2997
+ } = options;
2998
+ const { gl } = this;
2999
+ const imageData = pixels || data;
3000
+ this.bind();
3001
+ if (imageData instanceof Promise) {
3002
+ imageData.then((resolvedImageData) => this.setImageDataForFace(Object.assign({}, options, {
3003
+ face,
3004
+ data: resolvedImageData,
3005
+ pixels: resolvedImageData
3006
+ })));
3007
+ } else if (this.width || this.height) {
3008
+ gl.texImage2D(face, 0, format, width, height, 0, format, type, imageData);
3009
+ } else {
3010
+ gl.texImage2D(face, 0, format, format, type, imageData);
3119
3011
  }
3120
- if (!this.device.features.has("compilation-status-async-webgl")) {
3121
- this._getCompilationStatus();
3122
- this.debugShader();
3123
- if (this.compilationStatus === "error") {
3124
- throw new Error(`GLSL compilation errors in ${this.props.stage} shader ${this.props.id}`);
3012
+ }
3013
+ _getImageDataMap(faceData) {
3014
+ for (let i = 0; i < import_core14.Texture.CubeFaces.length; ++i) {
3015
+ const faceName = import_core14.Texture.CubeFaces[i];
3016
+ if (faceData[faceName]) {
3017
+ faceData[34069 + i] = faceData[faceName];
3018
+ delete faceData[faceName];
3125
3019
  }
3126
- return;
3127
3020
  }
3128
- import_core14.log.once(1, "Shader compilation is asynchronous")();
3129
- await this._waitForCompilationComplete();
3130
- import_core14.log.info(2, `Shader ${this.id} - async compilation complete: ${this.compilationStatus}`)();
3131
- this._getCompilationStatus();
3132
- this.debugShader();
3021
+ return faceData;
3133
3022
  }
3134
- /** Use KHR_parallel_shader_compile extension if available */
3135
- async _waitForCompilationComplete() {
3136
- const waitMs = async (ms) => await new Promise((resolve) => setTimeout(resolve, ms));
3137
- const DELAY_MS = 10;
3138
- if (!this.device.features.has("compilation-status-async-webgl")) {
3139
- await waitMs(DELAY_MS);
3140
- return;
3141
- }
3142
- const { gl } = this.device;
3143
- for (; ; ) {
3144
- const complete = gl.getShaderParameter(this.handle, 37297);
3145
- if (complete) {
3146
- return;
3023
+ // RESOURCE METHODS
3024
+ /**
3025
+ * Sets sampler parameters on texture
3026
+ */
3027
+ _setSamplerParameters(parameters) {
3028
+ import_core14.log.log(1, "texture sampler parameters", parameters)();
3029
+ this.gl.bindTexture(this.glTarget, this.handle);
3030
+ for (const [pname, pvalue] of Object.entries(parameters)) {
3031
+ const param = Number(pname);
3032
+ const value = pvalue;
3033
+ switch (param) {
3034
+ case 33082:
3035
+ case 33083:
3036
+ this.gl.texParameterf(this.glTarget, param, value);
3037
+ break;
3038
+ case 10241:
3039
+ this.gl.texParameteri(this.glTarget, param, value);
3040
+ break;
3041
+ case 10242:
3042
+ case 10243:
3043
+ this.gl.texParameteri(this.glTarget, param, value);
3044
+ break;
3045
+ case 34046:
3046
+ if (this.device.features.has("texture-filterable-anisotropic-webgl")) {
3047
+ this.gl.texParameteri(this.glTarget, param, value);
3048
+ }
3049
+ break;
3050
+ default:
3051
+ this.gl.texParameteri(this.glTarget, param, value);
3052
+ break;
3147
3053
  }
3148
- await waitMs(DELAY_MS);
3149
3054
  }
3055
+ this.gl.bindTexture(this.glTarget, null);
3150
3056
  }
3057
+ // CLASSIC
3058
+ /*
3059
+ setCubeMapData(options: {
3060
+ width: number;
3061
+ height: number;
3062
+ data: Record<GL, Texture2DData> | Record<TextureCubeFace, Texture2DData>;
3063
+ format?: any;
3064
+ type?: any;
3065
+ /** @deprecated Use .data *
3066
+ pixels: any;
3067
+ }): void {
3068
+ const {gl} = this;
3069
+
3070
+ const {width, height, pixels, data, format = GL.RGBA, type = GL.UNSIGNED_BYTE} = options;
3071
+
3072
+ // pixel data (imageDataMap) is an Object from Face to Image or Promise.
3073
+ // For example:
3074
+ // {
3075
+ // GL.TEXTURE_CUBE_MAP_POSITIVE_X : Image-or-Promise,
3076
+ // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : Image-or-Promise,
3077
+ // ... }
3078
+ // To provide multiple level-of-details (LODs) this can be Face to Array
3079
+ // of Image or Promise, like this
3080
+ // {
3081
+ // GL.TEXTURE_CUBE_MAP_POSITIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3082
+ // GL.TEXTURE_CUBE_MAP_NEGATIVE_X : [Image-or-Promise-LOD-0, Image-or-Promise-LOD-1],
3083
+ // ... }
3084
+
3085
+ const imageDataMap = this._getImageDataMap(pixels || data);
3086
+
3087
+ const resolvedFaces = WEBGLTexture.FACES.map(face => {
3088
+ const facePixels = imageDataMap[face];
3089
+ return Array.isArray(facePixels) ? facePixels : [facePixels];
3090
+ });
3091
+ this.bind();
3092
+
3093
+ WEBGLTexture.FACES.forEach((face, index) => {
3094
+ if (resolvedFaces[index].length > 1 && this.props.mipmaps !== false) {
3095
+ // If the user provides multiple LODs, then automatic mipmap
3096
+ // generation generateMipmap() should be disabled to avoid overwritting them.
3097
+ log.warn(`${this.id} has mipmap and multiple LODs.`)();
3098
+ }
3099
+ resolvedFaces[index].forEach((image, lodLevel) => {
3100
+ // TODO: adjust width & height for LOD!
3101
+ if (width && height) {
3102
+ gl.texImage2D(face, lodLevel, format, width, height, 0 /* border*, format, type, image);
3103
+ } else {
3104
+ gl.texImage2D(face, lodLevel, format, format, type, image);
3105
+ }
3106
+ });
3107
+ });
3108
+
3109
+ this.unbind();
3110
+ }
3111
+ */
3112
+ // INTERNAL SETTERS
3151
3113
  /**
3152
- * Get the shader compilation status
3153
- * TODO - Load log even when no error reported, to catch warnings?
3154
- * https://gamedev.stackexchange.com/questions/30429/how-to-detect-glsl-warnings
3114
+ * Copy a region of data from a CPU memory buffer into this texture.
3115
+ * @todo - GLUnpackParameters parameters
3155
3116
  */
3156
- _getCompilationStatus() {
3157
- this.compilationStatus = this.device.gl.getShaderParameter(this.handle, 35713) ? "success" : "error";
3117
+ _setMipLevel(depth, mipLevel, textureData, glTarget = this.glTarget) {
3118
+ if (import_core14.Texture.isExternalImage(textureData)) {
3119
+ copyExternalImageToMipLevel(this.device.gl, this.handle, textureData, {
3120
+ ...this,
3121
+ depth,
3122
+ mipLevel,
3123
+ glTarget
3124
+ });
3125
+ return;
3126
+ }
3127
+ if (import_core14.Texture.isTextureLevelData(textureData)) {
3128
+ copyCPUDataToMipLevel(this.device.gl, textureData.data, {
3129
+ ...this,
3130
+ depth,
3131
+ mipLevel,
3132
+ glTarget
3133
+ });
3134
+ return;
3135
+ }
3136
+ throw new Error("Texture: invalid image data");
3137
+ }
3138
+ // HELPERS
3139
+ getActiveUnit() {
3140
+ return this.gl.getParameter(34016) - 33984;
3141
+ }
3142
+ bind(textureUnit) {
3143
+ const { gl } = this;
3144
+ if (textureUnit !== void 0) {
3145
+ this.textureUnit = textureUnit;
3146
+ gl.activeTexture(33984 + textureUnit);
3147
+ }
3148
+ gl.bindTexture(this.glTarget, this.handle);
3149
+ return textureUnit;
3150
+ }
3151
+ unbind(textureUnit) {
3152
+ const { gl } = this;
3153
+ if (textureUnit !== void 0) {
3154
+ this.textureUnit = textureUnit;
3155
+ gl.activeTexture(33984 + textureUnit);
3156
+ }
3157
+ gl.bindTexture(this.glTarget, null);
3158
+ return textureUnit;
3158
3159
  }
3159
3160
  };
3160
3161