Support for sharing wl_buffers between Web and UI process.
[platform/framework/web/webkit-efl.git] / Source / WebCore / platform / graphics / efl / tizen / AcceleratedPlatformLayer.cpp
1 /*
2     Copyright (C) 2011 Samsung Electronics
3     Copyright (C) 2013 Intel Corporation. All rights reserved.
4
5     This library is free software; you can redistribute it and/or
6     modify it under the terms of the GNU Library General Public
7     License as published by the Free Software Foundation; either
8     version 2 of the License, or (at your option) any later version.
9
10     This library is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13     Library General Public License for more details.
14
15     You should have received a copy of the GNU Library General Public License
16     along with this library; see the file COPYING.LIB.  If not, write to
17     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18     Boston, MA 02110-1301, USA.
19 */
20
21 #include "config.h"
22 #include "AcceleratedPlatformLayer.h"
23
24 #if ENABLE(TIZEN_WEBKIT2_TILED_AC_SHARED_PLATFORM_SURFACE) && ENABLE(TIZEN_ACCELERATED_PLATFORM_LAYER)
25
26 #if ENABLE(TIZEN_DDK_WORKAROUND)
27 #include "Extensions3D.h"
28 #endif
29
30 #include "ImageBuffer.h"
31 #include "ImageData.h"
32 #include "NotImplemented.h"
33
34 #define GL_GLEXT_PROTOTYPES 1
35 #include <GLES2/gl2.h>
36 #include <GLES2/gl2ext.h>
37
38 #ifndef GLchar
39 #define GLchar char
40 #endif
41
42 #include <wtf/OwnArrayPtr.h>
43
44 namespace WebCore {
45
46 PassOwnPtr<AcceleratedPlatformLayer> AcceleratedPlatformLayer::create(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
47 {
48     if (renderStyle == GraphicsContext3D::RenderDirectlyToHostWindow)
49         return nullptr;
50
51     OwnPtr<AcceleratedPlatformLayer> internal = adoptPtr(new AcceleratedPlatformLayer(attrs, renderStyle));
52     if (!internal->initialize(0))
53         return nullptr;
54
55     return internal.release();
56 }
57
58 State::State()
59     : activeTexture(GraphicsContext3D::TEXTURE0)
60     , boundFBO(0)
61     , boundTexture0(0)
62     , sourceFactor(GraphicsContext3D::ONE)
63     , destinationFactor(GraphicsContext3D::ZERO)
64     , depthMask(true)
65     , scissorX(0)
66     , scissorY(0)
67     , scissorWidth(0)
68     , scissorHeight(0)
69     , stencilFunc(GraphicsContext3D::ALWAYS)
70     , stencilRef(0)
71     , stencilMask(UINT_MAX)
72     , stencilFail(GraphicsContext3D::KEEP)
73     , stencilZFail(GraphicsContext3D::KEEP)
74     , stencilZPass(GraphicsContext3D::KEEP)
75     , viewportX(0)
76     , viewportY(0)
77     , viewportWidth(0)
78     , viewportHeight(0)
79 {
80     m_state = BlendFuncCacheDirty | DepthMaskCacheDirty | StencilFuncCacheDirty | StencilOpCacheDirty | ViewportCacheDirty;
81 }
82
83 State::~State()
84 {
85     if (!pixelStoreIntMap.isEmpty())
86         pixelStoreIntMap.clear();
87
88     if (!capabilityStateMap.isEmpty())
89         capabilityStateMap.clear();
90 }
91
92 AcceleratedPlatformLayer::AcceleratedPlatformLayer(GraphicsContext3D::Attributes attrs, GraphicsContext3D::RenderStyle renderStyle)
93     : GraphicsContext3DInternal(attrs, GraphicsContext3D::RenderOffscreen)
94     , m_compositorTexture(0)
95     , m_layerComposited(false)
96     , m_swapBuffers(true)
97     , m_width(1)
98     , m_height(1)
99     , m_surfaceFlags(0)
100     , m_surfaceHandle(0)
101     , m_renderStyle(renderStyle)
102     , m_state(adoptPtr(new State()))
103 {
104 }
105
106 AcceleratedPlatformLayer::~AcceleratedPlatformLayer()
107 {
108     if (m_renderStyle == GraphicsContext3D::RenderToCurrentGLContext)
109         return;
110
111     makeContextCurrent();
112     GL_CMD(glBindFramebuffer(GL_FRAMEBUFFER, 0));
113     GL_CMD(glBindTexture(GL_TEXTURE_2D, 0));
114
115     if (m_compositorTexture)
116         GL_CMD(glDeleteTextures(1, &m_compositorTexture));
117
118     releaseResources();
119 }
120
121 void AcceleratedPlatformLayer::releaseResources()
122 {
123     // Release the current context and drawable only after destroying any associated gl resources.
124     m_surfaceHandle = 0;
125     if (m_offScreenSurface)
126         m_offScreenSurface->destroy();
127
128     if (m_offScreenContext) {
129         m_offScreenContext->destroy();
130         m_offScreenContext->releaseCurrent();
131     }
132 }
133
134 PlatformLayer* AcceleratedPlatformLayer::platformLayer() const
135 {
136     return const_cast<TextureMapperPlatformLayer*>(static_cast<const TextureMapperPlatformLayer*>(this));
137 }
138
139 bool AcceleratedPlatformLayer::initialize(HostWindow*)
140 {
141     if (!initializeSurface())
142         return false;
143
144     validateAttributes();
145
146     // ANGLE integration starts
147     ShBuiltInResources ANGLEResources;
148     ShInitBuiltInResources(&ANGLEResources);
149
150     GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &ANGLEResources.MaxVertexAttribs));
151     GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS, &ANGLEResources.MaxVertexUniformVectors));
152     GL_CMD(getIntegerv(GraphicsContext3D::MAX_VARYING_VECTORS, &ANGLEResources.MaxVaryingVectors));
153     GL_CMD(getIntegerv(GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxVertexTextureImageUnits));
154     GL_CMD(getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxCombinedTextureImageUnits));
155     GL_CMD(getIntegerv(GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS, &ANGLEResources.MaxTextureImageUnits));
156     GL_CMD(getIntegerv(GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS, &ANGLEResources.MaxFragmentUniformVectors));
157
158     // Always set to 1 for OpenGL ES.
159     ANGLEResources.MaxDrawBuffers = 1;
160     m_compiler.setResources(ANGLEResources);
161     // ANGLE Integration block ENDs
162
163     if (m_renderStyle != GraphicsContext3D::RenderToCurrentGLContext)
164         GL_CMD(glClearColor(0.0, 0.0, 0.0, 0.0));
165
166     return true;
167 }
168
169 bool AcceleratedPlatformLayer::initializeSurface()
170 {
171     m_offScreenContext = GLPlatformContext::createContext(m_renderStyle);
172     if (!m_offScreenContext)
173         return false;
174
175     if (m_renderStyle == GraphicsContext3D::RenderOffscreen) {
176         GLPlatformSurface::SurfaceAttributes sharedSurfaceAttributes = GLPlatformSurface::Default;
177         if (m_attributes.alpha)
178             sharedSurfaceAttributes |= GLPlatformSurface::SupportAlpha;
179
180         if (m_attributes.depth)
181             sharedSurfaceAttributes |= GLPlatformSurface::SupportDepth;
182
183         if (m_attributes.stencil)
184             sharedSurfaceAttributes |= GLPlatformSurface::SupportStencil;
185
186         m_offScreenSurface = GLPlatformSurface::createOffScreenSurface(sharedSurfaceAttributes, IntSize(m_width, m_height));
187
188         if (!m_offScreenSurface)
189             return false;
190
191         if (!m_offScreenContext->initialize(m_offScreenSurface.get()))
192             return false;
193
194         if (!makeContextCurrent())
195             return false;
196
197         if (m_offScreenSurface->attributes() & GLPlatformSurface::SupportAlpha)
198             m_surfaceFlags |= GraphicsSurface::Alpha;
199
200         if (m_attributes.premultipliedAlpha)
201             m_surfaceFlags |= GraphicsSurface::PremultipliedAlpha;
202
203         // synchronize the attributes,
204         m_attributes.stencil = m_offScreenSurface->attributes() & GLPlatformSurface::SupportStencil;
205         m_attributes.depth = m_offScreenSurface->attributes() & GLPlatformSurface::SupportDepth;
206         m_attributes.alpha = m_offScreenSurface->attributes() & GLPlatformSurface::SupportAlpha;
207
208         m_surfaceHandle = m_offScreenSurface->handle();
209     }
210
211     return true;
212 }
213
214 bool AcceleratedPlatformLayer::makeContextCurrent()
215 {
216     bool success = m_offScreenContext->makeCurrent(m_offScreenSurface.get());
217
218     if (!m_offScreenContext->isValid()) {
219         // FIXME: Restore context
220         if (m_contextLostCallback)
221             m_contextLostCallback->onContextLost();
222
223         return false;
224     }
225
226     return success;
227 }
228
229 void AcceleratedPlatformLayer::setContextLostCallback(PassOwnPtr<GraphicsContext3D::ContextLostCallback> callBack)
230 {
231     m_contextLostCallback = callBack;
232 }
233
234 bool AcceleratedPlatformLayer::paintToCanvas(const unsigned char* imagePixels, int imageWidth, int imageHeight, int canvasWidth, int canvasHeight, PlatformContextCairo* context)
235 {
236     if (!imagePixels || imageWidth <= 0 || imageHeight <= 0 || canvasWidth <= 0 || canvasHeight <= 0 || !context)
237         return false;
238
239     cairo_t* cr = context->cr();
240     context->save();
241
242     RefPtr<cairo_surface_t> imageSurface = adoptRef(cairo_image_surface_create_for_data(
243                                                         const_cast<unsigned char*>(imagePixels), CAIRO_FORMAT_ARGB32, imageWidth, imageHeight, imageWidth * 4));
244
245     cairo_rectangle(cr, 0, 0, canvasWidth, canvasHeight);
246
247     // OpenGL keeps the pixels stored bottom up, so we need to flip the image here.
248     cairo_matrix_t matrix;
249     cairo_matrix_init(&matrix, 1.0, 0.0, 0.0, -1.0, 0.0, imageHeight);
250     cairo_set_matrix(cr, &matrix);
251     cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
252     cairo_set_source_surface(cr, imageSurface.get(), 0, 0);
253     cairo_fill(cr);
254     context->restore();
255
256     return true;
257 }
258
259 void AcceleratedPlatformLayer::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, int width, int height)
260 {
261     int totalBytes = 4 * width * height;
262
263     OwnArrayPtr<unsigned char> pixels = adoptArrayPtr(new unsigned char[totalBytes]);
264     if (!pixels)
265         return;
266
267     readRenderingResults(pixels.get(), totalBytes , width , height);
268
269 #if ENABLE(TIZEN_CANVAS_CAIRO_GLES_RENDERING)
270     cairo_surface_t* surface = imageBuffer->getSurface();
271     if (cairo_surface_get_type(surface) == CAIRO_SURFACE_TYPE_GL) {
272         // TODO: premultipliedAlpha currently not getting applied. Need to apply the value properly.
273         if (!m_attributes.premultipliedAlpha) {
274             for (int i = 0; i < totalBytes; i = 4) {
275                 // Premultiply alpha.
276                 pixels[i+0] = std::min(255, pixels[i+0] * pixels[i+3] / 255);
277                 pixels[i+1] = std::min(255, pixels[i+1] * pixels[i+3] / 255);
278                 pixels[i+2] = std::min(255, pixels[i+2] * pixels[i+3] / 255);
279             }
280         }
281     }
282 #endif
283     paintToCanvas(pixels.get(), width, height,
284                   imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()->platformContext());
285 }
286
287 PassRefPtr<ImageData> AcceleratedPlatformLayer::paintRenderingResultsToImageData(int width, int height)
288 {
289     // Reading premultiplied alpha would involve unpremultiplying, which is
290     // lossy
291     if (m_attributes.premultipliedAlpha)
292         return 0;
293
294     RefPtr<ImageData> imageData = ImageData::create(IntSize(width, height));
295     unsigned char* pixels = imageData->data()->data();
296     int totalBytes = 4 * width * height;
297
298     readRenderingResults(pixels, totalBytes, width, height);
299
300     // Convert to RGBA
301     for (int i = 0; i < totalBytes; i = 4)
302         std::swap(pixels[i], pixels[i+2]);
303
304     return imageData.release();
305 }
306
307 void AcceleratedPlatformLayer::markContextChanged()
308 {
309     m_layerComposited = false;
310     m_swapBuffers = true;
311 }
312
313 bool AcceleratedPlatformLayer::swapPlatformSurfaces()
314 {
315     if (!m_swapBuffers)
316         return true;
317
318     makeContextCurrent();
319     m_swapBuffers = false;
320     m_offScreenSurface->swapBuffers();
321     m_layerComposited = true;
322     return true;
323 }
324
325 void AcceleratedPlatformLayer::prepareTexture(int width, int height)
326 {
327     if (m_layerComposited)
328         return;
329
330     GLuint internalColorFormat = 0;
331     if (m_attributes.alpha)
332         internalColorFormat = GL_RGBA;
333     else
334         internalColorFormat = GL_RGB;
335
336     makeContextCurrent();
337     GL_CMD(glActiveTexture(GL_TEXTURE0));
338     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_compositorTexture));
339     GL_CMD(glCopyTexImage2D(GL_TEXTURE_2D, 0, internalColorFormat, 0, 0, width, height, 0));
340     GL_CMD(glBindTexture(GL_TEXTURE_2D, m_state->boundTexture0));
341     GL_CMD(glActiveTexture(m_state->activeTexture));
342     GL_CMD(glFinish());
343
344     m_layerComposited = true;
345 }
346
347 void AcceleratedPlatformLayer::readRenderingResults(unsigned char *pixels, int pixelsSize, int width, int height)
348 {
349     int totalBytes = width * height * 4;
350     if (pixelsSize < totalBytes)
351         return;
352
353     makeContextCurrent();
354     if (m_attributes.antialias)
355         notImplemented();
356
357     GLint packAlignment = 4;
358     bool mustRestorePackAlignment = false;
359     GL_CMD(glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment));
360     if (packAlignment > 4) {
361         pixelStorei(GL_PACK_ALIGNMENT, 4);
362         mustRestorePackAlignment = true;
363     }
364
365     GL_CMD(glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels));
366     // Convert to BGRA
367     for (int i = 0; i < totalBytes; i = 4)
368         std::swap(pixels[i], pixels[i+2]);
369
370     if (mustRestorePackAlignment)
371         pixelStorei(GL_PACK_ALIGNMENT, packAlignment);
372 }
373
374 void AcceleratedPlatformLayer::reshape(int width, int height)
375 {
376     if ((m_width == width) && (m_height == height))
377         return;
378
379     m_width = width;
380     m_height = height;
381     makeContextCurrent();
382
383     if (m_offScreenSurface && (m_offScreenSurface->attributes() & GLPlatformSurface::DoubleBuffered)) {
384         m_offScreenSurface->swapBuffers();
385         m_offScreenSurface->setGeometry(IntRect(0, 0, m_width, m_height));
386     }
387     // FIXME: Handle resize case for single buffered surface.
388
389     m_surfaceHandle = m_offScreenSurface->handle();
390
391     if (m_attributes.antialias)
392         notImplemented();
393
394     // Initialize renderbuffers to 0.
395     GLfloat clearColorValue[] = {0, 0, 0, 0}, clearDepthValue = 0;
396     GLint clearStencilValue = 0;
397     GLboolean colorMaskValue[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMaskValue = GL_TRUE;
398     GLuint stencilMask = 0xffffffff;
399     GLboolean isScissorEnabled = GL_FALSE;
400     GLboolean isDitherEnabled = GL_FALSE;
401
402     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
403
404     GL_CMD(glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColorValue));
405     GL_CMD(glClearColor(0, 0, 0, 0));
406     GL_CMD(glGetBooleanv(GL_COLOR_WRITEMASK, colorMaskValue));
407     GL_CMD(glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE));
408
409     if (m_attributes.depth) {
410         GL_CMD(glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepthValue));
411         GL_CMD(glClearDepthf(1.0));
412         GL_CMD(glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMaskValue));
413         GL_CMD(glDepthMask(GL_TRUE));
414         clearMask |= GL_DEPTH_BUFFER_BIT;
415     }
416
417     if (m_attributes.stencil) {
418         GL_CMD(glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencilValue));
419         GL_CMD(glClearStencil(0));
420         GL_CMD(glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask)));
421         GL_CMD(glStencilMaskSeparate(GL_FRONT, 0xffffffff));
422         clearMask |= GL_STENCIL_BUFFER_BIT;
423     }
424
425     isScissorEnabled = GL_CMD(glIsEnabled(GL_SCISSOR_TEST));
426     GL_CMD(glDisable(GL_SCISSOR_TEST));
427     isDitherEnabled = GL_CMD(glIsEnabled(GL_DITHER));
428     GL_CMD(glDisable(GL_DITHER));
429
430     GL_CMD(glClear(clearMask));
431
432     GL_CMD(glClearColor(clearColorValue[0], clearColorValue[1], clearColorValue[2], clearColorValue[3]));
433     GL_CMD(glColorMask(colorMaskValue[0], colorMaskValue[1], colorMaskValue[2], colorMaskValue[3]));
434
435     if (m_attributes.depth) {
436         GL_CMD(glClearDepthf(clearDepthValue));
437         GL_CMD(glDepthMask(depthMaskValue));
438     }
439     if (m_attributes.stencil) {
440         GL_CMD(glClearStencil(clearStencilValue));
441         GL_CMD(glStencilMaskSeparate(GL_FRONT, stencilMask));
442     }
443
444     if (isScissorEnabled)
445         GL_CMD(glEnable(GL_SCISSOR_TEST));
446     else
447         GL_CMD(glDisable(GL_SCISSOR_TEST));
448
449     if (isDitherEnabled)
450         GL_CMD(glEnable(GL_DITHER));
451     else
452         GL_CMD(glDisable(GL_DITHER));
453 }
454
455 void AcceleratedPlatformLayer::activeTexture(GC3Denum texture)
456 {
457     if (m_state->activeTexture != texture) {
458         m_state->activeTexture = texture;
459         GraphicsContext3DInternal::activeTexture(texture);
460     }
461 }
462
463 void AcceleratedPlatformLayer::bindFramebuffer(GC3Denum target, Platform3DObject framebuffer)
464 {
465     GLuint fbo = framebuffer;
466     if (framebuffer != m_state->boundFBO) {
467         m_state->boundFBO = fbo;
468         // FIXME : Below lines are workaround codes.(driver issue)
469         // PlatformSurface surface is not updated properly after binding FBO.
470         // It seems previous frame is remained.
471 #if ENABLE(TIZEN_DDK_WORKAROUND)
472         if (flush && framebuffer && !m_layerComposited)
473             GL_CMD(glFlush());
474 #endif
475         GraphicsContext3DInternal::bindFramebuffer(target, fbo);
476     }
477 }
478
479 #if ENABLE(TIZEN_DDK_WORKAROUND)
480 void AcceleratedPlatformLayer::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
481 {
482     // We should probably remove the tid that was set to framebuffer from m_renderTargetTextures
483     // if texture is no longer rendered to, but since this is temporary code that will be removed
484     // when the DDK is fixed, and that scenario is quite unlikely to happen, I'll just leave it as is.
485     if (target != Extensions3D::READ_FRAMEBUFFER && texture)
486         m_renderTargetTextures.add(texture);
487
488     GraphicsContext3DInternal::framebufferTexture2D(target, attachment, textarget, texture, level);
489 }
490
491 void AcceleratedPlatformLayer::generateMipmap(GC3Denum target)
492 {
493     // FIXME: Render to texture related driver issue.
494     // Remove GC3DOffscreen::generateMipmap and related code when driver issue is fixed.
495     // The rendered texture contents are not properly flushed before generating mipmaps.
496     int boundTexture;
497     GL_CMD(glGetIntegerv(GL_TEXTURE_BINDING_2D, &boundTexture));
498     if (m_renderTargetTextures.contains(boundTexture))
499         GL_CMD(glFlush());
500
501     GraphicsContext3DInternal::generateMipmap(target);
502 }
503 #endif
504
505 void AcceleratedPlatformLayer::bindTexture(GC3Denum target, Platform3DObject texture)
506 {
507     if (m_state->activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D) {
508         if (m_state->boundTexture0 == texture)
509             return;
510
511         m_state->boundTexture0 = texture;
512     }
513
514     GraphicsContext3DInternal::bindTexture(target, texture);
515 }
516
517 void AcceleratedPlatformLayer::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
518 {
519     GraphicsContext3DInternal::bufferData(target, size, data, usage);
520
521     // FIXME : Driver issue!
522     // Following lines are temporary to avoid webgl conformance test failures.
523     // See draw-arrays-out-of-bounds.html.
524     // If a parameter size inputted to glBufferData is zero,
525     // GL_OUT_OF_MEMORY error is occurred while running in Mali driver.
526     if (!size) {
527         GC3Denum error = getError();
528         if (error == GL_OUT_OF_MEMORY)
529             return; // No error.
530         synthesizeGLError(error); // Push the error back again.
531     }
532 }
533
534 bool AcceleratedPlatformLayer::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
535 {
536     if (!program) {
537         synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
538         return false;
539     }
540
541     makeContextCurrent();
542     GLint maxAttributeSize = 0;
543     GL_CMD(glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize));
544
545     GLchar name[maxAttributeSize]; // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination
546     GLsizei nameLength = 0;
547     GLint size = 0;
548     GLenum type = 0;
549     GL_CMD(glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name));
550     if (!nameLength)
551         return false;
552
553     info.name = String(name, nameLength);
554     info.type = type;
555     info.size = size;
556     return true;
557 }
558
559 bool AcceleratedPlatformLayer::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
560 {
561     if (!program) {
562         synthesizeGLError(GL_INVALID_VALUE);
563         return false;
564     }
565
566     makeContextCurrent();
567     GC3Dint maxUniformSize = 0;
568     GL_CMD(glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize));
569
570     GLchar name[maxUniformSize]; // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination
571     GC3Dsizei nameLength = 0;
572     GC3Dint size = 0;
573     GC3Denum type = 0;
574     GL_CMD(glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name));
575     if (!nameLength)
576         return false;
577
578     info.name = String(name, nameLength);
579     info.type = type;
580     info.size = size;
581
582     // FIXME : "[0]" is added at end of name in WebGLRenderingContext::getActiveUniform()
583     // when isGLES2Compliant is only false. I can't understand the reason.
584     // I add "[0]" here to avoid faling webgl conformance test(get-active-test.html),
585     // but if it makes something wrong later, remove following lines
586     if (isGLES2Compliant() && info.size > 1 && !info.name.endsWith("[0]"))
587         info.name.append("[0]");
588
589     return true;
590 }
591
592 void AcceleratedPlatformLayer::getFloatv(GC3Denum pname, GC3Dfloat* value)
593 {
594     GraphicsContext3DInternal::getFloatv(pname, value);
595
596     // FIXME : Fllowing lines are for fixing SGX & Mali driver issue.
597     switch (pname) {
598     case GL_ALIASED_POINT_SIZE_RANGE:
599     case GL_ALIASED_LINE_WIDTH_RANGE:
600         if (value[0] == value[1]) {
601             if (!value[0])
602                 value[1] = 1.0;
603             else {
604                 if (value[0] < 1.0)
605                     value[1] = 1.0;
606                 else
607                     value[0] = 1.0;
608             }
609         } else {
610             if (value[0] < value[1]) {
611                 if (value[1] < 1.0) {
612                     value[0] = value[1];
613                     value[1] = 1.0;
614                 } else
615                     value[0] = 1.0;
616             } else {
617                 if (value[0] < 1.0)
618                     value[1] = 1.0;
619                 else {
620                     value[1] = value[0];
621                     value[0] = 1.0;
622                 }
623             }
624         }
625         break;
626     }
627 }
628
629 void AcceleratedPlatformLayer::getIntegerv(GC3Denum pname, GC3Dint* value)
630 {
631     makeContextCurrent();
632     GL_CMD(glGetIntegerv(pname, value));
633 }
634
635 void AcceleratedPlatformLayer::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
636 {
637     if (!updateViewportCache(x, y, width, height))
638         return;
639
640     makeContextCurrent();
641     GL_CMD(glViewport(x, y, width, height));
642 }
643
644 void AcceleratedPlatformLayer::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
645 {
646     if (!updateStencilOpCache(fail, zfail, zpass))
647         return;
648
649     makeContextCurrent();
650     GL_CMD(glStencilOp(fail, zfail, zpass));
651 }
652
653 void AcceleratedPlatformLayer::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
654 {
655     if (!updateStencilFuncCache(func, ref, mask))
656         return;
657
658     makeContextCurrent();
659     GL_CMD(glStencilFunc(func, ref, mask));
660 }
661
662 void AcceleratedPlatformLayer::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
663 {
664     if (!updateScissorCache(x, y, width, height))
665         return;
666
667     makeContextCurrent();
668     GL_CMD(glScissor(x, y, width, height));
669 }
670
671 void AcceleratedPlatformLayer::pixelStorei(GC3Denum pname, GC3Dint param)
672 {
673     if (!updatePixelStoreiCache(pname, param))
674         return;
675
676     makeContextCurrent();
677     GL_CMD(glPixelStorei(pname, param));
678 }
679
680 GC3Dboolean AcceleratedPlatformLayer::isEnabled(GC3Denum cap)
681 {
682     State::CapabilityState state = getCapabilityState(cap);
683     if (state != State::CapabilityUnknown)
684         return state == State::CapabilityEnabled ? true : false;
685
686     makeContextCurrent();
687     return GL_CMD(glIsEnabled(cap));
688 }
689
690 void AcceleratedPlatformLayer::enable(GC3Denum cap)
691 {
692     if (!updateCapabilityCache(cap, State::CapabilityEnabled))
693         return;
694
695     makeContextCurrent();
696     GL_CMD(glEnable(cap));
697 }
698
699 void AcceleratedPlatformLayer::disable(GC3Denum cap)
700 {
701     if (!updateCapabilityCache(cap, State::CapabilityDisabled))
702         return;
703
704     makeContextCurrent();
705     GL_CMD(glDisable(cap));
706 }
707
708 void AcceleratedPlatformLayer::depthMask(GC3Dboolean flag)
709 {
710     if (!updateDepthMaskCache(flag))
711         return;
712
713     makeContextCurrent();
714     GL_CMD(glDepthMask(flag));
715 }
716
717 void AcceleratedPlatformLayer::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
718 {
719     if (!updateBlendFuncCache(sfactor, dfactor))
720         return;
721
722     makeContextCurrent();
723     GL_CMD(glBlendFunc(sfactor, dfactor));
724 }
725
726 // below functions are for ANGLE integration
727 void AcceleratedPlatformLayer::compileShader(Platform3DObject shader)
728 {
729     ASSERT(shader);
730     makeContextCurrent();
731
732     int GLshaderType;
733     ANGLEShaderType shaderType;
734
735     GL_CMD(glGetShaderiv(shader, GraphicsContext3D::SHADER_TYPE, &GLshaderType));
736
737     if (GLshaderType == GraphicsContext3D::VERTEX_SHADER)
738         shaderType = SHADER_TYPE_VERTEX;
739     else if (GLshaderType == GraphicsContext3D::FRAGMENT_SHADER)
740         shaderType = SHADER_TYPE_FRAGMENT;
741     else
742         return; // Invalid shader type.
743
744     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
745
746     if (result == m_shaderSourceMap.end())
747         return;
748
749     ShaderSourceEntry& entry = result->second;
750
751     String translatedShaderSource;
752     String shaderInfoLog;
753
754     bool isValid = m_compiler.validateShaderSource(entry.source.utf8().data(), shaderType, translatedShaderSource, shaderInfoLog);
755
756     entry.log = shaderInfoLog;
757     entry.isValid = isValid;
758
759     if (!isValid)
760         return; // Shader didn't validate, don't move forward with compiling translated source.
761
762     int len = entry.source.length();
763     CString cstr = entry.source.utf8();
764     const char* s = cstr.data();
765
766     GL_CMD(glShaderSource(shader, 1, &s, &len));
767     GL_CMD(glCompileShader(shader));
768
769 }
770
771 void AcceleratedPlatformLayer::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
772 {
773     ASSERT(shader);
774
775     makeContextCurrent();
776
777     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
778
779     switch (pname) {
780     case GraphicsContext3D::DELETE_STATUS:
781     case GraphicsContext3D::SHADER_TYPE:
782         GL_CMD(glGetShaderiv(shader, pname, value));
783         break;
784     case GraphicsContext3D::COMPILE_STATUS:
785         if (result == m_shaderSourceMap.end()) {
786             *value = static_cast<int>(false);
787             return;
788         }
789         *value = static_cast<int>(result->second.isValid);
790         break;
791     case GraphicsContext3D::INFO_LOG_LENGTH:
792         if (result == m_shaderSourceMap.end()) {
793             *value = 0;
794             return;
795         }
796         *value = getShaderInfoLog(shader).length();
797         break;
798     case GraphicsContext3D::SHADER_SOURCE_LENGTH:
799         *value = getShaderSource(shader).length();
800         break;
801     default:
802         synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
803     }
804 }
805
806 String AcceleratedPlatformLayer::getShaderInfoLog(Platform3DObject shader)
807 {
808     ASSERT(shader);
809
810     makeContextCurrent();
811
812     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
813     if (result == m_shaderSourceMap.end())
814         return String();
815
816     ShaderSourceEntry entry = result->second;
817     if (!entry.isValid)
818         return entry.log;
819
820     GLint length = 0;
821     GL_CMD(glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length));
822     if (!length)
823         return String();
824
825     GLsizei size = 0;
826     OwnArrayPtr<GLchar> info = adoptArrayPtr(new GLchar[length]);
827     GL_CMD(glGetShaderInfoLog(shader, length, &size, info.get()));
828
829     return String(info.get());
830 }
831
832 String AcceleratedPlatformLayer::getShaderSource(Platform3DObject shader)
833 {
834     ASSERT(shader);
835
836     makeContextCurrent();
837
838     HashMap<Platform3DObject, ShaderSourceEntry>::iterator result = m_shaderSourceMap.find(shader);
839     if (result == m_shaderSourceMap.end())
840         return String();
841
842     return result->second.source;
843 }
844
845 void AcceleratedPlatformLayer::shaderSource(Platform3DObject shader, const String& string)
846 {
847     ASSERT(shader);
848
849     makeContextCurrent();
850
851     ShaderSourceEntry entry;
852
853     entry.source = string;
854     entry.isValid = false;
855
856     m_shaderSourceMap.set(shader, entry);
857 }
858
859 bool AcceleratedPlatformLayer::updateBlendFuncCache(GC3Denum sourceFactor, GC3Denum destinationFactor)
860 {
861     if (m_state->m_state & State::BlendFuncCacheDirty)
862         m_state->m_state &= ~State::BlendFuncCacheDirty;
863     else if (m_state->sourceFactor == sourceFactor && m_state->destinationFactor == destinationFactor)
864         return false;
865
866     m_state->sourceFactor = sourceFactor;
867     m_state->destinationFactor = destinationFactor;
868     return true;
869 }
870
871 bool AcceleratedPlatformLayer::updateDepthMaskCache(GC3Dboolean depthMask)
872 {
873     if (m_state->m_state & State::DepthMaskCacheDirty)
874         m_state->m_state &= ~State::DepthMaskCacheDirty;
875     else if (m_state->depthMask == depthMask)
876         return false;
877
878     m_state->depthMask = depthMask;
879     return true;
880 }
881
882 bool AcceleratedPlatformLayer::updateScissorCache(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
883 {
884     if (m_state->m_state & State::ScissorCacheDirty)
885         m_state->m_state &= ~State::ScissorCacheDirty;
886     else if (m_state->scissorX == x && m_state->scissorY == y && m_state->scissorWidth == width && m_state->scissorHeight == height)
887         return false;
888
889     m_state->scissorX = x;
890     m_state->scissorY = y;
891     m_state->scissorWidth = width;
892     m_state->scissorHeight = height;
893     return true;
894 }
895
896 bool AcceleratedPlatformLayer::updateStencilFuncCache(GC3Denum func, GC3Dint ref, GC3Duint mask)
897 {
898     if (m_state->m_state & State::StencilFuncCacheDirty)
899         m_state->m_state &= ~State::StencilFuncCacheDirty;
900     else if (m_state->stencilFunc == func && m_state->stencilRef == ref && m_state->stencilMask == mask)
901         return false;
902
903     m_state->stencilFunc = func;
904     m_state->stencilRef = ref;
905     m_state->stencilMask = mask;
906     return true;
907 }
908
909 bool AcceleratedPlatformLayer::updateStencilOpCache(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
910 {
911     return true;
912
913     if (m_state->m_state & State::StencilOpCacheDirty)
914         m_state->m_state &= ~State::StencilOpCacheDirty;
915     else if (m_state->stencilFail == fail && m_state->stencilZFail == zfail && m_state->stencilZPass == zpass)
916         return false;
917
918     m_state->stencilFail = fail;
919     m_state->stencilZFail = zfail;
920     m_state->stencilZPass = zpass;
921     return true;
922 }
923
924 bool AcceleratedPlatformLayer::updateViewportCache(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
925 {
926     if (m_state->m_state & State::ViewportCacheDirty)
927         m_state->m_state &= ~State::ViewportCacheDirty;
928     else if (m_state->viewportX == x && m_state->viewportY == y && m_state->viewportWidth == width && m_state->viewportHeight == height)
929         return false;
930
931     m_state->viewportX = x;
932     m_state->viewportY = y;
933     m_state->viewportWidth = width;
934     m_state->viewportHeight = height;
935     return true;
936 }
937
938 bool AcceleratedPlatformLayer::updatePixelStoreiCache(GC3Denum pname, GC3Dint param)
939 {
940     State::PixelStoreIntMap::const_iterator it = m_state->pixelStoreIntMap.find(pname);
941     if (it != m_state->pixelStoreIntMap.end() && it->second == param)
942         return false;
943
944     m_state->pixelStoreIntMap.set(pname, param);
945     return true;
946 }
947
948 State::CapabilityState AcceleratedPlatformLayer::getCapabilityState(GC3Denum cap)
949 {
950     State::CapabilityStateMap::const_iterator it = m_state->capabilityStateMap.find(cap);
951     if (it == m_state->capabilityStateMap.end())
952         return State::CapabilityUnknown;
953
954     return it->second;
955 }
956
957 bool AcceleratedPlatformLayer::updateCapabilityCache(GC3Denum cap, State::CapabilityState isEnabled)
958 {
959     State::CapabilityStateMap::const_iterator it = m_state->capabilityStateMap.find(cap);
960     if (it != m_state->capabilityStateMap.end() && it->second == isEnabled)
961         return false;
962
963     m_state->capabilityStateMap.set(cap, isEnabled);
964     return true;
965 }
966
967 } // namespace WebCore
968
969 #endif