• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
loadShader(GLenum shaderType,const char * pSource)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 
createProgram(const char * pVertexSource,const char * pFragmentSource)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 
ShaderProgram()195 ShaderProgram::ShaderProgram()
196     : m_blendingEnabled(false)
197     , m_contrast(1)
198 {
199     init();
200 }
201 
init()202 void ShaderProgram::init()
203 {
204     m_program = createProgram(gVertexShader, gFragmentShader);
205     m_programInverted = createProgram(gVertexShader, gFragmentShaderInverted);
206     m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
207     m_surfTexOESProgram =
208         createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
209     m_surfTexOESProgramInverted =
210         createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
211 
212     if (m_program == -1
213         || m_programInverted == -1
214         || m_videoProgram == -1
215         || m_surfTexOESProgram == -1
216         || m_surfTexOESProgramInverted == -1)
217         return;
218 
219     m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix");
220     m_hAlpha = glGetUniformLocation(m_program, "alpha");
221     m_hTexSampler = glGetUniformLocation(m_program, "s_texture");
222     m_hPosition = glGetAttribLocation(m_program, "vPosition");
223 
224     m_hProjectionMatrixInverted = glGetUniformLocation(m_programInverted, "projectionMatrix");
225     m_hAlphaInverted = glGetUniformLocation(m_programInverted, "alpha");
226     m_hContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
227     m_hTexSamplerInverted = glGetUniformLocation(m_programInverted, "s_texture");
228     m_hPositionInverted = glGetAttribLocation(m_programInverted, "vPosition");
229 
230     m_hVideoProjectionMatrix =
231         glGetUniformLocation(m_videoProgram, "projectionMatrix");
232     m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix");
233     m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture");
234     m_hVideoPosition = glGetAttribLocation(m_program, "vPosition");
235 
236     m_hSTOESProjectionMatrix =
237         glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix");
238     m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha");
239     m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture");
240     m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition");
241 
242     m_hSTOESProjectionMatrixInverted =
243         glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix");
244     m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha");
245     m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
246     m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture");
247     m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition");
248 
249 
250     const GLfloat coord[] = {
251         0.0f, 0.0f, // C
252         1.0f, 0.0f, // D
253         0.0f, 1.0f, // A
254         1.0f, 1.0f // B
255     };
256 
257     glGenBuffers(1, m_textureBuffer);
258     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
259     glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW);
260 
261     GLUtils::checkGlError("init");
262 }
263 
resetBlending()264 void ShaderProgram::resetBlending()
265 {
266     glDisable(GL_BLEND);
267     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
268     glBlendEquation(GL_FUNC_ADD);
269     m_blendingEnabled = false;
270 }
271 
setBlendingState(bool enableBlending)272 void ShaderProgram::setBlendingState(bool enableBlending)
273 {
274     if (enableBlending == m_blendingEnabled)
275         return;
276 
277     if (enableBlending)
278         glEnable(GL_BLEND);
279     else
280         glDisable(GL_BLEND);
281 
282     m_blendingEnabled = enableBlending;
283 }
284 
285 /////////////////////////////////////////////////////////////////////////////////////////
286 // Drawing
287 /////////////////////////////////////////////////////////////////////////////////////////
288 
setViewport(SkRect & viewport)289 void ShaderProgram::setViewport(SkRect& viewport)
290 {
291     TransformationMatrix ortho;
292     GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
293                                    viewport.fRight, viewport.fBottom, -1000, 1000);
294     m_projectionMatrix = ortho;
295     m_viewport = viewport;
296 }
297 
setProjectionMatrix(SkRect & geometry,GLint projectionMatrixHandle)298 void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
299 {
300     TransformationMatrix translate;
301     translate.translate3d(geometry.fLeft, geometry.fTop, 0.0);
302     TransformationMatrix scale;
303     scale.scale3d(geometry.width(), geometry.height(), 1.0);
304 
305     TransformationMatrix total = m_projectionMatrix * translate * scale;
306 
307     GLfloat projectionMatrix[16];
308     GLUtils::toGLMatrix(projectionMatrix, total);
309     glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
310 }
311 
drawQuadInternal(SkRect & geometry,GLint textureId,float opacity,GLint program,GLint projectionMatrixHandle,GLint texSampler,GLenum textureTarget,GLint position,GLint alpha,GLint texFilter,GLint contrast)312 void ShaderProgram::drawQuadInternal(SkRect& geometry,
313                                      GLint textureId,
314                                      float opacity,
315                                      GLint program,
316                                      GLint projectionMatrixHandle,
317                                      GLint texSampler,
318                                      GLenum textureTarget,
319                                      GLint position,
320                                      GLint alpha,
321                                      GLint texFilter,
322                                      GLint contrast)
323 {
324     glUseProgram(program);
325 
326     if (!geometry.isEmpty())
327          setProjectionMatrix(geometry, projectionMatrixHandle);
328     else {
329         TransformationMatrix matrix;
330         // Map x,y from (0,1) to (-1, 1)
331         matrix.scale3d(2, 2, 1);
332         matrix.translate3d(-0.5, -0.5, 0);
333         GLfloat projectionMatrix[16];
334         GLUtils::toGLMatrix(projectionMatrix, matrix);
335         glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
336     }
337 
338     glActiveTexture(GL_TEXTURE0);
339     glUniform1i(texSampler, 0);
340     glBindTexture(textureTarget, textureId);
341     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, texFilter);
342     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, texFilter);
343     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
344     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
345 
346     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
347     glEnableVertexAttribArray(position);
348     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
349     glUniform1f(alpha, opacity);
350     if (contrast != -1)
351         glUniform1f(contrast, m_contrast);
352 
353     setBlendingState(opacity < 1.0);
354     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
355 }
356 
drawQuad(SkRect & geometry,int textureId,float opacity,GLenum textureTarget,GLint texFilter)357 void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
358                              GLenum textureTarget, GLint texFilter)
359 {
360     if (textureTarget == GL_TEXTURE_2D) {
361         if (!TilesManager::instance()->invertedScreen()) {
362             drawQuadInternal(geometry, textureId, opacity, m_program,
363                              m_hProjectionMatrix,
364                              m_hTexSampler, GL_TEXTURE_2D,
365                              m_hPosition, m_hAlpha, texFilter);
366         } else {
367             // With the new GPU texture upload path, we do not use an FBO
368             // to blit the texture we receive from the TexturesGenerator thread.
369             // To implement inverted rendering, we thus have to do the rendering
370             // live, by using a different shader.
371             drawQuadInternal(geometry, textureId, opacity, m_programInverted,
372                              m_hProjectionMatrixInverted,
373                              m_hTexSamplerInverted, GL_TEXTURE_2D,
374                              m_hPositionInverted, m_hAlphaInverted, texFilter,
375                              m_hContrastInverted);
376         }
377     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
378                && !TilesManager::instance()->invertedScreen()) {
379         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
380                          m_hSTOESProjectionMatrix,
381                          m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
382                          m_hSTOESPosition, m_hSTOESAlpha, texFilter);
383     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
384                && TilesManager::instance()->invertedScreen()) {
385         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
386                          m_hSTOESProjectionMatrixInverted,
387                          m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
388                          m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
389                          texFilter, m_hSTOESContrastInverted);
390     }
391     GLUtils::checkGlError("drawQuad");
392 }
393 
setViewRect(const IntRect & viewRect)394 void ShaderProgram::setViewRect(const IntRect& viewRect)
395 {
396     m_viewRect = viewRect;
397 
398     // We do clipping using glScissor, which needs to take
399     // coordinates in screen space. The following matrix transform
400     // content coordinates in screen coordinates.
401     TransformationMatrix translate;
402     translate.translate(1.0, 1.0);
403 
404     TransformationMatrix scale;
405     scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1);
406 
407     m_documentToScreenMatrix = scale * translate * m_projectionMatrix;
408 
409     translate.scale3d(1, -1, 1);
410     m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
411 }
412 
413 // This function transform a clip rect extracted from the current layer
414 // into a clip rect in screen coordinates -- used by the clipping rects
rectInScreenCoord(const TransformationMatrix & drawMatrix,const IntSize & size)415 FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
416 {
417     FloatRect srect(0, 0, size.width(), size.height());
418     TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix;
419     return renderMatrix.mapRect(srect);
420 }
421 
422 // used by the partial screen invals
rectInInvScreenCoord(const TransformationMatrix & drawMatrix,const IntSize & size)423 FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
424 {
425     FloatRect srect(0, 0, size.width(), size.height());
426     TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix;
427     return renderMatrix.mapRect(srect);
428 }
429 
rectInInvScreenCoord(const FloatRect & rect)430 FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect)
431 {
432     return m_documentToInvScreenMatrix.mapRect(rect);
433 }
434 
rectInScreenCoord(const FloatRect & rect)435 FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
436 {
437     return m_documentToScreenMatrix.mapRect(rect);
438 }
439 
convertInvScreenCoordToScreenCoord(const FloatRect & rect)440 FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
441 {
442     FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
443     return rectInScreenCoord(documentRect);
444 }
445 
convertScreenCoordToInvScreenCoord(const FloatRect & rect)446 FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect)
447 {
448     FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect);
449     return rectInInvScreenCoord(documentRect);
450 }
451 
setScreenClip(const IntRect & clip)452 void ShaderProgram::setScreenClip(const IntRect& clip)
453 {
454     m_screenClip = clip;
455     IntRect mclip = clip;
456 
457     // the clip from frameworks is in full screen coordinates
458     mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight);
459     FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip);
460     IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height());
461     m_screenClip = screenClip;
462 }
463 
464 // clip is in screen coordinates
clip(const FloatRect & clip)465 void ShaderProgram::clip(const FloatRect& clip)
466 {
467     if (clip == m_clipRect)
468         return;
469 
470     // we should only call glScissor in this function, so that we can easily
471     // track the current clipping rect.
472 
473     IntRect screenClip(clip.x(),
474                        clip.y(),
475                        clip.width(), clip.height());
476 
477     if (!m_screenClip.isEmpty())
478         screenClip.intersect(m_screenClip);
479 
480     screenClip.setY(screenClip.y() + m_viewRect.y());
481     if (screenClip.x() < 0) {
482         int w = screenClip.width();
483         w += screenClip.x();
484         screenClip.setX(0);
485         screenClip.setWidth(w);
486     }
487     if (screenClip.y() < 0) {
488         int h = screenClip.height();
489         h += screenClip.y();
490         screenClip.setY(0);
491         screenClip.setHeight(h);
492     }
493 
494     glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
495 
496     m_clipRect = clip;
497 }
498 
clippedRectWithViewport(const IntRect & rect,int margin)499 IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin)
500 {
501     IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin,
502                      m_viewport.width() + margin, m_viewport.height() + margin);
503     viewport.intersect(rect);
504     return viewport;
505 }
506 
zValue(const TransformationMatrix & drawMatrix,float w,float h)507 float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
508 {
509     TransformationMatrix modifiedDrawMatrix = drawMatrix;
510     modifiedDrawMatrix.scale3d(w, h, 1);
511     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
512     FloatPoint3D point(0.5, 0.5, 0.0);
513     FloatPoint3D result = renderMatrix.mapPoint(point);
514     return result.z();
515 }
516 
drawLayerQuadInternal(const GLfloat * projectionMatrix,int textureId,float opacity,GLenum textureTarget,GLint program,GLint matrix,GLint texSample,GLint position,GLint alpha,GLint contrast)517 void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
518                                           int textureId, float opacity,
519                                           GLenum textureTarget, GLint program,
520                                           GLint matrix, GLint texSample,
521                                           GLint position, GLint alpha,
522                                           GLint contrast)
523 {
524     glUseProgram(program);
525     glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix);
526 
527     glActiveTexture(GL_TEXTURE0);
528     glUniform1i(texSample, 0);
529     glBindTexture(textureTarget, textureId);
530     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
531     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
532     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
533     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
534 
535 
536     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
537     glEnableVertexAttribArray(position);
538     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
539     glUniform1f(alpha, opacity);
540     if (contrast != -1)
541         glUniform1f(contrast, m_contrast);
542 }
543 
544 
drawLayerQuad(const TransformationMatrix & drawMatrix,const SkRect & geometry,int textureId,float opacity,bool forceBlending,GLenum textureTarget)545 void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
546                                   const SkRect& geometry, int textureId,
547                                   float opacity, bool forceBlending,
548                                   GLenum textureTarget)
549 {
550 
551     TransformationMatrix modifiedDrawMatrix = drawMatrix;
552     // move the drawing depending on where the texture is on the layer
553     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
554     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
555     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
556 
557     GLfloat projectionMatrix[16];
558     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
559     if (textureTarget == GL_TEXTURE_2D) {
560         if (!TilesManager::instance()->invertedScreen()) {
561             drawLayerQuadInternal(projectionMatrix, textureId, opacity,
562                                   GL_TEXTURE_2D, m_program,
563                                   m_hProjectionMatrix, m_hTexSampler,
564                                   m_hPosition, m_hAlpha);
565         } else {
566             drawLayerQuadInternal(projectionMatrix, textureId, opacity,
567                                   GL_TEXTURE_2D, m_programInverted,
568                                   m_hProjectionMatrixInverted, m_hTexSamplerInverted,
569                                   m_hPositionInverted, m_hAlphaInverted,
570                                   m_hContrastInverted);
571         }
572     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
573                && !TilesManager::instance()->invertedScreen()) {
574         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
575                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram,
576                               m_hSTOESProjectionMatrix, m_hSTOESTexSampler,
577                               m_hSTOESPosition, m_hSTOESAlpha);
578     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
579                && TilesManager::instance()->invertedScreen()) {
580         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
581                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted,
582                               m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted,
583                               m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
584                               m_hSTOESContrastInverted);
585     }
586 
587     setBlendingState(forceBlending || opacity < 1.0);
588     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
589 
590     GLUtils::checkGlError("drawLayerQuad");
591 }
592 
drawVideoLayerQuad(const TransformationMatrix & drawMatrix,float * textureMatrix,SkRect & geometry,int textureId)593 void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
594                                        float* textureMatrix, SkRect& geometry,
595                                        int textureId)
596 {
597     // switch to our custom yuv video rendering program
598     glUseProgram(m_videoProgram);
599 
600     TransformationMatrix modifiedDrawMatrix = drawMatrix;
601     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
602     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
603     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
604 
605     GLfloat projectionMatrix[16];
606     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
607     glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix);
608     glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix);
609 
610     glActiveTexture(GL_TEXTURE0);
611     glUniform1i(m_hVideoTexSampler, 0);
612     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
613 
614     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
615     glEnableVertexAttribArray(m_hVideoPosition);
616     glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
617 
618     setBlendingState(false);
619     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
620 }
621 
622 } // namespace WebCore
623 
624 #endif // USE(ACCELERATED_COMPOSITING)
625