1/*
2 * Copyright (C) 2013 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 "EGLHelper.h"
28
29#if USE(EGL)
30
31#include <opengl/GLPlatformContext.h>
32
33#if PLATFORM(X11)
34#include "X11Helper.h"
35#endif
36
37namespace WebCore {
38
39#if PLATFORM(X11)
40typedef X11Helper NativeWrapper;
41typedef Display NativeSharedDisplay;
42#else
43typedef void NativeSharedDisplay;
44#endif
45
46static PFNEGLCREATEIMAGEKHRPROC eglCreateImageKHR = 0;
47static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImageKHR = 0;
48static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2DOES = 0;
49
50struct EGLDisplayConnection {
51
52    EGLDisplayConnection(NativeSharedDisplay* display = 0)
53    {
54        if (display)
55            m_eglDisplay = eglGetDisplay(reinterpret_cast<EGLNativeDisplayType>(display));
56        else
57            m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
58
59        if (m_eglDisplay == EGL_NO_DISPLAY) {
60            LOG_ERROR("EGLDisplay Initialization failed.");
61            return;
62        }
63
64        EGLBoolean success;
65        success = eglInitialize(m_eglDisplay, 0, 0);
66
67        if (success != EGL_TRUE) {
68            LOG_ERROR("EGLInitialization failed.");
69            terminate();
70            return;
71        }
72
73        success = eglBindAPI(eglAPIVersion);
74
75        if (success != EGL_TRUE) {
76            LOG_ERROR("Failed to set EGL API(%d).", eglGetError());
77            terminate();
78            return;
79        }
80    }
81
82    ~EGLDisplayConnection()
83    {
84        terminate();
85    }
86
87    EGLDisplay display() { return m_eglDisplay; }
88
89private:
90    void terminate()
91    {
92        if (m_eglDisplay == EGL_NO_DISPLAY)
93            return;
94
95        eglTerminate(m_eglDisplay);
96        m_eglDisplay = EGL_NO_DISPLAY;
97    }
98
99    EGLDisplay m_eglDisplay;
100};
101
102PlatformDisplay EGLHelper::eglDisplay()
103{
104    // Display connection will only be broken at program shutdown.
105#if PLATFORM(X11)
106    static EGLDisplayConnection displayConnection(NativeWrapper::nativeDisplay());
107#else
108    static EGLDisplayConnection displayConnection;
109#endif
110    return displayConnection.display();
111}
112
113PlatformDisplay EGLHelper::currentDisplay()
114{
115    EGLDisplay display = eglGetCurrentDisplay();
116
117    if (display == EGL_NO_DISPLAY)
118        display = EGLHelper::eglDisplay();
119
120    return display;
121}
122
123void EGLHelper::resolveEGLBindings()
124{
125    static bool initialized = false;
126
127    if (initialized)
128        return;
129
130    initialized = true;
131
132    EGLDisplay display = currentDisplay();
133
134    if (display == EGL_NO_DISPLAY)
135        return;
136
137    if (GLPlatformContext::supportsEGLExtension(display, "EGL_KHR_image") && GLPlatformContext::supportsEGLExtension(display, "EGL_KHR_image_pixmap") && GLPlatformContext::supportsGLExtension("GL_OES_EGL_image")) {
138        eglCreateImageKHR = (PFNEGLCREATEIMAGEKHRPROC) eglGetProcAddress("eglCreateImageKHR");
139        eglDestroyImageKHR = (PFNEGLDESTROYIMAGEKHRPROC) eglGetProcAddress("eglDestroyImageKHR");
140        eglImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
141    }
142}
143
144void EGLHelper::createEGLImage(EGLImageKHR* image, GLenum target, const EGLClientBuffer clientBuffer, const EGLint attributes[])
145{
146    EGLDisplay display = currentDisplay();
147
148    if (display == EGL_NO_DISPLAY)
149        return;
150
151    EGLImageKHR tempHandle = EGL_NO_IMAGE_KHR;
152
153    if (eglCreateImageKHR && eglImageTargetTexture2DOES && eglDestroyImageKHR)
154        tempHandle = eglCreateImageKHR(display, EGL_NO_CONTEXT, target, clientBuffer, attributes);
155
156    *image = tempHandle;
157}
158
159void EGLHelper::destroyEGLImage(const EGLImageKHR image)
160{
161    EGLDisplay display = currentDisplay();
162
163    if (display == EGL_NO_DISPLAY)
164        return;
165
166    if (eglDestroyImageKHR)
167        eglDestroyImageKHR(display, image);
168}
169
170void EGLHelper::imageTargetTexture2DOES(const EGLImageKHR image)
171{
172    eglImageTargetTexture2DOES(GL_TEXTURE_2D, static_cast<GLeglImageOES>(image));
173}
174
175}
176#endif
177