| Index: src/gpu/gl/angle/SkANGLEGLContext.cpp
 | 
| diff --git a/src/gpu/gl/angle/SkANGLEGLContext.cpp b/src/gpu/gl/angle/SkANGLEGLContext.cpp
 | 
| new file mode 100644
 | 
| index 0000000000000000000000000000000000000000..c6ea44381f5e3ced522f5ae40bdbc7340a2ad515
 | 
| --- /dev/null
 | 
| +++ b/src/gpu/gl/angle/SkANGLEGLContext.cpp
 | 
| @@ -0,0 +1,229 @@
 | 
| +/*
 | 
| + * Copyright 2012 Google Inc.
 | 
| + *
 | 
| + * Use of this source code is governed by a BSD-style license that can be
 | 
| + * found in the LICENSE file.
 | 
| + */
 | 
| +
 | 
| +#include "gl/angle/SkANGLEGLContext.h"
 | 
| +
 | 
| +#include <EGL/egl.h>
 | 
| +#include <EGL/eglext.h>
 | 
| +
 | 
| +#include "gl/GrGLDefines.h"
 | 
| +#include "gl/GrGLUtil.h"
 | 
| +
 | 
| +#define EGL_PLATFORM_ANGLE_ANGLE                0x3202
 | 
| +#define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3203
 | 
| +#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3207
 | 
| +#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3208
 | 
| +#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE    0x320D
 | 
| +
 | 
| +void* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay, bool useGLBackend) {
 | 
| +    PFNEGLGETPLATFORMDISPLAYEXTPROC eglGetPlatformDisplayEXT;
 | 
| +    eglGetPlatformDisplayEXT =
 | 
| +        (PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
 | 
| +
 | 
| +    if (!eglGetPlatformDisplayEXT) {
 | 
| +        return eglGetDisplay(static_cast<EGLNativeDisplayType>(nativeDisplay));
 | 
| +    }
 | 
| +
 | 
| +    EGLDisplay display = EGL_NO_DISPLAY;
 | 
| +    if (useGLBackend) {
 | 
| +        // Try for an ANGLE D3D11 context, fall back to D3D9.
 | 
| +        EGLint attribs[3] = {
 | 
| +              EGL_PLATFORM_ANGLE_TYPE_ANGLE,
 | 
| +              EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
 | 
| +              EGL_NONE
 | 
| +        };
 | 
| +        display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, nativeDisplay, attribs);
 | 
| +    } else {
 | 
| +        // Try for an ANGLE D3D11 context, fall back to D3D9, and finally GL.
 | 
| +        EGLint attribs[3][3] = {
 | 
| +            {
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_ANGLE,
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
 | 
| +                EGL_NONE
 | 
| +            },
 | 
| +            {
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_ANGLE,
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
 | 
| +                EGL_NONE
 | 
| +            },
 | 
| +            {
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_ANGLE,
 | 
| +                EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE,
 | 
| +                EGL_NONE
 | 
| +            }
 | 
| +        };
 | 
| +        for (int i = 0; i < 3 && display == EGL_NO_DISPLAY; ++i) {
 | 
| +            display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,nativeDisplay, attribs[i]);
 | 
| +        }
 | 
| +    }
 | 
| +    return display;
 | 
| +}
 | 
| +
 | 
| +SkANGLEGLContext::SkANGLEGLContext(bool useGLBackend)
 | 
| +    : fContext(EGL_NO_CONTEXT)
 | 
| +    , fDisplay(EGL_NO_DISPLAY)
 | 
| +    , fSurface(EGL_NO_SURFACE) {
 | 
| +
 | 
| +    EGLint numConfigs;
 | 
| +    static const EGLint configAttribs[] = {
 | 
| +        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
 | 
| +        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
 | 
| +        EGL_RED_SIZE, 8,
 | 
| +        EGL_GREEN_SIZE, 8,
 | 
| +        EGL_BLUE_SIZE, 8,
 | 
| +        EGL_ALPHA_SIZE, 8,
 | 
| +        EGL_NONE
 | 
| +    };
 | 
| +
 | 
| +    fIsGLBackend = useGLBackend;
 | 
| +    fDisplay = GetD3DEGLDisplay(EGL_DEFAULT_DISPLAY, useGLBackend);
 | 
| +    if (EGL_NO_DISPLAY == fDisplay) {
 | 
| +        SkDebugf("Could not create EGL display!");
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    EGLint majorVersion;
 | 
| +    EGLint minorVersion;
 | 
| +    eglInitialize(fDisplay, &majorVersion, &minorVersion);
 | 
| +
 | 
| +    EGLConfig surfaceConfig;
 | 
| +    eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);
 | 
| +
 | 
| +    static const EGLint contextAttribs[] = {
 | 
| +        EGL_CONTEXT_CLIENT_VERSION, 2,
 | 
| +        EGL_NONE
 | 
| +    };
 | 
| +    fContext = eglCreateContext(fDisplay, surfaceConfig, nullptr, contextAttribs);
 | 
| +
 | 
| +
 | 
| +    static const EGLint surfaceAttribs[] = {
 | 
| +        EGL_WIDTH, 1,
 | 
| +        EGL_HEIGHT, 1,
 | 
| +        EGL_NONE
 | 
| +    };
 | 
| +
 | 
| +    fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
 | 
| +
 | 
| +    eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
 | 
| +
 | 
| +    SkAutoTUnref<const GrGLInterface> gl(GrGLCreateANGLEInterface());
 | 
| +    if (nullptr == gl.get()) {
 | 
| +        SkDebugf("Could not create ANGLE GL interface!\n");
 | 
| +        this->destroyGLContext();
 | 
| +        return;
 | 
| +    }
 | 
| +    if (!gl->validate()) {
 | 
| +        SkDebugf("Could not validate ANGLE GL interface!\n");
 | 
| +        this->destroyGLContext();
 | 
| +        return;
 | 
| +    }
 | 
| +
 | 
| +    this->init(gl.release());
 | 
| +}
 | 
