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