Hook into some shader symbol logic following the ANGLE update in r159533.
[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 bool GraphicsContext3D::areProgramSymbolsValid(Platform3DObject vertexShader, Platform3DObject fragmentShader) const
330 {
331     UNUSED_PARAM(vertexShader);
332     UNUSED_PARAM(fragmentShader);
333     // TODO: Fill me in.
334     return true;
335 }
336
337 IntSize GraphicsContext3D::getInternalFramebufferSize() const
338 {
339     return IntSize(m_currentWidth, m_currentHeight);
340 }
341
342 void GraphicsContext3D::activeTexture(GC3Denum texture)
343 {
344     makeContextCurrent();
345     m_state.activeTexture = texture;
346     ::glActiveTexture(texture);
347 }
348
349 void GraphicsContext3D::attachShader(Platform3DObject program, Platform3DObject shader)
350 {
351     ASSERT(program);
352     ASSERT(shader);
353     makeContextCurrent();
354     ::glAttachShader(program, shader);
355 }
356
357 void GraphicsContext3D::bindAttribLocation(Platform3DObject program, GC3Duint index, const String& name)
358 {
359     ASSERT(program);
360     makeContextCurrent();
361
362     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name);
363     LOG(WebGL, "::bindAttribLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
364     ::glBindAttribLocation(program, index, mappedName.utf8().data());
365 }
366
367 void GraphicsContext3D::bindBuffer(GC3Denum target, Platform3DObject buffer)
368 {
369     makeContextCurrent();
370     ::glBindBuffer(target, buffer);
371 }
372
373 void GraphicsContext3D::bindFramebuffer(GC3Denum target, Platform3DObject buffer)
374 {
375     makeContextCurrent();
376     GLuint fbo;
377     if (buffer)
378         fbo = buffer;
379     else
380 #if PLATFORM(BLACKBERRY)
381         fbo = m_fbo;
382 #else
383         fbo = (m_attrs.antialias ? m_multisampleFBO : m_fbo);
384 #endif
385     if (fbo != m_state.boundFBO) {
386         ::glBindFramebufferEXT(target, fbo);
387         m_state.boundFBO = fbo;
388     }
389 }
390
391 void GraphicsContext3D::bindRenderbuffer(GC3Denum target, Platform3DObject renderbuffer)
392 {
393     makeContextCurrent();
394     ::glBindRenderbufferEXT(target, renderbuffer);
395 }
396
397
398 void GraphicsContext3D::bindTexture(GC3Denum target, Platform3DObject texture)
399 {
400     makeContextCurrent();
401     if (m_state.activeTexture == GL_TEXTURE0 && target == GL_TEXTURE_2D)
402         m_state.boundTexture0 = texture;
403     ::glBindTexture(target, texture);
404 }
405
406 void GraphicsContext3D::blendColor(GC3Dclampf red, GC3Dclampf green, GC3Dclampf blue, GC3Dclampf alpha)
407 {
408     makeContextCurrent();
409     ::glBlendColor(red, green, blue, alpha);
410 }
411
412 void GraphicsContext3D::blendEquation(GC3Denum mode)
413 {
414     makeContextCurrent();
415     ::glBlendEquation(mode);
416 }
417
418 void GraphicsContext3D::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha)
419 {
420     makeContextCurrent();
421     ::glBlendEquationSeparate(modeRGB, modeAlpha);
422 }
423
424
425 void GraphicsContext3D::blendFunc(GC3Denum sfactor, GC3Denum dfactor)
426 {
427     makeContextCurrent();
428     ::glBlendFunc(sfactor, dfactor);
429 }       
430
431 void GraphicsContext3D::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha)
432 {
433     makeContextCurrent();
434     ::glBlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
435 }
436
437 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage)
438 {
439     makeContextCurrent();
440     ::glBufferData(target, size, 0, usage);
441 }
442
443 void GraphicsContext3D::bufferData(GC3Denum target, GC3Dsizeiptr size, const void* data, GC3Denum usage)
444 {
445     makeContextCurrent();
446     ::glBufferData(target, size, data, usage);
447 }
448
449 void GraphicsContext3D::bufferSubData(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr size, const void* data)
450 {
451     makeContextCurrent();
452     ::glBufferSubData(target, offset, size, data);
453 }
454
455 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
456 {
457     makeContextCurrent();
458     return ::glCheckFramebufferStatusEXT(target);
459 }
460
461 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
462 {
463     makeContextCurrent();
464     ::glClearColor(r, g, b, a);
465 }
466
467 void GraphicsContext3D::clear(GC3Dbitfield mask)
468 {
469     makeContextCurrent();
470     ::glClear(mask);
471 }
472
473 void GraphicsContext3D::clearStencil(GC3Dint s)
474 {
475     makeContextCurrent();
476     ::glClearStencil(s);
477 }
478
479 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
480 {
481     makeContextCurrent();
482     ::glColorMask(red, green, blue, alpha);
483 }
484
485 void GraphicsContext3D::compileShader(Platform3DObject shader)
486 {
487     ASSERT(shader);
488     makeContextCurrent();
489
490     // Turn on name mapping. Due to the way ANGLE name hashing works, we
491     // point a global hashmap to the map owned by this context.
492     ShBuiltInResources ANGLEResources = m_compiler.getResources();
493     ShHashFunction64 previousHashFunction = ANGLEResources.HashFunction;
494     ANGLEResources.HashFunction = nameHashForShader;
495
496     if (!nameHashMapForShaders)
497         nameHashMapForShaders = adoptPtr(new ShaderNameHash);
498     currentNameHashMapForShader = nameHashMapForShaders.get();
499     m_compiler.setResources(ANGLEResources);
500
501     String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader);
502
503     ANGLEResources.HashFunction = previousHashFunction;
504     m_compiler.setResources(ANGLEResources);
505     currentNameHashMapForShader = nullptr;
506
507     if (!translatedShaderSource.length())
508         return;
509
510     const CString& translatedShaderCString = translatedShaderSource.utf8();
511     const char* translatedShaderPtr = translatedShaderCString.data();
512     int translatedShaderLength = translatedShaderCString.length();
513
514     LOG(WebGL, "--- begin original shader source ---\n%s\n--- end original shader source ---\n", getShaderSource(shader).utf8().data());
515     LOG(WebGL, "--- begin translated shader source ---\n%s\n--- end translated shader source ---", translatedShaderPtr);
516
517     ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
518     
519     ::glCompileShader(shader);
520     
521     int GLCompileSuccess;
522     
523     ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
524
525     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
526     GraphicsContext3D::ShaderSourceEntry& entry = result->value;
527
528     // Populate the shader log
529     GLint length = 0;
530     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
531
532     if (length) {
533         GLsizei size = 0;
534         auto info = std::make_unique<GLchar[]>(length);
535         ::glGetShaderInfoLog(shader, length, &size, info.get());
536
537         entry.log = info.get();
538     }
539
540     if (GLCompileSuccess != GL_TRUE) {
541         entry.isValid = false;
542         LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile.");
543 #if PLATFORM(BLACKBERRY) && !defined(NDEBUG)
544         BBLOG(BlackBerry::Platform::LogLevelWarn, "The shader validated, but didn't compile.\n");
545 #endif
546     }
547 }
548
549 void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
550 {
551     makeContextCurrent();
552 #if !PLATFORM(BLACKBERRY)
553     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
554         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
555         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
556     }
557 #endif
558     ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
559 #if !PLATFORM(BLACKBERRY)
560     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
561         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
562 #endif
563 }
564
565 void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
566 {
567     makeContextCurrent();
568 #if !PLATFORM(BLACKBERRY)
569     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
570         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
571         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
572     }
573 #endif
574     ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
575 #if !PLATFORM(BLACKBERRY)
576     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
577         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
578 #endif
579 }
580
581 void GraphicsContext3D::cullFace(GC3Denum mode)
582 {
583     makeContextCurrent();
584     ::glCullFace(mode);
585 }
586
587 void GraphicsContext3D::depthFunc(GC3Denum func)
588 {
589     makeContextCurrent();
590     ::glDepthFunc(func);
591 }
592
593 void GraphicsContext3D::depthMask(GC3Dboolean flag)
594 {
595     makeContextCurrent();
596     ::glDepthMask(flag);
597 }
598
599 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
600 {
601     ASSERT(program);
602     ASSERT(shader);
603     makeContextCurrent();
604     ::glDetachShader(program, shader);
605 }
606
607 void GraphicsContext3D::disable(GC3Denum cap)
608 {
609     makeContextCurrent();
610     ::glDisable(cap);
611 }
612
613 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
614 {
615     makeContextCurrent();
616     ::glDisableVertexAttribArray(index);
617 }
618
619 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
620 {
621     makeContextCurrent();
622     ::glDrawArrays(mode, first, count);
623 }
624
625 void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
626 {
627     makeContextCurrent();
628     ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
629 }
630
631 void GraphicsContext3D::enable(GC3Denum cap)
632 {
633     makeContextCurrent();
634     ::glEnable(cap);
635 }
636
637 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
638 {
639     makeContextCurrent();
640     ::glEnableVertexAttribArray(index);
641 }
642
643 void GraphicsContext3D::finish()
644 {
645     makeContextCurrent();
646     ::glFinish();
647 }
648
649 void GraphicsContext3D::flush()
650 {
651     makeContextCurrent();
652     ::glFlush();
653 }
654
655 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
656 {
657     makeContextCurrent();
658     ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
659 }
660
661 void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
662 {
663     makeContextCurrent();
664     ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
665 }
666
667 void GraphicsContext3D::frontFace(GC3Denum mode)
668 {
669     makeContextCurrent();
670     ::glFrontFace(mode);
671 }
672
673 void GraphicsContext3D::generateMipmap(GC3Denum target)
674 {
675     makeContextCurrent();
676     ::glGenerateMipmap(target);
677 }
678
679 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
680 {
681     if (!program) {
682         synthesizeGLError(INVALID_VALUE);
683         return false;
684     }
685     makeContextCurrent();
686     GLint maxAttributeSize = 0;
687     ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
688     auto name = std::make_unique<GLchar[]>(maxAttributeSize); // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination.
689     GLsizei nameLength = 0;
690     GLint size = 0;
691     GLenum type = 0;
692     ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name.get());
693     if (!nameLength)
694         return false;
695     
696     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, String(name.get(), nameLength));
697     
698     info.name = originalName;
699     info.type = type;
700     info.size = size;
701     return true;
702 }
703
704 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
705 {
706     if (!program) {
707         synthesizeGLError(INVALID_VALUE);
708         return false;
709     }
710
711     makeContextCurrent();
712     GLint maxUniformSize = 0;
713     ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
714
715     auto name = std::make_unique<GLchar[]>(maxUniformSize); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination.
716     GLsizei nameLength = 0;
717     GLint size = 0;
718     GLenum type = 0;
719     ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get());
720     if (!nameLength)
721         return false;
722     
723     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, String(name.get(), nameLength));
724     
725     info.name = originalName;
726     info.type = type;
727     info.size = size;
728     return true;
729 }
730     
731 void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
732 {
733     if (!program) {
734         synthesizeGLError(INVALID_VALUE);
735         return;
736     }
737     makeContextCurrent();
738     ::glGetAttachedShaders(program, maxCount, count, shaders);
739 }
740
741 String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
742 {
743     GC3Dsizei count;
744     Platform3DObject shaders[2];
745     getAttachedShaders(program, 2, &count, shaders);
746
747     for (GC3Dsizei i = 0; i < count; ++i) {
748         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
749         if (result == m_shaderSourceMap.end())
750             continue;
751
752         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
753         ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name);
754         if (symbolEntry != symbolMap.end())
755             return symbolEntry->value.mappedName;
756     }
757     return name;
758 }
759     
760 String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
761 {
762     GC3Dsizei count;
763     Platform3DObject shaders[2];
764     getAttachedShaders(program, 2, &count, shaders);
765     
766     for (GC3Dsizei i = 0; i < count; ++i) {
767         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
768         if (result == m_shaderSourceMap.end())
769             continue;
770         
771         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
772         ShaderSymbolMap::const_iterator symbolEntry;
773         for (symbolEntry = symbolMap.begin(); symbolEntry != symbolMap.end(); ++symbolEntry) {
774             if (symbolEntry->value.mappedName == name)
775                 return symbolEntry->key;
776         }
777     }
778     return name;
779 }
780
781 int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
782 {
783     if (!program)
784         return -1;
785
786     makeContextCurrent();
787
788     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name);
789     LOG(WebGL, "::getAttribLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
790     return ::glGetAttribLocation(program, mappedName.utf8().data());
791 }
792
793 GraphicsContext3D::Attributes GraphicsContext3D::getContextAttributes()
794 {
795     return m_attrs;
796 }
797
798 GC3Denum GraphicsContext3D::getError()
799 {
800     if (m_syntheticErrors.size() > 0) {
801         ListHashSet<GC3Denum>::iterator iter = m_syntheticErrors.begin();
802         GC3Denum err = *iter;
803         m_syntheticErrors.remove(iter);
804         return err;
805     }
806
807     makeContextCurrent();
808     return ::glGetError();
809 }
810
811 String GraphicsContext3D::getString(GC3Denum name)
812 {
813     makeContextCurrent();
814     return String(reinterpret_cast<const char*>(::glGetString(name)));
815 }
816
817 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
818 {
819     makeContextCurrent();
820     ::glHint(target, mode);
821 }
822
823 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
824 {
825     if (!buffer)
826         return GL_FALSE;
827
828     makeContextCurrent();
829     return ::glIsBuffer(buffer);
830 }
831
832 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
833 {
834     makeContextCurrent();
835     return ::glIsEnabled(cap);
836 }
837
838 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
839 {
840     if (!framebuffer)
841         return GL_FALSE;
842
843     makeContextCurrent();
844     return ::glIsFramebufferEXT(framebuffer);
845 }
846
847 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
848 {
849     if (!program)
850         return GL_FALSE;
851
852     makeContextCurrent();
853     return ::glIsProgram(program);
854 }
855
856 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
857 {
858     if (!renderbuffer)
859         return GL_FALSE;
860
861     makeContextCurrent();
862     return ::glIsRenderbufferEXT(renderbuffer);
863 }
864
865 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
866 {
867     if (!shader)
868         return GL_FALSE;
869
870     makeContextCurrent();
871     return ::glIsShader(shader);
872 }
873
874 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
875 {
876     if (!texture)
877         return GL_FALSE;
878
879     makeContextCurrent();
880     return ::glIsTexture(texture);
881 }
882
883 void GraphicsContext3D::lineWidth(GC3Dfloat width)
884 {
885     makeContextCurrent();
886     ::glLineWidth(width);
887 }
888
889 void GraphicsContext3D::linkProgram(Platform3DObject program)
890 {
891     ASSERT(program);
892     makeContextCurrent();
893     ::glLinkProgram(program);
894 }
895
896 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
897 {
898     makeContextCurrent();
899     ::glPixelStorei(pname, param);
900 }
901
902 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
903 {
904     makeContextCurrent();
905     ::glPolygonOffset(factor, units);
906 }
907
908 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
909 {
910     makeContextCurrent();
911     ::glSampleCoverage(value, invert);
912 }
913
914 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
915 {
916     makeContextCurrent();
917     ::glScissor(x, y, width, height);
918 }
919
920 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
921 {
922     ASSERT(shader);
923
924     makeContextCurrent();
925
926     ShaderSourceEntry entry;
927
928     entry.source = string;
929
930     m_shaderSourceMap.set(shader, entry);
931 }
932
933 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
934 {
935     makeContextCurrent();
936     ::glStencilFunc(func, ref, mask);
937 }
938
939 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
940 {
941     makeContextCurrent();
942     ::glStencilFuncSeparate(face, func, ref, mask);
943 }
944
945 void GraphicsContext3D::stencilMask(GC3Duint mask)
946 {
947     makeContextCurrent();
948     ::glStencilMask(mask);
949 }
950
951 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
952 {
953     makeContextCurrent();
954     ::glStencilMaskSeparate(face, mask);
955 }
956
957 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
958 {
959     makeContextCurrent();
960     ::glStencilOp(fail, zfail, zpass);
961 }
962
963 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
964 {
965     makeContextCurrent();
966     ::glStencilOpSeparate(face, fail, zfail, zpass);
967 }
968
969 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
970 {
971     makeContextCurrent();
972     ::glTexParameterf(target, pname, value);
973 }
974
975 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
976 {
977     makeContextCurrent();
978     ::glTexParameteri(target, pname, value);
979 }
980
981 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
982 {
983     makeContextCurrent();
984     ::glUniform1f(location, v0);
985 }
986
987 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
988 {
989     makeContextCurrent();
990     ::glUniform1fv(location, size, array);
991 }
992
993 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
994 {
995     makeContextCurrent();
996     ::glUniform2f(location, v0, v1);
997 }
998
999 void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1000 {
1001     // FIXME: length needs to be a multiple of 2.
1002     makeContextCurrent();
1003     ::glUniform2fv(location, size, array);
1004 }
1005
1006 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1007 {
1008     makeContextCurrent();
1009     ::glUniform3f(location, v0, v1, v2);
1010 }
1011
1012 void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1013 {
1014     // FIXME: length needs to be a multiple of 3.
1015     makeContextCurrent();
1016     ::glUniform3fv(location, size, array);
1017 }
1018
1019 void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1020 {
1021     makeContextCurrent();
1022     ::glUniform4f(location, v0, v1, v2, v3);
1023 }
1024
1025 void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1026 {
1027     // FIXME: length needs to be a multiple of 4.
1028     makeContextCurrent();
1029     ::glUniform4fv(location, size, array);
1030 }
1031
1032 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
1033 {
1034     makeContextCurrent();
1035     ::glUniform1i(location, v0);
1036 }
1037
1038 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1039 {
1040     makeContextCurrent();
1041     ::glUniform1iv(location, size, array);
1042 }
1043
1044 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
1045 {
1046     makeContextCurrent();
1047     ::glUniform2i(location, v0, v1);
1048 }
1049
1050 void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1051 {
1052     // FIXME: length needs to be a multiple of 2.
1053     makeContextCurrent();
1054     ::glUniform2iv(location, size, array);
1055 }
1056
1057 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
1058 {
1059     makeContextCurrent();
1060     ::glUniform3i(location, v0, v1, v2);
1061 }
1062
1063 void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1064 {
1065     // FIXME: length needs to be a multiple of 3.
1066     makeContextCurrent();
1067     ::glUniform3iv(location, size, array);
1068 }
1069
1070 void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
1071 {
1072     makeContextCurrent();
1073     ::glUniform4i(location, v0, v1, v2, v3);
1074 }
1075
1076 void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1077 {
1078     // FIXME: length needs to be a multiple of 4.
1079     makeContextCurrent();
1080     ::glUniform4iv(location, size, array);
1081 }
1082
1083 void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1084 {
1085     // FIXME: length needs to be a multiple of 4.
1086     makeContextCurrent();
1087     ::glUniformMatrix2fv(location, size, transpose, array);
1088 }
1089
1090 void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1091 {
1092     // FIXME: length needs to be a multiple of 9.
1093     makeContextCurrent();
1094     ::glUniformMatrix3fv(location, size, transpose, array);
1095 }
1096
1097 void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1098 {
1099     // FIXME: length needs to be a multiple of 16.
1100     makeContextCurrent();
1101     ::glUniformMatrix4fv(location, size, transpose, array);
1102 }
1103
1104 void GraphicsContext3D::useProgram(Platform3DObject program)
1105 {
1106     makeContextCurrent();
1107     ::glUseProgram(program);
1108 }
1109
1110 void GraphicsContext3D::validateProgram(Platform3DObject program)
1111 {
1112     ASSERT(program);
1113
1114     makeContextCurrent();
1115     ::glValidateProgram(program);
1116 }
1117
1118 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
1119 {
1120     makeContextCurrent();
1121     ::glVertexAttrib1f(index, v0);
1122 }
1123
1124 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
1125 {
1126     makeContextCurrent();
1127     ::glVertexAttrib1fv(index, array);
1128 }
1129
1130 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
1131 {
1132     makeContextCurrent();
1133     ::glVertexAttrib2f(index, v0, v1);
1134 }
1135
1136 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
1137 {
1138     makeContextCurrent();
1139     ::glVertexAttrib2fv(index, array);
1140 }
1141
1142 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1143 {
1144     makeContextCurrent();
1145     ::glVertexAttrib3f(index, v0, v1, v2);
1146 }
1147
1148 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
1149 {
1150     makeContextCurrent();
1151     ::glVertexAttrib3fv(index, array);
1152 }
1153
1154 void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1155 {
1156     makeContextCurrent();
1157     ::glVertexAttrib4f(index, v0, v1, v2, v3);
1158 }
1159
1160 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
1161 {
1162     makeContextCurrent();
1163     ::glVertexAttrib4fv(index, array);
1164 }
1165
1166 void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
1167 {
1168     makeContextCurrent();
1169     ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
1170 }
1171
1172 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1173 {
1174     makeContextCurrent();
1175     ::glViewport(x, y, width, height);
1176 }
1177
1178 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
1179 {
1180     makeContextCurrent();
1181     ::glGetBooleanv(pname, value);
1182 }
1183
1184 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1185 {
1186     makeContextCurrent();
1187     ::glGetBufferParameteriv(target, pname, value);
1188 }
1189
1190 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
1191 {
1192     makeContextCurrent();
1193     ::glGetFloatv(pname, value);
1194 }
1195
1196 void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
1197 {
1198     makeContextCurrent();
1199     if (attachment == DEPTH_STENCIL_ATTACHMENT)
1200         attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
1201     ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
1202 }
1203
1204 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
1205 {
1206     makeContextCurrent();
1207     ::glGetProgramiv(program, pname, value);
1208 }
1209
1210 String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
1211 {
1212     ASSERT(program);
1213
1214     makeContextCurrent();
1215     GLint length = 0;
1216     ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
1217     if (!length)
1218         return String(); 
1219
1220     GLsizei size = 0;
1221     auto info = std::make_unique<GLchar[]>(length);
1222     ::glGetProgramInfoLog(program, length, &size, info.get());
1223
1224     return String(info.get());
1225 }
1226
1227 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1228 {
1229     makeContextCurrent();
1230     ::glGetRenderbufferParameterivEXT(target, pname, value);
1231 }
1232
1233 void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
1234 {
1235     ASSERT(shader);
1236
1237     makeContextCurrent();
1238
1239     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1240     
1241     switch (pname) {
1242     case DELETE_STATUS:
1243     case SHADER_TYPE:
1244         ::glGetShaderiv(shader, pname, value);
1245         break;
1246     case COMPILE_STATUS:
1247         if (result == m_shaderSourceMap.end()) {
1248             *value = static_cast<int>(false);
1249             return;
1250         }
1251         *value = static_cast<int>(result->value.isValid);
1252         break;
1253     case INFO_LOG_LENGTH:
1254         if (result == m_shaderSourceMap.end()) {
1255             *value = 0;
1256             return;
1257         }
1258         *value = getShaderInfoLog(shader).length();
1259         break;
1260     case SHADER_SOURCE_LENGTH:
1261         *value = getShaderSource(shader).length();
1262         break;
1263     default:
1264         synthesizeGLError(INVALID_ENUM);
1265     }
1266 }
1267
1268 String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
1269 {
1270     ASSERT(shader);
1271
1272     makeContextCurrent();
1273
1274     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1275     if (result == m_shaderSourceMap.end())
1276         return String(); 
1277
1278     ShaderSourceEntry entry = result->value;
1279     if (!entry.isValid)
1280         return entry.log;
1281
1282     GLint length = 0;
1283     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
1284     if (!length)
1285         return String(); 
1286
1287     GLsizei size = 0;
1288     auto info = std::make_unique<GLchar[]>(length);
1289     ::glGetShaderInfoLog(shader, length, &size, info.get());
1290
1291     return String(info.get());
1292 }
1293
1294 String GraphicsContext3D::getShaderSource(Platform3DObject shader)
1295 {
1296     ASSERT(shader);
1297
1298     makeContextCurrent();
1299
1300     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
1301     if (result == m_shaderSourceMap.end())
1302         return String(); 
1303
1304     return result->value.source;
1305 }
1306
1307
1308 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
1309 {
1310     makeContextCurrent();
1311     ::glGetTexParameterfv(target, pname, value);
1312 }
1313
1314 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1315 {
1316     makeContextCurrent();
1317     ::glGetTexParameteriv(target, pname, value);
1318 }
1319
1320 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
1321 {
1322     makeContextCurrent();
1323     ::glGetUniformfv(program, location, value);
1324 }
1325
1326 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
1327 {
1328     makeContextCurrent();
1329     ::glGetUniformiv(program, location, value);
1330 }
1331
1332 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
1333 {
1334     ASSERT(program);
1335
1336     makeContextCurrent();
1337
1338     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, name);
1339     LOG(WebGL, "::getUniformLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
1340     return ::glGetUniformLocation(program, mappedName.utf8().data());
1341 }
1342
1343 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
1344 {
1345     makeContextCurrent();
1346     ::glGetVertexAttribfv(index, pname, value);
1347 }
1348
1349 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
1350 {
1351     makeContextCurrent();
1352     ::glGetVertexAttribiv(index, pname, value);
1353 }
1354
1355 GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
1356 {
1357     makeContextCurrent();
1358
1359     GLvoid* pointer = 0;
1360     ::glGetVertexAttribPointerv(index, pname, &pointer);
1361     return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
1362 }
1363
1364 void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
1365 {
1366     makeContextCurrent();
1367
1368     if (type == HALF_FLOAT_OES)
1369         type = GL_HALF_FLOAT_ARB;
1370
1371     // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size.
1372     ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
1373 }
1374
1375 void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data)
1376 {
1377     makeContextCurrent();
1378     ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
1379 }
1380
1381 void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data)
1382 {
1383     makeContextCurrent();
1384     ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
1385 }
1386
1387 Platform3DObject GraphicsContext3D::createBuffer()
1388 {
1389     makeContextCurrent();
1390     GLuint o = 0;
1391     glGenBuffers(1, &o);
1392     return o;
1393 }
1394
1395 Platform3DObject GraphicsContext3D::createFramebuffer()
1396 {
1397     makeContextCurrent();
1398     GLuint o = 0;
1399     glGenFramebuffersEXT(1, &o);
1400     return o;
1401 }
1402
1403 Platform3DObject GraphicsContext3D::createProgram()
1404 {
1405     makeContextCurrent();
1406     return glCreateProgram();
1407 }
1408
1409 Platform3DObject GraphicsContext3D::createRenderbuffer()
1410 {
1411     makeContextCurrent();
1412     GLuint o = 0;
1413     glGenRenderbuffersEXT(1, &o);
1414     return o;
1415 }
1416
1417 Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
1418 {
1419     makeContextCurrent();
1420     return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
1421 }
1422
1423 Platform3DObject GraphicsContext3D::createTexture()
1424 {
1425     makeContextCurrent();
1426     GLuint o = 0;
1427     glGenTextures(1, &o);
1428     return o;
1429 }
1430
1431 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
1432 {
1433     makeContextCurrent();
1434     glDeleteBuffers(1, &buffer);
1435 }
1436
1437 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
1438 {
1439     makeContextCurrent();
1440     if (framebuffer == m_state.boundFBO) {
1441         // Make sure the framebuffer is not going to be used for drawing
1442         // operations after it gets deleted.
1443         bindFramebuffer(FRAMEBUFFER, 0);
1444     }
1445     glDeleteFramebuffersEXT(1, &framebuffer);
1446 }
1447
1448 void GraphicsContext3D::deleteProgram(Platform3DObject program)
1449 {
1450     makeContextCurrent();
1451     glDeleteProgram(program);
1452 }
1453
1454 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
1455 {
1456     makeContextCurrent();
1457     glDeleteRenderbuffersEXT(1, &renderbuffer);
1458 }
1459
1460 void GraphicsContext3D::deleteShader(Platform3DObject shader)
1461 {
1462     makeContextCurrent();
1463     glDeleteShader(shader);
1464 }
1465
1466 void GraphicsContext3D::deleteTexture(Platform3DObject texture)
1467 {
1468     makeContextCurrent();
1469     if (m_state.boundTexture0 == texture)
1470         m_state.boundTexture0 = 0;
1471     glDeleteTextures(1, &texture);
1472 }
1473
1474 void GraphicsContext3D::synthesizeGLError(GC3Denum error)
1475 {
1476     m_syntheticErrors.add(error);
1477 }
1478
1479 void GraphicsContext3D::markContextChanged()
1480 {
1481     m_layerComposited = false;
1482 }
1483
1484 void GraphicsContext3D::markLayerComposited()
1485 {
1486     m_layerComposited = true;
1487 }
1488
1489 bool GraphicsContext3D::layerComposited() const
1490 {
1491     return m_layerComposited;
1492 }
1493
1494 void GraphicsContext3D::texImage2DDirect(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
1495 {
1496     makeContextCurrent();
1497     ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
1498 }
1499
1500 }
1501
1502 #endif // USE(3D_GRAPHICS)