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 "GLXSurface.h" 28 29#if USE(ACCELERATED_COMPOSITING) && USE(GLX) 30 31namespace WebCore { 32 33static PFNGLXBINDTEXIMAGEEXTPROC pGlXBindTexImageEXT = 0; 34static PFNGLXRELEASETEXIMAGEEXTPROC pGlXReleaseTexImageEXT = 0; 35 36static bool resolveGLMethods() 37{ 38 static bool resolved = false; 39 if (resolved) 40 return true; 41 42 pGlXBindTexImageEXT = reinterpret_cast<PFNGLXBINDTEXIMAGEEXTPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXBindTexImageEXT"))); 43 pGlXReleaseTexImageEXT = reinterpret_cast<PFNGLXRELEASETEXIMAGEEXTPROC>(glXGetProcAddress(reinterpret_cast<const GLubyte*>("glXReleaseTexImageEXT"))); 44 45 resolved = pGlXBindTexImageEXT && pGlXReleaseTexImageEXT; 46 47 return resolved; 48} 49 50static int glxAttributes[] = { 51 GLX_TEXTURE_FORMAT_EXT, 52 GLX_TEXTURE_FORMAT_RGBA_EXT, 53 GLX_TEXTURE_TARGET_EXT, 54 GLX_TEXTURE_2D_EXT, 55 0 56}; 57 58static bool isMesaGLX() 59{ 60 static bool isMesa = !!strstr(glXGetClientString(X11Helper::nativeDisplay(), GLX_VENDOR), "Mesa"); 61 return isMesa; 62} 63 64GLXTransportSurface::GLXTransportSurface(const IntSize& size, SurfaceAttributes attributes) 65 : GLTransportSurface(size, attributes) 66{ 67 m_sharedDisplay = X11Helper::nativeDisplay(); 68 attributes |= GLPlatformSurface::DoubleBuffered; 69 m_configSelector = adoptPtr(new GLXConfigSelector(attributes)); 70 OwnPtrX11<XVisualInfo> visInfo(m_configSelector->visualInfo(m_configSelector->surfaceContextConfig())); 71 72 if (!visInfo.get()) { 73 destroy(); 74 return; 75 } 76 77 X11Helper::createOffScreenWindow(&m_bufferHandle, *visInfo.get(), size); 78 79 if (!m_bufferHandle) { 80 destroy(); 81 return; 82 } 83 84 m_drawable = m_bufferHandle; 85} 86 87GLXTransportSurface::~GLXTransportSurface() 88{ 89} 90 91PlatformSurfaceConfig GLXTransportSurface::configuration() 92{ 93 return m_configSelector->surfaceContextConfig(); 94} 95 96void GLXTransportSurface::setGeometry(const IntRect& newRect) 97{ 98 GLTransportSurface::setGeometry(newRect); 99 X11Helper::resizeWindow(newRect, m_drawable); 100 // Force resize of GL surface after window resize. 101 glXSwapBuffers(sharedDisplay(), m_drawable); 102} 103 104void GLXTransportSurface::swapBuffers() 105{ 106 if (!m_drawable) 107 return; 108 109 glXSwapBuffers(sharedDisplay(), m_drawable); 110} 111 112void GLXTransportSurface::destroy() 113{ 114 GLTransportSurface::destroy(); 115 116 if (m_bufferHandle) { 117 X11Helper::destroyWindow(m_bufferHandle); 118 m_bufferHandle = 0; 119 m_drawable = 0; 120 } 121 122 m_configSelector = nullptr; 123} 124 125GLPlatformSurface::SurfaceAttributes GLXTransportSurface::attributes() const 126{ 127 return m_configSelector->attributes(); 128} 129 130GLXOffScreenSurface::GLXOffScreenSurface(SurfaceAttributes surfaceAttributes) 131 : GLPlatformSurface(surfaceAttributes) 132 , m_pixmap(0) 133 , m_glxPixmap(0) 134{ 135 initialize(surfaceAttributes); 136} 137 138GLXOffScreenSurface::~GLXOffScreenSurface() 139{ 140} 141 142void GLXOffScreenSurface::initialize(SurfaceAttributes attributes) 143{ 144 m_sharedDisplay = X11Helper::nativeDisplay(); 145 146 m_configSelector = adoptPtr(new GLXConfigSelector(attributes)); 147 148 OwnPtrX11<XVisualInfo> visualInfo(m_configSelector->visualInfo(m_configSelector->pixmapContextConfig())); 149 X11Helper::createPixmap(&m_pixmap, *visualInfo.get()); 150 151 if (!m_pixmap) { 152 destroy(); 153 return; 154 } 155 156 m_glxPixmap = glXCreateGLXPixmap(m_sharedDisplay, visualInfo.get(), m_pixmap); 157 158 if (!m_glxPixmap) { 159 destroy(); 160 return; 161 } 162 163 m_drawable = m_glxPixmap; 164} 165 166PlatformSurfaceConfig GLXOffScreenSurface::configuration() 167{ 168 return m_configSelector->pixmapContextConfig(); 169} 170 171void GLXOffScreenSurface::destroy() 172{ 173 freeResources(); 174} 175 176void GLXOffScreenSurface::freeResources() 177{ 178 Display* display = sharedDisplay(); 179 180 if (!display) 181 return; 182 183 if (m_glxPixmap) { 184 glXDestroyGLXPixmap(display, m_glxPixmap); 185 glXWaitGL(); 186 m_glxPixmap = 0; 187 } 188 189 if (m_pixmap) { 190 X11Helper::destroyPixmap(m_pixmap); 191 m_pixmap = 0; 192 } 193 194 m_configSelector = nullptr; 195 m_drawable = 0; 196} 197 198GLXTransportSurfaceClient::GLXTransportSurfaceClient(const PlatformBufferHandle handle, bool hasAlpha) 199 : GLTransportSurfaceClient() 200{ 201 if (!resolveGLMethods()) 202 return; 203 204 XWindowAttributes attr; 205 Display* display = X11Helper::nativeDisplay(); 206 if (!XGetWindowAttributes(display, handle, &attr)) 207 return; 208 209 // Ensure that the window is mapped. 210 if (attr.map_state == IsUnmapped || attr.map_state == IsUnviewable) 211 return; 212 213 ScopedXPixmapCreationErrorHandler handler; 214 215 XRenderPictFormat* format = XRenderFindVisualFormat(display, attr.visual); 216 m_xPixmap = XCompositeNameWindowPixmap(display, handle); 217 218 if (!m_xPixmap) 219 return; 220 221 glxAttributes[1] = (format->depth == 32 && hasAlpha) ? GLX_TEXTURE_FORMAT_RGBA_EXT : GLX_TEXTURE_FORMAT_RGB_EXT; 222 223 GLPlatformSurface::SurfaceAttributes sharedSurfaceAttributes = GLPlatformSurface::Default; 224 225 if (hasAlpha) 226 sharedSurfaceAttributes = GLPlatformSurface::SupportAlpha; 227 228 GLXConfigSelector configSelector(sharedSurfaceAttributes); 229 230 m_glxPixmap = glXCreatePixmap(display, configSelector.surfaceClientConfig(format->depth, XVisualIDFromVisual(attr.visual)), m_xPixmap, glxAttributes); 231 232 if (!m_glxPixmap || !handler.isValidOperation()) { 233 destroy(); 234 return; 235 } 236 237 createTexture(); 238 glXWaitX(); 239 pGlXBindTexImageEXT(display, m_glxPixmap, GLX_FRONT_EXT, 0); 240} 241 242GLXTransportSurfaceClient::~GLXTransportSurfaceClient() 243{ 244} 245 246void GLXTransportSurfaceClient::destroy() 247{ 248 Display* display = X11Helper::nativeDisplay(); 249 if (!display) 250 return; 251 252 if (m_texture) { 253 pGlXReleaseTexImageEXT(display, m_glxPixmap, GLX_FRONT_EXT); 254 GLTransportSurfaceClient::destroy(); 255 } 256 257 if (m_glxPixmap) { 258 glXDestroyPixmap(display, m_glxPixmap); 259 m_glxPixmap = 0; 260 glXWaitGL(); 261 } 262 263 if (m_xPixmap) { 264 X11Helper::destroyPixmap(m_xPixmap); 265 m_xPixmap = 0; 266 } 267} 268 269void GLXTransportSurfaceClient::prepareTexture() 270{ 271 if (isMesaGLX() && m_texture) { 272 Display* display = X11Helper::nativeDisplay(); 273 glBindTexture(GL_TEXTURE_2D, m_texture); 274 // Mesa doesn't re-bind texture to the front buffer on glXSwapBufer 275 // Manually release previous lock and rebind texture to surface to ensure frame updates. 276 pGlXReleaseTexImageEXT(display, m_glxPixmap, GLX_FRONT_EXT); 277 pGlXBindTexImageEXT(display, m_glxPixmap, GLX_FRONT_EXT, 0); 278 } 279} 280 281} 282 283#endif 284