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