1d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
2d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com/*
3d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com * Copyright 2012 Google Inc.
4d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com *
5d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com * Use of this source code is governed by a BSD-style license that can be
6d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com * found in the LICENSE file.
7d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com */
8d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
9e4545210c950f98d9fa20f51bc1be6c5591534bddjsollen#include "gl/angle/SkANGLEGLContext.h"
10d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
1193276c683d383142dfad31a01c6fdb1c810b6c1fbsalomon#include <EGL/egl.h>
1293276c683d383142dfad31a01c6fdb1c810b6c1fbsalomon
1342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon#define EGL_PLATFORM_ANGLE_ANGLE                0x3201
1442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon#define EGL_PLATFORM_ANGLE_TYPE_ANGLE           0x3202
1542380174ca509e78ab932fa8c6dae953e1eaaa5absalomon#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE      0x3206
1642380174ca509e78ab932fa8c6dae953e1eaaa5absalomon#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE     0x3207
1742380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
1893276c683d383142dfad31a01c6fdb1c810b6c1fbsalomonvoid* SkANGLEGLContext::GetD3DEGLDisplay(void* nativeDisplay) {
1942380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
2042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    typedef EGLDisplay (*EGLGetPlatformDisplayEXT)(EGLenum platform,
2142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon                                                   void *native_display,
2242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon                                                   const EGLint *attrib_list);
2342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    EGLGetPlatformDisplayEXT eglGetPlatformDisplayEXT;
2442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    eglGetPlatformDisplayEXT =
2542380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        (EGLGetPlatformDisplayEXT) eglGetProcAddress("eglGetPlatformDisplayEXT");
2642380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
2742380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    if (!eglGetPlatformDisplayEXT) {
2893276c683d383142dfad31a01c6fdb1c810b6c1fbsalomon        return eglGetDisplay(static_cast<EGLNativeDisplayType>(nativeDisplay));
2942380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    }
3042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
3142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    // Try for an ANGLE D3D11 context, fall back to D3D9.
3242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    EGLint attribs[2][3] = {
3342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        {
3442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_PLATFORM_ANGLE_TYPE_ANGLE,
3542380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
3642380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_NONE
3742380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        },
3842380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        {
3942380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_PLATFORM_ANGLE_TYPE_ANGLE,
4042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE,
4142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon            EGL_NONE
4242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        }
4342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    };
4442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
4542380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    EGLDisplay display = EGL_NO_DISPLAY;
4642380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    for (int i = 0; i < 2 && display == EGL_NO_DISPLAY; ++i) {
4742380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        display = eglGetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE,
4842380174ca509e78ab932fa8c6dae953e1eaaa5absalomon                                            nativeDisplay, attribs[i]);
4942380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    }
5042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    return display;
5142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon}
5242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
53d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.comSkANGLEGLContext::SkANGLEGLContext()
54d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    : fContext(EGL_NO_CONTEXT)
55d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    , fDisplay(EGL_NO_DISPLAY)
56d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    , fSurface(EGL_NO_SURFACE) {
57d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
58d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    EGLint numConfigs;
59d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    static const EGLint configAttribs[] = {
60d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_SURFACE_TYPE, EGL_PBUFFER_BIT,
61d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
62d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_RED_SIZE, 8,
63d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_GREEN_SIZE, 8,
64d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_BLUE_SIZE, 8,
65d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_ALPHA_SIZE, 8,
66d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_NONE
67d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    };
68d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
6942380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    fDisplay = GetD3DEGLDisplay(EGL_DEFAULT_DISPLAY);
7042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    if (EGL_NO_DISPLAY == fDisplay) {
7142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        SkDebugf("Could not create EGL display!");
7242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        return;
7342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    }
7442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
7542380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    EGLint majorVersion;
7642380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    EGLint minorVersion;
7742380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    eglInitialize(fDisplay, &majorVersion, &minorVersion);
7842380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
79d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    EGLConfig surfaceConfig;
80d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    eglChooseConfig(fDisplay, configAttribs, &surfaceConfig, 1, &numConfigs);
81d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
82d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    static const EGLint contextAttribs[] = {
83d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_CONTEXT_CLIENT_VERSION, 2,
84d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        EGL_NONE
85d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    };
86d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    fContext = eglCreateContext(fDisplay, surfaceConfig, NULL, contextAttribs);
87d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
88d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
89d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    static const EGLint surfaceAttribs[] = {
9042380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        EGL_WIDTH, 1,
9142380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        EGL_HEIGHT, 1,
9242380174ca509e78ab932fa8c6dae953e1eaaa5absalomon        EGL_NONE
9342380174ca509e78ab932fa8c6dae953e1eaaa5absalomon    };
9442380174ca509e78ab932fa8c6dae953e1eaaa5absalomon
95d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    fSurface = eglCreatePbufferSurface(fDisplay, surfaceConfig, surfaceAttribs);
96d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
97d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    eglMakeCurrent(fDisplay, fSurface, fSurface, fContext);
98d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
9930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    fGL.reset(GrGLCreateANGLEInterface());
10030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    if (NULL == fGL.get()) {
101d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        SkDebugf("Could not create ANGLE GL interface!\n");
102d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        this->destroyGLContext();
10330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        return;
10430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    }
10530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    if (!fGL->validate()) {
10630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        SkDebugf("Could not validate ANGLE GL interface!\n");
10730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        this->destroyGLContext();
10830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        return;
109d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    }
11030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen}
111d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
11230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenSkANGLEGLContext::~SkANGLEGLContext() {
11330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    this->destroyGLContext();
11430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen}
11530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
11630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunenvoid SkANGLEGLContext::destroyGLContext() {
11730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    fGL.reset(NULL);
11830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    if (fDisplay) {
11930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        eglMakeCurrent(fDisplay, 0, 0, 0);
12030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
12130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        if (fContext) {
12230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            eglDestroyContext(fDisplay, fContext);
12330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            fContext = EGL_NO_CONTEXT;
12430bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        }
12530bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
12630bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        if (fSurface) {
12730bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            eglDestroySurface(fDisplay, fSurface);
12830bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen            fSurface = EGL_NO_SURFACE;
12930bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        }
13030bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen
13130bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        //TODO should we close the display?
13230bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen        fDisplay = EGL_NO_DISPLAY;
13330bc88ccd524c0372fd2f8f79190ea4b81685bebkkinnunen    }
134d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com}
135d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com
136d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.comvoid SkANGLEGLContext::makeCurrent() const {
137d5c8fe6f344e1b141390c733017656f6fb3f5f63robertphillips@google.com    if (!eglMakeCurrent(fDisplay, fSurface, fSurface, fContext)) {
138d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com        SkDebugf("Could not set the context.\n");
139d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com    }
140d3b9fbbc48c13a1b2a664cf7e01374a44c201f51robertphillips@google.com}
141c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com
142c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.comvoid SkANGLEGLContext::swapBuffers() const {
143c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com    if (!eglSwapBuffers(fDisplay, fSurface)) {
144c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com        SkDebugf("Could not complete eglSwapBuffers.\n");
145c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com    }
146c9542ca3d00878a18a57af80037060d6374d5650djsollen@google.com}
147