1e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala/*
2e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * Copyright (C) 2014 The Android Open Source Project
3e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
4e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * Licensed under the Apache License, Version 2.0 (the "License");
5e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * you may not use this file except in compliance with the License.
6e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * You may obtain a copy of the License at
7e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
8e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *      http://www.apache.org/licenses/LICENSE-2.0
9e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
10e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * Unless required by applicable law or agreed to in writing, software
11e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * distributed under the License is distributed on an "AS IS" BASIS,
12e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * See the License for the specific language governing permissions and
14e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * limitations under the License.
15e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala */
16e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
17e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalapackage android.hardware.camera2.legacy;
18e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
19e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport android.os.SystemClock;
20e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport android.util.Log;
21e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
22e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.io.BufferedWriter;
23e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.io.FileWriter;
24e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.io.IOException;
25e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.util.ArrayList;
26e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.util.LinkedList;
27e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaimport java.util.Queue;
28e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
29e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala/**
30e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * GPU and CPU performance measurement for the legacy implementation.
31e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
32e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * <p>Measures CPU and GPU processing duration for a set of operations, and dumps
33e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * the results into a file.</p>
34e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
35e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * <p>Rough usage:
36e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * <pre>
37e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * {@code
38e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   <set up workload>
39e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   <start long-running workload>
40e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   mPerfMeasurement.startTimer();
41e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   ...render a frame...
42e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   mPerfMeasurement.stopTimer();
43e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   <end workload>
44e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *   mPerfMeasurement.dumpPerformanceData("/sdcard/my_data.txt");
45e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * }
46e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * </pre>
47e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * </p>
48e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
49e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * <p>All calls to this object must be made within the same thread, and the same GL context.
50e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * PerfMeasurement cannot be used outside of a GL context.  The only exception is
51e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * dumpPerformanceData, which can be called outside of a valid GL context.</p>
52e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala */
53e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaclass PerfMeasurement {
54e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static final String TAG = "PerfMeasurement";
55e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
56e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public static final int DEFAULT_MAX_QUERIES = 3;
57e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
58e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private final long mNativeContext;
59e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
60e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private int mCompletedQueryCount = 0;
61e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
62e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
63e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Values for completed measurements
64e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
65e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private ArrayList<Long> mCollectedGpuDurations = new ArrayList<>();
66e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private ArrayList<Long> mCollectedCpuDurations = new ArrayList<>();
67e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private ArrayList<Long> mCollectedTimestamps = new ArrayList<>();
68e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
69e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
70e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Values for in-progress measurements (waiting for async GPU results)
71e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
72e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private Queue<Long> mTimestampQueue = new LinkedList<>();
73e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private Queue<Long> mCpuDurationsQueue = new LinkedList<>();
74e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
75e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private long mStartTimeNs;
76e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
77e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
78e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * The value returned by {@link #nativeGetNextGlDuration} if no new timing
79e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * measurement is available since the last call.
80e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
81e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static final long NO_DURATION_YET = -1l;
82e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
83e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
84e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * The value returned by {@link #nativeGetNextGlDuration} if timing failed for
85e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * the next timing interval
86e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
87e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static final long FAILED_TIMING = -2l;
88e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
89e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
90e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Create a performance measurement object with a maximum of {@value #DEFAULT_MAX_QUERIES}
91e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * in-progess queries.
92e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
93e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public PerfMeasurement() {
94e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mNativeContext = nativeCreateContext(DEFAULT_MAX_QUERIES);
95e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
96e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
97e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
98e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Create a performance measurement object with maxQueries as the maximum number of
99e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * in-progress queries.
100e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
101e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @param maxQueries maximum in-progress queries, must be larger than 0.
102e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalArgumentException if maxQueries is less than 1.
103e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
104e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public PerfMeasurement(int maxQueries) {
105e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (maxQueries < 1) throw new IllegalArgumentException("maxQueries is less than 1");
106e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mNativeContext = nativeCreateContext(maxQueries);
107e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
108e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
109e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
110e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Returns true if the Gl timing methods will work, false otherwise.
111e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
112e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Must be called within a valid GL context.</p>
113e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
114e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public static boolean isGlTimingSupported() {
115e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return nativeQuerySupport();
116e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
117e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
118e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
119e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Dump collected data to file, and clear the stored data.
120e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
121e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>
122e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Format is a simple csv-like text file with a header,
123e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * followed by a 3-column list of values in nanoseconds:
124e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <pre>
125e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *   timestamp gpu_duration cpu_duration
126e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *   <long> <long> <long>
127e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *   <long> <long> <long>
128e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *   <long> <long> <long>
129e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *   ....
130e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * </pre>
131e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * </p>
132e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
133e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public void dumpPerformanceData(String path) {
134e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        try (BufferedWriter dump = new BufferedWriter(new FileWriter(path))) {
135e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            dump.write("timestamp gpu_duration cpu_duration\n");
136e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            for (int i = 0; i < mCollectedGpuDurations.size(); i++) {
137e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                dump.write(String.format("%d %d %d\n",
138e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                                mCollectedTimestamps.get(i),
139e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                                mCollectedGpuDurations.get(i),
140e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                                mCollectedCpuDurations.get(i)));
141e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            }
142e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedTimestamps.clear();
143e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedGpuDurations.clear();
144e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedCpuDurations.clear();
145e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        } catch (IOException e) {
146e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            Log.e(TAG, "Error writing data dump to " + path + ":" + e);
147e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
148e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
149e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
150e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
151e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Start a GPU/CPU timing measurement.
152e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
153e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Call before starting a rendering pass. Only one timing measurement can be active at once,
154e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * so {@link #stopTimer} must be called before the next call to this method.</p>
155e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
156e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException if the maximum number of queries are in progress already,
157e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *                               or the method is called multiple times in a row, or there is
158e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *                               a GPU error.
159e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
160e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public void startTimer() {
161e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        nativeStartGlTimer(mNativeContext);
162e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mStartTimeNs = SystemClock.elapsedRealtimeNanos();
163e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
164e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
165e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
166e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Finish a GPU/CPU timing measurement.
167e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
168e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Call after finishing all the drawing for a rendering pass. Only one timing measurement can
169e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * be active at once, so {@link #startTimer} must be called before the next call to this
170e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * method.</p>
171e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
172e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException if no GL timer is currently started, or there is a GPU
173e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *                               error.
174e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
175e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public void stopTimer() {
176e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        // Complete CPU timing
177e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        long endTimeNs = SystemClock.elapsedRealtimeNanos();
178e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mCpuDurationsQueue.add(endTimeNs - mStartTimeNs);
179e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        // Complete GL timing
180e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        nativeStopGlTimer(mNativeContext);
181e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
182e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        // Poll to see if GL timing results have arrived; if so
183e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        // store the results for a frame
184e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        long duration = getNextGlDuration();
185e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (duration > 0) {
186e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedGpuDurations.add(duration);
187e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedTimestamps.add(mTimestampQueue.isEmpty() ?
188e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                    NO_DURATION_YET : mTimestampQueue.poll());
189e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCollectedCpuDurations.add(mCpuDurationsQueue.isEmpty() ?
190e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                    NO_DURATION_YET : mCpuDurationsQueue.poll());
191e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
192e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (duration == FAILED_TIMING) {
193e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            // Discard timestamp and CPU measurement since GPU measurement failed
194e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            if (!mTimestampQueue.isEmpty()) {
195e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                mTimestampQueue.poll();
196e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            }
197e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            if (!mCpuDurationsQueue.isEmpty()) {
198e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                mCpuDurationsQueue.poll();
199e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            }
200e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
201e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
202e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
203e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
204e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Add a timestamp to a timing measurement. These are queued up and matched to completed
205e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * workload measurements as they become available.
206e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
207e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public void addTimestamp(long timestamp) {
208e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mTimestampQueue.add(timestamp);
209e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
210e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
211e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
212e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Get the next available GPU timing measurement.
213e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
214e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Since the GPU works asynchronously, the results of a single start/stopGlTimer measurement
215e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * will only be available some time after the {@link #stopTimer} call is made. Poll this method
216e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * until the result becomes available. If multiple start/endTimer measurements are made in a
217e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * row, the results will be available in FIFO order.</p>
218e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
219e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @return The measured duration of the GPU workload for the next pending query, or
220e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *         {@link #NO_DURATION_YET} if no queries are pending or the next pending query has not
221e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *         yet finished, or {@link #FAILED_TIMING} if the GPU was unable to complete the
222e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *         measurement.
223e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
224e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException If there is a GPU error.
225e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
226e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
227e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private long getNextGlDuration() {
228e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        long duration = nativeGetNextGlDuration(mNativeContext);
229e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (duration > 0) {
230e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mCompletedQueryCount++;
231e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
232e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return duration;
233e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
234e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
235e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
236e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Returns the number of measurements so far that returned a valid duration
237e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * measurement.
238e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
239e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    public int getCompletedQueryCount() {
240e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return mCompletedQueryCount;
241e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
242e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
243e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    @Override
244e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    protected void finalize() {
245e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        nativeDeleteContext(mNativeContext);
246e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
247e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
248e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
249e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Create a native performance measurement context.
250e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
251e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @param maxQueryCount maximum in-progress queries; must be >= 1.
252e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
253e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static native long nativeCreateContext(int maxQueryCount);
254e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
255e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
256e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Delete the native context.
257e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
258e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Not safe to call more than once.</p>
259e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
260e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static native void nativeDeleteContext(long contextHandle);
261e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
262e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
263e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Query whether the relevant Gl extensions are available for Gl timing
264e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
265e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    private static native boolean nativeQuerySupport();
266e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
267e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
268e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Start a GL timing section.
269e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
270e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>All GL commands between this method and the next {@link #nativeEndGlTimer} will be
271e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * included in the timing.</p>
272e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
273e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Must be called from the same thread as calls to {@link #nativeEndGlTimer} and
274e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * {@link #nativeGetNextGlDuration}.</p>
275e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
276e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException if a GL error occurs or start is called repeatedly.
277e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
278e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    protected static native void nativeStartGlTimer(long contextHandle);
279e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
280e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
281e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Finish a GL timing section.
282e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
283e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Some time after this call returns, the time the GPU took to
284e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * execute all work submitted between the latest {@link #nativeStartGlTimer} and
285e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * this call, will become available from calling {@link #nativeGetNextGlDuration}.</p>
286e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
287e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Must be called from the same thread as calls to {@link #nativeStartGlTimer} and
288e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * {@link #nativeGetNextGlDuration}.</p>
289e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
290e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException if a GL error occurs or stop is called before start
291e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
292e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    protected static native void nativeStopGlTimer(long contextHandle);
293e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
294e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
295e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Get the next available GL duration measurement, in nanoseconds.
296e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
297e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * <p>Must be called from the same thread as calls to {@link #nativeStartGlTimer} and
298e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * {@link #nativeEndGlTimer}.</p>
299e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
300e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @return the next GL duration measurement, or {@link #NO_DURATION_YET} if
301e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *         no new measurement is available, or {@link #FAILED_TIMING} if timing
302e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *         failed for the next duration measurement.
303e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * @throws IllegalStateException if a GL error occurs
304e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
305e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    protected static native long nativeGetNextGlDuration(long contextHandle);
306e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
307e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
308e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
309