| +
 | 
| +SkANGLEGLContext::~SkANGLEGLContext() {
 | 
| +    this->teardown();
 | 
| +    this->destroyGLContext();
 | 
| +}
 | 
| +
 | 
| +GrEGLImage SkANGLEGLContext::texture2DToEGLImage(GrGLuint texID) const {
 | 
| +    if (!this->gl()->hasExtension("EGL_KHR_gl_texture_2D_image")) {
 | 
| +        return GR_EGL_NO_IMAGE;
 | 
| +    }
 | 
| +    GrEGLImage img;
 | 
| +    GrEGLint attribs[] = { GR_EGL_GL_TEXTURE_LEVEL, 0,
 | 
| +                           GR_EGL_IMAGE_PRESERVED, GR_EGL_TRUE,
 | 
| +                           GR_EGL_NONE };
 | 
| +    // 64 bit cast is to shut Visual C++ up about casting 32 bit value to a pointer.
 | 
| +    GrEGLClientBuffer clientBuffer = reinterpret_cast<GrEGLClientBuffer>((uint64_t)texID);
 | 
| +    GR_GL_CALL_RET(this->gl(), img,
 | 
| +                   EGLCreateImage(fDisplay, fContext, GR_EGL_GL_TEXTURE_2D, clientBuffer,
 | 
| +                                  attribs));
 | 
| +    return img;
 | 
| +}
 | 
| +
 | 
| +void SkANGLEGLContext::destroyEGLImage(GrEGLImage image) const {
 | 
| +    GR_GL_CALL(this->gl(), EGLDestroyImage(fDisplay, image));
 | 
| +}
 | 
| +
 | 
| +GrGLuint SkANGLEGLContext::eglImageToExternalTexture(GrEGLImage image) const {
 | 
| +    GrGLClearErr(this->gl());
 | 
| +    if (!this->gl()->hasExtension("GL_OES_EGL_image_external")) {
 | 
| +        return 0;
 | 
| +    }
 | 
| +    typedef GrGLvoid (*EGLImageTargetTexture2DProc)(GrGLenum, GrGLeglImage);
 | 
| +
 | 
| +    EGLImageTargetTexture2DProc glEGLImageTargetTexture2D =
 | 
| +        (EGLImageTargetTexture2DProc)eglGetProcAddress("glEGLImageTargetTexture2DOES");
 | 
| +    if (!glEGLImageTargetTexture2D) {
 | 
| +        return 0;
 | 
| +    }
 | 
| +    GrGLuint texID;
 | 
| +    GR_GL_CALL(this->gl(), GenTextures(1, &texID));
 | 
| +    if (!texID) {
 | 
| +        return 0;
 | 
| +    }
 | 
| +    GR_GL_CALL(this->gl(), BindTexture(GR_GL_TEXTURE_EXTERNAL, texID));
 | 
| +    if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
 | 
| +        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
 | 
| +        return 0;
 | 
| +    }
 | 
| +    glEGLImageTargetTexture2D(GR_GL_TEXTURE_EXTERNAL, image);
 | 
| +    if (GR_GL_GET_ERROR(this->gl()) != GR_GL_NO_ERROR) {
 | 
| +        GR_GL_CALL(this->gl(), DeleteTextures(1, &texID));
 | 
| +        return 0;
 | 
| +    }
 | 
| +    return texID;
 | 
| +}
 | 
| +
 | 
| +SkGLContext* SkANGLEGLContext::createNew() const {
 | 
| +#ifdef SK_BUILD_FOR_WIN
 | 
| +    SkGLContext* ctx = fIsGLBackend ? SkANGLEGLContext::CreateOpenGL()
 | 
| +                                    : SkANGLEGLContext::CreateDirectX();
 | 
| +#else
 | 
| +    SkGLContext* ctx = SkANGLEGLContext::CreateOpenGL();
 | 
| +#endif
 | 
| +    if (ctx) {
 | 
| +        ctx->makeCurrent();
 | 
| +    }
 | 
| +    return ctx;
 | 
| +}
 | 
| +
 | 
| +void SkANGLEGLContext::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;
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void SkANGLEGLContext::onPlatformMakeCurrent() const {
 | 
| +    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
 | 
| +        SkDebugf("Could not set the context.\n");
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +void SkANGLEGLContext::onPlatformSwapBuffers() const {
 | 
| +    if (!eglSwapBuffers(fDisplay, fSurface)) {
 | 
| +        SkDebugf("Could not complete eglSwapBuffers.\n");
 | 
| +    }
 | 
| +}
 | 
| +
 | 
| +GrGLFuncPtr SkANGLEGLContext::onPlatformGetProcAddress(const char* name) const {
 | 
| +    return eglGetProcAddress(name);
 | 
| +}
 | 
| 
 |