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 { ColorUtils } from '../../component/trace/base/ColorUtils';
17import { BaseStruct, dataFilterHandler, isFrameContainPoint, Render, RequestMessage } from './ProcedureWorkerCommon';
18import { TraceRow } from '../../component/trace/base/TraceRow';
19import { SpSegmentationChart } from '../../component/chart/SpSegmentationChart';
20import { drawLoadingFrame } from './ProcedureWorkerCommon';
21import { ns2x, Rect } from './ProcedureWorkerCommon';
22import { Flag } from '../../component/trace/timer-shaft/Flag';
23export class FreqExtendRender extends Render {
24  renderMainThread(
25    freqReq: {
26      context: CanvasRenderingContext2D;
27      useCache: boolean;
28      type: string;
29    },
30    row: TraceRow<CpuFreqExtendStruct>
31  ): void {
32    let freqExtendList = row.dataList;
33    let freqExtendFilter = row.dataListCache;
34    dataFilterHandler(freqExtendList, freqExtendFilter, {
35      startKey: 'startNS',
36      durKey: 'dur',
37      startNS: TraceRow.range?.startNS ?? 0,
38      endNS: TraceRow.range?.endNS ?? 0,
39      totalNS: TraceRow.range?.totalNS ?? 0,
40      frame: row.frame,
41      paddingTop: 5,
42      useCache: freqReq.useCache || !(TraceRow.range?.refresh ?? false),
43    });
44    drawLoadingFrame(freqReq.context, freqExtendFilter, row);
45    freqReq.context.beginPath();
46    let find = false;
47    // tab页点击周期
48    if (SpSegmentationChart.tabHoverObj && SpSegmentationChart.tabHoverObj.key !== '' && SpSegmentationChart.tabHoverObj.key === freqReq.type) {
49      // 鼠标不在tab页,清空高亮
50      if (!SpSegmentationChart.trace.isMousePointInSheet) {
51        SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 };
52        CpuFreqExtendStruct.hoverStruct = undefined;
53        SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined;
54        find = false;
55      }
56      // tab页点击周期对应泳道
57      if (SpSegmentationChart.tabHoverObj.key === freqReq.type) {
58        for (let re of freqExtendFilter) {
59          if (!row.isHover && re.cycle === SpSegmentationChart.tabHoverObj.cycle) {
60            CpuFreqExtendStruct.hoverStruct = re;
61            find = true;
62          }
63          CpuFreqExtendStruct.draw(freqReq.context, re, freqReq.type, row);
64        }
65        // dur太小,从datalist里面找
66        if (!find) {
67          let hoverData = freqExtendList.filter(v => {
68            return v.cycle === SpSegmentationChart.tabHoverObj.cycle;
69          })[0];
70          let pointX: number = ns2x(
71            hoverData.startNS || 0,
72            TraceRow.range!.startNS,
73            TraceRow.range!.endNS,
74            TraceRow.range!.totalNS,
75            new Rect(0, 0, TraceRow.FRAME_WIDTH, 0)
76          );
77          SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag(
78            Math.floor(pointX),
79            0,
80            0,
81            0,
82            hoverData.startNS,
83            '#666666',
84            '',
85            true,
86            ''
87          );
88        }
89      } else {
90        for (let re of freqExtendFilter) {
91          CpuFreqExtendStruct.draw(freqReq.context, re, freqReq.type, row);
92        }
93      }
94      // 正常悬浮或者tab页取消点击周期
95    } else {
96      // 鼠标悬浮色块
97      for (let re of freqExtendFilter) {
98        if (row.isHover && re.frame && isFrameContainPoint(re.frame, row.hoverX, row.hoverY)) {
99          if (SpSegmentationChart.tabHoverObj) {
100            // @ts-ignore
101            SpSegmentationChart.tabHoverObj = { key: freqReq.type, cycle: re.cycle };
102          }
103          CpuFreqExtendStruct.hoverStruct = re;
104          find = true;
105        }
106        CpuFreqExtendStruct.draw(freqReq.context, re, freqReq.type, row);
107      }
108      // 取消点击周期
109      if ((row.isHover && !find) || (!row.isHover && SpSegmentationChart.tabHoverObj && SpSegmentationChart.tabHoverObj.key !== '' &&
110        freqReq.type === SpSegmentationChart.tabHoverObj.key) ||
111        (SpSegmentationChart.trace.isMousePointInSheet && SpSegmentationChart.tabHoverObj && SpSegmentationChart.tabHoverObj.key === '')
112      ) {
113        CpuFreqExtendStruct.hoverStruct = undefined;
114        SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = undefined;
115        SpSegmentationChart.tabHoverObj = { key: '', cycle: -1 };
116      }
117    }
118    freqReq.context.closePath();
119  }
120}
121
122export class CpuFreqExtendStruct extends BaseStruct {
123  static hoverStruct: CpuFreqExtendStruct | undefined;
124  static cpuMaxValue: number = 0;
125  static gpuMaxValue: number = 0;
126  static schedMaxValue: number = 0;
127  static cpuCycle: number = -1;
128  static gpuCycle: number = -1;
129  static schedCycle: number = -1;
130  static isTabHover: boolean = false;
131  static hoverType: string = '';
132  static tabCycle: number = -1;
133  static selectCpuFreqStruct: CpuFreqExtendStruct | undefined;
134  value: number = 0;
135  startNS: number = 0;
136  dur: number | undefined; //自补充,数据库没有返回
137  cycle: number | undefined;
138  colorIndex: number = 0;
139
140  static draw(freqContext: CanvasRenderingContext2D, data: CpuFreqExtendStruct, type: string, row: TraceRow<CpuFreqExtendStruct>): void {
141    if (data.frame) {
142      let width = data.frame.width || 0;
143      let index = data.colorIndex || 0;
144      index += 2;
145      let color = ColorUtils.colorForTid(index);
146      if (type === 'SCHED-SWITCH') {
147        color = '#3ced33';
148      }
149      freqContext.fillStyle = color;
150      if (
151        data === CpuFreqExtendStruct.hoverStruct
152      ) {
153        freqContext.globalAlpha = 1.0;
154        let drawHeight: number = Math.floor(
155          ((data.value || 0) * (data.frame.height || 0) * 1.0) / (type === 'CPU-FREQ'
156            ? CpuFreqExtendStruct.cpuMaxValue : type === 'GPU-FREQ'
157              ? CpuFreqExtendStruct.gpuMaxValue : CpuFreqExtendStruct.schedMaxValue)
158        );
159        if (drawHeight < 1) {
160          drawHeight = 1;
161        }
162        freqContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width < 1 ? 1 : width, drawHeight);
163        let pointX: number = ns2x(
164          data.startNS || 0,
165          TraceRow.range!.startNS,
166          TraceRow.range!.endNS,
167          TraceRow.range!.totalNS,
168          new Rect(0, 0, TraceRow.FRAME_WIDTH, 0)
169        );
170        SpSegmentationChart.trace.traceSheetEL!.systemLogFlag = new Flag(
171          Math.floor(pointX),
172          0,
173          0,
174          0,
175          data.startNS,
176          '#666666',
177          '',
178          true,
179          ''
180        );
181      } else {
182        freqContext.globalAlpha = 0.6;
183        freqContext.lineWidth = 1;
184        let drawHeight: number = Math.floor(
185          ((data.value || 0) * (data.frame.height || 0)) / (type === 'CPU-FREQ'
186            ? CpuFreqExtendStruct.cpuMaxValue : type === 'GPU-FREQ'
187              ? CpuFreqExtendStruct.gpuMaxValue : CpuFreqExtendStruct.schedMaxValue)
188        );
189        if (drawHeight < 1) {
190          drawHeight = 1;
191        }
192        freqContext.fillRect(data.frame.x, data.frame.y + data.frame.height - drawHeight, width < 1 ? 1 : width, drawHeight);
193      }
194    }
195  }
196}
197