1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16import { 17 BaseStruct, 18 dataFilterHandler, 19 isFrameContainPoint, 20 ns2x, 21 Render, 22 drawLoadingFrame, 23 Rect, 24} from '../ProcedureWorkerCommon'; 25import { ColorUtils } from '../../../component/trace/base/ColorUtils'; 26import { TraceRow } from '../../../component/trace/base/TraceRow'; 27import { SpSystemTrace } from '../../../component/SpSystemTrace'; 28 29export class CpuFreqLimitRender extends Render { 30 renderMainThread( 31 cpuFreqLimitReq: { 32 useCache: boolean; 33 context: CanvasRenderingContext2D; 34 cpu: number; 35 type: string; 36 maxFreq: number; 37 maxFreqName: string; 38 }, 39 row: TraceRow<CpuFreqLimitsStruct> 40 ): void { 41 let list = row.dataList; 42 let filter = row.dataListCache; 43 dataFilterHandler(list, filter, { 44 startKey: 'startNs', 45 durKey: 'dur', 46 startNS: TraceRow.range?.startNS ?? 0, 47 endNS: TraceRow.range?.endNS ?? 0, 48 totalNS: TraceRow.range?.totalNS ?? 0, 49 frame: row.frame, 50 paddingTop: 5, 51 useCache: cpuFreqLimitReq.useCache || !(TraceRow.range?.refresh ?? false), 52 }); 53 drawLoadingFrame(cpuFreqLimitReq.context, filter, row); 54 cpuFreqLimitReq.context.beginPath(); 55 let maxFreq = cpuFreqLimitReq.maxFreq; 56 let maxFreqName = cpuFreqLimitReq.maxFreqName; 57 if (row.isHover) { 58 for (let re of filter) { 59 if (re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) { 60 CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct = re; 61 break; 62 } 63 } 64 } 65 for (let re of filter) { 66 CpuFreqLimitsStruct.draw(cpuFreqLimitReq.context, re, maxFreq); 67 } 68 cpuFreqLimitReq.context.closePath(); 69 let s = maxFreqName; 70 let textMetrics = cpuFreqLimitReq.context.measureText(s); 71 cpuFreqLimitReq.context.globalAlpha = 0.8; 72 cpuFreqLimitReq.context.fillStyle = '#f0f0f0'; 73 cpuFreqLimitReq.context.fillRect(0, 5, textMetrics.width + 8, 18); 74 cpuFreqLimitReq.context.globalAlpha = 1; 75 cpuFreqLimitReq.context.fillStyle = '#333'; 76 cpuFreqLimitReq.context.textBaseline = 'middle'; 77 cpuFreqLimitReq.context.fillText(s, 4, 5 + 9); 78 } 79} 80export function CpuFreqLimitsStructOnClick(clickRowType: string, sp: SpSystemTrace): Promise<unknown> { 81 return new Promise((resolve, reject) => { 82 if (clickRowType === TraceRow.ROW_TYPE_CPU_FREQ_LIMIT && CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct) { 83 CpuFreqLimitsStruct.selectCpuFreqLimitsStruct = CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct; 84 sp.traceSheetEL?.displayFreqLimitData(); 85 sp.timerShaftEL?.modifyFlagList(undefined); 86 reject(new Error()); 87 } else { 88 resolve(null); 89 } 90 }); 91} 92export class CpuFreqLimitsStruct extends BaseStruct { 93 static hoverCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined; 94 static selectCpuFreqLimitsStruct: CpuFreqLimitsStruct | undefined; 95 static minAlpha = 0.4; 96 static maxAlpha = 0.8; 97 startNs: number | undefined; 98 dur: number = 0; 99 max: number | undefined; 100 min: number | undefined; 101 cpu: number = 0; 102 103 static draw(ctx: CanvasRenderingContext2D, data: CpuFreqLimitsStruct, maxFreq: number): void { 104 if (data.frame) { 105 let width = data.frame.width || 0; 106 let drawMaxHeight: number = Math.floor(((data.max || 0) * (data.frame.height || 0)) / maxFreq); 107 let drawMinHeight: number = Math.floor(((data.min || 0) * (data.frame.height || 0)) / maxFreq); 108 let index = data.cpu || 0; 109 index += 2; 110 ctx.fillStyle = ColorUtils.colorForTid(index); 111 ctx.strokeStyle = ColorUtils.colorForTid(index); 112 if ( 113 data === CpuFreqLimitsStruct.hoverCpuFreqLimitsStruct || 114 data === CpuFreqLimitsStruct.selectCpuFreqLimitsStruct 115 ) { 116 ctx.lineWidth = 1; 117 ctx.globalAlpha = this.minAlpha; 118 this.drawArcLine(ctx, data, drawMaxHeight, drawMaxHeight - drawMinHeight); 119 ctx.globalAlpha = this.maxAlpha; 120 this.drawArcLine(ctx, data, drawMinHeight, drawMinHeight); 121 } else { 122 ctx.globalAlpha = this.minAlpha; 123 ctx.lineWidth = 1; 124 ctx.fillRect( 125 data.frame.x, 126 data.frame.y + data.frame.height - drawMaxHeight, 127 width, 128 drawMaxHeight - drawMinHeight 129 ); 130 ctx.globalAlpha = this.maxAlpha; 131 ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - drawMinHeight, width, drawMinHeight); 132 } 133 } 134 ctx.globalAlpha = 1.0; 135 ctx.lineWidth = 1; 136 } 137 138 static drawArcLine( 139 ctx: CanvasRenderingContext2D, 140 data: CpuFreqLimitsStruct, 141 yStartHeight: number, 142 drawHeight: number 143 ): void { 144 if (data.frame) { 145 let width = data.frame.width || 0; 146 ctx.fillRect(data.frame.x, data.frame.y + data.frame.height - yStartHeight, width, drawHeight); 147 ctx.globalAlpha = this.maxAlpha; 148 ctx.beginPath(); 149 ctx.arc(data.frame.x, data.frame.y + data.frame.height - yStartHeight, 3, 0, 2 * Math.PI, true); 150 ctx.fill(); 151 ctx.stroke(); 152 ctx.beginPath(); 153 ctx.moveTo(data.frame.x + 3, data.frame.y + data.frame.height - yStartHeight); 154 ctx.lineWidth = 3; 155 ctx.lineTo(data.frame.x + width, data.frame.y + data.frame.height - yStartHeight); 156 ctx.stroke(); 157 } 158 } 159 160 static setFreqLimitFrame( 161 freqLimitNode: CpuFreqLimitsStruct, 162 padding: number, 163 startNS: number, 164 endNS: number, 165 totalNS: number, 166 frame: Rect 167 ): void { 168 let x1: number; 169 let x2: number; 170 if ((freqLimitNode.startNs || 0) < startNS) { 171 x1 = 0; 172 } else { 173 x1 = ns2x(freqLimitNode.startNs || 0, startNS, endNS, totalNS, frame); 174 } 175 if ((freqLimitNode.startNs || 0) + (freqLimitNode.dur || 0) > endNS) { 176 x2 = frame.width; 177 } else { 178 x2 = ns2x((freqLimitNode.startNs || 0) + (freqLimitNode.dur || 0), startNS, endNS, totalNS, frame); 179 } 180 let cpuFreqLimitsGetV: number = x2 - x1 <= 1 ? 1 : x2 - x1; 181 if (!freqLimitNode.frame) { 182 freqLimitNode.frame = new Rect(0, 0, 0, 0); 183 } 184 freqLimitNode.frame.x = Math.floor(x1); 185 freqLimitNode.frame.y = frame.y + padding; 186 freqLimitNode.frame.width = Math.ceil(cpuFreqLimitsGetV); 187 freqLimitNode.frame.height = Math.floor(frame.height - padding * 2); 188 } 189} 190