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