/*---------------------------------------------------------------------------------------------
* 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 { PrimitiveVisibility } from "../RenderTarget";
import { LUTGeometry, SkySphereViewportQuadGeometry } from "./CachedGeometry";
import { DrawParams, PrimitiveCommand } from "./DrawCommand";
import { Graphic } from "./Graphic";
import { InstanceBuffers, InstancedGeometry, PatternBuffers } from "./InstancedGeometry";
import { System } from "./System";
/** @internal */
export class Primitive extends Graphic {
    constructor(cachedGeom) {
        super();
        this.isPixelMode = false;
        this.cachedGeometry = cachedGeom;
    }
    static create(geom, instances) {
        if (!geom)
            return undefined;
        if (instances) {
            assert(geom instanceof LUTGeometry, "Invalid geometry type for instancing");
            if (instances instanceof PatternBuffers) {
                geom = InstancedGeometry.createPattern(geom, true, instances);
            }
            else {
                geom = InstancedGeometry.create(geom, true, instances);
            }
        }
        return new this(geom);
    }
    static createShared(geom, instances) {
        if (!geom)
            return undefined;
        if (instances) {
            assert(geom instanceof LUTGeometry, "Invalid geometry type for instancing");
            if (instances instanceof InstanceBuffers)
                geom = InstancedGeometry.create(geom, false, instances);
            else
                geom = InstancedGeometry.createPattern(geom, false, instances);
        }
        return new this(geom);
    }
    get isDisposed() { return this.cachedGeometry.isDisposed; }
    get isPickable() { return false; }
    dispose() {
        dispose(this.cachedGeometry);
    }
    collectStatistics(stats) {
        this.cachedGeometry.collectStatistics(stats);
    }
    unionRange(range) {
        range.extendRange(this.cachedGeometry.computeRange());
    }
    getPass(target) {
        if (this.isPixelMode)
            return "view-overlay";
        switch (target.primitiveVisibility) {
            case PrimitiveVisibility.Uninstanced:
                if (this.cachedGeometry.isInstanced)
                    return "none";
                break;
            case PrimitiveVisibility.Instanced:
                if (!this.cachedGeometry.isInstanced)
                    return "none";
                break;
        }
        return this.cachedGeometry.getPass(target);
    }
    get hasFeatures() { return this.cachedGeometry.hasFeatures; }
    addCommands(commands) { commands.addPrimitive(this); }
    addHiliteCommands(commands, pass) {
        // Edges do not contribute to hilite pass.
        // Note that IsEdge() does not imply geom->ToEdge() => true...polylines can be edges too...
        if (!this.isEdge)
            commands.getCommands(pass).push(new PrimitiveCommand(this));
    }
    get hasAnimation() { return this.cachedGeometry.hasAnimation; }
    get isInstanced() { return this.cachedGeometry.isInstanced; }
    get isLit() { return this.cachedGeometry.isLitSurface; }
    get isEdge() { return this.cachedGeometry.isEdge; }
    get renderOrder() { return this.cachedGeometry.renderOrder; }
    get hasMaterialAtlas() { return this.cachedGeometry.hasMaterialAtlas; }
    toPrimitive() { return this; }
    static freeParams() { Primitive._drawParams = undefined; }
    draw(shader) {
        // ###TODO: local to world should be pushed before we're invoked...we shouldn't need to pass (or copy) it
        if (undefined === Primitive._drawParams)
            Primitive._drawParams = new DrawParams();
        const drawParams = Primitive._drawParams;
        drawParams.init(shader.params, this.cachedGeometry);
        shader.draw(drawParams);
    }
    get techniqueId() { return this.cachedGeometry.techniqueId; }
}
/** @internal */
export class SkyCubePrimitive extends Primitive {
    constructor(cachedGeom) { super(cachedGeom); }
    draw(shader) {
        // Alter viewport to maintain square aspect ratio of skybox images even as viewRect resizes
        const vh = shader.target.viewRect.height;
        const vw = shader.target.viewRect.width;
        if (vw > vh)
            System.instance.context.viewport(0, -(vw - vh) / 2, vw, vw);
        else
            System.instance.context.viewport(-(vh - vw) / 2, 0, vh, vh);
        super.draw(shader); // Draw the skybox cubemap
        System.instance.context.viewport(0, 0, vw, vh); // Restore viewport
    }
}
/** @internal */
export class SkySpherePrimitive extends Primitive {
    constructor(cachedGeom) {
        super(cachedGeom);
        assert(cachedGeom instanceof SkySphereViewportQuadGeometry);
    }
    draw(shader) {
        this.cachedGeometry.initWorldPos(shader.target);
        super.draw(shader); // Draw the skybox sphere
    }
}
//# sourceMappingURL=Primitive.js.map