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