/*---------------------------------------------------------------------------------------------
* Copyright (c) Bentley Systems, Incorporated. All rights reserved.
* See LICENSE.md in the project root for license terms and full copyright notice.
*--------------------------------------------------------------------------------------------*/
/** @packageDocumentation
 * @module WebGL
 */
import { assert, dispose } from "@itwin/core-bentley";
import { RenderMode } from "@itwin/core-common";
import { RenderMemory } from "../../../render/RenderMemory";
import { AttributeMap } from "./AttributeMap";
import { PolylineBuffers } from "./CachedGeometry";
import { ColorInfo } from "./ColorInfo";
import { GL } from "./GL";
import { BufferHandle, BufferParameters, BuffersContainer } from "./AttributeBuffers";
import { System } from "./System";
import { MeshGeometry } from "./MeshGeometry";
import { lineCodeFromLinePixels } from "../../../common/internal/render/LineCode";
/** @internal */
export class EdgeGeometry extends MeshGeometry {
    buffers;
    _indices;
    _endPointAndQuadIndices;
    get lutBuffers() { return this.buffers; }
    get asSurface() { return undefined; }
    get asEdge() { return this; }
    get asSilhouette() { return undefined; }
    static create(mesh, edges) {
        const indexBuffer = BufferHandle.createArrayBuffer(edges.indices.data);
        const endPointBuffer = BufferHandle.createArrayBuffer(edges.endPointAndQuadIndices);
        return undefined !== indexBuffer && undefined !== endPointBuffer ? new EdgeGeometry(indexBuffer, endPointBuffer, edges.indices.length, mesh) : undefined;
    }
    get isDisposed() {
        return this.buffers.isDisposed
            && this._indices.isDisposed
            && this._endPointAndQuadIndices.isDisposed;
    }
    [Symbol.dispose]() {
        dispose(this.buffers);
        dispose(this._indices);
        dispose(this._endPointAndQuadIndices);
    }
    collectStatistics(stats) {
        stats.addVisibleEdges(this._indices.bytesUsed + this._endPointAndQuadIndices.bytesUsed);
    }
    _draw(numInstances, instanceBuffersContainer) {
        const bufs = instanceBuffersContainer !== undefined ? instanceBuffersContainer : this.buffers;
        bufs.bind();
        System.instance.drawArrays(GL.PrimitiveType.Triangles, 0, this._numIndices, numInstances);
        bufs.unbind();
    }
    _wantWoWReversal(_target) { return true; }
    _getLineCode(params) { return this.computeEdgeLineCode(params); }
    get techniqueId() { return 4 /* TechniqueId.Edge */; }
    getPass(target) { return this.computeEdgePass(target); }
    get renderOrder() { return this.isPlanar ? 14 /* RenderOrder.PlanarEdge */ : 6 /* RenderOrder.Edge */; }
    getColor(target) { return this.computeEdgeColor(target); }
    get endPointAndQuadIndices() { return this._endPointAndQuadIndices; }
    wantMonochrome(target) {
        return target.currentViewFlags.renderMode === RenderMode.Wireframe;
    }
    constructor(indices, endPointAndQuadsIndices, numIndices, mesh) {
        super(mesh, numIndices);
        this.buffers = BuffersContainer.create();
        const attrPos = AttributeMap.findAttribute("a_pos", 4 /* TechniqueId.Edge */, false);
        const attrEndPointAndQuadIndices = AttributeMap.findAttribute("a_endPointAndQuadIndices", 4 /* TechniqueId.Edge */, false);
        assert(attrPos !== undefined);
        assert(attrEndPointAndQuadIndices !== undefined);
        this.buffers.addBuffer(indices, [BufferParameters.create(attrPos.location, 3, GL.DataType.UnsignedByte, false, 0, 0, false)]);
        this.buffers.addBuffer(endPointAndQuadsIndices, [BufferParameters.create(attrEndPointAndQuadIndices.location, 4, GL.DataType.UnsignedByte, false, 0, 0, false)]);
        this._indices = indices;
        this._endPointAndQuadIndices = endPointAndQuadsIndices;
    }
}
/** @internal */
export class SilhouetteEdgeGeometry extends EdgeGeometry {
    _normalPairs;
    get asSilhouette() { return this; }
    static createSilhouettes(mesh, params) {
        const indexBuffer = BufferHandle.createArrayBuffer(params.indices.data);
        const endPointBuffer = BufferHandle.createArrayBuffer(params.endPointAndQuadIndices);
        const normalsBuffer = BufferHandle.createArrayBuffer(params.normalPairs);
        return undefined !== indexBuffer && undefined !== endPointBuffer && undefined !== normalsBuffer ? new SilhouetteEdgeGeometry(indexBuffer, endPointBuffer, normalsBuffer, params.indices.length, mesh) : undefined;
    }
    get isDisposed() { return super.isDisposed && this._normalPairs.isDisposed; }
    [Symbol.dispose]() {
        super[Symbol.dispose]();
        dispose(this._normalPairs);
    }
    collectStatistics(stats) {
        stats.addSilhouetteEdges(this._indices.bytesUsed + this._endPointAndQuadIndices.bytesUsed + this._normalPairs.bytesUsed);
    }
    get techniqueId() { return 5 /* TechniqueId.SilhouetteEdge */; }
    get renderOrder() { return this.isPlanar ? 15 /* RenderOrder.PlanarSilhouette */ : 7 /* RenderOrder.Silhouette */; }
    get normalPairs() { return this._normalPairs; }
    constructor(indices, endPointAndQuadsIndices, normalPairs, numIndices, mesh) {
        super(indices, endPointAndQuadsIndices, numIndices, mesh);
        const attrNormals = AttributeMap.findAttribute("a_normals", 5 /* TechniqueId.SilhouetteEdge */, false);
        assert(attrNormals !== undefined);
        this.buffers.addBuffer(normalPairs, [BufferParameters.create(attrNormals.location, 4, GL.DataType.UnsignedByte, false, 0, 0, false)]);
        this._normalPairs = normalPairs;
    }
}
/** @internal */
export class PolylineEdgeGeometry extends MeshGeometry {
    _buffers;
    _colorInfo;
    _width;
    _lineCode;
    get lutBuffers() { return this._buffers.buffers; }
    static create(mesh, group) {
        const buffers = PolylineBuffers.create(group.polyline);
        return undefined !== buffers ? new PolylineEdgeGeometry(group.polyline.indices.length, buffers, mesh, group.appearance) : undefined;
    }
    get isDisposed() { return this._buffers.isDisposed; }
    [Symbol.dispose]() {
        dispose(this._buffers);
    }
    collectStatistics(stats) {
        this._buffers.collectStatistics(stats, RenderMemory.BufferType.PolylineEdges);
    }
    _wantWoWReversal(_target) { return true; }
    get techniqueId() { return 1 /* TechniqueId.Polyline */; }
    getPass(target) { return this.computeEdgePass(target); }
    get renderOrder() { return this.isPlanar ? 14 /* RenderOrder.PlanarEdge */ : 6 /* RenderOrder.Edge */; }
    get polylineBuffers() { return this._buffers; }
    _getLineCode(params) {
        return params.target.computeEdgeLineCode(params.renderPass, this._lineCode);
    }
    _getLineWeight(params) {
        return params.target.computeEdgeWeight(params.renderPass, this._width);
    }
    getColor(target) {
        return target.computeEdgeColor(this._colorInfo);
    }
    wantMonochrome(target) {
        return target.currentViewFlags.renderMode === RenderMode.Wireframe;
    }
    _draw(numInstances, instanceBuffersContainer) {
        const gl = System.instance;
        const bufs = instanceBuffersContainer !== undefined ? instanceBuffersContainer : this._buffers.buffers;
        bufs.bind();
        gl.drawArrays(GL.PrimitiveType.Triangles, 0, this._numIndices, numInstances);
        bufs.unbind();
    }
    constructor(numIndices, buffers, mesh, appearance) {
        super(mesh, numIndices);
        this._buffers = buffers;
        this._colorInfo = appearance?.color ? ColorInfo.createFromColorDef(appearance.color) : mesh.lut.colorInfo;
        this._width = appearance?.width ?? mesh.edgeWidth;
        this._lineCode = appearance?.linePixels ? lineCodeFromLinePixels(appearance?.linePixels) : mesh.edgeLineCode;
    }
}
//# sourceMappingURL=EdgeGeometry.js.map