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 { SpSystemTrace } from '../SpSystemTrace'; 17import { TraceRow } from '../trace/base/TraceRow'; 18import { renders } from '../../database/ui-worker/ProcedureWorker'; 19import { FlagsConfig } from '../SpFlags'; 20import { CpuFreqStruct } from '../../database/ui-worker/ProcedureWorkerFreq'; 21import { 22 queryFanceNameList, 23 queryFpsNameList, 24 queryRealFpsList, 25 queryRSNowTimeList, 26 querySignaledList, 27 querySkipDataList, 28} from '../../database/sql/Ltpo.sql'; 29import { LtpoRender, LtpoStruct } from '../../database/ui-worker/ProcedureWorkerLTPO'; 30import { HitchTimeStruct, hitchTimeRender } from '../../database/ui-worker/ProcedureWorkerHitchTime'; 31import { lostFrameSender } from '../../database/data-trafic/LostFrameSender'; 32 33export class SpLtpoChart { 34 private readonly trace: SpSystemTrace | undefined; 35 static APP_STARTUP_PID_ARR: Array<number> = []; 36 static jsonRow: TraceRow<CpuFreqStruct> | undefined; 37 static trace: SpSystemTrace; 38 static presentArr: Array<LtpoStruct> = []; 39 static fanceNameList: Array<LtpoStruct> = []; 40 static fpsnameList: Array<LtpoStruct> = []; 41 static realFpsList: Array<LtpoStruct> = []; 42 static rsNowTimeList: Array<LtpoStruct> = []; 43 static skipDataList: Array<LtpoStruct> = []; 44 static ltpoDataArr: Array<LtpoStruct> = []; 45 static sendLTPODataArr: Array<LtpoStruct> = []; 46 static sendHitchDataArr: Array<LtpoStruct> = []; 47 static signaledFence: Array<LtpoStruct> = []; 48 static tempRsNowTimeList: Array<LtpoStruct> = []; 49 static threadName: String = 'Present%'; 50 static funName: String = 'H:Waiting for Present Fence%'; 51 static signaledList: Array<LtpoStruct> = []; 52 constructor(trace: SpSystemTrace) { 53 SpLtpoChart.trace = trace; 54 } 55 56 async init() { 57 let loadLtpo: boolean = FlagsConfig.getFlagsConfigEnableStatus('LTPO'); 58 if (!loadLtpo) { 59 return; 60 } 61 SpLtpoChart.ltpoDataArr = []; 62 SpLtpoChart.fanceNameList = await queryFanceNameList(); 63 SpLtpoChart.fpsnameList = await queryFpsNameList(); 64 SpLtpoChart.realFpsList = await queryRealFpsList(); 65 SpLtpoChart.rsNowTimeList = await queryRSNowTimeList(); 66 SpLtpoChart.skipDataList = await querySkipDataList(); 67 SpLtpoChart.signaledList = await querySignaledList(); 68 this.initFenceName(); 69 this.initFpsName(); 70 if (SpLtpoChart.realFpsList.length > 0) { 71 this.initRealFps(); 72 } 73 this.initRsNowTime(); 74 //特殊情况:当前trace的RSHardwareThrea泳道最前面多一个单独的fence 75 if (SpLtpoChart.fpsnameList.length > 0 && SpLtpoChart.fanceNameList.length - SpLtpoChart.fpsnameList.length === 1) { 76 if (Number(SpLtpoChart.fanceNameList[0].ts) < Number(SpLtpoChart.fpsnameList[0].ts)) { 77 SpLtpoChart.fanceNameList.splice(0, 1); 78 } 79 } 80 if (SpLtpoChart.fanceNameList!.length && SpLtpoChart.fpsnameList.length !== SpLtpoChart.fanceNameList.length) { 81 let fpsIndex = 0; 82 let fanceIndex = 0; 83 while (fpsIndex < SpLtpoChart.fpsnameList!.length) { 84 if (SpLtpoChart.fanceNameList[fanceIndex] && SpLtpoChart.fpsnameList[fpsIndex]) { 85 if ( 86 SpLtpoChart.fanceNameList[fanceIndex].ts! > SpLtpoChart.fpsnameList[fpsIndex].ts! && 87 SpLtpoChart.fanceNameList[fanceIndex].ts! < 88 SpLtpoChart.fpsnameList[fpsIndex].ts! + SpLtpoChart.fpsnameList[fpsIndex].dur! 89 ) { 90 fpsIndex++; 91 fanceIndex++; 92 } else if (SpLtpoChart.fanceNameList[fanceIndex].ts! < SpLtpoChart.fpsnameList[fpsIndex].ts!) { 93 SpLtpoChart.fanceNameList.splice(fanceIndex, 1); 94 } else if ( 95 SpLtpoChart.fanceNameList[fanceIndex].ts! > 96 SpLtpoChart.fpsnameList[fpsIndex].ts! + SpLtpoChart.fpsnameList[fpsIndex].dur! 97 ) { 98 SpLtpoChart.fpsnameList.splice(fpsIndex, 1); 99 } 100 } else if (SpLtpoChart.fanceNameList[fanceIndex] && !SpLtpoChart.fpsnameList[fpsIndex]) { 101 SpLtpoChart.fanceNameList.splice(fanceIndex); 102 } else if (!SpLtpoChart.fanceNameList[fanceIndex] && SpLtpoChart.fpsnameList[fpsIndex]) { 103 SpLtpoChart.fpsnameList.splice(fpsIndex); 104 } else { 105 return; 106 } 107 } 108 } 109 if (SpLtpoChart.fanceNameList!.length && SpLtpoChart.fpsnameList.length === SpLtpoChart.fanceNameList.length) { 110 for (let i = 0; i < SpLtpoChart.fanceNameList.length; i++) { 111 let tmpFps = SpLtpoChart.fpsnameList[i]!.fps ? Number(SpLtpoChart.fpsnameList[i]!.fps) : 60; 112 let signaled = Number(SpLtpoChart.fanceNameList[i]!.signaled); 113 let startTime = Number(SpLtpoChart.fanceNameList[i]!.ts); 114 let durtaion = Number(SpLtpoChart.fanceNameList[i]!.dur); 115 if (SpLtpoChart.fanceNameList[i]!.signaled) { 116 this.pushLtpoData( 117 SpLtpoChart.ltpoDataArr, 118 SpLtpoChart.fanceNameList[i]!.fanceId!, 119 tmpFps, 120 signaled, 121 startTime, 122 durtaion, 123 0, 124 0 125 ); 126 } else { 127 this.pushLtpoData(SpLtpoChart.ltpoDataArr, SpLtpoChart.fanceNameList[i]!.fanceId!, tmpFps, 0, 0, 0, 0, 0); 128 } 129 } 130 } else { 131 return; 132 } 133 this.fenceToFps(); 134 this.fpsToRenderService(); 135 this.filterNowTime(); 136 if (SpLtpoChart.fanceNameList && SpLtpoChart.fanceNameList.length) { 137 await this.initFolder(); 138 await this.initHitchTime(); 139 } 140 } 141 //提取FenceId 142 initFenceName(): void { 143 SpLtpoChart.fanceNameList.map((item) => { 144 let cutFanceNameArr = item.name!.split(' '); 145 if (cutFanceNameArr[cutFanceNameArr.length - 1] === 'signaled') { 146 item.fanceId = Number(cutFanceNameArr[2]); 147 item.signaled = 1; 148 SpLtpoChart.signaledFence.push(item); 149 } else { 150 item.fanceId = Number(cutFanceNameArr[cutFanceNameArr.length - 1]); 151 } 152 }); 153 } 154 //从数据库中查询的name中提取fps 155 initFpsName(): void { 156 SpLtpoChart.fpsnameList.map((item) => { 157 if (item.name!.indexOf('=') === -1) { 158 let cutFpsNameArr = item.name!.split(',')[0].split(':'); 159 let cutFpsNameTimeArr = item.name!.split(',')[1].split(':'); 160 item.fps = Number(cutFpsNameArr[cutFpsNameArr.length - 1]); 161 item.nowTime = Number(cutFpsNameTimeArr[cutFpsNameTimeArr.length - 1]); 162 } else { 163 let cutFpsNameArr = item.name!.split('='); 164 item.fps = Number(cutFpsNameArr[cutFpsNameArr.length - 1]); 165 } 166 }); 167 } 168 //如果存在切帧,提取fps 169 initRealFps(): void { 170 SpLtpoChart.realFpsList.map((item) => { 171 let cutRealFpsArr = item.name!.split(' '); 172 item.fps = Number(cutRealFpsArr[cutRealFpsArr.length - 1]); 173 }); 174 this.setRealFps(); 175 } 176 //从render_service中获取nowTime 177 initRsNowTime(): void { 178 SpLtpoChart.rsNowTimeList.map((item) => { 179 let cutRsNameArr = item.name!.split(' ')[2].split(':'); 180 item.nowTime = Number(cutRsNameArr[cutRsNameArr.length - 1]); 181 }); 182 } 183 //处理fps 184 setRealFps(): void { 185 let moreIndex = 0; 186 let reallIndex = 0; 187 while (moreIndex < SpLtpoChart.fpsnameList.length) { 188 let itemMoreEndTs = 189 Number(SpLtpoChart.fpsnameList[moreIndex].ts) + Number(SpLtpoChart.fpsnameList[moreIndex].dur); 190 if (Number(SpLtpoChart.realFpsList[reallIndex].ts) < itemMoreEndTs) { 191 //此时这一帧包含了两个fps,将真实的fps赋给SpLtpoChart.fpsnameList 192 SpLtpoChart.fpsnameList[moreIndex].fps = SpLtpoChart.realFpsList[reallIndex].fps; 193 moreIndex++; 194 if (reallIndex < SpLtpoChart.realFpsList.length - 1) { 195 //判断SpLtpoChart.realFpsList有没有遍历完,没有就继续 196 reallIndex++; 197 } else { 198 //否则跳出 199 return; 200 } 201 } else { 202 //如果不满足的话,SpLtpoChart.fpsnameList数组往下走,而reallIndex不变 203 moreIndex++; 204 } 205 } 206 } 207 //RSHardwareThread泳道的fps数组集成FenceId数组中的FenceId和signaled 208 fenceToFps() { 209 if (SpLtpoChart.fanceNameList.length === SpLtpoChart.fpsnameList.length) { 210 let fenceIndex = 0; 211 let fpsIndex = 0; 212 while (fpsIndex < SpLtpoChart.fpsnameList.length) { 213 if (SpLtpoChart.fpsnameList[fpsIndex] && SpLtpoChart.fanceNameList[fenceIndex]) { 214 if ( 215 SpLtpoChart.fanceNameList[fenceIndex].ts! > SpLtpoChart.fpsnameList[fpsIndex].ts! && 216 SpLtpoChart.fanceNameList[fenceIndex].ts! < 217 SpLtpoChart.fpsnameList[fpsIndex].ts! + SpLtpoChart.fpsnameList[fpsIndex].dur! 218 ) { 219 SpLtpoChart.fpsnameList[fpsIndex].fanceId = SpLtpoChart.fanceNameList[fenceIndex].fanceId; 220 if (SpLtpoChart.fanceNameList[fenceIndex].signaled) { 221 SpLtpoChart.fpsnameList[fpsIndex].signaled = SpLtpoChart.fanceNameList[fenceIndex].signaled; 222 } 223 fenceIndex++; 224 fpsIndex++; 225 } else if (SpLtpoChart.fanceNameList[fenceIndex].ts! < SpLtpoChart.fpsnameList[fpsIndex].ts!) { 226 fenceIndex++; 227 } else if ( 228 SpLtpoChart.fanceNameList[fenceIndex].ts! > 229 SpLtpoChart.fpsnameList[fpsIndex].ts! + SpLtpoChart.fpsnameList[fpsIndex].dur! 230 ) { 231 fpsIndex++; 232 } 233 } else { 234 return; 235 } 236 } 237 } 238 } 239 //render_service的nowTime 集成RSHardThread泳道Fps数组的FenceId和Signaled 240 fpsToRenderService(): void { 241 let rsIndex = 0; 242 let hardIndex = 0; 243 while (rsIndex < SpLtpoChart.rsNowTimeList.length) { 244 if (SpLtpoChart.fpsnameList[hardIndex] && SpLtpoChart.rsNowTimeList[rsIndex]) { 245 if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! > SpLtpoChart.fpsnameList[hardIndex].nowTime!) { 246 //处理nowTime不一致的情况 247 hardIndex++; 248 } else if (SpLtpoChart.rsNowTimeList[rsIndex].nowTime! < SpLtpoChart.fpsnameList[hardIndex].nowTime!) { 249 rsIndex++; 250 } else { 251 SpLtpoChart.rsNowTimeList[rsIndex].fanceId = SpLtpoChart.fpsnameList[hardIndex].fanceId; 252 SpLtpoChart.rsNowTimeList[rsIndex].fps = SpLtpoChart.fpsnameList[hardIndex].fps; 253 if (SpLtpoChart.fpsnameList[hardIndex].signaled) { 254 SpLtpoChart.rsNowTimeList[rsIndex].signaled = SpLtpoChart.fpsnameList[hardIndex].signaled; 255 } 256 hardIndex++; 257 rsIndex++; 258 } 259 } else { 260 return; 261 } 262 } 263 } 264 //render_service中找出skip和signaled,将需要从上平时间减去的时间计算出来存在对应的nowTime的item中 265 filterNowTime(): void { 266 let skipIndex = 0; 267 let nowTimeIndex = 0; 268 let cutTimeSum = 0; 269 let tempFps = 0; //如果中间出现signaled,记录一下fps; 270 //将render_service中的nowTime数组中的skip去除掉 271 SpLtpoChart.tempRsNowTimeList = SpLtpoChart.rsNowTimeList.filter((item) => item.fps); 272 while (skipIndex < SpLtpoChart.skipDataList.length) { 273 if (SpLtpoChart.skipDataList[skipIndex] && SpLtpoChart.tempRsNowTimeList[nowTimeIndex]) { 274 if (SpLtpoChart.skipDataList[skipIndex].ts! > SpLtpoChart.tempRsNowTimeList[nowTimeIndex].ts!) { 275 if (cutTimeSum > 0 && nowTimeIndex > 0) { 276 SpLtpoChart.tempRsNowTimeList[nowTimeIndex - 1].cutTime = cutTimeSum; 277 if (!SpLtpoChart.tempRsNowTimeList[nowTimeIndex].signaled) { 278 cutTimeSum = 0; 279 } 280 } 281 if (SpLtpoChart.tempRsNowTimeList[nowTimeIndex].signaled && nowTimeIndex > 0) { 282 //两帧之间初心signaled 283 tempFps = SpLtpoChart.tempRsNowTimeList[nowTimeIndex].fps!; 284 cutTimeSum += 1000 / tempFps; 285 SpLtpoChart.tempRsNowTimeList[nowTimeIndex - 1].cutTime = cutTimeSum; 286 SpLtpoChart.tempRsNowTimeList.splice(nowTimeIndex, 1); 287 } else { 288 nowTimeIndex++; 289 cutTimeSum = 0; 290 tempFps = 0; 291 } 292 } else if (SpLtpoChart.skipDataList[skipIndex].ts! <= SpLtpoChart.tempRsNowTimeList[nowTimeIndex].ts!) { 293 if (nowTimeIndex > 0) { 294 cutTimeSum += tempFps ? 1000 / tempFps : 1000 / SpLtpoChart.tempRsNowTimeList[nowTimeIndex - 1].fps!; 295 } 296 skipIndex++; 297 } 298 } else { 299 return; 300 } 301 } 302 } 303 pushLtpoData( 304 lptoArr: unknown[] | undefined, 305 fanceId: Number, 306 fps: Number, 307 signaled: Number, 308 startTs: Number, 309 dur: Number, 310 nextStartTs: Number, 311 nextDur: number 312 ): void { 313 lptoArr?.push({ 314 fanceId: fanceId, 315 fps: fps, 316 signaled: signaled, 317 startTs: startTs, 318 dur: dur, 319 nextStartTs: nextStartTs, 320 nextDur: nextDur, 321 }); 322 } 323 sendDataHandle(presentArr: LtpoStruct[], ltpoDataArr: LtpoStruct[]): Array<LtpoStruct> { 324 let sendDataArr: LtpoStruct[] = []; 325 let ltpoDataIndex = 0; 326 let tempRsNowTimeIndex = 0; 327 let presentIndex = 0; 328 let ltpoIndex = 0; 329 //当有present缺失时: 330 this.deleteUselessFence(presentArr, ltpoDataArr); 331 while (presentIndex < presentArr.length) { 332 if (presentArr[presentIndex] && ltpoDataArr[ltpoIndex]) { 333 if ( 334 // @ts-ignore 335 presentArr[presentIndex].startTime! + presentArr[presentIndex].dur! - (window as unknown).recordStartNS === 336 TraceRow.range!.totalNS 337 ) { 338 presentArr.splice(presentIndex, 1); 339 } 340 if (presentArr[presentIndex].presentId === ltpoDataArr[ltpoIndex].fanceId) { 341 // @ts-ignore 342 ltpoDataArr[ltpoIndex].startTs = Number(presentArr[presentIndex].startTime) - (window as unknown).recordStartNS; 343 ltpoDataArr[ltpoIndex].dur = presentArr[presentIndex].dur; 344 ltpoDataArr[ltpoIndex].nextStartTs = presentArr[presentIndex + 1] 345 // @ts-ignore 346 ? Number(presentArr[presentIndex + 1].startTime) - (window as unknown).recordStartNS 347 : ''; 348 ltpoDataArr[ltpoIndex].nextDur = presentArr[presentIndex + 1] ? presentArr[presentIndex + 1].dur : 0; 349 presentIndex++; 350 ltpoIndex++; 351 } else if (presentArr[presentIndex].presentId! < ltpoDataArr[ltpoIndex].fanceId!) { 352 presentArr.splice(presentIndex, 1); 353 } else if (presentArr[presentIndex].presentId! > ltpoDataArr[ltpoIndex].fanceId!) { 354 ltpoDataArr.splice(ltpoIndex, 1); 355 } 356 } else { 357 break; 358 } 359 } 360 while (ltpoDataIndex < ltpoDataArr.length) { 361 let sendStartTs: number | undefined = 0; 362 let sendDur: number | undefined = 0; 363 let cutSendDur: number | undefined = 0; 364 if (ltpoDataArr[ltpoDataIndex] && SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex]) { 365 if (ltpoDataArr[ltpoDataIndex].fanceId! < SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].fanceId!) { 366 if (ltpoDataArr[ltpoDataIndex].fanceId !== -1 && ltpoDataArr[ltpoDataIndex].nextDur) { 367 sendStartTs = Number(ltpoDataArr[ltpoDataIndex].startTs) + Number(ltpoDataArr[ltpoDataIndex].dur); 368 sendDur = 369 Number(ltpoDataArr[ltpoDataIndex].nextStartTs) + Number(ltpoDataArr[ltpoDataIndex].nextDur) - sendStartTs; 370 } 371 let tmpDur = cutSendDur ? Math.ceil(cutSendDur / 100000) / 10 : Math.ceil(sendDur / 100000) / 10; 372 if (tmpDur < 170) { 373 sendDataArr.push({ 374 dur: sendDur, 375 cutSendDur: cutSendDur, 376 value: 0, 377 startTs: sendStartTs, 378 pid: ltpoDataArr[ltpoDataIndex].fanceId, 379 itid: ltpoDataArr[ltpoDataIndex].fanceId, 380 name: undefined, 381 presentId: ltpoDataArr[ltpoDataIndex].fanceId, 382 ts: undefined, 383 fanceId: ltpoDataArr[ltpoDataIndex].fanceId, 384 fps: ltpoDataArr[ltpoDataIndex].fps, 385 nextStartTs: ltpoDataArr[ltpoDataIndex].nextStartTs, 386 nextDur: ltpoDataArr[ltpoDataIndex].nextDur, 387 translateY: undefined, 388 isHover: false, 389 startTime: undefined, 390 signaled: undefined, 391 nowTime: undefined, 392 cutTime: undefined, 393 frame: undefined, 394 }); 395 } 396 ltpoDataIndex++; 397 } else if (ltpoDataArr[ltpoDataIndex].fanceId! > SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].fanceId!) { 398 tempRsNowTimeIndex++; 399 } else { 400 if (SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].cutTime) { 401 cutSendDur = sendDur - SpLtpoChart.tempRsNowTimeList[tempRsNowTimeIndex].cutTime! * 1000000; 402 cutSendDur = cutSendDur < 0 ? 0 : cutSendDur; 403 } 404 if (ltpoDataArr[ltpoDataIndex].fanceId !== -1 && ltpoDataArr[ltpoDataIndex].nextDur) { 405 sendStartTs = Number(ltpoDataArr[ltpoDataIndex].startTs) + Number(ltpoDataArr[ltpoDataIndex].dur); 406 sendDur = 407 Number(ltpoDataArr[ltpoDataIndex].nextStartTs) + Number(ltpoDataArr[ltpoDataIndex].nextDur) - sendStartTs; 408 } 409 let tmpDur = cutSendDur ? Math.ceil(cutSendDur / 100000) / 10 : Math.ceil(sendDur / 100000) / 10; 410 if (tmpDur < 170) { 411 sendDataArr.push({ 412 dur: sendDur, 413 cutSendDur: cutSendDur, 414 value: 0, 415 startTs: sendStartTs, 416 pid: ltpoDataArr[ltpoDataIndex].fanceId, 417 itid: ltpoDataArr[ltpoDataIndex].fanceId, 418 name: undefined, 419 presentId: ltpoDataArr[ltpoDataIndex].fanceId, 420 ts: undefined, 421 fanceId: ltpoDataArr[ltpoDataIndex].fanceId, 422 fps: ltpoDataArr[ltpoDataIndex].fps, 423 nextStartTs: ltpoDataArr[ltpoDataIndex].nextStartTs, 424 nextDur: ltpoDataArr[ltpoDataIndex].nextDur, 425 translateY: undefined, 426 isHover: false, 427 startTime: undefined, 428 signaled: undefined, 429 nowTime: undefined, 430 cutTime: undefined, 431 frame: undefined, 432 }); 433 } 434 ltpoDataIndex++; 435 tempRsNowTimeIndex++; 436 } 437 } else { 438 break; 439 } 440 } 441 return sendDataArr; 442 } 443 deleteUselessFence(presentArr: LtpoStruct[], ltpoDataArr: LtpoStruct[]) { 444 //当有present缺失时: 445 let presentIndex = 0; 446 let fpsIndex = 0; 447 while (fpsIndex < ltpoDataArr.length) { 448 //遍历present,把ltpoDataArr中不包含present中presentFance的item舍弃掉 449 if (presentArr[presentIndex] && ltpoDataArr[fpsIndex]) { 450 if (Number(presentArr[presentIndex].presentId) < Number(ltpoDataArr[fpsIndex].fanceId)) { 451 presentArr.splice(presentIndex, 1); 452 } else if (Number(presentArr[presentIndex].presentId) > Number(ltpoDataArr[fpsIndex].fanceId)) { 453 ltpoDataArr.splice(fpsIndex, 1); 454 } else { 455 if (presentIndex === presentArr.length - 1 && fpsIndex < ltpoDataArr.length - 1) { 456 //此时present已经遍历到最后一项,如果ltpoDataArr还没有遍历到最后一项,就把后面的舍弃掉 457 ltpoDataArr.splice(fpsIndex); 458 } 459 presentIndex++; 460 fpsIndex++; 461 } 462 } else { 463 return; 464 } 465 } 466 } 467 //六舍七入 468 specialValue(num: number) { 469 if (num < 0.7) { 470 return 0; 471 } else { 472 if (!num.toString().split('.')[1]) { 473 return num; 474 } else { 475 let tempNum = Number(num.toString().split('.')[1].charAt(0)); 476 if (tempNum > 6) { 477 return Math.ceil(num); 478 } else { 479 return Math.floor(num); 480 } 481 } 482 } 483 } 484 485 async initFolder() { 486 SpLtpoChart.presentArr = []; 487 let row: TraceRow<LtpoStruct> = TraceRow.skeleton<LtpoStruct>(); 488 row.rowId = SpLtpoChart.fanceNameList!.length ? `LTPO ${SpLtpoChart.fanceNameList[0].fanceId}` : ''; 489 row.rowParentId = ''; 490 row.rowType = TraceRow.ROW_TYPE_LTPO; 491 row.folder = false; 492 row.style.height = '40px'; 493 row.name = `Lost Frames`; 494 row.favoriteChangeHandler = SpLtpoChart.trace.favoriteChangeHandler; 495 row.selectChangeHandler = SpLtpoChart.trace.selectChangeHandler; 496 row.supplierFrame = () => { 497 return lostFrameSender(SpLtpoChart.threadName, SpLtpoChart.funName, row).then((res) => { 498 SpLtpoChart.presentArr = res; 499 SpLtpoChart.sendLTPODataArr = this.sendDataHandle(SpLtpoChart.presentArr, SpLtpoChart.ltpoDataArr); 500 for (let i = 0; i < SpLtpoChart.sendLTPODataArr.length; i++) { 501 let tmpDur = SpLtpoChart.sendLTPODataArr[i].cutSendDur 502 ? SpLtpoChart.sendLTPODataArr[i].cutSendDur! / 1000000 503 : SpLtpoChart.sendLTPODataArr[i].dur! / 1000000; 504 let mathValue = (tmpDur * Number(SpLtpoChart.sendLTPODataArr[i].fps)) / 1000 - 1; 505 SpLtpoChart.sendLTPODataArr[i].value = this.specialValue(mathValue); 506 } 507 return SpLtpoChart.sendLTPODataArr; 508 }); 509 }; 510 row.focusHandler = () => { 511 SpLtpoChart.trace?.displayTip( 512 row!, 513 LtpoStruct.hoverLtpoStruct, 514 `<span>${LtpoStruct.hoverLtpoStruct?.value!}</span>` 515 ); 516 }; 517 row.findHoverStruct = (): void => { 518 LtpoStruct.hoverLtpoStruct = row.getHoverStruct(true, false, 'value'); 519 }; 520 row.onThreadHandler = (useCache): void => { 521 let context: CanvasRenderingContext2D; 522 if (row.currentContext) { 523 context = row.currentContext; 524 } else { 525 context = row.collect ? SpLtpoChart.trace.canvasFavoritePanelCtx! : SpLtpoChart.trace.canvasPanelCtx!; 526 } 527 row.canvasSave(context); 528 (renders['ltpo-present'] as LtpoRender).renderMainThread( 529 { 530 ltpoContext: context, 531 useCache: useCache, 532 type: `ltpo-present ${row.rowId}`, 533 }, 534 row 535 ); 536 row.canvasRestore(context); 537 }; 538 SpLtpoChart.trace.rowsEL?.appendChild(row); 539 } 540 async initHitchTime() { 541 SpLtpoChart.presentArr = []; 542 let row: TraceRow<HitchTimeStruct> = TraceRow.skeleton<HitchTimeStruct>(); 543 this.takeStaticArg(row); 544 row.supplierFrame = () => { 545 return lostFrameSender(SpLtpoChart.threadName, SpLtpoChart.funName, row).then((res) => { 546 SpLtpoChart.presentArr = res; 547 SpLtpoChart.sendHitchDataArr = this.sendDataHandle(SpLtpoChart.presentArr, SpLtpoChart.ltpoDataArr); 548 for (let i = 0; i < SpLtpoChart.sendHitchDataArr.length; i++) { 549 let tmpVale = 0; 550 let tmpDur = 0; 551 if (SpLtpoChart.sendHitchDataArr[i].cutSendDur) { 552 tmpVale = 553 SpLtpoChart.sendHitchDataArr[i].cutSendDur! / 1000000 - 1000 / SpLtpoChart.sendHitchDataArr[i].fps!; 554 tmpDur = SpLtpoChart.sendHitchDataArr[i].cutSendDur! / 1000000; 555 } else { 556 tmpVale = SpLtpoChart.sendHitchDataArr[i].dur! / 1000000 - 1000 / SpLtpoChart.sendHitchDataArr[i].fps!; 557 tmpDur = SpLtpoChart.sendHitchDataArr[i].dur! / 1000000; 558 } 559 560 let mathValue = (tmpDur * Number(SpLtpoChart.sendHitchDataArr[i].fps)) / 1000 - 1; 561 let finalValue = (tmpVale! / (1000 / SpLtpoChart.sendHitchDataArr[i].fps!)) < 0.7 ? 0 : tmpVale; 562 SpLtpoChart.sendHitchDataArr[i].value = Number(finalValue.toFixed(1)); 563 SpLtpoChart.sendHitchDataArr[i].name = this.specialValue(mathValue)!.toString(); 564 } 565 return SpLtpoChart.sendHitchDataArr; 566 }); 567 }; 568 row.focusHandler = () => { 569 SpLtpoChart.trace?.displayTip( 570 row!, 571 HitchTimeStruct.hoverHitchTimeStruct, 572 `<span>${HitchTimeStruct.hoverHitchTimeStruct?.value!}</span>` 573 ); 574 }; 575 row.findHoverStruct = (): void => { 576 HitchTimeStruct.hoverHitchTimeStruct = row.getHoverStruct(true, false, 'value'); 577 }; 578 row.onThreadHandler = (useCache): void => { 579 let context: CanvasRenderingContext2D; 580 if (row.currentContext) { 581 context = row.currentContext; 582 } else { 583 context = row.collect ? SpLtpoChart.trace.canvasFavoritePanelCtx! : SpLtpoChart.trace.canvasPanelCtx!; 584 } 585 row.canvasSave(context); 586 (renders['hitch'] as hitchTimeRender).renderMainThread( 587 { 588 hitchTimeContext: context, 589 useCache: useCache, 590 type: `hitch ${row.rowId}`, 591 }, 592 row 593 ); 594 row.canvasRestore(context); 595 }; 596 SpLtpoChart.trace.rowsEL?.appendChild(row); 597 } 598 takeStaticArg(row: TraceRow<HitchTimeStruct>) { 599 row.rowId = SpLtpoChart.fanceNameList!.length ? `hitch-time ${SpLtpoChart.fanceNameList[0].fanceId}` : ''; 600 row.rowParentId = ''; 601 row.rowType = TraceRow.ROW_TYPE_HITCH_TIME; 602 row.folder = false; 603 row.style.height = '40px'; 604 row.name = `Hitch Time`; 605 row.favoriteChangeHandler = SpLtpoChart.trace.favoriteChangeHandler; 606 row.selectChangeHandler = SpLtpoChart.trace.selectChangeHandler; 607 } 608} 609