1/*
2 * Copyright (C) 2012 Intel Corporation. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27#include "EGLContext.h"
28
29#if USE(EGL)
30
31#include <wtf/text/WTFString.h>
32
33namespace WebCore {
34
35static const EGLint contextAttributes[] = {
36#if USE(OPENGL_ES_2)
37    EGL_CONTEXT_CLIENT_VERSION, 2,
38#endif
39    EGL_NONE
40};
41
42static const EGLint contextRobustnessAttributes[] = {
43#if USE(OPENGL_ES_2)
44    EGL_CONTEXT_CLIENT_VERSION, 2,
45#endif
46    EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT,
47    EGL_LOSE_CONTEXT_ON_RESET_EXT,
48    EGL_NONE
49};
50
51static bool isRobustnessExtSupported(EGLDisplay display)
52{
53    static bool didQueryForRobustnessExtension = false;
54    static bool isRobustnessExtensionSupported = false;
55
56    if (!didQueryForRobustnessExtension) {
57        didQueryForRobustnessExtension = true;
58        isRobustnessExtensionSupported = GLPlatformContext::supportsEGLExtension(display, "EGL_EXT_create_context_robustness");
59    }
60
61    return isRobustnessExtensionSupported;
62}
63
64EGLOffScreenContext::EGLOffScreenContext()
65    : GLPlatformContext()
66    , m_display(0)
67{
68}
69
70bool EGLOffScreenContext::initialize(GLPlatformSurface* surface, PlatformContext sharedContext)
71{
72    if (!surface)
73        return false;
74
75    if (!eglBindAPI(eglAPIVersion)) {
76        LOG_ERROR("Failed to set EGL API(%d).", eglGetError());
77        return false;
78    }
79
80    m_display = surface->sharedDisplay();
81    if (!m_display)
82        return false;
83
84    EGLConfig config = surface->configuration();
85    if (!config)
86        return false;
87
88    if (isRobustnessExtSupported(m_display))
89        m_contextHandle = eglCreateContext(m_display, config, sharedContext, contextRobustnessAttributes);
90
91    if (m_contextHandle != EGL_NO_CONTEXT) {
92        // The EGL_EXT_create_context_robustness spec requires that a context created with
93        // EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT bit set must also support GL_EXT_robustness or
94        // a version of OpenGL incorporating equivalent functionality.
95        // The spec also defines similar requirements for attribute EGL_LOSE_CONTEXT_ON_RESET_EXT.
96        if (platformMakeCurrent(surface) && (GLPlatformContext::supportsGLExtension("GL_EXT_robustness")))
97            m_resetLostContext = true;
98        else
99            eglDestroyContext(m_display, m_contextHandle);
100    }
101
102    if (m_contextHandle == EGL_NO_CONTEXT) {
103        m_contextHandle = eglCreateContext(m_display, config, sharedContext, contextAttributes);
104        if (!platformMakeCurrent(surface))
105            eglDestroyContext(m_display, m_contextHandle);
106    }
107
108    if (m_contextHandle != EGL_NO_CONTEXT)
109        return true;
110
111    return false;
112}
113
114EGLOffScreenContext::~EGLOffScreenContext()
115{
116}
117
118bool EGLOffScreenContext::isCurrentContext() const
119{
120    return m_contextHandle == eglGetCurrentContext();
121}
122
123bool EGLOffScreenContext::platformMakeCurrent(GLPlatformSurface* surface)
124{
125    if (!eglMakeCurrent(m_display, surface->drawable(), surface->drawable(), m_contextHandle)) {
126        LOG_ERROR("Failed to make context current(%d).", eglGetError());
127
128        if (m_resetLostContext && eglGetError() == EGL_CONTEXT_LOST) {
129            LOG_ERROR("Lost current context.");
130            m_contextLost = true;
131        }
132
133        return false;
134    }
135
136    return true;
137}
138
139void EGLOffScreenContext::platformReleaseCurrent()
140{
141    eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
142}
143
144void EGLOffScreenContext::freeResources()
145{
146    if (m_contextHandle == EGL_NO_CONTEXT)
147        return;
148
149    eglDestroyContext(m_display, m_contextHandle);
150    m_contextHandle = EGL_NO_CONTEXT;
151    m_display = 0;
152}
153
154void EGLOffScreenContext::destroy()
155{
156    GLPlatformContext::destroy();
157    freeResources();
158}
159
160}
161
162#endif
163