cc: Clamp texture coordinates in all tile shaders

Since we can draw quads with a texel:pixel ratio < 1, linear
filtering can cause us to blend texels in that don't have
valid content if we don't clamp texture sampling to the middle
of boundary texels.

Clamping was already done for the anti-aliasing tile shaders.
This patch adds clamping to all tile shaders.

BUG=170722
NOTRY=True

Review URL: https://codereview.chromium.org/12086036

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@179752 0039d316-1c4b-4281-b951-d872f2087c98
parent 3c8c7950
......@@ -873,18 +873,8 @@ void GLRenderer::drawTileQuad(const DrawingFrame& frame, const TileDrawQuad* qua
// We should not DCHECK(!clipped) here, because anti-aliasing inflation may cause deviceQuad to become
// clipped. To our knowledge this scenario does not need to be handled differently than the unclipped case.
} else {
// Move fragment shader transform to vertex shader. We can do this while
// still producing correct results as fragmentTexTransformLocation
// should always be non-negative when tiles are transformed in a way
// that could result in sampling outside the layer.
vertexTexScaleX *= fragmentTexScaleX;
vertexTexScaleY *= fragmentTexScaleY;
vertexTexTranslateX *= fragmentTexScaleX;
vertexTexTranslateY *= fragmentTexScaleY;
vertexTexTranslateX += fragmentTexTranslateX;
vertexTexTranslateY += fragmentTexTranslateY;
GLC(context(), context()->uniform4f(uniforms.vertexTexTransformLocation, vertexTexTranslateX, vertexTexTranslateY, vertexTexScaleX, vertexTexScaleY));
GLC(context(), context()->uniform4f(uniforms.fragmentTexTransformLocation, fragmentTexTranslateX, fragmentTexTranslateY, fragmentTexScaleX, fragmentTexScaleY));
localQuad = gfx::RectF(tileRect);
}
......
......@@ -144,12 +144,12 @@ private:
// This block of bindings defines all of the programs used by the compositor itself.
// Tiled layer shaders.
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexAlpha> TileProgram;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampAlpha> TileProgram;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampAlphaAA> TileProgramAA;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampSwizzleAlphaAA> TileProgramSwizzleAA;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexOpaque> TileProgramOpaque;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleAlpha> TileProgramSwizzle;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexSwizzleOpaque> TileProgramSwizzleOpaque;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampOpaque> TileProgramOpaque;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampSwizzleAlpha> TileProgramSwizzle;
typedef ProgramBinding<VertexShaderTile, FragmentShaderRGBATexClampSwizzleOpaque> TileProgramSwizzleOpaque;
typedef ProgramBinding<VertexShaderPosTex, FragmentShaderCheckerboard> TileCheckerboardProgram;
// Render surface shaders.
......
......@@ -345,6 +345,31 @@ void FragmentTexAlphaBinding::init(WebGraphicsContext3D* context, unsigned progr
DCHECK(m_samplerLocation != -1 && m_alphaLocation != -1);
}
FragmentTexClampAlphaBinding::FragmentTexClampAlphaBinding()
: m_samplerLocation(-1)
, m_alphaLocation(-1)
, m_fragmentTexTransformLocation(-1)
{
}
void FragmentTexClampAlphaBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex)
{
static const char* shaderUniforms[] = {
"s_texture",
"alpha",
"fragmentTexTransform",
};
int locations[3];
getProgramUniformLocations(context, program, shaderUniforms, arraysize(shaderUniforms), arraysize(locations), locations, usingBindUniform, baseUniformIndex);
m_samplerLocation = locations[0];
m_alphaLocation = locations[1];
m_fragmentTexTransformLocation = locations[2];
DCHECK(m_samplerLocation != -1 && m_alphaLocation != -1);
}
FragmentTexOpaqueBinding::FragmentTexOpaqueBinding()
: m_samplerLocation(-1)
{
......@@ -363,6 +388,27 @@ void FragmentTexOpaqueBinding::init(WebGraphicsContext3D* context, unsigned prog
DCHECK(m_samplerLocation != -1);
}
FragmentTexClampOpaqueBinding::FragmentTexClampOpaqueBinding()
: m_samplerLocation(-1)
, m_fragmentTexTransformLocation(-1)
{
}
void FragmentTexClampOpaqueBinding::init(WebGraphicsContext3D* context, unsigned program, bool usingBindUniform, int* baseUniformIndex)
{
static const char* shaderUniforms[] = {
"s_texture",
"fragmentTexTransform",
};
int locations[2];
getProgramUniformLocations(context, program, shaderUniforms, arraysize(shaderUniforms), arraysize(locations), locations, usingBindUniform, baseUniformIndex);
m_samplerLocation = locations[0];
m_fragmentTexTransformLocation = locations[1];
DCHECK(m_samplerLocation != -1);
}
std::string FragmentShaderRGBATexFlipVaryingAlpha::getShaderString() const
{
return SHADER(
......@@ -420,6 +466,24 @@ std::string FragmentShaderRGBATexAlpha::getShaderString() const
);
}
std::string FragmentShaderRGBATexClampAlpha::getShaderString() const
{
return SHADER(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
uniform float alpha;
uniform vec4 fragmentTexTransform;
void main()
{
vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy;
vec4 texColor = texture2D(s_texture, texCoord);
gl_FragColor = texColor * alpha;
}
);
}
std::string FragmentShaderRGBATexVaryingAlpha::getShaderString() const
{
return SHADER(
......@@ -466,15 +530,17 @@ std::string FragmentShaderRGBATexRectVaryingAlpha::getShaderString() const
"}\n";
}
std::string FragmentShaderRGBATexOpaque::getShaderString() const
std::string FragmentShaderRGBATexClampOpaque::getShaderString() const
{
return SHADER(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
uniform vec4 fragmentTexTransform;
void main()
{
vec4 texColor = texture2D(s_texture, v_texCoord);
vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy;
vec4 texColor = texture2D(s_texture, texCoord);
gl_FragColor = vec4(texColor.rgb, 1.0);
}
);
......@@ -493,30 +559,34 @@ std::string FragmentShaderRGBATex::getShaderString() const
);
}
std::string FragmentShaderRGBATexSwizzleAlpha::getShaderString() const
std::string FragmentShaderRGBATexClampSwizzleAlpha::getShaderString() const
{
return SHADER(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
uniform float alpha;
uniform vec4 fragmentTexTransform;
void main()
{
vec4 texColor = texture2D(s_texture, v_texCoord);
vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy;
vec4 texColor = texture2D(s_texture, texCoord);
gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, texColor.w) * alpha;
}
);
}
std::string FragmentShaderRGBATexSwizzleOpaque::getShaderString() const
std::string FragmentShaderRGBATexClampSwizzleOpaque::getShaderString() const
{
return SHADER(
precision mediump float;
varying vec2 v_texCoord;
uniform sampler2D s_texture;
uniform vec4 fragmentTexTransform;
void main()
{
vec4 texColor = texture2D(s_texture, v_texCoord);
vec2 texCoord = clamp(v_texCoord, 0.0, 1.0) * fragmentTexTransform.zw + fragmentTexTransform.xy;
vec4 texColor = texture2D(s_texture, texCoord);
gl_FragColor = vec4(texColor.z, texColor.y, texColor.x, 1.0);
}
);
......
......@@ -142,6 +142,22 @@ private:
int m_alphaLocation;
};
class FragmentTexClampAlphaBinding {
public:
FragmentTexClampAlphaBinding();
void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex);
int alphaLocation() const { return m_alphaLocation; }
int edgeLocation() const { return -1; }
int fragmentTexTransformLocation() const { return m_fragmentTexTransformLocation; }
int samplerLocation() const { return m_samplerLocation; }
private:
int m_samplerLocation;
int m_alphaLocation;
int m_fragmentTexTransformLocation;
};
class FragmentTexOpaqueBinding {
public:
FragmentTexOpaqueBinding();
......@@ -156,6 +172,21 @@ private:
int m_samplerLocation;
};
class FragmentTexClampOpaqueBinding {
public:
FragmentTexClampOpaqueBinding();
void init(WebKit::WebGraphicsContext3D*, unsigned program, bool usingBindUniform, int* baseUniformIndex);
int alphaLocation() const { return -1; }
int edgeLocation() const { return -1; }
int fragmentTexTransformLocation() const { return m_fragmentTexTransformLocation; }
int samplerLocation() const { return m_samplerLocation; }
private:
int m_samplerLocation;
int m_fragmentTexTransformLocation;
};
class FragmentShaderRGBATexFlipVaryingAlpha : public FragmentTexOpaqueBinding {
public:
std::string getShaderString() const;
......@@ -171,6 +202,11 @@ public:
std::string getShaderString() const;
};
class FragmentShaderRGBATexClampAlpha : public FragmentTexClampAlphaBinding {
public:
std::string getShaderString() const;
};
class FragmentShaderRGBATexRectFlipVaryingAlpha : public FragmentTexAlphaBinding {
public:
std::string getShaderString() const;
......@@ -181,7 +217,7 @@ public:
std::string getShaderString() const;
};
class FragmentShaderRGBATexOpaque : public FragmentTexOpaqueBinding {
class FragmentShaderRGBATexClampOpaque : public FragmentTexClampOpaqueBinding {
public:
std::string getShaderString() const;
};
......@@ -192,13 +228,13 @@ public:
};
// Swizzles the red and blue component of sampled texel with alpha.
class FragmentShaderRGBATexSwizzleAlpha : public FragmentTexAlphaBinding {
class FragmentShaderRGBATexClampSwizzleAlpha : public FragmentTexClampAlphaBinding {
public:
std::string getShaderString() const;
};
// Swizzles the red and blue component of sampled texel without alpha.
class FragmentShaderRGBATexSwizzleOpaque : public FragmentTexOpaqueBinding {
class FragmentShaderRGBATexClampSwizzleOpaque : public FragmentTexClampOpaqueBinding {
public:
std::string getShaderString() const;
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment