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