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