Index: src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp |
diff --git a/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp b/src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp |
index d57f761008cbf6ac57e15cdcca9c12368ee8cc80..9ed57a37a3c773f30cefe3a9085af5faf09cfc9e 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) { |