Changeset 149886 in webkit
- Timestamp:
- May 10, 2013 10:34:36 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 10 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r149882 r149886 1 2013-05-10 Andreas Kling <akling@apple.com> 2 3 Caching of generated images in CSS should be smarter. 4 <http://webkit.org/b/115902> 5 <rdar://problem/13542727> 6 7 Reviewed by Antti Koivisto. 8 9 Add an IntSize => GeneratorGeneratedImage cache at the CSSImageGeneratorValue level. 10 11 CSSGradientValue is currently the only CSSImageGeneratorValue subclass that makes use of the cache. 12 Generated images are kept for 3 seconds after last use. 13 14 The main problem with the previous approach was that background renderers (e.g <body>, <tr>, etc) 15 would be passed to multiple CSSImageGeneratorValue::getImage() calls with different sizes requested 16 for each of the descendent renderers that inherit their background from the same parent. 17 The cache wasn't smart enough for this, it just thought the background renderer was changing size 18 a lot, and would regenerate the image over and over. 19 20 We already had caching of intermediate image buffers for GeneratorGeneratedImage::drawPattern(). 21 This removes the eviction timer from that cache so that the intermediate images can live a bit longer. 22 23 (WebCore::CSSImageGeneratorValue::cachedImageForSize): 24 (WebCore::CSSImageGeneratorValue::saveCachedImageForSize): 25 26 Renamed from getImage() and putImage(). 27 28 (WebCore::CSSImageGeneratorValue::evictCachedGeneratedImage): 29 (WebCore::CSSImageGeneratorValue::CachedGeneratedImage::CachedGeneratedImage): 30 (WebCore::CSSImageGeneratorValue::CachedGeneratedImage::evictionTimerFired): 31 32 Let the CachedGeneratedImage throw itself out from cache when the timer fires. 33 34 * css/CSSImageGeneratorValue.h: 35 (CachedGeneratedImage): 36 37 Exactly what it sounds like. These go into CSSImageGeneratorValue::m_images with the size 38 as the hash key. 39 40 * platform/graphics/GeneratorGeneratedImage.cpp: 41 (WebCore::GeneratorGeneratedImage::drawPattern): 42 * platform/graphics/GeneratorGeneratedImage.h: 43 (WebCore::GeneratorGeneratedImage::~GeneratorGeneratedImage): 44 (WebCore::GeneratorGeneratedImage::GeneratorGeneratedImage): 45 46 Keep the intermediate image for drawPattern() until destruction instead of dropping it on 47 a timer. These objects are now evicted by the CSSImageGeneratorValue's image cache 48 after 3 seconds of disuse rather than kept for the lifetime of the renderer. 49 50 * css/CSSCanvasValue.cpp: 51 (WebCore::CSSCanvasValue::canvasChanged): 52 (WebCore::CSSCanvasValue::canvasResized): 53 * css/CSSCrossfadeValue.cpp: 54 (WebCore::CSSCrossfadeValue::crossfadeChanged): 55 * rendering/style/StyleGeneratedImage.cpp: 56 (WebCore::StyleGeneratedImage::addClient): 57 * css/CSSImageGeneratorValue.cpp: 58 (WebCore::CSSImageGeneratorValue::addClient): 59 (WebCore::CSSImageGeneratorValue::removeClient): 60 61 CSSImageGeneratorValue::m_clients is now a HashCountedSet<RenderObject*>, tweak accordingly. 62 1 63 2013-05-10 Anders Carlsson <andersca@apple.com> 2 64 -
trunk/Source/WebCore/css/CSSCanvasValue.cpp
r148921 r149886 51 51 { 52 52 IntRect imageChangeRect = enclosingIntRect(changedRect); 53 RenderObjectSizeCountMap::const_iterator end = clients().end();54 for ( RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)53 HashCountedSet<RenderObject*>::const_iterator end = clients().end(); 54 for (HashCountedSet<RenderObject*>::const_iterator curr = clients().begin(); curr != end; ++curr) 55 55 const_cast<RenderObject*>(curr->key)->imageChanged(static_cast<WrappedImagePtr>(this), &imageChangeRect); 56 56 } … … 58 58 void CSSCanvasValue::canvasResized(HTMLCanvasElement*) 59 59 { 60 RenderObjectSizeCountMap::const_iterator end = clients().end();61 for ( RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr)60 HashCountedSet<RenderObject*>::const_iterator end = clients().end(); 61 for (HashCountedSet<RenderObject*>::const_iterator curr = clients().begin(); curr != end; ++curr) 62 62 const_cast<RenderObject*>(curr->key)->imageChanged(static_cast<WrappedImagePtr>(this)); 63 63 } -
trunk/Source/WebCore/css/CSSCrossfadeValue.cpp
r148921 r149886 194 194 void CSSCrossfadeValue::crossfadeChanged(const IntRect&) 195 195 { 196 RenderObjectSizeCountMap::const_iterator end = clients().end();197 for ( RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr) {196 HashCountedSet<RenderObject*>::const_iterator end = clients().end(); 197 for (HashCountedSet<RenderObject*>::const_iterator curr = clients().begin(); curr != end; ++curr) { 198 198 RenderObject* client = const_cast<RenderObject*>(curr->key); 199 199 client->imageChanged(static_cast<WrappedImagePtr>(this)); -
trunk/Source/WebCore/css/CSSGradientValue.cpp
r149583 r149886 54 54 return 0; 55 55 56 // Need to look up our size. Create a string of width*height to use as a hash key. 57 Image* result = getImage(renderer, size); 56 Image* result = cachedImageForSize(size); 58 57 if (result) 59 58 return result; 60 59 } 61 60 62 // We need to create an image.63 61 RefPtr<Gradient> gradient; 64 62 … … 70 68 } 71 69 72 RefPtr< Image> newImage = GeneratorGeneratedImage::create(gradient, size);70 RefPtr<GeneratorGeneratedImage> newImage = GeneratorGeneratedImage::create(gradient, size); 73 71 if (cacheable) 74 putImage(size, newImage);72 saveCachedImageForSize(size, newImage); 75 73 76 74 return newImage.release(); -
trunk/Source/WebCore/css/CSSImageGeneratorValue.cpp
r149665 r149886 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2011, 2012, 2013 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 36 36 namespace WebCore { 37 37 38 static const double timeToKeepCachedGeneratedImagesInSeconds = 3; 39 38 40 CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType) 39 41 : CSSValue(classType) … … 45 47 } 46 48 47 void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size) 48 { 49 void CSSImageGeneratorValue::addClient(RenderObject* renderer) 50 { 51 ASSERT(renderer); 49 52 ref(); 50 53 m_clients.add(renderer); 54 } 55 56 void CSSImageGeneratorValue::removeClient(RenderObject* renderer) 57 { 51 58 ASSERT(renderer); 52 if (!size.isEmpty()) 53 m_sizes.add(size); 54 55 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer); 56 if (it == m_clients.end()) 57 m_clients.add(renderer, SizeAndCount(size, 1)); 58 else { 59 SizeAndCount& sizeCount = it->value; 60 ++sizeCount.count; 61 } 62 } 63 64 void CSSImageGeneratorValue::removeClient(RenderObject* renderer) 65 { 66 ASSERT(renderer); 67 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer); 68 ASSERT(it != m_clients.end()); 69 70 IntSize removedImageSize; 71 SizeAndCount& sizeCount = it->value; 72 IntSize size = sizeCount.size; 73 if (!size.isEmpty()) { 74 m_sizes.remove(size); 75 if (!m_sizes.contains(size)) 76 m_images.remove(size); 77 } 78 79 if (!--sizeCount.count) 80 m_clients.remove(renderer); 81 59 m_clients.remove(renderer); 82 60 deref(); 83 61 } 84 62 85 Image* CSSImageGeneratorValue::getImage(RenderObject* renderer, const IntSize& size) 86 { 87 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer); 88 if (it != m_clients.end()) { 89 SizeAndCount& sizeCount = it->value; 90 IntSize oldSize = sizeCount.size; 91 if (oldSize != size) { 92 RefPtr<CSSImageGeneratorValue> protect(this); 93 removeClient(renderer); 94 addClient(renderer, size); 95 } 96 } 97 98 // Don't generate an image for empty sizes. 63 GeneratorGeneratedImage* CSSImageGeneratorValue::cachedImageForSize(IntSize size) 64 { 99 65 if (size.isEmpty()) 100 66 return 0; 101 67 102 // Look up the image in our cache. 103 return m_images.get(size); 104 } 105 106 void CSSImageGeneratorValue::putImage(const IntSize& size, PassRefPtr<Image> image) 107 { 108 m_images.add(size, image); 68 CachedGeneratedImage* cachedGeneratedImage = m_images.get(size); 69 if (!cachedGeneratedImage) 70 return 0; 71 72 cachedGeneratedImage->puntEvictionTimer(); 73 return cachedGeneratedImage->image(); 74 } 75 76 void CSSImageGeneratorValue::saveCachedImageForSize(IntSize size, PassRefPtr<GeneratorGeneratedImage> image) 77 { 78 ASSERT(!m_images.contains(size)); 79 m_images.add(size, adoptPtr(new CachedGeneratedImage(*this, size, image))); 80 } 81 82 void CSSImageGeneratorValue::evictCachedGeneratedImage(IntSize size) 83 { 84 ASSERT(m_images.contains(size)); 85 m_images.remove(size); 86 } 87 88 CSSImageGeneratorValue::CachedGeneratedImage::CachedGeneratedImage(CSSImageGeneratorValue& owner, IntSize size, PassRefPtr<GeneratorGeneratedImage> image) 89 : m_owner(owner) 90 , m_size(size) 91 , m_image(image) 92 , m_evictionTimer(this, &CSSImageGeneratorValue::CachedGeneratedImage::evictionTimerFired, timeToKeepCachedGeneratedImagesInSeconds) 93 { 94 m_evictionTimer.restart(); 95 } 96 97 void CSSImageGeneratorValue::CachedGeneratedImage::evictionTimerFired(DeferrableOneShotTimer<CachedGeneratedImage>*) 98 { 99 // NOTE: This is essentially a "delete this", the object is no longer valid after this line. 100 m_owner.evictCachedGeneratedImage(m_size); 109 101 } 110 102 -
trunk/Source/WebCore/css/CSSImageGeneratorValue.h
r148921 r149886 1 1 /* 2 * Copyright (C) 2008 Apple Inc. All rights reserved.2 * Copyright (C) 2008, 2011, 2012, 2013 Apple Inc. All rights reserved. 3 3 * 4 4 * Redistribution and use in source and binary forms, with or without … … 28 28 29 29 #include "CSSValue.h" 30 #include "GeneratorGeneratedImage.h" 30 31 #include "IntSizeHash.h" 32 #include "Timer.h" 31 33 #include <wtf/HashCountedSet.h> 32 34 #include <wtf/RefPtr.h> … … 35 37 36 38 class CachedResourceLoader; 37 class Image;39 class GeneratorGeneratedImage; 38 40 class RenderObject; 39 41 class StyleResolver; 40 41 struct SizeAndCount {42 SizeAndCount(IntSize newSize = IntSize(), int newCount = 0)43 : size(newSize)44 , count(newCount)45 {46 }47 48 IntSize size;49 int count;50 };51 52 typedef HashMap<const RenderObject*, SizeAndCount> RenderObjectSizeCountMap;53 42 54 43 class CSSImageGeneratorValue : public CSSValue { … … 56 45 ~CSSImageGeneratorValue(); 57 46 58 void addClient(RenderObject* , const IntSize&);47 void addClient(RenderObject*); 59 48 void removeClient(RenderObject*); 49 60 50 PassRefPtr<Image> image(RenderObject*, const IntSize&); 61 51 … … 71 61 CSSImageGeneratorValue(ClassType); 72 62 73 Image* getImage(RenderObject*, const IntSize&);74 void putImage(const IntSize&, PassRefPtr<Image>);75 const RenderObjectSizeCountMap& clients() const { return m_clients; }63 GeneratorGeneratedImage* cachedImageForSize(IntSize); 64 void saveCachedImageForSize(IntSize, PassRefPtr<GeneratorGeneratedImage>); 65 const HashCountedSet<RenderObject*>& clients() const { return m_clients; } 76 66 77 HashCountedSet<IntSize> m_sizes; // A count of how many times a given image size is in use. 78 RenderObjectSizeCountMap m_clients; // A map from RenderObjects (with entry count) to image sizes. 79 HashMap<IntSize, RefPtr<Image> > m_images; // A cache of Image objects by image size. 67 private: 68 class CachedGeneratedImage { 69 public: 70 CachedGeneratedImage(CSSImageGeneratorValue&, IntSize, PassRefPtr<GeneratorGeneratedImage>); 71 GeneratorGeneratedImage* image() { return m_image.get(); } 72 void puntEvictionTimer() { m_evictionTimer.restart(); } 73 74 private: 75 void evictionTimerFired(DeferrableOneShotTimer<CachedGeneratedImage>*); 76 77 CSSImageGeneratorValue& m_owner; 78 IntSize m_size; 79 RefPtr<GeneratorGeneratedImage> m_image; 80 DeferrableOneShotTimer<CachedGeneratedImage> m_evictionTimer; 81 }; 82 83 friend class CachedGeneratedImage; 84 void evictCachedGeneratedImage(IntSize); 85 86 HashCountedSet<RenderObject*> m_clients; 87 HashMap<IntSize, OwnPtr<CachedGeneratedImage> > m_images; 80 88 }; 81 89 -
trunk/Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
r148921 r149886 77 77 // Tile the image buffer into the context. 78 78 m_cachedImageBuffer->drawPattern(destContext, adjustedSrcRect, adjustedPatternCTM, phase, styleColorSpace, compositeOp, destRect); 79 m_cacheTimer.restart();80 }81 82 void GeneratorGeneratedImage::invalidateCacheTimerFired(DeferrableOneShotTimer<GeneratorGeneratedImage>*)83 {84 m_cachedImageBuffer.clear();85 m_cachedAdjustedSize = IntSize();86 79 } 87 80 -
trunk/Source/WebCore/platform/graphics/GeneratorGeneratedImage.h
r148921 r149886 32 32 #include "ImageBuffer.h" 33 33 #include "IntSize.h" 34 #include "Timer.h"35 34 #include <wtf/RefPtr.h> 36 35 37 36 namespace WebCore { 38 39 static const int generatedImageCacheClearDelay = 1;40 37 41 38 class GeneratorGeneratedImage : public GeneratedImage { … … 46 43 } 47 44 48 virtual ~GeneratorGeneratedImage() 49 { 50 m_cacheTimer.stop(); 51 } 45 virtual ~GeneratorGeneratedImage() { } 52 46 53 47 protected: … … 56 50 const FloatPoint& phase, ColorSpace styleColorSpace, CompositeOperator, const FloatRect& destRect, BlendMode); 57 51 58 void invalidateCacheTimerFired(DeferrableOneShotTimer<GeneratorGeneratedImage>*);59 60 52 GeneratorGeneratedImage(PassRefPtr<Generator> generator, const IntSize& size) 61 53 : m_generator(generator) 62 , m_cacheTimer(this, &GeneratorGeneratedImage::invalidateCacheTimerFired, generatedImageCacheClearDelay)63 54 { 64 55 m_size = size; … … 66 57 67 58 RefPtr<Generator> m_generator; 68 69 59 OwnPtr<ImageBuffer> m_cachedImageBuffer; 70 DeferrableOneShotTimer<GeneratorGeneratedImage> m_cacheTimer;71 60 IntSize m_cachedAdjustedSize; 72 61 unsigned m_cachedGeneratorHash; -
trunk/Source/WebCore/rendering/style/StyleGeneratedImage.cpp
r141637 r149886 77 77 void StyleGeneratedImage::addClient(RenderObject* renderer) 78 78 { 79 m_imageGeneratorValue->addClient(renderer , IntSize());79 m_imageGeneratorValue->addClient(renderer); 80 80 } 81 81 -
trunk/Tools/Scripts/webkitpy/port/mac.py
r148502 r149886 137 137 138 138 def _build_java_test_support(self): 139 return True 139 140 java_tests_path = self._filesystem.join(self.layout_tests_dir(), "java") 140 141 build_java = [self.make_command(), "-C", java_tests_path]
Note: See TracChangeset
for help on using the changeset viewer.