[CSS Shaders] [BlackBerry] Refactor CustomFilterMesh and CustomFilter*Program
authoranilsson@rim.com <anilsson@rim.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Sep 2012 20:19:26 +0000 (20:19 +0000)
committeranilsson@rim.com <anilsson@rim.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 7 Sep 2012 20:19:26 +0000 (20:19 +0000)
https://bugs.webkit.org/show_bug.cgi?id=94725

Reviewed by Rob Buis.

Separate the MeshGenerator from the CustomFilterMesh into
CustomFilterMeshGenerator.h/cpp. This allows the BlackBerry port to
reuse the mesh generator in its accelerated compositing implementation.

Also add support for creating a "PlatformCompiledProgram" from a
CustomFilterValidatedProgram, so the BlackBerry port can reuse the
shader validation code in its accelerated compositing implementation.

It turns out the GraphicsContext3D is not needed for ANGLE to function,
so this patch removes an ASSERT that required a context before
validating the shaders using ANGLE. This allows the BlackBerry port to
reuse the validation code without triggering the assert. In the future,
the validation code could be moved to a separate class to make it more
obvious that it isn't really related to GraphicsContext3D.

In general, this refactoring can be useful for any port that uses
OpenGL to implement accelerated compositing.

Inspired by an original patch by Joshua Netterfield.

No new tests, because this patch implements no new functionality.

* GNUmakefile.list.am:
* Target.pri:
* WebCore.gypi:
* WebCore.vcproj/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* platform/graphics/filters/CustomFilterGlobalContext.cpp:
(WebCore::CustomFilterGlobalContext::getValidatedProgram):
* platform/graphics/filters/CustomFilterMesh.cpp:
(WebCore::CustomFilterMesh::CustomFilterMesh):
* platform/graphics/filters/CustomFilterMeshGenerator.cpp: Added.
(WebCore):
(WebCore::CustomFilterMeshGenerator::CustomFilterMeshGenerator):
(WebCore::CustomFilterMeshGenerator::addAttachedMeshIndex):
(WebCore::CustomFilterMeshGenerator::generateAttachedMesh):
(WebCore::CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex):
(WebCore::CustomFilterMeshGenerator::generateDetachedMesh):
(WebCore::CustomFilterMeshGenerator::addPositionAttribute):
(WebCore::CustomFilterMeshGenerator::addTexCoordAttribute):
(WebCore::CustomFilterMeshGenerator::addMeshCoordAttribute):
(WebCore::CustomFilterMeshGenerator::addTriangleCoordAttribute):
(WebCore::CustomFilterMeshGenerator::addAttachedMeshVertexAttributes):
(WebCore::CustomFilterMeshGenerator::addDetachedMeshVertexAttributes):
(WebCore::CustomFilterMeshGenerator::dumpBuffers):
* platform/graphics/filters/CustomFilterMeshGenerator.h: Added.
(WebCore):
(CustomFilterMeshGenerator):
(WebCore::CustomFilterMeshGenerator::vertices):
(WebCore::CustomFilterMeshGenerator::indices):
(WebCore::CustomFilterMeshGenerator::points):
(WebCore::CustomFilterMeshGenerator::pointsCount):
(WebCore::CustomFilterMeshGenerator::tiles):
(WebCore::CustomFilterMeshGenerator::tilesCount):
(WebCore::CustomFilterMeshGenerator::indicesCount):
(WebCore::CustomFilterMeshGenerator::floatsPerVertex):
(WebCore::CustomFilterMeshGenerator::verticesCount):
(WebCore::CustomFilterMeshGenerator::addTile):
* platform/graphics/filters/CustomFilterValidatedProgram.cpp:
(WebCore::CustomFilterValidatedProgram::CustomFilterValidatedProgram):
(WebCore::CustomFilterValidatedProgram::compiledProgram):
(WebCore::CustomFilterValidatedProgram::~CustomFilterValidatedProgram):
(WebCore):
(WebCore::CustomFilterValidatedProgram::platformCompiledProgram):
(WebCore::CustomFilterValidatedProgram::platformDestroy):
* platform/graphics/filters/CustomFilterValidatedProgram.h:
(WebCore):
(CustomFilterValidatedProgram):
* platform/graphics/filters/blackberry/CustomFilterValidatedProgramBlackBerry.cpp: Added.
(WebCore):
(WebCore::CustomFilterValidatedProgram::platformCompiledProgram):
(WebCore::CustomFilterValidatedProgram::platformDestroy):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@127911 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
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/platform/graphics/filters/CustomFilterGlobalContext.cpp
Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp
Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h [new file with mode: 0644]
Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.cpp
Source/WebCore/platform/graphics/filters/CustomFilterValidatedProgram.h
Source/WebCore/platform/graphics/filters/blackberry/CustomFilterValidatedProgramBlackBerry.cpp [new file with mode: 0644]

