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