Unreviewed, rolling out r212639.
[WebKit-https.git] / Source / WebCore / platform / graphics / opengl / GraphicsContext3DOpenGLCommon.cpp
1 /*
2  * Copyright (C) 2010, 2014 Apple Inc. All rights reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  * Copyright (C) 2012 ChangSeok Oh <shivamidow@gmail.com>
5  * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
20  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30
31 #if ENABLE(GRAPHICS_CONTEXT_3D)
32
33 #include "GraphicsContext3D.h"
34 #if PLATFORM(IOS)
35 #include "GraphicsContext3DIOS.h"
36 #endif
37
38 #if USE(OPENGL_ES_2)
39 #include "Extensions3DOpenGLES.h"
40 #else
41 #include "Extensions3DOpenGL.h"
42 #endif
43 #include "ANGLEWebKitBridge.h"
44 #include "GraphicsContext.h"
45 #include "ImageBuffer.h"
46 #include "ImageData.h"
47 #include "IntRect.h"
48 #include "IntSize.h"
49 #include "Logging.h"
50 #include "TemporaryOpenGLSetting.h"
51 #include "WebGLRenderingContextBase.h"
52 #include <cstring>
53 #include <wtf/HexNumber.h>
54 #include <wtf/MainThread.h>
55 #include <wtf/ThreadSpecific.h>
56 #include <wtf/text/CString.h>
57 #include <wtf/text/StringBuilder.h>
58 #include <yarr/RegularExpression.h>
59
60 #if PLATFORM(IOS)
61 #import <OpenGLES/ES2/glext.h>
62 #import <OpenGLES/ES3/gl.h>
63 // From <OpenGLES/glext.h>
64 #define GL_RGBA32F_ARB                      0x8814
65 #define GL_RGB32F_ARB                       0x8815
66 #else
67 #if USE(OPENGL_ES_2)
68 #include "OpenGLESShims.h"
69 #elif PLATFORM(MAC)
70 #define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
71 #include <OpenGL/gl.h>
72 #include <OpenGL/gl3.h>
73 #include <OpenGL/gl3ext.h>
74 #undef GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
75 #elif PLATFORM(GTK) || PLATFORM(WIN)
76 #include "OpenGLShims.h"
77 #endif
78 #endif
79
80 using namespace WTF;
81
82 namespace WebCore {
83
84 static ThreadSpecific<ShaderNameHash*>& getCurrentNameHashMapForShader()
85 {
86     static std::once_flag onceFlag;
87     static ThreadSpecific<ShaderNameHash*>* sharedNameHash;
88     std::call_once(onceFlag, [] {
89         sharedNameHash = new ThreadSpecific<ShaderNameHash*>;
90     });
91
92     return *sharedNameHash;
93 }
94
95 static void setCurrentNameHashMapForShader(ShaderNameHash* shaderNameHash)
96 {
97     *getCurrentNameHashMapForShader() = shaderNameHash;
98 }
99
100 // Hash function used by the ANGLE translator/compiler to do
101 // symbol name mangling. Since this is a static method, before
102 // calling compileShader we set currentNameHashMapForShader
103 // to point to the map kept by the current instance of GraphicsContext3D.
104
105 static uint64_t nameHashForShader(const char* name, size_t length)
106 {
107     if (!length)
108         return 0;
109
110     CString nameAsCString = CString(name);
111
112     // Look up name in our local map.
113     ShaderNameHash*& currentNameHashMapForShader = *getCurrentNameHashMapForShader();
114     ShaderNameHash::iterator findResult = currentNameHashMapForShader->find(nameAsCString);
115     if (findResult != currentNameHashMapForShader->end())
116         return findResult->value;
117
118     unsigned hashValue = nameAsCString.hash();
119
120     // Convert the 32-bit hash from CString::hash into a 64-bit result
121     // by shifting then adding the size of our table. Overflow would
122     // only be a problem if we're already hashing to the same value (and
123     // we're hoping that over the lifetime of the context we
124     // don't have that many symbols).
125
126     uint64_t result = hashValue;
127     result = (result << 32) + (currentNameHashMapForShader->size() + 1);
128
129     currentNameHashMapForShader->set(nameAsCString, result);
130     return result;
131 }
132
133 RefPtr<GraphicsContext3D> GraphicsContext3D::createForCurrentGLContext()
134 {
135     auto context = adoptRef(*new GraphicsContext3D({ }, 0, GraphicsContext3D::RenderToCurrentGLContext));
136 #if USE(TEXTURE_MAPPER)
137     if (!context->m_texmapLayer)
138         return nullptr;
139 #else
140     if (!context->m_private)
141         return nullptr;
142 #endif
143     return WTFMove(context);
144 }
145
146 void GraphicsContext3D::validateDepthStencil(const char* packedDepthStencilExtension)
147 {
148     Extensions3D& extensions = getExtensions();
149     if (m_attrs.stencil) {
150         if (extensions.supports(packedDepthStencilExtension)) {
151             extensions.ensureEnabled(packedDepthStencilExtension);
152             // Force depth if stencil is true.
153             m_attrs.depth = true;
154         } else
155             m_attrs.stencil = false;
156     }
157     if (m_attrs.antialias) {
158         if (!extensions.supports("GL_ANGLE_framebuffer_multisample") || isGLES2Compliant())
159             m_attrs.antialias = false;
160         else
161             extensions.ensureEnabled("GL_ANGLE_framebuffer_multisample");
162     }
163 }
164
165 void GraphicsContext3D::paintRenderingResultsToCanvas(ImageBuffer* imageBuffer)
166 {
167     int rowBytes = m_currentWidth * 4;
168     int totalBytes = rowBytes * m_currentHeight;
169
170     auto pixels = std::make_unique<unsigned char[]>(totalBytes);
171     if (!pixels)
172         return;
173
174     readRenderingResults(pixels.get(), totalBytes);
175
176     if (!m_attrs.premultipliedAlpha) {
177         for (int i = 0; i < totalBytes; i += 4) {
178             // Premultiply alpha.
179             pixels[i + 0] = std::min(255, pixels[i + 0] * pixels[i + 3] / 255);
180             pixels[i + 1] = std::min(255, pixels[i + 1] * pixels[i + 3] / 255);
181             pixels[i + 2] = std::min(255, pixels[i + 2] * pixels[i + 3] / 255);
182         }
183     }
184
185 #if USE(CG)
186     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight,
187                   imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context());
188 #else
189     paintToCanvas(pixels.get(), m_currentWidth, m_currentHeight, imageBuffer->internalSize().width(), imageBuffer->internalSize().height(), imageBuffer->context().platformContext());
190 #endif
191
192 #if PLATFORM(IOS)
193     endPaint();
194 #endif
195 }
196
197 bool GraphicsContext3D::paintCompositedResultsToCanvas(ImageBuffer*)
198 {
199     // Not needed at the moment, so return that nothing was done.
200     return false;
201 }
202
203 RefPtr<ImageData> GraphicsContext3D::paintRenderingResultsToImageData()
204 {
205     // Reading premultiplied alpha would involve unpremultiplying, which is
206     // lossy.
207     if (m_attrs.premultipliedAlpha)
208         return nullptr;
209
210     auto imageData = ImageData::create(IntSize(m_currentWidth, m_currentHeight));
211     unsigned char* pixels = imageData->data()->data();
212     int totalBytes = 4 * m_currentWidth * m_currentHeight;
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_THREADED)
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_THREADED)
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     ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
253     ::glActiveTexture(GL_TEXTURE0);
254     ::glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
255     ::glCopyTexImage2D(GL_TEXTURE_2D, 0, m_internalColorFormat, 0, 0, m_currentWidth, m_currentHeight, 0);
256     ::glBindTexture(GL_TEXTURE_2D, m_state.boundTexture0);
257     ::glActiveTexture(m_state.activeTexture);
258     if (m_state.boundFBO != m_fbo)
259         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO);
260     ::glFlush();
261 }
262
263 void GraphicsContext3D::readRenderingResults(unsigned char *pixels, int pixelsSize)
264 {
265     if (pixelsSize < m_currentWidth * m_currentHeight * 4)
266         return;
267
268     makeContextCurrent();
269
270     bool mustRestoreFBO = false;
271     if (m_attrs.antialias) {
272         resolveMultisamplingIfNecessary();
273         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
274         mustRestoreFBO = true;
275     } else {
276         if (m_state.boundFBO != m_fbo) {
277             mustRestoreFBO = true;
278             ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
279         }
280     }
281
282     GLint packAlignment = 4;
283     bool mustRestorePackAlignment = false;
284     ::glGetIntegerv(GL_PACK_ALIGNMENT, &packAlignment);
285     if (packAlignment > 4) {
286         ::glPixelStorei(GL_PACK_ALIGNMENT, 4);
287         mustRestorePackAlignment = true;
288     }
289
290     readPixelsAndConvertToBGRAIfNecessary(0, 0, m_currentWidth, m_currentHeight, pixels);
291
292     if (mustRestorePackAlignment)
293         ::glPixelStorei(GL_PACK_ALIGNMENT, packAlignment);
294
295     if (mustRestoreFBO)
296         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_state.boundFBO);
297 }
298
299 void GraphicsContext3D::reshape(int width, int height)
300 {
301     if (!platformGraphicsContext3D())
302         return;
303
304     if (width == m_currentWidth && height == m_currentHeight)
305         return;
306
307     markContextChanged();
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 #if PLATFORM(MAC) || PLATFORM(IOS)
551 void* GraphicsContext3D::mapBufferRange(GC3Denum target, GC3Dintptr offset, GC3Dsizeiptr length, GC3Dbitfield access)
552 {
553     makeContextCurrent();
554     return ::glMapBufferRange(target, offset, length, access);
555 }
556
557 GC3Dboolean GraphicsContext3D::unmapBuffer(GC3Denum target)
558 {
559     makeContextCurrent();
560     return ::glUnmapBuffer(target);
561 }
562
563 void GraphicsContext3D::copyBufferSubData(GC3Denum readTarget, GC3Denum writeTarget, GC3Dintptr readOffset, GC3Dintptr writeOffset, GC3Dsizeiptr size)
564 {
565     makeContextCurrent();
566     ::glCopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
567 }
568
569 void GraphicsContext3D::texStorage2D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height)
570 {
571     makeContextCurrent();
572     ::glTexStorage2D(target, levels, internalformat, width, height);
573 }
574
575 void GraphicsContext3D::texStorage3D(GC3Denum target, GC3Dsizei levels, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dsizei depth)
576 {
577     makeContextCurrent();
578     ::glTexStorage3D(target, levels, internalformat, width, height, depth);
579 }
580 #endif
581
582 GC3Denum GraphicsContext3D::checkFramebufferStatus(GC3Denum target)
583 {
584     makeContextCurrent();
585     return ::glCheckFramebufferStatusEXT(target);
586 }
587
588 void GraphicsContext3D::clearColor(GC3Dclampf r, GC3Dclampf g, GC3Dclampf b, GC3Dclampf a)
589 {
590     makeContextCurrent();
591     ::glClearColor(r, g, b, a);
592 }
593
594 void GraphicsContext3D::clear(GC3Dbitfield mask)
595 {
596     makeContextCurrent();
597     ::glClear(mask);
598 }
599
600 void GraphicsContext3D::clearStencil(GC3Dint s)
601 {
602     makeContextCurrent();
603     ::glClearStencil(s);
604 }
605
606 void GraphicsContext3D::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha)
607 {
608     makeContextCurrent();
609     ::glColorMask(red, green, blue, alpha);
610 }
611
612 void GraphicsContext3D::compileShader(Platform3DObject shader)
613 {
614     ASSERT(shader);
615     makeContextCurrent();
616
617     // Turn on name mapping. Due to the way ANGLE name hashing works, we
618     // point a global hashmap to the map owned by this context.
619     ShBuiltInResources ANGLEResources = m_compiler.getResources();
620     ShHashFunction64 previousHashFunction = ANGLEResources.HashFunction;
621     ANGLEResources.HashFunction = nameHashForShader;
622
623     if (!nameHashMapForShaders)
624         nameHashMapForShaders = std::make_unique<ShaderNameHash>();
625     setCurrentNameHashMapForShader(nameHashMapForShaders.get());
626     m_compiler.setResources(ANGLEResources);
627
628     String translatedShaderSource = m_extensions->getTranslatedShaderSourceANGLE(shader);
629
630     ANGLEResources.HashFunction = previousHashFunction;
631     m_compiler.setResources(ANGLEResources);
632     setCurrentNameHashMapForShader(nullptr);
633
634     if (!translatedShaderSource.length())
635         return;
636
637     const CString& translatedShaderCString = translatedShaderSource.utf8();
638     const char* translatedShaderPtr = translatedShaderCString.data();
639     int translatedShaderLength = translatedShaderCString.length();
640
641     LOG(WebGL, "--- begin original shader source ---\n%s\n--- end original shader source ---\n", getShaderSource(shader).utf8().data());
642     LOG(WebGL, "--- begin translated shader source ---\n%s\n--- end translated shader source ---", translatedShaderPtr);
643
644     ::glShaderSource(shader, 1, &translatedShaderPtr, &translatedShaderLength);
645     
646     ::glCompileShader(shader);
647     
648     int GLCompileSuccess;
649     
650     ::glGetShaderiv(shader, COMPILE_STATUS, &GLCompileSuccess);
651
652     ShaderSourceMap::iterator result = m_shaderSourceMap.find(shader);
653     GraphicsContext3D::ShaderSourceEntry& entry = result->value;
654
655     // Populate the shader log
656     GLint length = 0;
657     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
658
659     if (length) {
660         GLsizei size = 0;
661         auto info = std::make_unique<GLchar[]>(length);
662         ::glGetShaderInfoLog(shader, length, &size, info.get());
663
664         Platform3DObject shaders[2] = { shader, 0 };
665         entry.log = getUnmangledInfoLog(shaders, 1, String(info.get()));
666     }
667
668     if (GLCompileSuccess != GL_TRUE) {
669         entry.isValid = false;
670         LOG(WebGL, "Error: shader translator produced a shader that OpenGL would not compile.");
671     }
672 }
673
674 void GraphicsContext3D::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border)
675 {
676     makeContextCurrent();
677     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
678         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
679         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
680     }
681     ::glCopyTexImage2D(target, level, internalformat, x, y, width, height, border);
682     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
683         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
684 }
685
686 void GraphicsContext3D::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
687 {
688     makeContextCurrent();
689     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO) {
690         resolveMultisamplingIfNecessary(IntRect(x, y, width, height));
691         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_fbo);
692     }
693     ::glCopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
694     if (m_attrs.antialias && m_state.boundFBO == m_multisampleFBO)
695         ::glBindFramebufferEXT(GraphicsContext3D::FRAMEBUFFER, m_multisampleFBO);
696 }
697
698 void GraphicsContext3D::cullFace(GC3Denum mode)
699 {
700     makeContextCurrent();
701     ::glCullFace(mode);
702 }
703
704 void GraphicsContext3D::depthFunc(GC3Denum func)
705 {
706     makeContextCurrent();
707     ::glDepthFunc(func);
708 }
709
710 void GraphicsContext3D::depthMask(GC3Dboolean flag)
711 {
712     makeContextCurrent();
713     ::glDepthMask(flag);
714 }
715
716 void GraphicsContext3D::detachShader(Platform3DObject program, Platform3DObject shader)
717 {
718     ASSERT(program);
719     ASSERT(shader);
720     makeContextCurrent();
721     m_shaderProgramSymbolCountMap.remove(program);
722     ::glDetachShader(program, shader);
723 }
724
725 void GraphicsContext3D::disable(GC3Denum cap)
726 {
727     makeContextCurrent();
728     ::glDisable(cap);
729 }
730
731 void GraphicsContext3D::disableVertexAttribArray(GC3Duint index)
732 {
733     makeContextCurrent();
734     ::glDisableVertexAttribArray(index);
735 }
736
737 void GraphicsContext3D::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count)
738 {
739     makeContextCurrent();
740     ::glDrawArrays(mode, first, count);
741     checkGPUStatusIfNecessary();
742 }
743
744 void GraphicsContext3D::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset)
745 {
746     makeContextCurrent();
747     ::glDrawElements(mode, count, type, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
748     checkGPUStatusIfNecessary();
749 }
750
751 void GraphicsContext3D::enable(GC3Denum cap)
752 {
753     makeContextCurrent();
754     ::glEnable(cap);
755 }
756
757 void GraphicsContext3D::enableVertexAttribArray(GC3Duint index)
758 {
759     makeContextCurrent();
760     ::glEnableVertexAttribArray(index);
761 }
762
763 void GraphicsContext3D::finish()
764 {
765     makeContextCurrent();
766     ::glFinish();
767 }
768
769 void GraphicsContext3D::flush()
770 {
771     makeContextCurrent();
772     ::glFlush();
773 }
774
775 void GraphicsContext3D::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, Platform3DObject buffer)
776 {
777     makeContextCurrent();
778     ::glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget, buffer);
779 }
780
781 void GraphicsContext3D::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, Platform3DObject texture, GC3Dint level)
782 {
783     makeContextCurrent();
784     ::glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
785 }
786
787 void GraphicsContext3D::frontFace(GC3Denum mode)
788 {
789     makeContextCurrent();
790     ::glFrontFace(mode);
791 }
792
793 void GraphicsContext3D::generateMipmap(GC3Denum target)
794 {
795     makeContextCurrent();
796     ::glGenerateMipmap(target);
797 }
798
799 bool GraphicsContext3D::getActiveAttribImpl(Platform3DObject program, GC3Duint index, ActiveInfo& info)
800 {
801     if (!program) {
802         synthesizeGLError(INVALID_VALUE);
803         return false;
804     }
805     makeContextCurrent();
806     GLint maxAttributeSize = 0;
807     ::glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &maxAttributeSize);
808     auto name = std::make_unique<GLchar[]>(maxAttributeSize); // GL_ACTIVE_ATTRIBUTE_MAX_LENGTH includes null termination.
809     GLsizei nameLength = 0;
810     GLint size = 0;
811     GLenum type = 0;
812     ::glGetActiveAttrib(program, index, maxAttributeSize, &nameLength, &size, &type, name.get());
813     if (!nameLength)
814         return false;
815     
816     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, String(name.get(), nameLength));
817     
818 #ifndef NDEBUG
819     String uniformName(name.get(), nameLength);
820     LOG(WebGL, "Program %d is mapping active attribute %d from '%s' to '%s'", program, index, uniformName.utf8().data(), originalName.utf8().data());
821 #endif
822
823     info.name = originalName;
824     info.type = type;
825     info.size = size;
826     return true;
827 }
828
829 bool GraphicsContext3D::getActiveAttrib(Platform3DObject program, GC3Duint index, ActiveInfo& info)
830 {
831     GC3Dint symbolCount;
832     auto result = m_shaderProgramSymbolCountMap.find(program);
833     if (result == m_shaderProgramSymbolCountMap.end()) {
834         getNonBuiltInActiveSymbolCount(program, GraphicsContext3D::ACTIVE_ATTRIBUTES, &symbolCount);
835         result = m_shaderProgramSymbolCountMap.find(program);
836     }
837     
838     ActiveShaderSymbolCounts& symbolCounts = result->value;
839     GC3Duint rawIndex = (index < symbolCounts.filteredToActualAttributeIndexMap.size()) ? symbolCounts.filteredToActualAttributeIndexMap[index] : -1;
840
841     return getActiveAttribImpl(program, rawIndex, info);
842 }
843
844 bool GraphicsContext3D::getActiveUniformImpl(Platform3DObject program, GC3Duint index, ActiveInfo& info)
845 {
846     if (!program) {
847         synthesizeGLError(INVALID_VALUE);
848         return false;
849     }
850
851     makeContextCurrent();
852     GLint maxUniformSize = 0;
853     ::glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformSize);
854
855     auto name = std::make_unique<GLchar[]>(maxUniformSize); // GL_ACTIVE_UNIFORM_MAX_LENGTH includes null termination.
856     GLsizei nameLength = 0;
857     GLint size = 0;
858     GLenum type = 0;
859     ::glGetActiveUniform(program, index, maxUniformSize, &nameLength, &size, &type, name.get());
860     if (!nameLength)
861         return false;
862     
863     String originalName = originalSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, String(name.get(), nameLength));
864     
865 #ifndef NDEBUG
866     String uniformName(name.get(), nameLength);
867     LOG(WebGL, "Program %d is mapping active uniform %d from '%s' to '%s'", program, index, uniformName.utf8().data(), originalName.utf8().data());
868 #endif
869     
870     info.name = originalName;
871     info.type = type;
872     info.size = size;
873     return true;
874 }
875
876 bool GraphicsContext3D::getActiveUniform(Platform3DObject program, GC3Duint index, ActiveInfo& info)
877 {
878     GC3Dint symbolCount;
879     auto result = m_shaderProgramSymbolCountMap.find(program);
880     if (result == m_shaderProgramSymbolCountMap.end()) {
881         getNonBuiltInActiveSymbolCount(program, GraphicsContext3D::ACTIVE_UNIFORMS, &symbolCount);
882         result = m_shaderProgramSymbolCountMap.find(program);
883     }
884     
885     ActiveShaderSymbolCounts& symbolCounts = result->value;
886     GC3Duint rawIndex = (index < symbolCounts.filteredToActualUniformIndexMap.size()) ? symbolCounts.filteredToActualUniformIndexMap[index] : -1;
887     
888     return getActiveUniformImpl(program, rawIndex, info);
889 }
890
891 void GraphicsContext3D::getAttachedShaders(Platform3DObject program, GC3Dsizei maxCount, GC3Dsizei* count, Platform3DObject* shaders)
892 {
893     if (!program) {
894         synthesizeGLError(INVALID_VALUE);
895         return;
896     }
897     makeContextCurrent();
898     ::glGetAttachedShaders(program, maxCount, count, shaders);
899 }
900
901 static String generateHashedName(const String& name)
902 {
903     if (name.isEmpty())
904         return name;
905     uint64_t number = nameHashForShader(name.utf8().data(), name.length());
906     StringBuilder builder;
907     builder.appendLiteral("webgl_");
908     appendUnsigned64AsHex(number, builder, Lowercase);
909     return builder.toString();
910 }
911
912 String GraphicsContext3D::mappedSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
913 {
914     GC3Dsizei count = 0;
915     Platform3DObject shaders[2] = { };
916     getAttachedShaders(program, 2, &count, shaders);
917
918     for (GC3Dsizei i = 0; i < count; ++i) {
919         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
920         if (result == m_shaderSourceMap.end())
921             continue;
922
923         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
924         ShaderSymbolMap::const_iterator symbolEntry = symbolMap.find(name);
925         if (symbolEntry != symbolMap.end()) {
926             const std::string& mappedName = symbolEntry->value.mappedName;
927             return String(mappedName.c_str(), mappedName.length());
928         }
929     }
930
931     if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE && !name.isEmpty()) {
932         // Attributes are a special case: they may be requested before any shaders have been compiled,
933         // and aren't even required to be used in any shader program.
934         if (!nameHashMapForShaders)
935             nameHashMapForShaders = std::make_unique<ShaderNameHash>();
936         setCurrentNameHashMapForShader(nameHashMapForShaders.get());
937
938         String generatedName = generateHashedName(name);
939
940         setCurrentNameHashMapForShader(nullptr);
941
942         m_possiblyUnusedAttributeMap.set(generatedName, name);
943
944         return generatedName;
945     }
946
947     return name;
948 }
949     
950 String GraphicsContext3D::originalSymbolName(Platform3DObject program, ANGLEShaderSymbolType symbolType, const String& name)
951 {
952     GC3Dsizei count;
953     Platform3DObject shaders[2];
954     getAttachedShaders(program, 2, &count, shaders);
955     
956     for (GC3Dsizei i = 0; i < count; ++i) {
957         ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
958         if (result == m_shaderSourceMap.end())
959             continue;
960         
961         const ShaderSymbolMap& symbolMap = result->value.symbolMap(symbolType);
962         for (const auto& symbolEntry : symbolMap) {
963             if (name == symbolEntry.value.mappedName.c_str())
964                 return symbolEntry.key;
965         }
966     }
967
968     if (symbolType == SHADER_SYMBOL_TYPE_ATTRIBUTE && !name.isEmpty()) {
969         // Attributes are a special case: they may be requested before any shaders have been compiled,
970         // and aren't even required to be used in any shader program.
971
972         const auto& cached = m_possiblyUnusedAttributeMap.find(name);
973         if (cached != m_possiblyUnusedAttributeMap.end())
974             return cached->value;
975     }
976
977     return name;
978 }
979
980 String GraphicsContext3D::mappedSymbolName(Platform3DObject shaders[2], size_t count, const String& name)
981 {
982     for (size_t symbolType = 0; symbolType <= static_cast<size_t>(SHADER_SYMBOL_TYPE_VARYING); ++symbolType) {
983         for (size_t i = 0; i < count; ++i) {
984             ShaderSourceMap::iterator result = m_shaderSourceMap.find(shaders[i]);
985             if (result == m_shaderSourceMap.end())
986                 continue;
987             
988             const ShaderSymbolMap& symbolMap = result->value.symbolMap(static_cast<enum ANGLEShaderSymbolType>(symbolType));
989             for (const auto& symbolEntry : symbolMap) {
990                 if (name == symbolEntry.value.mappedName.c_str())
991                     return symbolEntry.key;
992             }
993         }
994     }
995     return name;
996 }
997
998 int GraphicsContext3D::getAttribLocation(Platform3DObject program, const String& name)
999 {
1000     if (!program)
1001         return -1;
1002
1003     makeContextCurrent();
1004
1005     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_ATTRIBUTE, name);
1006     LOG(WebGL, "::glGetAttribLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
1007     return ::glGetAttribLocation(program, mappedName.utf8().data());
1008 }
1009
1010 GraphicsContext3DAttributes GraphicsContext3D::getContextAttributes()
1011 {
1012     return m_attrs;
1013 }
1014
1015 bool GraphicsContext3D::moveErrorsToSyntheticErrorList()
1016 {
1017     makeContextCurrent();
1018     bool movedAnError = false;
1019
1020     // Set an arbitrary limit of 100 here to avoid creating a hang if
1021     // a problem driver has a bug that causes it to never clear the error.
1022     // Otherwise, we would just loop until we got NO_ERROR.
1023     for (unsigned i = 0; i < 100; ++i) {
1024         GC3Denum error = glGetError();
1025         if (error == NO_ERROR)
1026             break;
1027         m_syntheticErrors.add(error);
1028         movedAnError = true;
1029     }
1030
1031     return movedAnError;
1032 }
1033
1034 GC3Denum GraphicsContext3D::getError()
1035 {
1036     if (!m_syntheticErrors.isEmpty()) {
1037         // Need to move the current errors to the synthetic error list in case
1038         // that error is already there, since the expected behavior of both
1039         // glGetError and getError is to only report each error code once.
1040         moveErrorsToSyntheticErrorList();
1041         return m_syntheticErrors.takeFirst();
1042     }
1043
1044     makeContextCurrent();
1045     return ::glGetError();
1046 }
1047
1048 String GraphicsContext3D::getString(GC3Denum name)
1049 {
1050     makeContextCurrent();
1051     return String(reinterpret_cast<const char*>(::glGetString(name)));
1052 }
1053
1054 void GraphicsContext3D::hint(GC3Denum target, GC3Denum mode)
1055 {
1056     makeContextCurrent();
1057     ::glHint(target, mode);
1058 }
1059
1060 GC3Dboolean GraphicsContext3D::isBuffer(Platform3DObject buffer)
1061 {
1062     if (!buffer)
1063         return GL_FALSE;
1064
1065     makeContextCurrent();
1066     return ::glIsBuffer(buffer);
1067 }
1068
1069 GC3Dboolean GraphicsContext3D::isEnabled(GC3Denum cap)
1070 {
1071     makeContextCurrent();
1072     return ::glIsEnabled(cap);
1073 }
1074
1075 GC3Dboolean GraphicsContext3D::isFramebuffer(Platform3DObject framebuffer)
1076 {
1077     if (!framebuffer)
1078         return GL_FALSE;
1079
1080     makeContextCurrent();
1081     return ::glIsFramebufferEXT(framebuffer);
1082 }
1083
1084 GC3Dboolean GraphicsContext3D::isProgram(Platform3DObject program)
1085 {
1086     if (!program)
1087         return GL_FALSE;
1088
1089     makeContextCurrent();
1090     return ::glIsProgram(program);
1091 }
1092
1093 GC3Dboolean GraphicsContext3D::isRenderbuffer(Platform3DObject renderbuffer)
1094 {
1095     if (!renderbuffer)
1096         return GL_FALSE;
1097
1098     makeContextCurrent();
1099     return ::glIsRenderbufferEXT(renderbuffer);
1100 }
1101
1102 GC3Dboolean GraphicsContext3D::isShader(Platform3DObject shader)
1103 {
1104     if (!shader)
1105         return GL_FALSE;
1106
1107     makeContextCurrent();
1108     return ::glIsShader(shader);
1109 }
1110
1111 GC3Dboolean GraphicsContext3D::isTexture(Platform3DObject texture)
1112 {
1113     if (!texture)
1114         return GL_FALSE;
1115
1116     makeContextCurrent();
1117     return ::glIsTexture(texture);
1118 }
1119
1120 void GraphicsContext3D::lineWidth(GC3Dfloat width)
1121 {
1122     makeContextCurrent();
1123     ::glLineWidth(width);
1124 }
1125
1126 void GraphicsContext3D::linkProgram(Platform3DObject program)
1127 {
1128     ASSERT(program);
1129     makeContextCurrent();
1130     ::glLinkProgram(program);
1131 }
1132
1133 void GraphicsContext3D::pixelStorei(GC3Denum pname, GC3Dint param)
1134 {
1135     makeContextCurrent();
1136     ::glPixelStorei(pname, param);
1137 }
1138
1139 void GraphicsContext3D::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
1140 {
1141     makeContextCurrent();
1142     ::glPolygonOffset(factor, units);
1143 }
1144
1145 void GraphicsContext3D::sampleCoverage(GC3Dclampf value, GC3Dboolean invert)
1146 {
1147     makeContextCurrent();
1148     ::glSampleCoverage(value, invert);
1149 }
1150
1151 void GraphicsContext3D::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1152 {
1153     makeContextCurrent();
1154     ::glScissor(x, y, width, height);
1155 }
1156
1157 void GraphicsContext3D::shaderSource(Platform3DObject shader, const String& string)
1158 {
1159     ASSERT(shader);
1160
1161     makeContextCurrent();
1162
1163     ShaderSourceEntry entry;
1164
1165     entry.source = string;
1166
1167     m_shaderSourceMap.set(shader, entry);
1168 }
1169
1170 void GraphicsContext3D::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask)
1171 {
1172     makeContextCurrent();
1173     ::glStencilFunc(func, ref, mask);
1174 }
1175
1176 void GraphicsContext3D::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask)
1177 {
1178     makeContextCurrent();
1179     ::glStencilFuncSeparate(face, func, ref, mask);
1180 }
1181
1182 void GraphicsContext3D::stencilMask(GC3Duint mask)
1183 {
1184     makeContextCurrent();
1185     ::glStencilMask(mask);
1186 }
1187
1188 void GraphicsContext3D::stencilMaskSeparate(GC3Denum face, GC3Duint mask)
1189 {
1190     makeContextCurrent();
1191     ::glStencilMaskSeparate(face, mask);
1192 }
1193
1194 void GraphicsContext3D::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
1195 {
1196     makeContextCurrent();
1197     ::glStencilOp(fail, zfail, zpass);
1198 }
1199
1200 void GraphicsContext3D::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass)
1201 {
1202     makeContextCurrent();
1203     ::glStencilOpSeparate(face, fail, zfail, zpass);
1204 }
1205
1206 void GraphicsContext3D::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat value)
1207 {
1208     makeContextCurrent();
1209     ::glTexParameterf(target, pname, value);
1210 }
1211
1212 void GraphicsContext3D::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint value)
1213 {
1214     makeContextCurrent();
1215     ::glTexParameteri(target, pname, value);
1216 }
1217
1218 void GraphicsContext3D::uniform1f(GC3Dint location, GC3Dfloat v0)
1219 {
1220     makeContextCurrent();
1221     ::glUniform1f(location, v0);
1222 }
1223
1224 void GraphicsContext3D::uniform1fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1225 {
1226     makeContextCurrent();
1227     ::glUniform1fv(location, size, array);
1228 }
1229
1230 void GraphicsContext3D::uniform2f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1)
1231 {
1232     makeContextCurrent();
1233     ::glUniform2f(location, v0, v1);
1234 }
1235
1236 void GraphicsContext3D::uniform2fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1237 {
1238     // FIXME: length needs to be a multiple of 2.
1239     makeContextCurrent();
1240     ::glUniform2fv(location, size, array);
1241 }
1242
1243 void GraphicsContext3D::uniform3f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1244 {
1245     makeContextCurrent();
1246     ::glUniform3f(location, v0, v1, v2);
1247 }
1248
1249 void GraphicsContext3D::uniform3fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1250 {
1251     // FIXME: length needs to be a multiple of 3.
1252     makeContextCurrent();
1253     ::glUniform3fv(location, size, array);
1254 }
1255
1256 void GraphicsContext3D::uniform4f(GC3Dint location, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1257 {
1258     makeContextCurrent();
1259     ::glUniform4f(location, v0, v1, v2, v3);
1260 }
1261
1262 void GraphicsContext3D::uniform4fv(GC3Dint location, GC3Dsizei size, GC3Dfloat* array)
1263 {
1264     // FIXME: length needs to be a multiple of 4.
1265     makeContextCurrent();
1266     ::glUniform4fv(location, size, array);
1267 }
1268
1269 void GraphicsContext3D::uniform1i(GC3Dint location, GC3Dint v0)
1270 {
1271     makeContextCurrent();
1272     ::glUniform1i(location, v0);
1273 }
1274
1275 void GraphicsContext3D::uniform1iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1276 {
1277     makeContextCurrent();
1278     ::glUniform1iv(location, size, array);
1279 }
1280
1281 void GraphicsContext3D::uniform2i(GC3Dint location, GC3Dint v0, GC3Dint v1)
1282 {
1283     makeContextCurrent();
1284     ::glUniform2i(location, v0, v1);
1285 }
1286
1287 void GraphicsContext3D::uniform2iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1288 {
1289     // FIXME: length needs to be a multiple of 2.
1290     makeContextCurrent();
1291     ::glUniform2iv(location, size, array);
1292 }
1293
1294 void GraphicsContext3D::uniform3i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2)
1295 {
1296     makeContextCurrent();
1297     ::glUniform3i(location, v0, v1, v2);
1298 }
1299
1300 void GraphicsContext3D::uniform3iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1301 {
1302     // FIXME: length needs to be a multiple of 3.
1303     makeContextCurrent();
1304     ::glUniform3iv(location, size, array);
1305 }
1306
1307 void GraphicsContext3D::uniform4i(GC3Dint location, GC3Dint v0, GC3Dint v1, GC3Dint v2, GC3Dint v3)
1308 {
1309     makeContextCurrent();
1310     ::glUniform4i(location, v0, v1, v2, v3);
1311 }
1312
1313 void GraphicsContext3D::uniform4iv(GC3Dint location, GC3Dsizei size, GC3Dint* array)
1314 {
1315     // FIXME: length needs to be a multiple of 4.
1316     makeContextCurrent();
1317     ::glUniform4iv(location, size, array);
1318 }
1319
1320 void GraphicsContext3D::uniformMatrix2fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1321 {
1322     // FIXME: length needs to be a multiple of 4.
1323     makeContextCurrent();
1324     ::glUniformMatrix2fv(location, size, transpose, array);
1325 }
1326
1327 void GraphicsContext3D::uniformMatrix3fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1328 {
1329     // FIXME: length needs to be a multiple of 9.
1330     makeContextCurrent();
1331     ::glUniformMatrix3fv(location, size, transpose, array);
1332 }
1333
1334 void GraphicsContext3D::uniformMatrix4fv(GC3Dint location, GC3Dsizei size, GC3Dboolean transpose, GC3Dfloat* array)
1335 {
1336     // FIXME: length needs to be a multiple of 16.
1337     makeContextCurrent();
1338     ::glUniformMatrix4fv(location, size, transpose, array);
1339 }
1340
1341 void GraphicsContext3D::useProgram(Platform3DObject program)
1342 {
1343     makeContextCurrent();
1344     ::glUseProgram(program);
1345 }
1346
1347 void GraphicsContext3D::validateProgram(Platform3DObject program)
1348 {
1349     ASSERT(program);
1350
1351     makeContextCurrent();
1352     ::glValidateProgram(program);
1353 }
1354
1355 void GraphicsContext3D::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
1356 {
1357     makeContextCurrent();
1358     ::glVertexAttrib1f(index, v0);
1359 }
1360
1361 void GraphicsContext3D::vertexAttrib1fv(GC3Duint index, GC3Dfloat* array)
1362 {
1363     makeContextCurrent();
1364     ::glVertexAttrib1fv(index, array);
1365 }
1366
1367 void GraphicsContext3D::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
1368 {
1369     makeContextCurrent();
1370     ::glVertexAttrib2f(index, v0, v1);
1371 }
1372
1373 void GraphicsContext3D::vertexAttrib2fv(GC3Duint index, GC3Dfloat* array)
1374 {
1375     makeContextCurrent();
1376     ::glVertexAttrib2fv(index, array);
1377 }
1378
1379 void GraphicsContext3D::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
1380 {
1381     makeContextCurrent();
1382     ::glVertexAttrib3f(index, v0, v1, v2);
1383 }
1384
1385 void GraphicsContext3D::vertexAttrib3fv(GC3Duint index, GC3Dfloat* array)
1386 {
1387     makeContextCurrent();
1388     ::glVertexAttrib3fv(index, array);
1389 }
1390
1391 void GraphicsContext3D::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
1392 {
1393     makeContextCurrent();
1394     ::glVertexAttrib4f(index, v0, v1, v2, v3);
1395 }
1396
1397 void GraphicsContext3D::vertexAttrib4fv(GC3Duint index, GC3Dfloat* array)
1398 {
1399     makeContextCurrent();
1400     ::glVertexAttrib4fv(index, array);
1401 }
1402
1403 void GraphicsContext3D::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset)
1404 {
1405     makeContextCurrent();
1406     ::glVertexAttribPointer(index, size, type, normalized, stride, reinterpret_cast<GLvoid*>(static_cast<intptr_t>(offset)));
1407 }
1408
1409 void GraphicsContext3D::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
1410 {
1411     makeContextCurrent();
1412     ::glViewport(x, y, width, height);
1413 }
1414
1415 Platform3DObject GraphicsContext3D::createVertexArray()
1416 {
1417     makeContextCurrent();
1418     GLuint array = 0;
1419 #if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS))
1420     glGenVertexArrays(1, &array);
1421 #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
1422     glGenVertexArraysAPPLE(1, &array);
1423 #endif
1424     return array;
1425 }
1426
1427 void GraphicsContext3D::deleteVertexArray(Platform3DObject array)
1428 {
1429     if (!array)
1430         return;
1431     
1432     makeContextCurrent();
1433 #if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS))
1434     glDeleteVertexArrays(1, &array);
1435 #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
1436     glDeleteVertexArraysAPPLE(1, &array);
1437 #endif
1438 }
1439
1440 GC3Dboolean GraphicsContext3D::isVertexArray(Platform3DObject array)
1441 {
1442     if (!array)
1443         return GL_FALSE;
1444     
1445     makeContextCurrent();
1446 #if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS))
1447     return glIsVertexArray(array);
1448 #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
1449     return glIsVertexArrayAPPLE(array);
1450 #endif
1451     return GL_FALSE;
1452 }
1453
1454 void GraphicsContext3D::bindVertexArray(Platform3DObject array)
1455 {
1456     makeContextCurrent();
1457 #if !USE(OPENGL_ES_2) && (PLATFORM(GTK) || PLATFORM(WIN) || PLATFORM(IOS))
1458     glBindVertexArray(array);
1459 #elif defined(GL_APPLE_vertex_array_object) && GL_APPLE_vertex_array_object
1460     glBindVertexArrayAPPLE(array);
1461 #else
1462     UNUSED_PARAM(array);
1463 #endif
1464 }
1465
1466 void GraphicsContext3D::getBooleanv(GC3Denum pname, GC3Dboolean* value)
1467 {
1468     makeContextCurrent();
1469     ::glGetBooleanv(pname, value);
1470 }
1471
1472 void GraphicsContext3D::getBufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1473 {
1474     makeContextCurrent();
1475     ::glGetBufferParameteriv(target, pname, value);
1476 }
1477
1478 void GraphicsContext3D::getFloatv(GC3Denum pname, GC3Dfloat* value)
1479 {
1480     makeContextCurrent();
1481     ::glGetFloatv(pname, value);
1482 }
1483     
1484 void GraphicsContext3D::getInteger64v(GC3Denum pname, GC3Dint64* value)
1485 {
1486     UNUSED_PARAM(pname);
1487     makeContextCurrent();
1488     *value = 0;
1489     // 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.
1490     // ::glGetInteger64v(pname, value);
1491 }
1492
1493 void GraphicsContext3D::getFramebufferAttachmentParameteriv(GC3Denum target, GC3Denum attachment, GC3Denum pname, GC3Dint* value)
1494 {
1495     makeContextCurrent();
1496     if (attachment == DEPTH_STENCIL_ATTACHMENT)
1497         attachment = DEPTH_ATTACHMENT; // Or STENCIL_ATTACHMENT, either works.
1498     ::glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, value);
1499 }
1500
1501 void GraphicsContext3D::getProgramiv(Platform3DObject program, GC3Denum pname, GC3Dint* value)
1502 {
1503     makeContextCurrent();
1504     ::glGetProgramiv(program, pname, value);
1505 }
1506
1507 void GraphicsContext3D::getNonBuiltInActiveSymbolCount(Platform3DObject program, GC3Denum pname, GC3Dint* value)
1508 {
1509     ASSERT(ACTIVE_ATTRIBUTES == pname || ACTIVE_UNIFORMS == pname);
1510     if (!value)
1511         return;
1512
1513     makeContextCurrent();
1514     const auto& result = m_shaderProgramSymbolCountMap.find(program);
1515     if (result != m_shaderProgramSymbolCountMap.end()) {
1516         *value = result->value.countForType(pname);
1517         return;
1518     }
1519
1520     m_shaderProgramSymbolCountMap.set(program, ActiveShaderSymbolCounts());
1521     ActiveShaderSymbolCounts& symbolCounts = m_shaderProgramSymbolCountMap.find(program)->value;
1522
1523     // Retrieve the active attributes, build a filtered count, and a mapping of
1524     // our internal attributes indexes to the real unfiltered indexes inside OpenGL.
1525     GC3Dint attributeCount = 0;
1526     ::glGetProgramiv(program, ACTIVE_ATTRIBUTES, &attributeCount);
1527     for (GC3Dint i = 0; i < attributeCount; ++i) {
1528         ActiveInfo info;
1529         getActiveAttribImpl(program, i, info);
1530         if (info.name.startsWith("gl_"))
1531             continue;
1532
1533         symbolCounts.filteredToActualAttributeIndexMap.append(i);
1534     }
1535     
1536     // Do the same for uniforms.
1537     GC3Dint uniformCount = 0;
1538     ::glGetProgramiv(program, ACTIVE_UNIFORMS, &uniformCount);
1539     for (GC3Dint i = 0; i < uniformCount; ++i) {
1540         ActiveInfo info;
1541         getActiveUniformImpl(program, i, info);
1542         if (info.name.startsWith("gl_"))
1543             continue;
1544         
1545         symbolCounts.filteredToActualUniformIndexMap.append(i);
1546     }
1547     
1548     *value = symbolCounts.countForType(pname);
1549 }
1550
1551 String GraphicsContext3D::getUnmangledInfoLog(Platform3DObject shaders[2], GC3Dsizei count, const String& log)
1552 {
1553     LOG(WebGL, "Was: %s", log.utf8().data());
1554
1555     JSC::Yarr::RegularExpression regExp("webgl_[0123456789abcdefABCDEF]+", TextCaseSensitive);
1556
1557     StringBuilder processedLog;
1558     
1559     int startFrom = 0;
1560     int matchedLength = 0;
1561     do {
1562         int start = regExp.match(log, startFrom, &matchedLength);
1563         if (start == -1)
1564             break;
1565
1566         processedLog.append(log.substring(startFrom, start - startFrom));
1567         startFrom = start + matchedLength;
1568
1569         const String& mangledSymbol = log.substring(start, matchedLength);
1570         const String& mappedSymbol = mappedSymbolName(shaders, count, mangledSymbol);
1571         LOG(WebGL, "Demangling: %s to %s", mangledSymbol.utf8().data(), mappedSymbol.utf8().data());
1572         processedLog.append(mappedSymbol);
1573     } while (startFrom < static_cast<int>(log.length()));
1574
1575     processedLog.append(log.substring(startFrom, log.length() - startFrom));
1576
1577     LOG(WebGL, "-->: %s", processedLog.toString().utf8().data());
1578     return processedLog.toString();
1579 }
1580
1581 String GraphicsContext3D::getProgramInfoLog(Platform3DObject program)
1582 {
1583     ASSERT(program);
1584
1585     makeContextCurrent();
1586     GLint length = 0;
1587     ::glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
1588     if (!length)
1589         return String(); 
1590
1591     GLsizei size = 0;
1592     auto info = std::make_unique<GLchar[]>(length);
1593     ::glGetProgramInfoLog(program, length, &size, info.get());
1594
1595     GC3Dsizei count;
1596     Platform3DObject shaders[2];
1597     getAttachedShaders(program, 2, &count, shaders);
1598
1599     return getUnmangledInfoLog(shaders, count, String(info.get()));
1600 }
1601
1602 void GraphicsContext3D::getRenderbufferParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1603 {
1604     makeContextCurrent();
1605     ::glGetRenderbufferParameterivEXT(target, pname, value);
1606 }
1607
1608 void GraphicsContext3D::getShaderiv(Platform3DObject shader, GC3Denum pname, GC3Dint* value)
1609 {
1610     ASSERT(shader);
1611
1612     makeContextCurrent();
1613
1614     const auto& result = m_shaderSourceMap.find(shader);
1615     
1616     switch (pname) {
1617     case DELETE_STATUS:
1618     case SHADER_TYPE:
1619         ::glGetShaderiv(shader, pname, value);
1620         break;
1621     case COMPILE_STATUS:
1622         if (result == m_shaderSourceMap.end()) {
1623             *value = static_cast<int>(false);
1624             return;
1625         }
1626         *value = static_cast<int>(result->value.isValid);
1627         break;
1628     case INFO_LOG_LENGTH:
1629         if (result == m_shaderSourceMap.end()) {
1630             *value = 0;
1631             return;
1632         }
1633         *value = getShaderInfoLog(shader).length();
1634         break;
1635     case SHADER_SOURCE_LENGTH:
1636         *value = getShaderSource(shader).length();
1637         break;
1638     default:
1639         synthesizeGLError(INVALID_ENUM);
1640     }
1641 }
1642
1643 String GraphicsContext3D::getShaderInfoLog(Platform3DObject shader)
1644 {
1645     ASSERT(shader);
1646
1647     makeContextCurrent();
1648
1649     const auto& result = m_shaderSourceMap.find(shader);
1650     if (result == m_shaderSourceMap.end())
1651         return String(); 
1652
1653     const ShaderSourceEntry& entry = result->value;
1654     if (!entry.isValid)
1655         return entry.log;
1656
1657     GLint length = 0;
1658     ::glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
1659     if (!length)
1660         return String(); 
1661
1662     GLsizei size = 0;
1663     auto info = std::make_unique<GLchar[]>(length);
1664     ::glGetShaderInfoLog(shader, length, &size, info.get());
1665
1666     Platform3DObject shaders[2] = { shader, 0 };
1667     return getUnmangledInfoLog(shaders, 1, String(info.get()));
1668 }
1669
1670 String GraphicsContext3D::getShaderSource(Platform3DObject shader)
1671 {
1672     ASSERT(shader);
1673
1674     makeContextCurrent();
1675
1676     const auto& result = m_shaderSourceMap.find(shader);
1677     if (result == m_shaderSourceMap.end())
1678         return String(); 
1679
1680     return result->value.source;
1681 }
1682
1683
1684 void GraphicsContext3D::getTexParameterfv(GC3Denum target, GC3Denum pname, GC3Dfloat* value)
1685 {
1686     makeContextCurrent();
1687     ::glGetTexParameterfv(target, pname, value);
1688 }
1689
1690 void GraphicsContext3D::getTexParameteriv(GC3Denum target, GC3Denum pname, GC3Dint* value)
1691 {
1692     makeContextCurrent();
1693     ::glGetTexParameteriv(target, pname, value);
1694 }
1695
1696 void GraphicsContext3D::getUniformfv(Platform3DObject program, GC3Dint location, GC3Dfloat* value)
1697 {
1698     makeContextCurrent();
1699     ::glGetUniformfv(program, location, value);
1700 }
1701
1702 void GraphicsContext3D::getUniformiv(Platform3DObject program, GC3Dint location, GC3Dint* value)
1703 {
1704     makeContextCurrent();
1705     ::glGetUniformiv(program, location, value);
1706 }
1707
1708 GC3Dint GraphicsContext3D::getUniformLocation(Platform3DObject program, const String& name)
1709 {
1710     ASSERT(program);
1711
1712     makeContextCurrent();
1713
1714     String mappedName = mappedSymbolName(program, SHADER_SYMBOL_TYPE_UNIFORM, name);
1715     LOG(WebGL, "::getUniformLocation is mapping %s to %s", name.utf8().data(), mappedName.utf8().data());
1716     return ::glGetUniformLocation(program, mappedName.utf8().data());
1717 }
1718
1719 void GraphicsContext3D::getVertexAttribfv(GC3Duint index, GC3Denum pname, GC3Dfloat* value)
1720 {
1721     makeContextCurrent();
1722     ::glGetVertexAttribfv(index, pname, value);
1723 }
1724
1725 void GraphicsContext3D::getVertexAttribiv(GC3Duint index, GC3Denum pname, GC3Dint* value)
1726 {
1727     makeContextCurrent();
1728     ::glGetVertexAttribiv(index, pname, value);
1729 }
1730
1731 GC3Dsizeiptr GraphicsContext3D::getVertexAttribOffset(GC3Duint index, GC3Denum pname)
1732 {
1733     makeContextCurrent();
1734
1735     GLvoid* pointer = 0;
1736     ::glGetVertexAttribPointerv(index, pname, &pointer);
1737     return static_cast<GC3Dsizeiptr>(reinterpret_cast<intptr_t>(pointer));
1738 }
1739
1740 void GraphicsContext3D::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoff, GC3Dint yoff, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, const void* pixels)
1741 {
1742     makeContextCurrent();
1743
1744 #if !PLATFORM(IOS) && !USE(OPENGL_ES_2)
1745     if (type == HALF_FLOAT_OES)
1746         type = GL_HALF_FLOAT_ARB;
1747 #endif
1748
1749     if (m_usingCoreProfile && format == ALPHA) {
1750         // We are using a core profile. This means that GL_ALPHA, which is a valid format in WebGL for texSubImage2D
1751         // is not supported in OpenGL. We are using GL_RED to back GL_ALPHA, so do it here as well.
1752         format = RED;
1753     }
1754
1755     // FIXME: we will need to deal with PixelStore params when dealing with image buffers that differ from the subimage size.
1756     ::glTexSubImage2D(target, level, xoff, yoff, width, height, format, type, pixels);
1757 }
1758
1759 void GraphicsContext3D::compressedTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Dsizei imageSize, const void* data)
1760 {
1761     makeContextCurrent();
1762     ::glCompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
1763 }
1764
1765 void GraphicsContext3D::compressedTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Dsizei imageSize, const void* data)
1766 {
1767     makeContextCurrent();
1768     ::glCompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
1769 }
1770
1771 Platform3DObject GraphicsContext3D::createBuffer()
1772 {
1773     makeContextCurrent();
1774     GLuint o = 0;
1775     glGenBuffers(1, &o);
1776     return o;
1777 }
1778
1779 Platform3DObject GraphicsContext3D::createFramebuffer()
1780 {
1781     makeContextCurrent();
1782     GLuint o = 0;
1783     glGenFramebuffersEXT(1, &o);
1784     return o;
1785 }
1786
1787 Platform3DObject GraphicsContext3D::createProgram()
1788 {
1789     makeContextCurrent();
1790     return glCreateProgram();
1791 }
1792
1793 Platform3DObject GraphicsContext3D::createRenderbuffer()
1794 {
1795     makeContextCurrent();
1796     GLuint o = 0;
1797     glGenRenderbuffersEXT(1, &o);
1798     return o;
1799 }
1800
1801 Platform3DObject GraphicsContext3D::createShader(GC3Denum type)
1802 {
1803     makeContextCurrent();
1804     return glCreateShader((type == FRAGMENT_SHADER) ? GL_FRAGMENT_SHADER : GL_VERTEX_SHADER);
1805 }
1806
1807 Platform3DObject GraphicsContext3D::createTexture()
1808 {
1809     makeContextCurrent();
1810     GLuint o = 0;
1811     glGenTextures(1, &o);
1812     return o;
1813 }
1814
1815 void GraphicsContext3D::deleteBuffer(Platform3DObject buffer)
1816 {
1817     makeContextCurrent();
1818     glDeleteBuffers(1, &buffer);
1819 }
1820
1821 void GraphicsContext3D::deleteFramebuffer(Platform3DObject framebuffer)
1822 {
1823     makeContextCurrent();
1824     if (framebuffer == m_state.boundFBO) {
1825         // Make sure the framebuffer is not going to be used for drawing
1826         // operations after it gets deleted.
1827         bindFramebuffer(FRAMEBUFFER, 0);
1828     }
1829     glDeleteFramebuffersEXT(1, &framebuffer);
1830 }
1831
1832 void GraphicsContext3D::deleteProgram(Platform3DObject program)
1833 {
1834     makeContextCurrent();
1835     glDeleteProgram(program);
1836 }
1837
1838 void GraphicsContext3D::deleteRenderbuffer(Platform3DObject renderbuffer)
1839 {
1840     makeContextCurrent();
1841     glDeleteRenderbuffersEXT(1, &renderbuffer);
1842 }
1843
1844 void GraphicsContext3D::deleteShader(Platform3DObject shader)
1845 {
1846     makeContextCurrent();
1847     glDeleteShader(shader);
1848 }
1849
1850 void GraphicsContext3D::deleteTexture(Platform3DObject texture)
1851 {
1852     makeContextCurrent();
1853     if (m_state.boundTexture0 == texture)
1854         m_state.boundTexture0 = 0;
1855     glDeleteTextures(1, &texture);
1856 }
1857
1858 void GraphicsContext3D::synthesizeGLError(GC3Denum error)
1859 {
1860     // Need to move the current errors to the synthetic error list to
1861     // preserve the order of errors, so a caller to getError will get
1862     // any errors from glError before the error we are synthesizing.
1863     moveErrorsToSyntheticErrorList();
1864     m_syntheticErrors.add(error);
1865 }
1866
1867 void GraphicsContext3D::markContextChanged()
1868 {
1869     m_layerComposited = false;
1870 }
1871
1872 void GraphicsContext3D::markLayerComposited()
1873 {
1874     m_layerComposited = true;
1875 }
1876
1877 bool GraphicsContext3D::layerComposited() const
1878 {
1879     return m_layerComposited;
1880 }
1881
1882 void GraphicsContext3D::forceContextLost()
1883 {
1884 #if ENABLE(WEBGL)
1885     if (m_webglContext)
1886         m_webglContext->forceLostContext(WebGLRenderingContextBase::RealLostContext);
1887 #endif
1888 }
1889
1890 void GraphicsContext3D::recycleContext()
1891 {
1892 #if ENABLE(WEBGL)
1893     if (m_webglContext)
1894         m_webglContext->recycleContext();
1895 #endif
1896 }
1897
1898 void GraphicsContext3D::dispatchContextChangedNotification()
1899 {
1900 #if ENABLE(WEBGL)
1901     if (m_webglContext)
1902         m_webglContext->dispatchContextChangedEvent();
1903 #endif
1904 }
1905
1906 void GraphicsContext3D::texImage2DDirect(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height, GC3Dint border, GC3Denum format, GC3Denum type, const void* pixels)
1907 {
1908     makeContextCurrent();
1909     ::glTexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
1910 }
1911
1912 void GraphicsContext3D::drawArraysInstanced(GC3Denum mode, GC3Dint first, GC3Dsizei count, GC3Dsizei primcount)
1913 {
1914     getExtensions().drawArraysInstanced(mode, first, count, primcount);
1915 }
1916
1917 void GraphicsContext3D::drawElementsInstanced(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, GC3Dsizei primcount)
1918 {
1919     getExtensions().drawElementsInstanced(mode, count, type, offset, primcount);
1920 }
1921
1922 void GraphicsContext3D::vertexAttribDivisor(GC3Duint index, GC3Duint divisor)
1923 {
1924     getExtensions().vertexAttribDivisor(index, divisor);
1925 }
1926
1927 }
1928
1929 #endif // ENABLE(GRAPHICS_CONTEXT_3D)