1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2013 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "tools/gpu/gl/GLTestContext.h" 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include "include/gpu/GrDirectContext.h" 11cb93a386Sopenharmony_ci#include "src/gpu/gl/GrGLUtil.h" 12cb93a386Sopenharmony_ci#include "tools/gpu/GpuTimer.h" 13cb93a386Sopenharmony_ci 14cb93a386Sopenharmony_cinamespace { 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ciclass GLGpuTimer : public sk_gpu_test::GpuTimer { 17cb93a386Sopenharmony_cipublic: 18cb93a386Sopenharmony_ci static std::unique_ptr<GLGpuTimer> MakeIfSupported(const sk_gpu_test::GLTestContext*); 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ci QueryStatus checkQueryStatus(sk_gpu_test::PlatformTimerQuery) override; 21cb93a386Sopenharmony_ci std::chrono::nanoseconds getTimeElapsed(sk_gpu_test::PlatformTimerQuery) override; 22cb93a386Sopenharmony_ci void deleteQuery(sk_gpu_test::PlatformTimerQuery) override; 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_ciprivate: 25cb93a386Sopenharmony_ci#ifdef SK_GL 26cb93a386Sopenharmony_ci GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext*, const char* ext = ""); 27cb93a386Sopenharmony_ci bool validate() const; 28cb93a386Sopenharmony_ci#endif 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_ci sk_gpu_test::PlatformTimerQuery onQueueTimerStart() const override; 31cb93a386Sopenharmony_ci void onQueueTimerStop(sk_gpu_test::PlatformTimerQuery) const override; 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci inline static constexpr GrGLenum GL_QUERY_RESULT = 0x8866; 34cb93a386Sopenharmony_ci inline static constexpr GrGLenum GL_QUERY_RESULT_AVAILABLE = 0x8867; 35cb93a386Sopenharmony_ci inline static constexpr GrGLenum GL_TIME_ELAPSED = 0x88bf; 36cb93a386Sopenharmony_ci inline static constexpr GrGLenum GL_GPU_DISJOINT = 0x8fbb; 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLGetIntegervProc) (GrGLenum, GrGLint*); 39cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLGenQueriesProc) (GrGLsizei, GrGLuint*); 40cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLDeleteQueriesProc) (GrGLsizei, const GrGLuint*); 41cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLBeginQueryProc) (GrGLenum, GrGLuint); 42cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLEndQueryProc) (GrGLenum); 43cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectuivProc) (GrGLuint, GrGLenum, GrGLuint*); 44cb93a386Sopenharmony_ci typedef void (GR_GL_FUNCTION_TYPE* GLGetQueryObjectui64vProc) (GrGLuint, GrGLenum, GrGLuint64*); 45cb93a386Sopenharmony_ci 46cb93a386Sopenharmony_ci GLGetIntegervProc fGLGetIntegerv; 47cb93a386Sopenharmony_ci GLGenQueriesProc fGLGenQueries; 48cb93a386Sopenharmony_ci GLDeleteQueriesProc fGLDeleteQueries; 49cb93a386Sopenharmony_ci GLBeginQueryProc fGLBeginQuery; 50cb93a386Sopenharmony_ci GLEndQueryProc fGLEndQuery; 51cb93a386Sopenharmony_ci GLGetQueryObjectuivProc fGLGetQueryObjectuiv; 52cb93a386Sopenharmony_ci GLGetQueryObjectui64vProc fGLGetQueryObjectui64v; 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci using INHERITED = sk_gpu_test::GpuTimer; 56cb93a386Sopenharmony_ci}; 57cb93a386Sopenharmony_ci 58cb93a386Sopenharmony_cistd::unique_ptr<GLGpuTimer> GLGpuTimer::MakeIfSupported(const sk_gpu_test::GLTestContext* ctx) { 59cb93a386Sopenharmony_ci#ifdef SK_GL 60cb93a386Sopenharmony_ci std::unique_ptr<GLGpuTimer> ret; 61cb93a386Sopenharmony_ci const GrGLInterface* gl = ctx->gl(); 62cb93a386Sopenharmony_ci if (gl->fExtensions.has("GL_EXT_disjoint_timer_query")) { 63cb93a386Sopenharmony_ci ret.reset(new GLGpuTimer(true, ctx, "EXT")); 64cb93a386Sopenharmony_ci } else if (kGL_GrGLStandard == gl->fStandard && 65cb93a386Sopenharmony_ci (GrGLGetVersion(gl) > GR_GL_VER(3,3) || gl->fExtensions.has("GL_ARB_timer_query"))) { 66cb93a386Sopenharmony_ci ret.reset(new GLGpuTimer(false, ctx)); 67cb93a386Sopenharmony_ci } else if (gl->fExtensions.has("GL_EXT_timer_query")) { 68cb93a386Sopenharmony_ci ret.reset(new GLGpuTimer(false, ctx, "EXT")); 69cb93a386Sopenharmony_ci } 70cb93a386Sopenharmony_ci if (ret && !ret->validate()) { 71cb93a386Sopenharmony_ci ret = nullptr; 72cb93a386Sopenharmony_ci } 73cb93a386Sopenharmony_ci return ret; 74cb93a386Sopenharmony_ci#else 75cb93a386Sopenharmony_ci return nullptr; 76cb93a386Sopenharmony_ci#endif 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci#ifdef SK_GL 80cb93a386Sopenharmony_ciGLGpuTimer::GLGpuTimer(bool disjointSupport, const sk_gpu_test::GLTestContext* ctx, const char* ext) 81cb93a386Sopenharmony_ci : INHERITED(disjointSupport) { 82cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLGetIntegerv, "glGetIntegerv"); 83cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLGenQueries, "glGenQueries", ext); 84cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLDeleteQueries, "glDeleteQueries", ext); 85cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLBeginQuery, "glBeginQuery", ext); 86cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLEndQuery, "glEndQuery", ext); 87cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLGetQueryObjectuiv, "glGetQueryObjectuiv", ext); 88cb93a386Sopenharmony_ci ctx->getGLProcAddress(&fGLGetQueryObjectui64v, "glGetQueryObjectui64v", ext); 89cb93a386Sopenharmony_ci} 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_cibool GLGpuTimer::validate() const { 92cb93a386Sopenharmony_ci return fGLGetIntegerv && fGLGenQueries && fGLDeleteQueries && fGLBeginQuery && fGLEndQuery && 93cb93a386Sopenharmony_ci fGLGetQueryObjectuiv && fGLGetQueryObjectui64v; 94cb93a386Sopenharmony_ci} 95cb93a386Sopenharmony_ci#endif 96cb93a386Sopenharmony_ci 97cb93a386Sopenharmony_cisk_gpu_test::PlatformTimerQuery GLGpuTimer::onQueueTimerStart() const { 98cb93a386Sopenharmony_ci GrGLuint queryID; 99cb93a386Sopenharmony_ci fGLGenQueries(1, &queryID); 100cb93a386Sopenharmony_ci if (!queryID) { 101cb93a386Sopenharmony_ci return sk_gpu_test::kInvalidTimerQuery; 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci if (this->disjointSupport()) { 104cb93a386Sopenharmony_ci // Clear the disjoint flag. 105cb93a386Sopenharmony_ci GrGLint disjoint; 106cb93a386Sopenharmony_ci fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint); 107cb93a386Sopenharmony_ci } 108cb93a386Sopenharmony_ci fGLBeginQuery(GL_TIME_ELAPSED, queryID); 109cb93a386Sopenharmony_ci return static_cast<sk_gpu_test::PlatformTimerQuery>(queryID); 110cb93a386Sopenharmony_ci} 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_civoid GLGpuTimer::onQueueTimerStop(sk_gpu_test::PlatformTimerQuery platformTimer) const { 113cb93a386Sopenharmony_ci if (sk_gpu_test::kInvalidTimerQuery == platformTimer) { 114cb93a386Sopenharmony_ci return; 115cb93a386Sopenharmony_ci } 116cb93a386Sopenharmony_ci fGLEndQuery(GL_TIME_ELAPSED); 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_cisk_gpu_test::GpuTimer::QueryStatus 120cb93a386Sopenharmony_ciGLGpuTimer::checkQueryStatus(sk_gpu_test::PlatformTimerQuery platformTimer) { 121cb93a386Sopenharmony_ci const GrGLuint queryID = static_cast<GrGLuint>(platformTimer); 122cb93a386Sopenharmony_ci if (!queryID) { 123cb93a386Sopenharmony_ci return QueryStatus::kInvalid; 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci GrGLuint available = 0; 126cb93a386Sopenharmony_ci fGLGetQueryObjectuiv(queryID, GL_QUERY_RESULT_AVAILABLE, &available); 127cb93a386Sopenharmony_ci if (!available) { 128cb93a386Sopenharmony_ci return QueryStatus::kPending; 129cb93a386Sopenharmony_ci } 130cb93a386Sopenharmony_ci if (this->disjointSupport()) { 131cb93a386Sopenharmony_ci GrGLint disjoint = 1; 132cb93a386Sopenharmony_ci fGLGetIntegerv(GL_GPU_DISJOINT, &disjoint); 133cb93a386Sopenharmony_ci if (disjoint) { 134cb93a386Sopenharmony_ci return QueryStatus::kDisjoint; 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci return QueryStatus::kAccurate; 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_cistd::chrono::nanoseconds GLGpuTimer::getTimeElapsed(sk_gpu_test::PlatformTimerQuery platformTimer) { 141cb93a386Sopenharmony_ci SkASSERT(this->checkQueryStatus(platformTimer) >= QueryStatus::kDisjoint); 142cb93a386Sopenharmony_ci const GrGLuint queryID = static_cast<GrGLuint>(platformTimer); 143cb93a386Sopenharmony_ci GrGLuint64 nanoseconds; 144cb93a386Sopenharmony_ci fGLGetQueryObjectui64v(queryID, GL_QUERY_RESULT, &nanoseconds); 145cb93a386Sopenharmony_ci return std::chrono::nanoseconds(nanoseconds); 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_civoid GLGpuTimer::deleteQuery(sk_gpu_test::PlatformTimerQuery platformTimer) { 149cb93a386Sopenharmony_ci const GrGLuint queryID = static_cast<GrGLuint>(platformTimer); 150cb93a386Sopenharmony_ci fGLDeleteQueries(1, &queryID); 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_cistatic_assert(sizeof(GrGLuint) <= sizeof(sk_gpu_test::PlatformTimerQuery)); 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_ci} // anonymous namespace 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_cinamespace sk_gpu_test { 158cb93a386Sopenharmony_ci 159cb93a386Sopenharmony_ciGLTestContext::GLTestContext() : TestContext() {} 160cb93a386Sopenharmony_ci 161cb93a386Sopenharmony_ciGLTestContext::~GLTestContext() { 162cb93a386Sopenharmony_ci SkASSERT(!fGLInterface); 163cb93a386Sopenharmony_ci SkASSERT(!fOriginalGLInterface); 164cb93a386Sopenharmony_ci} 165cb93a386Sopenharmony_ci 166cb93a386Sopenharmony_cibool GLTestContext::isValid() const { 167cb93a386Sopenharmony_ci#ifdef SK_GL 168cb93a386Sopenharmony_ci return SkToBool(this->gl()); 169cb93a386Sopenharmony_ci#else 170cb93a386Sopenharmony_ci return fWasInitialized; 171cb93a386Sopenharmony_ci#endif 172cb93a386Sopenharmony_ci} 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_cistatic bool fence_is_supported(const GLTestContext* ctx) { 175cb93a386Sopenharmony_ci#ifdef SK_GL 176cb93a386Sopenharmony_ci if (kGL_GrGLStandard == ctx->gl()->fStandard) { 177cb93a386Sopenharmony_ci if (GrGLGetVersion(ctx->gl()) < GR_GL_VER(3, 2) && 178cb93a386Sopenharmony_ci !ctx->gl()->hasExtension("GL_ARB_sync")) { 179cb93a386Sopenharmony_ci return false; 180cb93a386Sopenharmony_ci } 181cb93a386Sopenharmony_ci return true; 182cb93a386Sopenharmony_ci } else { 183cb93a386Sopenharmony_ci if (ctx->gl()->hasExtension("GL_APPLE_sync")) { 184cb93a386Sopenharmony_ci return true; 185cb93a386Sopenharmony_ci } else if (ctx->gl()->hasExtension("GL_NV_fence")) { 186cb93a386Sopenharmony_ci return true; 187cb93a386Sopenharmony_ci } else if (GrGLGetVersion(ctx->gl()) >= GR_GL_VER(3, 0)) { 188cb93a386Sopenharmony_ci return true; 189cb93a386Sopenharmony_ci } else { 190cb93a386Sopenharmony_ci return false; 191cb93a386Sopenharmony_ci } 192cb93a386Sopenharmony_ci } 193cb93a386Sopenharmony_ci#else 194cb93a386Sopenharmony_ci return false; 195cb93a386Sopenharmony_ci#endif 196cb93a386Sopenharmony_ci} 197cb93a386Sopenharmony_ci 198cb93a386Sopenharmony_civoid GLTestContext::init(sk_sp<const GrGLInterface> gl) { 199cb93a386Sopenharmony_ci fGLInterface = std::move(gl); 200cb93a386Sopenharmony_ci fOriginalGLInterface = fGLInterface; 201cb93a386Sopenharmony_ci fFenceSupport = fence_is_supported(this); 202cb93a386Sopenharmony_ci fGpuTimer = GLGpuTimer::MakeIfSupported(this); 203cb93a386Sopenharmony_ci#ifndef SK_GL 204cb93a386Sopenharmony_ci fWasInitialized = true; 205cb93a386Sopenharmony_ci#endif 206cb93a386Sopenharmony_ci} 207cb93a386Sopenharmony_ci 208cb93a386Sopenharmony_civoid GLTestContext::teardown() { 209cb93a386Sopenharmony_ci fGLInterface.reset(); 210cb93a386Sopenharmony_ci fOriginalGLInterface.reset(); 211cb93a386Sopenharmony_ci INHERITED::teardown(); 212cb93a386Sopenharmony_ci} 213cb93a386Sopenharmony_ci 214cb93a386Sopenharmony_civoid GLTestContext::testAbandon() { 215cb93a386Sopenharmony_ci INHERITED::testAbandon(); 216cb93a386Sopenharmony_ci#ifdef SK_GL 217cb93a386Sopenharmony_ci if (fGLInterface) { 218cb93a386Sopenharmony_ci fGLInterface->abandon(); 219cb93a386Sopenharmony_ci fOriginalGLInterface->abandon(); 220cb93a386Sopenharmony_ci } 221cb93a386Sopenharmony_ci#endif 222cb93a386Sopenharmony_ci} 223cb93a386Sopenharmony_ci 224cb93a386Sopenharmony_civoid GLTestContext::finish() { 225cb93a386Sopenharmony_ci#ifdef SK_GL 226cb93a386Sopenharmony_ci if (fGLInterface) { 227cb93a386Sopenharmony_ci GR_GL_CALL(fGLInterface.get(), Finish()); 228cb93a386Sopenharmony_ci } 229cb93a386Sopenharmony_ci#endif 230cb93a386Sopenharmony_ci} 231cb93a386Sopenharmony_ci 232cb93a386Sopenharmony_civoid GLTestContext::overrideVersion(const char* version, const char* shadingLanguageVersion) { 233cb93a386Sopenharmony_ci#ifdef SK_GL 234cb93a386Sopenharmony_ci // GrGLFunction has both a limited capture size and doesn't call a destructor when it is 235cb93a386Sopenharmony_ci // initialized with a lambda. So here we're trusting fOriginalGLInterface will be kept alive. 236cb93a386Sopenharmony_ci auto getString = [wrapped = &fOriginalGLInterface->fFunctions.fGetString, 237cb93a386Sopenharmony_ci version, 238cb93a386Sopenharmony_ci shadingLanguageVersion](GrGLenum name) { 239cb93a386Sopenharmony_ci if (name == GR_GL_VERSION) { 240cb93a386Sopenharmony_ci return reinterpret_cast<const GrGLubyte*>(version); 241cb93a386Sopenharmony_ci } else if (name == GR_GL_SHADING_LANGUAGE_VERSION) { 242cb93a386Sopenharmony_ci return reinterpret_cast<const GrGLubyte*>(shadingLanguageVersion); 243cb93a386Sopenharmony_ci } 244cb93a386Sopenharmony_ci return (*wrapped)(name); 245cb93a386Sopenharmony_ci }; 246cb93a386Sopenharmony_ci auto newInterface = sk_make_sp<GrGLInterface>(*fOriginalGLInterface); 247cb93a386Sopenharmony_ci newInterface->fFunctions.fGetString = getString; 248cb93a386Sopenharmony_ci fGLInterface = std::move(newInterface); 249cb93a386Sopenharmony_ci#endif 250cb93a386Sopenharmony_ci}; 251cb93a386Sopenharmony_ci 252cb93a386Sopenharmony_cisk_sp<GrDirectContext> GLTestContext::makeContext(const GrContextOptions& options) { 253cb93a386Sopenharmony_ci#ifdef SK_GL 254cb93a386Sopenharmony_ci return GrDirectContext::MakeGL(fGLInterface, options); 255cb93a386Sopenharmony_ci#else 256cb93a386Sopenharmony_ci return nullptr; 257cb93a386Sopenharmony_ci#endif 258cb93a386Sopenharmony_ci} 259cb93a386Sopenharmony_ci 260cb93a386Sopenharmony_ci} // namespace sk_gpu_test 261