" gl_FragColor *= alpha; "
"}\n";
+static const char gFragmentShaderInverted[] =
+ "precision mediump float;\n"
+ "varying vec2 v_texCoord; \n"
+ "uniform float alpha; \n"
+ "uniform float contrast; \n"
+ "uniform sampler2D s_texture; \n"
+ "void main() {\n"
+ " vec4 pixel = texture2D(s_texture, v_texCoord); \n"
+ " float a = pixel.a; \n"
+ " float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
+ " color = ((color - a/2.0) * contrast) + a/2.0; \n"
+ " pixel.rgb = vec3(color, color, color); \n "
+ " gl_FragColor = pixel; \n"
+ " gl_FragColor *= alpha; \n"
+ "}\n";
+
static const char gVideoVertexShader[] =
"attribute vec4 vPosition;\n"
"uniform mat4 textureMatrix;\n"
ShaderProgram::ShaderProgram()
: m_blendingEnabled(false)
, m_contrast(1)
+ , m_alphaLayer(false)
+ , m_currentScale(1.0f)
{
init();
}
void ShaderProgram::init()
{
m_program = createProgram(gVertexShader, gFragmentShader);
+ m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted);
m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
m_surfTexOESProgram =
createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
if (m_program == -1
+ || m_programInverted == -1
|| m_videoProgram == -1
|| m_surfTexOESProgram == -1
|| m_surfTexOESProgramInverted == -1)
m_hTexSampler = glGetUniformLocation(m_program, "s_texture");
m_hPosition = glGetAttribLocation(m_program, "vPosition");
+ m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix");
+ m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha");
+ m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
+ m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture");
+ m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition");
+
m_hVideoProjectionMatrix =
glGetUniformLocation(m_videoProgram, "projectionMatrix");
m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix");
// Drawing
/////////////////////////////////////////////////////////////////////////////////////////
-void ShaderProgram::setViewport(SkRect& viewport)
+void ShaderProgram::setViewport(SkRect& viewport, float scale)
{
TransformationMatrix ortho;
GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
viewport.fRight, viewport.fBottom, -1000, 1000);
m_projectionMatrix = ortho;
m_viewport = viewport;
+ m_currentScale = scale;
}
void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
TransformationMatrix scale;
scale.scale3d(geometry.width(), geometry.height(), 1.0);
- TransformationMatrix total = m_projectionMatrix * translate * scale;
+ TransformationMatrix total;
+ if (!m_alphaLayer)
+ total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix
+ * translate * scale;
+ else
+ total = m_projectionMatrix * translate * scale;
GLfloat projectionMatrix[16];
GLUtils::toGLMatrix(projectionMatrix, total);
GLenum textureTarget,
GLint position,
GLint alpha,
+ GLint texFilter,
GLint contrast)
{
glUseProgram(program);
glActiveTexture(GL_TEXTURE0);
glUniform1i(texSampler, 0);
glBindTexture(textureTarget, textureId);
- glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter);
+ glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter);
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
- GLenum textureTarget)
+ GLenum textureTarget, GLint texFilter)
{
if (textureTarget == GL_TEXTURE_2D) {
- drawQuadInternal(geometry, textureId, opacity, m_program,
- m_hProjectionMatrix,
- m_hTexSampler, GL_TEXTURE_2D,
- m_hPosition, alpha());
+ if (!TilesManager::instance()->invertedScreen()) {
+ drawQuadInternal(geometry, textureId, opacity, m_program,
+ m_hProjectionMatrix,
+ m_hTexSampler, GL_TEXTURE_2D,
+ m_hPosition, m_hAlpha, texFilter);
+ } else {
+ // With the new GPU texture upload path, we do not use an FBO
+ // to blit the texture we receive from the TexturesGenerator thread.
+ // To implement inverted rendering, we thus have to do the rendering
+ // live, by using a different shader.
+ drawQuadInternal(geometry, textureId, opacity, m_programInverted,
+ m_hProjectionMatrixInverted,
+ m_hTexSamplerInverted, GL_TEXTURE_2D,
+ m_hPositionInverted, m_hAlphaInverted, texFilter,
+ m_hContrastInverted);
+ }
} else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
&& !TilesManager::instance()->invertedScreen()) {
drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
m_hSTOESProjectionMatrix,
m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
- m_hSTOESPosition, m_hSTOESAlpha);
+ m_hSTOESPosition, m_hSTOESAlpha, texFilter);
} else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
&& TilesManager::instance()->invertedScreen()) {
drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
m_hSTOESProjectionMatrixInverted,
m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
- m_hSTOESContrastInverted);
+ texFilter, m_hSTOESContrastInverted);
}
GLUtils::checkGlError("drawQuad");
}
translate.scale3d(1, -1, 1);
m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
+
+ IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height());
+ m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect);
}
// This function transform a clip rect extracted from the current layer
return m_documentToScreenMatrix.mapRect(rect);
}
+FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect)
+{
+ return m_documentToScreenMatrix.inverse().mapRect(rect);
+}
+
FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
{
FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
- SkRect& geometry, int textureId, float opacity,
- bool forceBlending, GLenum textureTarget)
+ const SkRect& geometry, int textureId,
+ float opacity, bool forceBlending,
+ GLenum textureTarget)
{
TransformationMatrix modifiedDrawMatrix = drawMatrix;
// move the drawing depending on where the texture is on the layer
modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
- TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
+
+ TransformationMatrix renderMatrix;
+ if (!m_alphaLayer)
+ renderMatrix = m_projectionMatrix * m_repositionMatrix
+ * m_webViewMatrix * modifiedDrawMatrix;
+ else
+ renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
GLfloat projectionMatrix[16];
GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
if (textureTarget == GL_TEXTURE_2D) {
- drawLayerQuadInternal(projectionMatrix, textureId, opacity,
- GL_TEXTURE_2D, m_program,
- m_hProjectionMatrix, m_hTexSampler,
- m_hPosition, alpha());
+ if (!TilesManager::instance()->invertedScreen()) {
+ drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+ GL_TEXTURE_2D, m_program,
+ m_hProjectionMatrix, m_hTexSampler,
+ m_hPosition, m_hAlpha);
+ } else {
+ drawLayerQuadInternal(projectionMatrix, textureId, opacity,
+ GL_TEXTURE_2D, m_programInverted,
+ m_hProjectionMatrixInverted, m_hTexSamplerInverted,
+ m_hPositionInverted, m_hAlphaInverted,
+ m_hContrastInverted);
+ }
} else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
&& !TilesManager::instance()->invertedScreen()) {
drawLayerQuadInternal(projectionMatrix, textureId, opacity,
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
}
+void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer)
+{
+ GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix);
+ m_alphaLayer = alphaLayer;
+}
+
+void ShaderProgram::calculateAnimationDelta()
+{
+ // The matrix contains the scrolling info, so this rect is starting from
+ // the m_viewport.
+ // So we just need to map the webview's visible rect using the matrix,
+ // calculate the difference b/t transformed rect and the webViewRect,
+ // then we can get the delta x , y caused by the animation.
+ // Note that the Y is for reporting back to GL viewport, so it is inverted.
+ // When it is alpha animation, then we rely on the framework implementation
+ // such that there is no matrix applied in native webkit.
+ if (!m_alphaLayer) {
+ FloatRect rect(m_viewport.fLeft * m_currentScale,
+ m_viewport.fTop * m_currentScale,
+ m_webViewRect.width(),
+ m_webViewRect.height());
+ rect = m_webViewMatrix.mapRect(rect);
+ m_animationDelta.setX(rect.x() - m_webViewRect.x() );
+ m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y()
+ - m_webViewRect.height() - m_titleBarHeight);
+
+ m_repositionMatrix.makeIdentity();
+ m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0);
+ m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0);
+ m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0);
+ } else {
+ m_animationDelta.setX(0);
+ m_animationDelta.setY(0);
+ m_repositionMatrix.makeIdentity();
+ }
+
+}
+
} // namespace WebCore
#endif // USE(ACCELERATED_COMPOSITING)