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 Talvala#define LOG_TAG "Camera2-Legacy-PerfMeasurement-JNI"
18e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <utils/Log.h>
19e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <utils/Errors.h>
20e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <utils/Trace.h>
21e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <utils/Vector.h>
22e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
23e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include "jni.h"
24e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include "JNIHelp.h"
25e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include "android_runtime/AndroidRuntime.h"
26e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
27e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <ui/GraphicBuffer.h>
28e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <system/window.h>
29e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <GLES2/gl2.h>
30e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#include <GLES2/gl2ext.h>
31e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
32e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalausing namespace android;
33e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
34e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala// fully-qualified class name
35e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala#define PERF_MEASUREMENT_CLASS_NAME "android/hardware/camera2/legacy/PerfMeasurement"
36e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
37e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala/** GL utility methods copied from com_google_android_gles_jni_GLImpl.cpp */
38e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
39e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala// Check if the extension at the head of pExtensions is pExtension. Note that pExtensions is
40e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala// terminated by either 0 or space, while pExtension is terminated by 0.
41e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
42e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic bool
43e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville TalvalaextensionEqual(const GLubyte* pExtensions, const GLubyte* pExtension) {
44e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    while (true) {
45e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        char a = *pExtensions++;
46e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        char b = *pExtension++;
47e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        bool aEnd = a == '\0' || a == ' ';
48e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        bool bEnd = b == '\0';
49e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (aEnd || bEnd) {
50e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return aEnd == bEnd;
51e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
52e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (a != b) {
53e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return false;
54e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
55e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
56e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
57e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
58e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic const GLubyte*
59e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville TalvalanextExtension(const GLubyte* pExtensions) {
60e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    while (true) {
61e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        char a = *pExtensions++;
62e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (a == '\0') {
63e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return pExtensions-1;
64e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        } else if ( a == ' ') {
65e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return pExtensions;
66e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
67e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
68e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
69e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
70e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic bool
71e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville TalvalacheckForExtension(const GLubyte* pExtensions, const GLubyte* pExtension) {
72e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    for (; *pExtensions != '\0'; pExtensions = nextExtension(pExtensions)) {
73e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (extensionEqual(pExtensions, pExtension)) {
74e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return true;
75e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
76e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
77e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return false;
78e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
79e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
80e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala/** End copied GL utility methods */
81e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
82e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalabool checkGlError(JNIEnv* env) {
83e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    int error;
84e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    if ((error = glGetError()) != GL_NO_ERROR) {
85e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
86e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                "GLES20 error: 0x%d", error);
87e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return true;
88e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
89e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return false;
90e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
91e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
92e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala/**
93e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * Asynchronous low-overhead GL performance measurement using
94e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * http://www.khronos.org/registry/gles/extensions/EXT/EXT_disjoint_timer_query.txt
95e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
96e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * Measures the duration of GPU processing for a set of GL commands, delivering
97e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * the measurement asynchronously once processing completes.
98e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala *
99e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala * All calls must come from a single thread with a valid GL context active.
100e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala **/
101e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaclass PerfMeasurementContext {
102e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala  private:
103e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    Vector<GLuint> mTimingQueries;
104e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    size_t mTimingStartIndex;
105e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    size_t mTimingEndIndex;
106e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    size_t mTimingQueryIndex;
107e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    size_t mFreeQueries;
108e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
109e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    bool mInitDone;
110e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala  public:
111e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
112e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
113e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * maxQueryCount should be a conservative estimate of how many query objects
114e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * will be active at once, which is a function of the GPU's level of
115e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * pipelining and the frequency of queries.
116e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
117e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext(size_t maxQueryCount):
118e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mTimingStartIndex(0),
119e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mTimingEndIndex(0),
120e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mTimingQueryIndex(0) {
121e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mTimingQueries.resize(maxQueryCount);
122e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mFreeQueries = maxQueryCount;
123e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mInitDone = false;
124e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
125e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
126e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    int getMaxQueryCount() {
127e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return mTimingQueries.size();
128e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
129e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
130e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
131e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Start a measurement period using the next available query object.
132e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Returns INVALID_OPERATION if called multiple times in a row,
133e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * and BAD_VALUE if no more query objects are available.
134e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
135e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    int startGlTimer() {
136e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        // Lazy init of queries to avoid needing GL context during construction
137e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (!mInitDone) {
138e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            glGenQueriesEXT(mTimingQueries.size(), mTimingQueries.editArray());
139e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            mInitDone = true;
140e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
141e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
142e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (mTimingEndIndex != mTimingStartIndex) {
143e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return INVALID_OPERATION;
144e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
145e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
146e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (mFreeQueries == 0) {
147e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return BAD_VALUE;
148e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
149e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
150e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        glBeginQueryEXT(GL_TIME_ELAPSED_EXT, mTimingQueries[mTimingStartIndex]);
151e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
152e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mTimingStartIndex = (mTimingStartIndex + 1) % mTimingQueries.size();
153e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mFreeQueries--;
154e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
155e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return OK;
156e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
157e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
158e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
159e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Finish the current measurement period
160e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Returns INVALID_OPERATION if called before any startGLTimer calls
161e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * or if called multiple times in a row.
162e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
163e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    int stopGlTimer() {
164e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        size_t nextEndIndex = (mTimingEndIndex + 1) % mTimingQueries.size();
165e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (nextEndIndex != mTimingStartIndex) {
166e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return INVALID_OPERATION;
167e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
168e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        glEndQueryEXT(GL_TIME_ELAPSED_EXT);
169e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
170e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mTimingEndIndex = nextEndIndex;
171e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
172e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return OK;
173e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
174e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
175e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    static const nsecs_t NO_DURATION_YET = -1L;
176e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    static const nsecs_t FAILED_MEASUREMENT = -2L;
177e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
178e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    /**
179e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Get the next available duration measurement.
180e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
181e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Returns NO_DURATION_YET if no new measurement is available,
182e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * and FAILED_MEASUREMENT if an error occurred during the next
183e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * measurement period.
184e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     *
185e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * Otherwise returns a positive number of nanoseconds measuring the
186e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     * duration of the oldest completed query.
187e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala     */
188e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    nsecs_t getNextGlDuration() {
189e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (!mInitDone) {
190e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            // No start/stop called yet
191e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return NO_DURATION_YET;
192e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
193e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
194e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        GLint available;
195e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        glGetQueryObjectivEXT(mTimingQueries[mTimingQueryIndex],
196e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                GL_QUERY_RESULT_AVAILABLE_EXT, &available);
197e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (!available) {
198e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            return NO_DURATION_YET;
199e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
200e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
201e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        GLint64 duration = FAILED_MEASUREMENT;
202e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        GLint disjointOccurred;
203e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjointOccurred);
204e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
205e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        if (!disjointOccurred) {
206e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            glGetQueryObjecti64vEXT(mTimingQueries[mTimingQueryIndex],
207e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                    GL_QUERY_RESULT_EXT,
208e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                    &duration);
209e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
210e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
211e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mTimingQueryIndex = (mTimingQueryIndex + 1) % mTimingQueries.size();
212e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        mFreeQueries++;
213e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
214e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return static_cast<nsecs_t>(duration);
215e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
216e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
217e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    static bool isMeasurementSupported() {
218e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        const GLubyte* extensions = glGetString(GL_EXTENSIONS);
219e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        return checkForExtension(extensions,
220e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                reinterpret_cast<const GLubyte*>("GL_EXT_disjoint_timer_query"));
221e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
222e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
223e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala};
224e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
225e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville TalvalaPerfMeasurementContext* getContext(jlong context) {
226e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return reinterpret_cast<PerfMeasurementContext*>(context);
227e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
228e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
229e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaextern "C" {
230e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
231e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic jlong PerfMeasurement_nativeCreateContext(JNIEnv* env, jobject thiz,
232e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        jint maxQueryCount) {
233e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext *context = new PerfMeasurementContext(maxQueryCount);
234e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return reinterpret_cast<jlong>(context);
235e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
236e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
237e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic void PerfMeasurement_nativeDeleteContext(JNIEnv* env, jobject thiz,
238e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        jlong contextHandle) {
239e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext *context = getContext(contextHandle);
240e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    delete(context);
241e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
242e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
243e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic jboolean PerfMeasurement_nativeQuerySupport(JNIEnv* env, jobject thiz) {
244e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    bool supported = PerfMeasurementContext::isMeasurementSupported();
245e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    checkGlError(env);
246e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return static_cast<jboolean>(supported);
247e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
248e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
249e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic void PerfMeasurement_nativeStartGlTimer(JNIEnv* env, jobject thiz,
250e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        jlong contextHandle) {
251e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
252e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext *context = getContext(contextHandle);
253e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    status_t err = context->startGlTimer();
254e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    if (err != OK) {
255e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        switch (err) {
256e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            case INVALID_OPERATION:
257e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
258e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        "Mismatched start/end GL timing calls");
259e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                return;
260e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            case BAD_VALUE:
261e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
262e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        "Too many timing queries in progress, max %d",
263e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        context->getMaxQueryCount());
264e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                return;
265e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            default:
266e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
267e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        "Unknown error starting GL timing");
268e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                return;
269e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
270e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
271e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    checkGlError(env);
272e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
273e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
274e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic void PerfMeasurement_nativeStopGlTimer(JNIEnv* env, jobject thiz,
275e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            jlong contextHandle) {
276e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
277e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext *context = getContext(contextHandle);
278e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    status_t err = context->stopGlTimer();
279e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    if (err != OK) {
280e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        switch (err) {
281e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            case INVALID_OPERATION:
282e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
283e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        "Mismatched start/end GL timing calls");
284e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                return;
285e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            default:
286e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                jniThrowExceptionFmt(env, "java/lang/IllegalStateException",
287e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                        "Unknown error ending GL timing");
288e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala                return;
289e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        }
290e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    }
291e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    checkGlError(env);
292e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
293e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
294e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic jlong PerfMeasurement_nativeGetNextGlDuration(JNIEnv* env,
295e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala        jobject thiz, jlong contextHandle) {
296e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    PerfMeasurementContext *context = getContext(contextHandle);
297e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    nsecs_t duration = context->getNextGlDuration();
298e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
299e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    checkGlError(env);
300e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return static_cast<jlong>(duration);
301e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
302e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
303e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala} // extern "C"
304e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
305e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalastatic JNINativeMethod gPerfMeasurementMethods[] = {
306e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeCreateContext",
307e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "(I)J",
308e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (jlong *)PerfMeasurement_nativeCreateContext },
309e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeDeleteContext",
310e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "(J)V",
311e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (void *)PerfMeasurement_nativeDeleteContext },
312e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeQuerySupport",
313e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "()Z",
314e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (jboolean *)PerfMeasurement_nativeQuerySupport },
315e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeStartGlTimer",
316e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "(J)V",
317e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (void *)PerfMeasurement_nativeStartGlTimer },
318e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeStopGlTimer",
319e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "(J)V",
320e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (void *)PerfMeasurement_nativeStopGlTimer },
321e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    { "nativeGetNextGlDuration",
322e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      "(J)J",
323e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala      (jlong *)PerfMeasurement_nativeGetNextGlDuration }
324e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala};
325e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
326e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala
327e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala// Get all the required offsets in java class and register native functions
328e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvalaint register_android_hardware_camera2_legacy_PerfMeasurement(JNIEnv* env)
329e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala{
330e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    // Register native functions
331e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala    return AndroidRuntime::registerNativeMethods(env,
332e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            PERF_MEASUREMENT_CLASS_NAME,
333e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            gPerfMeasurementMethods,
334e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala            NELEM(gPerfMeasurementMethods));
335e1f57d6f44909a66c7ab0af33dbc5289287e823aEino-Ville Talvala}
336