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