index f35e176..229a29c 100644 (file)
@@ -1,3 +1,83 @@
+2012-09-07  Arvid Nilsson  <anilsson@rim.com>
+
+        [CSS Shaders] [BlackBerry] Refactor CustomFilterMesh and CustomFilter*Program
+        https://bugs.webkit.org/show_bug.cgi?id=94725
+
+        Reviewed by Rob Buis.
+
+        Separate the MeshGenerator from the CustomFilterMesh into
+        CustomFilterMeshGenerator.h/cpp. This allows the BlackBerry port to
+        reuse the mesh generator in its accelerated compositing implementation.
+
+        Also add support for creating a "PlatformCompiledProgram" from a
+        CustomFilterValidatedProgram, so the BlackBerry port can reuse the
+        shader validation code in its accelerated compositing implementation.
+
+        It turns out the GraphicsContext3D is not needed for ANGLE to function,
+        so this patch removes an ASSERT that required a context before
+        validating the shaders using ANGLE. This allows the BlackBerry port to
+        reuse the validation code without triggering the assert. In the future,
+        the validation code could be moved to a separate class to make it more
+        obvious that it isn't really related to GraphicsContext3D.
+
+        In general, this refactoring can be useful for any port that uses
+        OpenGL to implement accelerated compositing.
+
+        Inspired by an original patch by Joshua Netterfield.
+
+        No new tests, because this patch implements no new functionality.
+
+        * GNUmakefile.list.am:
+        * Target.pri:
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/filters/CustomFilterGlobalContext.cpp:
+        (WebCore::CustomFilterGlobalContext::getValidatedProgram):
+        * platform/graphics/filters/CustomFilterMesh.cpp:
+        (WebCore::CustomFilterMesh::CustomFilterMesh):
+        * platform/graphics/filters/CustomFilterMeshGenerator.cpp: Added.
+        (WebCore):
+        (WebCore::CustomFilterMeshGenerator::CustomFilterMeshGenerator):
+        (WebCore::CustomFilterMeshGenerator::addAttachedMeshIndex):
+        (WebCore::CustomFilterMeshGenerator::generateAttachedMesh):
+        (WebCore::CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex):
+        (WebCore::CustomFilterMeshGenerator::generateDetachedMesh):
+        (WebCore::CustomFilterMeshGenerator::addPositionAttribute):
+        (WebCore::CustomFilterMeshGenerator::addTexCoordAttribute):
+        (WebCore::CustomFilterMeshGenerator::addMeshCoordAttribute):
+        (WebCore::CustomFilterMeshGenerator::addTriangleCoordAttribute):
+        (WebCore::CustomFilterMeshGenerator::addAttachedMeshVertexAttributes):
+        (WebCore::CustomFilterMeshGenerator::addDetachedMeshVertexAttributes):
+        (WebCore::CustomFilterMeshGenerator::dumpBuffers):
+        * platform/graphics/filters/CustomFilterMeshGenerator.h: Added.
+        (WebCore):
+        (CustomFilterMeshGenerator):
+        (WebCore::CustomFilterMeshGenerator::vertices):
+        (WebCore::CustomFilterMeshGenerator::indices):
+        (WebCore::CustomFilterMeshGenerator::points):
+        (WebCore::CustomFilterMeshGenerator::pointsCount):
+        (WebCore::CustomFilterMeshGenerator::tiles):
+        (WebCore::CustomFilterMeshGenerator::tilesCount):
+        (WebCore::CustomFilterMeshGenerator::indicesCount):
+        (WebCore::CustomFilterMeshGenerator::floatsPerVertex):
+        (WebCore::CustomFilterMeshGenerator::verticesCount):
+        (WebCore::CustomFilterMeshGenerator::addTile):
+        * platform/graphics/filters/CustomFilterValidatedProgram.cpp:
+        (WebCore::CustomFilterValidatedProgram::CustomFilterValidatedProgram):
+        (WebCore::CustomFilterValidatedProgram::compiledProgram):
+        (WebCore::CustomFilterValidatedProgram::~CustomFilterValidatedProgram):
+        (WebCore):
+        (WebCore::CustomFilterValidatedProgram::platformCompiledProgram):
+        (WebCore::CustomFilterValidatedProgram::platformDestroy):
+        * platform/graphics/filters/CustomFilterValidatedProgram.h:
+        (WebCore):
+        (CustomFilterValidatedProgram):
+        * platform/graphics/filters/blackberry/CustomFilterValidatedProgramBlackBerry.cpp: Added.
+        (WebCore):
+        (WebCore::CustomFilterValidatedProgram::platformCompiledProgram):
+        (WebCore::CustomFilterValidatedProgram::platformDestroy):
+
 2012-09-07  Dana Jansens  <danakj@chromium.org>
 
         [chromium] Make RenderPass ids hold both generating layer id and an index
index 252a6cf..687e2e3 100644 (file)
@@ -4252,6 +4252,8 @@ webcore_sources += \
        Source/WebCore/platform/graphics/filters/CustomFilterGlobalContext.h \
        Source/WebCore/platform/graphics/filters/CustomFilterMesh.cpp \
        Source/WebCore/platform/graphics/filters/CustomFilterMesh.h \
