зеркало из https://github.com/mozilla/pjs.git
Bug 716439; shaders for OpenGL mask layers. r=BenWa
This commit is contained in:
Родитель
4355d4a175
Коммит
679137b6a2
|
@ -37,6 +37,11 @@
|
|||
//
|
||||
// ***** END LICENSE BLOCK *****
|
||||
|
||||
//
|
||||
// This file is compiled by genshaders.py, use genshaders.sh, no arguments necessary.
|
||||
// The compiled shaders will be in LayerManagerOGLShaders.h.
|
||||
// This file must be compiled after editing, it is not compiled as part of the
|
||||
// build process.
|
||||
//
|
||||
// Syntax:
|
||||
//
|
||||
|
@ -54,44 +59,39 @@
|
|||
//
|
||||
// $FOO$ to paste
|
||||
//
|
||||
// To generate a constant string named ShaderName:
|
||||
// To generate a constant string named ShaderName (shader name should not
|
||||
// use '<', '>', ',', ':', except for parameters, see below):
|
||||
// @shader ShaderName
|
||||
// ...
|
||||
// @end
|
||||
//
|
||||
// @shader may have a single parameter with multiple values using
|
||||
// <param:val1,val2> an empty value is allowed. The shader is expanded for
|
||||
// each value, <param> in the body of the shader will be expanded to
|
||||
// the current value, as will the declaration of the parameter. The name of
|
||||
// defines may include <...> and this should work as expected.
|
||||
//
|
||||
// For example:
|
||||
//
|
||||
// @Shader<name:Name1,Name2>
|
||||
// string name = "<name>";
|
||||
// @end
|
||||
//
|
||||
// will be expanded to
|
||||
//
|
||||
// @ShaderName1
|
||||
// string name = "Name1";
|
||||
// @end
|
||||
// @ShaderName2
|
||||
// string name = "Name2";
|
||||
// @end
|
||||
//
|
||||
// This will be straightaway compiled to two constant strings named
|
||||
// ShaderName1 and ShaderName2.
|
||||
//
|
||||
|
||||
@define VERTEX_SHADER_HEADER
|
||||
@define VERTEX_SHADER_HEADER<>
|
||||
/* Vertex Shader */
|
||||
@end
|
||||
|
||||
@define FRAGMENT_SHADER_HEADER
|
||||
/* Fragment Shader */
|
||||
#ifdef GL_ES
|
||||
precision lowp float;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// fragment shader header for all layers
|
||||
@define LAYER_FRAGMENT
|
||||
$FRAGMENT_SHADER_HEADER$
|
||||
|
||||
#ifndef NO_LAYER_OPACITY
|
||||
uniform float uLayerOpacity;
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range
|
||||
varying mediump vec2 vTexCoord;
|
||||
#else
|
||||
varying vec2 vTexCoord;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// This is a basic Layer vertex shader. It's used for all
|
||||
// the Layer programs.
|
||||
|
||||
@shader sLayerVS
|
||||
$VERTEX_SHADER_HEADER$
|
||||
|
||||
uniform mat4 uMatrixProj;
|
||||
uniform mat4 uLayerQuadTransform;
|
||||
|
@ -106,6 +106,43 @@ varying mediump vec2 vTexCoord;
|
|||
#else
|
||||
varying vec2 vTexCoord;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@define VERTEX_SHADER_HEADER<Mask>
|
||||
$VERTEX_SHADER_HEADER<>$
|
||||
|
||||
uniform mat4 uMaskQuadTransform;
|
||||
varying vec2 vMaskCoord;
|
||||
@end
|
||||
|
||||
@define VERTEX_SHADER_HEADER<Mask3D>
|
||||
$VERTEX_SHADER_HEADER<>$
|
||||
|
||||
uniform mat4 uMaskQuadTransform;
|
||||
varying vec3 vMaskCoord;
|
||||
@end
|
||||
|
||||
@define VERTEX_MASK_STUFF<>
|
||||
@end
|
||||
|
||||
@define VERTEX_MASK_STUFF<Mask>
|
||||
vMaskCoord = (uMaskQuadTransform * finalPosition).xy;
|
||||
@end
|
||||
|
||||
@define VERTEX_MASK_STUFF<Mask3D>
|
||||
vMaskCoord.xy = (uMaskQuadTransform * vec4(finalPosition.xyz, 1.0)).xy;
|
||||
// correct for perspective correct interpolation, see comment in D3D10 shader
|
||||
vMaskCoord.z = 1.0;
|
||||
vMaskCoord *= finalPosition.w;
|
||||
@end
|
||||
|
||||
|
||||
// This is a basic Layer vertex shader. It's used for all
|
||||
// Layer programs.
|
||||
|
||||
@shader sLayer<mask:,Mask,Mask3D>VS
|
||||
$VERTEX_SHADER_HEADER<mask>$
|
||||
|
||||
|
||||
void main()
|
||||
{
|
||||
|
@ -113,6 +150,9 @@ void main()
|
|||
finalPosition = uLayerQuadTransform * finalPosition;
|
||||
finalPosition = uLayerTransform * finalPosition;
|
||||
finalPosition.xyz /= finalPosition.w;
|
||||
|
||||
$VERTEX_MASK_STUFF<mask>$
|
||||
|
||||
finalPosition = finalPosition - uRenderTargetOffset;
|
||||
finalPosition.xyz *= finalPosition.w;
|
||||
finalPosition = uMatrixProj * finalPosition;
|
||||
|
@ -122,37 +162,96 @@ void main()
|
|||
}
|
||||
@end
|
||||
|
||||
|
||||
/*
|
||||
* Fragment shaders
|
||||
*/
|
||||
|
||||
@define FRAGMENT_SHADER_HEADER
|
||||
/* Fragment Shader */
|
||||
#ifdef GL_ES
|
||||
precision lowp float;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// fragment shader header for layers
|
||||
@define LAYER_FRAGMENT<>
|
||||
$FRAGMENT_SHADER_HEADER$
|
||||
|
||||
#ifndef NO_LAYER_OPACITY
|
||||
uniform float uLayerOpacity;
|
||||
#endif
|
||||
|
||||
#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range
|
||||
varying mediump vec2 vTexCoord;
|
||||
#else
|
||||
varying vec2 vTexCoord;
|
||||
#endif
|
||||
@end
|
||||
|
||||
// fragment shader header for layers with masks
|
||||
@define LAYER_FRAGMENT<Mask>
|
||||
$LAYER_FRAGMENT<>$
|
||||
|
||||
varying vec2 vMaskCoord;
|
||||
uniform sampler2D uMaskTexture;
|
||||
@end
|
||||
|
||||
// fragment shader header for layers with masks and 3D transforms
|
||||
@define LAYER_FRAGMENT<Mask3D>
|
||||
$LAYER_FRAGMENT<>$
|
||||
|
||||
varying vec3 vMaskCoord;
|
||||
uniform sampler2D uMaskTexture;
|
||||
@end
|
||||
|
||||
@define FRAGMENT_CALC_MASK<>
|
||||
float mask = 1.0;
|
||||
@end
|
||||
|
||||
@define FRAGMENT_CALC_MASK<Mask>
|
||||
float mask = texture2D(uMaskTexture, vMaskCoord).a;
|
||||
@end
|
||||
|
||||
@define FRAGMENT_CALC_MASK<Mask3D>
|
||||
vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;
|
||||
float mask = texture2D(uMaskTexture, maskCoords).a;
|
||||
@end
|
||||
|
||||
// Solid color rendering.
|
||||
// texcoords are ignored (no texture to sample).
|
||||
// The layer opacity is baked in to the color.
|
||||
@shader sSolidColorLayerFS
|
||||
@shader sSolidColorLayer<mask:,Mask>FS
|
||||
#define NO_LAYER_OPACITY 1
|
||||
$LAYER_FRAGMENT$
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform vec4 uRenderColor;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = uRenderColor;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = mask * uRenderColor;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in RGBA format
|
||||
@shader sRGBATextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
@shader sRGBATextureLayer<mask:,Mask,Mask3D>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
// Single texture in RGBA format, but with a Rect texture.
|
||||
// Container layer needs this to render a FBO group.
|
||||
@shader sRGBARectTextureLayerFS
|
||||
@shader sRGBARectTextureLayer<mask:,Mask,Mask3D>FS
|
||||
#extension GL_ARB_texture_rectangle : enable
|
||||
|
||||
$LAYER_FRAGMENT$
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
|
||||
/* This should not be used on GL ES */
|
||||
#ifndef GL_ES
|
||||
|
@ -160,7 +259,8 @@ uniform sampler2DRect uTexture;
|
|||
uniform vec2 uTexCoordMultiplier;
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)) * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)) * uLayerOpacity * mask;
|
||||
}
|
||||
#else
|
||||
void main()
|
||||
|
@ -171,41 +271,44 @@ void main()
|
|||
@end
|
||||
|
||||
// Single texture in BGRA format (via swizzle)
|
||||
@shader sBGRATextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
@shader sBGRATextureLayer<mask:,Mask>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord).bgra * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = texture2D(uTexture, vTexCoord).bgra * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in RGBX format
|
||||
@shader sRGBXTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
@shader sRGBXTextureLayer<mask:,Mask>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).rgb, 1.0) * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).rgb, 1.0) * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
// Single texture in BGRX format (via swizzle)
|
||||
@shader sBGRXTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
@shader sBGRXTextureLayer<mask:,Mask>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).bgr, 1.0) * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = vec4(texture2D(uTexture, vTexCoord).bgr, 1.0) * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
// Three textures, representing YCbCr planes of a video image
|
||||
@shader sYCbCrTextureLayerFS
|
||||
$LAYER_FRAGMENT$
|
||||
@shader sYCbCrTextureLayer<mask:,Mask>FS
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
#ifdef GL_ES
|
||||
precision mediump float;
|
||||
#endif
|
||||
|
@ -224,10 +327,46 @@ void main()
|
|||
color.g = yuv.g * 1.164 - 0.813 * yuv.r - 0.391 * yuv.b;
|
||||
color.b = yuv.g * 1.164 + yuv.b * 2.018;
|
||||
color.a = 1.0;
|
||||
gl_FragColor = color * uLayerOpacity;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = color * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
// Two textures and two passes for component alpha rendering
|
||||
@shader sComponentPass<mask:,Mask>1FS
|
||||
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uBlackTexture;
|
||||
uniform sampler2D uWhiteTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 onBlack = texture2D(uBlackTexture, vTexCoord).bgr;
|
||||
vec3 onWhite = texture2D(uWhiteTexture, vTexCoord).bgr;
|
||||
vec4 alphas = (1.0 - onWhite + onBlack).rgbg;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = alphas * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
@shader sComponentPass<mask:,Mask>2FS
|
||||
|
||||
$LAYER_FRAGMENT<mask>$
|
||||
uniform sampler2D uBlackTexture;
|
||||
uniform sampler2D uWhiteTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 onBlack = texture2D(uBlackTexture, vTexCoord).bgr;
|
||||
vec3 onWhite = texture2D(uWhiteTexture, vTexCoord).bgr;
|
||||
vec4 alphas = (1.0 - onWhite + onBlack).rgbg;
|
||||
$FRAGMENT_CALC_MASK<mask>$
|
||||
gl_FragColor = vec4(onBlack, alphas.a) * uLayerOpacity * mask;
|
||||
}
|
||||
@end
|
||||
|
||||
|
||||
|
||||
//
|
||||
// The "Copy" program is used for blitting a texture to a destination
|
||||
// with no transforms or any other manipulation. They're used for
|
||||
|
@ -243,7 +382,7 @@ void main()
|
|||
//
|
||||
|
||||
@shader sCopyVS
|
||||
$VERTEX_SHADER_HEADER$
|
||||
/* Vertex Shader */
|
||||
|
||||
attribute vec4 aVertexCoord;
|
||||
attribute vec2 aTexCoord;
|
||||
|
@ -291,33 +430,3 @@ void main()
|
|||
#endif
|
||||
@end
|
||||
|
||||
// Two textures and two passes for component alpha rendering
|
||||
@shader sComponentPass1FS
|
||||
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uBlackTexture;
|
||||
uniform sampler2D uWhiteTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 onBlack = texture2D(uBlackTexture, vTexCoord).bgr;
|
||||
vec3 onWhite = texture2D(uWhiteTexture, vTexCoord).bgr;
|
||||
vec4 alphas = (1.0 - onWhite + onBlack).rgbg;
|
||||
gl_FragColor = alphas * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
||||
@shader sComponentPass2FS
|
||||
|
||||
$LAYER_FRAGMENT$
|
||||
uniform sampler2D uBlackTexture;
|
||||
uniform sampler2D uWhiteTexture;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 onBlack = texture2D(uBlackTexture, vTexCoord).bgr;
|
||||
vec3 onWhite = texture2D(uWhiteTexture, vTexCoord).bgr;
|
||||
vec4 alphas = (1.0 - onWhite + onBlack).rgbg;
|
||||
gl_FragColor = vec4(onBlack, alphas.a) * uLayerOpacity;
|
||||
}
|
||||
@end
|
||||
|
|
|
@ -170,11 +170,13 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
|||
if (passes == 2) {
|
||||
ShaderProgramOGL* alphaProgram;
|
||||
if (pass == 1) {
|
||||
alphaProgram = aManager->GetProgram(gl::ComponentAlphaPass1ProgramType);
|
||||
alphaProgram = aManager->GetProgram(gl::ComponentAlphaPass1ProgramType,
|
||||
mLayer->GetMaskLayer());
|
||||
gl()->fBlendFuncSeparate(LOCAL_GL_ZERO, LOCAL_GL_ONE_MINUS_SRC_COLOR,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
} else {
|
||||
alphaProgram = aManager->GetProgram(gl::ComponentAlphaPass2ProgramType);
|
||||
alphaProgram = aManager->GetProgram(gl::ComponentAlphaPass2ProgramType,
|
||||
mLayer->GetMaskLayer());
|
||||
gl()->fBlendFuncSeparate(LOCAL_GL_ONE, LOCAL_GL_ONE,
|
||||
LOCAL_GL_ONE, LOCAL_GL_ONE);
|
||||
}
|
||||
|
@ -187,7 +189,8 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
|||
// Note BGR: Cairo's image surfaces are always in what
|
||||
// OpenGL and our shaders consider BGR format.
|
||||
ShaderProgramOGL* basicProgram =
|
||||
aManager->GetProgram(mTexImage->GetShaderProgramType());
|
||||
aManager->GetProgram(mTexImage->GetShaderProgramType(),
|
||||
mLayer->GetMaskLayer());
|
||||
|
||||
basicProgram->Activate();
|
||||
basicProgram->SetTextureUnit(0);
|
||||
|
@ -197,6 +200,7 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
|||
program->SetLayerOpacity(mLayer->GetEffectiveOpacity());
|
||||
program->SetLayerTransform(mLayer->GetEffectiveTransform());
|
||||
program->SetRenderOffset(aOffset);
|
||||
program->LoadMask(mLayer->GetMaskLayer());
|
||||
|
||||
const nsIntRegion& visibleRegion = mLayer->GetEffectiveVisibleRegion();
|
||||
nsIntRegion tmpRegion;
|
||||
|
|
|
@ -42,28 +42,79 @@ import string
|
|||
|
||||
defines = dict()
|
||||
|
||||
def emitShader(fp, shadername, shaderlines):
|
||||
eolContinue = "\\n\\\n";
|
||||
fp.write("const char %s[] = \"/* %s */%s" % (shadername,shadername,eolContinue))
|
||||
for line in shaderlines:
|
||||
line.replace("\\", "\\\\")
|
||||
while line.find('$') != -1:
|
||||
expansions = re.findall('\$\S+\$', line)
|
||||
for m in expansions:
|
||||
mkey = m[1:-1]
|
||||
if not defines.has_key(mkey):
|
||||
print "Error: Undefined expansion used: '%s'" % (m,)
|
||||
sys.exit(1)
|
||||
mval = defines[mkey]
|
||||
if type(mval) == str:
|
||||
line = line.replace(m, mval)
|
||||
elif type(mval) == list:
|
||||
line = line.replace(m, eolContinue.join(mval) + eolContinue);
|
||||
else:
|
||||
print "Internal Error: Unknown type in defines array: '%s'" % (str(type(mval)),)
|
||||
def parseShaderName(shadername):
|
||||
name = ""
|
||||
params = {}
|
||||
inparams = None
|
||||
inparam = None
|
||||
curparams = []
|
||||
for c in shadername:
|
||||
if c == '<':
|
||||
inparams = ''
|
||||
elif c == ':':
|
||||
if inparams is None:
|
||||
raise Exception(": in shader name")
|
||||
inparam = ''
|
||||
elif c == ',':
|
||||
if inparams is None:
|
||||
raise Exception(", in shader name")
|
||||
if inparam is None:
|
||||
raise Exception("no values for parameter " + inparams)
|
||||
curparams.append(inparam)
|
||||
inparam = ''
|
||||
elif c == '>':
|
||||
if inparams is None:
|
||||
raise Exception("> in shader name")
|
||||
if inparam is None:
|
||||
raise Exception("no values for parameter " + inparams)
|
||||
curparams.append(inparam)
|
||||
params[inparams] = curparams
|
||||
name += '$' + inparams + '$'
|
||||
inparams = None
|
||||
inparam = None
|
||||
else:
|
||||
if inparam is not None:
|
||||
inparam += c
|
||||
elif inparams is not None:
|
||||
inparams += c
|
||||
else:
|
||||
name += c
|
||||
return (name, params)
|
||||
|
||||
fp.write("%s%s" % (line,eolContinue))
|
||||
fp.write("\";\n\n");
|
||||
def emitShader(fp, shadername, shaderlines):
|
||||
(parsedname, params) = parseShaderName(shadername)
|
||||
eolContinue = "\\n\\\n";
|
||||
pvals = ['']
|
||||
pname = ''
|
||||
pnames = params.keys()
|
||||
if len(pnames) > 1:
|
||||
raise Exception("Currently only supports zero or one parameters to a @shader")
|
||||
if pnames:
|
||||
pname = pnames[0]
|
||||
pvals = params[pname]
|
||||
for pval in pvals:
|
||||
name = parsedname.replace('$' + pname + '$', pval, 1);
|
||||
fp.write("const char %s[] = \"/* %s */%s" % (name,name,eolContinue))
|
||||
for line in shaderlines:
|
||||
line = line.replace("\\", "\\\\")
|
||||
while line.find('$') != -1:
|
||||
expansions = re.findall('\$\S+\$', line)
|
||||
for m in expansions:
|
||||
mkey = m[1:-1]
|
||||
mkey = mkey.replace('<' + pname + '>', '<' + pval + '>')
|
||||
if not defines.has_key(mkey):
|
||||
print "Error: Undefined expansion used: '%s'" % (m,)
|
||||
sys.exit(1)
|
||||
mval = defines[mkey]
|
||||
if type(mval) == str:
|
||||
line = line.replace(m, mval)
|
||||
elif type(mval) == list:
|
||||
line = line.replace(m, eolContinue.join(mval) + eolContinue);
|
||||
else:
|
||||
print "Internal Error: Unknown type in defines array: '%s'" % (str(type(mval)),)
|
||||
|
||||
fp.write("%s%s" % (line,eolContinue))
|
||||
fp.write("\";\n\n");
|
||||
|
||||
def genShaders(infile, outfile):
|
||||
source = open(infile, "r").readlines()
|
||||
|
|
Загрузка…
Ссылка в новой задаче