diff options
author | 2015-06-23 13:23:44 -0700 | |
---|---|---|
committer | 2015-06-23 13:23:44 -0700 | |
commit | d416a5b10ff9e6d4f55a1f5b0419722132d68ff3 (patch) | |
tree | f9f39528fd8fd7c033882c137d711e12939c6fa2 /src/gpu/gl/egl | |
parent | b607767703ff7898611cf88c1218d5d69535e984 (diff) |
Implement SkGLContext swapBuffers with fence syncs
Improves the GPU measuring accuracy of nanobench by using fence syncs.
Fence syncs are very widely supported and available on almost every
platform.
NO_MERGE_BUILDS
BUG=skia:
Review URL: https://codereview.chromium.org/1194783003
Diffstat (limited to 'src/gpu/gl/egl')
-rw-r--r-- | src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp | 88 |
1 files changed, 79 insertions, 9 deletions
diff --git a/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp b/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp index d57f761008..9ed57a37a3 100644 --- a/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp +++ b/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp @@ -8,20 +8,42 @@ #include "gl/SkGLContext.h" #include <GLES2/gl2.h> + +#define EGL_EGLEXT_PROTOTYPES #include <EGL/egl.h> +#include <EGL/eglext.h> namespace { +// TODO: Share this class with ANGLE if/when it gets support for EGL_KHR_fence_sync. +class SkEGLFenceSync : public SkGpuFenceSync { +public: + static SkEGLFenceSync* CreateIfSupported(EGLDisplay); + + SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override; + bool flushAndWaitFence(SkPlatformGpuFence fence) const override; + void deleteFence(SkPlatformGpuFence fence) const override; + +private: + SkEGLFenceSync(EGLDisplay display) : fDisplay(display) {} + + EGLDisplay fDisplay; + + typedef SkGpuFenceSync INHERITED; +}; + class EGLGLContext : public SkGLContext { public: EGLGLContext(GrGLStandard forcedGpuAPI); ~EGLGLContext() override; - void makeCurrent() const override; - void swapBuffers() const override; private: void destroyGLContext(); + void onPlatformMakeCurrent() const override; + void onPlatformSwapBuffers() const override; + GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; + EGLContext fContext; EGLDisplay fDisplay; EGLSurface fSurface; @@ -69,7 +91,9 @@ EGLGLContext::EGLGLContext(GrGLStandard forcedGpuAPI) } SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI); - for (; NULL == fGL.get() && api < apiLimit; ++api) { + SkAutoTUnref<const GrGLInterface> gl; + + for (; NULL == gl.get() && api < apiLimit; ++api) { fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); EGLint majorVersion; @@ -134,27 +158,30 @@ EGLGLContext::EGLGLContext(GrGLStandard forcedGpuAPI) continue; } - fGL.reset(GrGLCreateNativeInterface()); - if (NULL == fGL.get()) { + gl.reset(GrGLCreateNativeInterface()); + if (NULL == gl.get()) { SkDebugf("Failed to create gl interface.\n"); this->destroyGLContext(); continue; } - if (!fGL->validate()) { + if (!gl->validate()) { SkDebugf("Failed to validate gl interface.\n"); this->destroyGLContext(); continue; } + + this->init(gl.detach(), SkEGLFenceSync::CreateIfSupported(fDisplay)); + break; } } EGLGLContext::~EGLGLContext() { + this->teardown(); this->destroyGLContext(); } void EGLGLContext::destroyGLContext() { - fGL.reset(NULL); if (fDisplay) { eglMakeCurrent(fDisplay, 0, 0, 0); @@ -174,18 +201,61 @@ void EGLGLContext::destroyGLContext() { } -void EGLGLContext::makeCurrent() const { +void EGLGLContext::onPlatformMakeCurrent() const { if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) { SkDebugf("Could not set the context.\n"); } } -void EGLGLContext::swapBuffers() const { +void EGLGLContext::onPlatformSwapBuffers() const { if (!eglSwapBuffers(fDisplay, fSurface)) { SkDebugf("Could not complete eglSwapBuffers.\n"); } } +GrGLFuncPtr EGLGLContext::onPlatformGetProcAddress(const char* procName) const { + return eglGetProcAddress(procName); +} + +static bool supports_egl_extension(EGLDisplay display, const char* extension) { + int extensionLength = strlen(extension); + const char* extensionsStr = eglQueryString(display, EGL_EXTENSIONS); + while (const char* match = strstr(extensionsStr, extension)) { + // Ensure the string we found is its own extension, not a substring of a larger extension + // (e.g. GL_ARB_occlusion_query / GL_ARB_occlusion_query2). + if ((match == extensionsStr || match[-1] == ' ') && + (match[extensionLength] == ' ' || match[extensionLength] == '\0')) { + return true; + } + extensionsStr = match + extensionLength; + } + return false; +} + +SkEGLFenceSync* SkEGLFenceSync::CreateIfSupported(EGLDisplay display) { + if (!display || !supports_egl_extension(display, "EGL_KHR_fence_sync")) { + return NULL; + } + return SkNEW_ARGS(SkEGLFenceSync, (display)); +} + +SkPlatformGpuFence SkEGLFenceSync::insertFence() const { + return eglCreateSyncKHR(fDisplay, EGL_SYNC_FENCE_KHR, NULL); +} + +bool SkEGLFenceSync::flushAndWaitFence(SkPlatformGpuFence platformFence) const { + EGLSyncKHR eglsync = static_cast<EGLSyncKHR>(platformFence); + return EGL_CONDITION_SATISFIED_KHR == eglClientWaitSyncKHR(fDisplay, + eglsync, + EGL_SYNC_FLUSH_COMMANDS_BIT_KHR, + EGL_FOREVER_KHR); +} + +void SkEGLFenceSync::deleteFence(SkPlatformGpuFence platformFence) const { + EGLSyncKHR eglsync = static_cast<EGLSyncKHR>(platformFence); + eglDestroySyncKHR(fDisplay, eglsync); +} + } // anonymous namespace SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) { |