Changeset 55922 in webkit


Ignore:
Timestamp:
Mar 12, 2010 11:25:32 AM (14 years ago)
Author:
jpetsovits@rim.com
Message:

2010-03-12 Jakob Petsovits <jpetsovits@rim.com>

Reviewed by Dirk Schulze.

[OpenVG] Use masks to implement non-rectilinear clipping
https://bugs.webkit.org/show_bug.cgi?id=35544

Requires some additional context switching logic to
make sure the right context is current when dealing
with the mask, because we don't store it by ourselves.

Initial version of this code was written by
Eli Fidler <efidler@rim.com>, I did a couple of
bug fixes and efficiency improvements since then.

  • platform/graphics/openvg/GraphicsContextOpenVG.cpp: (WebCore::GraphicsContext::clipPath): (WebCore::GraphicsContext::clip): (WebCore::GraphicsContext::clipOut): (WebCore::GraphicsContext::clipOutEllipseInRect): (WebCore::GraphicsContext::addInnerRoundedRectClip):
  • platform/graphics/openvg/PainterOpenVG.cpp: (WebCore::PlatformPainterState::PlatformPainterState): (WebCore::PlatformPainterState::~PlatformPainterState): (WebCore::PlatformPainterState::maskingEnabled): (WebCore::PlatformPainterState::applyState): (WebCore::PlatformPainterState::saveMaskIfNecessary): (WebCore::PainterOpenVG::intersectClipRect): (WebCore::PainterOpenVG::clipPath): (WebCore::PainterOpenVG::save):
  • platform/graphics/openvg/PainterOpenVG.h: (WebCore::PainterOpenVG::):
  • platform/graphics/openvg/SurfaceOpenVG.cpp: (WebCore::SurfaceOpenVG::makeCurrent): (WebCore::SurfaceOpenVG::makeCompatibleCurrent):
  • platform/graphics/openvg/SurfaceOpenVG.h: (WebCore::SurfaceOpenVG::):
