Home | History | Annotate | Download | only in iOS
      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: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 
     79 IOSGLTestContext::~IOSGLTestContext() {
     80     this->teardown();
     81     this->destroyGLContext();
     82 }
     83 
     84 void 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 
     98 void IOSGLTestContext::onPlatformMakeCurrent() const {
     99     if (![EAGLContext setCurrentContext:fEAGLContext]) {
    100         SkDebugf("Could not set the context.\n");
    101     }
    102 }
    103 
    104 std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
    105     if ([EAGLContext currentContext] == fEAGLContext) {
    106 		return nullptr;
    107 	}
    108     return context_restorer();
    109 }
    110 
    111 void IOSGLTestContext::onPlatformSwapBuffers() const { }
    112 
    113 GrGLFuncPtr 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 
    120 namespace sk_gpu_test {
    121 GLTestContext *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