blob: a5310569da4535cf35ea28093bd911beeb186891 [file] [log] [blame]
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.tools.idea.monitor.gpu;
import com.android.ddmlib.Client;
import com.android.ddmlib.IDevice;
import com.android.tools.chartlib.EventData;
import com.android.tools.chartlib.TimelineComponent;
import com.android.tools.chartlib.TimelineData;
import com.android.tools.idea.ddms.DeviceContext;
import com.android.tools.idea.monitor.BaseMonitorView;
import com.android.tools.idea.monitor.DeviceSampler;
import com.android.tools.idea.monitor.TimelineEventListener;
import com.intellij.openapi.actionSystem.ActionGroup;
import com.intellij.openapi.actionSystem.DefaultActionGroup;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComponentWithActions;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
public class GpuMonitorView extends BaseMonitorView implements TimelineEventListener, DeviceContext.DeviceSelectionListener {
public static int DEFAULT_API_LEVEL = 22;
public static int DETAILED_API_LEVEL = 23;
public static final int PRE_M_SAMPLES = 2048;
public static final int POST_M_SAMPLES = 8192;
public static final int PRE_M_SAMPLE_FREQUENCY_MS = 33;
public static final int POST_M_SAMPLE_FREQUENCY_MS = 200;
private static final Color BACKGROUND_COLOR = UIUtil.getTextFieldBackground();
private int myApiLevel = DEFAULT_API_LEVEL;
@NotNull private final GpuSampler myGpuSampler;
public GpuMonitorView(@NotNull Project project, @NotNull DeviceContext deviceContext) {
super(project);
myApiLevel = getApiLevel(deviceContext.getSelectedClient());
TimelineData data = createTimelineData();
configureTimelineComponent(data);
myGpuSampler = new GpuSampler(data, PRE_M_SAMPLE_FREQUENCY_MS, myApiLevel);
myGpuSampler.addListener(this);
deviceContext.addListener(this, project);
}
@NotNull
public ActionGroup getToolbarActions() {
return new DefaultActionGroup();
}
@NotNull
public ComponentWithActions createComponent() {
return new ComponentWithActions.Impl(getToolbarActions(), null, null, null, myContentPane);
}
@Override
public void deviceSelected(@Nullable IDevice device) {
}
@Override
public void deviceChanged(@NotNull IDevice device, int changeMask) {
}
@Override
public void clientSelected(@Nullable Client c) {
int newApiLevel = getApiLevel(c);
if (newApiLevel != myApiLevel) {
myGpuSampler.stop();
myApiLevel = newApiLevel;
TimelineData data = createTimelineData();
configureTimelineComponent(data);
myGpuSampler.resetClientState(c, data, myApiLevel);
}
else {
myGpuSampler.setClient(c);
}
}
@Override
public void onStart() {
}
@Override
public void onStop() {
}
@Override
protected DeviceSampler getSampler() {
return myGpuSampler;
}
private int getApiLevel(@Nullable Client client) {
if (client != null) {
String apiString = client.getDevice().getProperty("ro.build.version.sdk");
if (apiString == null) {
return DEFAULT_API_LEVEL;
}
else {
try {
// TODO remove this version promotion workaround after M launches
int apiLevel = Integer.parseInt(apiString);
if (apiLevel == 22) {
String versionString = client.getDevice().getProperty("ro.build.version.release");
if (versionString == null) {
return 22;
}
return "M".equals(versionString) ? DETAILED_API_LEVEL : 22;
}
return apiLevel;
}
catch (NumberFormatException e) {
return DEFAULT_API_LEVEL;
}
}
}
return myApiLevel;
}
@NotNull
private TimelineData createTimelineData() {
if (myApiLevel >= DETAILED_API_LEVEL) {
return new TimelineData(9, POST_M_SAMPLES);
}
else {
return new TimelineData(4, PRE_M_SAMPLES);
}
}
private void configureTimelineComponent(@NotNull TimelineData data) {
TimelineComponent timelineComponent;
EventData events = new EventData();
if (myApiLevel >= DETAILED_API_LEVEL) {
// Buffer at one and a half times the sample frequency.
float bufferTimeInSeconds = POST_M_SAMPLE_FREQUENCY_MS * 1.5f / 1000.f;
timelineComponent = new TimelineComponent(data, events, bufferTimeInSeconds, 17.0f, 67.0f, 3.0f);
timelineComponent.configureUnits("ms");
timelineComponent.configureStream(0, "VSync Delay", new JBColor(0x007c6d, 0x00695c));
timelineComponent.configureStream(1, "Input Handling", new JBColor(0x00a292, 0x00897b));
timelineComponent.configureStream(2, "Animation", new JBColor(0x00b2a1, 0x009688));
timelineComponent.configureStream(3, "Measure/Layout", new JBColor(0x2dc5b6, 0x26a69a));
timelineComponent.configureStream(4, "Draw", new JBColor(0x27b2ff, 0x2196f3));
timelineComponent.configureStream(5, "Sync", new JBColor(0x5de7ff, 0x4fc3f7));
timelineComponent.configureStream(6, "Command Issue", new JBColor(0xff4f40, 0xf44336));
timelineComponent.configureStream(7, "Swap Buffers", new JBColor(0xffb400, 0xff9800));
timelineComponent.configureStream(8, "Misc Time", new JBColor(0x008f7f, 0x00796b));
timelineComponent.setBackground(BACKGROUND_COLOR);
}
else {
// Buffer at one and a half times the sample frequency.
float bufferTimeInSeconds = PRE_M_SAMPLE_FREQUENCY_MS * 1.5f / 1000.f;
timelineComponent = new TimelineComponent(data, events, bufferTimeInSeconds, 17.0f, 100.0f, 3.0f);
timelineComponent.configureUnits("ms");
timelineComponent.configureStream(0, "Draw", new JBColor(0x4979f2, 0x3e66cc));
timelineComponent.configureStream(1, "Prepare", new JBColor(0xa900ff, 0x8f00ff));
timelineComponent.configureStream(2, "Process", new JBColor(0xff4315, 0xdc3912));
timelineComponent.configureStream(3, "Execute", new JBColor(0xffb400, 0xe69800));
timelineComponent.setBackground(BACKGROUND_COLOR);
}
setComponent(timelineComponent);
}
}