OSDN Git Service

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