OSDN Git Service

Merge "Check the available memory when allocating an ImageBuffer."
[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 contrast)
298 {
299     glUseProgram(program);
300
301     if (!geometry.isEmpty())
302          setProjectionMatrix(geometry, projectionMatrixHandle);
303     else {
304         TransformationMatrix matrix;
305         // Map x,y from (0,1) to (-1, 1)
306         matrix.scale3d(2, 2, 1);
307         matrix.translate3d(-0.5, -0.5, 0);
308         GLfloat projectionMatrix[16];
309         GLUtils::toGLMatrix(projectionMatrix, matrix);
310         glUniformMatrix4fv(projectionMatrixHandle, 1, GL_FALSE, projectionMatrix);
311     }
312
313     glActiveTexture(GL_TEXTURE0);
314     glUniform1i(texSampler, 0);
315     glBindTexture(textureTarget, textureId);
316     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
317     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
318     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
319     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
320
321     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
322     glEnableVertexAttribArray(position);
323     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
324     glUniform1f(alpha, opacity);
325     if (contrast != -1)
326         glUniform1f(contrast, m_contrast);
327
328     setBlendingState(opacity < 1.0);
329     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
330 }
331
332 void ShaderProgram::drawQuad(SkRect& geometry, int textureId, float opacity,
333                              GLenum textureTarget)
334 {
335     if (textureTarget == GL_TEXTURE_2D) {
336         drawQuadInternal(geometry, textureId, opacity, m_program,
337                          m_hProjectionMatrix,
338                          m_hTexSampler, GL_TEXTURE_2D,
339                          m_hPosition, alpha());
340     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
341                && !TilesManager::instance()->invertedScreen()) {
342         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgram,
343                          m_hSTOESProjectionMatrix,
344                          m_hSTOESTexSampler, GL_TEXTURE_EXTERNAL_OES,
345                          m_hSTOESPosition, m_hSTOESAlpha);
346     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
347                && TilesManager::instance()->invertedScreen()) {
348         drawQuadInternal(geometry, textureId, opacity, m_surfTexOESProgramInverted,
349                          m_hSTOESProjectionMatrixInverted,
350                          m_hSTOESTexSamplerInverted, GL_TEXTURE_EXTERNAL_OES,
351                          m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
352                          m_hSTOESContrastInverted);
353     }
354     GLUtils::checkGlError("drawQuad");
355 }
356
357 void ShaderProgram::setViewRect(const IntRect& viewRect)
358 {
359     m_viewRect = viewRect;
360
361     // We do clipping using glScissor, which needs to take
362     // coordinates in screen space. The following matrix transform
363     // content coordinates in screen coordinates.
364     TransformationMatrix translate;
365     translate.translate(1.0, 1.0);
366
367     TransformationMatrix scale;
368     scale.scale3d(m_viewRect.width() * 0.5f, m_viewRect.height() * 0.5f, 1);
369
370     m_documentToScreenMatrix = scale * translate * m_projectionMatrix;
371
372     translate.scale3d(1, -1, 1);
373     m_documentToInvScreenMatrix = scale * translate * m_projectionMatrix;
374 }
375
376 // This function transform a clip rect extracted from the current layer
377 // into a clip rect in screen coordinates -- used by the clipping rects
378 FloatRect ShaderProgram::rectInScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
379 {
380     FloatRect srect(0, 0, size.width(), size.height());
381     TransformationMatrix renderMatrix = m_documentToScreenMatrix * drawMatrix;
382     return renderMatrix.mapRect(srect);
383 }
384
385 // used by the partial screen invals
386 FloatRect ShaderProgram::rectInInvScreenCoord(const TransformationMatrix& drawMatrix, const IntSize& size)
387 {
388     FloatRect srect(0, 0, size.width(), size.height());
389     TransformationMatrix renderMatrix = m_documentToInvScreenMatrix * drawMatrix;
390     return renderMatrix.mapRect(srect);
391 }
392
393 FloatRect ShaderProgram::rectInInvScreenCoord(const FloatRect& rect)
394 {
395     return m_documentToInvScreenMatrix.mapRect(rect);
396 }
397
398 FloatRect ShaderProgram::rectInScreenCoord(const FloatRect& rect)
399 {
400     return m_documentToScreenMatrix.mapRect(rect);
401 }
402
403 FloatRect ShaderProgram::convertInvScreenCoordToScreenCoord(const FloatRect& rect)
404 {
405     FloatRect documentRect = m_documentToInvScreenMatrix.inverse().mapRect(rect);
406     return rectInScreenCoord(documentRect);
407 }
408
409 FloatRect ShaderProgram::convertScreenCoordToInvScreenCoord(const FloatRect& rect)
410 {
411     FloatRect documentRect = m_documentToScreenMatrix.inverse().mapRect(rect);
412     return rectInInvScreenCoord(documentRect);
413 }
414
415 void ShaderProgram::setScreenClip(const IntRect& clip)
416 {
417     m_screenClip = clip;
418     IntRect mclip = clip;
419
420     // the clip from frameworks is in full screen coordinates
421     mclip.setY(clip.y() - m_webViewRect.y() - m_titleBarHeight);
422     FloatRect tclip = convertInvScreenCoordToScreenCoord(mclip);
423     IntRect screenClip(tclip.x(), tclip.y(), tclip.width(), tclip.height());
424     m_screenClip = screenClip;
425 }
426
427 // clip is in screen coordinates
428 void ShaderProgram::clip(const FloatRect& clip)
429 {
430     if (clip == m_clipRect)
431         return;
432
433     // we should only call glScissor in this function, so that we can easily
434     // track the current clipping rect.
435
436     IntRect screenClip(clip.x(),
437                        clip.y(),
438                        clip.width(), clip.height());
439
440     if (!m_screenClip.isEmpty())
441         screenClip.intersect(m_screenClip);
442
443     screenClip.setY(screenClip.y() + m_viewRect.y());
444     if (screenClip.x() < 0) {
445         int w = screenClip.width();
446         w += screenClip.x();
447         screenClip.setX(0);
448         screenClip.setWidth(w);
449     }
450     if (screenClip.y() < 0) {
451         int h = screenClip.height();
452         h += screenClip.y();
453         screenClip.setY(0);
454         screenClip.setHeight(h);
455     }
456
457     glScissor(screenClip.x(), screenClip.y(), screenClip.width(), screenClip.height());
458
459     m_clipRect = clip;
460 }
461
462 IntRect ShaderProgram::clippedRectWithViewport(const IntRect& rect, int margin)
463 {
464     IntRect viewport(m_viewport.fLeft - margin, m_viewport.fTop - margin,
465                      m_viewport.width() + margin, m_viewport.height() + margin);
466     viewport.intersect(rect);
467     return viewport;
468 }
469
470 float ShaderProgram::zValue(const TransformationMatrix& drawMatrix, float w, float h)
471 {
472     TransformationMatrix modifiedDrawMatrix = drawMatrix;
473     modifiedDrawMatrix.scale3d(w, h, 1);
474     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
475     FloatPoint3D point(0.5, 0.5, 0.0);
476     FloatPoint3D result = renderMatrix.mapPoint(point);
477     return result.z();
478 }
479
480 void ShaderProgram::drawLayerQuadInternal(const GLfloat* projectionMatrix,
481                                           int textureId, float opacity,
482                                           GLenum textureTarget, GLint program,
483                                           GLint matrix, GLint texSample,
484                                           GLint position, GLint alpha,
485                                           GLint contrast)
486 {
487     glUseProgram(program);
488     glUniformMatrix4fv(matrix, 1, GL_FALSE, projectionMatrix);
489
490     glActiveTexture(GL_TEXTURE0);
491     glUniform1i(texSample, 0);
492     glBindTexture(textureTarget, textureId);
493     glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
494     glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
495     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
496     glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
497
498
499     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
500     glEnableVertexAttribArray(position);
501     glVertexAttribPointer(position, 2, GL_FLOAT, GL_FALSE, 0, 0);
502     glUniform1f(alpha, opacity);
503     if (contrast != -1)
504         glUniform1f(contrast, m_contrast);
505 }
506
507
508 void ShaderProgram::drawLayerQuad(const TransformationMatrix& drawMatrix,
509                                   SkRect& geometry, int textureId, float opacity,
510                                   bool forceBlending, GLenum textureTarget)
511 {
512
513     TransformationMatrix modifiedDrawMatrix = drawMatrix;
514     // move the drawing depending on where the texture is on the layer
515     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
516     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
517     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
518
519     GLfloat projectionMatrix[16];
520     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
521     if (textureTarget == GL_TEXTURE_2D) {
522         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
523                               GL_TEXTURE_2D, m_program,
524                               m_hProjectionMatrix, m_hTexSampler,
525                               m_hPosition, alpha());
526     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
527                && !TilesManager::instance()->invertedScreen()) {
528         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
529                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgram,
530                               m_hSTOESProjectionMatrix, m_hSTOESTexSampler,
531                               m_hSTOESPosition, m_hSTOESAlpha);
532     } else if (textureTarget == GL_TEXTURE_EXTERNAL_OES
533                && TilesManager::instance()->invertedScreen()) {
534         drawLayerQuadInternal(projectionMatrix, textureId, opacity,
535                               GL_TEXTURE_EXTERNAL_OES, m_surfTexOESProgramInverted,
536                               m_hSTOESProjectionMatrixInverted, m_hSTOESTexSamplerInverted,
537                               m_hSTOESPositionInverted, m_hSTOESAlphaInverted,
538                               m_hSTOESContrastInverted);
539     }
540
541     setBlendingState(forceBlending || opacity < 1.0);
542     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
543
544     GLUtils::checkGlError("drawLayerQuad");
545 }
546
547 void ShaderProgram::drawVideoLayerQuad(const TransformationMatrix& drawMatrix,
548                                        float* textureMatrix, SkRect& geometry,
549                                        int textureId)
550 {
551     // switch to our custom yuv video rendering program
552     glUseProgram(m_videoProgram);
553
554     TransformationMatrix modifiedDrawMatrix = drawMatrix;
555     modifiedDrawMatrix.translate(geometry.fLeft, geometry.fTop);
556     modifiedDrawMatrix.scale3d(geometry.width(), geometry.height(), 1);
557     TransformationMatrix renderMatrix = m_projectionMatrix * modifiedDrawMatrix;
558
559     GLfloat projectionMatrix[16];
560     GLUtils::toGLMatrix(projectionMatrix, renderMatrix);
561     glUniformMatrix4fv(m_hVideoProjectionMatrix, 1, GL_FALSE, projectionMatrix);
562     glUniformMatrix4fv(m_hVideoTextureMatrix, 1, GL_FALSE, textureMatrix);
563
564     glActiveTexture(GL_TEXTURE0);
565     glUniform1i(m_hVideoTexSampler, 0);
566     glBindTexture(GL_TEXTURE_EXTERNAL_OES, textureId);
567
568     glBindBuffer(GL_ARRAY_BUFFER, m_textureBuffer[0]);
569     glEnableVertexAttribArray(m_hVideoPosition);
570     glVertexAttribPointer(m_hVideoPosition, 2, GL_FLOAT, GL_FALSE, 0, 0);
571
572     setBlendingState(false);
573     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
574 }
575
576 } // namespace WebCore
577
578 #endif // USE(ACCELERATED_COMPOSITING)