// -*- Mode: glsl; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40; -*-

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// 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:
//
// // comments (only at the start of a line)
//
// (@ is used because # is valid inside GLSL)
//
// multi-line:
// @define FOO
// ...
// @end
//
// single:
// @define FOO 123
//
// $FOO$ to paste
//
// 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<>
/* Vertex Shader */

uniform mat4 uMatrixProj;
uniform mat4 uLayerQuadTransform;
uniform mat4 uLayerTransform;
uniform vec4 uRenderTargetOffset;

attribute vec4 aVertexCoord;
attribute vec2 aTexCoord;

#ifdef GL_ES // for tiling, texcoord can be greater than the lowfp range
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()
{
  vec4 finalPosition = aVertexCoord;
  finalPosition = uLayerQuadTransform * finalPosition;
  finalPosition = uLayerTransform * finalPosition;
  finalPosition.xyz /= finalPosition.w;

$VERTEX_MASK_STUFF<mask>$

  finalPosition = finalPosition - uRenderTargetOffset;
  finalPosition.xyz *= finalPosition.w;
  finalPosition = uMatrixProj * finalPosition;

  vTexCoord = aTexCoord;
  gl_Position = finalPosition;
}
@end


/*
 * Fragment shaders
 */

@define FRAGMENT_SHADER_HEADER
/* Fragment Shader */
#ifdef GL_ES
#ifdef MEDIUMP_SHADER
precision mediump float;
#else
precision lowp float;
#endif
#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).r;
@end

@define FRAGMENT_CALC_MASK<Mask3D>
  vec2 maskCoords = vMaskCoord.xy / vMaskCoord.z;
  float mask = texture2D(uMaskTexture, maskCoords).r;
@end

// Solid color rendering.
// texcoords are ignored (no texture to sample).
// The layer opacity is baked in to the color.
@shader sSolidColorLayer<mask:,Mask>FS
#define NO_LAYER_OPACITY 1
$LAYER_FRAGMENT<mask>$
uniform vec4 uRenderColor;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = mask * uRenderColor;
}
@end

// Single texture in RGBA format
@shader sRGBATextureLayer<mask:,Mask,Mask3D>FS
$LAYER_FRAGMENT<mask>$
uniform sampler2D uTexture;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;
}
@end

// Single texture in RGBA format for use with GL_TEXTURE_EXTERNAL_OES
@shader sRGBATextureLayerExternal<mask:,Mask,Mask3D>FS
#extension GL_OES_EGL_image_external : require

#define MEDIUMP_SHADER 1
$LAYER_FRAGMENT<mask>$

uniform samplerExternalOES uTexture;
uniform mat4 uTextureTransform;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = texture2D(uTexture, (uTextureTransform * vec4(vTexCoord.x, vTexCoord.y, 0.0, 1.0)).xy) * uLayerOpacity * mask;
}
@end


// Single texture in RGBA format, but with a Rect texture.
// Container layer needs this to render a FBO group.
@shader sRGBARectTextureLayer<mask:,Mask,Mask3D>FS
#extension GL_ARB_texture_rectangle : enable

$LAYER_FRAGMENT<mask>$

/* This should not be used on GL ES */
#ifndef GL_ES
uniform sampler2DRect uTexture;
uniform vec2 uTexCoordMultiplier;
void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = texture2DRect(uTexture, vec2(vTexCoord * uTexCoordMultiplier)) * uLayerOpacity * mask;
}
#else
void main()
{
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
#endif
@end

// Single texture in RGBA format, but uses external image.  External
// image is an EGLImage which have internal formats not otherwise
// supported by OpenGL ES. It is up to the implementation exactly what
// formats are accepted. It is specified in the OES_EGL_image_external
// extension.
@shader sRGBAExternalTextureLayer<mask:,Mask,Mask3D>FS
#extension GL_OES_EGL_image_external : require

$LAYER_FRAGMENT<mask>$
uniform samplerExternalOES uTexture;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = texture2D(uTexture, vTexCoord) * uLayerOpacity * mask;
}
@end


// Single texture in BGRA format (via swizzle)
@shader sBGRATextureLayer<mask:,Mask>FS
$LAYER_FRAGMENT<mask>$
uniform sampler2D uTexture;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = texture2D(uTexture, vTexCoord).bgra * uLayerOpacity * mask;
}
@end

// Single texture in RGBX format
@shader sRGBXTextureLayer<mask:,Mask>FS
$LAYER_FRAGMENT<mask>$
uniform sampler2D uTexture;

void main()
{
$FRAGMENT_CALC_MASK<mask>$
  gl_FragColor = vec4(texture2D(uTexture, vTexCoord).rgb, 1.0) * uLayerOpacity * mask; 
}
@end

// Single texture in BGRX format (via swizzle)
@shader sBGRXTextureLayer<mask:,Mask>FS
$LAYER_FRAGMENT<mask>$
uniform sampler2D uTexture;

void main()
{
$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.
//
// Some older versions of the Tegra 2 android driver have a bug
// where arithmetic ops on a texture read are just ignored.  So,
// if the below was |cb = texture2D(...).r - 0.5|, the "- 0.5" was
// just being ignored/skipped.  This, of course, lead to crappy
// rendering -- see bug 765150.  Doing them separately like below
// makes it all OK.  We don't know if this is special to constants,
// special to 0.5, special to addition/subtraction, etc.
@shader sYCbCrTextureLayer<mask:,Mask>FS
$LAYER_FRAGMENT<mask>$
#ifdef GL_ES
precision mediump float;
#endif
uniform sampler2D uYTexture;
uniform sampler2D uCbTexture;
uniform sampler2D uCrTexture;

void main()
{
  vec4 color;

  float y = texture2D(uYTexture, vTexCoord).r;
  float cb = texture2D(uCbTexture, vTexCoord).r;
  float cr = texture2D(uCrTexture, vTexCoord).r;

  y = (y - 0.0625) * 1.164;
  cb = cb - 0.5;
  cr = cr - 0.5;

  color.r = y + cr * 1.596;
  color.g = y - 0.813 * cr - 0.391 * cb;
  color.b = y + cb * 2.018;
  color.a = 1.0;
$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
// blitting the contents of a FBO-rendered texture to a destination.
//
// There are two variants of the fragment shader: one that uses 2D
// textures and one that uses 2DRect textures (for when
// EXT_TEXTURE_RECTANGLE is used for FBOs).
//
// On GL ES, EXT_TEXTURE_RECTANGLE isn't available, so we still
// compile the shader but have it render pure red.  It should never
// be used.
//

@shader sCopyVS
/* Vertex Shader */

attribute vec4 aVertexCoord;
attribute vec2 aTexCoord;

varying vec2 vTexCoord;

void main()
{
  gl_Position = aVertexCoord;
  vTexCoord = aTexCoord;
}
@end

@shader sCopy2DFS
$FRAGMENT_SHADER_HEADER$

varying vec2 vTexCoord;

uniform sampler2D uTexture;
void main()
{
  gl_FragColor = texture2D(uTexture, vTexCoord);
}
@end

@shader sCopy2DRectFS
#extension GL_ARB_texture_rectangle : enable

$FRAGMENT_SHADER_HEADER$

varying vec2 vTexCoord;
uniform vec2 uTexCoordMultiplier;

#ifndef GL_ES
uniform sampler2DRect uTexture;
void main()
{
  gl_FragColor = texture2DRect(uTexture, vTexCoord * uTexCoordMultiplier);
}
#else
void main()
{
  gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
#endif
@end

