OSDN Git Service

WebView Animation support
[android-x86/external-webkit.git] / Source / WebCore / platform / graphics / android / ShaderProgram.cpp
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)