aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/gl/egl
diff options
context:
space:
mode:
authorGravatar cdalton <cdalton@nvidia.com>2015-06-23 13:23:44 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2015-06-23 13:23:44 -0700
commitd416a5b10ff9e6d4f55a1f5b0419722132d68ff3 (patch)
treef9f39528fd8fd7c033882c137d711e12939c6fa2 /src/gpu/gl/egl
parentb607767703ff7898611cf88c1218d5d69535e984 (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.cpp88
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) {