Changeset 138489 in webkit
- Timestamp:
- Dec 26, 2012 6:29:21 PM (11 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r138487 r138489 1 2012-12-26 No'am Rosenthal <noam@webkit.org> 2 3 [Texmap] Instead of having multiple shaders sources with lots of duplication, we should have one shader source with MACRO variants 4 https://bugs.webkit.org/show_bug.cgi?id=104815 5 6 Reviewed by Kenneth Rohde Christiansen. 7 8 Created templates for the vertex and fragment shaders, and added some MACROs in 9 TextureMapperShaderManager to allow GLSL precompiler-based configuration. 10 11 The template follows a pattern where the main function in the shader calls 12 applyFooBarIfNeeded(), while applyFooBar() is implemented. The Macros prepended to the template define whether applyIfNeeded resolves to the real function or to a noop. 13 14 In addition, made some small changes to the filter shaders so that they can use the same code as the normal shaders. 15 16 Covered by existing pixel/ref tests when run on Qt/EFL/GTK. 17 18 * platform/graphics/texmap/TextureMapperGL.cpp: 19 (WebCore::TextureMapperGL::drawTexture): 20 (WebCore::TextureMapperGL::drawSolidColor): 21 (WebCore::TextureMapperGL::drawTextureWithAntialiasing): 22 (WebCore::optionsForFilterType): 23 (WebCore): 24 (WebCore::getPassesRequiredForFilter): 25 (WebCore::prepareFilterProgram): 26 (WebCore::TextureMapperGL::drawFiltered): 27 (WebCore::BitmapTextureGL::applyFilters): 28 Always draw using the drawQuad function, and use the new TextureMapperShaderManager::Options mask instead of the old ShaderKey. 29 30 * platform/graphics/texmap/TextureMapperShaderManager.cpp: 31 (WebCore): 32 (WebCore::getShaderSpec): 33 (WebCore::TextureMapperShaderManager::getShaderProgram): 34 * platform/graphics/texmap/TextureMapperShaderManager.h: 35 (TextureMapperShaderProgram): 36 (TextureMapperShaderManager): 37 1 38 2012-12-26 Huang Dongsung <luxtella@company100.net> 2 39 -
trunk/Source/WebCore/platform/graphics/texmap/TextureMapperGL.cpp
r138168 r138489 85 85 return adoptRef(new SharedGLData(context)); 86 86 } 87 88 89 87 90 88 TextureMapperShaderManager textureMapperShaderManager; … … 414 412 return; 415 413 416 TextureMapperShaderManager:: ShaderKey key = TextureMapperShaderManager::Default;417 if (masked && useRect)418 key = TextureMapperShaderManager::MaskedRect;419 else if (masked)420 key = TextureMapperShaderManager::Masked;421 else if (useRect)422 key = TextureMapperShaderManager::Rect;414 TextureMapperShaderManager::Options options = TextureMapperShaderManager::Texture; 415 if (masked) 416 options |= TextureMapperShaderManager::Mask; 417 if (flags & ShouldUseARBTextureRect) 418 options |= TextureMapperShaderManager::Rect; 419 if (opacity < 1) 420 options |= TextureMapperShaderManager::Opacity; 423 421 424 422 RefPtr<TextureMapperShaderProgram> program; 425 program = data().sharedGLData().textureMapperShaderManager.getShaderProgram( key);423 program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(options); 426 424 m_context3D->useProgram(program->programID()); 427 425 … … 563 561 quadToEdgeArray(expandedQuadInScreenSpace, targetQuadEdges); 564 562 quadToEdgeArray(inflateQuad(quadInScreenSpace.boundingBox(), inflationDistance), targetQuadEdges + 12); 565 566 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::Antialiased); 563 TextureMapperShaderManager::Options options = TextureMapperShaderManager::Antialias | TextureMapperShaderManager::Texture; 564 if (opacity < 1) 565 options |= TextureMapperShaderManager::Opacity; 566 567 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(options); 567 568 m_context3D->useProgram(program->programID()); 568 569 m_context3D->uniform3fv(program->expandedQuadEdgesInScreenSpaceLocation(), 8, targetQuadEdges); … … 757 758 #if ENABLE(CSS_FILTERS) 758 759 759 static TextureMapperShaderManager:: ShaderKey keyForFilterType(FilterOperation::OperationType type, unsigned pass)760 static TextureMapperShaderManager::Options optionsForFilterType(FilterOperation::OperationType type, unsigned pass) 760 761 { 761 762 switch (type) { 762 763 case FilterOperation::GRAYSCALE: 763 return TextureMapperShaderManager:: GrayscaleFilter;764 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::GrayscaleFilter; 764 765 case FilterOperation::SEPIA: 765 return TextureMapperShaderManager:: SepiaFilter;766 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::SepiaFilter; 766 767 case FilterOperation::SATURATE: 767 return TextureMapperShaderManager:: SaturateFilter;768 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::SaturateFilter; 768 769 case FilterOperation::HUE_ROTATE: 769 return TextureMapperShaderManager:: HueRotateFilter;770 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::HueRotateFilter; 770 771 case FilterOperation::INVERT: 771 return TextureMapperShaderManager:: InvertFilter;772 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::InvertFilter; 772 773 case FilterOperation::BRIGHTNESS: 773 return TextureMapperShaderManager:: BrightnessFilter;774 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::BrightnessFilter; 774 775 case FilterOperation::CONTRAST: 775 return TextureMapperShaderManager:: ContrastFilter;776 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::ContrastFilter; 776 777 case FilterOperation::OPACITY: 777 return TextureMapperShaderManager:: OpacityFilter;778 return TextureMapperShaderManager::Texture | TextureMapperShaderManager::OpacityFilter; 778 779 case FilterOperation::BLUR: 779 780 return TextureMapperShaderManager::BlurFilter; 780 781 case FilterOperation::DROP_SHADOW: 781 return pass ? TextureMapperShaderManager::ShadowFilterPass2 : TextureMapperShaderManager::ShadowFilterPass1; 782 return TextureMapperShaderManager::AlphaBlur 783 | (pass ? TextureMapperShaderManager::ContentTexture | TextureMapperShaderManager::SolidColor: 0); 782 784 default: 783 785 ASSERT_NOT_REACHED(); 784 return TextureMapperShaderManager::Invalid;786 return 0; 785 787 } 786 788 } … … 853 855 case FilterOperation::SATURATE: 854 856 case FilterOperation::HUE_ROTATE: 855 context->uniform1f(program-> amountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount());857 context->uniform1f(program->filterAmountLocation(), static_cast<const BasicColorMatrixFilterOperation&>(operation).amount()); 856 858 break; 857 859 case FilterOperation::INVERT: … … 859 861 case FilterOperation::CONTRAST: 860 862 case FilterOperation::OPACITY: 861 context->uniform1f(program-> amountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount());863 context->uniform1f(program->filterAmountLocation(), static_cast<const BasicComponentTransferFilterOperation&>(operation).amount()); 862 864 break; 863 865 case FilterOperation::BLUR: { … … 880 882 switch (pass) { 881 883 case 0: 882 // First pass: vertical alpha blur. 884 // First pass: horizontal alpha blur. 885 context->uniform2f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()), 0); 883 886 context->uniform2f(program->shadowOffsetLocation(), float(shadow.location().x()) / float(size.width()), float(shadow.location().y()) / float(size.height())); 884 context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.width()));885 887 break; 886 888 case 1: 887 889 // Second pass: we need the shadow color and the content texture for compositing. 888 context->uniform1f(program->blurRadiusLocation(), shadow.stdDeviation() / float(size.height())); 890 float r, g, b, a; 891 shadow.color().getRGBA(r, g, b, a); 892 context->uniform4f(program->colorLocation(), r, g, b, a); 893 context->uniform2f(program->blurRadiusLocation(), 0, shadow.stdDeviation() / float(size.height())); 894 context->uniform2f(program->shadowOffsetLocation(), 0, 0); 889 895 context->activeTexture(GraphicsContext3D::TEXTURE1); 890 896 context->bindTexture(GraphicsContext3D::TEXTURE_2D, contentTexture); 891 897 context->uniform1i(program->contentTextureLocation(), 1); 892 float r, g, b, a;893 shadow.color().getRGBA(r, g, b, a);894 context->uniform4f(program->shadowColorLocation(), r, g, b, a);895 898 break; 896 899 } … … 961 964 { 962 965 // For standard filters, we always draw the whole texture without transformations. 963 TextureMapperShaderManager:: ShaderKey key = keyForFilterType(filter.getOperationType(), pass);964 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram( key);966 TextureMapperShaderManager::Options options = optionsForFilterType(filter.getOperationType(), pass); 967 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(options); 965 968 ASSERT(program); 966 969 967 970 prepareFilterProgram(program.get(), filter, pass, sampler.contentSize(), static_cast<const BitmapTextureGL&>(contentTexture).id()); 968 969 m_context3D->enableVertexAttribArray(program->vertexLocation()); 970 m_context3D->enableVertexAttribArray(program->texCoordLocation()); 971 m_context3D->activeTexture(GraphicsContext3D::TEXTURE0); 972 m_context3D->bindTexture(GraphicsContext3D::TEXTURE_2D, static_cast<const BitmapTextureGL&>(sampler).id()); 973 m_context3D->uniform1i(program->samplerLocation(), 0); 974 const GC3Dfloat targetVertices[] = {-1, -1, 1, -1, 1, 1, -1, 1}; 975 const GC3Dfloat sourceVertices[] = {0, 0, 1, 0, 1, 1, 0, 1}; 976 m_context3D->vertexAttribPointer(program->vertexLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(targetVertices)); 977 m_context3D->vertexAttribPointer(program->texCoordLocation(), 2, GraphicsContext3D::FLOAT, false, 0, GC3Dintptr(sourceVertices)); 978 m_context3D->disable(GraphicsContext3D::BLEND); 979 m_context3D->drawArrays(GraphicsContext3D::TRIANGLE_FAN, 0, 4); 980 m_context3D->disableVertexAttribArray(program->vertexLocation()); 981 m_context3D->disableVertexAttribArray(program->texCoordLocation()); 971 FloatRect targetRect(IntPoint::zero(), sampler.contentSize()); 972 drawTexturedQuadWithProgram(program.get(), static_cast<const BitmapTextureGL&>(sampler).id(), 0, IntSize(1, 1), targetRect, TransformationMatrix(), 1, 0); 982 973 } 983 974 … … 1173 1164 data().initializeStencil(); 1174 1165 1175 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager:: Default);1166 RefPtr<TextureMapperShaderProgram> program = data().sharedGLData().textureMapperShaderManager.getShaderProgram(TextureMapperShaderManager::SolidColor); 1176 1167 1177 1168 m_context3D->useProgram(program->programID()); -
trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.cpp
r138168 r138489 24 24 25 25 #if USE(ACCELERATED_COMPOSITING) && USE(TEXTURE_MAPPER) 26 27 26 #include "LengthFunctions.h" 28 27 #include "Logging.h" 29 28 #include "TextureMapperGL.h" 30 29 30 #include <wtf/text/StringBuilder.h> 31 31 32 #define STRINGIFY(...) #__VA_ARGS__ 32 33 33 34 namespace WebCore { 34 35 35 36 36 static inline bool compositingLogEnabled() … … 107 107 } 108 108 109 struct ShaderSpec { 109 static const char* vertexShaderSource = 110 STRINGIFY( 111 uniform mat4 u_matrix; 112 uniform float u_flip; 113 uniform vec2 u_textureSize; 114 attribute vec4 a_vertex; 115 varying vec2 v_texCoord; 116 varying vec2 v_maskTexCoord; 117 118 void main(void) 119 { 120 vec4 position = a_vertex; 121 v_texCoord = vec2(position.x, mix(position.y, 1. - position.y, u_flip)) * u_textureSize; 122 v_maskTexCoord = vec2(position); 123 gl_Position = u_matrix * a_vertex; 124 } 125 ); 126 127 #define GLSL_DIRECTIVE(...) "#"#__VA_ARGS__"\n" 128 #define DEFINE_APPLIER(Name) \ 129 "#ifdef ENABLE_"#Name"\n" \ 130 "#define apply"#Name"IfNeeded apply"#Name"\n"\ 131 "#else\n"\ 132 "#define apply"#Name"IfNeeded noop\n"\ 133 "#endif\n" 134 135 #define RECT_TEXTURE_DIRECTIVE \ 136 GLSL_DIRECTIVE(ifdef ENABLE_Rect) \ 137 GLSL_DIRECTIVE(define SamplerType sampler2DRect) \ 138 GLSL_DIRECTIVE(define SamplerFunction texture2DRect) \ 139 GLSL_DIRECTIVE(else) \ 140 GLSL_DIRECTIVE(define SamplerType sampler2D) \ 141 GLSL_DIRECTIVE(define SamplerFunction texture2D) \ 142 GLSL_DIRECTIVE(endif) 143 144 #define ENABLE_APPLIER(Name) "#define ENABLE_"#Name"\n" 145 #define BLUR_CONSTANTS \ 146 GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_HALF_WIDTH 11) \ 147 GLSL_DIRECTIVE(define GAUSSIAN_KERNEL_STEP 0.2) 148 149 150 static const char* fragmentTemplate = 151 DEFINE_APPLIER(Texture) 152 DEFINE_APPLIER(SolidColor) 153 DEFINE_APPLIER(Opacity) 154 DEFINE_APPLIER(Mask) 155 DEFINE_APPLIER(Antialias) 156 DEFINE_APPLIER(GrayscaleFilter) 157 DEFINE_APPLIER(SepiaFilter) 158 DEFINE_APPLIER(SaturateFilter) 159 DEFINE_APPLIER(HueRotateFilter) 160 DEFINE_APPLIER(InvertFilter) 161 DEFINE_APPLIER(BrightnessFilter) 162 DEFINE_APPLIER(ContrastFilter) 163 DEFINE_APPLIER(OpacityFilter) 164 DEFINE_APPLIER(BlurFilter) 165 DEFINE_APPLIER(AlphaBlur) 166 DEFINE_APPLIER(ContentTexture) 167 RECT_TEXTURE_DIRECTIVE 168 BLUR_CONSTANTS 169 STRINGIFY( 170 precision mediump float; 171 uniform SamplerType s_sampler; 172 uniform sampler2D s_mask; 173 uniform sampler2D s_contentTexture; 174 uniform float u_opacity; 175 varying vec2 v_texCoord; 176 varying vec2 v_maskTexCoord; 177 uniform vec3 u_expandedQuadEdgesInScreenSpace[8]; 178 uniform float u_filterAmount; 179 uniform vec2 u_blurRadius; 180 uniform vec2 u_shadowOffset; 181 uniform vec4 u_color; 182 uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH]; 183 184 void noop(inout vec4 dummyParameter) { } 185 186 // The data passed in u_expandedQuadEdgesInScreenSpace is merely the 187 // pre-scaled coeffecients of the line equations describing the four edges 188 // of the expanded quad in screen space and the rectangular bounding box 189 // of the expanded quad. 190 // 191 float normalizedDistance(vec3 edgeCoefficient) 192 { 193 // We are doing a simple distance calculation here according to the formula: 194 // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p 195 // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2). 196 return clamp(dot(edgeCoefficient, vec3(gl_FragCoord.xy, 1.)), 0., 1.); 197 } 198 199 float antialiasQuad(vec3 coefficient1, vec3 coefficient2, vec3 coefficient3, vec3 coefficient4) 200 { 201 // Now we want to reduce the alpha value of the fragment if it is close to the 202 // edges of the expanded quad (or rectangular bounding box -- which seems to be 203 // important for backfacing quads). Note that we are combining the contribution 204 // from the (top || bottom) and (left || right) edge by simply multiplying. This follows 205 // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html, 206 // in this case without using Gaussian weights. 207 return min(normalizedDistance(coefficient1), normalizedDistance(coefficient2)) 208 * min(normalizedDistance(coefficient3), normalizedDistance(coefficient4)); 209 } 210 211 float antialias() 212 { 213 float antialiasValueForQuad = 214 antialiasQuad(u_expandedQuadEdgesInScreenSpace[0], 215 u_expandedQuadEdgesInScreenSpace[1], 216 u_expandedQuadEdgesInScreenSpace[2], 217 u_expandedQuadEdgesInScreenSpace[3]); 218 219 float antialiasValueForBoundingRect = 220 antialiasQuad(u_expandedQuadEdgesInScreenSpace[4], 221 u_expandedQuadEdgesInScreenSpace[5], 222 u_expandedQuadEdgesInScreenSpace[6], 223 u_expandedQuadEdgesInScreenSpace[7]); 224 225 return min(antialiasValueForQuad, antialiasValueForBoundingRect); 226 } 227 228 void applyTexture(inout vec4 color) { color = SamplerFunction(s_sampler, v_texCoord); } 229 void applyOpacity(inout vec4 color) { color *= u_opacity; } 230 void applyAntialias(inout vec4 color) { color *= antialias(); } 231 void applyMask(inout vec4 color) { color *= texture2D(s_mask, v_maskTexCoord).a; } 232 233 void applyGrayscaleFilter(inout vec4 color) 234 { 235 float amount = 1.0 - u_filterAmount; 236 color = vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b, 237 (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b, 238 (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b, 239 color.a); 240 } 241 242 void applySepiaFilter(inout vec4 color) 243 { 244 float amount = 1.0 - u_filterAmount; 245 color = vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b, 246 (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b, 247 (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b, 248 color.a); 249 } 250 251 void applySaturateFilter(inout vec4 color) 252 { 253 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, 254 (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 + 0.285 * u_filterAmount) * color.g + (0.072 - 0.072 * u_filterAmount) * color.b, 255 (0.213 - 0.213 * u_filterAmount) * color.r + (0.715 - 0.715 * u_filterAmount) * color.g + (0.072 + 0.928 * u_filterAmount) * color.b, 256 color.a); 257 } 258 259 void applyHueRotateFilter(inout vec4 color) 260 { 261 float pi = 3.14159265358979323846; 262 float c = cos(u_filterAmount * pi / 180.0); 263 float s = sin(u_filterAmount * pi / 180.0); 264 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), 265 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), 266 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), 267 color.a); 268 } 269 270 float invert(float n) { return (1.0 - n) * u_filterAmount + n * (1.0 - u_filterAmount); } 271 void applyInvertFilter(inout vec4 color) 272 { 273 color = vec4(invert(color.r), invert(color.g), invert(color.b), color.a); 274 } 275 276 void applyBrightnessFilter(inout vec4 color) 277 { 278 color = vec4(color.rgb * (1.0 + u_filterAmount), color.a); 279 } 280 281 float contrast(float n) { return (n - 0.5) * u_filterAmount + 0.5; } 282 void applyContrastFilter(inout vec4 color) 283 { 284 color = vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a); 285 } 286 287 void applyOpacityFilter(inout vec4 color) 288 { 289 color = vec4(color.r, color.g, color.b, color.a * u_filterAmount); 290 } 291 292 vec4 sampleColorAtRadius(float radius) 293 { 294 vec2 coord = v_texCoord + radius * u_blurRadius; 295 return SamplerFunction(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); 296 } 297 298 float sampleAlphaAtRadius(float radius) 299 { 300 vec2 coord = v_texCoord - u_shadowOffset + radius * u_blurRadius; 301 return SamplerFunction(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.); 302 } 303 304 void applyBlurFilter(inout vec4 color) 305 { 306 vec4 total = sampleColorAtRadius(0.) * u_gaussianKernel[0]; 307 for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { 308 total += sampleColorAtRadius(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; 309 total += sampleColorAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; 310 } 311 312 color = total; 313 } 314 315 void applyAlphaBlur(inout vec4 color) 316 { 317 float total = sampleAlphaAtRadius(0.) * u_gaussianKernel[0]; 318 for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) { 319 total += sampleAlphaAtRadius(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; 320 total += sampleAlphaAtRadius(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i]; 321 } 322 323 color *= total; 324 } 325 326 vec4 sourceOver(vec4 src, vec4 dst) { return src + dst * (1. - dst.a); } 327 328 void applyContentTexture(inout vec4 color) 329 { 330 vec4 contentColor = texture2D(s_contentTexture, v_texCoord); 331 color = sourceOver(contentColor, color); 332 } 333 334 void applySolidColor(inout vec4 color) 335 { 336 color *= u_color; 337 } 338 339 void main(void) 340 { 341 vec4 color = vec4(1., 1., 1., 1.); 342 applyTextureIfNeeded(color); 343 applySolidColorIfNeeded(color); 344 applyAntialiasIfNeeded(color); 345 applyMaskIfNeeded(color); 346 applyOpacityIfNeeded(color); 347 applyGrayscaleFilterIfNeeded(color); 348 applySepiaFilterIfNeeded(color); 349 applySaturateFilterIfNeeded(color); 350 applyHueRotateFilterIfNeeded(color); 351 applyInvertFilterIfNeeded(color); 352 applyBrightnessFilterIfNeeded(color); 353 applyContrastFilterIfNeeded(color); 354 applyOpacityFilterIfNeeded(color); 355 applyBlurFilterIfNeeded(color); 356 applyAlphaBlurIfNeeded(color); 357 applyContentTextureIfNeeded(color); 358 gl_FragColor = color; 359 } 360 ); 361 362 363 static void getShaderSpec(TextureMapperShaderManager::Options options, String& vertexSource, String& fragmentSource) 364 { 365 StringBuilder fragmentBuilder; 366 #define SET_APPLIER_FROM_OPTIONS(Applier) \ 367 if (options & TextureMapperShaderManager::Applier) \ 368 fragmentBuilder.append(ENABLE_APPLIER(Applier)); 369 370 SET_APPLIER_FROM_OPTIONS(Texture) 371 SET_APPLIER_FROM_OPTIONS(Rect) 372 SET_APPLIER_FROM_OPTIONS(SolidColor) 373 SET_APPLIER_FROM_OPTIONS(Opacity) 374 SET_APPLIER_FROM_OPTIONS(Mask) 375 SET_APPLIER_FROM_OPTIONS(Antialias) 376 SET_APPLIER_FROM_OPTIONS(GrayscaleFilter) 377 SET_APPLIER_FROM_OPTIONS(SepiaFilter) 378 SET_APPLIER_FROM_OPTIONS(SaturateFilter) 379 SET_APPLIER_FROM_OPTIONS(HueRotateFilter) 380 SET_APPLIER_FROM_OPTIONS(BrightnessFilter) 381 SET_APPLIER_FROM_OPTIONS(ContrastFilter) 382 SET_APPLIER_FROM_OPTIONS(InvertFilter) 383 SET_APPLIER_FROM_OPTIONS(OpacityFilter) 384 SET_APPLIER_FROM_OPTIONS(BlurFilter) 385 SET_APPLIER_FROM_OPTIONS(AlphaBlur) 386 SET_APPLIER_FROM_OPTIONS(ContentTexture) 387 388 fragmentBuilder.append(fragmentTemplate); 389 vertexSource = vertexShaderSource; 390 fragmentSource = fragmentBuilder.toString(); 391 } 392 393 TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context) 394 : m_context(context) 395 { 396 } 397 398 TextureMapperShaderManager::~TextureMapperShaderManager() 399 { 400 } 401 402 PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(Options options) 403 { 404 TextureMapperShaderProgramMap::iterator it = m_programs.find(options); 405 if (it != m_programs.end()) 406 return it->value; 407 110 408 String vertexShader; 111 409 String fragmentShader; 112 ShaderSpec(const char* vertex = 0, const char* fragment = 0)113 : vertexShader(vertex ? String(ASCIILiteral(vertex)) : String())114 , fragmentShader(fragment ? String(ASCIILiteral(fragment)) : String())115 {116 410 getShaderSpec(options, vertexShader, fragmentShader); 411 RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader); 412 m_programs.add(options, program); 413 return program; 414 } 117 415 }; 118 416 119 static void getShaderSpec(TextureMapperShaderManager::ShaderKey key, String& vertexSource, String& fragmentSource)120 {121 static Vector<ShaderSpec> specs = Vector<ShaderSpec>();122 static const char* fragmentOpacityAndMask =123 STRINGIFY(124 precision mediump float;125 uniform sampler2D s_sampler;126 uniform sampler2D s_mask;127 uniform float u_opacity;128 varying vec2 v_sourceTexCoord;129 varying vec2 v_maskTexCoord;130 void main(void)131 {132 vec4 color = texture2D(s_sampler, v_sourceTexCoord);133 vec4 maskColor = texture2D(s_mask, v_maskTexCoord);134 float fragmentAlpha = u_opacity * maskColor.a;135 gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);136 }137 );138 139 static const char* fragmentRectOpacityAndMask =140 STRINGIFY(141 precision mediump float;142 uniform sampler2DRect s_sampler;143 uniform sampler2DRect s_mask;144 uniform float u_opacity;145 varying vec2 v_sourceTexCoord;146 varying vec2 v_maskTexCoord;147 void main(void)148 {149 vec4 color = texture2DRect(s_sampler, v_sourceTexCoord);150 vec4 maskColor = texture2DRect(s_mask, v_maskTexCoord);151 float fragmentAlpha = u_opacity * maskColor.a;152 gl_FragColor = vec4(color.rgb * fragmentAlpha, color.a * fragmentAlpha);153 }154 );155 156 static const char* vertexOpacityAndMask =157 STRINGIFY(158 uniform mat4 u_matrix;159 uniform float u_flip;160 uniform vec2 u_textureSize;161 attribute vec4 a_vertex;162 varying vec2 v_sourceTexCoord;163 varying vec2 v_maskTexCoord;164 void main(void)165 {166 v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)) * u_textureSize;167 v_maskTexCoord = vec2(a_vertex);168 gl_Position = u_matrix * a_vertex;169 }170 );171 172 static const char* fragmentSimple =173 STRINGIFY(174 precision mediump float;175 uniform sampler2D s_sampler;176 uniform float u_opacity;177 varying vec2 v_sourceTexCoord;178 void main(void)179 {180 vec4 color = texture2D(s_sampler, v_sourceTexCoord);181 gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);182 }183 );184 185 static const char* fragmentAntialiasingNoMask =186 STRINGIFY(187 precision mediump float;188 uniform sampler2D s_sampler;189 varying vec2 v_sourceTexCoord;190 uniform float u_opacity;191 uniform vec3 u_expandedQuadEdgesInScreenSpace[8];192 193 // The data passed in u_expandedQuadEdgesInScreenSpace is merely the194 // pre-scaled coeffecients of the line equations describing the four edges195 // of the expanded quad in screen space and the rectangular bounding box196 // of the expanded quad.197 //198 float normalizedDistance(vec3 edgeCoefficient)199 {200 // We are doing a simple distance calculation here according to the formula:201 // (A*p.x + B*p.y + C) / sqrt(A^2 + B^2) = distance from line to p202 // Note that A, B and C have already been scaled by 1 / sqrt(A^2 + B^2).203 return clamp(dot(edgeCoefficient, vec3(gl_FragCoord.xy, 1.)), 0., 1.);204 }205 206 float antialiasQuad(vec3 coefficient1, vec3 coefficient2, vec3 coefficient3, vec3 coefficient4)207 {208 // Now we want to reduce the alpha value of the fragment if it is close to the209 // edges of the expanded quad (or rectangular bounding box -- which seems to be210 // important for backfacing quads). Note that we are combining the contribution211 // from the (top || bottom) and (left || right) edge by simply multiplying. This follows212 // the approach described at: http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter22.html,213 // in this case without using Gaussian weights.214 return min(normalizedDistance(coefficient1), normalizedDistance(coefficient2))215 * min(normalizedDistance(coefficient3), normalizedDistance(coefficient4));216 }217 218 float antialias()219 {220 float antialiasValueForQuad =221 antialiasQuad(u_expandedQuadEdgesInScreenSpace[0],222 u_expandedQuadEdgesInScreenSpace[1],223 u_expandedQuadEdgesInScreenSpace[2],224 u_expandedQuadEdgesInScreenSpace[3]);225 226 float antialiasValueForBoundingRect =227 antialiasQuad(u_expandedQuadEdgesInScreenSpace[4],228 u_expandedQuadEdgesInScreenSpace[5],229 u_expandedQuadEdgesInScreenSpace[6],230 u_expandedQuadEdgesInScreenSpace[7]);231 232 return min(antialiasValueForQuad, antialiasValueForBoundingRect);233 }234 235 void main()236 {237 vec4 sampledColor = texture2D(s_sampler, clamp(v_sourceTexCoord, 0.0, 1.0));238 gl_FragColor = sampledColor * u_opacity * antialias();239 }240 );241 242 static const char* fragmentRectSimple =243 STRINGIFY(244 precision mediump float;245 uniform sampler2DRect s_sampler;246 uniform float u_opacity;247 varying vec2 v_sourceTexCoord;248 void main(void)249 {250 vec4 color = texture2DRect(s_sampler, v_sourceTexCoord);251 gl_FragColor = vec4(color.rgb * u_opacity, color.a * u_opacity);252 }253 );254 255 static const char* vertexSimple =256 STRINGIFY(257 uniform mat4 u_matrix;258 uniform float u_flip;259 uniform vec2 u_textureSize;260 attribute vec4 a_vertex;261 varying vec2 v_sourceTexCoord;262 void main(void)263 {264 v_sourceTexCoord = vec2(a_vertex.x, mix(a_vertex.y, 1. - a_vertex.y, u_flip)) * u_textureSize;265 gl_Position = u_matrix * a_vertex;266 }267 );268 269 static const char* vertexSolidColor =270 STRINGIFY(271 uniform mat4 u_matrix;272 attribute vec4 a_vertex;273 void main(void)274 {275 gl_Position = u_matrix * a_vertex;276 }277 );278 279 280 static const char* fragmentSolidColor =281 STRINGIFY(282 precision mediump float;283 uniform vec4 u_color;284 void main(void)285 {286 gl_FragColor = u_color;287 }288 );289 290 static const char* vertexFilter =291 STRINGIFY(292 attribute vec4 a_vertex;293 attribute vec4 a_texCoord;294 varying vec2 v_texCoord;295 void main(void)296 {297 v_texCoord = vec2(a_texCoord);298 gl_Position = a_vertex;299 }300 );301 302 #define STANDARD_FILTER(...) \303 "precision mediump float;\n"\304 "varying vec2 v_texCoord;\n"\305 "uniform float u_amount;\n"\306 "uniform sampler2D s_sampler;\n"#__VA_ARGS__ \307 "void main(void)\n { gl_FragColor = shade(texture2D(s_sampler, v_texCoord)); }"308 309 static const char* fragmentGrayscaleFilter =310 STANDARD_FILTER(311 vec4 shade(lowp vec4 color)312 {313 float amount = 1.0 - u_amount;314 return vec4((0.2126 + 0.7874 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,315 (0.2126 - 0.2126 * amount) * color.r + (0.7152 + 0.2848 * amount) * color.g + (0.0722 - 0.0722 * amount) * color.b,316 (0.2126 - 0.2126 * amount) * color.r + (0.7152 - 0.7152 * amount) * color.g + (0.0722 + 0.9278 * amount) * color.b,317 color.a);318 }319 );320 321 static const char* fragmentSepiaFilter =322 STANDARD_FILTER(323 vec4 shade(lowp vec4 color)324 {325 float amount = 1.0 - u_amount;326 return vec4((0.393 + 0.607 * amount) * color.r + (0.769 - 0.769 * amount) * color.g + (0.189 - 0.189 * amount) * color.b,327 (0.349 - 0.349 * amount) * color.r + (0.686 + 0.314 * amount) * color.g + (0.168 - 0.168 * amount) * color.b,328 (0.272 - 0.272 * amount) * color.r + (0.534 - 0.534 * amount) * color.g + (0.131 + 0.869 * amount) * color.b,329 color.a);330 }331 );332 333 static const char* fragmentSaturateFilter =334 STANDARD_FILTER(335 vec4 shade(lowp vec4 color)336 {337 return vec4((0.213 + 0.787 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,338 (0.213 - 0.213 * u_amount) * color.r + (0.715 + 0.285 * u_amount) * color.g + (0.072 - 0.072 * u_amount) * color.b,339 (0.213 - 0.213 * u_amount) * color.r + (0.715 - 0.715 * u_amount) * color.g + (0.072 + 0.928 * u_amount) * color.b,340 color.a);341 }342 );343 344 static const char* fragmentHueRotateFilter =345 STANDARD_FILTER(346 vec4 shade(lowp vec4 color)347 {348 float pi = 3.14159265358979323846;349 float c = cos(u_amount * pi / 180.0);350 float s = sin(u_amount * pi / 180.0);351 return 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),352 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),353 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),354 color.a);355 }356 );357 358 static const char* fragmentInvertFilter =359 STANDARD_FILTER(360 float invert(lowp float n) { return (1.0 - n) * u_amount + n * (1.0 - u_amount); }361 vec4 shade(lowp vec4 color)362 {363 return vec4(invert(color.r), invert(color.g), invert(color.b), color.a);364 }365 );366 367 static const char* fragmentBrightnessFilter =368 STANDARD_FILTER(369 vec4 shade(lowp vec4 color)370 {371 return vec4(color.rgb * (1.0 + u_amount), color.a);372 }373 );374 375 static const char* fragmentContrastFilter =376 STANDARD_FILTER(377 float contrast(lowp float n) { return (n - 0.5) * u_amount + 0.5; }378 vec4 shade(lowp vec4 color)379 {380 return vec4(contrast(color.r), contrast(color.g), contrast(color.b), color.a);381 }382 );383 384 static const char* fragmentOpacityFilter =385 STANDARD_FILTER(386 vec4 shade(lowp vec4 color)387 {388 return vec4(color.r, color.g, color.b, color.a * u_amount);389 }390 );391 392 #define BLUR_CONSTANTS "#define GAUSSIAN_KERNEL_HALF_WIDTH 11\n#define GAUSSIAN_KERNEL_STEP 0.2\n"393 394 static const char* fragmentBlurFilter =395 BLUR_CONSTANTS396 STRINGIFY(397 // Create a normal distribution of 21 values between -2 and 2.398 precision mediump float;399 varying vec2 v_texCoord;400 uniform vec2 u_blurRadius;401 uniform sampler2D s_sampler;402 uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];403 404 vec4 sampleColor(float radius)405 {406 vec2 coord = v_texCoord + radius * u_blurRadius;407 return texture2D(s_sampler, coord) * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);408 }409 410 vec4 blur()411 {412 vec4 total = sampleColor(0.) * u_gaussianKernel[0];413 for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {414 total += sampleColor(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];415 total += sampleColor(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];416 }417 418 return total;419 }420 421 void main(void)422 {423 gl_FragColor = blur();424 }425 );426 427 static const char* fragmentShadowFilter1 =428 BLUR_CONSTANTS429 STRINGIFY(430 precision mediump float;431 varying vec2 v_texCoord;432 uniform float u_blurRadius;433 uniform vec2 u_shadowOffset;434 uniform sampler2D s_sampler;435 uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];436 437 float sampleAlpha(float radius)438 {439 vec2 coord = v_texCoord - u_shadowOffset + vec2(radius * u_blurRadius, 0.);440 return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);441 }442 443 float shadowBlurHorizontal()444 {445 float total = sampleAlpha(0.) * u_gaussianKernel[0];446 for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {447 total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];448 total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];449 }450 451 return total;452 }453 454 void main(void)455 {456 gl_FragColor = vec4(1., 1., 1., 1.) * shadowBlurHorizontal();457 }458 );459 460 // Second pass: vertical alpha blur and composite with origin.461 static const char* fragmentShadowFilter2 =462 BLUR_CONSTANTS463 STRINGIFY(464 precision mediump float;465 varying vec2 v_texCoord;466 uniform float u_blurRadius;467 uniform vec4 u_shadowColor;468 uniform sampler2D s_sampler;469 uniform sampler2D s_contentTexture;470 uniform float u_gaussianKernel[GAUSSIAN_KERNEL_HALF_WIDTH];471 472 float sampleAlpha(float r)473 {474 vec2 coord = v_texCoord + vec2(0., r * u_blurRadius);475 return texture2D(s_sampler, coord).a * float(coord.x > 0. && coord.y > 0. && coord.x < 1. && coord.y < 1.);476 }477 478 float shadowBlurVertical()479 {480 float total = sampleAlpha(0.) * u_gaussianKernel[0];481 for (int i = 1; i < GAUSSIAN_KERNEL_HALF_WIDTH; i++) {482 total += sampleAlpha(float(i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];483 total += sampleAlpha(float(-1 * i) * GAUSSIAN_KERNEL_STEP) * u_gaussianKernel[i];484 }485 486 return total;487 }488 489 vec4 sourceOver(lowp vec4 source, vec4 destination)490 {491 // Composite the shadow with the original texture.492 return source + destination * (1. - source.a);493 }494 495 void main(void)496 {497 gl_FragColor = sourceOver(texture2D(s_contentTexture, v_texCoord), shadowBlurVertical() * u_shadowColor);498 }499 );500 501 if (specs.isEmpty()) {502 specs.resize(TextureMapperShaderManager::LastFilter);503 specs[TextureMapperShaderManager::Default] = ShaderSpec(vertexSimple, fragmentSimple);504 specs[TextureMapperShaderManager::SolidColor] = ShaderSpec(vertexSolidColor, fragmentSolidColor);505 specs[TextureMapperShaderManager::Rect] = ShaderSpec(vertexSimple, fragmentRectSimple);506 specs[TextureMapperShaderManager::Masked] = ShaderSpec(vertexOpacityAndMask, fragmentOpacityAndMask);507 specs[TextureMapperShaderManager::MaskedRect] = ShaderSpec(vertexOpacityAndMask, fragmentRectOpacityAndMask);508 specs[TextureMapperShaderManager::Antialiased] = ShaderSpec(vertexSimple, fragmentAntialiasingNoMask);509 specs[TextureMapperShaderManager::GrayscaleFilter] = ShaderSpec(vertexFilter, fragmentGrayscaleFilter);510 specs[TextureMapperShaderManager::SepiaFilter] = ShaderSpec(vertexFilter, fragmentSepiaFilter);511 specs[TextureMapperShaderManager::SaturateFilter] = ShaderSpec(vertexFilter, fragmentSaturateFilter);512 specs[TextureMapperShaderManager::HueRotateFilter] = ShaderSpec(vertexFilter, fragmentHueRotateFilter);513 specs[TextureMapperShaderManager::BrightnessFilter] = ShaderSpec(vertexFilter, fragmentBrightnessFilter);514 specs[TextureMapperShaderManager::ContrastFilter] = ShaderSpec(vertexFilter, fragmentContrastFilter);515 specs[TextureMapperShaderManager::InvertFilter] = ShaderSpec(vertexFilter, fragmentInvertFilter);516 specs[TextureMapperShaderManager::OpacityFilter] = ShaderSpec(vertexFilter, fragmentOpacityFilter);517 specs[TextureMapperShaderManager::BlurFilter] = ShaderSpec(vertexFilter, fragmentBlurFilter);518 specs[TextureMapperShaderManager::ShadowFilterPass1] = ShaderSpec(vertexFilter, fragmentShadowFilter1);519 specs[TextureMapperShaderManager::ShadowFilterPass2] = ShaderSpec(vertexFilter, fragmentShadowFilter2);520 }521 522 ASSERT(specs.size() > key);523 ShaderSpec& spec = specs[key];524 vertexSource = spec.vertexShader;525 fragmentSource = spec.fragmentShader;526 }527 528 TextureMapperShaderManager::TextureMapperShaderManager(GraphicsContext3D* context)529 : m_context(context)530 {531 }532 533 TextureMapperShaderManager::~TextureMapperShaderManager()534 {535 }536 537 PassRefPtr<TextureMapperShaderProgram> TextureMapperShaderManager::getShaderProgram(ShaderKey key)538 {539 TextureMapperShaderProgramMap::iterator it = m_programs.find(key);540 if (it != m_programs.end())541 return it->value;542 543 String vertexShader;544 String fragmentShader;545 getShaderSpec(key, vertexShader, fragmentShader);546 RefPtr<TextureMapperShaderProgram> program = TextureMapperShaderProgram::create(m_context, vertexShader, fragmentShader);547 m_programs.add(key, program);548 return program;549 }550 };551 552 417 #endif -
trunk/Source/WebCore/platform/graphics/texmap/TextureMapperShaderManager.h
r138168 r138489 60 60 61 61 #if ENABLE(CSS_FILTERS) 62 TEXMAP_DECLARE_UNIFORM( amount)62 TEXMAP_DECLARE_UNIFORM(filterAmount) 63 63 TEXMAP_DECLARE_UNIFORM(gaussianKernel) 64 64 TEXMAP_DECLARE_UNIFORM(blurRadius) 65 TEXMAP_DECLARE_UNIFORM(shadowColor)66 65 TEXMAP_DECLARE_UNIFORM(shadowOffset) 67 66 TEXMAP_DECLARE_SAMPLER(contentTexture) … … 83 82 class TextureMapperShaderManager { 84 83 public: 85 enum ShaderKey { 86 Invalid = 0, 87 Default, 88 Rect, 89 Masked, 90 MaskedRect, 91 SolidColor, 92 Antialiased, 93 GrayscaleFilter, 94 SepiaFilter, 95 SaturateFilter, 96 HueRotateFilter, 97 BrightnessFilter, 98 ContrastFilter, 99 OpacityFilter, 100 InvertFilter, 101 BlurFilter, 102 ShadowFilterPass1, 103 ShadowFilterPass2, 104 LastFilter 84 enum Option { 85 Texture = 1L << 0, 86 Rect = 1L << 1, 87 SolidColor = 1L << 2, 88 Opacity = 1L << 3, 89 Mask = 1L << 4, 90 Antialias = 1L << 5, 91 GrayscaleFilter = 1L << 6, 92 SepiaFilter = 1L << 7, 93 SaturateFilter = 1L << 8, 94 HueRotateFilter = 1L << 9, 95 BrightnessFilter = 1L << 10, 96 ContrastFilter = 1L << 11, 97 InvertFilter = 1L << 12, 98 OpacityFilter = 1L << 13, 99 BlurFilter = 1L << 14, 100 AlphaBlur = 1L << 15, 101 ContentTexture = 1L << 16 105 102 }; 103 104 typedef unsigned Options; 106 105 107 106 TextureMapperShaderManager() { } … … 109 108 virtual ~TextureMapperShaderManager(); 110 109 111 PassRefPtr<TextureMapperShaderProgram> getShaderProgram( ShaderKey);110 PassRefPtr<TextureMapperShaderProgram> getShaderProgram(Options); 112 111 113 112 private: 114 typedef HashMap< ShaderKey, RefPtr<TextureMapperShaderProgram>, DefaultHash<int>::Hash, HashTraits<int> > TextureMapperShaderProgramMap;113 typedef HashMap<Options, RefPtr<TextureMapperShaderProgram> > TextureMapperShaderProgramMap; 115 114 TextureMapperShaderProgramMap m_programs; 116 115 RefPtr<GraphicsContext3D> m_context;
Note: See TracChangeset
for help on using the changeset viewer.