1 | /* |
2 | Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies) |
3 | Copyright (C) 2012 Igalia S.L. |
4 | Copyright (C) 2011 Google Inc. All rights reserved. |
5 | |
6 | This library is free software; you can redistribute it and/or |
7 | modify it under the terms of the GNU Library General Public |
8 | License as published by the Free Software Foundation; either |
9 | version 2 of the License, or (at your option) any later version. |
10 | |
11 | This library is distributed in the hope that it will be useful, |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | Library General Public License for more details. |
15 | |
16 | You should have received a copy of the GNU Library General Public License |
17 | along with this library; see the file COPYING.LIB. If not, write to |
18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
19 | Boston, MA 02110-1301, USA. |
20 | */ |
21 | |
22 | #include "config.h" |
23 | #include "TextureMapperShaderProgram.h" |
24 | |
25 | #if USE(TEXTURE_MAPPER_GL) |
26 | |
27 | #include "GLContext.h" |
28 | #include "Logging.h" |
29 | #include "TextureMapperGL.h" |
30 | #include <wtf/text/StringBuilder.h> |
31 | |
32 | namespace WebCore { |
33 | |
34 | static inline bool compositingLogEnabled() |
35 | { |
36 | #if !LOG_DISABLED |
37 | return LogCompositing.state == WTFLogChannelState::On; |
38 | #else |
39 | return false; |
40 | #endif |
41 | } |
42 | |
43 | #define STRINGIFY(...) #__VA_ARGS__ |
44 | |
45 | #define GLSL_DIRECTIVE(...) "#"#__VA_ARGS__"\n" |
46 | |
47 | #define TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE \ |
48 | GLSL_DIRECTIVE(ifdef GL_FRAGMENT_PRECISION_HIGH) \ |
49 | GLSL_DIRECTIVE(define TextureSpaceMatrixPrecision highp) \ |
50 | GLSL_DIRECTIVE(else) \ |
51 | GLSL_DIRECTIVE(define TextureSpaceMatrixPrecision mediump) \ |
52 | GLSL_DIRECTIVE(endif) |
53 | |
54 | |
55 | // Input/output variables definition for both GLES and OpenGL < 3.2. |
56 | // The default precision directive is only needed for GLES. |
57 | static const char* vertexTemplateLT320Vars = |
58 | #if USE(OPENGL_ES) |
59 | TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE |
60 | #endif |
61 | #if USE(OPENGL_ES) |
62 | STRINGIFY( |
63 | precision TextureSpaceMatrixPrecision float; |
64 | ) |
65 | #endif |
66 | STRINGIFY( |
67 | attribute vec4 a_vertex; |
68 | varying vec2 v_texCoord; |
69 | varying vec2 v_transformedTexCoord; |
70 | varying float v_antialias; |
71 | ); |
72 | |
73 | #if !USE(OPENGL_ES) |
74 | // Input/output variables definition for OpenGL >= 3.2. |
75 | static const char* vertexTemplateGE320Vars = |
76 | STRINGIFY( |
77 | in vec4 a_vertex; |
78 | out vec2 v_texCoord; |
79 | out vec2 v_transformedTexCoord; |
80 | out float v_antialias; |
81 | ); |
82 | #endif |
83 | |
84 | static const char* vertexTemplateCommon = |
85 | STRINGIFY( |
86 | uniform mat4 u_modelViewMatrix; |
87 | uniform mat4 u_projectionMatrix; |
88 | uniform mat4 u_textureSpaceMatrix; |
89 | |
90 | void noop(inout vec2 dummyParameter) { } |
91 | |
92 | vec4 toViewportSpace(vec2 pos) { return vec4(pos, 0., 1.) * u_modelViewMatrix; } |
93 | |
94 | // This function relies on the assumption that we get edge triangles with control points, |
95 | // a control point being the nearest point to the coordinate that is on the edge. |
96 | void applyAntialiasing(inout vec2 position) |
97 | { |
98 | // We count on the fact that quad passed in is always a unit rect, |
99 | // and the transformation matrix applies the real rect. |
100 | const vec2 center = vec2(0.5, 0.5); |
101 | const float antialiasInflationDistance = 1.; |
102 | |
103 | // We pass the control point as the zw coordinates of the vertex. |
104 | // The control point is the point on the edge closest to the current position. |
105 | // The control point is used to compute the antialias value. |
106 | vec2 controlPoint = a_vertex.zw; |
107 | |
108 | // First we calculate the distance in viewport space. |
109 | vec4 centerInViewportCoordinates = toViewportSpace(center); |
110 | vec4 controlPointInViewportCoordinates = toViewportSpace(controlPoint); |
111 | float viewportSpaceDistance = distance(centerInViewportCoordinates, controlPointInViewportCoordinates); |
112 | |
113 | // We add the inflation distance to the computed distance, and compute the ratio. |
114 | float inflationRatio = (viewportSpaceDistance + antialiasInflationDistance) / viewportSpaceDistance; |
115 | |
116 | // v_antialias needs to be 0 for the outer edge and 1. for the inner edge. |
117 | // Since the controlPoint is equal to the position in the edge vertices, the value is always 0 for those. |
118 | // For the center point, the distance is always 0.5, so we normalize to 1. by multiplying by 2. |
119 | // By multplying by inflationRatio and dividing by (inflationRatio - 1), |
120 | // We make sure that the varying interpolates between 0 (outer edge), 1 (inner edge) and n > 1 (center). |
121 | v_antialias = distance(controlPoint, position) * 2. * inflationRatio / (inflationRatio - 1.); |
122 | |
123 | // Now inflate the actual position. By using this formula instead of inflating position directly, |
124 | // we ensure that the center vertex is never inflated. |
125 | position = center + (position - center) * inflationRatio; |
126 | } |
127 | |
128 | void main(void) |
129 | { |
130 | vec2 position = a_vertex.xy; |
131 | applyAntialiasingIfNeeded(position); |
132 | |
133 | v_texCoord = position; |
134 | vec4 clampedPosition = clamp(vec4(position, 0., 1.), 0., 1.); |
135 | v_transformedTexCoord = (u_textureSpaceMatrix * clampedPosition).xy; |
136 | gl_Position = u_projectionMatrix * u_modelViewMatrix * vec4(position, 0., 1.); |
137 | } |
138 | ); |
139 | |
140 | #define RECT_TEXTURE_DIRECTIVE \ |
141 | GLSL_DIRECTIVE(ifdef ENABLE_Rect) \ |
142 | GLSL_DIRECTIVE(define SamplerType sampler2DRect) \ |
143 | GLSL_DIRECTIVE(define SamplerFunction texture2DRect) \ |
144 | GLSL_DIRECTIVE(else) \ |
145 | GLSL_DIRECTIVE(define SamplerType sampler2D) \ |
146 | GLSL_DIRECTIVE(define SamplerFunction texture2D) \ |
147 | GLSL_DIRECTIVE(endif) |
148 | |
149 | #define ANTIALIASING_TEX_COORD_DIRECTIVE \ |
150 | GLSL_DIRECTIVE(if defined(ENABLE_Antialiasing) && defined(ENABLE_Texture)) \ |
151 | GLSL_DIRECTIVE(define transformTexCoord fragmentTransformTexCoord) \ |
152 | GLSL_DIRECTIVE(else) \ |
153 | GLSL_DIRECTIVE(define transformTexCoord vertexTransformTexCoord) \ |
154 | GLSL_DIRECTIVE(endif) |
155 | |
156 | #define ENABLE_APPLIER(Name) "#define ENABLE_"#Name"\n#define apply"#Name"IfNeeded apply"#Name"\n" |
157 | #define DISABLE_APPLIER(Name) "#define apply"#Name"IfNeeded noop\n" |
158 | #define BLUR_CONSTANTS \ |
159 | GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_HALF_WIDTH 11) \ |
160 | GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_STEP 0.2) |
161 | |
162 | |
163 | // Common header for all versions. We define the matrices variables here to keep the precision |
164 | // directives scope: the first one applies to the matrices variables and the next one to the |
165 | // rest of them. The precision is only used in GLES. |
166 | static const char* = |
167 | RECT_TEXTURE_DIRECTIVE |
168 | ANTIALIASING_TEX_COORD_DIRECTIVE |
169 | BLUR_CONSTANTS |
170 | #if USE(OPENGL_ES) |
171 | TEXTURE_SPACE_MATRIX_PRECISION_DIRECTIVE |
172 | #endif |
173 | #if USE(OPENGL_ES) |
174 | STRINGIFY( |
175 | precision TextureSpaceMatrixPrecision float; |
176 | ) |
177 | #endif |
178 | STRINGIFY( |
179 | uniform mat4 u_textureSpaceMatrix; |
180 | uniform mat4 u_textureColorSpaceMatrix; |
181 | ) |
182 | #if USE(OPENGL_ES) |
183 | STRINGIFY( |
184 | precision mediump float; |
185 | ) |
186 | #endif |
187 | ; |
188 | |
189 | // Input/output variables definition for both GLES and OpenGL < 3.2. |
190 | static const char* fragmentTemplateLT320Vars = |
191 | STRINGIFY( |
192 | varying float v_antialias; |
193 | varying vec2 v_texCoord; |
194 | varying vec2 v_transformedTexCoord; |
195 | ); |
196 | |
197 | #if !USE(OPENGL_ES) |
198 | // Input/output variables definition for OpenGL >= 3.2. |
199 | static const char* fragmentTemplateGE320Vars = |
200 | STRINGIFY( |
201 | in float v_antialias; |
202 | in vec2 v_texCoord; |
203 | in vec2 v_transformedTexCoord; |
204 | ); |
205 | #endif |
206 | |
207 | static const char* fragmentTemplateCommon = |
208 | STRINGIFY( |
209 | uniform SamplerType s_sampler; |
210 | uniform sampler2D s_contentTexture; |
211 | uniform float u_opacity; |
212 | uniform float u_filterAmount; |
213 | uniform vec2 u_blurRadius; |
214 | uniform vec2 u_shadowOffset; |
215 | uniform vec4 u_color; |
216 | uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; |
217 | |
218 | void noop(inout vec4 dummyParameter) { } |
219 | void noop(inout vec4 dummyParameter, vec2 texCoord) { } |
220 | void noop(inout vec2 dummyParameter) { } |
221 | |
222 | float antialias() { return smoothstep(0., 1., v_antialias); } |
223 | |
224 | vec2 fragmentTransformTexCoord() |
225 | { |
226 | vec4 clampedPosition = clamp(vec4(v_texCoord, 0., 1.), 0., 1.); |
227 | return (u_textureSpaceMatrix * clampedPosition).xy; |
228 | } |
229 | |
230 | vec2 vertexTransformTexCoord() { return v_transformedTexCoord; } |
231 | |
232 | void applyManualRepeat(inout vec2 pos) { pos = fract(pos); } |
233 | |
234 | void applyTexture(inout vec4 color, vec2 texCoord) { color = u_textureColorSpaceMatrix * SamplerFunction(s_sampler, texCoord); } |
235 | void applyOpacity(inout vec4 color) { color *= u_opacity; } |
236 | void applyAntialiasing(inout vec4 color) { color *= antialias(); } |
237 | |
238 | void applyGrayscaleFilter(inout vec4 color) |
239 | { |
240 | float amount = 1.0 - u_filterAmount; |
241 | color = vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b, |
242 | (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b, |
243 | (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b, |
244 | color.a); |
245 | } |
246 | |
247 | void applySepiaFilter(inout vec4 color) |
248 | { |
249 | float amount = 1.0 - u_filterAmount; |
250 | color = vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b, |
251 | (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b, |
252 | (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b, |
253 | color.a); |
254 | } |
255 | |
256 | void applySaturateFilter(inout vec4 color) |
257 | { |
258 | color = vec4((0.213 + 0.787 * u_filterAmount) * color.r + (0.715 - 0.715 * u_filterAmount) * color.g + (0.072 - 0.072 * u_filterAmount) * color.b, |
259 | (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 + 0.285 * u_filterAmount) * color.g + (0.072 - 0.072 * u_filterAmount) * color.b, |
260 | (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 - 0.715 * u_filterAmount) * color.g + (0.072 + 0.928 * u_filterAmount) * color.b, |
261 | color.a); |
262 | } |
263 | |
264 | void applyHueRotateFilter(inout vec4 color) |
265 | { |
266 | float pi = 3.14159265358979323846; |
267 | float c = cos(u_filterAmount * pi / 180.0); |
268 | float s = sin(u_filterAmount * pi / 180.0); |
269 | color = vec4(color.r * (0.213 + c * 0.787 - s * 0.213) + color.g * (0.715 - c * 0.715 - s * 0.715) + color.b * (0.072 - c * 0.072 + s * 0.928), |
270 | color.r * (0.213 - c * 0.213 + s * 0.143) + color.g * (0.715 + c * 0.285 + s * 0.140) + color.b * (0.072 - c * 0.072 - s * 0.283), |
271 | color.r * (0.213 - c * 0.213 - s * 0.787) + color.g * (0.715 - c * 0.715 + s * 0.715) + color.b * (0.072 + c * 0.928 + s * 0.072), |
272 | color.a); |
273 | } |
274 | |
275 | float invert(float n) { return (1.0 - n) * u_filterAmount + n * (1.0 - u_filterAmount); } |
276 | void applyInvertFilter(inout vec4 color) |
277 | { |
278 | color = vec4(invert(color.r), invert(color.g), invert(color.b), color.a); |
279 | } |
280 | |
281 | void applyBrightnessFilter(inout vec4 color) |
282 | { |
283 | color = vec4(color.rgb * u_filterAmount, color.a); |
284 | } |
285 | |
286 | float contrast(float n) { return (n - 0.5) * u_filterAmount + 0.5; } |
287 | void applyContrastFilter(inout vec4 color) |
288 | { |
289 | color = vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a); |
290 | } |
291 | |
292 | void applyOpacityFilter(inout vec4 color) |
293 | { |
294 | color = vec4(color.r, color.g, color.b, color.a * u_filterAmount); |
295 | } |
296 | |
297 | vec4 sampleColorAtRadius(float radius, vec2 texCoord) |
298 | { |
299 | vec2 coord = texCoord + radius * u_blurRadius; |
300 | return SamplerFunction(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); |
301 | } |
302 | |
303 | float sampleAlphaAtRadius(float radius, vec2 texCoord) |
304 | { |
305 | vec2 coord = texCoord - u_shadowOffset + radius * u_blurRadius; |
306 | return SamplerFunction(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); |
307 | } |
308 | |
309 | void applyBlurFilter(inout vec4 color, vec2 texCoord) |
310 | { |
311 | vec4 total = sampleColorAtRadius(0., texCoord) * u_gaussianKernel[0]; |
312 | for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { |
313 | total += sampleColorAtRadius(float(i) * GAUSSIAN_KERNEL_STEP, texCoord) * u_gaussianKernel[i]; |
314 | total += sampleColorAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP, texCoord) * u_gaussianKernel[i]; |
315 | } |
316 | |
317 | color = total; |
318 | } |
319 | |
320 | void applyAlphaBlur(inout vec4 color, vec2 texCoord) |
321 | { |
322 | float total = sampleAlphaAtRadius(0., texCoord) * u_gaussianKernel[0]; |
323 | for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { |
324 | total += sampleAlphaAtRadius(float(i) * GAUSSIAN_KERNEL_STEP, texCoord) * u_gaussianKernel[i]; |
325 | total += sampleAlphaAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP, texCoord) * u_gaussianKernel[i]; |
326 | } |
327 | |
328 | color *= total; |
329 | } |
330 | |
331 | vec4 sourceOver(vec4 src, vec4 dst) { return src + dst * (1. - dst.a); } |
332 | |
333 | void applyContentTexture(inout vec4 color, vec2 texCoord) |
334 | { |
335 | vec4 contentColor = texture2D(s_contentTexture, texCoord); |
336 | color = sourceOver(contentColor, color); |
337 | } |
338 | |
339 | void applySolidColor(inout vec4 color) { color *= u_color; } |
340 | |
341 | void main(void) |
342 | { |
343 | vec4 color = vec4(1., 1., 1., 1.); |
344 | vec2 texCoord = transformTexCoord(); |
345 | applyManualRepeatIfNeeded(texCoord); |
346 | applyTextureIfNeeded(color, texCoord); |
347 | applySolidColorIfNeeded(color); |
348 | applyAntialiasingIfNeeded(color); |
349 | applyOpacityIfNeeded(color); |
350 | applyGrayscaleFilterIfNeeded(color); |
351 | applySepiaFilterIfNeeded(color); |
352 | applySaturateFilterIfNeeded(color); |
353 | applyHueRotateFilterIfNeeded(color); |
354 | applyInvertFilterIfNeeded(color); |
355 | applyBrightnessFilterIfNeeded(color); |
356 | applyContrastFilterIfNeeded(color); |
357 | applyOpacityFilterIfNeeded(color); |
358 | applyBlurFilterIfNeeded(color, texCoord); |
359 | applyAlphaBlurIfNeeded(color, texCoord); |
360 | applyContentTextureIfNeeded(color, texCoord); |
361 | gl_FragColor = color; |
362 | } |
363 | ); |
364 | |
365 | Ref<TextureMapperShaderProgram> TextureMapperShaderProgram::create(TextureMapperShaderProgram::Options options) |
366 | { |
367 | #define SET_APPLIER_FROM_OPTIONS(Applier) \ |
368 | optionsApplierBuilder.append(\ |
369 | (options & TextureMapperShaderProgram::Applier) ? ENABLE_APPLIER(Applier) : DISABLE_APPLIER(Applier)) |
370 | |
371 | StringBuilder optionsApplierBuilder; |
372 | SET_APPLIER_FROM_OPTIONS(Texture); |
373 | SET_APPLIER_FROM_OPTIONS(Rect); |
374 | SET_APPLIER_FROM_OPTIONS(SolidColor); |
375 | SET_APPLIER_FROM_OPTIONS(Opacity); |
376 | SET_APPLIER_FROM_OPTIONS(Antialiasing); |
377 | SET_APPLIER_FROM_OPTIONS(GrayscaleFilter); |
378 | SET_APPLIER_FROM_OPTIONS(SepiaFilter); |
379 | SET_APPLIER_FROM_OPTIONS(SaturateFilter); |
380 | SET_APPLIER_FROM_OPTIONS(HueRotateFilter); |
381 | SET_APPLIER_FROM_OPTIONS(BrightnessFilter); |
382 | SET_APPLIER_FROM_OPTIONS(ContrastFilter); |
383 | SET_APPLIER_FROM_OPTIONS(InvertFilter); |
384 | SET_APPLIER_FROM_OPTIONS(OpacityFilter); |
385 | SET_APPLIER_FROM_OPTIONS(BlurFilter); |
386 | SET_APPLIER_FROM_OPTIONS(AlphaBlur); |
387 | SET_APPLIER_FROM_OPTIONS(ContentTexture); |
388 | SET_APPLIER_FROM_OPTIONS(ManualRepeat); |
389 | |
390 | StringBuilder vertexShaderBuilder; |
391 | |
392 | // OpenGL >= 3.2 requires a #version directive at the beginning of the code. |
393 | #if !USE(OPENGL_ES) |
394 | unsigned glVersion = GLContext::current()->version(); |
395 | if (glVersion >= 320) |
396 | vertexShaderBuilder.append(GLSL_DIRECTIVE(version 150)); |
397 | #endif |
398 | |
399 | // Append the options. |
400 | vertexShaderBuilder.append(optionsApplierBuilder.toString()); |
401 | |
402 | // Append the appropriate input/output variable definitions. |
403 | #if USE(OPENGL_ES) |
404 | vertexShaderBuilder.append(vertexTemplateLT320Vars); |
405 | #else |
406 | if (glVersion >= 320) |
407 | vertexShaderBuilder.append(vertexTemplateGE320Vars); |
408 | else |
409 | vertexShaderBuilder.append(vertexTemplateLT320Vars); |
410 | #endif |
411 | |
412 | // Append the common code. |
413 | vertexShaderBuilder.append(vertexTemplateCommon); |
414 | |
415 | StringBuilder fragmentShaderBuilder; |
416 | |
417 | // OpenGL >= 3.2 requires a #version directive at the beginning of the code. |
418 | #if !USE(OPENGL_ES) |
419 | if (glVersion >= 320) |
420 | fragmentShaderBuilder.append(GLSL_DIRECTIVE(version 150)); |
421 | #endif |
422 | |
423 | // Append the options. |
424 | fragmentShaderBuilder.append(optionsApplierBuilder.toString()); |
425 | |
426 | // Append the common header. |
427 | fragmentShaderBuilder.append(fragmentTemplateHeaderCommon); |
428 | |
429 | // Append the appropriate input/output variable definitions. |
430 | #if USE(OPENGL_ES) |
431 | fragmentShaderBuilder.append(fragmentTemplateLT320Vars); |
432 | #else |
433 | if (glVersion >= 320) |
434 | fragmentShaderBuilder.append(fragmentTemplateGE320Vars); |
435 | else |
436 | fragmentShaderBuilder.append(fragmentTemplateLT320Vars); |
437 | #endif |
438 | |
439 | // Append the common code. |
440 | fragmentShaderBuilder.append(fragmentTemplateCommon); |
441 | |
442 | return adoptRef(*new TextureMapperShaderProgram(vertexShaderBuilder.toString(), fragmentShaderBuilder.toString())); |
443 | } |
444 | |
445 | #if !LOG_DISABLED |
446 | static CString getShaderLog(GLuint shader) |
447 | { |
448 | GLint logLength = 0; |
449 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &logLength); |
450 | if (!logLength) |
451 | return { }; |
452 | |
453 | Vector<GLchar> info(logLength); |
454 | GLsizei infoLength = 0; |
455 | glGetShaderInfoLog(shader, logLength, &infoLength, info.data()); |
456 | |
457 | size_t stringLength = std::max(infoLength, 0); |
458 | return { info.data(), stringLength }; |
459 | } |
460 | |
461 | static CString getProgramLog(GLuint program) |
462 | { |
463 | GLint logLength = 0; |
464 | glGetProgramiv(program, GL_INFO_LOG_LENGTH, &logLength); |
465 | if (!logLength) |
466 | return { }; |
467 | |
468 | Vector<GLchar> info(logLength); |
469 | GLsizei infoLength = 0; |
470 | glGetProgramInfoLog(program, logLength, &infoLength, info.data()); |
471 | |
472 | size_t stringLength = std::max(infoLength, 0); |
473 | return { info.data(), stringLength }; |
474 | } |
475 | #endif |
476 | |
477 | TextureMapperShaderProgram::TextureMapperShaderProgram(const String& vertex, const String& fragment) |
478 | { |
479 | m_vertexShader = glCreateShader(GL_VERTEX_SHADER); |
480 | { |
481 | CString vertexCString = vertex.utf8(); |
482 | const char* data = vertexCString.data(); |
483 | int length = vertexCString.length(); |
484 | glShaderSource(m_vertexShader, 1, &data, &length); |
485 | } |
486 | glCompileShader(m_vertexShader); |
487 | |
488 | m_fragmentShader = glCreateShader(GL_FRAGMENT_SHADER); |
489 | { |
490 | CString fragmentCString = fragment.utf8(); |
491 | const char* data = fragmentCString.data(); |
492 | int length = fragmentCString.length(); |
493 | glShaderSource(m_fragmentShader, 1, &data, &length); |
494 | } |
495 | glCompileShader(m_fragmentShader); |
496 | |
497 | m_id = glCreateProgram(); |
498 | glAttachShader(m_id, m_vertexShader); |
499 | glAttachShader(m_id, m_fragmentShader); |
500 | glLinkProgram(m_id); |
501 | |
502 | if (!compositingLogEnabled() || glGetError() == GL_NO_ERROR) |
503 | return; |
504 | |
505 | LOG(Compositing, "Vertex shader log: %s\n" , getShaderLog(m_vertexShader).data()); |
506 | LOG(Compositing, "Fragment shader log: %s\n" , getShaderLog(m_fragmentShader).data()); |
507 | LOG(Compositing, "Program log: %s\n" , getProgramLog(m_id).data()); |
508 | } |
509 | |
510 | TextureMapperShaderProgram::~TextureMapperShaderProgram() |
511 | { |
512 | if (!m_id) |
513 | return; |
514 | |
515 | glDetachShader(m_id, m_vertexShader); |
516 | glDeleteShader(m_vertexShader); |
517 | glDetachShader(m_id, m_fragmentShader); |
518 | glDeleteShader(m_fragmentShader); |
519 | glDeleteProgram(m_id); |
520 | } |
521 | |
522 | void TextureMapperShaderProgram::setMatrix(GLuint location, const TransformationMatrix& matrix) |
523 | { |
524 | auto floatMatrix = matrix.toColumnMajorFloatArray(); |
525 | glUniformMatrix4fv(location, 1, false, floatMatrix.data()); |
526 | } |
527 | |
528 | GLuint TextureMapperShaderProgram::getLocation(const AtomicString& name, VariableType type) |
529 | { |
530 | auto addResult = m_variables.ensure(name, |
531 | [this, &name, type] { |
532 | CString nameCString = name.string().utf8(); |
533 | switch (type) { |
534 | case UniformVariable: |
535 | return glGetUniformLocation(m_id, nameCString.data()); |
536 | case AttribVariable: |
537 | return glGetAttribLocation(m_id, nameCString.data()); |
538 | } |
539 | ASSERT_NOT_REACHED(); |
540 | return 0; |
541 | }); |
542 | return addResult.iterator->value; |
543 | } |
544 | |
545 | } // namespace WebCore |
546 | |
547 | #endif // USE(TEXTURE_MAPPER_GL) |
548 | |