Home | History | Annotate | Download | only in openvg
      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