"use strict"; (function (global) { const nowMs = () => (global.performance?.now ? global.performance.now() : Date.now()); const buckets = new Map(); let frameOpen = null; let frameCount = 0; let lastQualityCheckAt = 0; let tier = "high"; let dprScale = 1; let resizeRequested = false; function bucketFor(label) { let b = buckets.get(label); if (!b) { b = { label, ms: 0, avg: 0, max: 0, calls: 0, last: 0 }; buckets.set(label, b); } return b; } function begin(label) { const start = nowMs(); return () => { const elapsed = Math.max(0, nowMs() - start); const b = bucketFor(label); b.ms += elapsed; b.calls += 1; b.last = elapsed; if (elapsed > b.max) b.max = elapsed; return elapsed; }; } function beginFrame() { frameOpen = nowMs(); return frameOpen; } function smoothBuckets() { for (const b of buckets.values()) { b.avg = b.avg ? b.avg * 0.82 + b.ms * 0.18 : b.ms; b.ms = 0; b.calls = 0; } } function qualityFromFps(fps) { const f = Number(fps) || 0; if (f > 55) return { tier: "high", dpr: 1 }; if (f < 32) return { tier: "low", dpr: 0.72 }; if (f < 45) return { tier: "mid", dpr: 0.86 }; return { tier: tier === "low" ? "mid" : tier, dpr: tier === "low" ? 0.86 : dprScale }; } function endFrame(rawDt = 0, fps = global.__tarinaiFps || 0) { frameCount += 1; if (frameOpen != null) { const b = bucketFor("frame.total"); const elapsed = Math.max(0, nowMs() - frameOpen); b.ms += elapsed; b.calls += 1; b.last = elapsed; if (elapsed > b.max) b.max = elapsed; frameOpen = null; } const t = nowMs(); if (t - lastQualityCheckAt >= 750) { lastQualityCheckAt = t; smoothBuckets(); const next = qualityFromFps(fps); const nextDpr = next.dpr; if (next.tier !== tier || Math.abs(nextDpr - dprScale) > 0.04) { tier = next.tier; dprScale = nextDpr; resizeRequested = true; } } } function renderQualityTier() { return tier; } function dprScaleValue() { return dprScale; } function consumeResizeRequest() { const v = resizeRequested; resizeRequested = false; return v; } function snapshot() { const entries = [...buckets.values()].map(b => ({ label: b.label, avg: Number((b.avg || 0).toFixed(2)), max: Number((b.max || 0).toFixed(2)), last: Number((b.last || 0).toFixed(2)), calls: b.calls || 0, })).sort((a, b) => b.avg - a.avg); return { tier, dprScale, frameCount, entries }; } global.TarinaiPerf = Object.freeze({ begin, beginFrame, endFrame, renderQualityTier, dprScale: dprScaleValue, consumeResizeRequest, snapshot, }); })(typeof window !== "undefined" ? window : globalThis);