1 2 /* 3 * Copyright 2012 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 #include "gl/GLTestContext.h" 10 #import <OpenGLES/EAGL.h> 11 #include <dlfcn.h> 12 13 #define EAGLCTX ((EAGLContext*)(fEAGLContext)) 14 15 namespace { 16 17 std::function<void()> context_restorer() { 18 EAGLContext* context = [EAGLContext currentContext]; 19 return [context] { [EAGLContext setCurrentContext:context]; }; 20 } 21 22 class IOSGLTestContext : public sk_gpu_test::GLTestContext { 23 public: 24 IOSGLTestContext(IOSGLTestContext* shareContext); 25 ~IOSGLTestContext() override; 26 27 private: 28 void destroyGLContext(); 29 30 void onPlatformMakeCurrent() const override; 31 std::function<void()> onPlatformGetAutoContextRestore() const override; 32 void onPlatformSwapBuffers() const override; 33 GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; 34 35 EAGLContext* fEAGLContext; 36 void* fGLLibrary; 37 }; 38 39 IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext) 40 : fEAGLContext(NULL) 41 , fGLLibrary(RTLD_DEFAULT) { 42 43 if (shareContext) { 44 EAGLContext* iosShareContext = shareContext->fEAGLContext; 45 fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2 46 sharegroup: [iosShareContext sharegroup]]; 47 } else { 48 fEAGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]; 49 } 50 SkScopeExit restorer(context_restorer()); 51 [EAGLContext setCurrentContext:fEAGLContext]; 52 53 sk_sp<const GrGLInterface> gl(GrGLCreateNativeInterface()); 54 if (NULL == gl.get()) { 55 SkDebugf("Failed to create gl interface"); 56 this->destroyGLContext(); 57 return; 58 } 59 if (!gl->validate()) { 60 SkDebugf("Failed to validate gl interface"); 61 this->destroyGLContext(); 62 return; 63 } 64 65 fGLLibrary = dlopen( 66 "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib", 67 RTLD_LAZY); 68 69 this->init(std::move(gl)); 70 } 71 72 IOSGLTestContext::~IOSGLTestContext() { 73 this->teardown(); 74 this->destroyGLContext(); 75 } 76 77 void IOSGLTestContext::destroyGLContext() { 78 if (fEAGLContext) { 79 if ([EAGLContext currentContext] == fEAGLContext) { 80 // This will ensure that the context is immediately deleted. 81 [EAGLContext setCurrentContext:nil]; 82 } 83 fEAGLContext = nil; 84 } 85 if (nullptr != fGLLibrary) { 86 dlclose(fGLLibrary); 87 } 88 } 89 90 91 void IOSGLTestContext::onPlatformMakeCurrent() const { 92 if (![EAGLContext setCurrentContext:fEAGLContext]) { 93 SkDebugf("Could not set the context.\n"); 94 } 95 } 96 97 std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const { 98 if ([EAGLContext currentContext] == fEAGLContext) { 99 return nullptr; 100 } 101 return context_restorer(); 102 } 103 104 void IOSGLTestContext::onPlatformSwapBuffers() const { } 105 106 GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const { 107 void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary; 108 return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName)); 109 } 110 111 } // anonymous namespace 112 113 namespace sk_gpu_test { 114 GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, 115 GLTestContext *shareContext) { 116 if (kGL_GrGLStandard == forcedGpuAPI) { 117 return NULL; 118 } 119 IOSGLTestContext* iosShareContext = reinterpret_cast<IOSGLTestContext*>(shareContext); 120 IOSGLTestContext *ctx = new IOSGLTestContext(iosShareContext); 121 if (!ctx->isValid()) { 122 delete ctx; 123 return NULL; 124 } 125 return ctx; 126 } 127 } 128