| OLD | NEW |
| 1 <!DOCTYPE html> | 1 <!DOCTYPE html> |
| 2 <!-- | 2 <!-- |
| 3 Copyright (c) 2015 The Chromium Authors. All rights reserved. | 3 Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 4 Use of this source code is governed by a BSD-style license that can be | 4 Use of this source code is governed by a BSD-style license that can be |
| 5 found in the LICENSE file. | 5 found in the LICENSE file. |
| 6 --> | 6 --> |
| 7 | 7 |
| 8 <link rel="import" href="/tracing/base/range_utils.html"> | 8 <link rel="import" href="/tracing/base/range_utils.html"> |
| 9 <link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.htm
l"> | 9 <link rel="import" href="/tracing/extras/chrome/cc/input_latency_async_slice.htm
l"> |
| 10 <link rel="import" href="/tracing/importer/proto_expectation.html"> | 10 <link rel="import" href="/tracing/importer/proto_expectation.html"> |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 var MOUSE_WHEEL_THRESHOLD_MS = 40; | 94 var MOUSE_WHEEL_THRESHOLD_MS = 40; |
| 95 | 95 |
| 96 /** | 96 /** |
| 97 * If two MouseMoves are more than this far apart, then they're two Responses, | 97 * If two MouseMoves are more than this far apart, then they're two Responses, |
| 98 * not Animation. | 98 * not Animation. |
| 99 */ | 99 */ |
| 100 var MOUSE_MOVE_THRESHOLD_MS = 40; | 100 var MOUSE_MOVE_THRESHOLD_MS = 40; |
| 101 | 101 |
| 102 // TODO(benjhayden) Find a better home for this. | 102 // TODO(benjhayden) Find a better home for this. |
| 103 function compareEvents(x, y) { | 103 function compareEvents(x, y) { |
| 104 if (x.start !== y.start) | 104 if (x.start !== y.start) { |
| 105 return x.start - y.start; | 105 return x.start - y.start; |
| 106 if (x.end !== y.end) | 106 } |
| 107 if (x.end !== y.end) { |
| 107 return x.end - y.end; | 108 return x.end - y.end; |
| 108 if (x.guid && y.guid) | 109 } |
| 110 if (x.guid && y.guid) { |
| 109 return x.guid - y.guid; | 111 return x.guid - y.guid; |
| 112 } |
| 110 return 0; | 113 return 0; |
| 111 } | 114 } |
| 112 | 115 |
| 113 function forEventTypesIn(events, typeNames, cb, opt_this) { | 116 function forEventTypesIn(events, typeNames, cb, opt_this) { |
| 114 events.forEach(function(event) { | 117 events.forEach(function(event) { |
| 115 if (typeNames.indexOf(event.typeName) >= 0) { | 118 if (typeNames.indexOf(event.typeName) >= 0) { |
| 116 cb.call(opt_this, event); | 119 cb.call(opt_this, event); |
| 117 } | 120 } |
| 118 }); | 121 }); |
| 119 } | 122 } |
| (...skipping 13 matching lines...) Expand all Loading... |
| 133 return frameEventsByPid; | 136 return frameEventsByPid; |
| 134 } | 137 } |
| 135 | 138 |
| 136 function getSortedInputEvents(modelHelper) { | 139 function getSortedInputEvents(modelHelper) { |
| 137 var inputEvents = []; | 140 var inputEvents = []; |
| 138 | 141 |
| 139 var browserProcess = modelHelper.browserHelper.process; | 142 var browserProcess = modelHelper.browserHelper.process; |
| 140 var mainThread = browserProcess.findAtMostOneThreadNamed( | 143 var mainThread = browserProcess.findAtMostOneThreadNamed( |
| 141 'CrBrowserMain'); | 144 'CrBrowserMain'); |
| 142 for (var slice of mainThread.asyncSliceGroup.getDescendantEvents()) { | 145 for (var slice of mainThread.asyncSliceGroup.getDescendantEvents()) { |
| 143 if (!slice.isTopLevel) | 146 if (!slice.isTopLevel) continue; |
| 144 continue; | |
| 145 | 147 |
| 146 if (!(slice instanceof tr.e.cc.InputLatencyAsyncSlice)) | 148 if (!(slice instanceof tr.e.cc.InputLatencyAsyncSlice)) continue; |
| 147 continue; | |
| 148 | 149 |
| 149 // TODO(beaudoin): This should never happen but it does. Investigate | 150 // TODO(beaudoin): This should never happen but it does. Investigate |
| 150 // the trace linked at in #1567 and remove that when it's fixed. | 151 // the trace linked at in #1567 and remove that when it's fixed. |
| 151 if (isNaN(slice.start) || | 152 if (isNaN(slice.start) || |
| 152 isNaN(slice.duration) || | 153 isNaN(slice.duration) || |
| 153 isNaN(slice.end)) | 154 isNaN(slice.end)) { |
| 154 continue; | 155 continue; |
| 156 } |
| 155 | 157 |
| 156 inputEvents.push(slice); | 158 inputEvents.push(slice); |
| 157 } | 159 } |
| 158 | 160 |
| 159 return inputEvents.sort(compareEvents); | 161 return inputEvents.sort(compareEvents); |
| 160 } | 162 } |
| 161 | 163 |
| 162 function findProtoExpectations(modelHelper, sortedInputEvents) { | 164 function findProtoExpectations(modelHelper, sortedInputEvents) { |
| 163 var protoExpectations = []; | 165 var protoExpectations = []; |
| 164 // This order is not important. Handlers are independent. | 166 // This order is not important. Handlers are independent. |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 pe.pushEvent(event); | 342 pe.pushEvent(event); |
| 341 protoExpectations.push(pe); | 343 protoExpectations.push(pe); |
| 342 break; | 344 break; |
| 343 } | 345 } |
| 344 | 346 |
| 345 if (currentPE) { | 347 if (currentPE) { |
| 346 currentPE.pushEvent(event); | 348 currentPE.pushEvent(event); |
| 347 } else { | 349 } else { |
| 348 currentPE = new ProtoExpectation( | 350 currentPE = new ProtoExpectation( |
| 349 ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE); | 351 ProtoExpectation.RESPONSE_TYPE, INITIATOR_TYPE.MOUSE); |
| 350 if (mouseDownEvent) | 352 if (mouseDownEvent) { |
| 351 currentPE.associatedEvents.push(mouseDownEvent); | 353 currentPE.associatedEvents.push(mouseDownEvent); |
| 354 } |
| 352 currentPE.pushEvent(event); | 355 currentPE.pushEvent(event); |
| 353 protoExpectations.push(currentPE); | 356 protoExpectations.push(currentPE); |
| 354 } | 357 } |
| 355 mouseDownEvent = undefined; | 358 mouseDownEvent = undefined; |
| 356 currentPE = undefined; | 359 currentPE = undefined; |
| 357 break; | 360 break; |
| 358 } | 361 } |
| 359 }); | 362 }); |
| 360 if (mouseDownEvent) { | 363 if (mouseDownEvent) { |
| 361 currentPE = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); | 364 currentPE = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 576 var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); | 579 var pe = new ProtoExpectation(ProtoExpectation.IGNORED_TYPE); |
| 577 pe.pushEvent(event); | 580 pe.pushEvent(event); |
| 578 protoExpectations.push(pe); | 581 protoExpectations.push(pe); |
| 579 } | 582 } |
| 580 break; | 583 break; |
| 581 } | 584 } |
| 582 }); | 585 }); |
| 583 // If there was neither a FLING_CANCEL nor a renderer fling after the | 586 // If there was neither a FLING_CANCEL nor a renderer fling after the |
| 584 // FLING_START, then assume that it ends at the end of the model, so set | 587 // FLING_START, then assume that it ends at the end of the model, so set |
| 585 // the end of currentPE to the end of the model. | 588 // the end of currentPE to the end of the model. |
| 586 if (currentPE && !currentPE.end) | 589 if (currentPE && !currentPE.end) { |
| 587 currentPE.end = modelHelper.model.bounds.max; | 590 currentPE.end = modelHelper.model.bounds.max; |
| 591 } |
| 588 return protoExpectations; | 592 return protoExpectations; |
| 589 } | 593 } |
| 590 | 594 |
| 591 /** | 595 /** |
| 592 * The TouchStart and the first TouchMove comprise a Response, then the | 596 * The TouchStart and the first TouchMove comprise a Response, then the |
| 593 * rest of the TouchMoves comprise an Animation. | 597 * rest of the TouchMoves comprise an Animation. |
| 594 * | 598 * |
| 595 * RRRRRRRAAAAAAAAAAAAAAAAAAAA | 599 * RRRRRRRAAAAAAAAAAAAAAAAAAAA |
| 596 * SSS MMM MMM MMM MMM MMM EEE | 600 * SSS MMM MMM MMM MMM MMM EEE |
| 597 * | 601 * |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 * VideoPlayback async events (going from the VideoFrameCompositor::Start | 752 * VideoPlayback async events (going from the VideoFrameCompositor::Start |
| 749 * to VideoFrameCompositor::Stop calls) | 753 * to VideoFrameCompositor::Stop calls) |
| 750 */ | 754 */ |
| 751 function handleVideoAnimations(modelHelper, sortedInputEvents) { | 755 function handleVideoAnimations(modelHelper, sortedInputEvents) { |
| 752 var events = []; | 756 var events = []; |
| 753 for (var pid in modelHelper.rendererHelpers) { | 757 for (var pid in modelHelper.rendererHelpers) { |
| 754 for (var tid in modelHelper.rendererHelpers[pid].process.threads) { | 758 for (var tid in modelHelper.rendererHelpers[pid].process.threads) { |
| 755 for (var asyncSlice of | 759 for (var asyncSlice of |
| 756 modelHelper.rendererHelpers[pid].process.threads[tid] | 760 modelHelper.rendererHelpers[pid].process.threads[tid] |
| 757 .asyncSliceGroup.slices) { | 761 .asyncSliceGroup.slices) { |
| 758 if (asyncSlice.title === PLAYBACK_EVENT_TITLE) | 762 if (asyncSlice.title === PLAYBACK_EVENT_TITLE) { |
| 759 events.push(asyncSlice); | 763 events.push(asyncSlice); |
| 764 } |
| 760 } | 765 } |
| 761 } | 766 } |
| 762 } | 767 } |
| 763 | 768 |
| 764 events.sort(tr.importer.compareEvents); | 769 events.sort(tr.importer.compareEvents); |
| 765 | 770 |
| 766 var protoExpectations = []; | 771 var protoExpectations = []; |
| 767 for (var event of events) { | 772 for (var event of events) { |
| 768 var currentPE = new ProtoExpectation( | 773 var currentPE = new ProtoExpectation( |
| 769 ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.VIDEO); | 774 ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.VIDEO); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 829 start = modelHelper.model.bounds.min; | 834 start = modelHelper.model.bounds.min; |
| 830 } | 835 } |
| 831 | 836 |
| 832 pushAnimationRange(start, sub.start, animation); | 837 pushAnimationRange(start, sub.start, animation); |
| 833 start = undefined; | 838 start = undefined; |
| 834 } | 839 } |
| 835 }); | 840 }); |
| 836 | 841 |
| 837 // An animation was still running when the | 842 // An animation was still running when the |
| 838 // top-level animation event ended. | 843 // top-level animation event ended. |
| 839 if (start !== undefined) | 844 if (start !== undefined) { |
| 840 pushAnimationRange(start, animation.end, animation); | 845 pushAnimationRange(start, animation.end, animation); |
| 846 } |
| 841 } | 847 } |
| 842 }); | 848 }); |
| 843 | 849 |
| 844 // Now we have a set of time ranges when css animations were actually | 850 // Now we have a set of time ranges when css animations were actually |
| 845 // running. | 851 // running. |
| 846 // Leave merging intersecting animations to mergeIntersectingAnimations(), | 852 // Leave merging intersecting animations to mergeIntersectingAnimations(), |
| 847 // after findFrameEventsForAnimations removes frame-less animations. | 853 // after findFrameEventsForAnimations removes frame-less animations. |
| 848 | 854 |
| 849 return animationRanges.map(function(range) { | 855 return animationRanges.map(function(range) { |
| 850 var protoExpectation = new ProtoExpectation( | 856 var protoExpectation = new ProtoExpectation( |
| 851 ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.CSS); | 857 ProtoExpectation.ANIMATION_TYPE, INITIATOR_TYPE.CSS); |
| 852 protoExpectation.start = range.min; | 858 protoExpectation.start = range.min; |
| 853 protoExpectation.end = range.max; | 859 protoExpectation.end = range.max; |
| 854 protoExpectation.associatedEvents.push(range.animation); | 860 protoExpectation.associatedEvents.push(range.animation); |
| 855 return protoExpectation; | 861 return protoExpectation; |
| 856 }); | 862 }); |
| 857 } | 863 } |
| 858 | 864 |
| 859 /** | 865 /** |
| 860 * Get all the events (prepareMailbox and serviceScriptedAnimations) | 866 * Get all the events (prepareMailbox and serviceScriptedAnimations) |
| 861 * relevant to WebGL. Note that modelHelper is the helper object containing | 867 * relevant to WebGL. Note that modelHelper is the helper object containing |
| 862 * the model, and mailboxEvents and animationEvents are arrays where the | 868 * the model, and mailboxEvents and animationEvents are arrays where the |
| 863 * events are being pushed into (DrawingBuffer::prepareMailbox events go | 869 * events are being pushed into (DrawingBuffer::prepareMailbox events go |
| 864 * into mailboxEvents; PageAnimator::serviceScriptedAnimations events go | 870 * into mailboxEvents; PageAnimator::serviceScriptedAnimations events go |
| 865 * into animationEvents). The function does not return anything but | 871 * into animationEvents). The function does not return anything but |
| 866 * modifies mailboxEvents and animationEvents. | 872 * modifies mailboxEvents and animationEvents. |
| 867 */ | 873 */ |
| 868 function findWebGLEvents(modelHelper, mailboxEvents, animationEvents) { | 874 function findWebGLEvents(modelHelper, mailboxEvents, animationEvents) { |
| 869 for (var event of modelHelper.model.getDescendantEvents()) { | 875 for (var event of modelHelper.model.getDescendantEvents()) { |
| 870 if (event.title === 'DrawingBuffer::prepareMailbox') | 876 if (event.title === 'DrawingBuffer::prepareMailbox') { |
| 871 mailboxEvents.push(event); | 877 mailboxEvents.push(event); |
| 872 else if (event.title === 'PageAnimator::serviceScriptedAnimations') | 878 } else if (event.title === 'PageAnimator::serviceScriptedAnimations') { |
| 873 animationEvents.push(event); | 879 animationEvents.push(event); |
| 880 } |
| 874 } | 881 } |
| 875 } | 882 } |
| 876 | 883 |
| 877 /** | 884 /** |
| 878 * Returns a list of events in mailboxEvents that have an event in | 885 * Returns a list of events in mailboxEvents that have an event in |
| 879 * animationEvents close by (within ANIMATION_MERGE_THRESHOLD_MS). | 886 * animationEvents close by (within ANIMATION_MERGE_THRESHOLD_MS). |
| 880 */ | 887 */ |
| 881 function findMailboxEventsNearAnimationEvents( | 888 function findMailboxEventsNearAnimationEvents( |
| 882 mailboxEvents, animationEvents) { | 889 mailboxEvents, animationEvents) { |
| 883 if (animationEvents.length === 0) | 890 if (animationEvents.length === 0) return []; |
| 884 return []; | |
| 885 | 891 |
| 886 mailboxEvents.sort(compareEvents); | 892 mailboxEvents.sort(compareEvents); |
| 887 animationEvents.sort(compareEvents); | 893 animationEvents.sort(compareEvents); |
| 888 var animationIterator = animationEvents[Symbol.iterator](); | 894 var animationIterator = animationEvents[Symbol.iterator](); |
| 889 var animationEvent = animationIterator.next().value; | 895 var animationEvent = animationIterator.next().value; |
| 890 | 896 |
| 891 var filteredEvents = []; | 897 var filteredEvents = []; |
| 892 | 898 |
| 893 // We iterate through the mailboxEvents. With each event, we check if | 899 // We iterate through the mailboxEvents. With each event, we check if |
| 894 // there is a animationEvent near it, and if so, add it to the result. | 900 // there is a animationEvent near it, and if so, add it to the result. |
| 895 for (var event of mailboxEvents) { | 901 for (var event of mailboxEvents) { |
| 896 // If the current animationEvent is too far before the mailboxEvent, | 902 // If the current animationEvent is too far before the mailboxEvent, |
| 897 // we advance until we get to the next animationEvent that is not too | 903 // we advance until we get to the next animationEvent that is not too |
| 898 // far before the animationEvent. | 904 // far before the animationEvent. |
| 899 while (animationEvent && | 905 while (animationEvent && |
| 900 (animationEvent.start < ( | 906 (animationEvent.start < ( |
| 901 event.start - ANIMATION_MERGE_THRESHOLD_MS))) | 907 event.start - ANIMATION_MERGE_THRESHOLD_MS))) { |
| 902 animationEvent = animationIterator.next().value; | 908 animationEvent = animationIterator.next().value; |
| 909 } |
| 903 | 910 |
| 904 // If there aren't any more animationEvents, then that means all the | 911 // If there aren't any more animationEvents, then that means all the |
| 905 // remaining mailboxEvents are too far after the animationEvents, so | 912 // remaining mailboxEvents are too far after the animationEvents, so |
| 906 // we can quit now. | 913 // we can quit now. |
| 907 if (!animationEvent) | 914 if (!animationEvent) break; |
| 908 break; | |
| 909 | 915 |
| 910 // If there's a animationEvent close to the mailboxEvent, then we push | 916 // If there's a animationEvent close to the mailboxEvent, then we push |
| 911 // the current mailboxEvent onto the stack. | 917 // the current mailboxEvent onto the stack. |
| 912 if (animationEvent.start < (event.start + ANIMATION_MERGE_THRESHOLD_MS)) | 918 if (animationEvent.start < (event.start + ANIMATION_MERGE_THRESHOLD_MS)) { |
| 913 filteredEvents.push(event); | 919 filteredEvents.push(event); |
| 920 } |
| 914 } | 921 } |
| 915 return filteredEvents; | 922 return filteredEvents; |
| 916 } | 923 } |
| 917 | 924 |
| 918 /** | 925 /** |
| 919 * Merge consecutive mailbox events into a ProtoExpectation. Note: Only | 926 * Merge consecutive mailbox events into a ProtoExpectation. Note: Only |
| 920 * the drawingBuffer::prepareMailbox events will end up in the | 927 * the drawingBuffer::prepareMailbox events will end up in the |
| 921 * associatedEvents. The PageAnimator::serviceScriptedAnimations events | 928 * associatedEvents. The PageAnimator::serviceScriptedAnimations events |
| 922 * will not end up in the associatedEvents. | 929 * will not end up in the associatedEvents. |
| 923 */ | 930 */ |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 980 * protoExpectations is input only. | 987 * protoExpectations is input only. |
| 981 * Returns a modified set of ProtoExpectations. | 988 * Returns a modified set of ProtoExpectations. |
| 982 */ | 989 */ |
| 983 function mergeIntersectingResponses(protoExpectations) { | 990 function mergeIntersectingResponses(protoExpectations) { |
| 984 var newPEs = []; | 991 var newPEs = []; |
| 985 while (protoExpectations.length) { | 992 while (protoExpectations.length) { |
| 986 var pe = protoExpectations.shift(); | 993 var pe = protoExpectations.shift(); |
| 987 newPEs.push(pe); | 994 newPEs.push(pe); |
| 988 | 995 |
| 989 // Only consider Responses for now. | 996 // Only consider Responses for now. |
| 990 if (pe.type !== ProtoExpectation.RESPONSE_TYPE) | 997 if (pe.type !== ProtoExpectation.RESPONSE_TYPE) continue; |
| 991 continue; | |
| 992 | 998 |
| 993 for (var i = 0; i < protoExpectations.length; ++i) { | 999 for (var i = 0; i < protoExpectations.length; ++i) { |
| 994 var otherPE = protoExpectations[i]; | 1000 var otherPE = protoExpectations[i]; |
| 995 | 1001 |
| 996 if (otherPE.type !== pe.type) | 1002 if (otherPE.type !== pe.type) continue; |
| 997 continue; | |
| 998 | 1003 |
| 999 if (!otherPE.intersects(pe)) | 1004 if (!otherPE.intersects(pe)) continue; |
| 1000 continue; | |
| 1001 | 1005 |
| 1002 // Don't merge together Responses of the same type. | 1006 // Don't merge together Responses of the same type. |
| 1003 // If handleTouchEvents wanted two of its Responses to be merged, then | 1007 // If handleTouchEvents wanted two of its Responses to be merged, then |
| 1004 // it would have made them that way to begin with. | 1008 // it would have made them that way to begin with. |
| 1005 var typeNames = pe.associatedEvents.map(function(event) { | 1009 var typeNames = pe.associatedEvents.map(function(event) { |
| 1006 return event.typeName; | 1010 return event.typeName; |
| 1007 }); | 1011 }); |
| 1008 if (otherPE.containsTypeNames(typeNames)) | 1012 if (otherPE.containsTypeNames(typeNames)) continue; |
| 1009 continue; | |
| 1010 | 1013 |
| 1011 pe.merge(otherPE); | 1014 pe.merge(otherPE); |
| 1012 protoExpectations.splice(i, 1); | 1015 protoExpectations.splice(i, 1); |
| 1013 | 1016 |
| 1014 // Don't skip the next otherPE! | 1017 // Don't skip the next otherPE! |
| 1015 --i; | 1018 --i; |
| 1016 } | 1019 } |
| 1017 } | 1020 } |
| 1018 return newPEs; | 1021 return newPEs; |
| 1019 } | 1022 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1030 * protoExpectations is input only. | 1033 * protoExpectations is input only. |
| 1031 * Returns a modified set of ProtoExpectations. | 1034 * Returns a modified set of ProtoExpectations. |
| 1032 */ | 1035 */ |
| 1033 function mergeIntersectingAnimations(protoExpectations) { | 1036 function mergeIntersectingAnimations(protoExpectations) { |
| 1034 var newPEs = []; | 1037 var newPEs = []; |
| 1035 while (protoExpectations.length) { | 1038 while (protoExpectations.length) { |
| 1036 var pe = protoExpectations.shift(); | 1039 var pe = protoExpectations.shift(); |
| 1037 newPEs.push(pe); | 1040 newPEs.push(pe); |
| 1038 | 1041 |
| 1039 // Only consider Animations for now. | 1042 // Only consider Animations for now. |
| 1040 if (pe.type !== ProtoExpectation.ANIMATION_TYPE) | 1043 if (pe.type !== ProtoExpectation.ANIMATION_TYPE) continue; |
| 1041 continue; | |
| 1042 | 1044 |
| 1043 var isCSS = pe.containsSliceTitle(CSS_ANIMATION_TITLE); | 1045 var isCSS = pe.containsSliceTitle(CSS_ANIMATION_TITLE); |
| 1044 var isFling = pe.containsTypeNames([INPUT_TYPE.FLING_START]); | 1046 var isFling = pe.containsTypeNames([INPUT_TYPE.FLING_START]); |
| 1045 var isVideo = pe.containsTypeNames([INITIATOR_TYPE.VIDEO]); | 1047 var isVideo = pe.containsTypeNames([INITIATOR_TYPE.VIDEO]); |
| 1046 | 1048 |
| 1047 for (var i = 0; i < protoExpectations.length; ++i) { | 1049 for (var i = 0; i < protoExpectations.length; ++i) { |
| 1048 var otherPE = protoExpectations[i]; | 1050 var otherPE = protoExpectations[i]; |
| 1049 | 1051 |
| 1050 if (otherPE.type !== pe.type) | 1052 if (otherPE.type !== pe.type) continue; |
| 1051 continue; | |
| 1052 | 1053 |
| 1053 // Don't merge CSS Animations with any other types. | 1054 // Don't merge CSS Animations with any other types. |
| 1054 if (isCSS !== otherPE.containsSliceTitle(CSS_ANIMATION_TITLE)) | 1055 if (isCSS !== otherPE.containsSliceTitle(CSS_ANIMATION_TITLE)) { |
| 1055 continue; | 1056 continue; |
| 1057 } |
| 1056 | 1058 |
| 1057 if (isCSS) { | 1059 if (isCSS) { |
| 1058 if (!pe.isNear(otherPE, ANIMATION_MERGE_THRESHOLD_MS)) | 1060 if (!pe.isNear(otherPE, ANIMATION_MERGE_THRESHOLD_MS)) { |
| 1059 continue; | 1061 continue; |
| 1062 } |
| 1060 } else if (!otherPE.intersects(pe)) { | 1063 } else if (!otherPE.intersects(pe)) { |
| 1061 continue; | 1064 continue; |
| 1062 } | 1065 } |
| 1063 | 1066 |
| 1064 // Don't merge Fling Animations with any other types. | 1067 // Don't merge Fling Animations with any other types. |
| 1065 if (isFling !== otherPE.containsTypeNames([INPUT_TYPE.FLING_START])) | 1068 if (isFling !== otherPE.containsTypeNames([INPUT_TYPE.FLING_START])) { |
| 1066 continue; | 1069 continue; |
| 1070 } |
| 1067 | 1071 |
| 1068 // Don't merge Video Animations with any other types. | 1072 // Don't merge Video Animations with any other types. |
| 1069 if (isVideo !== otherPE.containsTypeNames([INITIATOR_TYPE.VIDEO])) | 1073 if (isVideo !== otherPE.containsTypeNames([INITIATOR_TYPE.VIDEO])) { |
| 1070 continue; | 1074 continue; |
| 1075 } |
| 1071 | 1076 |
| 1072 pe.merge(otherPE); | 1077 pe.merge(otherPE); |
| 1073 protoExpectations.splice(i, 1); | 1078 protoExpectations.splice(i, 1); |
| 1074 // Don't skip the next otherPE! | 1079 // Don't skip the next otherPE! |
| 1075 --i; | 1080 --i; |
| 1076 } | 1081 } |
| 1077 } | 1082 } |
| 1078 return newPEs; | 1083 return newPEs; |
| 1079 } | 1084 } |
| 1080 | 1085 |
| 1081 /** | 1086 /** |
| 1082 * The ends of responses frequently overlap the starts of animations. | 1087 * The ends of responses frequently overlap the starts of animations. |
| 1083 * Fix the animations to reflect the fact that the user can only start to | 1088 * Fix the animations to reflect the fact that the user can only start to |
| 1084 * expect 60fps after the response. | 1089 * expect 60fps after the response. |
| 1085 * | 1090 * |
| 1086 * For example: | 1091 * For example: |
| 1087 * RRR -> RRRAA | 1092 * RRR -> RRRAA |
| 1088 * AAAA | 1093 * AAAA |
| 1089 * | 1094 * |
| 1090 * protoExpectations is input only. | 1095 * protoExpectations is input only. |
| 1091 * Returns a modified set of ProtoExpectations. | 1096 * Returns a modified set of ProtoExpectations. |
| 1092 */ | 1097 */ |
| 1093 function fixResponseAnimationStarts(protoExpectations) { | 1098 function fixResponseAnimationStarts(protoExpectations) { |
| 1094 protoExpectations.forEach(function(ape) { | 1099 protoExpectations.forEach(function(ape) { |
| 1095 // Only consider animations for now. | 1100 // Only consider animations for now. |
| 1096 if (ape.type !== ProtoExpectation.ANIMATION_TYPE) | 1101 if (ape.type !== ProtoExpectation.ANIMATION_TYPE) { |
| 1097 return; | 1102 return; |
| 1103 } |
| 1098 | 1104 |
| 1099 protoExpectations.forEach(function(rpe) { | 1105 protoExpectations.forEach(function(rpe) { |
| 1100 // Only consider responses for now. | 1106 // Only consider responses for now. |
| 1101 if (rpe.type !== ProtoExpectation.RESPONSE_TYPE) | 1107 if (rpe.type !== ProtoExpectation.RESPONSE_TYPE) { |
| 1102 return; | 1108 return; |
| 1109 } |
| 1103 | 1110 |
| 1104 // Only consider responses that end during the animation. | 1111 // Only consider responses that end during the animation. |
| 1105 if (!ape.containsTimestampInclusive(rpe.end)) | 1112 if (!ape.containsTimestampInclusive(rpe.end)) { |
| 1106 return; | 1113 return; |
| 1114 } |
| 1107 | 1115 |
| 1108 // Ignore Responses that are entirely contained by the animation. | 1116 // Ignore Responses that are entirely contained by the animation. |
| 1109 if (ape.containsTimestampInclusive(rpe.start)) | 1117 if (ape.containsTimestampInclusive(rpe.start)) { |
| 1110 return; | 1118 return; |
| 1119 } |
| 1111 | 1120 |
| 1112 // Move the animation start to the response end. | 1121 // Move the animation start to the response end. |
| 1113 ape.start = rpe.end; | 1122 ape.start = rpe.end; |
| 1114 }); | 1123 }); |
| 1115 }); | 1124 }); |
| 1116 return protoExpectations; | 1125 return protoExpectations; |
| 1117 } | 1126 } |
| 1118 | 1127 |
| 1119 /** | 1128 /** |
| 1120 * Merge Tap Responses that overlap Touch-only Animations. | 1129 * Merge Tap Responses that overlap Touch-only Animations. |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1133 } | 1142 } |
| 1134 var newPEs = []; | 1143 var newPEs = []; |
| 1135 while (protoExpectations.length) { | 1144 while (protoExpectations.length) { |
| 1136 var pe = protoExpectations.shift(); | 1145 var pe = protoExpectations.shift(); |
| 1137 newPEs.push(pe); | 1146 newPEs.push(pe); |
| 1138 | 1147 |
| 1139 // protoExpectations are sorted by start time, and we don't know whether | 1148 // protoExpectations are sorted by start time, and we don't know whether |
| 1140 // the Tap Response or the Touch Animation will be first | 1149 // the Tap Response or the Touch Animation will be first |
| 1141 var peIsTapResponse = isTapResponse(pe); | 1150 var peIsTapResponse = isTapResponse(pe); |
| 1142 var peIsTouchAnimation = isTouchAnimation(pe); | 1151 var peIsTouchAnimation = isTouchAnimation(pe); |
| 1143 if (!peIsTapResponse && !peIsTouchAnimation) | 1152 if (!peIsTapResponse && !peIsTouchAnimation) { |
| 1144 continue; | 1153 continue; |
| 1154 } |
| 1145 | 1155 |
| 1146 for (var i = 0; i < protoExpectations.length; ++i) { | 1156 for (var i = 0; i < protoExpectations.length; ++i) { |
| 1147 var otherPE = protoExpectations[i]; | 1157 var otherPE = protoExpectations[i]; |
| 1148 | 1158 |
| 1149 if (!otherPE.intersects(pe)) | 1159 if (!otherPE.intersects(pe)) continue; |
| 1150 continue; | |
| 1151 | 1160 |
| 1152 if (peIsTapResponse && !isTouchAnimation(otherPE)) | 1161 if (peIsTapResponse && !isTouchAnimation(otherPE)) continue; |
| 1153 continue; | |
| 1154 | 1162 |
| 1155 if (peIsTouchAnimation && !isTapResponse(otherPE)) | 1163 if (peIsTouchAnimation && !isTapResponse(otherPE)) continue; |
| 1156 continue; | |
| 1157 | 1164 |
| 1158 // pe might be the Touch Animation, but the merged ProtoExpectation | 1165 // pe might be the Touch Animation, but the merged ProtoExpectation |
| 1159 // should be a Response. | 1166 // should be a Response. |
| 1160 pe.type = ProtoExpectation.RESPONSE_TYPE; | 1167 pe.type = ProtoExpectation.RESPONSE_TYPE; |
| 1161 | 1168 |
| 1162 pe.merge(otherPE); | 1169 pe.merge(otherPE); |
| 1163 protoExpectations.splice(i, 1); | 1170 protoExpectations.splice(i, 1); |
| 1164 // Don't skip the next otherPE! | 1171 // Don't skip the next otherPE! |
| 1165 --i; | 1172 --i; |
| 1166 } | 1173 } |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1211 | 1218 |
| 1212 /** | 1219 /** |
| 1213 * Check that none of the handlers accidentally ignored an input event. | 1220 * Check that none of the handlers accidentally ignored an input event. |
| 1214 */ | 1221 */ |
| 1215 function checkAllInputEventsHandled(sortedInputEvents, protoExpectations) { | 1222 function checkAllInputEventsHandled(sortedInputEvents, protoExpectations) { |
| 1216 var handledEvents = []; | 1223 var handledEvents = []; |
| 1217 protoExpectations.forEach(function(protoExpectation) { | 1224 protoExpectations.forEach(function(protoExpectation) { |
| 1218 protoExpectation.associatedEvents.forEach(function(event) { | 1225 protoExpectation.associatedEvents.forEach(function(event) { |
| 1219 // Ignore CSS Animations that might have multiple active ranges. | 1226 // Ignore CSS Animations that might have multiple active ranges. |
| 1220 if ((event.title === CSS_ANIMATION_TITLE) && | 1227 if ((event.title === CSS_ANIMATION_TITLE) && |
| 1221 (event.subSlices.length > 0)) | 1228 (event.subSlices.length > 0)) { |
| 1222 return; | 1229 return; |
| 1230 } |
| 1223 | 1231 |
| 1224 if ((handledEvents.indexOf(event) >= 0) && | 1232 if ((handledEvents.indexOf(event) >= 0) && |
| 1225 (event.title !== tr.model.helpers.IMPL_RENDERING_STATS)) { | 1233 (event.title !== tr.model.helpers.IMPL_RENDERING_STATS)) { |
| 1226 modelHelper.model.importWarning({ | 1234 modelHelper.model.importWarning({ |
| 1227 type: 'UserModelBuilder', | 1235 type: 'UserModelBuilder', |
| 1228 message: 'Please file a bug with this trace: ' + | 1236 message: 'Please file a bug with this trace: ' + |
| 1229 `double-handled event: ${event.typeName} @ ${event.start}`, | 1237 `double-handled event: ${event.typeName} @ ${event.start}`, |
| 1230 showToUser: true | 1238 showToUser: true |
| 1231 }); | 1239 }); |
| 1232 return; | 1240 return; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1254 var sortedInputEvents = getSortedInputEvents(modelHelper); | 1262 var sortedInputEvents = getSortedInputEvents(modelHelper); |
| 1255 var protoExpectations = findProtoExpectations( | 1263 var protoExpectations = findProtoExpectations( |
| 1256 modelHelper, sortedInputEvents); | 1264 modelHelper, sortedInputEvents); |
| 1257 protoExpectations = postProcessProtoExpectations( | 1265 protoExpectations = postProcessProtoExpectations( |
| 1258 modelHelper, protoExpectations); | 1266 modelHelper, protoExpectations); |
| 1259 checkAllInputEventsHandled(sortedInputEvents, protoExpectations); | 1267 checkAllInputEventsHandled(sortedInputEvents, protoExpectations); |
| 1260 | 1268 |
| 1261 var expectations = []; | 1269 var expectations = []; |
| 1262 protoExpectations.forEach(function(protoExpectation) { | 1270 protoExpectations.forEach(function(protoExpectation) { |
| 1263 var ir = protoExpectation.createInteractionRecord(modelHelper.model); | 1271 var ir = protoExpectation.createInteractionRecord(modelHelper.model); |
| 1264 if (ir) | 1272 if (ir) { |
| 1265 expectations.push(ir); | 1273 expectations.push(ir); |
| 1274 } |
| 1266 }); | 1275 }); |
| 1267 return expectations; | 1276 return expectations; |
| 1268 } | 1277 } |
| 1269 | 1278 |
| 1270 return { | 1279 return { |
| 1271 findInputExpectations, | 1280 findInputExpectations, |
| 1272 compareEvents, | 1281 compareEvents, |
| 1273 CSS_ANIMATION_TITLE, | 1282 CSS_ANIMATION_TITLE, |
| 1274 INITIATOR_TYPE, | 1283 INITIATOR_TYPE, |
| 1275 }; | 1284 }; |
| 1276 }); | 1285 }); |
| 1277 </script> | 1286 </script> |
| OLD | NEW |