+       Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp \
+       Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h \
        Source/WebCore/platform/graphics/filters/CustomFilterNumberParameter.h \
        Source/WebCore/platform/graphics/filters/CustomFilterOperation.cpp \
        Source/WebCore/platform/graphics/filters/CustomFilterOperation.h \
index 78e0308..edbe2f4 100644 (file)
@@ -2044,6 +2044,7 @@ HEADERS += \
     platform/graphics/CrossfadeGeneratedImage.h \
     platform/graphics/filters/CustomFilterGlobalContext.h \
     platform/graphics/filters/CustomFilterMesh.h \
+    platform/graphics/filters/CustomFilterMeshGenerator.h \
     platform/graphics/filters/CustomFilterNumberParameter.h \
     platform/graphics/filters/CustomFilterCompiledProgram.h \
     platform/graphics/filters/CustomFilterOperation.h \
@@ -3446,6 +3447,7 @@ contains(DEFINES, ENABLE_FILTERS=1) {
         platform/graphics/filters/CustomFilterProgram.cpp \
         platform/graphics/filters/CustomFilterCompiledProgram.cpp \
         platform/graphics/filters/CustomFilterMesh.cpp \
+        platform/graphics/filters/CustomFilterMeshGenerator.cpp \
         platform/graphics/filters/CustomFilterValidatedProgram.cpp \
         platform/graphics/filters/DistantLightSource.cpp \
         platform/graphics/filters/FEBlend.cpp \
index e0aeeab..b4dc656 100644 (file)
             'platform/graphics/filters/CustomFilterGlobalContext.cpp',
             'platform/graphics/filters/CustomFilterGlobalContext.h',
             'platform/graphics/filters/CustomFilterMesh.h',
+            'platform/graphics/filters/CustomFilterMeshGenerator.h',
             'platform/graphics/filters/CustomFilterNumberParameter.h',
             'platform/graphics/filters/CustomFilterOperation.cpp',
             'platform/graphics/filters/CustomFilterOperation.h',
             'platform/graphics/filters/CustomFilterValidatedProgram.cpp',
             'platform/graphics/filters/CustomFilterValidatedProgram.h',
             'platform/graphics/filters/CustomFilterMesh.cpp',
+            'platform/graphics/filters/CustomFilterMeshGenerator.cpp',
             'platform/graphics/filters/CustomFilterTransformParameter.h',
             'platform/graphics/filters/DistantLightSource.cpp',
             'platform/graphics/filters/DistantLightSource.h',
index fd2b562..7e2f0b0 100755 (executable)
                                                >
                                        </File>
                                        <File
+                                               RelativePath="..\platform\graphics\filters\CustomFilterMeshGenerator.cpp"
+                                               >
+                                       </File>
+                                       <File
+                                               RelativePath="..\platform\graphics\filters\CustomFilterMeshGenerator.h"
+                                               >
+                                       </File>
+                                       <File
                                                RelativePath="..\platform\graphics\filters\CustomFilterNumberParameter.h"
                                                >
                                        </File>
index e4dcf50..84fcad8 100644 (file)
                7BD117EB15B8DB0100C974A3 /* DOMTransactionStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7BD117E915B8DB0100C974A3 /* DOMTransactionStep.cpp */; };
                7BD117EC15B8DB0100C974A3 /* DOMTransactionStep.h in Headers */ = {isa = PBXBuildFile; fileRef = 7BD117EA15B8DB0100C974A3 /* DOMTransactionStep.h */; };
                7C522D4B15B477E8009B7C95 /* InspectorOverlay.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7C522D4915B477E8009B7C95 /* InspectorOverlay.cpp */; };
