~compiz-team/compiz/0.9.12

« back to all changes in this revision

Viewing changes to plugins/opengl/src/shadercache.cpp

  • Committer: Sam Spilsbury
  • Date: 2012-08-22 10:07:45 UTC
  • mfrom: (3201.2.177 gles2)
  • mto: (3248.1.29 compiz)
  • mto: This revision was merged to the branch mainline in revision 3451.
  • Revision ID: sam.spilsbury@canonical.com-20120822100745-j5bofdehkq79wcvq
Merge

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2012 Linaro Ltd.
 
3
 *
 
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
 
13
 * implied warranty.
 
14
 *
 
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.
 
22
 *
 
23
 * Authors: Alexandros Frantzis <alexandros.frantzis@linaro.org>
 
24
 */
 
25
#include <map>
 
26
#include <sstream>
 
27
 
 
28
#include <opengl/shadercache.h>
 
29
 
 
30
/** 
 
31
 * Compares two GLShaderParameters objects.
 
32
 */
 
33
class GLShaderParametersComparer
 
34
{
 
35
public:
 
36
    bool operator()(const GLShaderParameters &left, const GLShaderParameters &right) const
 
37
    {
 
38
        return left.hash() < right.hash();
 
39
    }
 
40
 
 
41
};
 
42
 
 
43
typedef std::map<GLShaderParameters, GLShaderData, GLShaderParametersComparer> ShaderMapType;
 
44
 
 
45
/** 
 
46
 * Private data for GLPrivate
 
47
 */
 
48
class PrivateShaderCache
 
49
{
 
50
public:
 
51
    PrivateShaderCache() {}
 
52
 
 
53
    ShaderMapType::const_iterator addShaderData(const GLShaderParameters &params);
 
54
 
 
55
    std::string createVertexShader (const GLShaderParameters &params);
 
56
    std::string createFragmentShader (const GLShaderParameters &params);
 
57
 
 
58
    ShaderMapType shaderMap;
 
59
};
 
60
 
 
61
/**********************
 
62
 * GLShaderParameters *
 
63
 **********************/
 
64
 
 
65
int
 
66
GLShaderParameters::hash() const
 
67
{
 
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);
 
74
}
 
75
 
 
76
std::string
 
77
GLShaderParameters::id() const
 
78
{
 
79
    std::stringstream ss;
 
80
 
 
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");
 
86
 
 
87
    ss << (normal == GLShaderVariableNone ? "n" :
 
88
           normal == GLShaderVariableUniform ? "u" : "v");
 
89
    ss << numTextures;
 
90
 
 
91
    return ss.str();
 
92
}
 
93
 
 
94
/*****************
 
95
 * GLShaderCache *
 
96
 *****************/
 
97
 
 
98
GLShaderCache::GLShaderCache () :
 
99
    priv (new PrivateShaderCache ())
 
100
{
 
101
}
 
102
 
 
103
const GLShaderData &
 
104
GLShaderCache::getShaderData (const GLShaderParameters &params)
 
105
{
 
106
    ShaderMapType::const_iterator iter;
 
107
 
 
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);
 
112
 
 
113
    return iter->second;
 
114
}
 
115
 
 
116
/**********************
 
117
 * PrivateShaderCache *
 
118
 **********************/
 
119
 
 
120
ShaderMapType::const_iterator
 
121
PrivateShaderCache::addShaderData (const GLShaderParameters &params)
 
122
{
 
123
    GLShaderData shaderData;
 
124
 
 
125
    shaderData.name = params.id ();
 
126
    shaderData.fragmentShader = createFragmentShader (params);
 
127
    shaderData.vertexShader = createVertexShader (params);
 
128
 
 
129
    std::pair<ShaderMapType::iterator, bool> ret =
 
130
        shaderMap.insert(std::pair<GLShaderParameters, GLShaderData>(params,shaderData));
 
131
 
 
132
    return ret.first;
 
133
}
 
