2
* Copyright © 2012 Linaro Ltd.
4
* Permission to use, copy, modify, distribute, and sell this software
5
* and its documentation for any purpose is hereby granted without
6
* fee, provided that the above copyright notice appear in all copies
7
* and that both that copyright notice and this permission notice
8
* appear in supporting documentation, and that the name of
9
* Linaro Ltd. not be used in advertising or publicity pertaining to
10
* distribution of the software without specific, written prior permission.
11
* Linaro Ltd. makes no representations about the suitability of this
12
* software for any purpose. It is provided "as is" without express or
15
* LINARO LTD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
16
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN
17
* NO EVENT SHALL LINARO LTD. BE LIABLE FOR ANY SPECIAL, INDIRECT OR
18
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
19
* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
20
* NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
21
* WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23
* Authors: Alexandros Frantzis <alexandros.frantzis@linaro.org>
28
#include <opengl/shadercache.h>
31
* Compares two GLShaderParameters objects.
33
class GLShaderParametersComparer
36
bool operator()(const GLShaderParameters &left, const GLShaderParameters &right) const
38
return left.hash() < right.hash();
43
typedef std::map<GLShaderParameters, GLShaderData, GLShaderParametersComparer> ShaderMapType;
46
* Private data for GLPrivate
48
class PrivateShaderCache
51
PrivateShaderCache() {}
53
ShaderMapType::const_iterator addShaderData(const GLShaderParameters ¶ms);
55
std::string createVertexShader (const GLShaderParameters ¶ms);
56
std::string createFragmentShader (const GLShaderParameters ¶ms);
58
ShaderMapType shaderMap;
61
/**********************
62
* GLShaderParameters *
63
**********************/
66
GLShaderParameters::hash() const
68
return static_cast<int>(opacity) |
69
(static_cast<int>(brightness) << 1) |
70
(static_cast<int>(saturation) << 2) |
71
(static_cast<int>(color) << 3) |
72
(static_cast<int>(normal) << 5) |
73
(static_cast<int>(numTextures) << 8);
77
GLShaderParameters::id() const
81
ss << (opacity ? "t" : "f");
82
ss << (brightness ? "t" : "f");
83
ss << (saturation ? "t" : "f");
84
ss << (color == GLShaderVariableNone ? "n" :
85
color == GLShaderVariableUniform ? "u" : "v");
87
ss << (normal == GLShaderVariableNone ? "n" :
88
normal == GLShaderVariableUniform ? "u" : "v");
98
GLShaderCache::GLShaderCache () :
99
priv (new PrivateShaderCache ())
104
GLShaderCache::getShaderData (const GLShaderParameters ¶ms)
106
ShaderMapType::const_iterator iter;
108
// Try to find a cached shader pair that matches the parameters.
109
// If we don't have it cached, create it.
110
if ((iter = priv->shaderMap.find (params)) == priv->shaderMap.end ())
111
iter = priv->addShaderData (params);
116
/**********************
117
* PrivateShaderCache *
118
**********************/
120
ShaderMapType::const_iterator
121
PrivateShaderCache::addShaderData (const GLShaderParameters ¶ms)
123
GLShaderData shaderData;
125
shaderData.name = params.id ();
126
shaderData.fragmentShader = createFragmentShader (params);
127
shaderData.vertexShader = createVertexShader (params);
129
std::pair<ShaderMapType::iterator, bool> ret =
130
shaderMap.insert(std::pair<GLShaderParameters, GLShaderData>(params,shaderData));
136
* Creates a minimal vertex shader that can handle the GLShaderParameters.
138
* @param params the GLShaderParameters the created shader should handle.
140
* @return the shader string
143
PrivateShaderCache::createVertexShader (const GLShaderParameters ¶ms)
145
std::stringstream ss;
147
ss << "#ifdef GL_ES\n" <<
148
"precision mediump float;\n" <<
151
ss << "uniform mat4 modelview;\n" <<
152
"uniform mat4 projection;\n";
154
ss << "attribute vec3 position;\n" <<
155
"attribute vec3 normal;\n" <<
156
"attribute vec4 color;\n" <<
157
"attribute vec2 texCoord0;\n" <<
158
"attribute vec2 texCoord1;\n" <<
159
"attribute vec2 texCoord2;\n" <<
160
"attribute vec2 texCoord3;\n";
162
ss << "@VERTEX_FUNCTIONS@\n";
164
if (params.color == GLShaderVariableVarying)
165
ss << "varying vec4 vColor;\n";
167
for (int i = 0; i < params.numTextures; i++)
168
ss << "varying vec2 vTexCoord" << i << ";\n";
170
ss << "void main() {\n";
172
for (int i = 0; i < params.numTextures; i++)
173
ss << "vTexCoord" << i << " = texCoord" << i <<";\n";
175
if (params.color == GLShaderVariableVarying)
176
ss << "vColor = color;\n";
178
ss << "gl_Position = projection * modelview * vec4(position, 1.0);\n";
180
ss << "@VERTEX_FUNCTION_CALLS@\n}";
186
* Creates a minimal fragment shader that can handle the GLShaderParameters.
188
* @param params the GLShaderParameters the created shader should handle.
190
* @return the shader string
193
PrivateShaderCache::createFragmentShader (const GLShaderParameters ¶ms)
195
std::stringstream ss;
196
ss << "#ifdef GL_ES\n" <<
197
"precision mediump float;\n" <<
200
ss << "uniform vec3 paintAttrib;\n";
202
for (int i = 0; i < params.numTextures; i++) {
203
ss << "uniform sampler2D texture" << i << ";\n";
204
ss << "varying vec2 vTexCoord" << i << ";\n";
207
if (params.color == GLShaderVariableUniform)
208
ss << "uniform vec4 singleColor;\n";
209
else if (params.color == GLShaderVariableVarying)
210
ss << "varying vec4 vColor;\n";
212
ss << "@FRAGMENT_FUNCTIONS@\n";
214
ss << "void main() {\n vec4 color = ";
216
if (params.color == GLShaderVariableUniform)
217
ss << "singleColor *";
218
else if (params.color == GLShaderVariableVarying)
221
for (int i = 0; i < params.numTextures; i++)
222
ss << " texture2D(texture" << i << ", vTexCoord" << i << ") *";
226
if (params.saturation) {
227
ss << "vec3 desaturated = color.rgb * vec3 (0.30, 0.59, 0.11);\n" <<
228
"desaturated = vec3 (dot (desaturated, color.rgb));\n" <<
229
"color.rgb = color.rgb * vec3 (paintAttrib.z) + desaturated *\n" <<
230
" vec3 (1.0 - paintAttrib.z);\n";
233
if (params.brightness) {
234
ss << "color.rgb = color.rgb * paintAttrib.y" <<
235
(params.opacity ? " * paintAttrib.x;\n" : ";\n") <<
236
(params.opacity ? "color.a = color.a * paintAttrib.x;\n" : "");
238
else if (params.opacity) {
239
ss << "color = color * paintAttrib.x;\n";
242
ss << "gl_FragColor = color;\n";
243
ss << "@FRAGMENT_FUNCTION_CALLS@\n}";