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#if ENABLE(CSS_FILTERS) 33#include "RenderLayerFilterInfo.h" 34 35#include "FilterEffectRenderer.h" 36#include "RenderLayer.h" 37 38#if ENABLE(SVG) 39#include "CachedSVGDocument.h" 40#include "CachedSVGDocumentReference.h" 41#include "SVGElement.h" 42#include "SVGFilter.h" 43#include "SVGFilterPrimitiveStandardAttributes.h" 44#endif 45 46#if ENABLE(CSS_SHADERS) 47#include "CustomFilterOperation.h" 48#include "CustomFilterProgram.h" 49#endif 50 51namespace WebCore { 52 53RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0; 54 55RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer) 56{ 57 if (!s_filterMap) 58 return 0; 59 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 60 return (iter != s_filterMap->end()) ? iter->value : 0; 61} 62 63RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer) 64{ 65 if (!s_filterMap) 66 s_filterMap = new RenderLayerFilterInfoMap(); 67 68 RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer); 69 if (iter != s_filterMap->end()) { 70 ASSERT(layer->hasFilterInfo()); 71 return iter->value; 72 } 73 74 RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer); 75 s_filterMap->set(layer, filter); 76 layer->setHasFilterInfo(true); 77 return filter; 78} 79 80void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer) 81{ 82 if (!s_filterMap) 83 return; 84 RenderLayerFilterInfo* filter = s_filterMap->take(layer); 85 if (s_filterMap->isEmpty()) { 86 delete s_filterMap; 87 s_filterMap = 0; 88 } 89 if (!filter) { 90 ASSERT(!layer->hasFilterInfo()); 91 return; 92 } 93 layer->setHasFilterInfo(false); 94 delete filter; 95} 96 97RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer) 98 : m_layer(layer) 99{ 100} 101 102RenderLayerFilterInfo::~RenderLayerFilterInfo() 103{ 104#if ENABLE(CSS_SHADERS) 105 removeCustomFilterClients(); 106#endif 107#if ENABLE(SVG) 108 removeReferenceFilterClients(); 109#endif 110} 111 112void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer) 113{ 114 m_renderer = renderer; 115} 116 117#if ENABLE(SVG) 118void RenderLayerFilterInfo::notifyFinished(CachedResource*) 119{ 120 m_layer->filterNeedsRepaint(); 121} 122 123void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations) 124{ 125 removeReferenceFilterClients(); 126 for (size_t i = 0; i < operations.size(); ++i) { 127 RefPtr<FilterOperation> filterOperation = operations.operations().at(i); 128 if (filterOperation->getOperationType() != FilterOperation::REFERENCE) 129 continue; 130 ReferenceFilterOperation* referenceFilterOperation = toReferenceFilterOperation(filterOperation.get()); 131 CachedSVGDocumentReference* documentReference = referenceFilterOperation->cachedSVGDocumentReference(); 132 CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : 0; 133 134 if (cachedSVGDocument) { 135 // Reference is external; wait for notifyFinished(). 136 cachedSVGDocument->addClient(this); 137 m_externalSVGReferences.append(cachedSVGDocument); 138 } else { 139 // Reference is internal; add layer as a client so we can trigger 140 // filter repaint on SVG attribute change. 141 Element* filter = m_layer->renderer()->document()->getElementById(referenceFilterOperation->fragment()); 142 143 if (!filter || !filter->renderer() || !filter->renderer()->isSVGResourceFilter()) 144 continue; 145 filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(m_layer); 146 m_internalSVGReferences.append(filter); 147 } 148 } 149} 150 151void RenderLayerFilterInfo::removeReferenceFilterClients() 152{ 153 for (size_t i = 0; i < m_externalSVGReferences.size(); ++i) 154 m_externalSVGReferences.at(i)->removeClient(this); 155 m_externalSVGReferences.clear(); 156 for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) { 157 Element* filter = m_internalSVGReferences.at(i).get(); 158 if (!filter->renderer()) 159 continue; 160 filter->renderer()->toRenderSVGResourceContainer()->removeClientRenderLayer(m_layer); 161 } 162 m_internalSVGReferences.clear(); 163} 164#endif 165 166#if ENABLE(CSS_SHADERS) 167void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*) 168{ 169 RenderObject* renderer = m_layer->renderer(); 170 renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange); 171 renderer->repaint(); 172} 173 174void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations) 175{ 176 if (!operations.size()) { 177 removeCustomFilterClients(); 178 return; 179 } 180 CustomFilterProgramList cachedCustomFilterPrograms; 181 for (size_t i = 0; i < operations.size(); ++i) { 182 const FilterOperation* filterOperation = operations.at(i); 183 if (filterOperation->getOperationType() != FilterOperation::CUSTOM) 184 continue; 185 const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation); 186 RefPtr<CustomFilterProgram> program = customFilterOperation->program(); 187 cachedCustomFilterPrograms.append(program); 188 program->addClient(this); 189 } 190 // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged. 191 removeCustomFilterClients(); 192 m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms); 193} 194 195void RenderLayerFilterInfo::removeCustomFilterClients() 196{ 197 for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i) 198 m_cachedCustomFilterPrograms.at(i)->removeClient(this); 199 m_cachedCustomFilterPrograms.clear(); 200} 201#endif 202 203} // namespace WebCore 204 205#endif // ENABLE(CSS_FILTERS) 206