/* * Copyright 2012 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "gl/GLTestContext.h" #import #include #define EAGLCTX ((EAGLContext*)(fEAGLContext)) namespace { std::function context_restorer() { EAGLContext* context = [EAGLContext currentContext]; return [context] { [EAGLContext setCurrentContext:context]; }; } class IOSGLTestContext : public sk_gpu_test::GLTestContext { public: IOSGLTestContext(IOSGLTestContext* shareContext); ~IOSGLTestContext() override; private: void destroyGLContext(); void onPlatformMakeCurrent() const override; std::function onPlatformGetAutoContextRestore() const override; void onPlatformSwapBuffers() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; EAGLContext* fEAGLContext; void* fGLLibrary; }; IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext) : fEAGLContext(NULL) , fGLLibrary(RTLD_DEFAULT) { if (shareContext) { EAGLContext* iosShareContext = shareContext->fEAGLContext; fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 sharegroup: [iosShareContext sharegroup]]; } else { fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; } SkScopeExit restorer(context_restorer()); [EAGLContext setCurrentContext:fEAGLContext]; sk_sp gl(GrGLCreateNativeInterface()); if (NULL == gl.get()) { SkDebugf("Failed to create gl interface"); this->destroyGLContext(); return; } 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(std::move(gl)); } IOSGLTestContext::~IOSGLTestContext() { this->teardown(); this->destroyGLContext(); } void IOSGLTestContext::destroyGLContext() { if (fEAGLContext) { if ([EAGLContext currentContext] == fEAGLContext) { // This will ensure that the context is immediately deleted. [EAGLContext setCurrentContext:nil]; } fEAGLContext = nil; } if (nullptr != fGLLibrary) { dlclose(fGLLibrary); } } void IOSGLTestContext::onPlatformMakeCurrent() const { if (![EAGLContext setCurrentContext:fEAGLContext]) { SkDebugf("Could not set the context.\n"); } } std::function IOSGLTestContext::onPlatformGetAutoContextRestore() const { if ([EAGLContext currentContext] == fEAGLContext) { return nullptr; } return context_restorer(); } void IOSGLTestContext::onPlatformSwapBuffers() const { } GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const { void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary; return reinterpret_cast(dlsym(handle, procName)); } } // anonymous namespace namespace sk_gpu_test { GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, GLTestContext *shareContext) { if (kGL_GrGLStandard == forcedGpuAPI) { return NULL; } IOSGLTestContext* iosShareContext = reinterpret_cast(shareContext); IOSGLTestContext *ctx = new IOSGLTestContext(iosShareContext); if (!ctx->isValid()) { delete ctx; return NULL; } return ctx; } }