134
 
 
135
/** 
 
136
 * Creates a minimal vertex shader that can handle the GLShaderParameters.
 
137
 * 
 
138
 * @param params the GLShaderParameters the created shader should handle.
 
139
 * 
 
140
 * @return the shader string
 
141
 */
 
142
std::string
 
143
PrivateShaderCache::createVertexShader (const GLShaderParameters &params)
 
144
{
 
145
    std::stringstream ss;
 
146
 
 
147
    ss << "#ifdef GL_ES\n" <<
 
148
          "precision mediump float;\n" <<
 
149
          "#endif\n";
 
150
 
 
151
    ss << "uniform mat4 modelview;\n" <<
 
152
          "uniform mat4 projection;\n";
 
153
 
 
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";
 
161
 
 
162
    ss << "@VERTEX_FUNCTIONS@\n";
 
163
 
 
164
    if (params.color == GLShaderVariableVarying)
 
165
        ss << "varying vec4 vColor;\n";
 
166
 
 
167
    for (int i = 0; i < params.numTextures; i++)
 
168
        ss << "varying vec2 vTexCoord" << i << ";\n";
 
169
 
 
170
    ss << "void main() {\n";
 
171
 
 
172
    for (int i = 0; i < params.numTextures; i++)
 
173
        ss << "vTexCoord" << i << " = texCoord" << i <<";\n";
 
174
 
 
175
    if (params.color == GLShaderVariableVarying)
 
176
        ss << "vColor = color;\n";
 
177
 
 
178
    ss << "gl_Position = projection * modelview * vec4(position, 1.0);\n";
 
179
 
 
180
    ss << "@VERTEX_FUNCTION_CALLS@\n}";
 
181
 
 
182
    return ss.str();
 
183
}
 
184
 
 
185
/** 
 
186
 * Creates a minimal fragment shader that can handle the GLShaderParameters.
 
187
 * 
 
188
 * @param params the GLShaderParameters the created shader should handle.
 
189
 * 
 
190
 * @return the shader string
 
191
 */
 
192
std::string
 
193
PrivateShaderCache::createFragmentShader (const GLShaderParameters &params)
 
194
{
 
195
    std::stringstream ss;
 
196
    ss << "#ifdef GL_ES\n" <<
 
197
          "precision mediump float;\n" <<
 
198
          "#endif\n";
 
199
 
 
200
    ss << "uniform vec3 paintAttrib;\n";
 
201
 
 
202
    for (int i = 0; i < params.numTextures; i++) {
 
203
        ss << "uniform sampler2D texture" << i << ";\n";
 
204
        ss << "varying vec2 vTexCoord" << i << ";\n";
 
205
    }
 
206
 
 
207
    if (params.color == GLShaderVariableUniform)
 
208
        ss << "uniform vec4 singleColor;\n";
 
209
    else if (params.color == GLShaderVariableVarying)
 
210
        ss << "varying vec4 vColor;\n";
 
211
 
 
212
    ss << "@FRAGMENT_FUNCTIONS@\n";
 
213
 
 
214
    ss << "void main() {\n vec4 color = ";
 
215
 
 
216
    if (params.color == GLShaderVariableUniform)
 
217
        ss << "singleColor *";
 
218
    else if (params.color == GLShaderVariableVarying)
 
219
        ss << "vColor *";
 
220
 
 
221
    for (int i = 0; i < params.numTextures; i++)
 
222
        ss << " texture2D(texture" << i << ", vTexCoord" << i << ") *";
 
223
 
 
224
    ss << " 1.0;\n";
 
225
 
 
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";
 
231
    }
 
232
 
 
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" : "");
 
237
    }
 
238
    else if (params.opacity) {
 
239
        ss << "color = color * paintAttrib.x;\n";
 
240
    }
 
241
 
 
242
    ss << "gl_FragColor = color;\n";
 
243
    ss << "@FRAGMENT_FUNCTION_CALLS@\n}";
 
244
 
 
245
    return ss.str();
 
246
}