OSDN Git Service

Merge "Support drawing the quad in GL_NEAREST mode."
[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 gVideoVertexShader[] =
66     "attribute vec4 vPosition;\n"
67     "uniform mat4 textureMatrix;\n"
68     "uniform mat4 projectionMatrix;\n"
69     "varying vec2 v_texCoord;\n"
70     "void main() {\n"
71     "  gl_Position = projectionMatrix * vPosition;\n"
72     "  v_texCoord = vec2(textureMatrix * vec4(vPosition.x, 1.0 - vPosition.y, 0.0, 1.0));\n"
73     "}\n";
74
75 static const char gVideoFragmentShader[] =
76     "#extension GL_OES_EGL_image_external : require\n"
77     "precision mediump float;\n"
78     "uniform samplerExternalOES s_yuvTexture;\n"
79     "varying vec2 v_texCoord;\n"
80     "void main() {\n"
81     "  gl_FragColor = texture2D(s_yuvTexture, v_texCoord);\n"
82     "}\n";
83
84 static const char gSurfaceTextureOESFragmentShader[] =
85     "#extension GL_OES_EGL_image_external : require\n"
86     "precision mediump float;\n"
87     "varying vec2 v_texCoord; \n"
88     "uniform float alpha; \n"
89     "uniform samplerExternalOES s_texture; \n"
90     "void main() {\n"
91     "  gl_FragColor = texture2D(s_texture, v_texCoord); \n"
92     "  gl_FragColor *= alpha; "
93     "}\n";
94
95 static const char gSurfaceTextureOESFragmentShaderInverted[] =
96     "#extension GL_OES_EGL_image_external : require\n"
97     "precision mediump float;\n"
98     "varying vec2 v_texCoord; \n"
99     "uniform float alpha; \n"
100     "uniform float contrast; \n"
101     "uniform samplerExternalOES s_texture; \n"
102     "void main() {\n"
103     "  vec4 pixel = texture2D(s_texture, v_texCoord); \n"
104     "  float a = pixel.a; \n"
105     "  float color = a - (0.2989 * pixel.r + 0.5866 * pixel.g + 0.1145 * pixel.b);\n"
106     "  color = ((color - a/2.0) * contrast) + a/2.0; \n"
107     "  pixel.rgb = vec3(color, color, color); \n "
108     "  gl_FragColor = pixel; \n"
109     "  gl_FragColor *= alpha; \n"
110     "}\n";
111
112 GLuint ShaderProgram::loadShader(GLenum shaderType, const char* pSource)
113 {
114     GLuint shader = glCreateShader(shaderType);
115     if (shader) {
116         glShaderSource(shader, 1, &pSource, 0);
117         glCompileShader(shader);
118         GLint compiled = 0;
119         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);
120         if (!compiled) {
121             GLint infoLen = 0;
122             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
123             if (infoLen) {
124                 char* buf = (char*) malloc(infoLen);
125                 if (buf) {
126                 glGetShaderInfoLog(shader, infoLen, 0, buf);
127                 XLOG("could not compile shader %d:\n%s\n", shaderType, buf);
128                 free(buf);
129             }
130             glDeleteShader(shader);
131             shader = 0;
132             }
133         }
134     }
135     return shader;
136 }
137
138 GLuint ShaderProgram::createProgram(const char* pVertexSource, const char* pFragmentSource)
139 {
140     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);
141     if (!vertexShader) {
142         XLOG("couldn't load the vertex shader!");
143         return -1;
144     }
145
146     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);
147     if (!pixelShader) {
148         XLOG("couldn't load the pixel shader!");
149         return -1;
150     }
151
152     GLuint program = glCreateProgram();
153     if (program) {
154         glAttachShader(program, vertexShader);
155         GLUtils::checkGlError("glAttachShader vertex");
156         glAttachShader(program, pixelShader);
157         GLUtils::checkGlError("glAttachShader pixel");
158         glLinkProgram(program);
159         GLint linkStatus = GL_FALSE;
160         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
161         if (linkStatus != GL_TRUE) {
162             GLint bufLength = 0;
163             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);
164             if (bufLength) {
165                 char* buf = (char*) malloc(bufLength);
166                 if (buf) {
167                     glGetProgramInfoLog(program, bufLength, 0, buf);
168                     XLOG("could not link program:\n%s\n", buf);
169                     free(buf);
170                 }
171             }
172             glDeleteProgram(program);
173             program = -1;
174         }
175     }
176     return program;
177 }
178
179 ShaderProgram::ShaderProgram()
180     : m_blendingEnabled(false)
181     , m_contrast(1)
182 {
183     init();
184 }
185
186 void ShaderProgram::init()
187 {
188     m_program = createProgram(gVertexShader, gFragmentShader);
189     m_videoProgram = createProgram(gVideoVertexShader, gVideoFragmentShader);
190     m_surfTexOESProgram =
191         createProgram(gVertexShader, gSurfaceTextureOESFragmentShader);
192     m_surfTexOESProgramInverted =
193         createProgram(gVertexShader, gSurfaceTextureOESFragmentShaderInverted);
194
195     if (m_program == -1
196         || m_videoProgram == -1
197         || m_surfTexOESProgram == -1
198         || m_surfTexOESProgramInverted == -1)
199         return;
200
201     m_hProjectionMatrix = glGetUniformLocation(m_program, "projectionMatrix");
202     m_hAlpha = glGetUniformLocation(m_program, "alpha");
203     m_hTexSampler = glGetUniformLocation(m_program, "s_texture");
204     m_hPosition = glGetAttribLocation(m_program, "vPosition");
205
206     m_hVideoProjectionMatrix =
207         glGetUniformLocation(m_videoProgram, "projectionMatrix");
208     m_hVideoTextureMatrix = glGetUniformLocation(m_videoProgram, "textureMatrix");
209     m_hVideoTexSampler = glGetUniformLocation(m_videoProgram, "s_yuvTexture");
210     m_hVideoPosition = glGetAttribLocation(m_program, "vPosition");
211
212     m_hSTOESProjectionMatrix =
213         glGetUniformLocation(m_surfTexOESProgram, "projectionMatrix");
214     m_hSTOESAlpha = glGetUniformLocation(m_surfTexOESProgram, "alpha");
215     m_hSTOESTexSampler = glGetUniformLocation(m_surfTexOESProgram, "s_texture");
216     m_hSTOESPosition = glGetAttribLocation(m_surfTexOESProgram, "vPosition");
217
218     m_hSTOESProjectionMatrixInverted =
219         glGetUniformLocation(m_surfTexOESProgramInverted, "projectionMatrix");
220     m_hSTOESAlphaInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "alpha");
221     m_hSTOESContrastInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "contrast");
222     m_hSTOESTexSamplerInverted = glGetUniformLocation(m_surfTexOESProgramInverted, "s_texture");
223     m_hSTOESPositionInverted = glGetAttribLocation(m_surfTexOESProgramInverted, "vPosition");
224
225
226     const GLfloat coord[] = {
227         0.0f, 0.0f, // C
228         1.0f, 0.0f, // D
229         0.0f, 1.0f, // A
230         1.0f, 1.0f // B
231     };
232
233     glGenBuffers(1, m_textureBuffer);
234     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
235     glBufferData(GL_ARRAY_BUFFER, 2 * 4 * sizeof(GLfloat), coord, GL_STATIC_DRAW);
236
237     GLUtils::checkGlError("init");
238 }
239
240 void ShaderProgram::resetBlending()
241 {
242     glDisable(GL_BLEND);
243     glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
244     glBlendEquation(GL_FUNC_ADD);
245     m_blendingEnabled = false;
246 }
247
248 void ShaderProgram::setBlendingState(bool enableBlending)
249 {
250     if (enableBlending == m_blendingEnabled)
251         return;
252
253     if (enableBlending)
254         glEnable(GL_BLEND);
255     else
256         glDisable(GL_BLEND);
257
258     m_blendingEnabled = enableBlending;
259 }
260
261 /////////////////////////////////////////////////////////////////////////////////////////
262 // Drawing
263 /////////////////////////////////////////////////////////////////////////////////////////
264
265 void ShaderProgram::setViewport(SkRect& viewport)
266 {
267     TransformationMatrix ortho;
268     GLUtils::setOrthographicMatrix(ortho, viewport.fLeft, viewport.fTop,
269                                    viewport.fRight, viewport.fBottom, -1000, 1000);
270     m_projectionMatrix = ortho;
271     m_viewport = viewport;
272 }
273
274 void ShaderProgram::setProjectionMatrix(SkRect& geometry, GLint projectionMatrixHandle)
275 {
276     TransformationMatrix translate;
277     translate.translate3d(geometry.fLeft, geometry.fTop, 0.0);
278     TransformationMatrix scale;
279     scale.scale3d(geometry.width(), geometry.height(), 1.0);
280
281     TransformationMatrix total = m_projectionMatrix * translate * scale;
282
283     GLfloat projectionMatrix[16];
284     GLUtils::toGLMatrix(projectionMatrix, total);
285     glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
286 }
287
288 void ShaderProgram::drawQuadInternal(SkRect& geometry,
289                                      GLint textureId,
290                                      float opacity,
291                                      GLint program,
292                                      GLint projectionMatrixHandle,
293                                      GLint texSampler,
294                                      GLenum textureTarget,
295                                      GLint position,
296                                      GLint alpha,
297                                      GLint texFilter,
298                                      GLint contrast)
299 {
300     glUseProgram(program);
301
302     if (!geometry.isEmpty())
303          setProjectionMatrix(geometry, projectionMatrixHandle);
304     else {
305         TransformationMatrix matrix;
306         // Map x,y from (0,1) to (-1, 1)
307         matrix.scale3d(2, 2, 1);
308         matrix.translate3d(-0.5, -0.5, 0);
309         GLfloat projectionMatrix[16];
310         GLUtils::toGLMatrix(projectionMatrix, matrix);
311         glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
312     }
313
314     glActiveTexture(GL_TEXTURE0);
315     glUniform1i(texSampler, 0);
316     glBindTexture(textureTarget, textureId);
317     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
318     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
319     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
320     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
321
322     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
323     glEnableVertexAttribArray(position);
324     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
325     glUniform1f(alpha, opacity);
326     if (contrast != -1)
327         glUniform1f(contrast, m_contrast);
328
329     setBlendingState(opacity < 1.0);
330     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
331 }
332
333 void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
334                              GLenum textureTarget, GLint texFilter)
335 {
336     if (textureTarget == GL_TEXTURE_2D) {
337         drawQuadInternal(geometry, textureId, opacity, m_program,
338                          m_hProjectionMatrix,
339                          m_hTexSampler, GL_TEXTURE_2D,
340                          m_hPosition, alpha(), texFilter);
341     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
342                && !TilesManager::instance()->invertedScreen()) {
343         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
344                          m_hSTOESProjectionMatrix,
345                          m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
346                          m_hSTOESPosition, m_hSTOESAlpha, texFilter);
347     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
348                && TilesManager::instance()->invertedScreen()) {
349         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
350                          m_hSTOESProjectionMatrixInverted,
351                          m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
352                          m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
353                          texFilter, m_hSTOESContrastInverted);
354     }
355     GLUtils::checkGlError("drawQuad");
356 }
357
358 void ShaderProgram::setViewRect(const IntRect& viewRect)
359 {
360     m_viewRect = viewRect;
361
362     // We do clipping using glScissor, which needs to take
363     // coordinates in screen space. The following matrix transform
364     // content coordinates in screen coordinates.
365     TransformationMatrix translate;
366     translate.translate(1.0, 1.0);
367
368     TransformationMatrix scale;
369     scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1);
370
371     m_documentToScreenMatrix = scale * translate * m_projectionMatrix;
372
373     translate.scale3d(1, -1, 1);
374     m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
375 }
376
377 // This function transform a clip rect extracted from the current layer
378 // into a clip rect in screen coordinates -- used by the clipping rects
379 FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
380 {
381     FloatRect srect(0, 0, size.width(), size.height());
382     TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix;
383     return renderMatrix.mapRect(srect);
384 }
385
386 // used by the partial screen invals
387 FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
388 {
389     FloatRect srect(0, 0, size.width(), size.height());
390     TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix;
391     return renderMatrix.mapRect(srect);
392 }
393
394 FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect)
395 {
396     return m_documentToInvScreenMatrix.mapRect(rect);
397 }
398
399 FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
400 {
401     return m_documentToScreenMatrix.mapRect(rect);
402 }
403
404 FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
405 {
406     FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
407     return rectInScreenCoord(documentRect);
408 }
409
410 FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect)
411 {
412     FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect);
413     return rectInInvScreenCoord(documentRect);
414 }
415
416 void ShaderProgram::setScreenClip(const IntRect& clip)
417 {
418     m_screenClip = clip;
419     IntRect mclip = clip;
420
421     // the clip from frameworks is in full screen coordinates
422     mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight);
423     FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip);
424     IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height());
425     m_screenClip = screenClip;
426 }
427
428 // clip is in screen coordinates
429 void ShaderProgram::clip(const FloatRect& clip)
430 {
431     if (clip == m_clipRect)
432         return;
433
434     // we should only call glScissor in this function, so that we can easily
435     // track the current clipping rect.
436
437     IntRect screenClip(clip.x(),
438                        clip.y(),
439                        clip.width(), clip.height());
440
441     if (!m_screenClip.isEmpty())
442         screenClip.intersect(m_screenClip);
443
444     screenClip.setY(screenClip.y() + m_viewRect.y());
445     if (screenClip.x() < 0) {
446         int w = screenClip.width();
447         w += screenClip.x();
448         screenClip.setX(0);
449         screenClip.setWidth(w);
450     }
451     if (screenClip.y() < 0) {
452         int h = screenClip.height();
453         h += screenClip.y();
454         screenClip.setY(0);
455         screenClip.setHeight(h);
456     }
457
458     glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
459
460     m_clipRect = clip;
461 }
462
463 IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin)
464 {
465     IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin,
466                      m_viewport.width() + margin, m_viewport.height() + margin);
467     viewport.intersect(rect);
468     return viewport;
469 }
470
471 float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
472 {
473     TransformationMatrix modifiedDrawMatrix = drawMatrix;
474     modifiedDrawMatrix.scale3d(w, h, 1);
475     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
476     FloatPoint3D point(0.5, 0.5, 0.0);
477     FloatPoint3D result = renderMatrix.mapPoint(point);
478     return result.z();
479 }
480
481 void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
482                                           int textureId, float opacity,
483                                           GLenum textureTarget, GLint program,
484                                           GLint matrix, GLint texSample,
485                                           GLint position, GLint alpha,
486                                           GLint contrast)
487 {
488     glUseProgram(program);
489     glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix);
490
491     glActiveTexture(GL_TEXTURE0);
492     glUniform1i(texSample, 0);
493     glBindTexture(textureTarget, textureId);
494     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
495     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
496     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
497     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
498
499
500     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
501     glEnableVertexAttribArray(position);
502     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
503     glUniform1f(alpha, opacity);
504     if (contrast != -1)
505         glUniform1f(contrast, m_contrast);
506 }
507
508
509 void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
510                                   SkRect& geometry, int textureId, float opacity,
511                                   bool forceBlending, GLenum textureTarget)
512 {
513
514     TransformationMatrix modifiedDrawMatrix = drawMatrix;
515     // move the drawing depending on where the texture is on the layer
516     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
517     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
518     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
519
520     GLfloat projectionMatrix[16];
521     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
522     if (textureTarget == GL_TEXTURE_2D) {
523         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
524                               GL_TEXTURE_2D, m_program,
525                               m_hProjectionMatrix, m_hTexSampler,
526                               m_hPosition, alpha());
527     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
528                && !TilesManager::instance()->invertedScreen()) {
529         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
530                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram,
531                               m_hSTOESProjectionMatrix, m_hSTOESTexSampler,
532                               m_hSTOESPosition, m_hSTOESAlpha);
533     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
534                && TilesManager::instance()->invertedScreen()) {
535         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
536                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted,
537                               m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted,
538                               m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
539                               m_hSTOESContrastInverted);
540     }
541
542     setBlendingState(forceBlending || opacity < 1.0);
543     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
544
545     GLUtils::checkGlError("drawLayerQuad");
546 }
547
548 void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
549                                        float* textureMatrix, SkRect& geometry,
550                                        int textureId)
551 {
552     // switch to our custom yuv video rendering program
553     glUseProgram(m_videoProgram);
554
555     TransformationMatrix modifiedDrawMatrix = drawMatrix;
556     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
557     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
558     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
559
560     GLfloat projectionMatrix[16];
561     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
562     glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix);
563     glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix);
564
565     glActiveTexture(GL_TEXTURE0);
566     glUniform1i(m_hVideoTexSampler, 0);
567     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
568
569     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
570     glEnableVertexAttribArray(m_hVideoPosition);
571     glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
572
573     setBlendingState(false);
574     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
575 }
576
577 } // namespace WebCore
578
579 #endif // USE(ACCELERATED_COMPOSITING)