+               7E12E90F15FA5D3A005E4126 /* CustomFilterMeshGenerator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E12E90D15FA5D3A005E4126 /* CustomFilterMeshGenerator.h */; };
+               7E12E91015FA5D3A005E4126 /* CustomFilterMeshGenerator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E12E90E15FA5D3A005E4126 /* CustomFilterMeshGenerator.cpp */; };
                7E33CD01127F340D00BE8F17 /* PurgePriority.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E33CD00127F340D00BE8F17 /* PurgePriority.h */; settings = {ATTRIBUTES = (Private, ); }; };
                7E37EF2E1339208800B29250 /* SubresourceLoaderCF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */; };
                7E99AF510B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7E99AF520B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp */; };
                7C522D4915B477E8009B7C95 /* InspectorOverlay.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = InspectorOverlay.cpp; sourceTree = "<group>"; };
                7C522D4A15B478B2009B7C95 /* InspectorOverlay.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InspectorOverlay.h; sourceTree = "<group>"; };
                7C60128060078BB70E367A95 /* DNSResolveQueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DNSResolveQueue.cpp; sourceTree = "<group>"; };
+               7E12E90D15FA5D3A005E4126 /* CustomFilterMeshGenerator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomFilterMeshGenerator.h; path = filters/CustomFilterMeshGenerator.h; sourceTree = "<group>"; };
+               7E12E90E15FA5D3A005E4126 /* CustomFilterMeshGenerator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CustomFilterMeshGenerator.cpp; path = filters/CustomFilterMeshGenerator.cpp; sourceTree = "<group>"; };
                7E33CD00127F340D00BE8F17 /* PurgePriority.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PurgePriority.h; sourceTree = "<group>"; };
                7E37EF2D1339208800B29250 /* SubresourceLoaderCF.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SubresourceLoaderCF.cpp; path = cf/SubresourceLoaderCF.cpp; sourceTree = "<group>"; };
                7E99AF520B13846468FB01A5 /* WindowFocusAllowedIndicator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = WindowFocusAllowedIndicator.cpp; sourceTree = "<group>"; };
                A75E8B7F0E1DE2B0007F2481 /* filters */ = {
                        isa = PBXGroup;
                        children = (
+                               7E12E90D15FA5D3A005E4126 /* CustomFilterMeshGenerator.h */,
+                               7E12E90E15FA5D3A005E4126 /* CustomFilterMeshGenerator.cpp */,
                                509EC10815E848CA00E82581 /* CustomFilterTransformParameter.h */,
                                49ECEB5C1499790D00CDD3A4 /* arm */,
                                50D4060F147D49DE00D30BB5 /* CustomFilterCompiledProgram.cpp */,
                                76F2E2EC15F74CEF005FF664 /* RenderDialog.h in Headers */,
                                0F605AED15F94848004DF0C0 /* ScrollingConstraints.h in Headers */,
                                4F377FF515FA356A00E5D60D /* WebCoreMemoryInstrumentation.h in Headers */,
+                               7E12E90F15FA5D3A005E4126 /* CustomFilterMeshGenerator.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                BCD8A5F015F56F2C0098D071 /* TextBreakIterator.cpp in Sources */,
                                76F2E2EB15F74CEF005FF664 /* RenderDialog.cpp in Sources */,
                                0F605AEC15F94848004DF0C0 /* ScrollingConstraints.cpp in Sources */,
+                               7E12E91015FA5D3A005E4126 /* CustomFilterMeshGenerator.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index e0144b9..582846e 100644 (file)
@@ -87,9 +87,6 @@ void CustomFilterGlobalContext::prepareContextIfNeeded(HostWindow* hostWindow)
 
 PassRefPtr<CustomFilterValidatedProgram> CustomFilterGlobalContext::getValidatedProgram(const CustomFilterProgramInfo& programInfo)
 {
-    // Check that the context is already prepared.
-    ASSERT(m_context);
-
     CustomFilterValidatedProgramsMap::iterator iter = m_programs.find(programInfo);
     if (iter != m_programs.end())
         return iter->second;
index e014f0a..0278aba 100644 (file)
 
 #if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
 #include "CustomFilterMesh.h"
+#include "CustomFilterMeshGenerator.h"
 #include "GraphicsContext3D.h"
 
 namespace WebCore {
-    
-#ifndef NDEBUG
-// Use "call 'WebCore::s_dumpCustomFilterMeshBuffers' = 1" in GDB to activate printing of the mesh buffers.
-static bool s_dumpCustomFilterMeshBuffers = false;
-#endif
-
-class MeshGenerator {
-public:
-    // Lines and columns are the values passed in CSS. The result is vertex mesh that has 'rows' numbers of rows
-    // and 'columns' number of columns with a total of 'rows + 1' * 'columns + 1' vertices.
-    // MeshBox is the filtered area calculated defined using the border-box, padding-box, content-box or filter-box 
-    // attributes. A value of (0, 0, 1, 1) will cover the entire output surface.
-    MeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
-        : m_meshType(meshType)
-        , m_points(columns + 1, rows + 1)
-        , m_tiles(columns, rows)
-        , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height())
-        , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height())
-        , m_meshBox(meshBox)
-    {
-        // Build the two buffers needed to draw triangles:
-        // * m_vertices has a number of float attributes that will be passed to the vertex shader
-        // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType.
-        // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside
-        // the m_vertices buffer.
-        m_vertices.reserveCapacity(verticesCount() * floatsPerVertex());
-        m_indices.reserveCapacity(indicesCount());
-        
-        // Based on the meshType there can be two types of meshes.
-        // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory
-        // when there's no need to explode the tiles.
-        // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3
-        // attribute is passed, so that each vertex can be uniquely identified.
-        if (m_meshType == CustomFilterOperation::ATTACHED)
-            generateAttachedMesh();
-        else
-            generateDetachedMesh();
-        
-#ifndef NDEBUG
-        if (s_dumpCustomFilterMeshBuffers)
-            dumpBuffers();
-#endif
-    }
-
-    const Vector<float>& vertices() const { return m_vertices; }
-    const Vector<uint16_t>& indices() const { return m_indices; }
-
-    const IntSize& points() const { return m_points; }
-    unsigned pointsCount() const { return m_points.width() * m_points.height(); }
-    
-    const IntSize& tiles() const { return m_tiles; }
-    unsigned tilesCount() const { return m_tiles.width() * m_tiles.height(); }
-    
-    unsigned indicesCount() const
-    {
-        const unsigned trianglesPerTile = 2;
-        const unsigned indicesPerTriangle = 3;
-        return tilesCount() * trianglesPerTile * indicesPerTriangle;
-    }
-    
-    unsigned floatsPerVertex() const
-    {
-        static const unsigned AttachedMeshVertexSize = 4 + // vec4 a_position
-                                                       2 + // vec2 a_texCoord
-                                                       2; // vec2 a_meshCoord
-
-        static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize +
-                                                       3; // vec3 a_triangleCoord
-
-        return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize;
-    }
-    
-    unsigned verticesCount() const
-    {
-        return m_meshType == CustomFilterOperation::ATTACHED ? pointsCount() : indicesCount();
-    }
-
-private:
-    typedef void (MeshGenerator::*AddTriangleVertexFunction)(int quadX, int quadY, int triangleX, int triangleY, int triangle);
-    
-    template <AddTriangleVertexFunction addTriangleVertex>
-    void addTile(int quadX, int quadY)
-    {
-        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 1);
-        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 0, 2);
-        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 3);
-        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 4);
-        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 5);
-        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 1, 6);
-    }
-    
-    void addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
-    {
-        UNUSED_PARAM(triangle);
-        m_indices.append((quadY + triangleY) * m_points.width() + (quadX + triangleX));
-    }
-    
-    void generateAttachedMesh()
-    {
-        for (int j = 0; j < m_points.height(); ++j) {
-            for (int i = 0; i < m_points.width(); ++i)
-                addAttachedMeshVertexAttributes(i, j);
-        }
-        
-        for (int j = 0; j < m_tiles.height(); ++j) {
-            for (int i = 0; i < m_tiles.width(); ++i)
-                addTile<&MeshGenerator::addAttachedMeshIndex>(i, j);
-        }
-    }
-    
-    void addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
-    {
-        addDetachedMeshVertexAttributes(quadX, quadY, triangleX, triangleY, triangle);
-        m_indices.append(m_indices.size());
-    }
-    
-    void generateDetachedMesh()
-    {
-        for (int j = 0; j < m_tiles.height(); ++j) {
-            for (int i = 0; i < m_tiles.width(); ++i)
-                addTile<&MeshGenerator::addDetachedMeshVertexAndIndex>(i, j);
-        }
-    }
-    
-    void addPositionAttribute(int quadX, int quadY)
-    {
-        // vec4 a_position
-        m_vertices.append(m_tileSizeInPixels.width() * quadX - 0.5f + m_meshBox.x());
-        m_vertices.append(m_tileSizeInPixels.height() * quadY - 0.5f + m_meshBox.y());
-        m_vertices.append(0.0f); // z
-        m_vertices.append(1.0f);
-    }
-
-    void addTexCoordAttribute(int quadX, int quadY)
-    {
-        // vec2 a_texCoord
-        m_vertices.append(m_tileSizeInPixels.width() * quadX + m_meshBox.x());
-        m_vertices.append(m_tileSizeInPixels.height() * quadY + m_meshBox.y());
-    }
-
-    void addMeshCoordAttribute(int quadX, int quadY)
-    {
-        // vec2 a_meshCoord
-        m_vertices.append(m_tileSizeInDeviceSpace.width() * quadX);
-        m_vertices.append(m_tileSizeInDeviceSpace.height() * quadY);
-    }
-
-    void addTriangleCoordAttribute(int quadX, int quadY, int triangle)
-    {
-        // vec3 a_triangleCoord
-        m_vertices.append(quadX);
-        m_vertices.append(quadY);
-        m_vertices.append(triangle);
-    }
-
-    void addAttachedMeshVertexAttributes(int quadX, int quadY)
-    {
-        addPositionAttribute(quadX, quadY);
-        addTexCoordAttribute(quadX, quadY);
-        addMeshCoordAttribute(quadX, quadY);
-    }
-
-    void addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle)
-    {
-        addAttachedMeshVertexAttributes(quadX + triangleX, quadY + triangleY);
-        addTriangleCoordAttribute(quadX, quadY, triangle);
-    }
-    
-#ifndef NDEBUG
-    void dumpBuffers() const
-    {
-        printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n", 
-               m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(), 
-               (m_meshType == CustomFilterOperation::ATTACHED) ? "Attached" : "Detached");
-        printf("---Vertex:\n\t");
-        for (unsigned i = 0; i < m_vertices.size(); ++i) {
-            printf("%f ", m_vertices.at(i));
-            if (!((i + 1) % floatsPerVertex()))
-                printf("\n\t");
-        }
-        printf("\n---Indices: ");
-        for (unsigned i = 0; i < m_indices.size(); ++i)
-            printf("%d ", m_indices.at(i));
-        printf("\n");
-    }
-#endif
-
-private:
-    Vector<float> m_vertices;
-    Vector<uint16_t> m_indices;
-    
-    CustomFilterOperation::MeshType m_meshType;
-    IntSize m_points;
-    IntSize m_tiles;
-    FloatSize m_tileSizeInPixels;
-    FloatSize m_tileSizeInDeviceSpace;
-    FloatRect m_meshBox;
-};
 
-CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, unsigned rows, 
+CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns, unsigned rows,
                                    const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
     : m_context(context)
     , m_verticesBufferObject(0)
@@ -241,7 +44,7 @@ CustomFilterMesh::CustomFilterMesh(GraphicsContext3D* context, unsigned columns,
     , m_meshBox(meshBox)
     , m_meshType(meshType)
 {
-    MeshGenerator generator(columns, rows, meshBox, meshType);
+    CustomFilterMeshGenerator generator(columns, rows, meshBox, meshType);
     m_indicesCount = generator.indicesCount();
     m_bytesPerVertex = generator.floatsPerVertex() * sizeof(float);    
 
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.cpp
new file mode 100644 (file)
index 0000000..3d9d4d1
--- /dev/null
@@ -0,0 +1,173 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
+#include "CustomFilterMeshGenerator.h"
+
+namespace WebCore {
+
+#ifndef NDEBUG
+// Use "call 'WebCore::s_dumpCustomFilterMeshBuffers' = 1" in GDB to activate printing of the mesh buffers.
+static bool s_dumpCustomFilterMeshBuffers = false;
+#endif
+
+CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType meshType)
+    : m_meshType(meshType)
+    , m_points(columns + 1, rows + 1)
+    , m_tiles(columns, rows)
+    , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height())
+    , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height())
+    , m_meshBox(meshBox)
+{
+    // Build the two buffers needed to draw triangles:
+    // * m_vertices has a number of float attributes that will be passed to the vertex shader
+    // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType.
+    // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside
+    // the m_vertices buffer.
+    m_vertices.reserveCapacity(verticesCount() * floatsPerVertex());
+    m_indices.reserveCapacity(indicesCount());
+
+    // Based on the meshType there can be two types of meshes.
+    // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory
+    // when there's no need to explode the tiles.
+    // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3
+    // attribute is passed, so that each vertex can be uniquely identified.
+    if (m_meshType == CustomFilterOperation::ATTACHED)
+        generateAttachedMesh();
+    else
+        generateDetachedMesh();
+
+#ifndef NDEBUG
+    if (s_dumpCustomFilterMeshBuffers)
+        dumpBuffers();
+#endif
+}
+
+void CustomFilterMeshGenerator::addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+{
+    UNUSED_PARAM(triangle);
+    m_indices.append((quadY + triangleY) * m_points.width() + (quadX + triangleX));
+}
+
+void CustomFilterMeshGenerator::generateAttachedMesh()
+{
+    for (int j = 0; j < m_points.height(); ++j) {
+        for (int i = 0; i < m_points.width(); ++i)
+            addAttachedMeshVertexAttributes(i, j);
+    }
+
+    for (int j = 0; j < m_tiles.height(); ++j) {
+        for (int i = 0; i < m_tiles.width(); ++i)
+            addTile<&CustomFilterMeshGenerator::addAttachedMeshIndex>(i, j);
+    }
+}
+
+void CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+{
+    addDetachedMeshVertexAttributes(quadX, quadY, triangleX, triangleY, triangle);
+    m_indices.append(m_indices.size());
+}
+
+void CustomFilterMeshGenerator::generateDetachedMesh()
+{
+    for (int j = 0; j < m_tiles.height(); ++j) {
+        for (int i = 0; i < m_tiles.width(); ++i)
+            addTile<&CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex>(i, j);
+    }
+}
+
+void CustomFilterMeshGenerator::addPositionAttribute(int quadX, int quadY)
+{
+    // vec4 a_position
+    m_vertices.append(m_tileSizeInPixels.width() * quadX - 0.5f + m_meshBox.x());
+    m_vertices.append(m_tileSizeInPixels.height() * quadY - 0.5f + m_meshBox.y());
+    m_vertices.append(0.0f); // z
+    m_vertices.append(1.0f);
+}
+
+void CustomFilterMeshGenerator::addTexCoordAttribute(int quadX, int quadY)
+{
+    // vec2 a_texCoord
+    m_vertices.append(m_tileSizeInPixels.width() * quadX + m_meshBox.x());
+    m_vertices.append(m_tileSizeInPixels.height() * quadY + m_meshBox.y());
+}
+
+void CustomFilterMeshGenerator::addMeshCoordAttribute(int quadX, int quadY)
+{
+    // vec2 a_meshCoord
+    m_vertices.append(m_tileSizeInDeviceSpace.width() * quadX);
+    m_vertices.append(m_tileSizeInDeviceSpace.height() * quadY);
+}
+
+void CustomFilterMeshGenerator::addTriangleCoordAttribute(int quadX, int quadY, int triangle)
+{
+    // vec3 a_triangleCoord
+    m_vertices.append(quadX);
+    m_vertices.append(quadY);
+    m_vertices.append(triangle);
+}
+
+void CustomFilterMeshGenerator::addAttachedMeshVertexAttributes(int quadX, int quadY)
+{
+    addPositionAttribute(quadX, quadY);
+    addTexCoordAttribute(quadX, quadY);
+    addMeshCoordAttribute(quadX, quadY);
+}
+
+void CustomFilterMeshGenerator::addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle)
+{
+    addAttachedMeshVertexAttributes(quadX + triangleX, quadY + triangleY);
+    addTriangleCoordAttribute(quadX, quadY, triangle);
+}
+
+#ifndef NDEBUG
+void CustomFilterMeshGenerator::dumpBuffers() const
+{
+    printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n",
+           m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(),
+           (m_meshType == CustomFilterOperation::ATTACHED) ? "Attached" : "Detached");
+    printf("---Vertex:\n\t");
+    for (unsigned i = 0; i < m_vertices.size(); ++i) {
+        printf("%f ", m_vertices.at(i));
+        if (!((i + 1) % floatsPerVertex()))
+            printf("\n\t");
+    }
+    printf("\n---Indices: ");
+    for (unsigned i = 0; i < m_indices.size(); ++i)
+        printf("%d ", m_indices.at(i));
+    printf("\n");
+}
+#endif
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
+
diff --git a/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h b/Source/WebCore/platform/graphics/filters/CustomFilterMeshGenerator.h
new file mode 100644 (file)
index 0000000..09f7562
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef CustomFilterMeshGenerator_h
+#define CustomFilterMeshGenerator_h
+
+#if ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
+
+#include "CustomFilterOperation.h"
+#include "FloatRect.h"
+
+namespace WebCore {
+
+class CustomFilterMeshGenerator {
+public:
+    // Lines and columns are the values passed in CSS. The result is vertex mesh that has 'rows' numbers of rows
+    // and 'columns' number of columns with a total of 'rows + 1' * 'columns + 1' vertices.
+    // MeshBox is the filtered area calculated defined using the border-box, padding-box, content-box or filter-box
+    // attributes. A value of (0, 0, 1, 1) will cover the entire output surface.
+    CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterOperation::MeshType);
+
+    const Vector<float>& vertices() const { return m_vertices; }
+    const Vector<uint16_t>& indices() const { return m_indices; }
+
+    const IntSize& points() const { return m_points; }
+    unsigned pointsCount() const { return m_points.width() * m_points.height(); }
+
+    const IntSize& tiles() const { return m_tiles; }
+    unsigned tilesCount() const { return m_tiles.width() * m_tiles.height(); }
+
+    unsigned indicesCount() const
+    {
+        const unsigned trianglesPerTile = 2;
+        const unsigned indicesPerTriangle = 3;
+        return tilesCount() * trianglesPerTile * indicesPerTriangle;
+    }
+
+    unsigned floatsPerVertex() const
+    {
+        static const unsigned AttachedMeshVertexSize = 4 + // vec4 a_position
+                                                       2 + // vec2 a_texCoord
+                                                       2; // vec2 a_meshCoord
+
+        static const unsigned DetachedMeshVertexSize = AttachedMeshVertexSize +
+                                                       3; // vec3 a_triangleCoord
+
+        return m_meshType == CustomFilterOperation::ATTACHED ? AttachedMeshVertexSize : DetachedMeshVertexSize;
+    }
+
+    unsigned verticesCount() const
+    {
+        return m_meshType == CustomFilterOperation::ATTACHED ? pointsCount() : indicesCount();
+    }
+
+private:
+    typedef void (CustomFilterMeshGenerator::*AddTriangleVertexFunction)(int quadX, int quadY, int triangleX, int triangleY, int triangle);
+
+    template <AddTriangleVertexFunction addTriangleVertex>
+    void addTile(int quadX, int quadY)
+    {
+        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 1);
+        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 0, 2);
+        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 3);
+        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 0, 4);
+        ((*this).*(addTriangleVertex))(quadX, quadY, 1, 1, 5);
+        ((*this).*(addTriangleVertex))(quadX, quadY, 0, 1, 6);
+    }
+
+    void addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle);
+
+    void generateAttachedMesh();
+
+    void addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle);
+
+    void generateDetachedMesh();
+    void addPositionAttribute(int quadX, int quadY);
+    void addTexCoordAttribute(int quadX, int quadY);
+    void addMeshCoordAttribute(int quadX, int quadY);
+    void addTriangleCoordAttribute(int quadX, int quadY, int triangle);
+    void addAttachedMeshVertexAttributes(int quadX, int quadY);
+    void addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle);
+
+#ifndef NDEBUG
+    void dumpBuffers() const;
+#endif
+
+private:
+    Vector<float> m_vertices;
+    Vector<uint16_t> m_indices;
+
+    CustomFilterOperation::MeshType m_meshType;
+    IntSize m_points;
+    IntSize m_tiles;
+    FloatSize m_tileSizeInPixels;
+    FloatSize m_tileSizeInDeviceSpace;
+    FloatRect m_meshBox;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS) && USE(3D_GRAPHICS)
+
+#endif // CustomFilterMeshGenerator_h
index 21778a8..1802fe0 100644 (file)
@@ -70,6 +70,7 @@ String CustomFilterValidatedProgram::defaultFragmentShaderString()
 CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalContext* globalContext, const CustomFilterProgramInfo& programInfo)
     : m_globalContext(globalContext)
     , m_programInfo(programInfo)
+    , m_platformCompiledProgram(0)
     , m_isInitialized(false)
 {
     String originalVertexShader = programInfo.vertexShaderString();
@@ -102,7 +103,7 @@ CustomFilterValidatedProgram::CustomFilterValidatedProgram(CustomFilterGlobalCon
 
 PassRefPtr<CustomFilterCompiledProgram> CustomFilterValidatedProgram::compiledProgram()
 {
-    ASSERT(m_isInitialized && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
+    ASSERT(m_isInitialized && m_globalContext && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
     if (!m_compiledProgram)
         m_compiledProgram = CustomFilterCompiledProgram::create(m_globalContext->context(), m_validatedVertexShader, m_validatedFragmentShader);
     return m_compiledProgram;
@@ -263,10 +264,23 @@ String CustomFilterValidatedProgram::compositeFunctionString(CompositeOperator c
     
 CustomFilterValidatedProgram::~CustomFilterValidatedProgram()
 {
+    platformDestroy();
+
     if (m_globalContext)
         m_globalContext->removeValidatedProgram(this);
 }
 
+#if !PLATFORM(BLACKBERRY)
+PlatformCompiledProgram* CustomFilterValidatedProgram::platformCompiledProgram()
+{
+    return 0;
+}
+
+void CustomFilterValidatedProgram::platformDestroy()
+{
+}
+#endif
+
 } // namespace WebCore
 
 #endif // ENABLE(CSS_SHADERS)
index 3a9e0f1..afa7e12 100644 (file)
 #include <wtf/RefPtr.h>
 #include <wtf/text/WTFString.h>
 
+// PlatformCompiledProgram defines a type that is compatible with the framework used to implement accelerated compositing on a particular platform.
+#if PLATFORM(BLACKBERRY)
+namespace WebCore {
+class LayerCompiledProgram;
+}
+typedef WebCore::LayerCompiledProgram PlatformCompiledProgram;
+#else
+typedef void PlatformCompiledProgram;
+#endif
+
 namespace WebCore {
 
 class ANGLEWebKitBridge;
@@ -71,6 +81,8 @@ public:
     const CustomFilterProgramInfo& programInfo() const { return m_programInfo; }
     PassRefPtr<CustomFilterCompiledProgram> compiledProgram();
 
+    PlatformCompiledProgram* platformCompiledProgram();
+
     bool isInitialized() const { return m_isInitialized; }
 
     // 'detachFromGlobalContext' is called when the CustomFilterGlobalContext is deleted, and there's no need for the callback anymore. 
@@ -79,6 +91,8 @@ public:
 private:
     CustomFilterValidatedProgram(CustomFilterGlobalContext*, const CustomFilterProgramInfo&);
 
+    void platformDestroy();
+
     static String defaultVertexShaderString();
     static String defaultFragmentShaderString();
 
@@ -95,6 +109,7 @@ private:
     String m_validatedFragmentShader;
 
     RefPtr<CustomFilterCompiledProgram> m_compiledProgram;
+    PlatformCompiledProgram* m_platformCompiledProgram;
 
     bool m_isInitialized;
 };
diff --git a/Source/WebCore/platform/graphics/filters/blackberry/CustomFilterValidatedProgramBlackBerry.cpp b/Source/WebCore/platform/graphics/filters/blackberry/CustomFilterValidatedProgramBlackBerry.cpp
new file mode 100644 (file)
index 0000000..b498ef7
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer.
+ * 2. Redistributions in binary form must reproduce the above
+ *    copyright notice, this list of conditions and the following
+ *    disclaimer in the documentation and/or other materials
+ *    provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER “AS IS” AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+ * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if ENABLE(CSS_SHADERS)
+
+#include "CustomFilterValidatedProgram.h"
+
+#include "LayerCompiledProgram.h"
+
+namespace WebCore {
+
+LayerCompiledProgram* CustomFilterValidatedProgram::platformCompiledProgram()
+{
+    ASSERT(m_isInitialized && !m_validatedVertexShader.isNull() && !m_validatedFragmentShader.isNull());
+
+    if (!m_platformCompiledProgram)
+        m_platformCompiledProgram = LayerCompiledProgram::create(m_validatedVertexShader, m_validatedFragmentShader).leakRef();
+
+    return m_platformCompiledProgram;
+}
+
+void CustomFilterValidatedProgram::platformDestroy()
+{
+    derefIfNotNull(m_platformCompiledProgram);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_SHADERS)