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