aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
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
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')
-rw-r--r--src/gpu/SkGpuFenceSync.h29
-rw-r--r--src/gpu/gl/GrGLAssembleInterface.h1
-rw-r--r--src/gpu/gl/SkGLContext.cpp136
-rw-r--r--src/gpu/gl/SkNullGLContext.cpp6
-rw-r--r--src/gpu/gl/angle/SkANGLEGLContext.cpp18
-rw-r--r--src/gpu/gl/debug/SkDebugGLContext.cpp4
-rw-r--r--src/gpu/gl/debug/SkDebugGLContext.h6
-rw-r--r--src/gpu/gl/egl/SkCreatePlatformGLContext_egl.cpp88
-rw-r--r--src/gpu/gl/glx/SkCreatePlatformGLContext_glx.cpp24
-rw-r--r--src/gpu/gl/iOS/SkCreatePlatformGLContext_iOS.mm36
-rw-r--r--src/gpu/gl/mac/SkCreatePlatformGLContext_mac.cpp36
-rw-r--r--src/gpu/gl/mesa/SkMesaGLContext.cpp18
-rw-r--r--src/gpu/gl/mesa/SkMesaGLContext.h6
-rw-r--r--src/gpu/gl/win/SkCreatePlatformGLContext_win.cpp24
14 files changed, 365 insertions, 67 deletions
diff --git a/src/gpu/SkGpuFenceSync.h b/src/gpu/SkGpuFenceSync.h
new file mode 100644
index 0000000000..b78398fed8
--- /dev/null
+++ b/src/gpu/SkGpuFenceSync.h
@@ -0,0 +1,29 @@
+
+/*
+ * Copyright 2015 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef SkGpuFenceSync_DEFINED
+#define SkGpuFenceSync_DEFINED
+
+#include "SkTypes.h"
+
+typedef void* SkPlatformGpuFence;
+
+/*
+ * This class provides an interface to interact with fence syncs. A fence sync is an object that the
+ * client can insert into the GPU command stream, and then at any future time, wait until all
+ * commands that were issued before the fence have completed.
+ */
+class SkGpuFenceSync {
+public:
+ virtual SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const = 0;
+ virtual bool flushAndWaitFence(SkPlatformGpuFence) const = 0;
+ virtual void deleteFence(SkPlatformGpuFence) const = 0;
+
+ virtual ~SkGpuFenceSync() {}
+};
+
+#endif
diff --git a/src/gpu/gl/GrGLAssembleInterface.h b/src/gpu/gl/GrGLAssembleInterface.h
index aa0fbcadd5..2a4835be38 100644
--- a/src/gpu/gl/GrGLAssembleInterface.h
+++ b/src/gpu/gl/GrGLAssembleInterface.h
@@ -8,7 +8,6 @@
#include "gl/GrGLInterface.h"
-typedef void(*GrGLFuncPtr)();
typedef GrGLFuncPtr (*GrGLGetProc)(void* ctx, const char name[]);
diff --git a/src/gpu/gl/SkGLContext.cpp b/src/gpu/gl/SkGLContext.cpp
index 7cc728d62e..8975a989d1 100644
--- a/src/gpu/gl/SkGLContext.cpp
+++ b/src/gpu/gl/SkGLContext.cpp
@@ -7,16 +7,148 @@
*/
#include "gl/SkGLContext.h"
#include "GrGLUtil.h"
+#include "SkGpuFenceSync.h"
-SkGLContext::SkGLContext() {
+class SkGLContext::GLFenceSync : public SkGpuFenceSync {
+public:
+ static GLFenceSync* CreateIfSupported(const SkGLContext*);
+
+ SkPlatformGpuFence SK_WARN_UNUSED_RESULT insertFence() const override;
+ bool flushAndWaitFence(SkPlatformGpuFence fence) const override;
+ void deleteFence(SkPlatformGpuFence fence) const override;
+
+private:
+ GLFenceSync() {}
+
+ static const GrGLenum GL_SYNC_GPU_COMMANDS_COMPLETE = 0x9117;
+ static const GrGLenum GL_WAIT_FAILED = 0x911d;
+ static const GrGLbitfield GL_SYNC_FLUSH_COMMANDS_BIT = 0x00000001;
+
+ typedef struct __GLsync *GLsync;
+
+ typedef GLsync (GR_GL_FUNCTION_TYPE* GLFenceSyncProc) (GrGLenum, GrGLbitfield);
+ typedef GrGLenum (GR_GL_FUNCTION_TYPE* GLClientWaitSyncProc) (GLsync, GrGLbitfield, GrGLuint64);
+ typedef GrGLvoid (GR_GL_FUNCTION_TYPE* GLDeleteSyncProc) (GLsync);
+
+ GLFenceSyncProc fGLFenceSync;
+ GLClientWaitSyncProc fGLClientWaitSync;
+ GLDeleteSyncProc fGLDeleteSync;
+
+ typedef SkGpuFenceSync INHERITED;
+};
+
+SkGLContext::SkGLContext()
+ : fCurrentFenceIdx(0) {
+ memset(fFrameFences, 0, sizeof(fFrameFences));
}
SkGLContext::~SkGLContext() {
- SkASSERT(NULL == fGL.get()); // Subclass should destroy the interface.
+ // Subclass should call teardown.
+#ifdef SK_DEBUG
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
+ SkASSERT(0 == fFrameFences[i]);
+ }
+#endif
+ SkASSERT(NULL == fGL.get());
+ SkASSERT(NULL == fFenceSync.get());
+}
+
+void SkGLContext::init(const GrGLInterface* gl, SkGpuFenceSync* fenceSync) {
+ SkASSERT(!fGL.get());
+ fGL.reset(gl);
+ fFenceSync.reset(fenceSync ? fenceSync : GLFenceSync::CreateIfSupported(this));
+}
+
+void SkGLContext::teardown() {
+ if (fFenceSync) {
+ for (size_t i = 0; i < SK_ARRAY_COUNT(fFrameFences); i++) {
+ if (fFrameFences[i]) {
+ fFenceSync->deleteFence(fFrameFences[i]);
+ fFrameFences[i] = 0;
+ }
+ }
+ fFenceSync.reset(NULL);
+ }
+
+ fGL.reset(NULL);
+}
+
+void SkGLContext::makeCurrent() const {
+ this->onPlatformMakeCurrent();
+}
+
+void SkGLContext::swapBuffers() {
+ if (!fFenceSync) {
+ // Fallback on the platform SwapBuffers method for synchronization. This may have no effect.
+ this->onPlatformSwapBuffers();
+ return;
+ }
+
+ if (fFrameFences[fCurrentFenceIdx]) {
+ if (!fFenceSync->flushAndWaitFence(fFrameFences[fCurrentFenceIdx])) {
+ SkDebugf("WARNING: Wait failed for fence sync. Timings might not be accurate.\n");
+ }
+ fFenceSync->deleteFence(fFrameFences[fCurrentFenceIdx]);
+ }
+
+ fFrameFences[fCurrentFenceIdx] = fFenceSync->insertFence();
+ fCurrentFenceIdx = (fCurrentFenceIdx + 1) % SK_ARRAY_COUNT(fFrameFences);
}
void SkGLContext::testAbandon() {
if (fGL) {
fGL->abandon();
}
+ if (fFenceSync) {
+ memset(fFrameFences, 0, sizeof(fFrameFences));
+ }
+}
+
+SkGLContext::GLFenceSync* SkGLContext::GLFenceSync::CreateIfSupported(const SkGLContext* ctx) {
+ SkAutoTDelete<GLFenceSync> ret(SkNEW(GLFenceSync));
+
+ if (kGL_GrGLStandard == ctx->gl()->fStandard) {
+ const GrGLubyte* versionStr;
+ SK_GL_RET(*ctx, versionStr, GetString(GR_GL_VERSION));
+ GrGLVersion version = GrGLGetVersionFromString(reinterpret_cast<const char*>(versionStr));
+ if (version < GR_GL_VER(3,2) && !ctx->gl()->hasExtension("GL_ARB_sync")) {
+ return NULL;
+ }
+ ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>(
+ ctx->onPlatformGetProcAddress("glFenceSync"));
+ ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>(
+ ctx->onPlatformGetProcAddress("glClientWaitSync"));
+ ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>(
+ ctx->onPlatformGetProcAddress("glDeleteSync"));
+ } else {
+ if (!ctx->gl()->hasExtension("GL_APPLE_sync")) {
+ return NULL;
+ }
+ ret->fGLFenceSync = reinterpret_cast<GLFenceSyncProc>(
+ ctx->onPlatformGetProcAddress("glFenceSyncAPPLE"));
+ ret->fGLClientWaitSync = reinterpret_cast<GLClientWaitSyncProc>(
+ ctx->onPlatformGetProcAddress("glClientWaitSyncAPPLE"));
+ ret->fGLDeleteSync = reinterpret_cast<GLDeleteSyncProc>(
+ ctx->onPlatformGetProcAddress("glDeleteSyncAPPLE"));
+ }
+
+ if (!ret->fGLFenceSync || !ret->fGLClientWaitSync || !ret->fGLDeleteSync) {
+ return NULL;
+ }
+
+ return ret.detach();
+}
+
+SkPlatformGpuFence SkGLContext::GLFenceSync::insertFence() const {
+ return fGLFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+bool SkGLContext::GLFenceSync::flushAndWaitFence(SkPlatformGpuFence fence) const {
+ GLsync glsync = static_cast<GLsync>(fence);
+ return GL_WAIT_FAILED != fGLClientWaitSync(glsync, GL_SYNC_FLUSH_COMMANDS_BIT, -1);
+}
+
+void SkGLContext::GLFenceSync::deleteFence(SkPlatformGpuFence fence) const {
+ GLsync glsync = static_cast<GLsync>(fence);
+ fGLDeleteSync(glsync);
}
diff --git a/src/gpu/gl/SkNullGLContext.cpp b/src/gpu/gl/SkNullGLContext.cpp
index 7ced85e89e..1d67578cae 100644
--- a/src/gpu/gl/SkNullGLContext.cpp
+++ b/src/gpu/gl/SkNullGLContext.cpp
@@ -547,7 +547,7 @@ SkNullGLContext* SkNullGLContext::Create(GrGLStandard forcedGpuAPI) {
SkNullGLContext::SkNullGLContext() {
fState = SkNEW(ContextState);
GrGLInterface* interface = create_null_interface(fState);
- fGL.reset(interface);
+ this->init(interface);
#if GR_GL_PER_GL_FUNC_CALLBACK
interface->fCallback = set_current_context_from_interface;
interface->fCallbackData = reinterpret_cast<GrGLInterfaceCallbackData>(fState);
@@ -555,8 +555,8 @@ SkNullGLContext::SkNullGLContext() {
}
SkNullGLContext::~SkNullGLContext() {
- fGL.reset(NULL);
+ this->teardown();
fState->unref();
}
-void SkNullGLContext::makeCurrent() const { set_current_context(fState); }
+void SkNullGLContext::onPlatformMakeCurrent() const { set_current_context(fState); }
diff --git a/src/gpu/gl/angle/SkANGLEGLContext.cpp b/src/gpu/gl/angle/SkANGLEGLContext.cpp
index cea2adf989..f6321988aa 100644
--- a/src/gpu/gl/angle/SkANGLEGLContext.cpp
+++ b/src/gpu/gl/angle/SkANGLEGLContext.cpp
@@ -96,25 +96,27 @@ SkANGLEGLContext::SkANGLEGLContext()
eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
- fGL.reset(GrGLCreateANGLEInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateANGLEInterface());
+ if (NULL == gl.get()) {
SkDebugf("Could not create ANGLE GL interface!\n");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Could not validate ANGLE GL interface!\n");
this->destroyGLContext();
return;
}
+
+ this->init(gl.detach());
}
SkANGLEGLContext::~SkANGLEGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void SkANGLEGLContext::destroyGLContext() {
- fGL.reset(NULL);
if (fDisplay) {
eglMakeCurrent(fDisplay, 0, 0, 0);
@@ -133,14 +135,18 @@ void SkANGLEGLContext::destroyGLContext() {
}
}
-void SkANGLEGLContext::makeCurrent() const {
+void SkANGLEGLContext::onPlatformMakeCurrent() const {
if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
SkDebugf("Could not set the context.\n");
}
}
-void SkANGLEGLContext::swapBuffers() const {
+void SkANGLEGLContext::onPlatformSwapBuffers() const {
if (!eglSwapBuffers(fDisplay, fSurface)) {
SkDebugf("Could not complete eglSwapBuffers.\n");
}
}
+
+GrGLFuncPtr SkANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
+ return eglGetProcAddress(name);
+}
diff --git a/src/gpu/gl/debug/SkDebugGLContext.cpp b/src/gpu/gl/debug/SkDebugGLContext.cpp
index ae55104d46..531e6c3ab8 100644
--- a/src/gpu/gl/debug/SkDebugGLContext.cpp
+++ b/src/gpu/gl/debug/SkDebugGLContext.cpp
@@ -9,9 +9,9 @@
#include "gl/debug/SkDebugGLContext.h"
SkDebugGLContext::SkDebugGLContext() {
- fGL.reset(GrGLCreateDebugInterface());
+ this->init(GrGLCreateDebugInterface());
}
SkDebugGLContext::~SkDebugGLContext() {
- fGL.reset(NULL);
+ this->teardown();
}
diff --git a/src/gpu/gl/debug/SkDebugGLContext.h b/src/gpu/gl/debug/SkDebugGLContext.h
index 577953223a..6a4d9fc38b 100644
--- a/src/gpu/gl/debug/SkDebugGLContext.h
+++ b/src/gpu/gl/debug/SkDebugGLContext.h
@@ -13,8 +13,6 @@
class SkDebugGLContext : public SkGLContext {
public:
~SkDebugGLContext() override;
- void makeCurrent() const override {}
- void swapBuffers() const override {}
static SkDebugGLContext* Create(GrGLStandard forcedGpuAPI) {
if (kGLES_GrGLStandard == forcedGpuAPI) {
@@ -23,6 +21,10 @@ public:
return SkNEW(SkDebugGLContext);
}
private:
+ void onPlatformMakeCurrent() const override {}
+ void onPlatformSwapBuffers() const override {}
+ GrGLFuncPtr onPlatformGetProcAddress(const char*) const override { return NULL; }
+
SkDebugGLContext();
};
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) {
diff --git a/src/gpu/gl/glx/SkCreatePlatformGLContext_glx.cpp b/src/gpu/gl/glx/SkCreatePlatformGLContext_glx.cpp
index 8006d498aa..7933757186 100644
--- a/src/gpu/gl/glx/SkCreatePlatformGLContext_glx.cpp
+++ b/src/gpu/gl/glx/SkCreatePlatformGLContext_glx.cpp
@@ -48,12 +48,14 @@ class GLXGLContext : public SkGLContext {
public:
GLXGLContext(GrGLStandard forcedGpuAPI);
~GLXGLContext() 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;
+
GLXContext fContext;
Display* fDisplay;
Pixmap fPixmap;
@@ -267,27 +269,29 @@ GLXGLContext::GLXGLContext(GrGLStandard forcedGpuAPI)
return;
}
- fGL.reset(GrGLCreateNativeInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateNativeInterface());
+ if (NULL == gl.get()) {
SkDebugf("Failed to create gl interface");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Failed to validate gl interface");
this->destroyGLContext();
return;
}
+
+ this->init(gl.detach());
}
GLXGLContext::~GLXGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void GLXGLContext::destroyGLContext() {
- fGL.reset(NULL);
if (fDisplay) {
glXMakeCurrent(fDisplay, 0, 0);
@@ -311,16 +315,20 @@ void GLXGLContext::destroyGLContext() {
}
}
-void GLXGLContext::makeCurrent() const {
+void GLXGLContext::onPlatformMakeCurrent() const {
if (!glXMakeCurrent(fDisplay, fGlxPixmap, fContext)) {
SkDebugf("Could not set the context.\n");
}
}
-void GLXGLContext::swapBuffers() const {
+void GLXGLContext::onPlatformSwapBuffers() const {
glXSwapBuffers(fDisplay, fGlxPixmap);
}
+GrGLFuncPtr GLXGLContext::onPlatformGetProcAddress(const char* procName) const {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(procName));
+}
+
} // anonymous namespace
SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) {
diff --git a/src/gpu/gl/iOS/SkCreatePlatformGLContext_iOS.mm b/src/gpu/gl/iOS/SkCreatePlatformGLContext_iOS.mm
index 884216845c..08e6f239ee 100644
--- a/src/gpu/gl/iOS/SkCreatePlatformGLContext_iOS.mm
+++ b/src/gpu/gl/iOS/SkCreatePlatformGLContext_iOS.mm
@@ -8,6 +8,7 @@
#include "gl/SkGLContext.h"
#import <OpenGLES/EAGL.h>
+#include <dlfcn.h>
#define EAGLCTX ((EAGLContext*)(fEAGLContext))
@@ -17,40 +18,50 @@ class IOSGLContext : public SkGLContext {
public:
IOSGLContext();
~IOSGLContext() 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;
+
void* fEAGLContext;
+ void* fGLLibrary;
};
IOSGLContext::IOSGLContext()
- : fEAGLContext(NULL) {
+ : fEAGLContext(NULL)
+ , fGLLibrary(RTLD_DEFAULT) {
fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
[EAGLContext setCurrentContext:EAGLCTX];
- fGL.reset(GrGLCreateNativeInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateNativeInterface());
+ if (NULL == gl.get()) {
SkDebugf("Failed to create gl interface");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Failed to validate gl interface");
this->destroyGLContext();
return;
}
+
+ fGLLibrary = dlopen(
+ "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
+ RTLD_LAZY);
+
+ this->init(gl.detach());
}
IOSGLContext::~IOSGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void IOSGLContext::destroyGLContext() {
- fGL.reset(NULL);
if (fEAGLContext) {
if ([EAGLContext currentContext] == EAGLCTX) {
[EAGLContext setCurrentContext:nil];
@@ -58,16 +69,23 @@ void IOSGLContext::destroyGLContext() {
[EAGLCTX release];
fEAGLContext = NULL;
}
+ if (RTLD_DEFAULT != fGLLibrary) {
+ dlclose(fGLLibrary);
+ }
}
-void IOSGLContext::makeCurrent() const {
+void IOSGLContext::onPlatformMakeCurrent() const {
if (![EAGLContext setCurrentContext:EAGLCTX]) {
SkDebugf("Could not set the context.\n");
}
}
-void IOSGLContext::swapBuffers() const { }
+void IOSGLContext::onPlatformSwapBuffers() const { }
+
+GrGLFuncPtr IOSGLContext::onPlatformGetProcAddress(const char* procName) const {
+ return reinterpret_cast<GrGLFuncPtr>(dlsym(fGLLibrary, procName));
+}
} // anonymous namespace
diff --git a/src/gpu/gl/mac/SkCreatePlatformGLContext_mac.cpp b/src/gpu/gl/mac/SkCreatePlatformGLContext_mac.cpp
index 436c53f0bb..d2d8569938 100644
--- a/src/gpu/gl/mac/SkCreatePlatformGLContext_mac.cpp
+++ b/src/gpu/gl/mac/SkCreatePlatformGLContext_mac.cpp
@@ -9,23 +9,28 @@
#include "AvailabilityMacros.h"
#include <OpenGL/OpenGL.h>
+#include <dlfcn.h>
namespace {
class MacGLContext : public SkGLContext {
public:
MacGLContext();
~MacGLContext() 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;
+
CGLContextObj fContext;
+ void* fGLLibrary;
};
MacGLContext::MacGLContext()
- : fContext(NULL) {
+ : fContext(NULL)
+ , fGLLibrary(RTLD_DEFAULT) {
CGLPixelFormatAttribute attributes[] = {
#if MAC_OS_X_VERSION_10_7
kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
@@ -53,39 +58,52 @@ MacGLContext::MacGLContext()
CGLSetCurrentContext(fContext);
- fGL.reset(GrGLCreateNativeInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateNativeInterface());
+ if (NULL == gl.get()) {
SkDebugf("Context could not create GL interface.\n");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Context could not validate GL interface.\n");
this->destroyGLContext();
return;
}
+
+ fGLLibrary = dlopen(
+ "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
+ RTLD_LAZY);
+
+ this->init(gl.detach());
}
MacGLContext::~MacGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void MacGLContext::destroyGLContext() {
- fGL.reset(NULL);
if (fContext) {
CGLReleaseContext(fContext);
fContext = NULL;
}
+ if (RTLD_DEFAULT != fGLLibrary) {
+ dlclose(fGLLibrary);
+ }
}
-void MacGLContext::makeCurrent() const {
+void MacGLContext::onPlatformMakeCurrent() const {
CGLSetCurrentContext(fContext);
}
-void MacGLContext::swapBuffers() const {
+void MacGLContext::onPlatformSwapBuffers() const {
CGLFlushDrawable(fContext);
}
+GrGLFuncPtr MacGLContext::onPlatformGetProcAddress(const char* procName) const {
+ return reinterpret_cast<GrGLFuncPtr>(dlsym(fGLLibrary, procName));
+}
+
} // anonymous namespace
SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) {
diff --git a/src/gpu/gl/mesa/SkMesaGLContext.cpp b/src/gpu/gl/mesa/SkMesaGLContext.cpp
index 1fac5fadd6..701cc0d320 100644
--- a/src/gpu/gl/mesa/SkMesaGLContext.cpp
+++ b/src/gpu/gl/mesa/SkMesaGLContext.cpp
@@ -50,26 +50,28 @@ SkMesaGLContext::SkMesaGLContext()
return;
}
- fGL.reset(GrGLCreateMesaInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateMesaInterface());
+ if (NULL == gl.get()) {
SkDebugf("Could not create GL interface!\n");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Could not validate GL interface!\n");
this->destroyGLContext();
return;
}
+
+ this->init(gl.detach());
}
SkMesaGLContext::~SkMesaGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void SkMesaGLContext::destroyGLContext() {
- fGL.reset(NULL);
if (fImage) {
sk_free(fImage);
fImage = NULL;
@@ -83,7 +85,7 @@ void SkMesaGLContext::destroyGLContext() {
-void SkMesaGLContext::makeCurrent() const {
+void SkMesaGLContext::onPlatformMakeCurrent() const {
if (fContext) {
if (!OSMesaMakeCurrent((OSMesaContext)fContext, fImage,
GR_GL_UNSIGNED_BYTE, gBOGUS_SIZE, gBOGUS_SIZE)) {
@@ -92,4 +94,8 @@ void SkMesaGLContext::makeCurrent() const {
}
}
-void SkMesaGLContext::swapBuffers() const { }
+void SkMesaGLContext::onPlatformSwapBuffers() const { }
+
+GrGLFuncPtr SkMesaGLContext::onPlatformGetProcAddress(const char* procName) const {
+ return OSMesaGetProcAddress(procName);
+}
diff --git a/src/gpu/gl/mesa/SkMesaGLContext.h b/src/gpu/gl/mesa/SkMesaGLContext.h
index bf0c7e9060..fa3df7b7c7 100644
--- a/src/gpu/gl/mesa/SkMesaGLContext.h
+++ b/src/gpu/gl/mesa/SkMesaGLContext.h
@@ -18,8 +18,6 @@ private:
public:
~SkMesaGLContext() override;
- void makeCurrent() const override;
- void swapBuffers() const override;
static SkMesaGLContext* Create(GrGLStandard forcedGpuAPI) {
if (kGLES_GrGLStandard == forcedGpuAPI) {
@@ -37,6 +35,10 @@ private:
SkMesaGLContext();
void destroyGLContext();
+ void onPlatformMakeCurrent() const override;
+ void onPlatformSwapBuffers() const override;
+ GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
+
Context fContext;
GrGLubyte *fImage;
};
diff --git a/src/gpu/gl/win/SkCreatePlatformGLContext_win.cpp b/src/gpu/gl/win/SkCreatePlatformGLContext_win.cpp
index d387ef4922..8a4c5db5b3 100644
--- a/src/gpu/gl/win/SkCreatePlatformGLContext_win.cpp
+++ b/src/gpu/gl/win/SkCreatePlatformGLContext_win.cpp
@@ -21,12 +21,14 @@ class WinGLContext : public SkGLContext {
public:
WinGLContext(GrGLStandard forcedGpuAPI);
~WinGLContext() override;
- void makeCurrent() const override;
- void swapBuffers() const override;
private:
void destroyGLContext();
+ void onPlatformMakeCurrent() const override;
+ void onPlatformSwapBuffers() const override;
+ GrGLFuncPtr onPlatformGetProcAddress(const char* name) const override;
+
HWND fWindow;
HDC fDeviceContext;
HGLRC fGlRenderContext;
@@ -113,25 +115,27 @@ WinGLContext::WinGLContext(GrGLStandard forcedGpuAPI)
return;
}
- fGL.reset(GrGLCreateNativeInterface());
- if (NULL == fGL.get()) {
+ SkAutoTUnref<const GrGLInterface> gl(GrGLCreateNativeInterface());
+ if (NULL == gl.get()) {
SkDebugf("Could not create GL interface.\n");
this->destroyGLContext();
return;
}
- if (!fGL->validate()) {
+ if (!gl->validate()) {
SkDebugf("Could not validate GL interface.\n");
this->destroyGLContext();
return;
}
+
+ this->init(gl.detach());
}
WinGLContext::~WinGLContext() {
+ this->teardown();
this->destroyGLContext();
}
void WinGLContext::destroyGLContext() {
- fGL.reset(NULL);
SkSafeSetNull(fPbufferContext);
if (fGlRenderContext) {
wglDeleteContext(fGlRenderContext);
@@ -147,7 +151,7 @@ void WinGLContext::destroyGLContext() {
}
}
-void WinGLContext::makeCurrent() const {
+void WinGLContext::onPlatformMakeCurrent() const {
HDC dc;
HGLRC glrc;
@@ -164,7 +168,7 @@ void WinGLContext::makeCurrent() const {
}
}
-void WinGLContext::swapBuffers() const {
+void WinGLContext::onPlatformSwapBuffers() const {
HDC dc;
if (NULL == fPbufferContext) {
@@ -177,6 +181,10 @@ void WinGLContext::swapBuffers() const {
}
}
+GrGLFuncPtr WinGLContext::onPlatformGetProcAddress(const char* name) const {
+ return reinterpret_cast<GrGLFuncPtr>(wglGetProcAddress(name));
+}
+
} // anonymous namespace
SkGLContext* SkCreatePlatformGLContext(GrGLStandard forcedGpuAPI) {