1 /* 2 * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Library General Public 6 * License as published by the Free Software Foundation; either 7 * version 2 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20 #include "config.h" 21 #include "SurfaceOpenVG.h" 22 23 #include "IntSize.h" 24 #include "PainterOpenVG.h" 25 26 #if PLATFORM(EGL) 27 #include "EGLDisplayOpenVG.h" 28 #include "EGLUtils.h" 29 #endif 30 31 #include <wtf/Assertions.h> 32 33 namespace WebCore { 34 35 PainterOpenVG* SurfaceOpenVG::s_currentPainter = 0; 36 37 SurfaceOpenVG* SurfaceOpenVG::currentSurface() 38 { 39 #if PLATFORM(EGL) 40 return EGLDisplayOpenVG::currentSurface(); 41 #else 42 ASSERT_NOT_REACHED(); 43 return 0; 44 #endif 45 } 46 47 #if PLATFORM(EGL) 48 SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode) 49 : m_activePainter(0) 50 , m_eglDisplay(display) 51 , m_eglSurface(EGL_NO_SURFACE) 52 , m_eglContext(EGL_NO_CONTEXT) 53 { 54 ASSERT(m_eglDisplay != EGL_NO_DISPLAY); 55 56 EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); 57 EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig(); 58 m_eglSurface = displayManager->createPbufferSurface(size, config, errorCode); 59 60 if (m_eglSurface == EGL_NO_SURFACE) 61 return; 62 63 m_eglContext = displayManager->contextForSurface(m_eglSurface); 64 EGLDisplayOpenVG::registerPlatformSurface(this); 65 } 66 67 SurfaceOpenVG::SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode) 68 : m_activePainter(0) 69 , m_eglDisplay(display) 70 , m_eglSurface(EGL_NO_SURFACE) 71 , m_eglContext(EGL_NO_CONTEXT) 72 { 73 ASSERT(m_eglDisplay != EGL_NO_DISPLAY); 74 75 EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); 76 EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig(); 77 m_eglSurface = displayManager->createPbufferFromClientBuffer(buffer, bufferType, config, errorCode); 78 79 if (m_eglSurface == EGL_NO_SURFACE) 80 return; 81 82 m_eglContext = displayManager->contextForSurface(m_eglSurface); 83 EGLDisplayOpenVG::registerPlatformSurface(this); 84 } 85 86 SurfaceOpenVG::SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr) 87 : m_activePainter(0) 88 , m_eglDisplay(display) 89 , m_eglSurface(EGL_NO_SURFACE) 90 , m_eglContext(EGL_NO_CONTEXT) 91 { 92 ASSERT(m_eglDisplay != EGL_NO_DISPLAY); 93 94 EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); 95 EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultWindowConfig(); 96 m_eglSurface = displayManager->surfaceForWindow(window, config); 97 ASSERT(m_eglSurface != EGL_NO_SURFACE); 98 99 m_eglContext = displayManager->contextForSurface(m_eglSurface); 100 EGLDisplayOpenVG::registerPlatformSurface(this); 101 } 102 103 // Constructor only accessible to EGLDisplayOpenVG for shared context 104 // initialization. The parameter types might define to void* like in the 105 // window surface constructor, so it can't be overloaded with all the required 106 // arguments and EGLDisplayOpenVG basically implements the constructor 107 // by itself. 108 SurfaceOpenVG::SurfaceOpenVG() 109 : m_activePainter(0) 110 , m_eglDisplay(EGL_NO_DISPLAY) 111 , m_eglSurface(EGL_NO_SURFACE) 112 , m_eglContext(EGL_NO_CONTEXT) 113 { 114 } 115 #endif 116 117 SurfaceOpenVG::~SurfaceOpenVG() 118 { 119 if (!isValid()) 120 return; 121 122 if (m_activePainter && this == m_activePainter->baseSurface()) 123 m_activePainter->end(); 124 125 #if PLATFORM(EGL) 126 EGLDisplayOpenVG::forDisplay(m_eglDisplay)->destroySurface(m_eglSurface); 127 EGLDisplayOpenVG::unregisterPlatformSurface(this); 128 #else 129 ASSERT_NOT_REACHED(); 130 #endif 131 } 132 133 bool SurfaceOpenVG::isValid() const 134 { 135 #if PLATFORM(EGL) 136 return (m_eglSurface != EGL_NO_SURFACE); 137 #else 138 ASSERT_NOT_REACHED(); 139 return false; 140 #endif 141 } 142 143 int SurfaceOpenVG::width() const 144 { 145 #if PLATFORM(EGL) 146 ASSERT(m_eglSurface != EGL_NO_SURFACE); 147 148 EGLint width; 149 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width); 150 ASSERT_EGL_NO_ERROR(); 151 return width; 152 #else 153 ASSERT_NOT_REACHED(); 154 return 0; 155 #endif 156 } 157 158 int SurfaceOpenVG::height() const 159 { 160 #if PLATFORM(EGL) 161 ASSERT(m_eglSurface != EGL_NO_SURFACE); 162 163 EGLint height; 164 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height); 165 ASSERT_EGL_NO_ERROR(); 166 return height; 167 #else 168 ASSERT_NOT_REACHED(); 169 return 0; 170 #endif 171 } 172 173 SurfaceOpenVG* SurfaceOpenVG::sharedSurface() const 174 { 175 #if PLATFORM(EGL) 176 ASSERT(m_eglSurface != EGL_NO_SURFACE); 177 return EGLDisplayOpenVG::forDisplay(m_eglDisplay)->sharedPlatformSurface(); 178 #else 179 ASSERT_NOT_REACHED(); 180 return 0; 181 #endif 182 } 183 184 void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode) 185 { 186 #if PLATFORM(EGL) 187 ASSERT(m_eglSurface != EGL_NO_SURFACE); 188 189 eglBindAPI(EGL_OPENVG_API); 190 ASSERT_EGL_NO_ERROR(); 191 EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); 192 ASSERT_EGL_NO_ERROR(); 193 194 if (currentSurface != m_eglSurface) { 195 // Save other context before switching over. 196 if (s_currentPainter && mode != DontSaveOrApplyPainterState 197 && s_currentPainter->surface()->m_eglSurface == currentSurface) 198 s_currentPainter->save(PainterOpenVG::KeepCurrentState); 199 200 eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 201 ASSERT_EGL_NO_ERROR(); 202 s_currentPainter = 0; 203 } 204 #endif 205 206 if (m_activePainter && mode == ApplyPainterStateOnSurfaceSwitch 207 && s_currentPainter != m_activePainter) { 208 m_activePainter->applyState(); 209 s_currentPainter = m_activePainter; 210 } 211 } 212 213 void SurfaceOpenVG::makeCompatibleCurrent() 214 { 215 #if PLATFORM(EGL) 216 ASSERT(m_eglSurface != EGL_NO_SURFACE); 217 218 eglBindAPI(EGL_OPENVG_API); 219 ASSERT_EGL_NO_ERROR(); 220 EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); 221 ASSERT_EGL_NO_ERROR(); 222 223 if (currentSurface == m_eglSurface) { 224 if (m_activePainter && s_currentPainter != m_activePainter) { 225 m_activePainter->applyState(); 226 s_currentPainter = m_activePainter; 227 } 228 } else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) { 229 // Save other context before switching over. 230 if (s_currentPainter && s_currentPainter->surface()->m_eglSurface == currentSurface) 231 s_currentPainter->save(PainterOpenVG::KeepCurrentState); 232 233 eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 234 ASSERT_EGL_NO_ERROR(); 235 s_currentPainter = 0; 236 } 237 // else: surfaces compatible, no need to switch contexts 238 #endif 239 } 240 241 void SurfaceOpenVG::flush() 242 { 243 #if PLATFORM(EGL) 244 ASSERT(m_eglSurface != EGL_NO_SURFACE); 245 246 eglSwapBuffers(m_eglDisplay, m_eglSurface); 247 ASSERT_EGL_NO_ERROR(); 248 #endif 249 } 250 251 void SurfaceOpenVG::setActivePainter(PainterOpenVG* painter) 252 { 253 ASSERT(isValid()); 254 255 // If painter is non-zero, we want to make sure there was no previous painter set. 256 ASSERT(!painter || !m_activePainter); 257 258 // Make sure a disabled painter isn't marked as global current painter anymore. 259 if (!painter && s_currentPainter == m_activePainter) 260 s_currentPainter = 0; 261 262 m_activePainter = painter; 263 } 264 265 PainterOpenVG* SurfaceOpenVG::activePainter() 266 { 267 ASSERT(isValid()); 268 return m_activePainter; 269 } 270 271 } 272