Home | History | Annotate | Download | only in custom
      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 #include "core/platform/graphics/filters/custom/CustomFilterCompiledProgram.h"
     33 
     34 namespace WebCore {
     35 
     36 CustomFilterCompiledProgram::CustomFilterCompiledProgram(PassRefPtr<GraphicsContext3D> context, const String& validatedVertexShader, const String& validatedFragmentShader, CustomFilterProgramType programType)
     37     : m_context(context)
     38     , m_program(0)
     39     , m_positionAttribLocation(-1)
     40     , m_texAttribLocation(-1)
     41     , m_meshAttribLocation(-1)
     42     , m_triangleAttribLocation(-1)
     43     , m_meshBoxLocation(-1)
     44     , m_projectionMatrixLocation(-1)
     45     , m_tileSizeLocation(-1)
     46     , m_meshSizeLocation(-1)
     47     , m_samplerLocation(-1)
     48     , m_samplerSizeLocation(-1)
     49     , m_contentSamplerLocation(-1)
     50     , m_isInitialized(false)
     51 {
     52     m_context->makeContextCurrent();
     53 
     54     Platform3DObject vertexShader = compileShader(GraphicsContext3D::VERTEX_SHADER, validatedVertexShader);
     55     if (!vertexShader)
     56         return;
     57 
     58     Platform3DObject fragmentShader = compileShader(GraphicsContext3D::FRAGMENT_SHADER, validatedFragmentShader);
     59     if (!fragmentShader) {
     60         m_context->deleteShader(vertexShader);
     61         return;
     62     }
     63 
     64     m_program = linkProgram(vertexShader, fragmentShader);
     65 
     66     m_context->deleteShader(vertexShader);
     67     m_context->deleteShader(fragmentShader);
     68 
     69     if (!m_program)
     70         return;
     71 
     72     initializeParameterLocations(programType);
     73 
     74     m_isInitialized = true;
     75 }
     76 
     77 Platform3DObject CustomFilterCompiledProgram::compileShader(GC3Denum shaderType, const String& shaderString)
     78 {
     79     ASSERT(!shaderString.isNull());
     80 
     81     Platform3DObject shader = m_context->createShader(shaderType);
     82     m_context->shaderSource(shader, shaderString);
     83     m_context->compileShader(shader);
     84 
     85     int compiled = 0;
     86     m_context->getShaderiv(shader, GraphicsContext3D::COMPILE_STATUS, &compiled);
     87     if (!compiled) {
     88         // FIXME: This is an invalid shader. Throw some errors.
     89         // https://bugs.webkit.org/show_bug.cgi?id=74416
     90         m_context->deleteShader(shader);
     91         return 0;
     92     }
     93 
     94     return shader;
     95 }
     96 
     97 Platform3DObject CustomFilterCompiledProgram::linkProgram(Platform3DObject vertexShader, Platform3DObject fragmentShader)
     98 {
     99     Platform3DObject program = m_context->createProgram();
    100     m_context->attachShader(program, vertexShader);
    101     m_context->attachShader(program, fragmentShader);
    102     m_context->linkProgram(program);
    103 
    104     int linked = 0;
    105     m_context->getProgramiv(program, GraphicsContext3D::LINK_STATUS, &linked);
    106     if (!linked) {
    107         // FIXME: Invalid vertex/fragment shader combination. Throw some errors here.
    108         // https://bugs.webkit.org/show_bug.cgi?id=74416
    109         m_context->deleteProgram(program);
    110         return 0;
    111     }
    112 
    113     return program;
    114 }
    115 
    116 void CustomFilterCompiledProgram::initializeParameterLocations(CustomFilterProgramType programType)
    117 {
    118     m_positionAttribLocation = m_context->getAttribLocation(m_program, "a_position");
    119     m_texAttribLocation = m_context->getAttribLocation(m_program, "a_texCoord");
    120     m_meshAttribLocation = m_context->getAttribLocation(m_program, "a_meshCoord");
    121     m_triangleAttribLocation = m_context->getAttribLocation(m_program, "a_triangleCoord");
    122     m_meshBoxLocation = m_context->getUniformLocation(m_program, "u_meshBox");
    123     m_tileSizeLocation = m_context->getUniformLocation(m_program, "u_tileSize");
    124     m_meshSizeLocation = m_context->getUniformLocation(m_program, "u_meshSize");
    125     m_projectionMatrixLocation = m_context->getUniformLocation(m_program, "u_projectionMatrix");
    126     m_samplerSizeLocation = m_context->getUniformLocation(m_program, "u_textureSize");
    127     m_contentSamplerLocation = m_context->getUniformLocation(m_program, "u_contentTexture");
    128     if (programType == PROGRAM_TYPE_BLENDS_ELEMENT_TEXTURE) {
    129         // When the author uses the CSS mix function in a custom filter, WebKit adds the internal
    130         // symbol css_u_texture to the shader code, which references the texture of the element.
    131         m_samplerLocation = m_context->getUniformLocation(m_program, "css_u_texture");
    132     }
    133 }
    134 
    135 int CustomFilterCompiledProgram::uniformLocationByName(const String& name)
    136 {
    137     ASSERT(m_isInitialized);
    138     // FIXME: Improve this by caching the uniform locations.
    139     return m_context->getUniformLocation(m_program, name);
    140 }
    141 
    142 CustomFilterCompiledProgram::~CustomFilterCompiledProgram()
    143 {
    144     if (m_program) {
    145         m_context->makeContextCurrent();
    146         m_context->deleteProgram(m_program);
    147     }
    148 }
    149 
    150 } // namespace WebCore
    151