2 * Copyright (C) 2012 Samsung Electronics. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
14 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
15 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
16 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
17 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
19 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #if ENABLE(TIZEN_WEBKIT2_TILED_AC)
29 #include "SharedPlatformSurfaceTizen.h"
30 #include "PixmapContextTizen.h"
32 #include "NotImplemented.h"
35 #include <EGL/eglext.h>
36 #include <wtf/HashMap.h>
37 #include <wtf/OwnPtr.h>
38 #include <wtf/RefCounted.h>
39 #include <wtf/text/WTFString.h>
40 #include <wtf/StdLibExtras.h>
42 #include <X11/Xutil.h>
46 static PFNEGLLOCKSURFACEKHRPROC eglLockSurfaceKHR = 0;
47 static PFNEGLUNLOCKSURFACEKHRPROC eglUnlockSurfaceKHR = 0;
49 static bool vendorNeedsMakeCurrent(const EGLDisplay display)
51 static bool queryDone = false;
52 static bool needsMakeCurrent = true;
56 String vendor = eglQueryString(display, EGL_VENDOR);
57 Vector<String> vendorComponents;
58 vendor.lower().split(' ', vendorComponents);
60 if (vendorComponents.contains("imagination") || vendorComponents.contains("mesa") || vendorComponents.contains("arm"))
61 needsMakeCurrent = false;
64 return needsMakeCurrent;
69 Display* g_nativeDisplay;
71 class PixmapContextPool {
73 PixmapContextPool(void);
74 virtual ~PixmapContextPool();
76 static inline PixmapContextPool& getInstance()
78 static PixmapContextPool pixmapContextPool;
79 return pixmapContextPool;
82 PixmapContextTizen* getContext(bool isLockable, bool hasAlpha, bool hasDepth, bool hasStencil);
85 typedef HashMap<int, RefPtr<PixmapContextTizen> > PixmapContextMap;
86 PixmapContextMap m_pixmapContexts;
89 PixmapContextPool::PixmapContextPool()
92 g_nativeDisplay = XOpenDisplay(0);
94 g_nativeWindow = XCreateSimpleWindow(g_nativeDisplay, XDefaultRootWindow(g_nativeDisplay),
96 BlackPixel(g_nativeDisplay, 0), WhitePixel(g_nativeDisplay, 0));
97 XFlush(g_nativeDisplay);
100 PixmapContextPool::~PixmapContextPool()
102 PixmapContextMap::iterator end = m_pixmapContexts.end();
103 for (PixmapContextMap::iterator iter = m_pixmapContexts.begin(); iter != end; ++iter) {
104 RefPtr<PixmapContextTizen> context = iter->second;
107 m_pixmapContexts.clear();
109 if (g_nativeWindow) {
110 XDestroyWindow(g_nativeDisplay, g_nativeWindow);
115 PixmapContextTizen* PixmapContextPool::getContext(bool isLockable, bool hasAlpha, bool hasDepth, bool hasStencil)
117 int contextId = ((isLockable) | (hasAlpha << 1) | (hasDepth << 2) | (hasStencil << 3));
118 RefPtr<PixmapContextTizen> pixmapContext = m_pixmapContexts.get(contextId);
119 if (!pixmapContext) {
120 pixmapContext = PixmapContextTizen::create(isLockable, hasAlpha, hasDepth, hasStencil);
122 m_pixmapContexts.add(contextId, pixmapContext);
126 return pixmapContext.get();
129 PassRefPtr<PixmapContextTizen> PixmapContextTizen::create(bool isLockable, bool hasAlpha, bool hasDepth, bool hasStencil)
131 RefPtr<PixmapContextTizen> context = adoptRef(new PixmapContextTizen(isLockable, hasAlpha, hasDepth, hasStencil));
132 if (!context->initialize())
134 return context.release();
137 void PixmapContextTizen::HandleEGLError(const char* name)
139 static const char* const egErrorStrings[] =
142 "EGL_NOT_INITIALIZED",
148 "EGL_BAD_CURRENT_SURFACE",
151 "EGL_BAD_NATIVE_PIXMAP",
152 "EGL_BAD_NATIVE_WINDOW",
157 EGLint errorCode = eglGetError();
159 if (errorCode != EGL_SUCCESS)
160 TIZEN_LOGE("'%s' returned egl error '%s' (0x%x)", name, egErrorStrings[errorCode - EGL_SUCCESS], errorCode);
163 PixmapContextTizen::PixmapContextTizen(bool isLockable, bool hasAlpha, bool hasDepth, bool hasStencil)
164 : m_initialized(false)
165 , m_display(EGL_NO_DISPLAY)
166 , m_context(EGL_NO_CONTEXT)
167 , m_isLockable(isLockable)
168 , m_hasAlpha(hasAlpha)
169 , m_hasDepth(hasDepth)
170 , m_hasStencil(hasStencil)
174 PixmapContextTizen::~PixmapContextTizen()
177 eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
178 eglDestroyContext(m_display, m_context);
179 m_context = EGL_NO_CONTEXT;
184 bool PixmapContextTizen::initialize()
187 EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
189 m_display = eglGetDisplay(g_nativeDisplay);
190 if (m_display == EGL_NO_DISPLAY)
191 HandleEGLError("eglGetDisplay");
193 if (eglInitialize(m_display, &major, &minor) != EGL_TRUE)
194 HandleEGLError("eglInitialize");
196 EGLint configCount = 0;
198 EGLint configAttribs[32];
199 configAttribs[i++] = EGL_LEVEL;
200 configAttribs[i++] = 0;
201 // FIXME : Create pixmap surface with RGB_565 when alpha is off. Graphics driver needs to be fixed first.
202 configAttribs[i++] = EGL_RED_SIZE;
203 configAttribs[i++] = 8;
204 configAttribs[i++] = EGL_GREEN_SIZE;
205 configAttribs[i++] = 8;
206 configAttribs[i++] = EGL_BLUE_SIZE;
207 configAttribs[i++] = 8;
208 configAttribs[i++] = EGL_ALPHA_SIZE;
210 configAttribs[i++] = 8;
212 configAttribs[i++] = 0;
213 configAttribs[i++] = EGL_CONFIG_CAVEAT;
214 if (!strcmp(eglQueryString (m_display, EGL_VENDOR), "Imagination Technologies"))
215 configAttribs[i++] = EGL_NONE;
217 configAttribs[i++] = EGL_NON_CONFORMANT_CONFIG;
221 configAttribs[i++] = EGL_MATCH_FORMAT_KHR;
222 // FIXME : This strcmp will be replaced.to the feature macro.
223 if (!strcmp(eglQueryString (m_display, EGL_VENDOR), "ARM"))
224 configAttribs[i++] = EGL_FORMAT_RGBA_8888_EXACT_KHR;
225 else if (!strcmp(eglQueryString (m_display, EGL_VENDOR), "Imagination Technologies"))
226 configAttribs[i++] = EGL_FORMAT_RGBA_8888_EXACT_KHR;
228 configAttribs[i++] = EGL_FORMAT_RGBA_8888_KHR;
229 configAttribs[i++] = EGL_SURFACE_TYPE;
230 configAttribs[i++] = EGL_PIXMAP_BIT | EGL_LOCK_SURFACE_BIT_KHR;
231 configAttribs[i++] = EGL_DEPTH_SIZE;
232 configAttribs[i++] = 0;
233 configAttribs[i++] = EGL_STENCIL_SIZE;
234 configAttribs[i++] = 0;
236 configAttribs[i++] = EGL_SURFACE_TYPE;
237 configAttribs[i++] = EGL_PIXMAP_BIT;
238 configAttribs[i++] = EGL_DEPTH_SIZE;
240 configAttribs[i++] = 16;
242 configAttribs[i++] = 0;
243 configAttribs[i++] = EGL_STENCIL_SIZE;
245 configAttribs[i++] = 8;
247 configAttribs[i++] = 0;
249 configAttribs[i++] = EGL_RENDERABLE_TYPE;
250 configAttribs[i++] = EGL_OPENGL_ES2_BIT;
251 configAttribs[i++] = EGL_NONE;
253 if (eglChooseConfig(m_display, configAttribs, &m_surfaceConfig, 1, &configCount) != EGL_TRUE) {
254 HandleEGLError("eglChooseConfig");
257 m_context = eglCreateContext(m_display, m_surfaceConfig, EGL_NO_CONTEXT, contextAttribs);
258 if( m_context == EGL_NO_CONTEXT) {
259 HandleEGLError("eglCreateContext");
265 bool PixmapContextTizen::makeCurrent(EGLSurface surface)
267 if (eglGetCurrentSurface(EGL_READ) == surface && eglGetCurrentSurface(EGL_DRAW) == surface && eglGetCurrentContext() == m_context)
270 if (eglMakeCurrent(m_display, surface, surface, m_context) != EGL_TRUE) {
271 HandleEGLError("eglMakeCurrent");
277 void* PixmapContextTizen::createSurface(int pixmapID)
279 EGLSurface surface = eglCreatePixmapSurface(m_display, m_surfaceConfig, pixmapID, NULL);
280 if (surface == EGL_NO_SURFACE)
281 HandleEGLError("eglCreatePixmapSurface");
286 void PixmapContextTizen::destroySurface(EGLSurface surface)
289 if (eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT) != EGL_TRUE)
290 HandleEGLError("eglMakeCurrent");
291 eglDestroySurface(m_display, surface);
295 bool PixmapContextTizen::lockSurface(EGLSurface surface)
297 EGLint lockAttrib[] = { EGL_LOCK_USAGE_HINT_KHR, EGL_WRITE_SURFACE_BIT_KHR, EGL_NONE };
298 if (!eglLockSurfaceKHR)
299 eglLockSurfaceKHR = (PFNEGLLOCKSURFACEKHRPROC)eglGetProcAddress("eglLockSurfaceKHR");
301 if (vendorNeedsMakeCurrent(m_display))
302 eglMakeCurrent(m_display, surface, surface, m_context);
304 if (eglLockSurfaceKHR(m_display, surface, lockAttrib) != EGL_TRUE) {
305 HandleEGLError("eglLockSurfaceKHR");
311 bool PixmapContextTizen::unlockSurface(EGLSurface surface)
313 if (!eglUnlockSurfaceKHR)
314 eglUnlockSurfaceKHR = (PFNEGLUNLOCKSURFACEKHRPROC)eglGetProcAddress("eglUnlockSurfaceKHR");
315 if (eglUnlockSurfaceKHR(m_display, surface) != EGL_TRUE) {
316 HandleEGLError("eglUnlockSurfaceKHR");
322 bool PixmapContextTizen::querySurface(EGLSurface surface, EGLint* value)
324 if (eglQuerySurface(m_display, surface, EGL_BITMAP_POINTER_KHR, value) != EGL_TRUE) {
325 HandleEGLError("eglQuerySurface");
331 int PixmapContextTizen::createPixmap(int width, int height)
333 // FIXME : Create 16 bit pixmap when alpha is off. Graphics driver needs to be fixed first.
334 int pix = XCreatePixmap(g_nativeDisplay, g_nativeWindow, width, height, 32);
335 XFlush(g_nativeDisplay);
340 void PixmapContextTizen::freePixmap(int pixmap)
343 XFreePixmap(g_nativeDisplay, pixmap);
346 PassOwnPtr<SharedPlatformSurfaceTizen> SharedPlatformSurfaceTizen::create(const IntSize& size, bool lockable, bool hasAlpha, bool hasDepth, bool hasStencil, PixmapContextTizen* pixmapContext)
348 OwnPtr<SharedPlatformSurfaceTizen> pixmap = adoptPtr(new SharedPlatformSurfaceTizen(size, lockable, hasAlpha, hasDepth, hasStencil, pixmapContext));
349 if (!pixmap->initialize())
351 return pixmap.release();
354 SharedPlatformSurfaceTizen::SharedPlatformSurfaceTizen(const IntSize& size, bool lockable, bool hasAlpha, bool hasDepth, bool hasStencil, PixmapContextTizen* pixmapContext)
358 , m_isLockable(lockable)
359 , m_hasAlpha(hasAlpha)
360 , m_hasDepth(hasDepth)
361 , m_hasStencil(hasStencil)
364 m_pixmapContext = pixmapContext;
367 SharedPlatformSurfaceTizen::~SharedPlatformSurfaceTizen()
369 if (m_surface != EGL_NO_SURFACE) {
370 m_pixmapContext->destroySurface(m_surface);
371 m_surface = EGL_NO_SURFACE;
374 m_pixmapContext->freePixmap(m_pixmap);
379 bool SharedPlatformSurfaceTizen::initialize()
381 if (m_size.isEmpty())
384 if(!m_pixmapContext) {
385 PixmapContextPool& pixmapContextPool = PixmapContextPool::getInstance();
386 m_pixmapContext = pixmapContextPool.getContext(m_isLockable, m_hasAlpha, m_hasDepth, m_hasStencil);
392 m_pixmap = m_pixmapContext->createPixmap(m_size.width(), m_size.height());
395 m_surface = (void*)(m_pixmapContext->createSurface(m_pixmap));
396 if (m_surface == EGL_NO_SURFACE)
401 void* SharedPlatformSurfaceTizen::context()
403 return m_pixmapContext->context();
406 bool SharedPlatformSurfaceTizen::makeContextCurrent()
408 return m_pixmapContext->makeCurrent(m_surface);
411 bool SharedPlatformSurfaceTizen::lockSurface()
413 return m_pixmapContext->lockSurface(m_surface);
416 bool SharedPlatformSurfaceTizen::unlockSurface()
418 return m_pixmapContext->unlockSurface(m_surface);
421 bool SharedPlatformSurfaceTizen::querySurface(int* value)
426 ret = m_pixmapContext->querySurface(m_surface, (EGLint*)&value_local);
427 *value = (int)value_local;
432 #endif // ENABLE(TIZEN_ACCELERATED_COMPOSITING)