Home | History | Annotate | Download | only in custom
      1 /*
      2  * Copyright (C) 2011 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/platform/graphics/filters/custom/CustomFilterMeshGenerator.h"
     33 
     34 #ifndef NDEBUG
     35 #include <stdio.h> // Needed for printf used in dumpBuffers.
     36 #endif
     37 
     38 namespace WebCore {
     39 
     40 #ifndef NDEBUG
     41 // Use "call 'WebCore::s_dumpCustomFilterMeshBuffers' = 1" in GDB to activate printing of the mesh buffers.
     42 static bool s_dumpCustomFilterMeshBuffers = false;
     43 #endif
     44 
     45 CustomFilterMeshGenerator::CustomFilterMeshGenerator(unsigned columns, unsigned rows, const FloatRect& meshBox, CustomFilterMeshType meshType)
     46     : m_meshType(meshType)
     47     , m_points(columns + 1, rows + 1)
     48     , m_tiles(columns, rows)
     49     , m_tileSizeInPixels(meshBox.width() / m_tiles.width(), meshBox.height() / m_tiles.height())
     50     , m_tileSizeInDeviceSpace(1.0f / m_tiles.width(), 1.0f / m_tiles.height())
     51     , m_meshBox(meshBox)
     52 {
     53     // Build the two buffers needed to draw triangles:
     54     // * m_vertices has a number of float attributes that will be passed to the vertex shader
     55     // for each computed vertex. This number is calculated in floatsPerVertex() based on the meshType.
     56     // * m_indices is a buffer that will have 3 indices per triangle. Each index will point inside
     57     // the m_vertices buffer.
     58     m_vertices.reserveCapacity(verticesCount() * floatsPerVertex());
     59     m_indices.reserveCapacity(indicesCount());
     60 
     61     // Based on the meshType there can be two types of meshes.
     62     // * attached: each triangle uses vertices from the neighbor triangles. This is useful to save some GPU memory
     63     // when there's no need to explode the tiles.
     64     // * detached: each triangle has its own vertices. This means each triangle can be moved independently and a vec3
     65     // attribute is passed, so that each vertex can be uniquely identified.
     66     if (m_meshType == MeshTypeAttached)
     67         generateAttachedMesh();
     68     else
     69         generateDetachedMesh();
     70 
     71 #ifndef NDEBUG
     72     if (s_dumpCustomFilterMeshBuffers)
     73         dumpBuffers();
     74 #endif
     75 }
     76 
     77 void CustomFilterMeshGenerator::addAttachedMeshIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
     78 {
     79     UNUSED_PARAM(triangle);
     80     m_indices.append((quadY + triangleY) * m_points.width() + (quadX + triangleX));
     81 }
     82 
     83 void CustomFilterMeshGenerator::generateAttachedMesh()
     84 {
     85     for (int j = 0; j < m_points.height(); ++j) {
     86         for (int i = 0; i < m_points.width(); ++i)
     87             addAttachedMeshVertexAttributes(i, j);
     88     }
     89 
     90     for (int j = 0; j < m_tiles.height(); ++j) {
     91         for (int i = 0; i < m_tiles.width(); ++i)
     92             addTile<&CustomFilterMeshGenerator::addAttachedMeshIndex>(i, j);
     93     }
     94 }
     95 
     96 void CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex(int quadX, int quadY, int triangleX, int triangleY, int triangle)
     97 {
     98     addDetachedMeshVertexAttributes(quadX, quadY, triangleX, triangleY, triangle);
     99     m_indices.append(m_indices.size());
    100 }
    101 
    102 void CustomFilterMeshGenerator::generateDetachedMesh()
    103 {
    104     for (int j = 0; j < m_tiles.height(); ++j) {
    105         for (int i = 0; i < m_tiles.width(); ++i)
    106             addTile<&CustomFilterMeshGenerator::addDetachedMeshVertexAndIndex>(i, j);
    107     }
    108 }
    109 
    110 void CustomFilterMeshGenerator::addPositionAttribute(int quadX, int quadY)
    111 {
    112     // vec4 a_position
    113     m_vertices.append(m_tileSizeInPixels.width() * quadX - 0.5f + m_meshBox.x());
    114     m_vertices.append(m_tileSizeInPixels.height() * quadY - 0.5f + m_meshBox.y());
    115     m_vertices.append(0.0f); // z
    116     m_vertices.append(1.0f);
    117 }
    118 
    119 void CustomFilterMeshGenerator::addTexCoordAttribute(int quadX, int quadY)
    120 {
    121     // vec2 a_texCoord
    122     m_vertices.append(m_tileSizeInPixels.width() * quadX + m_meshBox.x());
    123     m_vertices.append(m_tileSizeInPixels.height() * quadY + m_meshBox.y());
    124 }
    125 
    126 void CustomFilterMeshGenerator::addMeshCoordAttribute(int quadX, int quadY)
    127 {
    128     // vec2 a_meshCoord
    129     m_vertices.append(m_tileSizeInDeviceSpace.width() * quadX);
    130     m_vertices.append(m_tileSizeInDeviceSpace.height() * quadY);
    131 }
    132 
    133 void CustomFilterMeshGenerator::addTriangleCoordAttribute(int quadX, int quadY, int triangle)
    134 {
    135     // vec3 a_triangleCoord
    136     m_vertices.append(quadX);
    137     m_vertices.append(quadY);
    138     m_vertices.append(triangle);
    139 }
    140 
    141 void CustomFilterMeshGenerator::addAttachedMeshVertexAttributes(int quadX, int quadY)
    142 {
    143     addPositionAttribute(quadX, quadY);
    144     addTexCoordAttribute(quadX, quadY);
    145     addMeshCoordAttribute(quadX, quadY);
    146 }
    147 
    148 void CustomFilterMeshGenerator::addDetachedMeshVertexAttributes(int quadX, int quadY, int triangleX, int triangleY, int triangle)
    149 {
    150     addAttachedMeshVertexAttributes(quadX + triangleX, quadY + triangleY);
    151     addTriangleCoordAttribute(quadX, quadY, triangle);
    152 }
    153 
    154 #ifndef NDEBUG
    155 void CustomFilterMeshGenerator::dumpBuffers() const
    156 {
    157     printf("Mesh buffers: Points.width(): %d, Points.height(): %d meshBox: %f, %f, %f, %f, type: %s\n",
    158         m_points.width(), m_points.height(), m_meshBox.x(), m_meshBox.y(), m_meshBox.width(), m_meshBox.height(),
    159         (m_meshType == MeshTypeAttached) ? "Attached" : "Detached");
    160     printf("---Vertex:\n\t");
    161     for (unsigned i = 0; i < m_vertices.size(); ++i) {
    162         printf("%f ", m_vertices.at(i));
    163         if (!((i + 1) % floatsPerVertex()))
    164             printf("\n\t");
    165     }
    166     printf("\n---Indices: ");
    167     for (unsigned i = 0; i < m_indices.size(); ++i)
    168         printf("%d ", m_indices.at(i));
    169     printf("\n");
    170 }
    171 #endif
    172 
    173 } // namespace WebCore
    174