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