f2f70bc63c2262454924b530b1b07e4ede1cb7c6
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / GraphicsContext3DOpenGLCommon.cpp
1 /*
2  * Copyright (C) 2010 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com>
5  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
27  */
28
29 #include "config.h"
30
31 #if USE(3D_GRAPHICS)
32
33 #include "GraphicsContext3D.h"
34
35 #if USE(OPENGL_ES_2)
36 #include "Extensions3DOpenGLES.h"
37 #else
38 #include "Extensions3DOpenGL.h"
39 #endif
40 #include "GraphicsContext.h"
41 #include "ImageBuffer.h"
42 #include "ImageData.h"
43 #include "IntRect.h"
44 #include "IntSize.h"
45 #include "Logging.h"
46 #include "NotImplemented.h"
47 #include <cstring>
48 #include <runtime/ArrayBuffer.h>
49 #include <runtime/ArrayBufferView.h>
50 #include <runtime/Float32Array.h>
51 #include <runtime/Int32Array.h>
52 #include <runtime/Uint8Array.h>
53 #include <wtf/MainThread.h>
54 #include <wtf/text/CString.h>
55
56 #if USE(OPENGL_ES_2)
57 #include "OpenGLESShims.h"
58 #elif PLATFORM(MAC)
59 #include <OpenGL/gl.h>
60 #elif PLATFORM(GTK) || PLATFORM(EFL) || PLATFORM(WIN) || PLATFORM(NIX)
61 #include "OpenGLShims.h"
62 #endif
63
64 #if PLATFORM(BLACKBERRY)
65 #include <BlackBerryPlatformLog.h>
66 #endif
67
68 namespace WebCore {
69
70 static ShaderNameHash* currentNameHashMapForShader;
71
72 // Hash function used by the ANGLE translator/compiler to do
73 // symbol name mangling. Since this is a static method, before
74 // calling compileShader we set currentNameHashMapForShader
75 // to point to the map kept by the current instance of GraphicsContext3D.
76
77 static uint64_t nameHashForShader(const char* name, size_t length)
78 {
79     if (!length)
80         return 0;
81
82     CString nameAsCString = CString(name);
83
84     // Look up name in our local map.
85     if (currentNameHashMapForShader) {
86         ShaderNameHash::iterator result = currentNameHashMapForShader->find(nameAsCString);
87         if (result != currentNameHashMapForShader->end())
88             return result->value;
89     }
90
91     unsigned hashValue = nameAsCString.hash();
92
93     // Convert the 32-bit hash from CString::hash into a 64-bit result
94     // by shifting then adding the size of our table. Overflow would
95     // only be a problem if we're already hashing to the same value (and
96     // we're hoping that over the lifetime of the context we
97     // don't have that many symbols).
98
99     uint64_t result = hashValue;
100     result = (result << 32) + (currentNameHashMapForShader->size() + 1);
101
102     currentNameHashMapForShader->set(nameAsCString, result);
103     return result;
104 }
105
106 PassRefPtr<GraphicsContext3D> GraphicsContext3D::createForCurrentGLContext()
107 {
108     RefPtr<GraphicsContext3D> context = adoptRef(new GraphicsContext3D(Attributes(), 0, GraphicsContext3D::RenderToCurrentGLContext));
109     return context->m_private ? context.release() : 0;
110 }
111
112 void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExtension)
113 {
114     Extensions3D* extensions = getExtensions();
115     if (m_attrs.stencil) {
116         if (extensions->supports(packedDepthStencilExtension)) {
117             extensions->ensureEnabled(packedDepthStencilExtension);
118             // Force depth if stencil is true.
119             m_attrs.depth = true;
120         } else
121             m_attrs.stencil = false;
122     }
123     if (m_attrs.antialias) {
124         if (!extensions->maySupportMultisampling() || !extensions->supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant())
125             m_attrs.antialias = false;
126         else
127             extensions->ensureEnabled("GL_ANGLE_framebuffer_multisample");
128     }
129 }
130
131 bool GraphicsContext3D::isResourceSafe()
132 {
133     return false;
134 }
135
136 void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer, DrawingBuffer*)
137 {
138     int rowBytes = m_currentWidth * 4;
139     int totalBytes = rowBytes * m_currentHeight;
140
141     auto pixels = std::make_unique<unsigned char[]>(totalBytes);
142     if (!pixels)
143         return;
144
145     readRenderingResults(pixels.get(), totalBytes);
146
147     if (!m_attrs.premultipliedAlpha) {
148         for (int i = 0; i < totalBytes; i += 4) {
149             // Premultiply alpha.
150             pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
151             pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
152             pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
153         }
154     }
155
156 #if PLATFORM(BLACKBERRY) || USE(CG)
157     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
158                   imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context());
159 #else
160     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
161                   imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context()->platformContext());
162 #endif
163 }
164
165 bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*)
166 {
167     // Not needed at the moment, so return that nothing was done.
168     return false;
169 }
170
171 PassRefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData(DrawingBuffer*)
172 {
173     // Reading premultiplied alpha would involve unpremultiplying, which is
174     // lossy.
175     if (m_attrs.premultipliedAlpha)
176         return 0;
177
178     RefPtr<ImageData> imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
179     unsigned char* pixels = imageData->data()->data();
180     int totalBytes = 4 * m_currentWidth * m_currentHeight;
181
182     readRenderingResults(pixels, totalBytes);
183
184     // Convert to RGBA.
185     for (int i = 0; i < totalBytes; i += 4)
186         std::swap(pixels[i], pixels[i + 2]);
187
188     return imageData.release();
189 }
190
191 #if !PLATFORM(BLACKBERRY)
192 void GraphicsContext3D::prepareTexture()
193 {
194     if (m_layerComposited)
195         return;
196
197     makeContextCurrent();
198     if (m_attrs.antialias)
199         resolveMultisamplingIfNecessary();
200
201     ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
202     ::glActiveTexture(GL_TEXTURE0);
203     ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
204     ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0);
205     ::glBindTexture(GL_TEXTURE_2D, m_state.boundTexture0);
206     ::glActiveTexture(m_state.activeTexture);
207     if (m_state.boundFBO != m_fbo)
208         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO);
209     ::glFinish();
210     m_layerComposited = true;
211 }
212 #endif
213
214 void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
215 {
216     if (pixelsSize < m_currentWidth * m_currentHeight * 4)
217         return;
218
219     makeContextCurrent();
220
221     bool mustRestoreFBO = false;
222     if (m_attrs.antialias) {
223         resolveMultisamplingIfNecessary();
224         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
225         mustRestoreFBO = true;
226     } else {
227         if (m_state.boundFBO != m_fbo) {
228             mustRestoreFBO = true;
229             ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
230         }
231     }
232
233     GLint packAlignment = 4;
234     bool mustRestorePackAlignment = false;
235     ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment);
236     if (packAlignment > 4) {
237         ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
238         mustRestorePackAlignment = true;
239     }
240
241     readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels);
242
243     if (mustRestorePackAlignment)
244         ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
245
246     if (mustRestoreFBO)
247         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO);
248 }
249
250 void GraphicsContext3D::reshape(int width, int height)
251 {
252     if (!platformGraphicsContext3D())
253         return;
254
255     if (width == m_currentWidth && height == m_currentHeight)
256         return;
257
258 #if (PLATFORM(EFL) || PLATFORM(NIX)) && USE(GRAPHICS_SURFACE)
259     ::glFlush(); // Make sure all GL calls have been committed before resizing.
260     createGraphicsSurfaces(IntSize(width, height));
261 #endif
262
263     m_currentWidth = width;
264     m_currentHeight = height;
265
266     makeContextCurrent();
267     validateAttributes();
268
269     bool mustRestoreFBO = reshapeFBOs(IntSize(width, height));
270
271     // Initialize renderbuffers to 0.
272     GLfloat clearColor[] = {0, 0, 0, 0}, clearDepth = 0;
273     GLint clearStencil = 0;
274     GLboolean colorMask[] = {GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE}, depthMask = GL_TRUE;
275     GLuint stencilMask = 0xffffffff;
276     GLboolean isScissorEnabled = GL_FALSE;
277     GLboolean isDitherEnabled = GL_FALSE;
278     GLbitfield clearMask = GL_COLOR_BUFFER_BIT;
279     ::glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor);
280     ::glClearColor(0, 0, 0, 0);
281     ::glGetBooleanv(GL_COLOR_WRITEMASK, colorMask);
282     ::glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
283     if (m_attrs.depth) {
284         ::glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth);
285         GraphicsContext3D::clearDepth(1);
286         ::glGetBooleanv(GL_DEPTH_WRITEMASK, &depthMask);
287         ::glDepthMask(GL_TRUE);
288         clearMask |= GL_DEPTH_BUFFER_BIT;
289     }
290     if (m_attrs.stencil) {
291         ::glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &clearStencil);
292         ::glClearStencil(0);
293         ::glGetIntegerv(GL_STENCIL_WRITEMASK, reinterpret_cast<GLint*>(&stencilMask));
294         ::glStencilMaskSeparate(GL_FRONT, 0xffffffff);
295         clearMask |= GL_STENCIL_BUFFER_BIT;
296     }
297     isScissorEnabled = ::glIsEnabled(GL_SCISSOR_TEST);
298     ::glDisable(GL_SCISSOR_TEST);
299     isDitherEnabled = ::glIsEnabled(GL_DITHER);
300     ::glDisable(GL_DITHER);
301
302     ::glClear(clearMask);
303
304     ::glClearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]);
305     ::glColorMask(colorMask[0], colorMask[1], colorMask[2], colorMask[3]);
306     if (m_attrs.depth) {
307         GraphicsContext3D::clearDepth(clearDepth);
308         ::glDepthMask(depthMask);
309     }
310     if (m_attrs.stencil) {
311         ::glClearStencil(clearStencil);
312         ::glStencilMaskSeparate(GL_FRONT, stencilMask);
313     }
314     if (isScissorEnabled)
315         ::glEnable(GL_SCISSOR_TEST);
316     else
317         ::glDisable(GL_SCISSOR_TEST);
318     if (isDitherEnabled)
319         ::glEnable(GL_DITHER);
320     else
321         ::glDisable(GL_DITHER);
322
323     if (mustRestoreFBO)
324         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO);
325
326     ::glFlush();
327 }
328
329 IntSize GraphicsContext3D::getInternalFramebufferSize() const
330 {
331     return IntSize(m_currentWidth, m_currentHeight);
332 }
333
334 void GraphicsContext3D::activeTexture(GC3Denum texture)
335 {
336     makeContextCurrent();
337     m_state.activeTexture = texture;
338     ::glActiveTexture(texture);
339 }
340
341 void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
342 {
343     ASSERT(program);
344     ASSERT(shader);
345     makeContextCurrent();
346     ::glAttachShader(program, shader);
347 }
348
349 void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
350 {
351     ASSERT(program);
352     makeContextCurrent();
353
354     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name);
355     LOG(WebGL, "::bindAttribLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
356     ::glBindAttribLocation(program, index, mappedName.utf8().data());
357 }
358
359 void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
360 {
361     makeContextCurrent();
362     ::glBindBuffer(target, buffer);
363 }
364
365 void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
366 {
367     makeContextCurrent();
368     GLuint fbo;
369     if (buffer)
370         fbo = buffer;
371     else
372 #if PLATFORM(BLACKBERRY)
373         fbo = m_fbo;
374 #else
375         fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo);
376 #endif
377     if (fbo != m_state.boundFBO) {
378         ::glBindFramebufferEXT(target, fbo);
379         m_state.boundFBO = fbo;
380     }
381 }
382
383 void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
384 {
385     makeContextCurrent();
386     ::glBindRenderbufferEXT(target, renderbuffer);
387 }
388
389
390 void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
391 {
392     makeContextCurrent();
393     if (m_state.activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D)
394         m_state.boundTexture0 = texture;
395     ::glBindTexture(target, texture);
396 }
397
398 void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
399 {
400     makeContextCurrent();
401     ::glBlendColor(red, green, blue, alpha);
402 }
403
404 void GraphicsContext3D::blendEquation(GC3Denum mode)
405 {
406     makeContextCurrent();
407     ::glBlendEquation(mode);
408 }
409
410 void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
411 {
412     makeContextCurrent();
413     ::glBlendEquationSeparate(modeRGB, modeAlpha);
414 }
415
416
417 void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
418 {
419     makeContextCurrent();
420     ::glBlendFunc(sfactor, dfactor);
421 }       
422
423 void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
424 {
425     makeContextCurrent();
426     ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
427 }
428
429 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
430 {
431     makeContextCurrent();
432     ::glBufferData(target, size, 0, usage);
433 }
434
435 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
436 {
437     makeContextCurrent();
438     ::glBufferData(target, size, data, usage);
439 }
440
441 void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
442 {
443     makeContextCurrent();
444     ::glBufferSubData(target, offset, size, data);
445 }
446
447 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
448 {
449     makeContextCurrent();
450     return ::glCheckFramebufferStatusEXT(target);
451 }
452
453 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
454 {
455     makeContextCurrent();
456     ::glClearColor(r, g, b, a);
457 }
458
459 void GraphicsContext3D::clear(GC3Dbitfield mask)
460 {
461     makeContextCurrent();
462     ::glClear(mask);
463 }
464
465 void GraphicsContext3D::clearStencil(GC3Dint s)
466 {
467     makeContextCurrent();
468     ::glClearStencil(s);
469 }
470
471 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
472 {
473     makeContextCurrent();
474     ::glColorMask(red, green, blue, alpha);
475 }
476
477 void GraphicsContext3D::compileShader(Platform3DObject shader)
478 {
479     ASSERT(shader);
480     makeContextCurrent();
481
482     // Turn on name mapping. Due to the way ANGLE name hashing works, we
483     // point a global hashmap to the map owned by this context.
484     ShBuiltInResources ANGLEResources = m_compiler.getResources();
485     ShHashFunction64 previousHashFunction = ANGLEResources.HashFunction;
486     ANGLEResources.HashFunction = nameHashForShader;
487
488     if (!nameHashMapForShaders)
489         nameHashMapForShaders = adoptPtr(new ShaderNameHash);
490     currentNameHashMapForShader = nameHashMapForShaders.get();
491     m_compiler.setResources(ANGLEResources);
492
493     String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader);
494
495     ANGLEResources.HashFunction = previousHashFunction;
496     m_compiler.setResources(ANGLEResources);
497     currentNameHashMapForShader = nullptr;
498
499     if (!translatedShaderSource.length())
500         return;
501
502     const CString& translatedShaderCString = translatedShaderSource.utf8();
503     const char* translatedShaderPtr = translatedShaderCString.data();
504     int translatedShaderLength = translatedShaderCString.length();
505
506     LOG(WebGL, "--- begin original shader source ---\n%s\n--- end original shader source ---\n", getShaderSource(shader).utf8().data());
507     LOG(WebGL, "--- begin translated shader source ---\n%s\n--- end translated shader source ---", translatedShaderPtr);
508
509     ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
510     
511     ::glCompileShader(shader);
512     
513     int GLCompileSuccess;
514     
515     ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
516
517     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
518     GraphicsContext3D::ShaderSourceEntry& entry = result->value;
519
520     // Populate the shader log
521     GLint length = 0;
522     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
523
524     if (length) {
525         GLsizei size = 0;
526         auto info = std::make_unique<GLchar[]>(length);
527         ::glGetShaderInfoLog(shader, length, &size, info.get());
528
529         entry.log = info.get();
530     }
531
532     if (GLCompileSuccess != GL_TRUE) {
533         entry.isValid = false;
534         LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile.");
535 #if PLATFORM(BLACKBERRY) && !defined(NDEBUG)
536         BBLOG(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n");
537 #endif
538     }
539 }
540
541 void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
542 {
543     makeContextCurrent();
544 #if !PLATFORM(BLACKBERRY)
545     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
546         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
547         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
548     }
549 #endif
550     ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
551 #if !PLATFORM(BLACKBERRY)
552     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
553         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
554 #endif
555 }
556
557 void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
558 {
559     makeContextCurrent();
560 #if !PLATFORM(BLACKBERRY)
561     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
562         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
563         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
564     }
565 #endif
566     ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
567 #if !PLATFORM(BLACKBERRY)
568     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
569         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
570 #endif
571 }
572
573 void GraphicsContext3D::cullFace(GC3Denum mode)
574 {
575     makeContextCurrent();
576     ::glCullFace(mode);
577 }
578
579 void GraphicsContext3D::depthFunc(GC3Denum func)
580 {
581     makeContextCurrent();
582     ::glDepthFunc(func);
583 }
584
585 void GraphicsContext3D::depthMask(GC3Dboolean flag)
586 {
587     makeContextCurrent();
588     ::glDepthMask(flag);
589 }
590
591 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
592 {
593     ASSERT(program);
594     ASSERT(shader);
595     makeContextCurrent();
596     ::glDetachShader(program, shader);
597 }
598
599 void GraphicsContext3D::disable(GC3Denum cap)
600 {
601     makeContextCurrent();
602     ::glDisable(cap);
603 }
604
605 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
606 {
607     makeContextCurrent();
608     ::glDisableVertexAttribArray(index);
609 }
610
611 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
612 {
613     makeContextCurrent();
614     ::glDrawArrays(mode, first, count);
615 }
616
617 void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
618 {
619     makeContextCurrent();
620     ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
621 }
622
623 void GraphicsContext3D::enable(GC3Denum cap)
624 {
625     makeContextCurrent();
626     ::glEnable(cap);
627 }
628
629 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
630 {
631     makeContextCurrent();
632     ::glEnableVertexAttribArray(index);
633 }
634
635 void GraphicsContext3D::finish()
636 {
637     makeContextCurrent();
638     ::glFinish();
639 }
640
641 void GraphicsContext3D::flush()
642 {
643     makeContextCurrent();
644     ::glFlush();
645 }
646
647 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
648 {
649     makeContextCurrent();
650     ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
651 }
652
653 void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
654 {
655     makeContextCurrent();
656     ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
657 }
658
659 void GraphicsContext3D::frontFace(GC3Denum mode)
660 {
661     makeContextCurrent();
662     ::glFrontFace(mode);
663 }
664
665 void GraphicsContext3D::generateMipmap(GC3Denum target)
666 {
667     makeContextCurrent();
668     ::glGenerateMipmap(target);
669 }
670
671 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
672 {
673     if (!program) {
674         synthesizeGLError(INVALID_VALUE);
675         return false;
676     }
677     makeContextCurrent();
678     GLint maxAttributeSize = 0;
679     ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
680     auto name = std::make_unique<GLchar[]>(maxAttributeSize); // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination.
681     GLsizei nameLength = 0;
682     GLint size = 0;
683     GLenum type = 0;
684     ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name.get());
685     if (!nameLength)
686         return false;
687     
688     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, String(name.get(), nameLength));
689     
690     info.name = originalName;
691     info.type = type;
692     info.size = size;
693     return true;
694 }
695
696 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
697 {
698     if (!program) {
699         synthesizeGLError(INVALID_VALUE);
700         return false;
701     }
702
703     makeContextCurrent();
704     GLint maxUniformSize = 0;
705     ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
706
707     auto name = std::make_unique<GLchar[]>(maxUniformSize); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination.
708     GLsizei nameLength = 0;
709     GLint size = 0;
710     GLenum type = 0;
711     ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get());
712     if (!nameLength)
713         return false;
714     
715     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, String(name.get(), nameLength));
716     
717     info.name = originalName;
718     info.type = type;
719     info.size = size;
720     return true;
721 }
722     
723 void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
724 {
725     if (!program) {
726         synthesizeGLError(INVALID_VALUE);
727         return;
728     }
729     makeContextCurrent();
730     ::glGetAttachedShaders(program, maxCount, count, shaders);
731 }
732
733 String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
734 {
735     GC3Dsizei count;
736     Platform3DObject shaders[2];
737     getAttachedShaders(program, 2, &count, shaders);
738
739     for (GC3Dsizei i = 0; i < count; ++i) {
740         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
741         if (result == m_shaderSourceMap.end())
742             continue;
743
744         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
745         ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name);
746         if (symbolEntry != symbolMap.end())
747             return symbolEntry->value.mappedName;
748     }
749     return name;
750 }
751     
752 String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
753 {
754     GC3Dsizei count;
755     Platform3DObject shaders[2];
756     getAttachedShaders(program, 2, &count, shaders);
757     
758     for (GC3Dsizei i = 0; i < count; ++i) {
759         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
760         if (result == m_shaderSourceMap.end())
761             continue;
762         
763         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
764         ShaderSymbolMap::const_iterator symbolEntry;
765         for (symbolEntry = symbolMap.begin(); symbolEntry != symbolMap.end(); ++symbolEntry) {
766             if (symbolEntry->value.mappedName == name)
767                 return symbolEntry->key;
768         }
769     }
770     return name;
771 }
772
773 int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
774 {
775     if (!program)
776         return -1;
777
778     makeContextCurrent();
779
780     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name);
781     LOG(WebGL, "::getAttribLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
782     return ::glGetAttribLocation(program, mappedName.utf8().data());
783 }
784
785 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
786 {
787     return m_attrs;
788 }
789
790 GC3Denum GraphicsContext3D::getError()
791 {
792     if (m_syntheticErrors.size() > 0) {
793         ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin();
794         GC3Denum err = *iter;
795         m_syntheticErrors.remove(iter);
796         return err;
797     }
798
799     makeContextCurrent();
800     return ::glGetError();
801 }
802
803 String GraphicsContext3D::getString(GC3Denum name)
804 {
805     makeContextCurrent();
806     return String(reinterpret_cast<const char*>(::glGetString(name)));
807 }
808
809 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
810 {
811     makeContextCurrent();
812     ::glHint(target, mode);
813 }
814
815 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
816 {
817     if (!buffer)
818         return GL_FALSE;
819
820     makeContextCurrent();
821     return ::glIsBuffer(buffer);
822 }
823
824 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
825 {
826     makeContextCurrent();
827     return ::glIsEnabled(cap);
828 }
829
830 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
831 {
832     if (!framebuffer)
833         return GL_FALSE;
834
835     makeContextCurrent();
836     return ::glIsFramebufferEXT(framebuffer);
837 }
838
839 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
840 {
841     if (!program)
842         return GL_FALSE;
843
844     makeContextCurrent();
845     return ::glIsProgram(program);
846 }
847
848 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
849 {
850     if (!renderbuffer)
851         return GL_FALSE;
852
853     makeContextCurrent();
854     return ::glIsRenderbufferEXT(renderbuffer);
855 }
856
857 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
858 {
859     if (!shader)
860         return GL_FALSE;
861
862     makeContextCurrent();
863     return ::glIsShader(shader);
864 }
865
866 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
867 {
868     if (!texture)
869         return GL_FALSE;
870
871     makeContextCurrent();
872     return ::glIsTexture(texture);
873 }
874
875 void GraphicsContext3D::lineWidth(GC3Dfloat width)
876 {
877     makeContextCurrent();
878     ::glLineWidth(width);
879 }
880
881 void GraphicsContext3D::linkProgram(Platform3DObject program)
882 {
883     ASSERT(program);
884     makeContextCurrent();
885     ::glLinkProgram(program);
886 }
887
888 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
889 {
890     makeContextCurrent();
891     ::glPixelStorei(pname, param);
892 }
893
894 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
895 {
896     makeContextCurrent();
897     ::glPolygonOffset(factor, units);
898 }
899
900 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
901 {
902     makeContextCurrent();
903     ::glSampleCoverage(value, invert);
904 }
905
906 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
907 {
908     makeContextCurrent();
909     ::glScissor(x, y, width, height);
910 }
911
912 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
913 {
914     ASSERT(shader);
915
916     makeContextCurrent();
917
918     ShaderSourceEntry entry;
919
920     entry.source = string;
921
922     m_shaderSourceMap.set(shader, entry);
923 }
924
925 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
926 {
927     makeContextCurrent();
928     ::glStencilFunc(func, ref, mask);
929 }
930
931 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
932 {
933     makeContextCurrent();
934     ::glStencilFuncSeparate(face, func, ref, mask);
935 }
936
937 void GraphicsContext3D::stencilMask(GC3Duint mask)
938 {
939     makeContextCurrent();
940     ::glStencilMask(mask);
941 }
942
943 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
944 {
945     makeContextCurrent();
946     ::glStencilMaskSeparate(face, mask);
947 }
948
949 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
950 {
951     makeContextCurrent();
952     ::glStencilOp(fail, zfail, zpass);
953 }
954
955 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
956 {
957     makeContextCurrent();
958     ::glStencilOpSeparate(face, fail, zfail, zpass);
959 }
960
961 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
962 {
963     makeContextCurrent();
964     ::glTexParameterf(target, pname, value);
965 }
966
967 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
968 {
969     makeContextCurrent();
970     ::glTexParameteri(target, pname, value);
971 }
972
973 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
974 {
975     makeContextCurrent();
976     ::glUniform1f(location, v0);
977 }
978
979 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
980 {
981     makeContextCurrent();
982     ::glUniform1fv(location, size, array);
983 }
984
985 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
986 {
987     makeContextCurrent();
988     ::glUniform2f(location, v0, v1);
989 }
990
991 void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
992 {
993     // FIXME: length needs to be a multiple of 2.
994     makeContextCurrent();
995     ::glUniform2fv(location, size, array);
996 }
997
998 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
999 {
1000     makeContextCurrent();
1001     ::glUniform3f(location, v0, v1, v2);
1002 }
1003
1004 void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1005 {
1006     // FIXME: length needs to be a multiple of 3.
1007     makeContextCurrent();
1008     ::glUniform3fv(location, size, array);
1009 }
1010
1011 void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1012 {
1013     makeContextCurrent();
1014     ::glUniform4f(location, v0, v1, v2, v3);
1015 }
1016
1017 void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1018 {
1019     // FIXME: length needs to be a multiple of 4.
1020     makeContextCurrent();
1021     ::glUniform4fv(location, size, array);
1022 }
1023
1024 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
1025 {
1026     makeContextCurrent();
1027     ::glUniform1i(location, v0);
1028 }
1029
1030 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1031 {
1032     makeContextCurrent();
1033     ::glUniform1iv(location, size, array);
1034 }
1035
1036 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
1037 {
1038     makeContextCurrent();
1039     ::glUniform2i(location, v0, v1);
1040 }
1041
1042 void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1043 {
1044     // FIXME: length needs to be a multiple of 2.
1045     makeContextCurrent();
1046     ::glUniform2iv(location, size, array);
1047 }
1048
1049 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
1050 {
1051     makeContextCurrent();
1052     ::glUniform3i(location, v0, v1, v2);
1053 }
1054
1055 void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1056 {
1057     // FIXME: length needs to be a multiple of 3.
1058     makeContextCurrent();
1059     ::glUniform3iv(location, size, array);
1060 }
1061
1062 void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
1063 {
1064     makeContextCurrent();
1065     ::glUniform4i(location, v0, v1, v2, v3);
1066 }
1067
1068 void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1069 {
1070     // FIXME: length needs to be a multiple of 4.
1071     makeContextCurrent();
1072     ::glUniform4iv(location, size, array);
1073 }
1074
1075 void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1076 {
1077     // FIXME: length needs to be a multiple of 4.
1078     makeContextCurrent();
1079     ::glUniformMatrix2fv(location, size, transpose, array);
1080 }
1081
1082 void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1083 {
1084     // FIXME: length needs to be a multiple of 9.
1085     makeContextCurrent();
1086     ::glUniformMatrix3fv(location, size, transpose, array);
1087 }
1088
1089 void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1090 {
1091     // FIXME: length needs to be a multiple of 16.
1092     makeContextCurrent();
1093     ::glUniformMatrix4fv(location, size, transpose, array);
1094 }
1095
1096 void GraphicsContext3D::useProgram(Platform3DObject program)
1097 {
1098     makeContextCurrent();
1099     ::glUseProgram(program);
1100 }
1101
1102 void GraphicsContext3D::validateProgram(Platform3DObject program)
1103 {
1104     ASSERT(program);
1105
1106     makeContextCurrent();
1107     ::glValidateProgram(program);
1108 }
1109
1110 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
1111 {
1112     makeContextCurrent();
1113     ::glVertexAttrib1f(index, v0);
1114 }
1115
1116 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
1117 {
1118     makeContextCurrent();
1119     ::glVertexAttrib1fv(index, array);
1120 }
1121
1122 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
1123 {
1124     makeContextCurrent();
1125     ::glVertexAttrib2f(index, v0, v1);
1126 }
1127
1128 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
1129 {
1130     makeContextCurrent();
1131     ::glVertexAttrib2fv(index, array);
1132 }
1133
1134 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1135 {
1136     makeContextCurrent();
1137     ::glVertexAttrib3f(index, v0, v1, v2);
1138 }
1139
1140 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
1141 {
1142     makeContextCurrent();
1143     ::glVertexAttrib3fv(index, array);
1144 }
1145
1146 void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1147 {
1148     makeContextCurrent();
1149     ::glVertexAttrib4f(index, v0, v1, v2, v3);
1150 }
1151
1152 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
1153 {
1154     makeContextCurrent();
1155     ::glVertexAttrib4fv(index, array);
1156 }
1157
1158 void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
1159 {
1160     makeContextCurrent();
1161     ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
1162 }
1163
1164 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1165 {
1166     makeContextCurrent();
1167     ::glViewport(x, y, width, height);
1168 }
1169
1170 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
1171 {
1172     makeContextCurrent();
1173     ::glGetBooleanv(pname, value);
1174 }
1175
1176 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1177 {
1178     makeContextCurrent();
1179     ::glGetBufferParameteriv(target, pname, value);
1180 }
1181
1182 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
1183 {
1184     makeContextCurrent();
1185     ::glGetFloatv(pname, value);
1186 }
1187
1188 void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
1189 {
1190     makeContextCurrent();
1191     if (attachment == DEPTH_STENCIL_ATTACHMENT)
1192         attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
1193     ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
1194 }
1195
1196 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
1197 {
1198     makeContextCurrent();
1199     ::glGetProgramiv(program, pname, value);
1200 }
1201
1202 String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
1203 {
1204     ASSERT(program);
1205
1206     makeContextCurrent();
1207     GLint length = 0;
1208     ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
1209     if (!length)
1210         return String(); 
1211
1212     GLsizei size = 0;
1213     auto info = std::make_unique<GLchar[]>(length);
1214     ::glGetProgramInfoLog(program, length, &size, info.get());
1215
1216     return String(info.get());
1217 }
1218
1219 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1220 {
1221     makeContextCurrent();
1222     ::glGetRenderbufferParameterivEXT(target, pname, value);
1223 }
1224
1225 void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
1226 {
1227     ASSERT(shader);
1228
1229     makeContextCurrent();
1230
1231     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1232     
1233     switch (pname) {
1234     case DELETE_STATUS:
1235     case SHADER_TYPE:
1236         ::glGetShaderiv(shader, pname, value);
1237         break;
1238     case COMPILE_STATUS:
1239         if (result == m_shaderSourceMap.end()) {
1240             *value = static_cast<int>(false);
1241             return;
1242         }
1243         *value = static_cast<int>(result->value.isValid);
1244         break;
1245     case INFO_LOG_LENGTH:
1246         if (result == m_shaderSourceMap.end()) {
1247             *value = 0;
1248             return;
1249         }
1250         *value = getShaderInfoLog(shader).length();
1251         break;
1252     case SHADER_SOURCE_LENGTH:
1253         *value = getShaderSource(shader).length();
1254         break;
1255     default:
1256         synthesizeGLError(INVALID_ENUM);
1257     }
1258 }
1259
1260 String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
1261 {
1262     ASSERT(shader);
1263
1264     makeContextCurrent();
1265
1266     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1267     if (result == m_shaderSourceMap.end())
1268         return String(); 
1269
1270     ShaderSourceEntry entry = result->value;
1271     if (!entry.isValid)
1272         return entry.log;
1273
1274     GLint length = 0;
1275     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
1276     if (!length)
1277         return String(); 
1278
1279     GLsizei size = 0;
1280     auto info = std::make_unique<GLchar[]>(length);
1281     ::glGetShaderInfoLog(shader, length, &size, info.get());
1282
1283     return String(info.get());
1284 }
1285
1286 String GraphicsContext3D::getShaderSource(Platform3DObject shader)
1287 {
1288     ASSERT(shader);
1289
1290     makeContextCurrent();
1291
1292     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1293     if (result == m_shaderSourceMap.end())
1294         return String(); 
1295
1296     return result->value.source;
1297 }
1298
1299
1300 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
1301 {
1302     makeContextCurrent();
1303     ::glGetTexParameterfv(target, pname, value);
1304 }
1305
1306 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1307 {
1308     makeContextCurrent();
1309     ::glGetTexParameteriv(target, pname, value);
1310 }
1311
1312 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
1313 {
1314     makeContextCurrent();
1315     ::glGetUniformfv(program, location, value);
1316 }
1317
1318 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
1319 {
1320     makeContextCurrent();
1321     ::glGetUniformiv(program, location, value);
1322 }
1323
1324 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
1325 {
1326     ASSERT(program);
1327
1328     makeContextCurrent();
1329
1330     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, name);
1331     LOG(WebGL, "::getUniformLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
1332     return ::glGetUniformLocation(program, mappedName.utf8().data());
1333 }
1334
1335 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
1336 {
1337     makeContextCurrent();
1338     ::glGetVertexAttribfv(index, pname, value);
1339 }
1340
1341 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
1342 {
1343     makeContextCurrent();
1344     ::glGetVertexAttribiv(index, pname, value);
1345 }
1346
1347 GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
1348 {
1349     makeContextCurrent();
1350
1351     GLvoid* pointer = 0;
1352     ::glGetVertexAttribPointerv(index, pname, &pointer);
1353     return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
1354 }
1355
1356 void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
1357 {
1358     makeContextCurrent();
1359
1360     if (type == HALF_FLOAT_OES)
1361         type = GL_HALF_FLOAT_ARB;
1362
1363     // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size.
1364     ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
1365 }
1366
1367 void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data)
1368 {
1369     makeContextCurrent();
1370     ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
1371 }
1372
1373 void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data)
1374 {
1375     makeContextCurrent();
1376     ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
1377 }
1378
1379 Platform3DObject GraphicsContext3D::createBuffer()
1380 {
1381     makeContextCurrent();
1382     GLuint o = 0;
1383     glGenBuffers(1, &o);
1384     return o;
1385 }
1386
1387 Platform3DObject GraphicsContext3D::createFramebuffer()
1388 {
1389     makeContextCurrent();
1390     GLuint o = 0;
1391     glGenFramebuffersEXT(1, &o);
1392     return o;
1393 }
1394
1395 Platform3DObject GraphicsContext3D::createProgram()
1396 {
1397     makeContextCurrent();
1398     return glCreateProgram();
1399 }
1400
1401 Platform3DObject GraphicsContext3D::createRenderbuffer()
1402 {
1403     makeContextCurrent();
1404     GLuint o = 0;
1405     glGenRenderbuffersEXT(1, &o);
1406     return o;
1407 }
1408
1409 Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
1410 {
1411     makeContextCurrent();
1412     return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
1413 }
1414
1415 Platform3DObject GraphicsContext3D::createTexture()
1416 {
1417     makeContextCurrent();
1418     GLuint o = 0;
1419     glGenTextures(1, &o);
1420     return o;
1421 }
1422
1423 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
1424 {
1425     makeContextCurrent();
1426     glDeleteBuffers(1, &buffer);
1427 }
1428
1429 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
1430 {
1431     makeContextCurrent();
1432     if (framebuffer == m_state.boundFBO) {
1433         // Make sure the framebuffer is not going to be used for drawing
1434         // operations after it gets deleted.
1435         bindFramebuffer(FRAMEBUFFER, 0);
1436     }
1437     glDeleteFramebuffersEXT(1, &framebuffer);
1438 }
1439
1440 void GraphicsContext3D::deleteProgram(Platform3DObject program)
1441 {
1442     makeContextCurrent();
1443     glDeleteProgram(program);
1444 }
1445
1446 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
1447 {
1448     makeContextCurrent();
1449     glDeleteRenderbuffersEXT(1, &renderbuffer);
1450 }
1451
1452 void GraphicsContext3D::deleteShader(Platform3DObject shader)
1453 {
1454     makeContextCurrent();
1455     glDeleteShader(shader);
1456 }
1457
1458 void GraphicsContext3D::deleteTexture(Platform3DObject texture)
1459 {
1460     makeContextCurrent();
1461     if (m_state.boundTexture0 == texture)
1462         m_state.boundTexture0 = 0;
1463     glDeleteTextures(1, &texture);
1464 }
1465
1466 void GraphicsContext3D::synthesizeGLError(GC3Denum error)
1467 {
1468     m_syntheticErrors.add(error);
1469 }
1470
1471 void GraphicsContext3D::markContextChanged()
1472 {
1473     m_layerComposited = false;
1474 }
1475
1476 void GraphicsContext3D::markLayerComposited()
1477 {
1478     m_layerComposited = true;
1479 }
1480
1481 bool GraphicsContext3D::layerComposited() const
1482 {
1483     return m_layerComposited;
1484 }
1485
1486 void GraphicsContext3D::texImage2DDirect(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
1487 {
1488     makeContextCurrent();
1489     ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
1490 }
1491
1492 }
1493
1494 #endif // USE(3D_GRAPHICS)