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