17f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy/*
27f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * Copyright (C) 2013 The Android Open Source Project
37f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *
47f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * Licensed under the Apache License, Version 2.0 (the "License");
57f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * you may not use this file except in compliance with the License.
67f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * You may obtain a copy of the License at
77f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *
87f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *      http://www.apache.org/licenses/LICENSE-2.0
97f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *
107f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * Unless required by applicable law or agreed to in writing, software
117f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * distributed under the License is distributed on an "AS IS" BASIS,
127f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * See the License for the specific language governing permissions and
147f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * limitations under the License.
157f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy */
167f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
177f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy#ifndef ANDROID_HWUI_QUERY_H
187f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy#define ANDROID_HWUI_QUERY_H
197f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
207f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy#include <GLES3/gl3.h>
217f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
227f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy#include "Extensions.h"
237f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
247f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guynamespace android {
257f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guynamespace uirenderer {
267f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
277f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy/**
287f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * A Query instance can be used to perform occlusion queries. If the device
297f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * does not support occlusion queries, the result of a query will always be
307f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * 0 and the result will always be marked available.
317f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *
327f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * To run an occlusion query successfully, you must start end end the query:
337f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy *
347f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * Query query;
357f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * query.begin();
367f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * // execute OpenGL calls
377f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * query.end();
387f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy * GLuint result = query.getResult();
397f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy */
407f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guyclass Query {
417f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guypublic:
427f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
437f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Possible query targets.
447f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
457f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    enum Target {
467f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        /**
477f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         * Indicates if any sample passed the depth & stencil tests.
487f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         */
497f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        kTargetSamples = GL_ANY_SAMPLES_PASSED,
507f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        /**
517f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         * Indicates if any sample passed the depth & stencil tests.
527f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         * The implementation may choose to use a less precise version
537f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         * of the test, potentially resulting in false positives.
547f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy         */
557f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        kTargetConservativeSamples = GL_ANY_SAMPLES_PASSED_CONSERVATIVE,
567f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    };
577f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
587f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
597f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Creates a new query with the specified target. The default
607f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * target is kTargetSamples (of GL_ANY_SAMPLES_PASSED in OpenGL.)
617f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
627f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    Query(Target target = kTargetSamples): mActive(false), mTarget(target),
637f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            mCanQuery(Extensions::getInstance().hasOcclusionQueries()),
647f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            mQuery(0) {
657f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
667f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
677f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    ~Query() {
687f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        if (mQuery) {
697f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            glDeleteQueries(1, &mQuery);
707f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        }
717f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
727f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
737f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
747f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Begins the query. If the query has already begun or if the device
757f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * does not support occlusion queries, calling this method as no effect.
767f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * After calling this method successfully, the query is marked active.
777f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
787f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    void begin() {
797f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        if (!mActive && mCanQuery) {
807f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            if (!mQuery) {
817f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy                glGenQueries(1, &mQuery);
827f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            }
837f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
847f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            glBeginQuery(mTarget, mQuery);
857f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            mActive = true;
867f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        }
877f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
887f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
897f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
907f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Ends the query. If the query has already begun or if the device
917f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * does not support occlusion queries, calling this method as no effect.
927f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * After calling this method successfully, the query is marked inactive.
937f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
947f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    void end() {
957f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        if (mQuery && mActive) {
967f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            glEndQuery(mTarget);
977f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy            mActive = false;
987f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        }
997f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
1007f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1017f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
1027f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Returns true if the query is active, false otherwise.
1037f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
1047f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    bool isActive() {
1057f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        return mActive;
1067f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
1077f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1087f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
1097f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Returns true if the result of the query is available,
1107f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * false otherwise. Calling getResult() before the result
1117f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * is available may result in the calling thread being blocked.
1127f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * If the device does not support queries, this method always
1137f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * returns true.
1147f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
1157f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    bool isResultAvailable() {
1167f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        if (!mQuery) return true;
1177f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1187f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        GLuint result;
1197f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        glGetQueryObjectuiv(mQuery, GL_QUERY_RESULT_AVAILABLE, &result);
1207f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        return result == GL_TRUE;
1217f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
1227f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1237f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    /**
1247f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Returns the result of the query. If the device does not
1257f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * support queries this method will return 0.
1267f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     *
1277f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * Calling this method implicitely calls end() if the query
1287f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     * is currently active.
1297f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy     */
1307f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    GLuint getResult() {
1317f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        if (!mQuery) return 0;
1327f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1337f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        end();
1347f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1357f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        GLuint result;
1367f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        glGetQueryObjectuiv(mQuery, GL_QUERY_RESULT, &result);
1377f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy        return result;
1387f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    }
1397f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1407f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1417f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guyprivate:
1427f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    bool mActive;
1437f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    GLenum mTarget;
1447f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    bool mCanQuery;
1457f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy    GLuint mQuery;
1467f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1477f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy}; // class Query
1487f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1497f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy}; // namespace uirenderer
1507f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy}; // namespace android
1517f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy
1527f4307668b10467ee39d41c7ea29cf1ff238a835Romain Guy#endif // ANDROID_HWUI_QUERY_H
153