Home | History | Annotate | Download | only in android
      1 /*
      2  * Copyright 2010, The Android Open Source Project
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *  * Redistributions of source code must retain the above copyright
      8  *    notice, this list of conditions and the following disclaimer.
      9  *  * Redistributions in binary form must reproduce the above copyright
     10  *    notice, this list of conditions and the following disclaimer in the
     11  *    documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #include "config.h"
     27 #include "ShaderProgram.h"
     28 
     29 #if USE(ACCELERATED_COMPOSITING)
     30 
     31 #include "FloatPoint3D.h"
     32 #include "GLUtils.h"
     33 #include "TilesManager.h"
     34 
     35 #include <GLES2/gl2.h>
     36 #include <GLES2/gl2ext.h>
     37 #include <cutils/log.h>
     38 #include <wtf/CurrentTime.h>
     39 #include <wtf/text/CString.h>
     40 
     41 #undef XLOG
     42 #define XLOG(...) android_printLog(ANDROID_LOG_DEBUG, "ShaderProgram", __VA_ARGS__)
     43 
     44 namespace WebCore {
     45 
     46 static const char gVertexShader[] =
     47     "attribute vec4 vPosition;\n"
     48     "uniform mat4 projectionMatrix;\n"
     49     "varying vec2 v_texCoord;\n"
     50     "void main() {\n"
     51     "  gl_Position = projectionMatrix * vPosition;\n"
     52     "  v_texCoord = vec2(vPosition);\n"
     53     "}\n";
     54 
     55 static const char gFragmentShader[] =
     56     "precision mediump float;\n"
     57     "varying vec2 v_texCoord; \n"
     58     "uniform float alpha; \n"
     59     "uniform sampler2D s_texture; \n"
     60     "void main() {\n"
     61     "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
     62     "  gl_FragColor *= alpha; "
     63     "}\n";
     64 
     65 static const char gFragmentShaderInverted[] =
     66     "precision mediump float;\n"
     67     "varying vec2 v_texCoord; \n"
     68     "uniform float alpha; \n"
     69     "uniform float contrast; \n"
     70     "uniform sampler2D s_texture; \n"
     71     "void main() {\n"
     72     "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
     73     "  float a = pixel.a; \n"
     74     "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
     75     "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
     76     "  pixel.rgb = vec3(color, color, color); \n "
     77     "  gl_FragColor = pixel; \n"
     78     "  gl_FragColor *= alpha; \n"
     79     "}\n";
     80 
     81 static const char gVideoVertexShader[] =
     82     "attribute vec4 vPosition;\n"
     83     "uniform mat4 textureMatrix;\n"
     84     "uniform mat4 projectionMatrix;\n"
     85     "varying vec2 v_texCoord;\n"
     86     "void main() {\n"
     87     "  gl_Position = projectionMatrix * vPosition;\n"
     88     "  v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n"
     89     "}\n";
     90 
     91 static const char gVideoFragmentShader[] =
     92     "#extension GL_OES_EGL_image_external : require\n"
     93     "precision mediump float;\n"
     94     "uniform samplerExternalOES s_yuvTexture;\n"
     95     "varying vec2 v_texCoord;\n"
     96     "void main() {\n"
     97     "  gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n"
     98     "}\n";
     99 
    100 static const char gSurfaceTextureOESFragmentShader[] =
    101     "#extension GL_OES_EGL_image_external : require\n"
    102     "precision mediump float;\n"
    103     "varying vec2 v_texCoord; \n"
    104     "uniform float alpha; \n"
    105     "uniform samplerExternalOES s_texture; \n"
    106     "void main() {\n"
    107     "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
    108     "  gl_FragColor *= alpha; "
    109     "}\n";
    110 
    111 static const char gSurfaceTextureOESFragmentShaderInverted[] =
    112     "#extension GL_OES_EGL_image_external : require\n"
    113     "precision mediump float;\n"
    114     "varying vec2 v_texCoord; \n"
    115     "uniform float alpha; \n"
    116     "uniform float contrast; \n"
    117     "uniform samplerExternalOES s_texture; \n"
    118     "void main() {\n"
    119     "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
    120     "  float a = pixel.a; \n"
    121     "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
    122     "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
    123     "  pixel.rgb = vec3(color, color, color); \n "
    124     "  gl_FragColor = pixel; \n"
    125     "  gl_FragColor *= alpha; \n"
    126     "}\n";
    127 
    128 GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource)
    129 {
    130     GLuint shader = glCreateShader(shaderType);
    131     if (shader) {
    132         glShaderSource(shader, 1, &pSource, 0);
    133         glCompileShader(shader);
    134         GLint compiled = 0;
    135         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
    136         if (!compiled) {
    137             GLint infoLen = 0;
    138             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
    139             if (infoLen) {
    140                 char* buf = (char*) malloc(infoLen);
    141                 if (buf) {
    142                 glGetShaderInfoLog(shader, infoLen, 0, buf);
    143                 XLOG("could not compile shader %d:\n%s\n", shaderType, buf);
    144                 free(buf);
    145             }
    146             glDeleteShader(shader);
    147             shader = 0;
    148             }
    149         }
    150     }
    151     return shader;
    152 }
    153 
    154 GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource)
    155 {
    156     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
    157     if (!vertexShader) {
    158         XLOG("couldn't load the vertex shader!");
    159         return -1;
    160     }
    161 
    162     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
    163     if (!pixelShader) {
    164         XLOG("couldn't load the pixel shader!");
    165         return -1;
    166     }
    167 
    168     GLuint program = glCreateProgram();
    169     if (program) {
    170         glAttachShader(program, vertexShader);
    171         GLUtils::checkGlError("glAttachShader vertex");
    172         glAttachShader(program, pixelShader);
    173         GLUtils::checkGlError("glAttachShader pixel");
    174         glLinkProgram(program);
    175         GLint linkStatus = GL_FALSE;
    176         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
    177         if (linkStatus != GL_TRUE) {
    178             GLint bufLength = 0;
    179             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
    180             if (bufLength) {
    181                 char* buf = (char*) malloc(bufLength);
    182                 if (buf) {
    183                     glGetProgramInfoLog(program, bufLength, 0, buf);
    184                     XLOG("could not link program:\n%s\n", buf);
    185                     free(buf);
    186                 }
    187             }
    188             glDeleteProgram(program);
    189             program = -1;
    190         }
    191     }
    192     return program;
    193 }
    194 
    195 ShaderProgram::ShaderProgram()
    196     : m_blendingEnabled(false)
    197     , m_contrast(1)
    198     , m_alphaLayer(false)
    199     , m_currentScale(1.0f)
    200 {
    201     init();
    202 }
    203 
    204 void ShaderProgram::init()
    205 {
    206     m_program = createProgram(gVertexShader, gFragmentShader);
    207     m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted);
    208     m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
    209     m_surfTexOESProgram =
    210         createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
    211     m_surfTexOESProgramInverted =
    212         createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
    213 
    214     if (m_program == -1
    215         || m_programInverted == -1
    216         || m_videoProgram == -1
    217         || m_surfTexOESProgram == -1
    218         || m_surfTexOESProgramInverted == -1)
    219         return;
    220 
    221     m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix");
    222     m_hAlpha = glGetUniformLocation(m_program, "alpha");
    223     m_hTexSampler = glGetUniformLocation(m_program, "s_texture");
    224     m_hPosition = glGetAttribLocation(m_program, "vPosition");
    225 
    226     m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix");
    227     m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha");
    228     m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
    229     m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture");
    230     m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition");
    231 
    232     m_hVideoProjectionMatrix =
    233         glGetUniformLocation(m_videoProgram, "projectionMatrix");
    234     m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix");
    235     m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture");
    236     m_hVideoPosition = glGetAttribLocation(m_program, "vPosition");
    237 
    238     m_hSTOESProjectionMatrix =
    239         glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix");
    240     m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha");
    241     m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture");
    242     m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition");
    243 
    244     m_hSTOESProjectionMatrixInverted =
    245         glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix");
    246     m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha");
    247     m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
    248     m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture");
    249     m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition");
    250 
    251 
    252     const GLfloat coord[] = {
    253         0.0f, 0.0f, // C
    254         1.0f, 0.0f, // D
    255         0.0f, 1.0f, // A
    256         1.0f, 1.0f // B
    257     };
    258 
    259     glGenBuffers(1, m_textureBuffer);
    260     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
    261     glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW);
    262 
    263     GLUtils::checkGlError("init");
    264 }
    265 
    266 void ShaderProgram::resetBlending()
    267 {
    268     glDisable(GL_BLEND);
    269     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    270     glBlendEquation(GL_FUNC_ADD);
    271     m_blendingEnabled = false;
    272 }
    273 
    274 void ShaderProgram::setBlendingState(bool enableBlending)
    275 {
    276     if (enableBlending == m_blendingEnabled)
    277         return;
    278 
    279     if (enableBlending)
    280         glEnable(GL_BLEND);
    281     else
    282         glDisable(GL_BLEND);
    283 
    284     m_blendingEnabled = enableBlending;
    285 }
    286 
    287 /////////////////////////////////////////////////////////////////////////////////////////
    288 // Drawing
    289 /////////////////////////////////////////////////////////////////////////////////////////
    290 
    291 void ShaderProgram::setViewport(SkRect& viewport, float scale)
    292 {
    293     TransformationMatrix ortho;
    294     GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
    295                                    viewport.fRight, viewport.fBottom, -1000, 1000);
    296     m_projectionMatrix = ortho;
    297     m_viewport = viewport;
    298     m_currentScale = scale;
    299 }
    300 
    301 void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
    302 {
    303     TransformationMatrix translate;
    304     translate.translate3d(geometry.fLeft, geometry.fTop, 0.0);
    305     TransformationMatrix scale;
    306     scale.scale3d(geometry.width(), geometry.height(), 1.0);
    307 
    308     TransformationMatrix total;
    309     if (!m_alphaLayer)
    310         total = m_projectionMatrix * m_repositionMatrix * m_webViewMatrix
    311                 * translate * scale;
    312     else
    313         total = m_projectionMatrix * translate * scale;
    314 
    315     GLfloat projectionMatrix[16];
    316     GLUtils::toGLMatrix(projectionMatrix, total);
    317     glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
    318 }
    319 
    320 void ShaderProgram::drawQuadInternal(SkRect& geometry,
    321                                      GLint textureId,
    322                                      float opacity,
    323                                      GLint program,
    324                                      GLint projectionMatrixHandle,
    325                                      GLint texSampler,
    326                                      GLenum textureTarget,
    327                                      GLint position,
    328                                      GLint alpha,
    329                                      GLint texFilter,
    330                                      GLint contrast)
    331 {
    332     glUseProgram(program);
    333 
    334     if (!geometry.isEmpty())
    335          setProjectionMatrix(geometry, projectionMatrixHandle);
    336     else {
    337         TransformationMatrix matrix;
    338         // Map x,y from (0,1) to (-1, 1)
    339         matrix.scale3d(2, 2, 1);
    340         matrix.translate3d(-0.5, -0.5, 0);
    341         GLfloat projectionMatrix[16];
    342         GLUtils::toGLMatrix(projectionMatrix, matrix);
    343         glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
    344     }
    345 
    346     glActiveTexture(GL_TEXTURE0);
    347     glUniform1i(texSampler, 0);
    348     glBindTexture(textureTarget, textureId);
    349     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter);
    350     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter);
    351     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    352     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    353 
    354     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
    355     glEnableVertexAttribArray(position);
    356     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
    357     glUniform1f(alpha, opacity);
    358     if (contrast != -1)
    359         glUniform1f(contrast, m_contrast);
    360 
    361     setBlendingState(opacity < 1.0);
    362     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    363 }
    364 
    365 void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
    366                              GLenum textureTarget, GLint texFilter)
    367 {
    368     if (textureTarget == GL_TEXTURE_2D) {
    369         if (!TilesManager::instance()->invertedScreen()) {
    370             drawQuadInternal(geometry, textureId, opacity, m_program,
    371                              m_hProjectionMatrix,
    372                              m_hTexSampler, GL_TEXTURE_2D,
    373                              m_hPosition, m_hAlpha, texFilter);
    374         } else {
    375             // With the new GPU texture upload path, we do not use an FBO
    376             // to blit the texture we receive from the TexturesGenerator thread.
    377             // To implement inverted rendering, we thus have to do the rendering
    378             // live, by using a different shader.
    379             drawQuadInternal(geometry, textureId, opacity, m_programInverted,
    380                              m_hProjectionMatrixInverted,
    381                              m_hTexSamplerInverted, GL_TEXTURE_2D,
    382                              m_hPositionInverted, m_hAlphaInverted, texFilter,
    383                              m_hContrastInverted);
    384         }
    385     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
    386                && !TilesManager::instance()->invertedScreen()) {
    387         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
    388                          m_hSTOESProjectionMatrix,
    389                          m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
    390                          m_hSTOESPosition, m_hSTOESAlpha, texFilter);
    391     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
    392                && TilesManager::instance()->invertedScreen()) {
    393         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
    394                          m_hSTOESProjectionMatrixInverted,
    395                          m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
    396                          m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
    397                          texFilter, m_hSTOESContrastInverted);
    398     }
    399     GLUtils::checkGlError("drawQuad");
    400 }
    401 
    402 void ShaderProgram::setViewRect(const IntRect& viewRect)
    403 {
    404     m_viewRect = viewRect;
    405 
    406     // We do clipping using glScissor, which needs to take
    407     // coordinates in screen space. The following matrix transform
    408     // content coordinates in screen coordinates.
    409     TransformationMatrix translate;
    410     translate.translate(1.0, 1.0);
    411 
    412     TransformationMatrix scale;
    413     scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1);
    414 
    415     m_documentToScreenMatrix = scale * translate * m_projectionMatrix;
    416 
    417     translate.scale3d(1, -1, 1);
    418     m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
    419 
    420     IntRect rect(0, 0, m_webViewRect.width(), m_webViewRect.height());
    421     m_documentViewport = m_documentToScreenMatrix.inverse().mapRect(rect);
    422 }
    423 
    424 // This function transform a clip rect extracted from the current layer
    425 // into a clip rect in screen coordinates -- used by the clipping rects
    426 FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
    427 {
    428     FloatRect srect(0, 0, size.width(), size.height());
    429     TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix;
    430     return renderMatrix.mapRect(srect);
    431 }
    432 
    433 // used by the partial screen invals
    434 FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
    435 {
    436     FloatRect srect(0, 0, size.width(), size.height());
    437     TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix;
    438     return renderMatrix.mapRect(srect);
    439 }
    440 
    441 FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect)
    442 {
    443     return m_documentToInvScreenMatrix.mapRect(rect);
    444 }
    445 
    446 FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
    447 {
    448     return m_documentToScreenMatrix.mapRect(rect);
    449 }
    450 
    451 FloatRect ShaderProgram::convertScreenCoordToDocumentCoord(const FloatRect& rect)
    452 {
    453     return m_documentToScreenMatrix.inverse().mapRect(rect);
    454 }
    455 
    456 FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
    457 {
    458     FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
    459     return rectInScreenCoord(documentRect);
    460 }
    461 
    462 FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect)
    463 {
    464     FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect);
    465     return rectInInvScreenCoord(documentRect);
    466 }
    467 
    468 void ShaderProgram::setScreenClip(const IntRect& clip)
    469 {
    470     m_screenClip = clip;
    471     IntRect mclip = clip;
    472 
    473     // the clip from frameworks is in full screen coordinates
    474     mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight);
    475     FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip);
    476     IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height());
    477     m_screenClip = screenClip;
    478 }
    479 
    480 // clip is in screen coordinates
    481 void ShaderProgram::clip(const FloatRect& clip)
    482 {
    483     if (clip == m_clipRect)
    484         return;
    485 
    486     // we should only call glScissor in this function, so that we can easily
    487     // track the current clipping rect.
    488 
    489     IntRect screenClip(clip.x(),
    490                        clip.y(),
    491                        clip.width(), clip.height());
    492 
    493     if (!m_screenClip.isEmpty())
    494         screenClip.intersect(m_screenClip);
    495 
    496     screenClip.setY(screenClip.y() + m_viewRect.y());
    497     if (screenClip.x() < 0) {
    498         int w = screenClip.width();
    499         w += screenClip.x();
    500         screenClip.setX(0);
    501         screenClip.setWidth(w);
    502     }
    503     if (screenClip.y() < 0) {
    504         int h = screenClip.height();
    505         h += screenClip.y();
    506         screenClip.setY(0);
    507         screenClip.setHeight(h);
    508     }
    509 
    510     glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
    511 
    512     m_clipRect = clip;
    513 }
    514 
    515 IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin)
    516 {
    517     IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin,
    518                      m_viewport.width() + margin, m_viewport.height() + margin);
    519     viewport.intersect(rect);
    520     return viewport;
    521 }
    522 
    523 float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
    524 {
    525     TransformationMatrix modifiedDrawMatrix = drawMatrix;
    526     modifiedDrawMatrix.scale3d(w, h, 1);
    527     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
    528     FloatPoint3D point(0.5, 0.5, 0.0);
    529     FloatPoint3D result = renderMatrix.mapPoint(point);
    530     return result.z();
    531 }
    532 
    533 void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
    534                                           int textureId, float opacity,
    535                                           GLenum textureTarget, GLint program,
    536                                           GLint matrix, GLint texSample,
    537                                           GLint position, GLint alpha,
    538                                           GLint contrast)
    539 {
    540     glUseProgram(program);
    541     glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix);
    542 
    543     glActiveTexture(GL_TEXTURE0);
    544     glUniform1i(texSample, 0);
    545     glBindTexture(textureTarget, textureId);
    546     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    547     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    548     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    549     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    550 
    551 
    552     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
    553     glEnableVertexAttribArray(position);
    554     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
    555     glUniform1f(alpha, opacity);
    556     if (contrast != -1)
    557         glUniform1f(contrast, m_contrast);
    558 }
    559 
    560 
    561 void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
    562                                   const SkRect& geometry, int textureId,
    563                                   float opacity, bool forceBlending,
    564                                   GLenum textureTarget)
    565 {
    566 
    567     TransformationMatrix modifiedDrawMatrix = drawMatrix;
    568     // move the drawing depending on where the texture is on the layer
    569     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
    570     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
    571 
    572     TransformationMatrix renderMatrix;
    573     if (!m_alphaLayer)
    574         renderMatrix = m_projectionMatrix * m_repositionMatrix
    575                        * m_webViewMatrix * modifiedDrawMatrix;
    576     else
    577         renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
    578 
    579     GLfloat projectionMatrix[16];
    580     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
    581     if (textureTarget == GL_TEXTURE_2D) {
    582         if (!TilesManager::instance()->invertedScreen()) {
    583             drawLayerQuadInternal(projectionMatrix, textureId, opacity,
    584                                   GL_TEXTURE_2D, m_program,
    585                                   m_hProjectionMatrix, m_hTexSampler,
    586                                   m_hPosition, m_hAlpha);
    587         } else {
    588             drawLayerQuadInternal(projectionMatrix, textureId, opacity,
    589                                   GL_TEXTURE_2D, m_programInverted,
    590                                   m_hProjectionMatrixInverted, m_hTexSamplerInverted,
    591                                   m_hPositionInverted, m_hAlphaInverted,
    592                                   m_hContrastInverted);
    593         }
    594     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
    595                && !TilesManager::instance()->invertedScreen()) {
    596         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
    597                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram,
    598                               m_hSTOESProjectionMatrix, m_hSTOESTexSampler,
    599                               m_hSTOESPosition, m_hSTOESAlpha);
    600     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
    601                && TilesManager::instance()->invertedScreen()) {
    602         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
    603                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted,
    604                               m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted,
    605                               m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
    606                               m_hSTOESContrastInverted);
    607     }
    608 
    609     setBlendingState(forceBlending || opacity < 1.0);
    610     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    611 
    612     GLUtils::checkGlError("drawLayerQuad");
    613 }
    614 
    615 void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
    616                                        float* textureMatrix, SkRect& geometry,
    617                                        int textureId)
    618 {
    619     // switch to our custom yuv video rendering program
    620     glUseProgram(m_videoProgram);
    621 
    622     TransformationMatrix modifiedDrawMatrix = drawMatrix;
    623     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
    624     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
    625     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
    626 
    627     GLfloat projectionMatrix[16];
    628     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
    629     glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix);
    630     glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix);
    631 
    632     glActiveTexture(GL_TEXTURE0);
    633     glUniform1i(m_hVideoTexSampler, 0);
    634     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
    635 
    636     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
    637     glEnableVertexAttribArray(m_hVideoPosition);
    638     glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
    639 
    640     setBlendingState(false);
    641     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    642 }
    643 
    644 void ShaderProgram::setWebViewMatrix(const float* matrix, bool alphaLayer)
    645 {
    646     GLUtils::convertToTransformationMatrix(matrix, m_webViewMatrix);
    647     m_alphaLayer = alphaLayer;
    648 }
    649 
    650 void ShaderProgram::calculateAnimationDelta()
    651 {
    652     // The matrix contains the scrolling info, so this rect is starting from
    653     // the m_viewport.
    654     // So we just need to map the webview's visible rect using the matrix,
    655     // calculate the difference b/t transformed rect and the webViewRect,
    656     // then we can get the delta x , y caused by the animation.
    657     // Note that the Y is for reporting back to GL viewport, so it is inverted.
    658     // When it is alpha animation, then we rely on the framework implementation
    659     // such that there is no matrix applied in native webkit.
    660     if (!m_alphaLayer) {
    661         FloatRect rect(m_viewport.fLeft * m_currentScale,
    662                        m_viewport.fTop * m_currentScale,
    663                        m_webViewRect.width(),
    664                        m_webViewRect.height());
    665         rect = m_webViewMatrix.mapRect(rect);
    666         m_animationDelta.setX(rect.x() - m_webViewRect.x() );
    667         m_animationDelta.setY(rect.y() + rect.height() - m_webViewRect.y()
    668                               - m_webViewRect.height() - m_titleBarHeight);
    669 
    670         m_repositionMatrix.makeIdentity();
    671         m_repositionMatrix.translate3d(-m_webViewRect.x(), -m_webViewRect.y() - m_titleBarHeight, 0);
    672         m_repositionMatrix.translate3d(m_viewport.fLeft * m_currentScale, m_viewport.fTop * m_currentScale, 0);
    673         m_repositionMatrix.translate3d(-m_animationDelta.x(), -m_animationDelta.y(), 0);
    674     } else {
    675         m_animationDelta.setX(0);
    676         m_animationDelta.setY(0);
    677         m_repositionMatrix.makeIdentity();
    678     }
    679 
    680 }
    681 
    682 } // namespace WebCore
    683 
    684 #endif // USE(ACCELERATED_COMPOSITING)
    685