Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1. Redistributions of source code must retain the above
      9  *    copyright notice, this list of conditions and the following
     10  *    disclaimer.
     11  * 2. Redistributions in binary form must reproduce the above
     12  *    copyright notice, this list of conditions and the following
     13  *    disclaimer in the documentation and/or other materials
     14  *    provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY
     17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
     20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
     21  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
     25  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
     26  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27  * SUCH DAMAGE.
     28  */
     29 
     30 #include "config.h"
     31 
     32 #include "core/rendering/RenderLayerFilterInfo.h"
     33 
     34 #include "core/fetch/DocumentResourceReference.h"
     35 #include "core/rendering/FilterEffectRenderer.h"
     36 #include "core/rendering/RenderLayer.h"
     37 #include "core/rendering/svg/ReferenceFilterBuilder.h"
     38 #include "core/rendering/svg/RenderSVGResourceContainer.h"
     39 #include "core/svg/SVGFilterElement.h"
     40 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
     41 #include "core/svg/graphics/filters/SVGFilter.h"
     42 #include "platform/graphics/filters/custom/CustomFilterOperation.h"
     43 #include "platform/graphics/filters/custom/CustomFilterProgram.h"
     44 
     45 namespace WebCore {
     46 
     47 RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0;
     48 
     49 RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer)
     50 {
     51     if (!s_filterMap)
     52         return 0;
     53     RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
     54     return (iter != s_filterMap->end()) ? iter->value : 0;
     55 }
     56 
     57 RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer)
     58 {
     59     if (!s_filterMap)
     60         s_filterMap = new RenderLayerFilterInfoMap();
     61 
     62     RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
     63     if (iter != s_filterMap->end()) {
     64         ASSERT(layer->hasFilterInfo());
     65         return iter->value;
     66     }
     67 
     68     RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer);
     69     s_filterMap->set(layer, filter);
     70     layer->setHasFilterInfo(true);
     71     return filter;
     72 }
     73 
     74 void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer)
     75 {
     76     if (!s_filterMap)
     77         return;
     78     RenderLayerFilterInfo* filter = s_filterMap->take(layer);
     79     if (s_filterMap->isEmpty()) {
     80         delete s_filterMap;
     81         s_filterMap = 0;
     82     }
     83     if (!filter) {
     84         ASSERT(!layer->hasFilterInfo());
     85         return;
     86     }
     87     layer->setHasFilterInfo(false);
     88     delete filter;
     89 }
     90 
     91 RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
     92     : m_layer(layer)
     93 {
     94 }
     95 
     96 RenderLayerFilterInfo::~RenderLayerFilterInfo()
     97 {
     98     removeCustomFilterClients();
     99     removeReferenceFilterClients();
    100 }
    101 
    102 void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer)
    103 {
    104     m_renderer = renderer;
    105 }
    106 
    107 void RenderLayerFilterInfo::notifyFinished(Resource*)
    108 {
    109     RenderObject* renderer = m_layer->renderer();
    110     toElement(renderer->node())->scheduleLayerUpdate();
    111     renderer->repaint();
    112 }
    113 
    114 void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
    115 {
    116     removeReferenceFilterClients();
    117     for (size_t i = 0; i < operations.size(); ++i) {
    118         RefPtr<FilterOperation> filterOperation = operations.operations().at(i);
    119         if (filterOperation->type() != FilterOperation::REFERENCE)
    120             continue;
    121         ReferenceFilterOperation* referenceFilterOperation = toReferenceFilterOperation(filterOperation.get());
    122         DocumentResourceReference* documentReference = ReferenceFilterBuilder::documentResourceReference(referenceFilterOperation);
    123         DocumentResource* cachedSVGDocument = documentReference ? documentReference->document() : 0;
    124 
    125         if (cachedSVGDocument) {
    126             // Reference is external; wait for notifyFinished().
    127             cachedSVGDocument->addClient(this);
    128             m_externalSVGReferences.append(cachedSVGDocument);
    129         } else {
    130             // Reference is internal; add layer as a client so we can trigger
    131             // filter repaint on SVG attribute change.
    132             Element* filter = m_layer->renderer()->node()->document().getElementById(referenceFilterOperation->fragment());
    133             if (!filter || !filter->hasTagName(SVGNames::filterTag))
    134                 continue;
    135             if (filter->renderer())
    136                 toRenderSVGResourceContainer(filter->renderer())->addClientRenderLayer(m_layer);
    137             else
    138                 toSVGFilterElement(filter)->addClient(m_layer->renderer()->node());
    139             m_internalSVGReferences.append(filter);
    140         }
    141     }
    142 }
    143 
    144 void RenderLayerFilterInfo::removeReferenceFilterClients()
    145 {
    146     for (size_t i = 0; i < m_externalSVGReferences.size(); ++i)
    147         m_externalSVGReferences.at(i)->removeClient(this);
    148     m_externalSVGReferences.clear();
    149     for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) {
    150         Element* filter = m_internalSVGReferences.at(i).get();
    151         if (filter->renderer())
    152             toRenderSVGResourceContainer(filter->renderer())->removeClientRenderLayer(m_layer);
    153         else
    154             toSVGFilterElement(filter)->removeClient(m_layer->renderer()->node());
    155     }
    156     m_internalSVGReferences.clear();
    157 }
    158 
    159 void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
    160 {
    161     RenderObject* renderer = m_layer->renderer();
    162     toElement(renderer->node())->scheduleLayerUpdate();
    163     renderer->repaint();
    164 }
    165 
    166 void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations)
    167 {
    168     if (!operations.size()) {
    169         removeCustomFilterClients();
    170         return;
    171     }
    172     CustomFilterProgramList cachedCustomFilterPrograms;
    173     for (size_t i = 0; i < operations.size(); ++i) {
    174         const FilterOperation* filterOperation = operations.at(i);
    175         if (filterOperation->type() != FilterOperation::CUSTOM)
    176             continue;
    177         RefPtr<CustomFilterProgram> program = toCustomFilterOperation(filterOperation)->program();
    178         cachedCustomFilterPrograms.append(program);
    179         program->addClient(this);
    180     }
    181     // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged.
    182     removeCustomFilterClients();
    183     m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
    184 }
    185 
    186 void RenderLayerFilterInfo::removeCustomFilterClients()
    187 {
    188     for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i)
    189         m_cachedCustomFilterPrograms.at(i)->removeClient(this);
    190     m_cachedCustomFilterPrograms.clear();
    191 }
    192 
    193 } // namespace WebCore
    194 
    195