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 "EGLXSurface.h" 28 29#if PLATFORM(X11) && USE(EGL) && USE(GRAPHICS_SURFACE) 30 31#include "EGLConfigSelector.h" 32#include "EGLHelper.h" 33#include "GLPlatformContext.h" 34 35namespace WebCore { 36 37EGLWindowTransportSurface::EGLWindowTransportSurface(const IntSize& size, GLPlatformSurface::SurfaceAttributes attributes) 38 : EGLTransportSurface(size, attributes) 39{ 40 if (!m_configSelector) 41 return; 42 43 if (!m_configSelector->surfaceContextConfig()) { 44 destroy(); 45 return; 46 } 47 48 EGLint visualId = m_configSelector->nativeVisualId(m_configSelector->surfaceContextConfig()); 49 50 if (visualId == -1) { 51 destroy(); 52 return; 53 } 54 55 NativeWrapper::createOffScreenWindow(&m_bufferHandle, visualId, m_configSelector->attributes() & GLPlatformSurface::SupportAlpha, size); 56 57 if (!m_bufferHandle) { 58 destroy(); 59 return; 60 } 61 62 m_drawable = eglCreateWindowSurface(m_sharedDisplay, m_configSelector->surfaceContextConfig(), static_cast<EGLNativeWindowType>(m_bufferHandle), 0); 63 64 if (m_drawable == EGL_NO_SURFACE) { 65 LOG_ERROR("Failed to create EGL surface(%d).", eglGetError()); 66 destroy(); 67 } 68} 69 70EGLWindowTransportSurface::~EGLWindowTransportSurface() 71{ 72} 73 74void EGLWindowTransportSurface::swapBuffers() 75{ 76 if (!eglSwapBuffers(m_sharedDisplay, m_drawable)) 77 LOG_ERROR("Failed to SwapBuffers(%d).", eglGetError()); 78} 79 80void EGLWindowTransportSurface::destroy() 81{ 82 EGLTransportSurface::destroy(); 83 84 if (m_bufferHandle) { 85 NativeWrapper::destroyWindow(m_bufferHandle); 86 m_bufferHandle = 0; 87 } 88} 89 90EGLPixmapSurface::EGLPixmapSurface(GLPlatformSurface::SurfaceAttributes surfaceAttributes) 91 : EGLOffScreenSurface(surfaceAttributes) 92{ 93 if (!m_configSelector) 94 return; 95 96 EGLConfig config = m_configSelector->pixmapContextConfig(); 97 98 if (!config) { 99 destroy(); 100 return; 101 } 102 103 EGLint visualId = m_configSelector->nativeVisualId(config); 104 105 if (visualId == -1) { 106 destroy(); 107 return; 108 } 109 110 NativePixmap pixmap; 111 NativeWrapper::createPixmap(&pixmap, visualId, m_configSelector->attributes() & GLPlatformSurface::SupportAlpha); 112 m_bufferHandle = pixmap; 113 114 if (!m_bufferHandle) { 115 destroy(); 116 return; 117 } 118 119 m_drawable = eglCreatePixmapSurface(m_sharedDisplay, config, static_cast<EGLNativePixmapType>(m_bufferHandle), 0); 120 121 if (m_drawable == EGL_NO_SURFACE) { 122 LOG_ERROR("Failed to create EGL surface(%d).", eglGetError()); 123 destroy(); 124 } 125} 126 127EGLPixmapSurface::~EGLPixmapSurface() 128{ 129} 130 131void EGLPixmapSurface::destroy() 132{ 133 EGLOffScreenSurface::destroy(); 134 135 if (m_bufferHandle) { 136 NativeWrapper::destroyPixmap(m_bufferHandle); 137 m_bufferHandle = 0; 138 } 139} 140 141EGLXTransportSurfaceClient::EGLXTransportSurfaceClient(const PlatformBufferHandle handle, const IntSize& size, bool hasAlpha) 142 : GLTransportSurfaceClient() 143 , m_image(0) 144 , m_size(size) 145 , m_totalBytes(0) 146{ 147 if (!handle) 148 return; 149 150 m_handle = handle; 151 XWindowAttributes attr; 152 153 if (!XGetWindowAttributes(NativeWrapper::nativeDisplay(), m_handle, &attr)) 154 return; 155 156 createTexture(); 157 GLPlatformSurface::SurfaceAttributes sharedSurfaceAttributes = GLPlatformSurface::Default; 158 159 if (hasAlpha) 160 sharedSurfaceAttributes = GLPlatformSurface::SupportAlpha; 161 162 EGLConfigSelector configSelector(sharedSurfaceAttributes); 163 EGLConfig config = configSelector.surfaceClientConfig(XVisualIDFromVisual(attr.visual)); 164 m_eglImage = adoptPtr(new EGLTextureFromPixmap(m_handle, hasAlpha, config)); 165 166 if (!m_eglImage->isValid() || eglGetError() != EGL_SUCCESS) 167 destroy(); 168 169 if (m_eglImage) 170 return; 171 172 m_totalBytes = m_size.width() * m_size.height() * 4; 173 174#if USE(OPENGL_ES_2) 175 m_format = GraphicsContext3D::RGBA; 176 static bool bgraSupported = GLPlatformContext::supportsGLExtension("GL_EXT_texture_format_BGRA8888"); 177 if (bgraSupported) 178 m_format = GraphicsContext3D::BGRA; 179#endif 180 181 createTexture(); 182 prepareTexture(); 183} 184 185EGLXTransportSurfaceClient::~EGLXTransportSurfaceClient() 186{ 187} 188 189void EGLXTransportSurfaceClient::destroy() 190{ 191 GLTransportSurfaceClient::destroy(); 192 193 if (m_eglImage) { 194 m_eglImage->destroy(); 195 m_eglImage = nullptr; 196 } 197 198 eglWaitGL(); 199 200 if (m_image) { 201 XDestroyImage(m_image); 202 m_image = 0; 203 } 204} 205 206void EGLXTransportSurfaceClient::prepareTexture() 207{ 208 ::glBindTexture(GL_TEXTURE_2D, m_texture); 209 210 if (m_eglImage) { 211 m_eglImage->reBindTexImage(); 212 return; 213 } 214 215 // Fallback to use XImage in case EGLImage and TextureToPixmap are not supported. 216 m_image = XGetImage(NativeWrapper::nativeDisplay(), m_handle, 0, 0, m_size.width(), m_size.height(), AllPlanes, ZPixmap); 217 218#if USE(OPENGL_ES_2) 219 if (m_format != GraphicsContext3D::BGRA) { 220 for (unsigned i = 0; i < m_totalBytes; i += 4) 221 std::swap(m_image->data[i], m_image->data[i + 2]); 222 } 223#endif 224 225 glTexImage2D(GL_TEXTURE_2D, 0, m_format, m_size.width(), m_size.height(), 0, m_format, GL_UNSIGNED_BYTE, m_image->data); 226 227 if (m_image) { 228 XDestroyImage(m_image); 229 m_image = 0; 230 } 231} 232 233EGLTextureFromPixmap::EGLTextureFromPixmap(const NativePixmap handle, bool hasAlpha, EGLConfig config) 234 : m_eglImage(0) 235 , m_surface(EGL_NO_SURFACE) 236{ 237 if (!handle) 238 return; 239 240 static bool textureFromPixmapSupported = GLPlatformContext::supportsEGLExtension(EGLHelper::eglDisplay(), "EGL_NOK_texture_from_pixmap"); 241 242 if (textureFromPixmapSupported) { 243 const EGLint pixmapAttribs[] = { EGL_TEXTURE_FORMAT, hasAlpha ? EGL_TEXTURE_RGBA : EGL_TEXTURE_RGB, EGL_TEXTURE_TARGET, EGL_TEXTURE_2D, EGL_NONE }; 244 m_surface = eglCreatePixmapSurface(EGLHelper::eglDisplay(), config, handle, pixmapAttribs); 245 246 if (m_surface != EGL_NO_SURFACE && !eglBindTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER)) 247 destroy(); 248 } 249 250 if (m_surface != EGL_NO_SURFACE) 251 return; 252 253 static const EGLint imageAttrs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; 254 EGLHelper::createEGLImage(&m_eglImage, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)(handle), imageAttrs); 255 256 if (m_eglImage) { 257 EGLHelper::imageTargetTexture2DOES(m_eglImage); 258 EGLint error = eglGetError(); 259 260 if (error != EGL_SUCCESS) 261 destroy(); 262 } 263} 264 265EGLTextureFromPixmap::~EGLTextureFromPixmap() 266{ 267} 268 269void EGLTextureFromPixmap::destroy() 270{ 271 eglWaitNative(EGL_CORE_NATIVE_ENGINE); 272 273 if (m_surface != EGL_NO_SURFACE) 274 eglReleaseTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER); 275 276 if (m_eglImage) { 277 EGLHelper::destroyEGLImage(m_eglImage); 278 m_eglImage = 0; 279 } 280 281 if (m_surface != EGL_NO_SURFACE) { 282 eglDestroySurface(EGLHelper::eglDisplay(), m_surface); 283 m_surface = EGL_NO_SURFACE; 284 } 285 286 eglWaitGL(); 287} 288 289bool EGLTextureFromPixmap::isValid() const 290{ 291 if (m_surface || m_eglImage) 292 return true; 293 294 return false; 295} 296 297bool EGLTextureFromPixmap::bindTexImage() 298{ 299 if (m_surface != EGL_NO_SURFACE) { 300 bool success = eglBindTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER); 301 return success; 302 } 303 304 if (m_eglImage) { 305 EGLHelper::imageTargetTexture2DOES(m_eglImage); 306 return true; 307 } 308 309 return false; 310} 311 312bool EGLTextureFromPixmap::reBindTexImage() 313{ 314 if (m_surface != EGL_NO_SURFACE) { 315 bool success = eglReleaseTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER); 316 317 if (success) 318 success = eglBindTexImage(EGLHelper::eglDisplay(), m_surface, EGL_BACK_BUFFER); 319 320 return success; 321 } 322 323 if (m_eglImage) { 324 EGLHelper::imageTargetTexture2DOES(m_eglImage); 325 return true; 326 } 327 328 return false; 329} 330 331} 332 333#endif 334