[CSS Shaders] Implement a StyleCustomFilterProgram cache
authorachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2013 22:17:44 +0000 (22:17 +0000)
committerachicu@adobe.com <achicu@adobe.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Mar 2013 22:17:44 +0000 (22:17 +0000)
commit674bfc5d93c1990a224ec58750823a5c16987856
treec8ec9620a0e574e27b2d5544b7b7d6c4a3897d8c
parent1eadf8cb2a677ec4facb47055cb73d07d538a87f
[CSS Shaders] Implement a StyleCustomFilterProgram cache
https://bugs.webkit.org/show_bug.cgi?id=112602

Reviewed by Dean Jackson.

Source/WebCore:

When the style is recalculated, the new computed RenderStyle is saved as the m_style of the
RenderObject, even if the style was not different.

In the case of Custom Filters, a new StyleCustomFilterProgram was created at all times, but the
actual equality check was done by comparing the pair of cached shaders from inside the StyleCustomFilterProgram.

Because of that the RenderLayer::styleChanged was not called when the new StyleCustomFilterProgram was created, so it
will end up still knowing only about the previous StyleCustomFilterProgram.

The RenderLayer sets itself as a client of the StyleCustomFilterProgram, so that it can repaint itself
when the program is loaded, but because RenderLayer::styleChanged is not called, it will not add itself as a client of the new
StyleCustomFilterProgram.

StyleCustomFilterProgram waits until the first client to load the programs, so in this case it will just remain unloaded.

There was no crash, but just an assert in debug mode. Also, as a visible side-effect some frames were rendered using blank shaders,
resulting in a pass-through filter.

The fix would be to actually make the RenderStyle::diff detect the change of the StyleCustomFilterProgram
using the pointer value and not the values. However, that will always invalidate the "filter" property because
of the StyleCustomFilterProgram that always gets created during the recalculation time.

I've added StyleCustomFilterProgramCache to cache all the instances of the StyleCustomFilterPrograms that a
StyleResolver allocates. This way, next time it will try to reuse previously allocated StyleCustomFilterPrograms.
The key of the cache is the CustomFilterProgramInfo, that combines the URLs to the shaders and a couple of other program settings.

StyleCustomFilterProgramCache is owned by the StyleResovler and StyleCustomFilterPrograms are responsible with
removing themselves from the cache when the last reference goes away.

This change makes the previous "platform level" program cache obsolete and I will remove that in a future patch.
https://bugs.webkit.org/show_bug.cgi?id=112844

Test: css3/filters/custom/custom-filter-reload.html

* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* css/StyleResolver.cpp:
(WebCore::StyleResolver::lookupCustomFilterProgram): Lookup any similar programs in the cache. It will create a new pending
StyleCustomFilterProgram if there is no pre-cached version of the program.
if no program is found. loadPendingShaders is responsible for adding the program in the cache if it is actually going to be used.
(WebCore::StyleResolver::loadPendingShaders): At this point the program is final, so it's safe to add it to the cache.
(WebCore::StyleResolver::createCustomFilterOperationWithInlineSyntax):
* css/StyleResolver.h:
(StyleResolver):
* css/WebKitCSSShaderValue.cpp:
(WebCore::WebKitCSSShaderValue::completeURL): Factored out the function to compute the complete URL of the resource.
(WebCore::WebKitCSSShaderValue::cachedShader):
* css/WebKitCSSShaderValue.h:
(WebCore::toWebKitCSSShaderValue):
(WebKitCSSShaderValue):
* platform/graphics/filters/CustomFilterOperation.cpp:
(WebCore::CustomFilterOperation::blend):
* platform/graphics/filters/CustomFilterOperation.h:
(WebCore::CustomFilterOperation::operator==): Removed. Programs should now compare by pointer. Kept it as
private to catch any potential use of it.
* rendering/style/StyleCustomFilterProgram.cpp: Copied from Source/WebCore/css/WebKitCSSShaderValue.h.
(WebCore::StyleCustomFilterProgram::~StyleCustomFilterProgram): Destructor removes the program from the cache.
* rendering/style/StyleCustomFilterProgram.h:
(WebCore::StyleCustomFilterProgram::setVertexShader): Added an assert to check that the shader is not in the
cache while the mutation happens. Otherwise the cache might have the wrong key.
(WebCore::StyleCustomFilterProgram::setFragmentShader): Ditto.
(WebCore::StyleCustomFilterProgram::isLoaded): Added more asserts to catch cases when the program is used with no clients.
(StyleCustomFilterProgram):
(WebCore::StyleCustomFilterProgram::hasPendingShaders):
(WebCore::StyleCustomFilterProgram::inCache):
(WebCore::StyleCustomFilterProgram::setCache): Function called when a program is added to / removed from the cache.
(WebCore::StyleCustomFilterProgram::vertexShaderURL): Added methods to store the KURL that we used as keys in the cache.
The same KURLs will be used to lookup and remove the filter at the end.
(WebCore::StyleCustomFilterProgram::setVertexShaderURL):
(WebCore::StyleCustomFilterProgram::fragmentShaderURL):
(WebCore::StyleCustomFilterProgram::setFragmentShaderURL):
(WebCore::StyleCustomFilterProgram::StyleCustomFilterProgram):
* rendering/style/StyleCustomFilterProgramCache.cpp: Added.
(WebCore::StyleCustomFilterProgramCache::programCacheKey):
(WebCore::StyleCustomFilterProgramCache::StyleCustomFilterProgramCache):
(WebCore::StyleCustomFilterProgramCache::~StyleCustomFilterProgramCache): Destructor removes itself from all the
referenced StyleCustomFilterPrograms. This is to avoid issues with different destruction orders.
(WebCore::StyleCustomFilterProgramCache::lookup):
(WebCore::StyleCustomFilterProgramCache::add):
(WebCore::StyleCustomFilterProgramCache::remove):
* rendering/style/StyleCustomFilterProgramCache.h:
(StyleCustomFilterProgramCache):
* platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h:
(WebCore::CoordinatedCustomFilterProgram::operator==: Removed. Programs should now compare by pointer.

LayoutTests:

Added a new test to check for the case when the style is recalculated but the
filter property is not changed. All the other cases for the new StyleCustomFilterProgramCache
class should be tested by existing tests.

* css3/filters/custom/custom-filter-reload-expected.txt: Added.
* css3/filters/custom/custom-filter-reload.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@146529 268f45cc-cd09-0410-ab3c-d52691b4dbfc
22 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/filters/custom/custom-filter-reload-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/custom/custom-filter-reload.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/GNUmakefile.list.am
Source/WebCore/Target.pri
Source/WebCore/WebCore.gypi
Source/WebCore/WebCore.vcproj/WebCore.vcproj
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/StyleResolver.cpp
Source/WebCore/css/StyleResolver.h
Source/WebCore/css/WebKitCSSShaderValue.cpp
Source/WebCore/css/WebKitCSSShaderValue.h
Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp
Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
Source/WebCore/platform/graphics/filters/CustomFilterProgram.cpp
Source/WebCore/platform/graphics/filters/CustomFilterProgram.h
Source/WebCore/platform/graphics/texmap/coordinated/CoordinatedCustomFilterProgram.h
Source/WebCore/rendering/style/StyleCustomFilterProgram.cpp [new file with mode: 0644]
Source/WebCore/rendering/style/StyleCustomFilterProgram.h
Source/WebCore/rendering/style/StyleCustomFilterProgramCache.cpp [new file with mode: 0644]
Source/WebCore/rendering/style/StyleCustomFilterProgramCache.h [new file with mode: 0644]