| /* |
| * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Library General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Library General Public License for more details. |
| * |
| * You should have received a copy of the GNU Library General Public License |
| * along with this library; see the file COPYING.LIB. If not, write to |
| * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| |
| #include "config.h" |
| #include "SurfaceOpenVG.h" |
| |
| #include "IntSize.h" |
| #include "PainterOpenVG.h" |
| |
| #if PLATFORM(EGL) |
| #include "EGLDisplayOpenVG.h" |
| #include "EGLUtils.h" |
| #endif |
| |
| #include <wtf/Assertions.h> |
| |
| namespace WebCore { |
| |
| PainterOpenVG* SurfaceOpenVG::s_currentPainter = 0; |
| |
| SurfaceOpenVG* SurfaceOpenVG::currentSurface() |
| { |
| #if PLATFORM(EGL) |
| return EGLDisplayOpenVG::currentSurface(); |
| #else |
| ASSERT_NOT_REACHED(); |
| return 0; |
| #endif |
| } |
| |
| #if PLATFORM(EGL) |
| SurfaceOpenVG::SurfaceOpenVG(const IntSize& size, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode) |
| : m_activePainter(0) |
| , m_eglDisplay(display) |
| , m_eglSurface(EGL_NO_SURFACE) |
| , m_eglContext(EGL_NO_CONTEXT) |
| { |
| ASSERT(m_eglDisplay != EGL_NO_DISPLAY); |
| |
| EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); |
| EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig(); |
| m_eglSurface = displayManager->createPbufferSurface(size, config, errorCode); |
| |
| if (m_eglSurface == EGL_NO_SURFACE) |
| return; |
| |
| m_eglContext = displayManager->contextForSurface(m_eglSurface); |
| EGLDisplayOpenVG::registerPlatformSurface(this); |
| } |
| |
| SurfaceOpenVG::SurfaceOpenVG(EGLClientBuffer buffer, EGLenum bufferType, const EGLDisplay& display, EGLConfig* confPtr, EGLint* errorCode) |
| : m_activePainter(0) |
| , m_eglDisplay(display) |
| , m_eglSurface(EGL_NO_SURFACE) |
| , m_eglContext(EGL_NO_CONTEXT) |
| { |
| ASSERT(m_eglDisplay != EGL_NO_DISPLAY); |
| |
| EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); |
| EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultPbufferConfig(); |
| m_eglSurface = displayManager->createPbufferFromClientBuffer(buffer, bufferType, config, errorCode); |
| |
| if (m_eglSurface == EGL_NO_SURFACE) |
| return; |
| |
| m_eglContext = displayManager->contextForSurface(m_eglSurface); |
| EGLDisplayOpenVG::registerPlatformSurface(this); |
| } |
| |
| SurfaceOpenVG::SurfaceOpenVG(EGLNativeWindowType window, const EGLDisplay& display, EGLConfig* confPtr) |
| : m_activePainter(0) |
| , m_eglDisplay(display) |
| , m_eglSurface(EGL_NO_SURFACE) |
| , m_eglContext(EGL_NO_CONTEXT) |
| { |
| ASSERT(m_eglDisplay != EGL_NO_DISPLAY); |
| |
| EGLDisplayOpenVG* displayManager = EGLDisplayOpenVG::forDisplay(m_eglDisplay); |
| EGLConfig config = confPtr ? (*confPtr) : displayManager->defaultWindowConfig(); |
| m_eglSurface = displayManager->surfaceForWindow(window, config); |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| m_eglContext = displayManager->contextForSurface(m_eglSurface); |
| EGLDisplayOpenVG::registerPlatformSurface(this); |
| } |
| |
| // Constructor only accessible to EGLDisplayOpenVG for shared context |
| // initialization. The parameter types might define to void* like in the |
| // window surface constructor, so it can't be overloaded with all the required |
| // arguments and EGLDisplayOpenVG basically implements the constructor |
| // by itself. |
| SurfaceOpenVG::SurfaceOpenVG() |
| : m_activePainter(0) |
| , m_eglDisplay(EGL_NO_DISPLAY) |
| , m_eglSurface(EGL_NO_SURFACE) |
| , m_eglContext(EGL_NO_CONTEXT) |
| { |
| } |
| #endif |
| |
| SurfaceOpenVG::~SurfaceOpenVG() |
| { |
| if (!isValid()) |
| return; |
| |
| if (m_activePainter && this == m_activePainter->baseSurface()) |
| m_activePainter->end(); |
| |
| #if PLATFORM(EGL) |
| EGLDisplayOpenVG::forDisplay(m_eglDisplay)->destroySurface(m_eglSurface); |
| EGLDisplayOpenVG::unregisterPlatformSurface(this); |
| #else |
| ASSERT_NOT_REACHED(); |
| #endif |
| } |
| |
| bool SurfaceOpenVG::isValid() const |
| { |
| #if PLATFORM(EGL) |
| return (m_eglSurface != EGL_NO_SURFACE); |
| #else |
| ASSERT_NOT_REACHED(); |
| return false; |
| #endif |
| } |
| |
| int SurfaceOpenVG::width() const |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| EGLint width; |
| eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_WIDTH, &width); |
| ASSERT_EGL_NO_ERROR(); |
| return width; |
| #else |
| ASSERT_NOT_REACHED(); |
| return 0; |
| #endif |
| } |
| |
| int SurfaceOpenVG::height() const |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| EGLint height; |
| eglQuerySurface(m_eglDisplay, m_eglSurface, EGL_HEIGHT, &height); |
| ASSERT_EGL_NO_ERROR(); |
| return height; |
| #else |
| ASSERT_NOT_REACHED(); |
| return 0; |
| #endif |
| } |
| |
| SurfaceOpenVG* SurfaceOpenVG::sharedSurface() const |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| return EGLDisplayOpenVG::forDisplay(m_eglDisplay)->sharedPlatformSurface(); |
| #else |
| ASSERT_NOT_REACHED(); |
| return 0; |
| #endif |
| } |
| |
| void SurfaceOpenVG::makeCurrent(MakeCurrentMode mode) |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| eglBindAPI(EGL_OPENVG_API); |
| ASSERT_EGL_NO_ERROR(); |
| EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); |
| ASSERT_EGL_NO_ERROR(); |
| |
| if (currentSurface != m_eglSurface) { |
| // Save other context before switching over. |
| if (s_currentPainter && mode != DontSaveOrApplyPainterState |
| && s_currentPainter->surface()->m_eglSurface == currentSurface) |
| s_currentPainter->save(PainterOpenVG::KeepCurrentState); |
| |
| eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); |
| ASSERT_EGL_NO_ERROR(); |
| s_currentPainter = 0; |
| } |
| #endif |
| |
| if (m_activePainter && mode == ApplyPainterStateOnSurfaceSwitch |
| && s_currentPainter != m_activePainter) { |
| m_activePainter->applyState(); |
| s_currentPainter = m_activePainter; |
| } |
| } |
| |
| void SurfaceOpenVG::makeCompatibleCurrent() |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| eglBindAPI(EGL_OPENVG_API); |
| ASSERT_EGL_NO_ERROR(); |
| EGLSurface currentSurface = eglGetCurrentSurface(EGL_DRAW); |
| ASSERT_EGL_NO_ERROR(); |
| |
| if (currentSurface == m_eglSurface) { |
| if (m_activePainter && s_currentPainter != m_activePainter) { |
| m_activePainter->applyState(); |
| s_currentPainter = m_activePainter; |
| } |
| } else if (!EGLDisplayOpenVG::forDisplay(m_eglDisplay)->surfacesCompatible(currentSurface, m_eglSurface)) { |
| // Save other context before switching over. |
| if (s_currentPainter && s_currentPainter->surface()->m_eglSurface == currentSurface) |
| s_currentPainter->save(PainterOpenVG::KeepCurrentState); |
| |
| eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); |
| ASSERT_EGL_NO_ERROR(); |
| s_currentPainter = 0; |
| } |
| // else: surfaces compatible, no need to switch contexts |
| #endif |
| } |
| |
| void SurfaceOpenVG::flush() |
| { |
| #if PLATFORM(EGL) |
| ASSERT(m_eglSurface != EGL_NO_SURFACE); |
| |
| eglSwapBuffers(m_eglDisplay, m_eglSurface); |
| ASSERT_EGL_NO_ERROR(); |
| #endif |
| } |
| |
| void SurfaceOpenVG::setActivePainter(PainterOpenVG* painter) |
| { |
| ASSERT(isValid()); |
| |
| // If painter is non-zero, we want to make sure there was no previous painter set. |
| ASSERT(!painter || !m_activePainter); |
| |
| // Make sure a disabled painter isn't marked as global current painter anymore. |
| if (!painter && s_currentPainter == m_activePainter) |
| s_currentPainter = 0; |
| |
| m_activePainter = painter; |
| } |
| |
| PainterOpenVG* SurfaceOpenVG::activePainter() |
| { |
| ASSERT(isValid()); |
| return m_activePainter; |
| } |
| |
| } |