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