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(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr) 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->defaultWindowConfig(); 77 m_eglSurface = displayManager->surfaceForWindow(window, config); 78 ASSERT(m_eglSurface != EGL_NO_SURFACE); 79 80 m_eglContext = displayManager->contextForSurface(m_eglSurface); 81 EGLDisplayOpenVG::registerPlatformSurface(this); 82 } 83 84 // Constructor only accessible to EGLDisplayOpenVG for shared context 85 // initialization. The parameter types might define to void* like in the 86 // window surface constructor, so it can't be overloaded with all the required 87 // arguments and EGLDisplayOpenVG basically implements the constructor 88 // by itself. 89 SurfaceOpenVG::SurfaceOpenVG() 90 : m_activePainter(0) 91 , m_eglDisplay(EGL_NO_DISPLAY) 92 , m_eglSurface(EGL_NO_SURFACE) 93 , m_eglContext(EGL_NO_CONTEXT) 94 { 95 } 96 #endif 97 98 SurfaceOpenVG::~SurfaceOpenVG() 99 { 100 if (!isValid()) 101 return; 102 103 if (m_activePainter && this == m_activePainter->baseSurface()) 104 m_activePainter->end(); 105 106 #if PLATFORM(EGL) 107 EGLDisplayOpenVG::forDisplay(m_eglDisplay)->destroySurface(m_eglSurface); 108 EGLDisplayOpenVG::unregisterPlatformSurface(this); 109 #else 110 ASSERT_NOT_REACHED(); 111 #endif 112 } 113 114 bool SurfaceOpenVG::isValid() const 115 { 116 #if PLATFORM(EGL) 117 return (m_eglSurface != EGL_NO_SURFACE); 118 #else 119 ASSERT_NOT_REACHED(); 120 return false; 121 #endif 122 } 123 124 int SurfaceOpenVG::width() const 125 { 126 #if PLATFORM(EGL) 127 ASSERT(m_eglSurface != EGL_NO_SURFACE); 128 129 EGLint width; 130 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width); 131 ASSERT_EGL_NO_ERROR(); 132 return width; 133 #else 134 ASSERT_NOT_REACHED(); 135 return 0; 136 #endif 137 } 138 139 int SurfaceOpenVG::height() const 140 { 141 #if PLATFORM(EGL) 142 ASSERT(m_eglSurface != EGL_NO_SURFACE); 143 144 EGLint height; 145 eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height); 146 ASSERT_EGL_NO_ERROR(); 147 return height; 148 #else 149 ASSERT_NOT_REACHED(); 150 return 0; 151 #endif 152 } 153 154 SurfaceOpenVG* SurfaceOpenVG::sharedSurface() const 155 { 156 #if PLATFORM(EGL) 157 ASSERT(m_eglSurface != EGL_NO_SURFACE); 158 return EGLDisplayOpenVG::forDisplay(m_eglDisplay)->sharedPlatformSurface(); 159 #else 160 ASSERT_NOT_REACHED(); 161 return 0; 162 #endif 163 } 164 165 void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode) 166 { 167 #if PLATFORM(EGL) 168 ASSERT(m_eglSurface != EGL_NO_SURFACE); 169 170 eglBindAPI(EGL_OPENVG_API); 171 ASSERT_EGL_NO_ERROR(); 172 EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); 173 ASSERT_EGL_NO_ERROR(); 174 175 if (currentSurface != m_eglSurface) { 176 eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 177 ASSERT_EGL_NO_ERROR(); 178 s_currentPainter = 0; 179 } 180 #endif 181 182 if (m_activePainter && mode == ApplyPainterStateOnSurfaceSwitch 183 && s_currentPainter != m_activePainter) { 184 m_activePainter->applyState(); 185 s_currentPainter = m_activePainter; 186 } 187 } 188 189 void SurfaceOpenVG::makeCompatibleCurrent() 190 { 191 #if PLATFORM(EGL) 192 ASSERT(m_eglSurface != EGL_NO_SURFACE); 193 194 eglBindAPI(EGL_OPENVG_API); 195 ASSERT_EGL_NO_ERROR(); 196 EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); 197 ASSERT_EGL_NO_ERROR(); 198 199 if (currentSurface == m_eglSurface) { 200 if (m_activePainter && s_currentPainter != m_activePainter) { 201 m_activePainter->applyState(); 202 s_currentPainter = m_activePainter; 203 } 204 } else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) { 205 eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); 206 ASSERT_EGL_NO_ERROR(); 207 s_currentPainter = 0; 208 } 209 // else: surfaces compatible, no need to switch contexts 210 #endif 211 } 212 213 void SurfaceOpenVG::flush() 214 { 215 #if PLATFORM(EGL) 216 ASSERT(m_eglSurface != EGL_NO_SURFACE); 217 218 eglSwapBuffers(m_eglDisplay, m_eglSurface); 219 ASSERT_EGL_NO_ERROR(); 220 #endif 221 } 222 223 void SurfaceOpenVG::setActivePainter(PainterOpenVG* painter) 224 { 225 ASSERT(isValid()); 226 227 // If painter is non-zero, we want to make sure there was no previous painter set. 228 ASSERT(!painter || !m_activePainter); 229 230 // Make sure a disabled painter isn't marked as global current painter anymore. 231 if (!painter && s_currentPainter == m_activePainter) 232 s_currentPainter = 0; 233 234 m_activePainter = painter; 235 } 236 237 PainterOpenVG* SurfaceOpenVG::activePainter() 238 { 239 ASSERT(isValid()); 240 return m_activePainter; 241 } 242 243 } 244