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(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