47cf5d1353eb2d3beffd8eb83c261e758ee42e97
[WebKit-https.git] / Source / WebCore / platform / graphics / nicosia / texmap / NicosiaGC3DANGLELayer.cpp
1 /*
2  * Copyright (C) 2018 Metrological Group B.V.
3  * Copyright (C) 2018, 2019 Igalia S.L.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above
12  *    copyright notice, this list of conditions and the following
13  *    disclaimer in the documentation and/or other materials provided
14  *    with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "NicosiaGC3DANGLELayer.h"
31
32 #if USE(NICOSIA) && USE(TEXTURE_MAPPER)
33
34 #include "Logging.h"
35
36 #define EGL_EGL_PROTOTYPES 0
37 // Skip the inclusion of ANGLE's explicit context entry points for now.
38 #define GL_ANGLE_explicit_context
39 #define GL_ANGLE_explicit_context_gles1
40 typedef void* GLeglContext;
41 #include <ANGLE/egl.h>
42 #include <ANGLE/eglext.h>
43 #include <ANGLE/eglext_angle.h>
44 #include <ANGLE/entry_points_egl.h>
45 #include <ANGLE/entry_points_gles_2_0_autogen.h>
46 #include <ANGLE/entry_points_gles_ext_autogen.h>
47 #include <ANGLE/gl2ext.h>
48 #include <ANGLE/gl2ext_angle.h>
49
50 namespace Nicosia {
51
52 using namespace WebCore;
53
54 const char* GC3DANGLELayer::ANGLEContext::errorString(int statusCode)
55 {
56     static_assert(sizeof(int) >= sizeof(EGLint), "EGLint must not be wider than int");
57     switch (statusCode) {
58 #define CASE_RETURN_STRING(name) case name: return #name
59         // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetError.xhtml
60         CASE_RETURN_STRING(EGL_SUCCESS);
61         CASE_RETURN_STRING(EGL_NOT_INITIALIZED);
62         CASE_RETURN_STRING(EGL_BAD_ACCESS);
63         CASE_RETURN_STRING(EGL_BAD_ALLOC);
64         CASE_RETURN_STRING(EGL_BAD_ATTRIBUTE);
65         CASE_RETURN_STRING(EGL_BAD_CONTEXT);
66         CASE_RETURN_STRING(EGL_BAD_CONFIG);
67         CASE_RETURN_STRING(EGL_BAD_CURRENT_SURFACE);
68         CASE_RETURN_STRING(EGL_BAD_DISPLAY);
69         CASE_RETURN_STRING(EGL_BAD_SURFACE);
70         CASE_RETURN_STRING(EGL_BAD_MATCH);
71         CASE_RETURN_STRING(EGL_BAD_PARAMETER);
72         CASE_RETURN_STRING(EGL_BAD_NATIVE_PIXMAP);
73         CASE_RETURN_STRING(EGL_BAD_NATIVE_WINDOW);
74         CASE_RETURN_STRING(EGL_CONTEXT_LOST);
75 #undef CASE_RETURN_STRING
76     default: return "Unknown EGL error";
77     }
78 }
79
80 const char* GC3DANGLELayer::ANGLEContext::lastErrorString()
81 {
82     return errorString(EGL_GetError());
83 }
84
85 std::unique_ptr<GC3DANGLELayer::ANGLEContext> GC3DANGLELayer::ANGLEContext::createContext()
86 {
87     EGLDisplay display = EGL_GetDisplay(EGL_DEFAULT_DISPLAY);
88     if (display == EGL_NO_DISPLAY)
89         return nullptr;
90
91     EGLint majorVersion, minorVersion;
92     if (EGL_Initialize(display, &majorVersion, &minorVersion) == EGL_FALSE) {
93         LOG(WebGL, "EGLDisplay Initialization failed.");
94         return nullptr;
95     }
96     LOG(WebGL, "ANGLE initialised Major: %d Minor: %d", majorVersion, minorVersion);
97
98     const char* displayExtensions = EGL_QueryString(display, EGL_EXTENSIONS);
99     LOG(WebGL, "Extensions: %s", displayExtensions);
100
101     EGLConfig config;
102     EGLint configAttributes[] = {
103         EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
104         EGL_RED_SIZE, 8,
105         EGL_GREEN_SIZE, 8,
106         EGL_BLUE_SIZE, 8,
107         EGL_ALPHA_SIZE, 8,
108         EGL_NONE
109     };
110     EGLint numberConfigsReturned = 0;
111     EGL_ChooseConfig(display, configAttributes, &config, 1, &numberConfigsReturned);
112     if (numberConfigsReturned != 1) {
113         LOG(WebGL, "EGLConfig Initialization failed.");
114         return nullptr;
115     }
116     LOG(WebGL, "Got EGLConfig");
117
118     EGL_BindAPI(EGL_OPENGL_ES_API);
119     if (EGL_GetError() != EGL_SUCCESS) {
120         LOG(WebGL, "Unable to bind to OPENGL_ES_API");
121         return nullptr;
122     }
123
124     std::vector<EGLint> contextAttributes;
125     contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
126     contextAttributes.push_back(2);
127     contextAttributes.push_back(EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE);
128     contextAttributes.push_back(EGL_TRUE);
129     contextAttributes.push_back(EGL_EXTENSIONS_ENABLED_ANGLE);
130     contextAttributes.push_back(EGL_TRUE);
131     if (strstr(displayExtensions, "EGL_ANGLE_power_preference")) {
132         contextAttributes.push_back(EGL_POWER_PREFERENCE_ANGLE);
133         // EGL_LOW_POWER_ANGLE is the default. Change to
134         // EGL_HIGH_POWER_ANGLE if desired.
135         contextAttributes.push_back(EGL_LOW_POWER_ANGLE);
136     }
137     contextAttributes.push_back(EGL_NONE);
138
139     EGLContext context = EGL_CreateContext(display, config, EGL_NO_CONTEXT, contextAttributes.data());
140     if (context == EGL_NO_CONTEXT) {
141         LOG(WebGL, "EGLContext Initialization failed.");
142         return nullptr;
143     }
144     LOG(WebGL, "Got EGLContext");
145
146     return std::unique_ptr<ANGLEContext>(new ANGLEContext(display, context, EGL_NO_SURFACE));
147 }
148
149 GC3DANGLELayer::ANGLEContext::ANGLEContext(EGLDisplay display, EGLContext context, EGLSurface surface)
150     : m_display(display)
151     , m_context(context)
152     , m_surface(surface)
153 {
154 }
155
156 GC3DANGLELayer::ANGLEContext::~ANGLEContext()
157 {
158     if (m_context) {
159         gl::BindFramebuffer(GL_FRAMEBUFFER, 0);
160         EGL_MakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
161         EGL_DestroyContext(m_display, m_context);
162     }
163
164     if (m_surface)
165         EGL_DestroySurface(m_display, m_surface);
166 }
167
168 bool GC3DANGLELayer::ANGLEContext::makeContextCurrent()
169 {
170     ASSERT(m_context);
171
172     if (EGL_GetCurrentContext() != m_context)
173         return EGL_MakeCurrent(m_display, m_surface, m_surface, m_context);
174     return true;
175 }
176
177 PlatformGraphicsContext3D GC3DANGLELayer::ANGLEContext::platformContext()
178 {
179     return m_context;
180 }
181
182 GC3DANGLELayer::GC3DANGLELayer(GraphicsContext3D& context, GraphicsContext3D::RenderStyle renderStyle)
183     : GC3DLayer(context)
184 {
185     switch (renderStyle) {
186     case GraphicsContext3D::RenderOffscreen:
187         m_angleContext = ANGLEContext::createContext();
188         break;
189     case GraphicsContext3D::RenderDirectlyToHostWindow:
190         ASSERT_NOT_REACHED();
191         break;
192     }
193 }
194
195 GC3DANGLELayer::~GC3DANGLELayer()
196 {
197 }
198
199 bool GC3DANGLELayer::makeContextCurrent()
200 {
201     ASSERT(m_angleContext);
202     return m_angleContext->makeContextCurrent();
203
204 }
205
206 PlatformGraphicsContext3D GC3DANGLELayer::platformContext()
207 {
208     ASSERT(m_angleContext);
209     return m_angleContext->platformContext();
210 }
211
212 } // namespace Nicosia
213
214 #endif // USE(NICOSIA) && USE(TEXTURE_MAPPER)