• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 */
15import { query } from '../../database/SqlLite';
16import { TraceRow } from '../trace/base/TraceRow';
17interface VSyncData {
18  startTime: number;
19  dur: number;
20  value?: number;
21}
22
23let vSyncDataList: VSyncData[] = [];
24let vSyncEnable = false;
25let isSingle = false;
26let isQuery = false;
27
28export function resetVSync(): void {
29  vSyncEnable = false;
30  isQuery = false;
31}
32
33export const querySfVSyncData = (): Promise<Array<VSyncData>> =>
34  query(
35    'querySfVSyncData',
36    `SELECT value, c.ts - tb.start_ts startTime
37     FROM process_measure c,
38          trace_range tb
39     WHERE c.filter_id IN (SELECT process_measure_filter.id AS traceId
40                           FROM process_measure_filter
41                                    JOIN process USING (ipid)
42                           WHERE process.name = ${
43                             `'` +
44                             String.fromCharCode(115, 117, 114, 102, 97, 99, 101, 102, 108, 105, 110, 103, 101, 114) +
45                             `'`
46                           }
47                             AND process_measure_filter.name = ${
48                               `'` + String.fromCharCode(86, 83, 89, 78, 67, 45, 97, 112, 112) + `'`
49                             })`
50  );
51
52export const querySingleVSyncData = (): Promise<Array<VSyncData>> =>
53  query(
54    'querySingleVSyncData',
55    `SELECT c.ts - tb.start_ts startTime
56     FROM callstack c,
57          trace_range tb
58     WHERE c.id IN (SELECT callstack.id AS trackId
59                    FROM callstack
60                             JOIN process
61                    WHERE process.name = 'render_service'
62                      AND (callstack.name like 'H:GenerateVsyncCount%' or callstack.name like 'H:VSyncGenerator::ThreadLoop::Continue%'))`
63  );
64
65/**
66 * load single vsync data
67 */
68export async function setVSyncData(): Promise<void> {
69  let sfvSyncData = await querySfVSyncData();
70  if (sfvSyncData.length === 0) {
71    sfvSyncData = await querySingleVSyncData();
72    isSingle = true;
73  }
74  sfvSyncData.forEach((it, index, array): void => {
75    if (index < array.length - 1) {
76      it.dur = array[index + 1].startTime - it.startTime;
77    } else {
78      it.dur = window.totalNS - it.startTime;
79    }
80  });
81  vSyncDataList = sfvSyncData;
82  isQuery = true;
83}
84
85/**
86 * draw chart
87 */
88export function drawVSync(ctx: CanvasRenderingContext2D, width: number, height: number): void {
89  if (!vSyncEnable) {
90    return;
91  }
92  function draw(it: VSyncData): void {
93    let x = ns2x(it.startTime, width);
94    let x2 = ns2x(it.startTime + it.dur, width);
95    ctx.fillRect(x, 0, x2 - x, height);
96  }
97  ctx.beginPath();
98  ctx.fillStyle = '#555555';
99  ctx.lineWidth = 1;
100  ctx.globalAlpha = 0.3;
101  if (isSingle) {
102    // 单框架灰白交替
103    for (let i = 0; i < vSyncDataList.length; i++) {
104      if (i % 2 === 1) {
105        continue;
106      }
107      draw(vSyncDataList[i]);
108    }
109  } else {
110    // 双框架绘制vSync 信号为1的数据为灰
111    vSyncDataList
112      ?.filter((it) => it.value === 1)
113      .forEach((it) => {
114        draw(it);
115      });
116  }
117  ctx.stroke();
118  ctx.globalAlpha = 1.0;
119  ctx.closePath();
120}
121
122/**
123 * enable/disable SingleVSync
124 */
125export function enableVSync(press: boolean, ev: KeyboardEvent, handler?: Function): void {
126  if (!isQuery) {
127    window.publish(window.SmartEvent.UI.Loading, { loading: true, text: 'Query VSync' });
128    setVSyncData();
129    window.publish(window.SmartEvent.UI.Loading, { loading: false, text: 'Query VSync' });
130  }
131  if (ev.key.toLocaleLowerCase() === 'v' && !ev.ctrlKey) {
132    vSyncEnable = !vSyncEnable;
133    handler?.();
134  }
135}
136
137/**
138 * ns to px
139 */
140function ns2x(ns: number, width: number): number {
141  let startNS = TraceRow.range?.startNS || 0;
142  let endNS = TraceRow.range?.endNS || 0;
143  if (endNS === 0) {
144    endNS = (window as any).totalNS;
145  }
146  let xWidth: number = ((ns - startNS) * width) / (endNS - startNS);
147  if (xWidth < 0) {
148    xWidth = 0;
149  } else if (xWidth > width) {
150    xWidth = width;
151  }
152  return xWidth;
153}
154