1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/layers/opengl/OGLShaderProgram.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,541 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include "OGLShaderProgram.h" 1.9 +#include <stdint.h> // for uint32_t 1.10 +#include <sstream> // for ostringstream 1.11 +#include "gfxRect.h" // for gfxRect 1.12 +#include "mozilla/DebugOnly.h" // for DebugOnly 1.13 +#include "nsAString.h" 1.14 +#include "nsAutoPtr.h" // for nsRefPtr 1.15 +#include "nsString.h" // for nsAutoCString 1.16 +#include "prenv.h" // for PR_GetEnv 1.17 +#include "Layers.h" 1.18 +#include "GLContext.h" 1.19 + 1.20 +struct gfxRGBA; 1.21 + 1.22 +namespace mozilla { 1.23 +namespace layers { 1.24 + 1.25 +using namespace std; 1.26 + 1.27 +typedef ProgramProfileOGL::Argument Argument; 1.28 + 1.29 +#define GAUSSIAN_KERNEL_HALF_WIDTH 11 1.30 +#define GAUSSIAN_KERNEL_STEP 0.2 1.31 + 1.32 +void 1.33 +AddUniforms(ProgramProfileOGL& aProfile) 1.34 +{ 1.35 + static const char *sKnownUniformNames[] = { 1.36 + "uLayerTransform", 1.37 + "uMaskQuadTransform", 1.38 + "uLayerQuadTransform", 1.39 + "uMatrixProj", 1.40 + "uTextureTransform", 1.41 + "uRenderTargetOffset", 1.42 + "uLayerOpacity", 1.43 + "uTexture", 1.44 + "uYTexture", 1.45 + "uCbTexture", 1.46 + "uCrTexture", 1.47 + "uBlackTexture", 1.48 + "uWhiteTexture", 1.49 + "uMaskTexture", 1.50 + "uRenderColor", 1.51 + "uTexCoordMultiplier", 1.52 + "uTexturePass2", 1.53 + nullptr 1.54 + }; 1.55 + 1.56 + for (int i = 0; sKnownUniformNames[i] != nullptr; ++i) { 1.57 + aProfile.mUniforms[i].mNameString = sKnownUniformNames[i]; 1.58 + aProfile.mUniforms[i].mName = (KnownUniform::KnownUniformName) i; 1.59 + } 1.60 +} 1.61 + 1.62 +void 1.63 +ShaderConfigOGL::SetRenderColor(bool aEnabled) 1.64 +{ 1.65 + SetFeature(ENABLE_RENDER_COLOR, aEnabled); 1.66 +} 1.67 + 1.68 +void 1.69 +ShaderConfigOGL::SetTextureTarget(GLenum aTarget) 1.70 +{ 1.71 + SetFeature(ENABLE_TEXTURE_EXTERNAL | ENABLE_TEXTURE_RECT, false); 1.72 + switch (aTarget) { 1.73 + case LOCAL_GL_TEXTURE_EXTERNAL: 1.74 + SetFeature(ENABLE_TEXTURE_EXTERNAL, true); 1.75 + break; 1.76 + case LOCAL_GL_TEXTURE_RECTANGLE_ARB: 1.77 + SetFeature(ENABLE_TEXTURE_RECT, true); 1.78 + break; 1.79 + } 1.80 +} 1.81 + 1.82 +void 1.83 +ShaderConfigOGL::SetRBSwap(bool aEnabled) 1.84 +{ 1.85 + SetFeature(ENABLE_TEXTURE_RB_SWAP, aEnabled); 1.86 +} 1.87 + 1.88 +void 1.89 +ShaderConfigOGL::SetNoAlpha(bool aEnabled) 1.90 +{ 1.91 + SetFeature(ENABLE_TEXTURE_NO_ALPHA, aEnabled); 1.92 +} 1.93 + 1.94 +void 1.95 +ShaderConfigOGL::SetOpacity(bool aEnabled) 1.96 +{ 1.97 + SetFeature(ENABLE_OPACITY, aEnabled); 1.98 +} 1.99 + 1.100 +void 1.101 +ShaderConfigOGL::SetYCbCr(bool aEnabled) 1.102 +{ 1.103 + SetFeature(ENABLE_TEXTURE_YCBCR, aEnabled); 1.104 +} 1.105 + 1.106 +void 1.107 +ShaderConfigOGL::SetComponentAlpha(bool aEnabled) 1.108 +{ 1.109 + SetFeature(ENABLE_TEXTURE_COMPONENT_ALPHA, aEnabled); 1.110 +} 1.111 + 1.112 +void 1.113 +ShaderConfigOGL::SetColorMatrix(bool aEnabled) 1.114 +{ 1.115 + SetFeature(ENABLE_COLOR_MATRIX, aEnabled); 1.116 +} 1.117 + 1.118 +void 1.119 +ShaderConfigOGL::SetBlur(bool aEnabled) 1.120 +{ 1.121 + SetFeature(ENABLE_BLUR, aEnabled); 1.122 +} 1.123 + 1.124 +void 1.125 +ShaderConfigOGL::SetMask2D(bool aEnabled) 1.126 +{ 1.127 + SetFeature(ENABLE_MASK_2D, aEnabled); 1.128 +} 1.129 + 1.130 +void 1.131 +ShaderConfigOGL::SetMask3D(bool aEnabled) 1.132 +{ 1.133 + SetFeature(ENABLE_MASK_3D, aEnabled); 1.134 +} 1.135 + 1.136 +/* static */ ProgramProfileOGL 1.137 +ProgramProfileOGL::GetProfileFor(ShaderConfigOGL aConfig) 1.138 +{ 1.139 + ProgramProfileOGL result; 1.140 + ostringstream fs, vs; 1.141 + 1.142 + AddUniforms(result); 1.143 + 1.144 + vs << "uniform mat4 uMatrixProj;" << endl; 1.145 + vs << "uniform mat4 uLayerQuadTransform;" << endl; 1.146 + vs << "uniform mat4 uLayerTransform;" << endl; 1.147 + vs << "uniform vec4 uRenderTargetOffset;" << endl; 1.148 + 1.149 + vs << "attribute vec4 aVertexCoord;" << endl; 1.150 + 1.151 + if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 1.152 + vs << "uniform mat4 uTextureTransform;" << endl; 1.153 + vs << "attribute vec2 aTexCoord;" << endl; 1.154 + vs << "varying vec2 vTexCoord;" << endl; 1.155 + } 1.156 + 1.157 + if (aConfig.mFeatures & ENABLE_MASK_2D || 1.158 + aConfig.mFeatures & ENABLE_MASK_3D) { 1.159 + vs << "uniform mat4 uMaskQuadTransform;" << endl; 1.160 + vs << "varying vec3 vMaskCoord;" << endl; 1.161 + } 1.162 + 1.163 + vs << "void main() {" << endl; 1.164 + vs << " vec4 finalPosition = aVertexCoord;" << endl; 1.165 + vs << " finalPosition = uLayerQuadTransform * finalPosition;" << endl; 1.166 + vs << " finalPosition = uLayerTransform * finalPosition;" << endl; 1.167 + vs << " finalPosition.xyz /= finalPosition.w;" << endl; 1.168 + 1.169 + if (aConfig.mFeatures & ENABLE_MASK_3D) { 1.170 + vs << " vMaskCoord.xy = (uMaskQuadTransform * vec4(finalPosition.xyz, 1.0)).xy;" << endl; 1.171 + // correct for perspective correct interpolation, see comment in D3D10 shader 1.172 + vs << " vMaskCoord.z = 1.0;" << endl; 1.173 + vs << " vMaskCoord *= finalPosition.w;" << endl; 1.174 + } else if (aConfig.mFeatures & ENABLE_MASK_2D) { 1.175 + vs << " vMaskCoord.xy = (uMaskQuadTransform * finalPosition).xy;" << endl; 1.176 + } 1.177 + 1.178 + vs << " finalPosition = finalPosition - uRenderTargetOffset;" << endl; 1.179 + vs << " finalPosition.xyz *= finalPosition.w;" << endl; 1.180 + vs << " finalPosition = uMatrixProj * finalPosition;" << endl; 1.181 + 1.182 + if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 1.183 + vs << " vTexCoord = (uTextureTransform * vec4(aTexCoord.x, aTexCoord.y, 0.0, 1.0)).xy;" << endl; 1.184 + } 1.185 + 1.186 + vs << " gl_Position = finalPosition;" << endl; 1.187 + vs << "}" << endl; 1.188 + 1.189 + if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 1.190 + fs << "#extension GL_ARB_texture_rectangle : require" << endl; 1.191 + } 1.192 + if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) { 1.193 + fs << "#extension GL_OES_EGL_image_external : require" << endl; 1.194 + } 1.195 + fs << "#ifdef GL_ES" << endl; 1.196 + fs << "precision mediump float;" << endl; 1.197 + fs << "#define COLOR_PRECISION lowp" << endl; 1.198 + fs << "#else" << endl; 1.199 + fs << "#define COLOR_PRECISION" << endl; 1.200 + fs << "#endif" << endl; 1.201 + if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 1.202 + fs << "uniform COLOR_PRECISION vec4 uRenderColor;" << endl; 1.203 + } else { 1.204 + // for tiling, texcoord can be greater than the lowfp range 1.205 + fs << "varying vec2 vTexCoord;" << endl; 1.206 + if (aConfig.mFeatures & ENABLE_BLUR) { 1.207 + fs << "uniform bool uBlurAlpha;" << endl; 1.208 + fs << "uniform vec2 uBlurRadius;" << endl; 1.209 + fs << "uniform vec2 uBlurOffset;" << endl; 1.210 + fs << "uniform float uBlurGaussianKernel[" << GAUSSIAN_KERNEL_HALF_WIDTH << "];" << endl; 1.211 + } 1.212 + if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) { 1.213 + fs << "uniform mat4 uColorMatrix;" << endl; 1.214 + fs << "uniform vec4 uColorMatrixVector;" << endl; 1.215 + } 1.216 + if (aConfig.mFeatures & ENABLE_OPACITY) { 1.217 + fs << "uniform COLOR_PRECISION float uLayerOpacity;" << endl; 1.218 + } 1.219 + } 1.220 + 1.221 + const char *sampler2D = "sampler2D"; 1.222 + const char *texture2D = "texture2D"; 1.223 + 1.224 + if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 1.225 + fs << "uniform vec2 uTexCoordMultiplier;" << endl; 1.226 + sampler2D = "sampler2DRect"; 1.227 + texture2D = "texture2DRect"; 1.228 + } 1.229 + 1.230 + if (aConfig.mFeatures & ENABLE_TEXTURE_EXTERNAL) { 1.231 + sampler2D = "samplerExternalOES"; 1.232 + } 1.233 + 1.234 + if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 1.235 + fs << "uniform sampler2D uYTexture;" << endl; 1.236 + fs << "uniform sampler2D uCbTexture;" << endl; 1.237 + fs << "uniform sampler2D uCrTexture;" << endl; 1.238 + } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 1.239 + fs << "uniform sampler2D uBlackTexture;" << endl; 1.240 + fs << "uniform sampler2D uWhiteTexture;" << endl; 1.241 + fs << "uniform bool uTexturePass2;" << endl; 1.242 + } else { 1.243 + fs << "uniform " << sampler2D << " uTexture;" << endl; 1.244 + } 1.245 + 1.246 + if (aConfig.mFeatures & ENABLE_MASK_2D || 1.247 + aConfig.mFeatures & ENABLE_MASK_3D) { 1.248 + fs << "varying vec3 vMaskCoord;" << endl; 1.249 + fs << "uniform sampler2D uMaskTexture;" << endl; 1.250 + } 1.251 + 1.252 + if (!(aConfig.mFeatures & ENABLE_RENDER_COLOR)) { 1.253 + fs << "vec4 sample(vec2 coord) {" << endl; 1.254 + fs << " vec4 color;" << endl; 1.255 + if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 1.256 + fs << " COLOR_PRECISION float y = texture2D(uYTexture, coord).r;" << endl; 1.257 + fs << " COLOR_PRECISION float cb = texture2D(uCbTexture, coord).r;" << endl; 1.258 + fs << " COLOR_PRECISION float cr = texture2D(uCrTexture, coord).r;" << endl; 1.259 + fs << " y = (y - 0.0625) * 1.164;" << endl; 1.260 + fs << " cb = cb - 0.5;" << endl; 1.261 + fs << " cr = cr - 0.5;" << endl; 1.262 + fs << " color.r = y + cr * 1.596;" << endl; 1.263 + fs << " color.g = y - 0.813 * cr - 0.391 * cb;" << endl; 1.264 + fs << " color.b = y + cb * 2.018;" << endl; 1.265 + fs << " color.a = 1.0;" << endl; 1.266 + } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 1.267 + fs << " COLOR_PRECISION vec3 onBlack = texture2D(uBlackTexture, coord).rgb;" << endl; 1.268 + fs << " COLOR_PRECISION vec3 onWhite = texture2D(uWhiteTexture, coord).rgb;" << endl; 1.269 + fs << " COLOR_PRECISION vec4 alphas = (1.0 - onWhite + onBlack).rgbg;" << endl; 1.270 + fs << " if (uTexturePass2)" << endl; 1.271 + fs << " color = vec4(onBlack, alphas.a);" << endl; 1.272 + fs << " else" << endl; 1.273 + fs << " color = alphas;" << endl; 1.274 + } else { 1.275 + fs << " color = " << texture2D << "(uTexture, coord);" << endl; 1.276 + } 1.277 + if (aConfig.mFeatures & ENABLE_TEXTURE_RB_SWAP) { 1.278 + fs << " color = color.bgra;" << endl; 1.279 + } 1.280 + if (aConfig.mFeatures & ENABLE_TEXTURE_NO_ALPHA) { 1.281 + fs << " color = vec4(color.rgb, 1.0);" << endl; 1.282 + } 1.283 + fs << " return color;" << endl; 1.284 + fs << "}" << endl; 1.285 + if (aConfig.mFeatures & ENABLE_BLUR) { 1.286 + fs << "vec4 sampleAtRadius(vec2 coord, float radius) {" << endl; 1.287 + fs << " coord += uBlurOffset;" << endl; 1.288 + fs << " coord += radius * uBlurRadius;" << endl; 1.289 + fs << " if (coord.x < 0. || coord.y < 0. || coord.x > 1. || coord.y > 1.)" << endl; 1.290 + fs << " return vec4(0, 0, 0, 0);" << endl; 1.291 + fs << " return sample(coord);" << endl; 1.292 + fs << "}" << endl; 1.293 + fs << "vec4 blur(vec4 color, vec2 coord) {" << endl; 1.294 + fs << " vec4 total = color * uBlurGaussianKernel[0];" << endl; 1.295 + fs << " for (int i = 1; i < " << GAUSSIAN_KERNEL_HALF_WIDTH << "; ++i) {" << endl; 1.296 + fs << " float r = float(i) * " << GAUSSIAN_KERNEL_STEP << " << endl;" << endl; 1.297 + fs << " float k = uBlurGaussianKernel[i];" << endl; 1.298 + fs << " total += sampleAtRadius(coord, r) * k;" << endl; 1.299 + fs << " total += sampleAtRadius(coord, -r) * k;" << endl; 1.300 + fs << " }" << endl; 1.301 + fs << " if (uBlurAlpha) {" << endl; 1.302 + fs << " color *= total.a;" << endl; 1.303 + fs << " } else {" << endl; 1.304 + fs << " color = total;" << endl; 1.305 + fs << " }" << endl; 1.306 + fs << " return color;" << endl; 1.307 + fs << "}" << endl; 1.308 + } 1.309 + } 1.310 + fs << "void main() {" << endl; 1.311 + if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 1.312 + fs << " vec4 color = uRenderColor;" << endl; 1.313 + } else { 1.314 + if (aConfig.mFeatures & ENABLE_TEXTURE_RECT) { 1.315 + fs << " vec4 color = sample(vTexCoord * uTexCoordMultiplier);" << endl; 1.316 + } else { 1.317 + fs << " vec4 color = sample(vTexCoord);" << endl; 1.318 + } 1.319 + if (aConfig.mFeatures & ENABLE_BLUR) { 1.320 + fs << " color = blur(color, vTexCoord);" << endl; 1.321 + } 1.322 + if (aConfig.mFeatures & ENABLE_COLOR_MATRIX) { 1.323 + fs << " color = uColorMatrix * vec4(color.rgb / color.a, color.a) + uColorMatrixVector;" << endl; 1.324 + fs << " color.rgb *= color.a;" << endl; 1.325 + } 1.326 + if (aConfig.mFeatures & ENABLE_OPACITY) { 1.327 + fs << " color *= uLayerOpacity;" << endl; 1.328 + } 1.329 + } 1.330 + if (aConfig.mFeatures & ENABLE_MASK_3D) { 1.331 + fs << " vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;" << endl; 1.332 + fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, maskCoords).r;" << endl; 1.333 + fs << " color *= mask;" << endl; 1.334 + } else if (aConfig.mFeatures & ENABLE_MASK_2D) { 1.335 + fs << " COLOR_PRECISION float mask = texture2D(uMaskTexture, vMaskCoord.xy).r;" << endl; 1.336 + fs << " color *= mask;" << endl; 1.337 + } else { 1.338 + fs << " COLOR_PRECISION float mask = 1.0;" << endl; 1.339 + fs << " color *= mask;" << endl; 1.340 + } 1.341 + fs << " gl_FragColor = color;" << endl; 1.342 + fs << "}" << endl; 1.343 + 1.344 + result.mVertexShaderString = vs.str(); 1.345 + result.mFragmentShaderString = fs.str(); 1.346 + 1.347 + result.mAttributes.AppendElement(Argument("aVertexCoord")); 1.348 + if (aConfig.mFeatures & ENABLE_RENDER_COLOR) { 1.349 + result.mTextureCount = 0; 1.350 + } else { 1.351 + result.mAttributes.AppendElement(Argument("aTexCoord")); 1.352 + if (aConfig.mFeatures & ENABLE_TEXTURE_YCBCR) { 1.353 + result.mTextureCount = 3; 1.354 + } else if (aConfig.mFeatures & ENABLE_TEXTURE_COMPONENT_ALPHA) { 1.355 + result.mTextureCount = 2; 1.356 + } else { 1.357 + result.mTextureCount = 1; 1.358 + } 1.359 + } 1.360 + if (aConfig.mFeatures & ENABLE_MASK_2D || 1.361 + aConfig.mFeatures & ENABLE_MASK_3D) { 1.362 + result.mTextureCount = 1; 1.363 + } 1.364 + 1.365 + return result; 1.366 +} 1.367 + 1.368 +const char* const ShaderProgramOGL::VertexCoordAttrib = "aVertexCoord"; 1.369 +const char* const ShaderProgramOGL::TexCoordAttrib = "aTexCoord"; 1.370 + 1.371 +ShaderProgramOGL::ShaderProgramOGL(GLContext* aGL, const ProgramProfileOGL& aProfile) 1.372 + : mGL(aGL) 1.373 + , mProgram(0) 1.374 + , mProfile(aProfile) 1.375 + , mProgramState(STATE_NEW) 1.376 +{ 1.377 +} 1.378 + 1.379 +ShaderProgramOGL::~ShaderProgramOGL() 1.380 +{ 1.381 + if (mProgram <= 0) { 1.382 + return; 1.383 + } 1.384 + 1.385 + nsRefPtr<GLContext> ctx = mGL->GetSharedContext(); 1.386 + if (!ctx) { 1.387 + ctx = mGL; 1.388 + } 1.389 + ctx->MakeCurrent(); 1.390 + ctx->fDeleteProgram(mProgram); 1.391 +} 1.392 + 1.393 +bool 1.394 +ShaderProgramOGL::Initialize() 1.395 +{ 1.396 + NS_ASSERTION(mProgramState == STATE_NEW, "Shader program has already been initialised"); 1.397 + 1.398 + ostringstream vs, fs; 1.399 + for (uint32_t i = 0; i < mProfile.mDefines.Length(); ++i) { 1.400 + vs << mProfile.mDefines[i] << endl; 1.401 + fs << mProfile.mDefines[i] << endl; 1.402 + } 1.403 + vs << mProfile.mVertexShaderString << endl; 1.404 + fs << mProfile.mFragmentShaderString << endl; 1.405 + 1.406 + if (!CreateProgram(vs.str().c_str(), fs.str().c_str())) { 1.407 + mProgramState = STATE_ERROR; 1.408 + return false; 1.409 + } 1.410 + 1.411 + mProgramState = STATE_OK; 1.412 + 1.413 + for (uint32_t i = 0; i < KnownUniform::KnownUniformCount; ++i) { 1.414 + mProfile.mUniforms[i].mLocation = 1.415 + mGL->fGetUniformLocation(mProgram, mProfile.mUniforms[i].mNameString); 1.416 + } 1.417 + 1.418 + for (uint32_t i = 0; i < mProfile.mAttributes.Length(); ++i) { 1.419 + mProfile.mAttributes[i].mLocation = 1.420 + mGL->fGetAttribLocation(mProgram, mProfile.mAttributes[i].mName); 1.421 + NS_ASSERTION(mProfile.mAttributes[i].mLocation >= 0, "Bad attribute location."); 1.422 + } 1.423 + 1.424 + //mProfile.mHasMatrixProj = mProfile.mUniforms[KnownUniform::MatrixProj].mLocation != -1; 1.425 + 1.426 + return true; 1.427 +} 1.428 + 1.429 +GLint 1.430 +ShaderProgramOGL::CreateShader(GLenum aShaderType, const char *aShaderSource) 1.431 +{ 1.432 + GLint success, len = 0; 1.433 + 1.434 + GLint sh = mGL->fCreateShader(aShaderType); 1.435 + mGL->fShaderSource(sh, 1, (const GLchar**)&aShaderSource, nullptr); 1.436 + mGL->fCompileShader(sh); 1.437 + mGL->fGetShaderiv(sh, LOCAL_GL_COMPILE_STATUS, &success); 1.438 + mGL->fGetShaderiv(sh, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len); 1.439 + /* Even if compiling is successful, there may still be warnings. Print them 1.440 + * in a debug build. The > 10 is to catch silly compilers that might put 1.441 + * some whitespace in the log but otherwise leave it empty. 1.442 + */ 1.443 + if (!success 1.444 +#ifdef DEBUG 1.445 + || (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS")) 1.446 +#endif 1.447 + ) 1.448 + { 1.449 + nsAutoCString log; 1.450 + log.SetCapacity(len); 1.451 + mGL->fGetShaderInfoLog(sh, len, (GLint*) &len, (char*) log.BeginWriting()); 1.452 + log.SetLength(len); 1.453 + 1.454 + if (!success) { 1.455 + printf_stderr("=== SHADER COMPILATION FAILED ===\n"); 1.456 + } else { 1.457 + printf_stderr("=== SHADER COMPILATION WARNINGS ===\n"); 1.458 + } 1.459 + 1.460 + printf_stderr("=== Source:\n%s\n", aShaderSource); 1.461 + printf_stderr("=== Log:\n%s\n", log.get()); 1.462 + printf_stderr("============\n"); 1.463 + 1.464 + if (!success) { 1.465 + mGL->fDeleteShader(sh); 1.466 + return 0; 1.467 + } 1.468 + } 1.469 + 1.470 + return sh; 1.471 +} 1.472 + 1.473 +bool 1.474 +ShaderProgramOGL::CreateProgram(const char *aVertexShaderString, 1.475 + const char *aFragmentShaderString) 1.476 +{ 1.477 + GLuint vertexShader = CreateShader(LOCAL_GL_VERTEX_SHADER, aVertexShaderString); 1.478 + GLuint fragmentShader = CreateShader(LOCAL_GL_FRAGMENT_SHADER, aFragmentShaderString); 1.479 + 1.480 + if (!vertexShader || !fragmentShader) 1.481 + return false; 1.482 + 1.483 + GLint result = mGL->fCreateProgram(); 1.484 + mGL->fAttachShader(result, vertexShader); 1.485 + mGL->fAttachShader(result, fragmentShader); 1.486 + 1.487 + mGL->fLinkProgram(result); 1.488 + 1.489 + GLint success, len; 1.490 + mGL->fGetProgramiv(result, LOCAL_GL_LINK_STATUS, &success); 1.491 + mGL->fGetProgramiv(result, LOCAL_GL_INFO_LOG_LENGTH, (GLint*) &len); 1.492 + /* Even if linking is successful, there may still be warnings. Print them 1.493 + * in a debug build. The > 10 is to catch silly compilers that might put 1.494 + * some whitespace in the log but otherwise leave it empty. 1.495 + */ 1.496 + if (!success 1.497 +#ifdef DEBUG 1.498 + || (len > 10 && PR_GetEnv("MOZ_DEBUG_SHADERS")) 1.499 +#endif 1.500 + ) 1.501 + { 1.502 + nsAutoCString log; 1.503 + log.SetCapacity(len); 1.504 + mGL->fGetProgramInfoLog(result, len, (GLint*) &len, (char*) log.BeginWriting()); 1.505 + log.SetLength(len); 1.506 + 1.507 + if (!success) { 1.508 + printf_stderr("=== PROGRAM LINKING FAILED ===\n"); 1.509 + } else { 1.510 + printf_stderr("=== PROGRAM LINKING WARNINGS ===\n"); 1.511 + } 1.512 + printf_stderr("=== Log:\n%s\n", log.get()); 1.513 + printf_stderr("============\n"); 1.514 + } 1.515 + 1.516 + // We can mark the shaders for deletion; they're attached to the program 1.517 + // and will remain attached. 1.518 + mGL->fDeleteShader(vertexShader); 1.519 + mGL->fDeleteShader(fragmentShader); 1.520 + 1.521 + if (!success) { 1.522 + mGL->fDeleteProgram(result); 1.523 + return false; 1.524 + } 1.525 + 1.526 + mProgram = result; 1.527 + return true; 1.528 +} 1.529 + 1.530 +void 1.531 +ShaderProgramOGL::Activate() 1.532 +{ 1.533 + if (mProgramState == STATE_NEW) { 1.534 + if (!Initialize()) { 1.535 + NS_WARNING("Shader could not be initialised"); 1.536 + return; 1.537 + } 1.538 + } 1.539 + NS_ASSERTION(HasInitialized(), "Attempting to activate a program that's not in use!"); 1.540 + mGL->fUseProgram(mProgram); 1.541 +} 1.542 + 1.543 +} /* layers */ 1.544 +} /* mozilla */