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/loader/cache/DocumentResource.h"
     35 #include "core/loader/cache/DocumentResourceReference.h"
     36 #include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
     37 #include "core/platform/graphics/filters/custom/CustomFilterProgram.h"
     38 #include "core/rendering/FilterEffectRenderer.h"
     39 #include "core/rendering/RenderLayer.h"
     40 #include "core/rendering/svg/RenderSVGResourceContainer.h"
     41 #include "core/svg/SVGElement.h"
     42 #include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
     43 #include "core/svg/graphics/filters/SVGFilter.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->getOperationType() != FilterOperation::REFERENCE)
    120             continue;
    121         ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation.get());
    122         DocumentResourceReference* documentReference = referenceFilterOperation->documentResourceReference();
    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->renderer() || !filter->renderer()->isSVGResourceFilter())
    134                 continue;
    135             filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(m_layer);
    136             m_internalSVGReferences.append(filter);
    137         }
    138     }
    139 }
    140 
    141 void RenderLayerFilterInfo::removeReferenceFilterClients()
    142 {
    143     for (size_t i = 0; i < m_externalSVGReferences.size(); ++i)
    144         m_externalSVGReferences.at(i)->removeClient(this);
    145     m_externalSVGReferences.clear();
    146     for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) {
    147         Element* filter = m_internalSVGReferences.at(i).get();
    148         if (!filter->renderer())
    149             continue;
    150         filter->renderer()->toRenderSVGResourceContainer()->removeClientRenderLayer(m_layer);
    151     }
    152     m_internalSVGReferences.clear();
    153 }
    154 
    155 void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
    156 {
    157     RenderObject* renderer = m_layer->renderer();
    158     toElement(renderer->node())->scheduleLayerUpdate();
    159     renderer->repaint();
    160 }
    161 
    162 void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations)
    163 {
    164     if (!operations.size()) {
    165         removeCustomFilterClients();
    166         return;
    167     }
    168     CustomFilterProgramList cachedCustomFilterPrograms;
    169     for (size_t i = 0; i < operations.size(); ++i) {
    170         const FilterOperation* filterOperation = operations.at(i);
    171         if (filterOperation->getOperationType() != FilterOperation::CUSTOM)
    172             continue;
    173         const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation);
    174         RefPtr<CustomFilterProgram> program = customFilterOperation->program();
    175         cachedCustomFilterPrograms.append(program);
    176         program->addClient(this);
    177     }
    178     // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged.
    179     removeCustomFilterClients();
    180     m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
    181 }
    182 
    183 void RenderLayerFilterInfo::removeCustomFilterClients()
    184 {
    185     for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i)
    186         m_cachedCustomFilterPrograms.at(i)->removeClient(this);
    187     m_cachedCustomFilterPrograms.clear();
    188 }
    189 
    190 } // namespace WebCore
    191 
    192