4ecba7c229ea33bc5664e4268d4c60cb6ad6b387
[platform/framework/web/webkit-efl.git] / Source / WebCore / platform / graphics / surfaces / egl / EGLConfigSelector.cpp
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 "EGLConfigSelector.h"
28
29 #if USE(EGL) || ENABLE(TIZEN_CANVAS_GRAPHICS_SURFACE)
30
31 #include "EGLHelper.h"
32 #include <wtf/HashMap.h>
33
34 namespace WebCore {
35
36 #if !defined(EGL_FORMAT_RGBA_8888_EXACT_KHR)
37 #define EGL_FORMAT_RGBA_8888_EXACT_KHR 0x30C2
38 #endif
39
40 #if !defined(EGL_FORMAT_RGBA_8888_KHR)
41 #define EGL_FORMAT_RGBA_8888_KHR 0x30C3
42 #endif
43
44 class EGLConfigPool {
45 public:
46     static inline EGLConfigPool& getInstance()
47     {
48         static EGLConfigPool eglConfigPool;
49         return eglConfigPool;
50     }
51     virtual ~EGLConfigPool();
52     EGLConfig pixmapContextConfig(GLPlatformSurface::SurfaceAttributes);
53     EGLConfig surfaceContextConfig(GLPlatformSurface::SurfaceAttributes);
54 private:
55     EGLConfigPool(void);
56     EGLConfig createConfig(EGLint expectedSurfaceType, GLPlatformSurface::SurfaceAttributes);
57     typedef HashMap<GLPlatformSurface::SurfaceAttributes, EGLConfig> PixmapConfigMap;
58     PixmapConfigMap m_pixmapConfigs;
59     typedef HashMap<GLPlatformSurface::SurfaceAttributes, EGLConfig> WindowConfigMap;
60     WindowConfigMap m_windowConfigs;
61 };
62
63 EGLConfigPool::EGLConfigPool()
64 {
65 }
66
67 EGLConfigPool::~EGLConfigPool()
68 {
69     m_windowConfigs.clear();
70     m_pixmapConfigs.clear();
71 }
72
73 EGLConfig EGLConfigPool::pixmapContextConfig(GLPlatformSurface::SurfaceAttributes attributes)
74 {
75     EGLConfig config = 0;
76     PixmapConfigMap::iterator it = m_pixmapConfigs.find(attributes);
77     if (it != m_pixmapConfigs.end()) {
78         config = it->second;
79         return config;
80     }
81
82     config = createConfig(attributes & GLPlatformSurface::Lockable ? EGL_PIXMAP_BIT | EGL_LOCK_SURFACE_BIT_KHR : EGL_PIXMAP_BIT, attributes);
83     if (config)
84         m_pixmapConfigs.add(attributes, config);
85
86     return config;
87 }
88
89 EGLConfig EGLConfigPool::surfaceContextConfig(GLPlatformSurface::SurfaceAttributes attributes)
90 {
91     EGLConfig config = 0;
92     WindowConfigMap::iterator it = m_windowConfigs.find(attributes);
93     if (it != m_windowConfigs.end()) {
94         config = it->second;
95         return config;
96     }
97
98     config = createConfig(attributes & GLPlatformSurface::Lockable ? EGL_WINDOW_BIT | EGL_LOCK_SURFACE_BIT_KHR : EGL_WINDOW_BIT, attributes);
99     if (config)
100         m_windowConfigs.add(attributes, config);
101
102     return config;
103 }
104
105 EGLConfig EGLConfigPool::createConfig(EGLint expectedSurfaceType, GLPlatformSurface::SurfaceAttributes attributes)
106 {
107     EGLDisplay display = EGLHelper::eglDisplay();
108     if (display == EGL_NO_DISPLAY)
109         return 0;
110
111     EGLint numConfigs;
112     eglGetConfigs(display, 0, 0, &numConfigs);
113
114     if (!numConfigs) {
115         LOG_ERROR("Failed to retrieve number of EGL configs.");
116         return 0;
117     }
118
119     EGLConfig configs[numConfigs];
120     eglGetConfigs(display, configs, numConfigs, &numConfigs);
121
122     if (!numConfigs) {
123         LOG_ERROR("Failed to retrieve any EGL configs.");
124         return 0;
125     }
126
127     EGLConfig config = 0;
128     EGLint alpha, surface, red, green, blue, renderType, stencil, depth, configAttribute, matchFormat, samples;
129     EGLint expectedAlpha = attributes & GLPlatformSurface::SupportAlpha ? 8 : 0;
130     EGLint expectedRed = 8;
131     EGLint expectedBlue = 8;
132     EGLint expectedGreen = 8;
133     EGLint expectedStencilSize = attributes & GLPlatformSurface::SupportStencil ? 8 : 0;
134     EGLint expectedDepthSize = attributes & GLPlatformSurface::SupportDepth ? 16 : 0;
135     EGLint expectedConfigAttribute = EGL_NONE;
136     EGLint expectedMatchFormat = EGL_NONE;
137     EGLint expectedSamples = attributes & GLPlatformSurface::SupportSamples ? 4 : 0;
138 #if USE(OPENGL_ES_2)
139     EGLint expectedRenderType = EGL_OPENGL_ES2_BIT;
140 #else
141     EGLint expectedRenderType = EGL_OPENGL_BIT;
142 #endif
143     static bool isVendorImagination = EGLHelper::isVendor("imagination");
144     static bool isVendorMesa = EGLHelper::isVendor("mesa");
145     static bool isVendorArm = EGLHelper::isVendor("arm");
146
147     if (isVendorMesa) {
148         expectedDepthSize = attributes & GLPlatformSurface::SupportDepth ? 24 : 0;
149         expectedStencilSize = attributes & GLPlatformSurface::SupportStencil ? 8 : 0;
150     }
151
152     if (!expectedAlpha && isVendorImagination)
153         expectedConfigAttribute = EGL_NON_CONFORMANT_CONFIG;
154
155     if (attributes & GLPlatformSurface::Lockable) {
156         if (isVendorImagination || isVendorArm)
157             matchFormat = EGL_FORMAT_RGBA_8888_EXACT_KHR;
158         else
159             matchFormat = EGL_FORMAT_RGBA_8888_KHR;
160     }
161
162     for (int i = 0; i < numConfigs; i++) {
163         EGLConfig tempConfig = configs[i];
164         eglGetConfigAttrib(display, tempConfig, EGL_RENDERABLE_TYPE, &renderType);
165         if (!(renderType & expectedRenderType))
166             continue;
167
168         if (expectedConfigAttribute != EGL_NONE) {
169             eglGetConfigAttrib(display, tempConfig, EGL_CONFIG_CAVEAT, &configAttribute);
170
171             if (expectedConfigAttribute != configAttribute) {
172                 LOG_ERROR("Expected config attribute didnt match. Checking next EGLConfig.");
173                 continue;
174             }
175         }
176
177         if (expectedMatchFormat != EGL_NONE) {
178             eglGetConfigAttrib(display, tempConfig, EGL_MATCH_FORMAT_KHR, &matchFormat);
179
180             if (expectedMatchFormat != matchFormat) {
181                 LOG_ERROR("ExpectedMatchFormat didnt match. Checking next EGLConfig.");
182                 continue;
183             }
184         }
185
186         eglGetConfigAttrib(display, tempConfig, EGL_ALPHA_SIZE, &alpha);
187
188         if (alpha != expectedAlpha) {
189             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "alpha", alpha, expectedAlpha);
190             continue;
191         }
192
193         eglGetConfigAttrib(display, tempConfig, EGL_RED_SIZE, &red);
194
195         if (red != expectedRed) {
196             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "red", red, expectedRed);
197             continue;
198         }
199
200         eglGetConfigAttrib(display, tempConfig, EGL_GREEN_SIZE, &green);
201
202         if (green != expectedGreen) {
203             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "Green", green, expectedGreen);
204             continue;
205         }
206
207         eglGetConfigAttrib(display, tempConfig, EGL_BLUE_SIZE, &blue);
208
209         if (blue != expectedBlue) {
210             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "Blue", blue, expectedBlue);
211             continue;
212         }
213
214         eglGetConfigAttrib(display, tempConfig, EGL_STENCIL_SIZE, &stencil);
215
216         if (stencil != expectedStencilSize) {
217             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "Stencil", stencil, expectedStencilSize);
218             continue;
219         }
220
221         eglGetConfigAttrib(display, tempConfig, EGL_DEPTH_SIZE, &depth);
222
223         if (depth != expectedDepthSize) {
224             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "Depth", depth, expectedDepthSize);
225             continue;
226         }
227
228         eglGetConfigAttrib(display, tempConfig, EGL_SAMPLES, &samples);
229
230         if (samples != expectedSamples) {
231             LOG_ERROR("Failed to match %s Attribute Value. Retrieved %d, Expected: %d. Checking next EGLConfig.", "Samples", samples, expectedSamples);
232             continue;
233         }
234
235         eglGetConfigAttrib(display, tempConfig, EGL_SURFACE_TYPE, &surface);
236
237         if (surface & expectedSurfaceType) {
238             config = configs[i];
239             break;
240         }
241     }
242
243     if ((attributes & GLPlatformSurface::SupportAlpha) && !config) {
244         LOG_ERROR("Failed to retrieve EGL Configuration with alpha. Trying to find one without alpha support.");
245         attributes &= ~GLPlatformSurface::SupportAlpha;
246         config = createConfig(expectedSurfaceType, attributes);
247     }
248
249     if (!config)
250         LOG_ERROR("Failed to find a valid EGL Configuration.");
251
252     return config;
253 }
254
255 EGLConfigSelector::EGLConfigSelector(GLPlatformSurface::SurfaceAttributes attributes)
256     : m_attributes(attributes)
257 {
258     static bool isVendorMesa = EGLHelper::isVendor("mesa");
259     if (isVendorMesa) {
260         if ((m_attributes & GLPlatformSurface::SupportStencil) || (m_attributes & GLPlatformSurface::SupportDepth)) {
261             m_attributes |= GLPlatformSurface::SupportStencil;
262             m_attributes |= GLPlatformSurface::SupportDepth;
263         }
264
265         m_attributes |= GLPlatformSurface::SupportAlpha;
266     }
267 }
268
269 EGLConfigSelector::~EGLConfigSelector()
270 {
271 }
272
273 EGLConfig EGLConfigSelector::pixmapContextConfig()
274 {
275     return EGLConfigPool::getInstance().pixmapContextConfig(m_attributes);
276 }
277
278 EGLConfig EGLConfigSelector::surfaceContextConfig()
279 {
280     return EGLConfigPool::getInstance().surfaceContextConfig(m_attributes);
281 }
282
283 EGLint EGLConfigSelector::nativeVisualId(const EGLConfig& config) const
284 {
285     EGLDisplay display = EGLHelper::eglDisplay();
286     if (display == EGL_NO_DISPLAY)
287         return -1;
288
289     EGLint eglValue = 0;
290     eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &eglValue);
291
292     return eglValue;
293 }
294
295 GLPlatformSurface::SurfaceAttributes EGLConfigSelector::attributes() const
296 {
297     return m_attributes;
298 }
299
300 void EGLConfigSelector::reset()
301 {
302 }
303
304 #if PLATFORM(X11)
305 EGLConfig EGLConfigSelector::surfaceClientConfig(NativeVisualId id)
306 {
307     EGLConfig config = findMatchingConfigWithVisualId(id);
308
309     if (!config)
310         config = pixmapContextConfig();
311
312     return config;
313 }
314
315 EGLConfig EGLConfigSelector::findMatchingConfigWithVisualId(NativeVisualId id)
316 {
317     EGLDisplay display = EGLHelper::eglDisplay();
318     if (display == EGL_NO_DISPLAY)
319         return 0;
320
321     EGLint numConfigs;
322     EGLint i;
323     EGLint visualId;
324     EGLConfig config = 0;
325
326     eglGetConfigs(display, 0, 0, &numConfigs);
327
328     if (!numConfigs) {
329         LOG_ERROR("Failed to retrieve any EGL configs.");
330         return 0;
331     }
332
333     EGLConfig configs[numConfigs];
334     eglGetConfigs(display, configs, numConfigs, &numConfigs);
335
336     if (!numConfigs) {
337         LOG_ERROR("Failed to retrieve any EGL configs.");
338         return 0;
339     }
340
341     int alphaChannelRequired = m_attributes & GLPlatformSurface::SupportAlpha ? 8 : 0;
342     for (i = 0; i < numConfigs; i++) {
343         EGLint alpha, surfaces;
344         EGLConfig tempConfig = configs[i];
345         eglGetConfigAttrib(display, tempConfig, EGL_NATIVE_VISUAL_ID, &visualId);
346
347         if (static_cast<NativeVisualId>(visualId) != id)
348             continue;
349
350         eglGetConfigAttrib(display, tempConfig, EGL_ALPHA_SIZE, &alpha);
351
352         if (alphaChannelRequired != alpha)
353             continue;
354
355         eglGetConfigAttrib(display, tempConfig, EGL_SURFACE_TYPE, &surfaces);
356
357         if (surfaces & EGL_PIXMAP_BIT) {
358             config = tempConfig;
359             break;
360         }
361     }
362
363     return config;
364 }
365 #endif
366
367 }
368
369 #endif