Location:
trunk/WebCore
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/WebCore/ChangeLog

    r55921 r55922  
     12010-03-12  Jakob Petsovits  <jpetsovits@rim.com>
     2
     3        Reviewed by Dirk Schulze.
     4
     5        [OpenVG] Use masks to implement non-rectilinear clipping
     6        https://bugs.webkit.org/show_bug.cgi?id=35544
     7
     8        Requires some additional context switching logic to
     9        make sure the right context is current when dealing
     10        with the mask, because we don't store it by ourselves.
     11
     12        Initial version of this code was written by
     13        Eli Fidler <efidler@rim.com>, I did a couple of
     14        bug fixes and efficiency improvements since then.
     15
     16        * platform/graphics/openvg/GraphicsContextOpenVG.cpp:
     17        (WebCore::GraphicsContext::clipPath):
     18        (WebCore::GraphicsContext::clip):
     19        (WebCore::GraphicsContext::clipOut):
     20        (WebCore::GraphicsContext::clipOutEllipseInRect):
     21        (WebCore::GraphicsContext::addInnerRoundedRectClip):
     22        * platform/graphics/openvg/PainterOpenVG.cpp:
     23        (WebCore::PlatformPainterState::PlatformPainterState):
     24        (WebCore::PlatformPainterState::~PlatformPainterState):
     25        (WebCore::PlatformPainterState::maskingEnabled):
     26        (WebCore::PlatformPainterState::applyState):
     27        (WebCore::PlatformPainterState::saveMaskIfNecessary):
     28        (WebCore::PainterOpenVG::intersectClipRect):
     29        (WebCore::PainterOpenVG::clipPath):
     30        (WebCore::PainterOpenVG::save):
     31        * platform/graphics/openvg/PainterOpenVG.h:
     32        (WebCore::PainterOpenVG::):
     33        * platform/graphics/openvg/SurfaceOpenVG.cpp:
     34        (WebCore::SurfaceOpenVG::makeCurrent):
     35        (WebCore::SurfaceOpenVG::makeCompatibleCurrent):
     36        * platform/graphics/openvg/SurfaceOpenVG.h:
     37        (WebCore::SurfaceOpenVG::):
     38
    1392010-03-12  Jian Li  <jianli@chromium.org>
    240
  • trunk/WebCore/platform/graphics/openvg/GraphicsContextOpenVG.cpp

    r55371 r55922  
    227227        return;
    228228
    229     notImplemented();
    230     UNUSED_PARAM(clipRule);
     229    m_data->clipPath(*(m_data->currentPath()), PainterOpenVG::IntersectClip, clipRule);
    231230}
    232231
     
    414413        return;
    415414
    416     notImplemented();
    417     UNUSED_PARAM(path);
     415    m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
    418416}
    419417
     
    428426        return;
    429427
    430     notImplemented();
    431     UNUSED_PARAM(path);
     428    m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
    432429}
    433430
     
    470467        return;
    471468
    472     notImplemented();
    473     UNUSED_PARAM(rect);
     469    Path path;
     470    path.addRect(rect);
     471    m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
    474472}
    475473
     
    479477        return;
    480478
    481     notImplemented();
    482     UNUSED_PARAM(rect);
     479    Path path;
     480    path.addEllipse(rect);
     481    m_data->clipPath(path, PainterOpenVG::SubtractClip, m_common->state.fillRule);
    483482}
    484483
     
    498497        return;
    499498
    500     notImplemented();
    501     UNUSED_PARAM(rect);
    502     UNUSED_PARAM(thickness);
     499    Path path;
     500    path.addEllipse(rect);
     501    path.addEllipse(FloatRect(rect.x() + thickness, rect.y() + thickness,
     502        rect.width() - (thickness * 2), rect.height() - (thickness * 2)));
     503
     504    m_data->clipPath(path, PainterOpenVG::IntersectClip, m_common->state.fillRule);
    503505}
    504506
  • trunk/WebCore/platform/graphics/openvg/PainterOpenVG.cpp

    r55371 r55922  
    108108    bool scissoringEnabled;
    109109    FloatRect scissorRect;
     110#ifdef OPENVG_VERSION_1_1
     111    bool maskingChangedAndEnabled;
     112    VGMaskLayer mask;
     113#endif
    110114
    111115    Color fillColor;
     
    125129        , opacity(1.0)
    126130        , scissoringEnabled(false)
     131#ifdef OPENVG_VERSION_1_1
     132        , maskingChangedAndEnabled(false)
     133        , mask(VG_INVALID_HANDLE)
     134#endif
    127135        , fillColor(Color::black)
    128136        , strokeStyle(NoStroke)
     
    136144    }
    137145
     146    ~PlatformPainterState()
     147    {
     148#ifdef OPENVG_VERSION_1_1
     149        if (maskingChangedAndEnabled && mask != VG_INVALID_HANDLE) {
     150            vgDestroyMaskLayer(mask);
     151            ASSERT_VG_NO_ERROR();
     152            mask = VG_INVALID_HANDLE;
     153        }
     154#endif
     155    }
     156
    138157    PlatformPainterState(const PlatformPainterState& state)
    139158    {
     
    142161        scissoringEnabled = state.scissoringEnabled;
    143162        scissorRect = state.scissorRect;
     163#ifdef OPENVG_VERSION_1_1
     164        maskingChangedAndEnabled = false;
     165        mask = state.mask;
     166#endif
    144167        copyPaintState(&state);
     168    }
     169
     170    inline bool maskingEnabled()
     171    {
     172        return maskingChangedAndEnabled || mask != VG_INVALID_HANDLE;
    145173    }
    146174
     
    185213        applyTransformation(painter);
    186214        applyScissorRect();
     215
     216#ifdef OPENVG_VERSION_1_1
     217        if (maskingEnabled()) {
     218            vgSeti(VG_MASKING, VG_TRUE);
     219            if (mask != VG_INVALID_HANDLE)
     220                vgMask(mask, VG_SET_MASK, 0, 0, painter->surface()->width(), painter->surface()->height());
     221        } else
     222            vgSeti(VG_MASKING, VG_FALSE);
     223#endif
     224        ASSERT_VG_NO_ERROR();
    187225    }
    188226
     
    336374        return (compositeOperation == CompositeSourceOver && !fillColor.alpha());
    337375    }
     376
     377    void saveMaskIfNecessary(PainterOpenVG* painter)
     378    {
     379#ifdef OPENVG_VERSION_1_1
     380        if (maskingChangedAndEnabled) {
     381            if (mask != VG_INVALID_HANDLE) {
     382                vgDestroyMaskLayer(mask);
     383                ASSERT_VG_NO_ERROR();
     384            }
     385            mask = vgCreateMaskLayer(painter->surface()->width(), painter->surface()->height());
     386            ASSERT(mask != VG_INVALID_HANDLE);
     387            vgCopyMask(mask, 0, 0, 0, 0, painter->surface()->width(), painter->surface()->height());
     388            ASSERT_VG_NO_ERROR();
     389        }
     390#endif
     391    }
    338392};
    339393
     
    731785    else {
    732786        // The transformed scissorRect cannot be represented as FloatRect
    733         // anymore, so we need to perform masking instead. Not yet implemented.
    734         notImplemented();
    735     }
     787        // anymore, so we need to perform masking instead.
     788        Path scissorRectPath;
     789        scissorRectPath.addRect(rect);
     790        clipPath(scissorRectPath, PainterOpenVG::IntersectClip);
     791    }
     792}
     793
     794void PainterOpenVG::clipPath(const Path& path, PainterOpenVG::ClipOperation maskOp, WindRule clipRule)
     795{
     796#ifdef OPENVG_VERSION_1_1
     797    ASSERT(m_state);
     798    m_surface->makeCurrent();
     799
     800    if (m_state->mask != VG_INVALID_HANDLE && !m_state->maskingChangedAndEnabled) {
     801        // The parent's mask has been inherited - dispose the handle so that
     802        // it won't be overwritten.
     803        m_state->maskingChangedAndEnabled = true;
     804        m_state->mask = VG_INVALID_HANDLE;
     805    } else if (!m_state->maskingEnabled()) {
     806        // None of the parent painter states had a mask enabled yet.
     807        m_state->maskingChangedAndEnabled = true;
     808        vgSeti(VG_MASKING, VG_TRUE);
     809        // Make sure not to inherit previous mask state from previously written
     810        // (but disabled) masks. For VG_FILL_MASK the first argument is ignored,
     811        // we pass VG_INVALID_HANDLE which is what the OpenVG spec suggests.
     812        vgMask(VG_INVALID_HANDLE, VG_FILL_MASK, 0, 0, m_surface->width(), m_surface->height());
     813    }
     814
     815    // Intersect the path from the mask, or subtract it from there.
     816    // (In either case we always decrease the visible area, never increase it,
     817    // which means masking never has to modify scissor rectangles.)
     818    vgSeti(VG_FILL_RULE, toVGFillRule(clipRule));
     819    vgRenderToMask(path.platformPath()->vgPath(), VG_FILL_PATH, (VGMaskOperation) maskOp);
     820    ASSERT_VG_NO_ERROR();
     821#elseif
     822    notImplemented();
     823#endif
    736824}
    737825
     
    9941082
    9951083    if (saveMode == PainterOpenVG::CreateNewState) {
     1084        m_state->saveMaskIfNecessary(this);
    9961085        PlatformPainterState* state = new PlatformPainterState(*m_state);
    9971086        m_stateStack.append(state);
    9981087        m_state = m_stateStack.last();
    999     } else { // if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) {
     1088    } else if (saveMode == PainterOpenVG::CreateNewStateWithPaintStateOnly) {
     1089        m_state->saveMaskIfNecessary(this);
    10001090        PlatformPainterState* state = new PlatformPainterState();
    10011091        state->copyPaintState(m_state);
    10021092        m_stateStack.append(state);
    10031093        m_state = m_stateStack.last();
    1004     }
     1094    } else // if (saveMode == PainterOpenVG::KeepCurrentState)
     1095        m_state->saveMaskIfNecessary(this);
    10051096}
    10061097
  • trunk/WebCore/platform/graphics/openvg/PainterOpenVG.h

    r55633 r55922  
    4848    enum SaveMode {
    4949        CreateNewState,
     50        KeepCurrentState,
    5051        CreateNewStateWithPaintStateOnly // internal usage only, do not use outside PainterOpenVG
     52    };
     53    enum ClipOperation {
     54        IntersectClip = VG_INTERSECT_MASK,
     55        SubtractClip = VG_SUBTRACT_MASK
    5156    };
    5257
     
    105110
    106111    void intersectClipRect(const FloatRect&);
     112    void clipPath(const Path&, PainterOpenVG::ClipOperation, WindRule clipRule = RULE_NONZERO);
    107113
    108114    void save(PainterOpenVG::SaveMode saveMode = CreateNewState);
  • trunk/WebCore/platform/graphics/openvg/SurfaceOpenVG.cpp

    r55919 r55922  
    193193
    194194    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
    195200        eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
    196201        ASSERT_EGL_NO_ERROR();
     
    222227        }
    223228    } 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
    224233        eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext);
    225234        ASSERT_EGL_NO_ERROR();
  • trunk/WebCore/platform/graphics/openvg/SurfaceOpenVG.h

    r55919 r55922  
    4848        ApplyPainterStateOnSurfaceSwitch,
    4949        DontApplyPainterState,
     50        DontSaveOrApplyPainterState
    5051    };
    5152
Note: See TracChangeset for help on using the changeset viewer.