1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "BenchGpuTimer_gl.h"
9#include "gl/SkGLContextHelper.h"
10#include "gl/GrGLUtil.h"
11
12BenchGpuTimer::BenchGpuTimer(const SkGLContextHelper* glctx) {
13    fContext = glctx;
14    glctx->ref();
15    glctx->makeCurrent();
16    fStarted = false;
17    fSupported = GrGLGetVersion(glctx->gl()) > GR_GL_VER(3,3) ||
18                 glctx->hasExtension("GL_ARB_timer_query") ||
19                 glctx->hasExtension("GL_EXT_timer_query");
20
21    if (fSupported) {
22        SK_GL(*glctx, GenQueries(1, &fQuery));
23    }
24}
25
26BenchGpuTimer::~BenchGpuTimer() {
27    if (fSupported) {
28        fContext->makeCurrent();
29        SK_GL(*fContext, DeleteQueries(1, &fQuery));
30    }
31    fContext->unref();
32}
33
34void BenchGpuTimer::startGpu() {
35    if (fSupported) {
36        fContext->makeCurrent();
37        fStarted = true;
38        SK_GL(*fContext, BeginQuery(GR_GL_TIME_ELAPSED, fQuery));
39    }
40}
41
42/**
43 * It is important to stop the cpu clocks first,
44 * as this will cpu wait for the gpu to finish.
45 */
46double BenchGpuTimer::endGpu() {
47    if (fSupported) {
48        fStarted = false;
49        fContext->makeCurrent();
50        SK_GL(*fContext, EndQuery(GR_GL_TIME_ELAPSED));
51
52        GrGLint available = 0;
53        while (!available) {
54            SK_GL_NOERRCHECK(*fContext, GetQueryObjectiv(fQuery,
55                                             GR_GL_QUERY_RESULT_AVAILABLE,
56                                             &available));
57            // If GetQueryObjectiv is erroring out we need some alternative
58            // means of breaking out of this loop
59            GrGLenum error;
60            SK_GL_RET_NOERRCHECK(*fContext, error, GetError());
61            if (GR_GL_NO_ERROR != error) {
62                break;
63            }
64        }
65        GrGLuint64 totalGPUTimeElapsed = 0;
66        SK_GL(*fContext, GetQueryObjectui64v(fQuery,
67                                             GR_GL_QUERY_RESULT,
68                                             &totalGPUTimeElapsed));
69
70        return totalGPUTimeElapsed / 1000000.0;
71    } else {
72        return 0;
73    }
74}
75