text: 
  /*
   * Copyright 2011 Google Inc.
   *
   * Use of this source code is governed by a BSD-style license that can be
   * found in the LICENSE file.
   */
  #include "gl/SkNativeGLContext.h"
  
  SkNativeGLContext::AutoContextRestore::AutoContextRestore() {
      fOldEGLContext = eglGetCurrentContext();
      fOldDisplay = eglGetCurrentDisplay();
      fOldSurface = eglGetCurrentSurface(EGL_DRAW);
  
  }
  
  SkNativeGLContext::AutoContextRestore::~AutoContextRestore() {
      if (fOldDisplay) {
          eglMakeCurrent(fOldDisplay, fOldSurface, fOldSurface, fOldEGLContext);
      }
  }
  
  ///////////////////////////////////////////////////////////////////////////////
  
  SkNativeGLContext::SkNativeGLContext()
      : fContext(EGL_NO_CONTEXT)
      , fDisplay(EGL_NO_DISPLAY)
      , fSurface(EGL_NO_SURFACE) {
  }
  
  SkNativeGLContext::~SkNativeGLContext() {
      this->destroyGLContext();
  }
  
  void SkNativeGLContext::destroyGLContext() {
      if (fDisplay) {
          eglMakeCurrent(fDisplay, 0, 0, 0);
  
          if (fContext) {
              eglDestroyContext(fDisplay, fContext);
              fContext = EGL_NO_CONTEXT;
          }
  
          if (fSurface) {
              eglDestroySurface(fDisplay, fSurface);
              fSurface = EGL_NO_SURFACE;
          }
  
          //TODO should we close the display?
          fDisplay = EGL_NO_DISPLAY;
      }
  }
  
  const GrGLInterface* SkNativeGLContext::createGLContext(GrGLStandard forcedGpuAPI) {
      static const EGLint kEGLContextAttribsForOpenGL[] = {
          EGL_NONE
      };
  
      static const EGLint kEGLContextAttribsForOpenGLES[] = {
          EGL_CONTEXT_CLIENT_VERSION, 2,
          EGL_NONE
      };
  
      static const struct {
          const EGLint* fContextAttribs;
          EGLenum fAPI;
          EGLint  fRenderableTypeBit;
          GrGLStandard fStandard;
      } kAPIs[] = {
          {   // OpenGL
              kEGLContextAttribsForOpenGL,
              EGL_OPENGL_API,
              EGL_OPENGL_BIT,
              kGL_GrGLStandard
          },
          {   // OpenGL ES. This seems to work for both ES2 and 3 (when available).
              kEGLContextAttribsForOpenGLES,
              EGL_OPENGL_ES_API,
              EGL_OPENGL_ES2_BIT,
              kGLES_GrGLStandard
          },
      };
  
      size_t apiLimit = SK_ARRAY_COUNT(kAPIs);
      size_t api = 0;
      if (forcedGpuAPI == kGL_GrGLStandard) {
          apiLimit = 1;
      } else if (forcedGpuAPI == kGLES_GrGLStandard) {
          api = 1;
      }
      SkASSERT(forcedGpuAPI == kNone_GrGLStandard || kAPIs[api].fStandard == forcedGpuAPI);
  
      const GrGLInterface* interface = NULL;
  
      for (; NULL == interface && api < apiLimit; ++api) {
          fDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
  
          EGLint majorVersion;
          EGLint minorVersion;
          eglInitialize(fDisplay, &majorVersion, &minorVersion);
  
  #if 0
          SkDebugf("VENDOR: %s\n", eglQueryString(fDisplay, EGL_VENDOR));
          SkDebugf("APIS: %s\n", eglQueryString(fDisplay, EGL_CLIENT_APIS));
          SkDebugf("VERSION: %s\n", eglQueryString(fDisplay, EGL_VERSION));
          SkDebugf("EXTENSIONS %s\n", eglQueryString(fDisplay, EGL_EXTENSIONS));
  #endif
  
          if (!eglBindAPI(kAPIs[api].fAPI)) {
              continue;
          }
  
          EGLint numConfigs;
          const EGLint configAttribs[] = {
              EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
              EGL_RENDERABLE_TYPE, kAPIs[api].fRenderableTypeBit,
              EGL_RED_SIZE, 8,
              EGL_GREEN_SIZE, 8,
              EGL_BLUE_SIZE, 8,
              EGL_ALPHA_SIZE, 8,
              EGL_NONE
          };
  
          EGLConfig surfaceConfig;
          if (!eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs)) {
              SkDebugf("eglChooseConfig failed. EGL Error: 0x%08x\n", eglGetError());
              continue;
          }
  
          fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, kAPIs[api].fContextAttribs);
          if (EGL_NO_CONTEXT == fContext) {
              SkDebugf("eglCreateContext failed.  EGL Error: 0x%08x\n", eglGetError());
              continue;
          }
  
          static const EGLint kSurfaceAttribs[] = {
              EGL_WIDTH, 1,
              EGL_HEIGHT, 1,
              EGL_NONE
          };
  
          fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, kSurfaceAttribs);
          if (EGL_NO_SURFACE == fSurface) {
              SkDebugf("eglCreatePbufferSurface failed. EGL Error: 0x%08x\n", eglGetError());
              this->destroyGLContext();
              continue;
          }
  
          if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
              SkDebugf("eglMakeCurrent failed.  EGL Error: 0x%08x\n", eglGetError());
              this->destroyGLContext();
              continue;
          }
  
          interface = GrGLCreateNativeInterface();
          if (NULL == interface) {
              SkDebugf("Failed to create gl interface.\n");
              this->destroyGLContext();
              continue;
          }
  
          if (!interface->validate()) {
              interface->unref();
              interface = NULL;
              this->destroyGLContext();
          }
      }
  
      return interface;
  }
  
  void SkNativeGLContext::makeCurrent() const {
      if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
          SkDebugf("Could not set the context.\n");
      }
  }
  
  void SkNativeGLContext::swapBuffers() const {
      if (!eglSwapBuffers(fDisplay, fSurface)) {
          SkDebugf("Could not complete eglSwapBuffers.\n");
      }
  }
  