WebGLRenderingContext.cpp revision ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddb
1/* 2 * Copyright (C) 2009 Apple Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#if ENABLE(3D_CANVAS) 29 30#include "WebGLRenderingContext.h" 31 32#include "CachedImage.h" 33#include "CanvasPixelArray.h" 34#include "CheckedInt.h" 35#include "WebKitLoseContext.h" 36#include "Console.h" 37#include "DOMWindow.h" 38#include "Extensions3D.h" 39#include "FrameView.h" 40#include "HTMLCanvasElement.h" 41#include "HTMLImageElement.h" 42#include "HTMLVideoElement.h" 43#include "ImageBuffer.h" 44#include "ImageData.h" 45#include "IntSize.h" 46#include "NotImplemented.h" 47#include "OESStandardDerivatives.h" 48#include "OESTextureFloat.h" 49#include "RenderBox.h" 50#include "RenderLayer.h" 51#include "Uint16Array.h" 52#include "WebGLActiveInfo.h" 53#include "WebGLBuffer.h" 54#include "WebGLContextAttributes.h" 55#include "WebGLContextEvent.h" 56#include "WebGLFramebuffer.h" 57#include "WebGLProgram.h" 58#include "WebGLRenderbuffer.h" 59#include "WebGLShader.h" 60#include "WebGLTexture.h" 61#include "WebGLUniformLocation.h" 62 63#include <wtf/ByteArray.h> 64#include <wtf/OwnArrayPtr.h> 65#include <wtf/PassOwnArrayPtr.h> 66#include <wtf/text/StringBuilder.h> 67 68namespace WebCore { 69 70const double secondsBetweenRestoreAttempts = 1.0; 71 72namespace { 73 74 Platform3DObject objectOrZero(WebGLObject* object) 75 { 76 return object ? object->object() : 0; 77 } 78 79 void clip1D(GC3Dint start, GC3Dsizei range, GC3Dsizei sourceRange, GC3Dint* clippedStart, GC3Dsizei* clippedRange) 80 { 81 ASSERT(clippedStart && clippedRange); 82 if (start < 0) { 83 range += start; 84 start = 0; 85 } 86 GC3Dint end = start + range; 87 if (end > sourceRange) 88 range -= end - sourceRange; 89 *clippedStart = start; 90 *clippedRange = range; 91 } 92 93 // Returns false if no clipping is necessary, i.e., x, y, width, height stay the same. 94 bool clip2D(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, 95 GC3Dsizei sourceWidth, GC3Dsizei sourceHeight, 96 GC3Dint* clippedX, GC3Dint* clippedY, GC3Dsizei* clippedWidth, GC3Dsizei*clippedHeight) 97 { 98 ASSERT(clippedX && clippedY && clippedWidth && clippedHeight); 99 clip1D(x, width, sourceWidth, clippedX, clippedWidth); 100 clip1D(y, height, sourceHeight, clippedY, clippedHeight); 101 return (*clippedX != x || *clippedY != y || *clippedWidth != width || *clippedHeight != height); 102 } 103 104 // Return true if a character belongs to the ASCII subset as defined in 105 // GLSL ES 1.0 spec section 3.1. 106 bool validateCharacter(unsigned char c) 107 { 108 // Printing characters are valid except " $ ` @ \ ' DEL. 109 if (c >= 32 && c <= 126 110 && c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'') 111 return true; 112 // Horizontal tab, line feed, vertical tab, form feed, carriage return 113 // are also valid. 114 if (c >= 9 && c <= 13) 115 return true; 116 return false; 117 } 118 119 // Strips comments from shader text. This allows non-ASCII characters 120 // to be used in comments without potentially breaking OpenGL 121 // implementations not expecting characters outside the GLSL ES set. 122 class StripComments { 123 public: 124 StripComments(const String& str) 125 : m_parseState(BeginningOfLine) 126 , m_sourceString(str) 127 , m_length(str.length()) 128 , m_position(0) 129 { 130 parse(); 131 } 132 133 String result() 134 { 135 return m_builder.toString(); 136 } 137 138 private: 139 bool hasMoreCharacters() 140 { 141 return (m_position < m_length); 142 } 143 144 void parse() 145 { 146 while (hasMoreCharacters()) { 147 process(current()); 148 // process() might advance the position. 149 if (hasMoreCharacters()) 150 advance(); 151 } 152 } 153 154 void process(UChar); 155 156 bool peek(UChar& character) 157 { 158 if (m_position + 1 >= m_length) 159 return false; 160 character = m_sourceString[m_position + 1]; 161 return true; 162 } 163 164 UChar current() 165 { 166 ASSERT(m_position < m_length); 167 return m_sourceString[m_position]; 168 } 169 170 void advance() 171 { 172 ++m_position; 173 } 174 175 bool isNewline(UChar character) 176 { 177 // Don't attempt to canonicalize newline related characters. 178 return (character == '\n' || character == '\r'); 179 } 180 181 void emit(UChar character) 182 { 183 m_builder.append(character); 184 } 185 186 enum ParseState { 187 // Have not seen an ASCII non-whitespace character yet on 188 // this line. Possible that we might see a preprocessor 189 // directive. 190 BeginningOfLine, 191 192 // Have seen at least one ASCII non-whitespace character 193 // on this line. 194 MiddleOfLine, 195 196 // Handling a preprocessor directive. Passes through all 197 // characters up to the end of the line. Disables comment 198 // processing. 199 InPreprocessorDirective, 200 201 // Handling a single-line comment. The comment text is 202 // replaced with a single space. 203 InSingleLineComment, 204 205 // Handling a multi-line comment. Newlines are passed 206 // through to preserve line numbers. 207 InMultiLineComment 208 }; 209 210 ParseState m_parseState; 211 String m_sourceString; 212 unsigned m_length; 213 unsigned m_position; 214 StringBuilder m_builder; 215 }; 216 217 void StripComments::process(UChar c) 218 { 219 if (isNewline(c)) { 220 // No matter what state we are in, pass through newlines 221 // so we preserve line numbers. 222 emit(c); 223 224 if (m_parseState != InMultiLineComment) 225 m_parseState = BeginningOfLine; 226 227 return; 228 } 229 230 UChar temp = 0; 231 switch (m_parseState) { 232 case BeginningOfLine: 233 if (WTF::isASCIISpace(c)) { 234 emit(c); 235 break; 236 } 237 238 if (c == '#') { 239 m_parseState = InPreprocessorDirective; 240 emit(c); 241 break; 242 } 243 244 // Transition to normal state and re-handle character. 245 m_parseState = MiddleOfLine; 246 process(c); 247 break; 248 249 case MiddleOfLine: 250 if (c == '/' && peek(temp)) { 251 if (temp == '/') { 252 m_parseState = InSingleLineComment; 253 emit(' '); 254 advance(); 255 break; 256 } 257 258 if (temp == '*') { 259 m_parseState = InMultiLineComment; 260 // Emit the comment start in case the user has 261 // an unclosed comment and we want to later 262 // signal an error. 263 emit('/'); 264 emit('*'); 265 advance(); 266 break; 267 } 268 } 269 270 emit(c); 271 break; 272 273 case InPreprocessorDirective: 274 // No matter what the character is, just pass it 275 // through. Do not parse comments in this state. This 276 // might not be the right thing to do long term, but it 277 // should handle the #error preprocessor directive. 278 emit(c); 279 break; 280 281 case InSingleLineComment: 282 // The newline code at the top of this function takes care 283 // of resetting our state when we get out of the 284 // single-line comment. Swallow all other characters. 285 break; 286 287 case InMultiLineComment: 288 if (c == '*' && peek(temp) && temp == '/') { 289 emit('*'); 290 emit('/'); 291 m_parseState = MiddleOfLine; 292 advance(); 293 break; 294 } 295 296 // Swallow all other characters. Unclear whether we may 297 // want or need to just emit a space per character to try 298 // to preserve column numbers for debugging purposes. 299 break; 300 } 301 } 302} // namespace anonymous 303 304class WebGLStateRestorer { 305public: 306 WebGLStateRestorer(WebGLRenderingContext* context, 307 bool changed) 308 : m_context(context) 309 , m_changed(changed) 310 { 311 } 312 313 ~WebGLStateRestorer() 314 { 315 m_context->cleanupAfterGraphicsCall(m_changed); 316 } 317 318private: 319 WebGLRenderingContext* m_context; 320 bool m_changed; 321}; 322 323void WebGLRenderingContext::WebGLRenderingContextRestoreTimer::fired() 324{ 325 // Timer is started when m_contextLost is false. It will first call 326 // onLostContext, which will set m_contextLost to true. Then it will keep 327 // calling restoreContext and reschedule itself until m_contextLost is back 328 // to false. 329 if (!m_context->m_contextLost) { 330 m_context->onLostContext(); 331 startOneShot(secondsBetweenRestoreAttempts); 332 } else { 333 // The rendering context is not restored if there is no handler for 334 // the context restored event. 335 if (!m_context->canvas()->hasEventListeners(eventNames().webglcontextrestoredEvent)) 336 return; 337 338 m_context->restoreContext(); 339 if (m_context->m_contextLost) 340 startOneShot(secondsBetweenRestoreAttempts); 341 } 342} 343 344PassOwnPtr<WebGLRenderingContext> WebGLRenderingContext::create(HTMLCanvasElement* canvas, WebGLContextAttributes* attrs) 345{ 346 HostWindow* hostWindow = canvas->document()->view()->root()->hostWindow(); 347 GraphicsContext3D::Attributes attributes = attrs ? attrs->attributes() : GraphicsContext3D::Attributes(); 348 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(attributes, hostWindow)); 349 350 if (!context) { 351 canvas->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextcreationerrorEvent, false, true, "Could not create a WebGL context.")); 352 return 0; 353 } 354 355 return new WebGLRenderingContext(canvas, context, attributes); 356} 357 358WebGLRenderingContext::WebGLRenderingContext(HTMLCanvasElement* passedCanvas, PassRefPtr<GraphicsContext3D> context, 359 GraphicsContext3D::Attributes attributes) 360 : CanvasRenderingContext(passedCanvas) 361 , m_context(context) 362 , m_restoreTimer(this) 363 , m_videoCache(4) 364 , m_contextLost(false) 365 , m_attributes(attributes) 366{ 367 ASSERT(m_context); 368 setupFlags(); 369 initializeNewContext(); 370} 371 372void WebGLRenderingContext::initializeNewContext() 373{ 374 ASSERT(!m_contextLost); 375 m_needsUpdate = true; 376 m_markedCanvasDirty = false; 377 m_activeTextureUnit = 0; 378 m_packAlignment = 4; 379 m_unpackAlignment = 4; 380 m_unpackFlipY = false; 381 m_unpackPremultiplyAlpha = false; 382 m_unpackColorspaceConversion = GraphicsContext3D::BROWSER_DEFAULT_WEBGL; 383 m_boundArrayBuffer = 0; 384 m_boundElementArrayBuffer = 0; 385 m_currentProgram = 0; 386 m_framebufferBinding = 0; 387 m_renderbufferBinding = 0; 388 m_stencilMask = 0xFFFFFFFF; 389 m_stencilMaskBack = 0xFFFFFFFF; 390 m_stencilFuncRef = 0; 391 m_stencilFuncRefBack = 0; 392 m_stencilFuncMask = 0xFFFFFFFF; 393 m_stencilFuncMaskBack = 0xFFFFFFFF; 394 m_vertexAttribState.clear(); 395 396 GC3Dint numCombinedTextureImageUnits = 0; 397 m_context->getIntegerv(GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS, &numCombinedTextureImageUnits); 398 m_textureUnits.clear(); 399 m_textureUnits.resize(numCombinedTextureImageUnits); 400 401 GC3Dint numVertexAttribs = 0; 402 m_context->getIntegerv(GraphicsContext3D::MAX_VERTEX_ATTRIBS, &numVertexAttribs); 403 m_maxVertexAttribs = numVertexAttribs; 404 405 m_maxTextureSize = 0; 406 m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_maxTextureSize); 407 m_maxTextureLevel = WebGLTexture::computeLevelCount(m_maxTextureSize, m_maxTextureSize); 408 m_maxCubeMapTextureSize = 0; 409 m_context->getIntegerv(GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE, &m_maxCubeMapTextureSize); 410 m_maxCubeMapTextureLevel = WebGLTexture::computeLevelCount(m_maxCubeMapTextureSize, m_maxCubeMapTextureSize); 411 412 if (!isGLES2NPOTStrict()) 413 createFallbackBlackTextures1x1(); 414 if (!isGLES2Compliant()) 415 initVertexAttrib0(); 416 417 m_context->reshape(canvas()->width(), canvas()->height()); 418 m_context->viewport(0, 0, canvas()->width(), canvas()->height()); 419} 420 421void WebGLRenderingContext::setupFlags() 422{ 423 ASSERT(m_context); 424 425 m_isGLES2Compliant = m_context->isGLES2Compliant(); 426 m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->supports("GL_CHROMIUM_strict_attribs"); 427 m_isResourceSafe = m_context->getExtensions()->supports("GL_CHROMIUM_resource_safe"); 428 if (m_isGLES2Compliant) { 429 m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_OES_texture_npot"); 430 m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_OES_packed_depth_stencil"); 431 } else { 432 m_isGLES2NPOTStrict = !m_context->getExtensions()->supports("GL_ARB_texture_non_power_of_two"); 433 m_isDepthStencilSupported = m_context->getExtensions()->supports("GL_EXT_packed_depth_stencil"); 434 } 435} 436 437WebGLRenderingContext::~WebGLRenderingContext() 438{ 439 detachAndRemoveAllObjects(); 440} 441 442void WebGLRenderingContext::markContextChanged() 443{ 444#if USE(ACCELERATED_COMPOSITING) 445 RenderBox* renderBox = canvas()->renderBox(); 446 if (renderBox && renderBox->hasLayer() && renderBox->layer()->hasAcceleratedCompositing()) 447 renderBox->layer()->contentChanged(RenderLayer::CanvasChanged); 448 else { 449#endif 450 if (!m_markedCanvasDirty) 451 canvas()->didDraw(FloatRect(0, 0, canvas()->width(), canvas()->height())); 452#if USE(ACCELERATED_COMPOSITING) 453 } 454#endif 455 m_markedCanvasDirty = true; 456} 457 458void WebGLRenderingContext::paintRenderingResultsToCanvas() 459{ 460 if (!m_markedCanvasDirty) 461 return; 462 canvas()->clearCopiedImage(); 463 m_markedCanvasDirty = false; 464 m_context->paintRenderingResultsToCanvas(this); 465} 466 467bool WebGLRenderingContext::paintsIntoCanvasBuffer() const 468{ 469 return m_context->paintsIntoCanvasBuffer(); 470} 471 472void WebGLRenderingContext::reshape(int width, int height) 473{ 474 if (m_needsUpdate) { 475#if USE(ACCELERATED_COMPOSITING) 476 RenderBox* renderBox = canvas()->renderBox(); 477 if (renderBox && renderBox->hasLayer()) 478 renderBox->layer()->contentChanged(RenderLayer::CanvasChanged); 479#endif 480 m_needsUpdate = false; 481 } 482 483 // We don't have to mark the canvas as dirty, since the newly created image buffer will also start off 484 // clear (and this matches what reshape will do). 485 m_context->reshape(width, height); 486} 487 488unsigned int WebGLRenderingContext::sizeInBytes(GC3Denum type) 489{ 490 return m_context->sizeInBytes(type); 491} 492 493void WebGLRenderingContext::activeTexture(GC3Denum texture, ExceptionCode& ec) 494{ 495 UNUSED_PARAM(ec); 496 if (isContextLost()) 497 return; 498 if (texture - GraphicsContext3D::TEXTURE0 >= m_textureUnits.size()) { 499 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 500 return; 501 } 502 m_activeTextureUnit = texture - GraphicsContext3D::TEXTURE0; 503 m_context->activeTexture(texture); 504 cleanupAfterGraphicsCall(false); 505} 506 507void WebGLRenderingContext::attachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) 508{ 509 UNUSED_PARAM(ec); 510 if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader)) 511 return; 512 if (!program->attachShader(shader)) { 513 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 514 return; 515 } 516 m_context->attachShader(objectOrZero(program), objectOrZero(shader)); 517 shader->onAttached(); 518 cleanupAfterGraphicsCall(false); 519} 520 521void WebGLRenderingContext::bindAttribLocation(WebGLProgram* program, GC3Duint index, const String& name, ExceptionCode& ec) 522{ 523 UNUSED_PARAM(ec); 524 if (isContextLost() || !validateWebGLObject(program)) 525 return; 526 if (!validateString(name)) 527 return; 528 m_context->bindAttribLocation(objectOrZero(program), index, name); 529 cleanupAfterGraphicsCall(false); 530} 531 532void WebGLRenderingContext::bindBuffer(GC3Denum target, WebGLBuffer* buffer, ExceptionCode& ec) 533{ 534 UNUSED_PARAM(ec); 535 if (isContextLost()) 536 return; 537 if (buffer && buffer->context() != this) { 538 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 539 return; 540 } 541 if (buffer && buffer->getTarget() && buffer->getTarget() != target) { 542 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 543 return; 544 } 545 546 if (target == GraphicsContext3D::ARRAY_BUFFER) 547 m_boundArrayBuffer = buffer; 548 else if (target == GraphicsContext3D::ELEMENT_ARRAY_BUFFER) 549 m_boundElementArrayBuffer = buffer; 550 else { 551 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 552 return; 553 } 554 555 m_context->bindBuffer(target, objectOrZero(buffer)); 556 if (buffer) 557 buffer->setTarget(target); 558 cleanupAfterGraphicsCall(false); 559} 560 561 562void WebGLRenderingContext::bindFramebuffer(GC3Denum target, WebGLFramebuffer* buffer, ExceptionCode& ec) 563{ 564 UNUSED_PARAM(ec); 565 if (isContextLost()) 566 return; 567 if (buffer && buffer->context() != this) { 568 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 569 return; 570 } 571 if (target != GraphicsContext3D::FRAMEBUFFER) { 572 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 573 return; 574 } 575 m_framebufferBinding = buffer; 576 m_context->bindFramebuffer(target, objectOrZero(buffer)); 577 if (buffer) 578 buffer->setHasEverBeenBound(); 579 cleanupAfterGraphicsCall(false); 580} 581 582void WebGLRenderingContext::bindRenderbuffer(GC3Denum target, WebGLRenderbuffer* renderBuffer, ExceptionCode& ec) 583{ 584 UNUSED_PARAM(ec); 585 if (isContextLost()) 586 return; 587 if (renderBuffer && renderBuffer->context() != this) { 588 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 589 return; 590 } 591 if (target != GraphicsContext3D::RENDERBUFFER) { 592 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 593 return; 594 } 595 m_renderbufferBinding = renderBuffer; 596 m_context->bindRenderbuffer(target, objectOrZero(renderBuffer)); 597 if (renderBuffer) 598 renderBuffer->setHasEverBeenBound(); 599 cleanupAfterGraphicsCall(false); 600} 601 602 603void WebGLRenderingContext::bindTexture(GC3Denum target, WebGLTexture* texture, ExceptionCode& ec) 604{ 605 UNUSED_PARAM(ec); 606 if (isContextLost()) 607 return; 608 if (texture && texture->context() != this) { 609 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 610 return; 611 } 612 GC3Dint maxLevel = 0; 613 if (target == GraphicsContext3D::TEXTURE_2D) { 614 m_textureUnits[m_activeTextureUnit].m_texture2DBinding = texture; 615 maxLevel = m_maxTextureLevel; 616 } else if (target == GraphicsContext3D::TEXTURE_CUBE_MAP) { 617 m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding = texture; 618 maxLevel = m_maxCubeMapTextureLevel; 619 } else { 620 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 621 return; 622 } 623 m_context->bindTexture(target, objectOrZero(texture)); 624 if (texture) 625 texture->setTarget(target, maxLevel); 626 627 // Note: previously we used to automatically set the TEXTURE_WRAP_R 628 // repeat mode to CLAMP_TO_EDGE for cube map textures, because OpenGL 629 // ES 2.0 doesn't expose this flag (a bug in the specification) and 630 // otherwise the application has no control over the seams in this 631 // dimension. However, it appears that supporting this properly on all 632 // platforms is fairly involved (will require a HashMap from texture ID 633 // in all ports), and we have not had any complaints, so the logic has 634 // been removed. 635 636 cleanupAfterGraphicsCall(false); 637} 638 639void WebGLRenderingContext::blendColor(GC3Dfloat red, GC3Dfloat green, GC3Dfloat blue, GC3Dfloat alpha) 640{ 641 if (isContextLost()) 642 return; 643 m_context->blendColor(red, green, blue, alpha); 644 cleanupAfterGraphicsCall(false); 645} 646 647void WebGLRenderingContext::blendEquation(GC3Denum mode) 648{ 649 if (isContextLost() || !validateBlendEquation(mode)) 650 return; 651 m_context->blendEquation(mode); 652 cleanupAfterGraphicsCall(false); 653} 654 655void WebGLRenderingContext::blendEquationSeparate(GC3Denum modeRGB, GC3Denum modeAlpha) 656{ 657 if (isContextLost() || !validateBlendEquation(modeRGB) || !validateBlendEquation(modeAlpha)) 658 return; 659 m_context->blendEquationSeparate(modeRGB, modeAlpha); 660 cleanupAfterGraphicsCall(false); 661} 662 663 664void WebGLRenderingContext::blendFunc(GC3Denum sfactor, GC3Denum dfactor) 665{ 666 if (isContextLost() || !validateBlendFuncFactors(sfactor, dfactor)) 667 return; 668 m_context->blendFunc(sfactor, dfactor); 669 cleanupAfterGraphicsCall(false); 670} 671 672void WebGLRenderingContext::blendFuncSeparate(GC3Denum srcRGB, GC3Denum dstRGB, GC3Denum srcAlpha, GC3Denum dstAlpha) 673{ 674 if (isContextLost() || !validateBlendFuncFactors(srcRGB, dstRGB)) 675 return; 676 m_context->blendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha); 677 cleanupAfterGraphicsCall(false); 678} 679 680void WebGLRenderingContext::bufferData(GC3Denum target, GC3Dsizeiptr size, GC3Denum usage, ExceptionCode& ec) 681{ 682 UNUSED_PARAM(ec); 683 if (isContextLost()) 684 return; 685 WebGLBuffer* buffer = validateBufferDataParameters(target, usage); 686 if (!buffer) 687 return; 688 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 689 if (!buffer->associateBufferData(size)) { 690 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 691 return; 692 } 693 } 694 695 m_context->bufferData(target, size, usage); 696 cleanupAfterGraphicsCall(false); 697} 698 699void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBuffer* data, GC3Denum usage, ExceptionCode& ec) 700{ 701 UNUSED_PARAM(ec); 702 if (isContextLost()) 703 return; 704 WebGLBuffer* buffer = validateBufferDataParameters(target, usage); 705 if (!buffer) 706 return; 707 if (!data) { 708 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 709 return; 710 } 711 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 712 if (!buffer->associateBufferData(data)) { 713 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 714 return; 715 } 716 } 717 718 m_context->bufferData(target, data->byteLength(), data->data(), usage); 719 cleanupAfterGraphicsCall(false); 720} 721 722void WebGLRenderingContext::bufferData(GC3Denum target, ArrayBufferView* data, GC3Denum usage, ExceptionCode& ec) 723{ 724 UNUSED_PARAM(ec); 725 if (isContextLost()) 726 return; 727 WebGLBuffer* buffer = validateBufferDataParameters(target, usage); 728 if (!buffer) 729 return; 730 if (!data) { 731 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 732 return; 733 } 734 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 735 if (!buffer->associateBufferData(data)) { 736 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 737 return; 738 } 739 } 740 741 m_context->bufferData(target, data->byteLength(), data->baseAddress(), usage); 742 cleanupAfterGraphicsCall(false); 743} 744 745void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBuffer* data, ExceptionCode& ec) 746{ 747 UNUSED_PARAM(ec); 748 if (isContextLost()) 749 return; 750 WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW); 751 if (!buffer) 752 return; 753 if (!data) 754 return; 755 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 756 if (!buffer->associateBufferSubData(offset, data)) { 757 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 758 return; 759 } 760 } 761 762 m_context->bufferSubData(target, offset, data->byteLength(), data->data()); 763 cleanupAfterGraphicsCall(false); 764} 765 766void WebGLRenderingContext::bufferSubData(GC3Denum target, GC3Dintptr offset, ArrayBufferView* data, ExceptionCode& ec) 767{ 768 UNUSED_PARAM(ec); 769 if (isContextLost()) 770 return; 771 WebGLBuffer* buffer = validateBufferDataParameters(target, GraphicsContext3D::STATIC_DRAW); 772 if (!buffer) 773 return; 774 if (!data) 775 return; 776 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 777 if (!buffer->associateBufferSubData(offset, data)) { 778 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 779 return; 780 } 781 } 782 783 m_context->bufferSubData(target, offset, data->byteLength(), data->baseAddress()); 784 cleanupAfterGraphicsCall(false); 785} 786 787GC3Denum WebGLRenderingContext::checkFramebufferStatus(GC3Denum target) 788{ 789 if (isContextLost()) 790 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; 791 if (target != GraphicsContext3D::FRAMEBUFFER) { 792 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 793 return 0; 794 } 795 if (!m_framebufferBinding || !m_framebufferBinding->object()) 796 return GraphicsContext3D::FRAMEBUFFER_COMPLETE; 797 if (m_framebufferBinding->isIncomplete(true)) 798 return GraphicsContext3D::FRAMEBUFFER_UNSUPPORTED; 799 unsigned long result = m_context->checkFramebufferStatus(target); 800 cleanupAfterGraphicsCall(false); 801 return result; 802} 803 804void WebGLRenderingContext::clear(GC3Dbitfield mask) 805{ 806 if (isContextLost()) 807 return; 808 if (mask & ~(GraphicsContext3D::COLOR_BUFFER_BIT | GraphicsContext3D::DEPTH_BUFFER_BIT | GraphicsContext3D::STENCIL_BUFFER_BIT)) { 809 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 810 return; 811 } 812 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 813 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 814 return; 815 } 816 m_context->clear(mask); 817 cleanupAfterGraphicsCall(true); 818} 819 820void WebGLRenderingContext::clearColor(GC3Dfloat r, GC3Dfloat g, GC3Dfloat b, GC3Dfloat a) 821{ 822 if (isContextLost()) 823 return; 824 if (isnan(r)) 825 r = 0; 826 if (isnan(g)) 827 g = 0; 828 if (isnan(b)) 829 b = 0; 830 if (isnan(a)) 831 a = 1; 832 m_context->clearColor(r, g, b, a); 833 cleanupAfterGraphicsCall(false); 834} 835 836void WebGLRenderingContext::clearDepth(GC3Dfloat depth) 837{ 838 if (isContextLost()) 839 return; 840 m_context->clearDepth(depth); 841 cleanupAfterGraphicsCall(false); 842} 843 844void WebGLRenderingContext::clearStencil(GC3Dint s) 845{ 846 if (isContextLost()) 847 return; 848 m_context->clearStencil(s); 849 cleanupAfterGraphicsCall(false); 850} 851 852void WebGLRenderingContext::colorMask(GC3Dboolean red, GC3Dboolean green, GC3Dboolean blue, GC3Dboolean alpha) 853{ 854 if (isContextLost()) 855 return; 856 m_context->colorMask(red, green, blue, alpha); 857 cleanupAfterGraphicsCall(false); 858} 859 860void WebGLRenderingContext::compileShader(WebGLShader* shader, ExceptionCode& ec) 861{ 862 UNUSED_PARAM(ec); 863 if (isContextLost() || !validateWebGLObject(shader)) 864 return; 865 m_context->compileShader(objectOrZero(shader)); 866 cleanupAfterGraphicsCall(false); 867} 868 869void WebGLRenderingContext::copyTexImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Dint border) 870{ 871 if (isContextLost()) 872 return; 873 if (!validateTexFuncParameters(target, level, internalformat, width, height, border, internalformat, GraphicsContext3D::UNSIGNED_BYTE)) 874 return; 875 WebGLTexture* tex = validateTextureBinding(target, true); 876 if (!tex) 877 return; 878 if (!isTexInternalFormatColorBufferCombinationValid(internalformat, getBoundFramebufferColorFormat())) { 879 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 880 return; 881 } 882 if (!isGLES2NPOTStrict() && level && WebGLTexture::isNPOT(width, height)) { 883 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 884 return; 885 } 886 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 887 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 888 return; 889 } 890 if (isResourceSafe()) 891 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); 892 else { 893 GC3Dint clippedX, clippedY; 894 GC3Dsizei clippedWidth, clippedHeight; 895 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { 896 m_context->texImage2DResourceSafe(target, level, internalformat, width, height, border, 897 internalformat, GraphicsContext3D::UNSIGNED_BYTE, m_unpackAlignment); 898 if (clippedWidth > 0 && clippedHeight > 0) { 899 m_context->copyTexSubImage2D(target, level, clippedX - x, clippedY - y, 900 clippedX, clippedY, clippedWidth, clippedHeight); 901 } 902 } else 903 m_context->copyTexImage2D(target, level, internalformat, x, y, width, height, border); 904 } 905 // FIXME: if the framebuffer is not complete, none of the below should be executed. 906 tex->setLevelInfo(target, level, internalformat, width, height, GraphicsContext3D::UNSIGNED_BYTE); 907 cleanupAfterGraphicsCall(false); 908} 909 910void WebGLRenderingContext::copyTexSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) 911{ 912 if (isContextLost()) 913 return; 914 if (!validateTexFuncLevel(target, level)) 915 return; 916 WebGLTexture* tex = validateTextureBinding(target, true); 917 if (!tex) 918 return; 919 if (!validateSize(xoffset, yoffset) || !validateSize(width, height)) 920 return; 921 if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) { 922 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 923 return; 924 } 925 if (!isTexInternalFormatColorBufferCombinationValid(tex->getInternalFormat(target, level), getBoundFramebufferColorFormat())) { 926 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 927 return; 928 } 929 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 930 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 931 return; 932 } 933 if (isResourceSafe()) 934 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); 935 else { 936 GC3Dint clippedX, clippedY; 937 GC3Dsizei clippedWidth, clippedHeight; 938 if (clip2D(x, y, width, height, getBoundFramebufferWidth(), getBoundFramebufferHeight(), &clippedX, &clippedY, &clippedWidth, &clippedHeight)) { 939 GC3Denum format = tex->getInternalFormat(target, level); 940 GC3Denum type = tex->getType(target, level); 941 OwnArrayPtr<unsigned char> zero; 942 if (width && height) { 943 unsigned int size; 944 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &size, 0); 945 if (error != GraphicsContext3D::NO_ERROR) { 946 m_context->synthesizeGLError(error); 947 return; 948 } 949 zero = adoptArrayPtr(new unsigned char[size]); 950 if (!zero) { 951 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 952 return; 953 } 954 memset(zero.get(), 0, size); 955 } 956 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, zero.get()); 957 if (clippedWidth > 0 && clippedHeight > 0) { 958 m_context->copyTexSubImage2D(target, level, xoffset + clippedX - x, yoffset + clippedY - y, 959 clippedX, clippedY, clippedWidth, clippedHeight); 960 } 961 } else 962 m_context->copyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height); 963 } 964 cleanupAfterGraphicsCall(false); 965} 966 967PassRefPtr<WebGLBuffer> WebGLRenderingContext::createBuffer() 968{ 969 if (isContextLost()) 970 return 0; 971 RefPtr<WebGLBuffer> o = WebGLBuffer::create(this); 972 addObject(o.get()); 973 return o; 974} 975 976PassRefPtr<WebGLFramebuffer> WebGLRenderingContext::createFramebuffer() 977{ 978 if (isContextLost()) 979 return 0; 980 RefPtr<WebGLFramebuffer> o = WebGLFramebuffer::create(this); 981 addObject(o.get()); 982 return o; 983} 984 985PassRefPtr<WebGLTexture> WebGLRenderingContext::createTexture() 986{ 987 if (isContextLost()) 988 return 0; 989 RefPtr<WebGLTexture> o = WebGLTexture::create(this); 990 addObject(o.get()); 991 return o; 992} 993 994PassRefPtr<WebGLProgram> WebGLRenderingContext::createProgram() 995{ 996 if (isContextLost()) 997 return 0; 998 RefPtr<WebGLProgram> o = WebGLProgram::create(this); 999 addObject(o.get()); 1000 return o; 1001} 1002 1003PassRefPtr<WebGLRenderbuffer> WebGLRenderingContext::createRenderbuffer() 1004{ 1005 if (isContextLost()) 1006 return 0; 1007 RefPtr<WebGLRenderbuffer> o = WebGLRenderbuffer::create(this); 1008 addObject(o.get()); 1009 return o; 1010} 1011 1012PassRefPtr<WebGLShader> WebGLRenderingContext::createShader(GC3Denum type, ExceptionCode& ec) 1013{ 1014 UNUSED_PARAM(ec); 1015 if (isContextLost()) 1016 return 0; 1017 if (type != GraphicsContext3D::VERTEX_SHADER && type != GraphicsContext3D::FRAGMENT_SHADER) { 1018 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1019 return 0; 1020 } 1021 1022 RefPtr<WebGLShader> o = WebGLShader::create(this, type); 1023 addObject(o.get()); 1024 return o; 1025} 1026 1027void WebGLRenderingContext::cullFace(GC3Denum mode) 1028{ 1029 if (isContextLost()) 1030 return; 1031 m_context->cullFace(mode); 1032 cleanupAfterGraphicsCall(false); 1033} 1034 1035void WebGLRenderingContext::deleteBuffer(WebGLBuffer* buffer) 1036{ 1037 if (isContextLost() || !buffer) 1038 return; 1039 1040 buffer->deleteObject(); 1041 1042 if (!isGLES2Compliant()) { 1043 VertexAttribState& state = m_vertexAttribState[0]; 1044 if (buffer == state.bufferBinding) { 1045 state.bufferBinding = m_vertexAttrib0Buffer; 1046 state.bytesPerElement = 0; 1047 state.size = 4; 1048 state.type = GraphicsContext3D::FLOAT; 1049 state.normalized = false; 1050 state.stride = 16; 1051 state.originalStride = 0; 1052 state.offset = 0; 1053 } 1054 } 1055} 1056 1057void WebGLRenderingContext::deleteFramebuffer(WebGLFramebuffer* framebuffer) 1058{ 1059 if (isContextLost() || !framebuffer) 1060 return; 1061 if (framebuffer == m_framebufferBinding) { 1062 m_framebufferBinding = 0; 1063 // Have to call bindFramebuffer here to bind back to internal fbo. 1064 m_context->bindFramebuffer(GraphicsContext3D::FRAMEBUFFER, 0); 1065 } 1066 framebuffer->deleteObject(); 1067} 1068 1069void WebGLRenderingContext::deleteProgram(WebGLProgram* program) 1070{ 1071 if (isContextLost() || !program) 1072 return; 1073 if (program->context() != this) { 1074 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1075 return; 1076 } 1077 if (!program->object()) 1078 return; 1079 program->deleteObject(); 1080} 1081 1082void WebGLRenderingContext::deleteRenderbuffer(WebGLRenderbuffer* renderbuffer) 1083{ 1084 if (isContextLost() || !renderbuffer) 1085 return; 1086 if (renderbuffer == m_renderbufferBinding) 1087 m_renderbufferBinding = 0; 1088 renderbuffer->deleteObject(); 1089 if (m_framebufferBinding) 1090 m_framebufferBinding->removeAttachment(renderbuffer); 1091} 1092 1093void WebGLRenderingContext::deleteShader(WebGLShader* shader) 1094{ 1095 if (isContextLost() || !shader) 1096 return; 1097 1098 shader->deleteObject(); 1099} 1100 1101void WebGLRenderingContext::deleteTexture(WebGLTexture* texture) 1102{ 1103 if (isContextLost() || !texture) 1104 return; 1105 1106 texture->deleteObject(); 1107 if (m_framebufferBinding) 1108 m_framebufferBinding->removeAttachment(texture); 1109} 1110 1111void WebGLRenderingContext::depthFunc(GC3Denum func) 1112{ 1113 if (isContextLost()) 1114 return; 1115 m_context->depthFunc(func); 1116 cleanupAfterGraphicsCall(false); 1117} 1118 1119void WebGLRenderingContext::depthMask(GC3Dboolean flag) 1120{ 1121 if (isContextLost()) 1122 return; 1123 m_context->depthMask(flag); 1124 cleanupAfterGraphicsCall(false); 1125} 1126 1127void WebGLRenderingContext::depthRange(GC3Dfloat zNear, GC3Dfloat zFar) 1128{ 1129 if (isContextLost()) 1130 return; 1131 if (zNear > zFar) { 1132 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1133 return; 1134 } 1135 m_context->depthRange(zNear, zFar); 1136 cleanupAfterGraphicsCall(false); 1137} 1138 1139void WebGLRenderingContext::detachShader(WebGLProgram* program, WebGLShader* shader, ExceptionCode& ec) 1140{ 1141 UNUSED_PARAM(ec); 1142 if (isContextLost() || !validateWebGLObject(program) || !validateWebGLObject(shader)) 1143 return; 1144 if (!program->detachShader(shader)) { 1145 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1146 return; 1147 } 1148 m_context->detachShader(objectOrZero(program), objectOrZero(shader)); 1149 shader->onDetached(); 1150 cleanupAfterGraphicsCall(false); 1151} 1152 1153 1154void WebGLRenderingContext::disable(GC3Denum cap) 1155{ 1156 if (isContextLost() || !validateCapability(cap)) 1157 return; 1158 m_context->disable(cap); 1159 cleanupAfterGraphicsCall(false); 1160} 1161 1162void WebGLRenderingContext::disableVertexAttribArray(GC3Duint index, ExceptionCode& ec) 1163{ 1164 UNUSED_PARAM(ec); 1165 if (isContextLost()) 1166 return; 1167 if (index >= m_maxVertexAttribs) { 1168 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1169 return; 1170 } 1171 1172 if (index < m_vertexAttribState.size()) 1173 m_vertexAttribState[index].enabled = false; 1174 1175 if (index > 0 || isGLES2Compliant()) { 1176 m_context->disableVertexAttribArray(index); 1177 cleanupAfterGraphicsCall(false); 1178 } 1179} 1180 1181bool WebGLRenderingContext::validateElementArraySize(GC3Dsizei count, GC3Denum type, GC3Dintptr offset) 1182{ 1183 if (!m_boundElementArrayBuffer) 1184 return false; 1185 1186 if (offset < 0) 1187 return false; 1188 1189 if (type == GraphicsContext3D::UNSIGNED_SHORT) { 1190 // For an unsigned short array, offset must be divisible by 2 for alignment reasons. 1191 if (offset % 2) 1192 return false; 1193 1194 // Make uoffset an element offset. 1195 offset /= 2; 1196 1197 GC3Dsizeiptr n = m_boundElementArrayBuffer->byteLength() / 2; 1198 if (offset > n || count > n - offset) 1199 return false; 1200 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { 1201 GC3Dsizeiptr n = m_boundElementArrayBuffer->byteLength(); 1202 if (offset > n || count > n - offset) 1203 return false; 1204 } 1205 return true; 1206} 1207 1208bool WebGLRenderingContext::validateIndexArrayConservative(GC3Denum type, int& numElementsRequired) 1209{ 1210 // Performs conservative validation by caching a maximum index of 1211 // the given type per element array buffer. If all of the bound 1212 // array buffers have enough elements to satisfy that maximum 1213 // index, skips the expensive per-draw-call iteration in 1214 // validateIndexArrayPrecise. 1215 1216 if (!m_boundElementArrayBuffer) 1217 return false; 1218 1219 GC3Dsizeiptr numElements = m_boundElementArrayBuffer->byteLength(); 1220 // The case count==0 is already dealt with in drawElements before validateIndexArrayConservative. 1221 if (!numElements) 1222 return false; 1223 const ArrayBuffer* buffer = m_boundElementArrayBuffer->elementArrayBuffer(); 1224 ASSERT(buffer); 1225 1226 int maxIndex = m_boundElementArrayBuffer->getCachedMaxIndex(type); 1227 if (maxIndex < 0) { 1228 // Compute the maximum index in the entire buffer for the given type of index. 1229 switch (type) { 1230 case GraphicsContext3D::UNSIGNED_BYTE: { 1231 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(buffer->data()); 1232 for (GC3Dsizeiptr i = 0; i < numElements; i++) 1233 maxIndex = max(maxIndex, static_cast<int>(p[i])); 1234 break; 1235 } 1236 case GraphicsContext3D::UNSIGNED_SHORT: { 1237 numElements /= sizeof(GC3Dushort); 1238 const GC3Dushort* p = static_cast<const GC3Dushort*>(buffer->data()); 1239 for (GC3Dsizeiptr i = 0; i < numElements; i++) 1240 maxIndex = max(maxIndex, static_cast<int>(p[i])); 1241 break; 1242 } 1243 default: 1244 return false; 1245 } 1246 m_boundElementArrayBuffer->setCachedMaxIndex(type, maxIndex); 1247 } 1248 1249 if (maxIndex >= 0) { 1250 // The number of required elements is one more than the maximum 1251 // index that will be accessed. 1252 numElementsRequired = maxIndex + 1; 1253 return true; 1254 } 1255 1256 return false; 1257} 1258 1259bool WebGLRenderingContext::validateIndexArrayPrecise(GC3Dsizei count, GC3Denum type, GC3Dintptr offset, int& numElementsRequired) 1260{ 1261 ASSERT(count >= 0 && offset >= 0); 1262 int lastIndex = -1; 1263 1264 if (!m_boundElementArrayBuffer) 1265 return false; 1266 1267 if (!count) { 1268 numElementsRequired = 0; 1269 return true; 1270 } 1271 1272 if (!m_boundElementArrayBuffer->elementArrayBuffer()) 1273 return false; 1274 1275 unsigned long uoffset = offset; 1276 unsigned long n = count; 1277 1278 if (type == GraphicsContext3D::UNSIGNED_SHORT) { 1279 // Make uoffset an element offset. 1280 uoffset /= sizeof(GC3Dushort); 1281 const GC3Dushort* p = static_cast<const GC3Dushort*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset; 1282 while (n-- > 0) { 1283 if (*p > lastIndex) 1284 lastIndex = *p; 1285 ++p; 1286 } 1287 } else if (type == GraphicsContext3D::UNSIGNED_BYTE) { 1288 const GC3Dubyte* p = static_cast<const GC3Dubyte*>(m_boundElementArrayBuffer->elementArrayBuffer()->data()) + uoffset; 1289 while (n-- > 0) { 1290 if (*p > lastIndex) 1291 lastIndex = *p; 1292 ++p; 1293 } 1294 } 1295 1296 // Then set the last index in the index array and make sure it is valid. 1297 numElementsRequired = lastIndex + 1; 1298 return numElementsRequired > 0; 1299} 1300 1301bool WebGLRenderingContext::validateRenderingState(int numElementsRequired) 1302{ 1303 if (!m_currentProgram) 1304 return false; 1305 1306 int numAttribStates = static_cast<int>(m_vertexAttribState.size()); 1307 1308 // Look in each enabled vertex attrib and check if they've been bound to a buffer. 1309 for (int i = 0; i < numAttribStates; ++i) { 1310 if (m_vertexAttribState[i].enabled 1311 && (!m_vertexAttribState[i].bufferBinding || !m_vertexAttribState[i].bufferBinding->object())) 1312 return false; 1313 } 1314 1315 if (numElementsRequired <= 0) 1316 return true; 1317 1318 // Look in each consumed vertex attrib (by the current program) and find the smallest buffer size 1319 int smallestNumElements = INT_MAX; 1320 int numActiveAttribLocations = m_currentProgram->numActiveAttribLocations(); 1321 for (int i = 0; i < numActiveAttribLocations; ++i) { 1322 int loc = m_currentProgram->getActiveAttribLocation(i); 1323 if (loc >=0 && loc < numAttribStates) { 1324 const VertexAttribState& state = m_vertexAttribState[loc]; 1325 if (state.enabled) { 1326 // Avoid off-by-one errors in numElements computation. 1327 // For the last element, we will only touch the data for the 1328 // element and nothing beyond it. 1329 int bytesRemaining = static_cast<int>(state.bufferBinding->byteLength() - state.offset); 1330 int numElements = 0; 1331 ASSERT(state.stride > 0); 1332 if (bytesRemaining >= state.bytesPerElement) 1333 numElements = 1 + (bytesRemaining - state.bytesPerElement) / state.stride; 1334 if (numElements < smallestNumElements) 1335 smallestNumElements = numElements; 1336 } 1337 } 1338 } 1339 1340 if (smallestNumElements == INT_MAX) 1341 smallestNumElements = 0; 1342 1343 return numElementsRequired <= smallestNumElements; 1344} 1345 1346bool WebGLRenderingContext::validateWebGLObject(WebGLObject* object) 1347{ 1348 if (!object || !object->object()) { 1349 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1350 return false; 1351 } 1352 if (object->context() != this) { 1353 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1354 return false; 1355 } 1356 return true; 1357} 1358 1359void WebGLRenderingContext::drawArrays(GC3Denum mode, GC3Dint first, GC3Dsizei count, ExceptionCode& ec) 1360{ 1361 UNUSED_PARAM(ec); 1362 1363 if (isContextLost() || !validateDrawMode(mode)) 1364 return; 1365 1366 if (!validateStencilSettings()) 1367 return; 1368 1369 if (first < 0 || count < 0) { 1370 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1371 return; 1372 } 1373 1374 if (!count) 1375 return; 1376 1377 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 1378 // Ensure we have a valid rendering state 1379 CheckedInt<GC3Dint> checkedFirst(first); 1380 CheckedInt<GC3Dint> checkedCount(count); 1381 CheckedInt<GC3Dint> checkedSum = checkedFirst + checkedCount; 1382 if (!checkedSum.valid() || !validateRenderingState(checkedSum.value())) { 1383 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1384 return; 1385 } 1386 } else { 1387 if (!validateRenderingState(0)) { 1388 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1389 return; 1390 } 1391 } 1392 1393 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 1394 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 1395 return; 1396 } 1397 1398 bool vertexAttrib0Simulated = false; 1399 if (!isGLES2Compliant()) 1400 vertexAttrib0Simulated = simulateVertexAttrib0(first + count - 1); 1401 if (!isGLES2NPOTStrict()) 1402 handleNPOTTextures(true); 1403 m_context->drawArrays(mode, first, count); 1404 if (!isGLES2Compliant() && vertexAttrib0Simulated) 1405 restoreStatesAfterVertexAttrib0Simulation(); 1406 if (!isGLES2NPOTStrict()) 1407 handleNPOTTextures(false); 1408 cleanupAfterGraphicsCall(true); 1409} 1410 1411void WebGLRenderingContext::drawElements(GC3Denum mode, GC3Dsizei count, GC3Denum type, GC3Dintptr offset, ExceptionCode& ec) 1412{ 1413 UNUSED_PARAM(ec); 1414 1415 if (isContextLost() || !validateDrawMode(mode)) 1416 return; 1417 1418 if (!validateStencilSettings()) 1419 return; 1420 1421 switch (type) { 1422 case GraphicsContext3D::UNSIGNED_BYTE: 1423 case GraphicsContext3D::UNSIGNED_SHORT: 1424 break; 1425 default: 1426 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1427 return; 1428 } 1429 1430 if (count < 0 || offset < 0) { 1431 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1432 return; 1433 } 1434 1435 if (!count) 1436 return; 1437 1438 int numElements = 0; 1439 if (!isErrorGeneratedOnOutOfBoundsAccesses()) { 1440 // Ensure we have a valid rendering state 1441 if (!validateElementArraySize(count, type, offset)) { 1442 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1443 return; 1444 } 1445 if (!count) 1446 return; 1447 if (!validateIndexArrayConservative(type, numElements) || !validateRenderingState(numElements)) { 1448 if (!validateIndexArrayPrecise(count, type, offset, numElements) || !validateRenderingState(numElements)) { 1449 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1450 return; 1451 } 1452 } 1453 } else { 1454 if (!validateRenderingState(0)) { 1455 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1456 return; 1457 } 1458 } 1459 1460 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 1461 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 1462 return; 1463 } 1464 1465 bool vertexAttrib0Simulated = false; 1466 if (!isGLES2Compliant()) { 1467 if (!numElements) 1468 validateIndexArrayPrecise(count, type, offset, numElements); 1469 vertexAttrib0Simulated = simulateVertexAttrib0(numElements); 1470 } 1471 if (!isGLES2NPOTStrict()) 1472 handleNPOTTextures(true); 1473 m_context->drawElements(mode, count, type, offset); 1474 if (!isGLES2Compliant() && vertexAttrib0Simulated) 1475 restoreStatesAfterVertexAttrib0Simulation(); 1476 if (!isGLES2NPOTStrict()) 1477 handleNPOTTextures(false); 1478 cleanupAfterGraphicsCall(true); 1479} 1480 1481void WebGLRenderingContext::enable(GC3Denum cap) 1482{ 1483 if (isContextLost() || !validateCapability(cap)) 1484 return; 1485 m_context->enable(cap); 1486 cleanupAfterGraphicsCall(false); 1487} 1488 1489void WebGLRenderingContext::enableVertexAttribArray(GC3Duint index, ExceptionCode& ec) 1490{ 1491 UNUSED_PARAM(ec); 1492 if (isContextLost()) 1493 return; 1494 if (index >= m_maxVertexAttribs) { 1495 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1496 return; 1497 } 1498 1499 if (index >= m_vertexAttribState.size()) 1500 m_vertexAttribState.resize(index + 1); 1501 1502 m_vertexAttribState[index].enabled = true; 1503 1504 m_context->enableVertexAttribArray(index); 1505 cleanupAfterGraphicsCall(false); 1506} 1507 1508void WebGLRenderingContext::finish() 1509{ 1510 if (isContextLost()) 1511 return; 1512 m_context->finish(); 1513 cleanupAfterGraphicsCall(true); 1514} 1515 1516 1517void WebGLRenderingContext::flush() 1518{ 1519 if (isContextLost()) 1520 return; 1521 m_context->flush(); 1522 cleanupAfterGraphicsCall(true); 1523} 1524 1525void WebGLRenderingContext::framebufferRenderbuffer(GC3Denum target, GC3Denum attachment, GC3Denum renderbuffertarget, WebGLRenderbuffer* buffer, ExceptionCode& ec) 1526{ 1527 UNUSED_PARAM(ec); 1528 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment)) 1529 return; 1530 if (renderbuffertarget != GraphicsContext3D::RENDERBUFFER) { 1531 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1532 return; 1533 } 1534 if (buffer && buffer->context() != this) { 1535 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1536 return; 1537 } 1538 // Don't allow the default framebuffer to be mutated; all current 1539 // implementations use an FBO internally in place of the default 1540 // FBO. 1541 if (!m_framebufferBinding || !m_framebufferBinding->object()) { 1542 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1543 return; 1544 } 1545 Platform3DObject bufferObject = objectOrZero(buffer); 1546 bool reattachDepth = false; 1547 bool reattachStencil = false; 1548 bool reattachDepthStencilDepth = false; 1549 bool reattachDepthStencilStencil = false; 1550 switch (attachment) { 1551 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: 1552 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, bufferObject); 1553 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, bufferObject); 1554 if (!bufferObject) { 1555 reattachDepth = true; 1556 reattachStencil = true; 1557 } 1558 break; 1559 case GraphicsContext3D::DEPTH_ATTACHMENT: 1560 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer)); 1561 if (!bufferObject) 1562 reattachDepthStencilDepth = true; 1563 break; 1564 case GraphicsContext3D::STENCIL_ATTACHMENT: 1565 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer)); 1566 if (!bufferObject) 1567 reattachDepthStencilStencil = true; 1568 break; 1569 default: 1570 m_context->framebufferRenderbuffer(target, attachment, renderbuffertarget, objectOrZero(buffer)); 1571 } 1572 m_framebufferBinding->setAttachment(attachment, buffer); 1573 if (reattachDepth) { 1574 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_ATTACHMENT)); 1575 if (object) 1576 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object); 1577 } 1578 if (reattachStencil) { 1579 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::STENCIL_ATTACHMENT)); 1580 if (object) 1581 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object); 1582 } 1583 if (reattachDepthStencilDepth) { 1584 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT)); 1585 if (object) 1586 m_context->framebufferRenderbuffer(target, GraphicsContext3D::DEPTH_ATTACHMENT, renderbuffertarget, object); 1587 } 1588 if (reattachDepthStencilStencil) { 1589 Platform3DObject object = objectOrZero(m_framebufferBinding->getAttachment(GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT)); 1590 if (object) 1591 m_context->framebufferRenderbuffer(target, GraphicsContext3D::STENCIL_ATTACHMENT, renderbuffertarget, object); 1592 } 1593 cleanupAfterGraphicsCall(false); 1594} 1595 1596void WebGLRenderingContext::framebufferTexture2D(GC3Denum target, GC3Denum attachment, GC3Denum textarget, WebGLTexture* texture, GC3Dint level, ExceptionCode& ec) 1597{ 1598 UNUSED_PARAM(ec); 1599 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment)) 1600 return; 1601 if (level) { 1602 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 1603 return; 1604 } 1605 if (texture && texture->context() != this) { 1606 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1607 return; 1608 } 1609 // Don't allow the default framebuffer to be mutated; all current 1610 // implementations use an FBO internally in place of the default 1611 // FBO. 1612 if (!m_framebufferBinding || !m_framebufferBinding->object()) { 1613 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1614 return; 1615 } 1616 m_context->framebufferTexture2D(target, attachment, textarget, objectOrZero(texture), level); 1617 m_framebufferBinding->setAttachment(attachment, textarget, texture, level); 1618 cleanupAfterGraphicsCall(false); 1619} 1620 1621void WebGLRenderingContext::frontFace(GC3Denum mode) 1622{ 1623 if (isContextLost()) 1624 return; 1625 m_context->frontFace(mode); 1626 cleanupAfterGraphicsCall(false); 1627} 1628 1629void WebGLRenderingContext::generateMipmap(GC3Denum target) 1630{ 1631 if (isContextLost()) 1632 return; 1633 WebGLTexture* tex = validateTextureBinding(target, false); 1634 if (!tex) 1635 return; 1636 if (!tex->canGenerateMipmaps()) { 1637 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1638 return; 1639 } 1640 // generateMipmap won't work properly if minFilter is not NEAREST_MIPMAP_LINEAR 1641 // on Mac. Remove the hack once this driver bug is fixed. 1642#if OS(DARWIN) 1643 bool needToResetMinFilter = false; 1644 if (tex->getMinFilter() != GraphicsContext3D::NEAREST_MIPMAP_LINEAR) { 1645 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, GraphicsContext3D::NEAREST_MIPMAP_LINEAR); 1646 needToResetMinFilter = true; 1647 } 1648#endif 1649 m_context->generateMipmap(target); 1650#if OS(DARWIN) 1651 if (needToResetMinFilter) 1652 m_context->texParameteri(target, GraphicsContext3D::TEXTURE_MIN_FILTER, tex->getMinFilter()); 1653#endif 1654 tex->generateMipmapLevelInfo(); 1655 cleanupAfterGraphicsCall(false); 1656} 1657 1658PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveAttrib(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) 1659{ 1660 UNUSED_PARAM(ec); 1661 if (isContextLost() || !validateWebGLObject(program)) 1662 return 0; 1663 ActiveInfo info; 1664 if (!m_context->getActiveAttrib(objectOrZero(program), index, info)) 1665 return 0; 1666 return WebGLActiveInfo::create(info.name, info.type, info.size); 1667} 1668 1669PassRefPtr<WebGLActiveInfo> WebGLRenderingContext::getActiveUniform(WebGLProgram* program, GC3Duint index, ExceptionCode& ec) 1670{ 1671 UNUSED_PARAM(ec); 1672 if (isContextLost() || !validateWebGLObject(program)) 1673 return 0; 1674 ActiveInfo info; 1675 if (!m_context->getActiveUniform(objectOrZero(program), index, info)) 1676 return 0; 1677 if (!isGLES2Compliant()) 1678 if (info.size > 1 && !info.name.endsWith("[0]")) 1679 info.name.append("[0]"); 1680 return WebGLActiveInfo::create(info.name, info.type, info.size); 1681} 1682 1683bool WebGLRenderingContext::getAttachedShaders(WebGLProgram* program, Vector<WebGLShader*>& shaderObjects, ExceptionCode& ec) 1684{ 1685 UNUSED_PARAM(ec); 1686 shaderObjects.clear(); 1687 if (isContextLost() || !validateWebGLObject(program)) 1688 return false; 1689 GC3Dint numShaders = 0; 1690 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ATTACHED_SHADERS, &numShaders); 1691 if (numShaders) { 1692 OwnArrayPtr<Platform3DObject> shaders(new Platform3DObject[numShaders]); 1693 GC3Dsizei count = 0; 1694 m_context->getAttachedShaders(objectOrZero(program), numShaders, &count, shaders.get()); 1695 if (count != numShaders) 1696 return false; 1697 shaderObjects.resize(numShaders); 1698 for (GC3Dint ii = 0; ii < numShaders; ++ii) { 1699 WebGLShader* shader = findShader(shaders[ii]); 1700 if (!shader) { 1701 shaderObjects.clear(); 1702 return false; 1703 } 1704 shaderObjects[ii] = shader; 1705 } 1706 } 1707 return true; 1708} 1709 1710GC3Dint WebGLRenderingContext::getAttribLocation(WebGLProgram* program, const String& name) 1711{ 1712 if (isContextLost()) 1713 return -1; 1714 if (!validateString(name)) 1715 return -1; 1716 return m_context->getAttribLocation(objectOrZero(program), name); 1717} 1718 1719WebGLGetInfo WebGLRenderingContext::getBufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) 1720{ 1721 UNUSED_PARAM(ec); 1722 if (isContextLost()) 1723 return WebGLGetInfo(); 1724 if (target != GraphicsContext3D::ARRAY_BUFFER && target != GraphicsContext3D::ELEMENT_ARRAY_BUFFER) { 1725 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1726 return WebGLGetInfo(); 1727 } 1728 1729 if (pname != GraphicsContext3D::BUFFER_SIZE && pname != GraphicsContext3D::BUFFER_USAGE) { 1730 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1731 return WebGLGetInfo(); 1732 } 1733 1734 WebGLStateRestorer(this, false); 1735 GC3Dint value = 0; 1736 m_context->getBufferParameteriv(target, pname, &value); 1737 if (pname == GraphicsContext3D::BUFFER_SIZE) 1738 return WebGLGetInfo(static_cast<long>(value)); 1739 return WebGLGetInfo(static_cast<unsigned long>(value)); 1740} 1741 1742PassRefPtr<WebGLContextAttributes> WebGLRenderingContext::getContextAttributes() 1743{ 1744 if (isContextLost()) 1745 return 0; 1746 // We always need to return a new WebGLContextAttributes object to 1747 // prevent the user from mutating any cached version. 1748 return WebGLContextAttributes::create(m_context->getContextAttributes()); 1749} 1750 1751GC3Denum WebGLRenderingContext::getError() 1752{ 1753 return m_context->getError(); 1754} 1755 1756WebGLExtension* WebGLRenderingContext::getExtension(const String& name) 1757{ 1758 if (isContextLost()) 1759 return 0; 1760 1761 if (equalIgnoringCase(name, "OES_standard_derivatives") 1762 && m_context->getExtensions()->supports("GL_OES_standard_derivatives")) { 1763 if (!m_oesStandardDerivatives) { 1764 m_context->getExtensions()->ensureEnabled("GL_OES_standard_derivatives"); 1765 m_oesStandardDerivatives = OESStandardDerivatives::create(); 1766 } 1767 return m_oesStandardDerivatives.get(); 1768 } 1769 if (equalIgnoringCase(name, "OES_texture_float") 1770 && m_context->getExtensions()->supports("GL_OES_texture_float")) { 1771 if (!m_oesTextureFloat) { 1772 m_context->getExtensions()->ensureEnabled("GL_OES_texture_float"); 1773 m_oesTextureFloat = OESTextureFloat::create(); 1774 } 1775 return m_oesTextureFloat.get(); 1776 } 1777 if (equalIgnoringCase(name, "WEBKIT_lose_context")) { 1778 if (!m_webkitLoseContext) 1779 m_webkitLoseContext = WebKitLoseContext::create(this); 1780 return m_webkitLoseContext.get(); 1781 } 1782 1783 return 0; 1784} 1785 1786WebGLGetInfo WebGLRenderingContext::getFramebufferAttachmentParameter(GC3Denum target, GC3Denum attachment, GC3Denum pname, ExceptionCode& ec) 1787{ 1788 UNUSED_PARAM(ec); 1789 if (isContextLost() || !validateFramebufferFuncParameters(target, attachment)) 1790 return WebGLGetInfo(); 1791 switch (pname) { 1792 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: 1793 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME: 1794 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL: 1795 case GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE: 1796 break; 1797 default: 1798 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 1799 return WebGLGetInfo(); 1800 } 1801 1802 if (!m_framebufferBinding || !m_framebufferBinding->object() || m_framebufferBinding->isIncomplete(false)) { 1803 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 1804 return WebGLGetInfo(); 1805 } 1806 1807 if (pname != GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME) { 1808 WebGLStateRestorer(this, false); 1809 GC3Dint value = 0; 1810 m_context->getFramebufferAttachmentParameteriv(target, attachment, pname, &value); 1811 if (pname == GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE) 1812 return WebGLGetInfo(static_cast<unsigned long>(value)); 1813 return WebGLGetInfo(static_cast<long>(value)); 1814 } 1815 1816 WebGLStateRestorer(this, false); 1817 GC3Dint type = 0; 1818 m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &type); 1819 if (!type) 1820 return WebGLGetInfo(); 1821 GC3Dint value = 0; 1822 m_context->getFramebufferAttachmentParameteriv(target, attachment, GraphicsContext3D::FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &value); 1823 switch (type) { 1824 case GraphicsContext3D::RENDERBUFFER: 1825 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(findRenderbuffer(static_cast<Platform3DObject>(value)))); 1826 case GraphicsContext3D::TEXTURE: 1827 return WebGLGetInfo(PassRefPtr<WebGLTexture>(findTexture(static_cast<Platform3DObject>(value)))); 1828 default: 1829 // FIXME: raise exception? 1830 return WebGLGetInfo(); 1831 } 1832} 1833 1834WebGLGetInfo WebGLRenderingContext::getParameter(GC3Denum pname, ExceptionCode& ec) 1835{ 1836 UNUSED_PARAM(ec); 1837 if (isContextLost()) 1838 return WebGLGetInfo(); 1839 WebGLStateRestorer(this, false); 1840 switch (pname) { 1841 case GraphicsContext3D::ACTIVE_TEXTURE: 1842 return getUnsignedLongParameter(pname); 1843 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE: 1844 return getWebGLFloatArrayParameter(pname); 1845 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE: 1846 return getWebGLFloatArrayParameter(pname); 1847 case GraphicsContext3D::ALPHA_BITS: 1848 return getLongParameter(pname); 1849 case GraphicsContext3D::ARRAY_BUFFER_BINDING: 1850 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundArrayBuffer)); 1851 case GraphicsContext3D::BLEND: 1852 return getBooleanParameter(pname); 1853 case GraphicsContext3D::BLEND_COLOR: 1854 return getWebGLFloatArrayParameter(pname); 1855 case GraphicsContext3D::BLEND_DST_ALPHA: 1856 return getUnsignedLongParameter(pname); 1857 case GraphicsContext3D::BLEND_DST_RGB: 1858 return getUnsignedLongParameter(pname); 1859 case GraphicsContext3D::BLEND_EQUATION_ALPHA: 1860 return getUnsignedLongParameter(pname); 1861 case GraphicsContext3D::BLEND_EQUATION_RGB: 1862 return getUnsignedLongParameter(pname); 1863 case GraphicsContext3D::BLEND_SRC_ALPHA: 1864 return getUnsignedLongParameter(pname); 1865 case GraphicsContext3D::BLEND_SRC_RGB: 1866 return getUnsignedLongParameter(pname); 1867 case GraphicsContext3D::BLUE_BITS: 1868 return getLongParameter(pname); 1869 case GraphicsContext3D::COLOR_CLEAR_VALUE: 1870 return getWebGLFloatArrayParameter(pname); 1871 case GraphicsContext3D::COLOR_WRITEMASK: 1872 return getBooleanArrayParameter(pname); 1873 case GraphicsContext3D::COMPRESSED_TEXTURE_FORMATS: 1874 // Defined as null in the spec 1875 return WebGLGetInfo(); 1876 case GraphicsContext3D::CULL_FACE: 1877 return getBooleanParameter(pname); 1878 case GraphicsContext3D::CULL_FACE_MODE: 1879 return getUnsignedLongParameter(pname); 1880 case GraphicsContext3D::CURRENT_PROGRAM: 1881 return WebGLGetInfo(PassRefPtr<WebGLProgram>(m_currentProgram)); 1882 case GraphicsContext3D::DEPTH_BITS: 1883 return getLongParameter(pname); 1884 case GraphicsContext3D::DEPTH_CLEAR_VALUE: 1885 return getFloatParameter(pname); 1886 case GraphicsContext3D::DEPTH_FUNC: 1887 return getUnsignedLongParameter(pname); 1888 case GraphicsContext3D::DEPTH_RANGE: 1889 return getWebGLFloatArrayParameter(pname); 1890 case GraphicsContext3D::DEPTH_TEST: 1891 return getBooleanParameter(pname); 1892 case GraphicsContext3D::DEPTH_WRITEMASK: 1893 return getBooleanParameter(pname); 1894 case GraphicsContext3D::DITHER: 1895 return getBooleanParameter(pname); 1896 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER_BINDING: 1897 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_boundElementArrayBuffer)); 1898 case GraphicsContext3D::FRAMEBUFFER_BINDING: 1899 return WebGLGetInfo(PassRefPtr<WebGLFramebuffer>(m_framebufferBinding)); 1900 case GraphicsContext3D::FRONT_FACE: 1901 return getUnsignedLongParameter(pname); 1902 case GraphicsContext3D::GENERATE_MIPMAP_HINT: 1903 return getUnsignedLongParameter(pname); 1904 case GraphicsContext3D::GREEN_BITS: 1905 return getLongParameter(pname); 1906 case GraphicsContext3D::LINE_WIDTH: 1907 return getFloatParameter(pname); 1908 case GraphicsContext3D::MAX_COMBINED_TEXTURE_IMAGE_UNITS: 1909 return getLongParameter(pname); 1910 case GraphicsContext3D::MAX_CUBE_MAP_TEXTURE_SIZE: 1911 return getLongParameter(pname); 1912 case GraphicsContext3D::MAX_FRAGMENT_UNIFORM_VECTORS: 1913 return getLongParameter(pname); 1914 case GraphicsContext3D::MAX_RENDERBUFFER_SIZE: 1915 return getLongParameter(pname); 1916 case GraphicsContext3D::MAX_TEXTURE_IMAGE_UNITS: 1917 return getLongParameter(pname); 1918 case GraphicsContext3D::MAX_TEXTURE_SIZE: 1919 return getLongParameter(pname); 1920 case GraphicsContext3D::MAX_VARYING_VECTORS: 1921 return getLongParameter(pname); 1922 case GraphicsContext3D::MAX_VERTEX_ATTRIBS: 1923 return getLongParameter(pname); 1924 case GraphicsContext3D::MAX_VERTEX_TEXTURE_IMAGE_UNITS: 1925 return getLongParameter(pname); 1926 case GraphicsContext3D::MAX_VERTEX_UNIFORM_VECTORS: 1927 return getLongParameter(pname); 1928 case GraphicsContext3D::MAX_VIEWPORT_DIMS: 1929 return getWebGLIntArrayParameter(pname); 1930 case GraphicsContext3D::NUM_COMPRESSED_TEXTURE_FORMATS: 1931 // WebGL 1.0 specifies that there are no compressed texture formats. 1932 return WebGLGetInfo(static_cast<long>(0)); 1933 case GraphicsContext3D::NUM_SHADER_BINARY_FORMATS: 1934 // FIXME: should we always return 0 for this? 1935 return getLongParameter(pname); 1936 case GraphicsContext3D::PACK_ALIGNMENT: 1937 return getLongParameter(pname); 1938 case GraphicsContext3D::POLYGON_OFFSET_FACTOR: 1939 return getFloatParameter(pname); 1940 case GraphicsContext3D::POLYGON_OFFSET_FILL: 1941 return getBooleanParameter(pname); 1942 case GraphicsContext3D::POLYGON_OFFSET_UNITS: 1943 return getFloatParameter(pname); 1944 case GraphicsContext3D::RED_BITS: 1945 return getLongParameter(pname); 1946 case GraphicsContext3D::RENDERBUFFER_BINDING: 1947 return WebGLGetInfo(PassRefPtr<WebGLRenderbuffer>(m_renderbufferBinding)); 1948 case GraphicsContext3D::RENDERER: 1949 return WebGLGetInfo(m_context->getString(GraphicsContext3D::RENDERER)); 1950 case GraphicsContext3D::SAMPLE_BUFFERS: 1951 return getLongParameter(pname); 1952 case GraphicsContext3D::SAMPLE_COVERAGE_INVERT: 1953 return getBooleanParameter(pname); 1954 case GraphicsContext3D::SAMPLE_COVERAGE_VALUE: 1955 return getFloatParameter(pname); 1956 case GraphicsContext3D::SAMPLES: 1957 return getLongParameter(pname); 1958 case GraphicsContext3D::SCISSOR_BOX: 1959 return getWebGLIntArrayParameter(pname); 1960 case GraphicsContext3D::SCISSOR_TEST: 1961 return getBooleanParameter(pname); 1962 case GraphicsContext3D::SHADING_LANGUAGE_VERSION: 1963 return WebGLGetInfo("WebGL GLSL ES 1.0 (" + m_context->getString(GraphicsContext3D::SHADING_LANGUAGE_VERSION) + ")"); 1964 case GraphicsContext3D::STENCIL_BACK_FAIL: 1965 return getUnsignedLongParameter(pname); 1966 case GraphicsContext3D::STENCIL_BACK_FUNC: 1967 return getUnsignedLongParameter(pname); 1968 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_FAIL: 1969 return getUnsignedLongParameter(pname); 1970 case GraphicsContext3D::STENCIL_BACK_PASS_DEPTH_PASS: 1971 return getUnsignedLongParameter(pname); 1972 case GraphicsContext3D::STENCIL_BACK_REF: 1973 return getLongParameter(pname); 1974 case GraphicsContext3D::STENCIL_BACK_VALUE_MASK: 1975 return getUnsignedLongParameter(pname); 1976 case GraphicsContext3D::STENCIL_BACK_WRITEMASK: 1977 return getUnsignedLongParameter(pname); 1978 case GraphicsContext3D::STENCIL_BITS: 1979 return getLongParameter(pname); 1980 case GraphicsContext3D::STENCIL_CLEAR_VALUE: 1981 return getLongParameter(pname); 1982 case GraphicsContext3D::STENCIL_FAIL: 1983 return getUnsignedLongParameter(pname); 1984 case GraphicsContext3D::STENCIL_FUNC: 1985 return getUnsignedLongParameter(pname); 1986 case GraphicsContext3D::STENCIL_PASS_DEPTH_FAIL: 1987 return getUnsignedLongParameter(pname); 1988 case GraphicsContext3D::STENCIL_PASS_DEPTH_PASS: 1989 return getUnsignedLongParameter(pname); 1990 case GraphicsContext3D::STENCIL_REF: 1991 return getLongParameter(pname); 1992 case GraphicsContext3D::STENCIL_TEST: 1993 return getBooleanParameter(pname); 1994 case GraphicsContext3D::STENCIL_VALUE_MASK: 1995 return getUnsignedLongParameter(pname); 1996 case GraphicsContext3D::STENCIL_WRITEMASK: 1997 return getUnsignedLongParameter(pname); 1998 case GraphicsContext3D::SUBPIXEL_BITS: 1999 return getLongParameter(pname); 2000 case GraphicsContext3D::TEXTURE_BINDING_2D: 2001 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_texture2DBinding)); 2002 case GraphicsContext3D::TEXTURE_BINDING_CUBE_MAP: 2003 return WebGLGetInfo(PassRefPtr<WebGLTexture>(m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding)); 2004 case GraphicsContext3D::UNPACK_ALIGNMENT: 2005 // FIXME: should this be "long" in the spec? 2006 return getIntParameter(pname); 2007 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: 2008 return WebGLGetInfo(m_unpackFlipY); 2009 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: 2010 return WebGLGetInfo(m_unpackPremultiplyAlpha); 2011 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: 2012 return WebGLGetInfo(static_cast<unsigned long>(m_unpackColorspaceConversion)); 2013 case GraphicsContext3D::VENDOR: 2014 return WebGLGetInfo("Webkit (" + m_context->getString(GraphicsContext3D::VENDOR) + ")"); 2015 case GraphicsContext3D::VERSION: 2016 return WebGLGetInfo("WebGL 1.0 (" + m_context->getString(GraphicsContext3D::VERSION) + ")"); 2017 case GraphicsContext3D::VIEWPORT: 2018 return getWebGLIntArrayParameter(pname); 2019 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives 2020 if (m_oesStandardDerivatives) 2021 return getUnsignedLongParameter(Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES); 2022 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2023 return WebGLGetInfo(); 2024 default: 2025 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2026 return WebGLGetInfo(); 2027 } 2028} 2029 2030WebGLGetInfo WebGLRenderingContext::getProgramParameter(WebGLProgram* program, GC3Denum pname, ExceptionCode& ec) 2031{ 2032 UNUSED_PARAM(ec); 2033 if (isContextLost() || !validateWebGLObject(program)) 2034 return WebGLGetInfo(); 2035 2036 WebGLStateRestorer(this, false); 2037 GC3Dint value = 0; 2038 switch (pname) { 2039 case GraphicsContext3D::DELETE_STATUS: 2040 return WebGLGetInfo(program->isDeleted()); 2041 case GraphicsContext3D::VALIDATE_STATUS: 2042 m_context->getProgramiv(objectOrZero(program), pname, &value); 2043 return WebGLGetInfo(static_cast<bool>(value)); 2044 case GraphicsContext3D::LINK_STATUS: 2045 return WebGLGetInfo(program->getLinkStatus()); 2046 case GraphicsContext3D::INFO_LOG_LENGTH: 2047 case GraphicsContext3D::ATTACHED_SHADERS: 2048 case GraphicsContext3D::ACTIVE_ATTRIBUTES: 2049 case GraphicsContext3D::ACTIVE_ATTRIBUTE_MAX_LENGTH: 2050 case GraphicsContext3D::ACTIVE_UNIFORMS: 2051 case GraphicsContext3D::ACTIVE_UNIFORM_MAX_LENGTH: 2052 m_context->getProgramiv(objectOrZero(program), pname, &value); 2053 return WebGLGetInfo(static_cast<long>(value)); 2054 default: 2055 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2056 return WebGLGetInfo(); 2057 } 2058} 2059 2060String WebGLRenderingContext::getProgramInfoLog(WebGLProgram* program, ExceptionCode& ec) 2061{ 2062 UNUSED_PARAM(ec); 2063 if (isContextLost()) 2064 return String(); 2065 if (!validateWebGLObject(program)) 2066 return ""; 2067 WebGLStateRestorer(this, false); 2068 return m_context->getProgramInfoLog(objectOrZero(program)); 2069} 2070 2071WebGLGetInfo WebGLRenderingContext::getRenderbufferParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) 2072{ 2073 UNUSED_PARAM(ec); 2074 if (isContextLost()) 2075 return WebGLGetInfo(); 2076 if (target != GraphicsContext3D::RENDERBUFFER) { 2077 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2078 return WebGLGetInfo(); 2079 } 2080 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { 2081 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2082 return WebGLGetInfo(); 2083 } 2084 2085 if (m_renderbufferBinding->getInternalFormat() == GraphicsContext3D::DEPTH_STENCIL 2086 && !m_renderbufferBinding->isValid()) { 2087 ASSERT(!isDepthStencilSupported()); 2088 long value = 0; 2089 switch (pname) { 2090 case GraphicsContext3D::RENDERBUFFER_WIDTH: 2091 value = static_cast<long>(m_renderbufferBinding->getWidth()); 2092 break; 2093 case GraphicsContext3D::RENDERBUFFER_HEIGHT: 2094 value = static_cast<long>(m_renderbufferBinding->getHeight()); 2095 break; 2096 case GraphicsContext3D::RENDERBUFFER_RED_SIZE: 2097 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: 2098 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: 2099 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: 2100 value = 0; 2101 break; 2102 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: 2103 value = 24; 2104 break; 2105 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: 2106 value = 8; 2107 break; 2108 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: 2109 return WebGLGetInfo(static_cast<unsigned long>(m_renderbufferBinding->getInternalFormat())); 2110 default: 2111 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2112 return WebGLGetInfo(); 2113 } 2114 return WebGLGetInfo(value); 2115 } 2116 2117 WebGLStateRestorer(this, false); 2118 GC3Dint value = 0; 2119 switch (pname) { 2120 case GraphicsContext3D::RENDERBUFFER_WIDTH: 2121 case GraphicsContext3D::RENDERBUFFER_HEIGHT: 2122 case GraphicsContext3D::RENDERBUFFER_RED_SIZE: 2123 case GraphicsContext3D::RENDERBUFFER_GREEN_SIZE: 2124 case GraphicsContext3D::RENDERBUFFER_BLUE_SIZE: 2125 case GraphicsContext3D::RENDERBUFFER_ALPHA_SIZE: 2126 case GraphicsContext3D::RENDERBUFFER_DEPTH_SIZE: 2127 case GraphicsContext3D::RENDERBUFFER_STENCIL_SIZE: 2128 m_context->getRenderbufferParameteriv(target, pname, &value); 2129 return WebGLGetInfo(static_cast<long>(value)); 2130 case GraphicsContext3D::RENDERBUFFER_INTERNAL_FORMAT: 2131 return WebGLGetInfo(static_cast<unsigned long>(m_renderbufferBinding->getInternalFormat())); 2132 default: 2133 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2134 return WebGLGetInfo(); 2135 } 2136} 2137 2138WebGLGetInfo WebGLRenderingContext::getShaderParameter(WebGLShader* shader, GC3Denum pname, ExceptionCode& ec) 2139{ 2140 UNUSED_PARAM(ec); 2141 if (isContextLost() || !validateWebGLObject(shader)) 2142 return WebGLGetInfo(); 2143 WebGLStateRestorer(this, false); 2144 GC3Dint value = 0; 2145 switch (pname) { 2146 case GraphicsContext3D::DELETE_STATUS: 2147 return WebGLGetInfo(shader->isDeleted()); 2148 case GraphicsContext3D::COMPILE_STATUS: 2149 m_context->getShaderiv(objectOrZero(shader), pname, &value); 2150 return WebGLGetInfo(static_cast<bool>(value)); 2151 case GraphicsContext3D::SHADER_TYPE: 2152 m_context->getShaderiv(objectOrZero(shader), pname, &value); 2153 return WebGLGetInfo(static_cast<unsigned long>(value)); 2154 case GraphicsContext3D::INFO_LOG_LENGTH: 2155 case GraphicsContext3D::SHADER_SOURCE_LENGTH: 2156 m_context->getShaderiv(objectOrZero(shader), pname, &value); 2157 return WebGLGetInfo(static_cast<long>(value)); 2158 default: 2159 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2160 return WebGLGetInfo(); 2161 } 2162} 2163 2164String WebGLRenderingContext::getShaderInfoLog(WebGLShader* shader, ExceptionCode& ec) 2165{ 2166 UNUSED_PARAM(ec); 2167 if (isContextLost()) 2168 return String(); 2169 if (!validateWebGLObject(shader)) 2170 return ""; 2171 WebGLStateRestorer(this, false); 2172 return m_context->getShaderInfoLog(objectOrZero(shader)); 2173} 2174 2175String WebGLRenderingContext::getShaderSource(WebGLShader* shader, ExceptionCode& ec) 2176{ 2177 UNUSED_PARAM(ec); 2178 if (isContextLost()) 2179 return String(); 2180 if (!validateWebGLObject(shader)) 2181 return ""; 2182 WebGLStateRestorer(this, false); 2183 return m_context->getShaderSource(objectOrZero(shader)); 2184} 2185 2186Vector<String> WebGLRenderingContext::getSupportedExtensions() 2187{ 2188 Vector<String> result; 2189 if (m_context->getExtensions()->supports("GL_OES_texture_float")) 2190 result.append("OES_texture_float"); 2191 if (m_context->getExtensions()->supports("GL_OES_standard_derivatives")) 2192 result.append("OES_standard_derivatives"); 2193 result.append("WEBKIT_lose_context"); 2194 return result; 2195} 2196 2197WebGLGetInfo WebGLRenderingContext::getTexParameter(GC3Denum target, GC3Denum pname, ExceptionCode& ec) 2198{ 2199 UNUSED_PARAM(ec); 2200 if (isContextLost()) 2201 return WebGLGetInfo(); 2202 WebGLTexture* tex = validateTextureBinding(target, false); 2203 if (!tex) 2204 return WebGLGetInfo(); 2205 WebGLStateRestorer(this, false); 2206 GC3Dint value = 0; 2207 switch (pname) { 2208 case GraphicsContext3D::TEXTURE_MAG_FILTER: 2209 case GraphicsContext3D::TEXTURE_MIN_FILTER: 2210 case GraphicsContext3D::TEXTURE_WRAP_S: 2211 case GraphicsContext3D::TEXTURE_WRAP_T: 2212 m_context->getTexParameteriv(target, pname, &value); 2213 return WebGLGetInfo(static_cast<unsigned long>(value)); 2214 default: 2215 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2216 return WebGLGetInfo(); 2217 } 2218} 2219 2220WebGLGetInfo WebGLRenderingContext::getUniform(WebGLProgram* program, const WebGLUniformLocation* uniformLocation, ExceptionCode& ec) 2221{ 2222 UNUSED_PARAM(ec); 2223 if (isContextLost() || !validateWebGLObject(program)) 2224 return WebGLGetInfo(); 2225 if (!uniformLocation || uniformLocation->program() != program) { 2226 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2227 return WebGLGetInfo(); 2228 } 2229 GC3Dint location = uniformLocation->location(); 2230 2231 WebGLStateRestorer(this, false); 2232 // FIXME: make this more efficient using WebGLUniformLocation and caching types in it 2233 GC3Dint activeUniforms = 0; 2234 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::ACTIVE_UNIFORMS, &activeUniforms); 2235 for (GC3Dint i = 0; i < activeUniforms; i++) { 2236 ActiveInfo info; 2237 if (!m_context->getActiveUniform(objectOrZero(program), i, info)) 2238 return WebGLGetInfo(); 2239 // Strip "[0]" from the name if it's an array. 2240 if (info.size > 1) 2241 info.name = info.name.left(info.name.length() - 3); 2242 // If it's an array, we need to iterate through each element, appending "[index]" to the name. 2243 for (GC3Dint index = 0; index < info.size; ++index) { 2244 String name = info.name; 2245 if (info.size > 1 && index >= 1) { 2246 name.append('['); 2247 name.append(String::number(index)); 2248 name.append(']'); 2249 } 2250 // Now need to look this up by name again to find its location 2251 GC3Dint loc = m_context->getUniformLocation(objectOrZero(program), name); 2252 if (loc == location) { 2253 // Found it. Use the type in the ActiveInfo to determine the return type. 2254 GC3Denum baseType; 2255 unsigned int length; 2256 switch (info.type) { 2257 case GraphicsContext3D::BOOL: 2258 baseType = GraphicsContext3D::BOOL; 2259 length = 1; 2260 break; 2261 case GraphicsContext3D::BOOL_VEC2: 2262 baseType = GraphicsContext3D::BOOL; 2263 length = 2; 2264 break; 2265 case GraphicsContext3D::BOOL_VEC3: 2266 baseType = GraphicsContext3D::BOOL; 2267 length = 3; 2268 break; 2269 case GraphicsContext3D::BOOL_VEC4: 2270 baseType = GraphicsContext3D::BOOL; 2271 length = 4; 2272 break; 2273 case GraphicsContext3D::INT: 2274 baseType = GraphicsContext3D::INT; 2275 length = 1; 2276 break; 2277 case GraphicsContext3D::INT_VEC2: 2278 baseType = GraphicsContext3D::INT; 2279 length = 2; 2280 break; 2281 case GraphicsContext3D::INT_VEC3: 2282 baseType = GraphicsContext3D::INT; 2283 length = 3; 2284 break; 2285 case GraphicsContext3D::INT_VEC4: 2286 baseType = GraphicsContext3D::INT; 2287 length = 4; 2288 break; 2289 case GraphicsContext3D::FLOAT: 2290 baseType = GraphicsContext3D::FLOAT; 2291 length = 1; 2292 break; 2293 case GraphicsContext3D::FLOAT_VEC2: 2294 baseType = GraphicsContext3D::FLOAT; 2295 length = 2; 2296 break; 2297 case GraphicsContext3D::FLOAT_VEC3: 2298 baseType = GraphicsContext3D::FLOAT; 2299 length = 3; 2300 break; 2301 case GraphicsContext3D::FLOAT_VEC4: 2302 baseType = GraphicsContext3D::FLOAT; 2303 length = 4; 2304 break; 2305 case GraphicsContext3D::FLOAT_MAT2: 2306 baseType = GraphicsContext3D::FLOAT; 2307 length = 4; 2308 break; 2309 case GraphicsContext3D::FLOAT_MAT3: 2310 baseType = GraphicsContext3D::FLOAT; 2311 length = 9; 2312 break; 2313 case GraphicsContext3D::FLOAT_MAT4: 2314 baseType = GraphicsContext3D::FLOAT; 2315 length = 16; 2316 break; 2317 default: 2318 // Can't handle this type 2319 // FIXME: what to do about samplers? 2320 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2321 return WebGLGetInfo(); 2322 } 2323 switch (baseType) { 2324 case GraphicsContext3D::FLOAT: { 2325 GC3Dfloat value[16] = {0}; 2326 m_context->getUniformfv(objectOrZero(program), location, value); 2327 if (length == 1) 2328 return WebGLGetInfo(value[0]); 2329 return WebGLGetInfo(Float32Array::create(value, length)); 2330 } 2331 case GraphicsContext3D::INT: { 2332 GC3Dint value[4] = {0}; 2333 m_context->getUniformiv(objectOrZero(program), location, value); 2334 if (length == 1) 2335 return WebGLGetInfo(static_cast<long>(value[0])); 2336 return WebGLGetInfo(Int32Array::create(value, length)); 2337 } 2338 case GraphicsContext3D::BOOL: { 2339 GC3Dint value[4] = {0}; 2340 m_context->getUniformiv(objectOrZero(program), location, value); 2341 if (length > 1) { 2342 bool boolValue[16] = {0}; 2343 for (unsigned j = 0; j < length; j++) 2344 boolValue[j] = static_cast<bool>(value[j]); 2345 return WebGLGetInfo(boolValue, length); 2346 } 2347 return WebGLGetInfo(static_cast<bool>(value[0])); 2348 } 2349 default: 2350 notImplemented(); 2351 } 2352 } 2353 } 2354 } 2355 // If we get here, something went wrong in our unfortunately complex logic above 2356 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2357 return WebGLGetInfo(); 2358} 2359 2360PassRefPtr<WebGLUniformLocation> WebGLRenderingContext::getUniformLocation(WebGLProgram* program, const String& name, ExceptionCode& ec) 2361{ 2362 UNUSED_PARAM(ec); 2363 if (isContextLost() || !validateWebGLObject(program)) 2364 return 0; 2365 if (!validateString(name)) 2366 return 0; 2367 WebGLStateRestorer(this, false); 2368 GC3Dint uniformLocation = m_context->getUniformLocation(objectOrZero(program), name); 2369 if (uniformLocation == -1) 2370 return 0; 2371 return WebGLUniformLocation::create(program, uniformLocation); 2372} 2373 2374WebGLGetInfo WebGLRenderingContext::getVertexAttrib(GC3Duint index, GC3Denum pname, ExceptionCode& ec) 2375{ 2376 UNUSED_PARAM(ec); 2377 if (isContextLost()) 2378 return WebGLGetInfo(); 2379 WebGLStateRestorer(this, false); 2380 if (index >= m_maxVertexAttribs) { 2381 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2382 return WebGLGetInfo(); 2383 } 2384 switch (pname) { 2385 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_BUFFER_BINDING: 2386 if ((!isGLES2Compliant() && !index && m_vertexAttribState[0].bufferBinding == m_vertexAttrib0Buffer) 2387 || index >= m_vertexAttribState.size() 2388 || !m_vertexAttribState[index].bufferBinding 2389 || !m_vertexAttribState[index].bufferBinding->object()) 2390 return WebGLGetInfo(); 2391 return WebGLGetInfo(PassRefPtr<WebGLBuffer>(m_vertexAttribState[index].bufferBinding)); 2392 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_ENABLED: 2393 if (index >= m_vertexAttribState.size()) 2394 return WebGLGetInfo(false); 2395 return WebGLGetInfo(m_vertexAttribState[index].enabled); 2396 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_NORMALIZED: 2397 if (index >= m_vertexAttribState.size()) 2398 return WebGLGetInfo(false); 2399 return WebGLGetInfo(m_vertexAttribState[index].normalized); 2400 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_SIZE: 2401 if (index >= m_vertexAttribState.size()) 2402 return WebGLGetInfo(static_cast<long>(4)); 2403 return WebGLGetInfo(static_cast<long>(m_vertexAttribState[index].size)); 2404 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_STRIDE: 2405 if (index >= m_vertexAttribState.size()) 2406 return WebGLGetInfo(static_cast<long>(0)); 2407 return WebGLGetInfo(static_cast<long>(m_vertexAttribState[index].originalStride)); 2408 case GraphicsContext3D::VERTEX_ATTRIB_ARRAY_TYPE: 2409 if (index >= m_vertexAttribState.size()) 2410 return WebGLGetInfo(static_cast<unsigned long>(GraphicsContext3D::FLOAT)); 2411 return WebGLGetInfo(static_cast<unsigned long>(m_vertexAttribState[index].type)); 2412 case GraphicsContext3D::CURRENT_VERTEX_ATTRIB: 2413 if (index >= m_vertexAttribState.size()) { 2414 float value[4] = { 0.0f, 0.0f, 0.0f, 1.0f }; 2415 return WebGLGetInfo(Float32Array::create(value, 4)); 2416 } 2417 return WebGLGetInfo(Float32Array::create(m_vertexAttribState[index].value, 4)); 2418 default: 2419 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2420 return WebGLGetInfo(); 2421 } 2422} 2423 2424GC3Dsizeiptr WebGLRenderingContext::getVertexAttribOffset(GC3Duint index, GC3Denum pname) 2425{ 2426 if (isContextLost()) 2427 return 0; 2428 GC3Dsizeiptr result = m_context->getVertexAttribOffset(index, pname); 2429 cleanupAfterGraphicsCall(false); 2430 return result; 2431} 2432 2433void WebGLRenderingContext::hint(GC3Denum target, GC3Denum mode) 2434{ 2435 if (isContextLost()) 2436 return; 2437 bool isValid = false; 2438 switch (target) { 2439 case GraphicsContext3D::GENERATE_MIPMAP_HINT: 2440 isValid = true; 2441 break; 2442 case Extensions3D::FRAGMENT_SHADER_DERIVATIVE_HINT_OES: // OES_standard_derivatives 2443 if (m_oesStandardDerivatives) 2444 isValid = true; 2445 break; 2446 } 2447 if (!isValid) { 2448 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2449 return; 2450 } 2451 m_context->hint(target, mode); 2452 cleanupAfterGraphicsCall(false); 2453} 2454 2455GC3Dboolean WebGLRenderingContext::isBuffer(WebGLBuffer* buffer) 2456{ 2457 if (!buffer || isContextLost()) 2458 return 0; 2459 2460 if (!buffer->hasEverBeenBound()) 2461 return 0; 2462 2463 return m_context->isBuffer(buffer->object()); 2464} 2465 2466bool WebGLRenderingContext::isContextLost() 2467{ 2468 if (m_restoreTimer.isActive()) 2469 return true; 2470 2471 bool newContextLost = m_context->getExtensions()->getGraphicsResetStatusARB() != GraphicsContext3D::NO_ERROR; 2472 2473 if (newContextLost != m_contextLost) 2474 m_restoreTimer.startOneShot(secondsBetweenRestoreAttempts); 2475 2476 return m_contextLost; 2477} 2478 2479GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap) 2480{ 2481 if (!validateCapability(cap) || isContextLost()) 2482 return 0; 2483 return m_context->isEnabled(cap); 2484} 2485 2486GC3Dboolean WebGLRenderingContext::isFramebuffer(WebGLFramebuffer* framebuffer) 2487{ 2488 if (!framebuffer || isContextLost()) 2489 return 0; 2490 2491 if (!framebuffer->hasEverBeenBound()) 2492 return 0; 2493 2494 return m_context->isFramebuffer(framebuffer->object()); 2495} 2496 2497GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program) 2498{ 2499 if (!program || isContextLost()) 2500 return 0; 2501 2502 return m_context->isProgram(program->object()); 2503} 2504 2505GC3Dboolean WebGLRenderingContext::isRenderbuffer(WebGLRenderbuffer* renderbuffer) 2506{ 2507 if (!renderbuffer || isContextLost()) 2508 return 0; 2509 2510 if (!renderbuffer->hasEverBeenBound()) 2511 return 0; 2512 2513 return m_context->isRenderbuffer(renderbuffer->object()); 2514} 2515 2516GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader) 2517{ 2518 if (!shader || isContextLost()) 2519 return 0; 2520 2521 return m_context->isShader(shader->object()); 2522} 2523 2524GC3Dboolean WebGLRenderingContext::isTexture(WebGLTexture* texture) 2525{ 2526 if (!texture || isContextLost()) 2527 return 0; 2528 2529 if (!texture->hasEverBeenBound()) 2530 return 0; 2531 2532 return m_context->isTexture(texture->object()); 2533} 2534 2535void WebGLRenderingContext::lineWidth(GC3Dfloat width) 2536{ 2537 if (isContextLost()) 2538 return; 2539 m_context->lineWidth(width); 2540 cleanupAfterGraphicsCall(false); 2541} 2542 2543void WebGLRenderingContext::linkProgram(WebGLProgram* program, ExceptionCode& ec) 2544{ 2545 UNUSED_PARAM(ec); 2546 if (isContextLost() || !validateWebGLObject(program)) 2547 return; 2548 if (!isGLES2Compliant()) { 2549 if (!program->getAttachedShader(GraphicsContext3D::VERTEX_SHADER) || !program->getAttachedShader(GraphicsContext3D::FRAGMENT_SHADER)) { 2550 program->setLinkStatus(false); 2551 return; 2552 } 2553 } 2554 2555 m_context->linkProgram(objectOrZero(program)); 2556 program->increaseLinkCount(); 2557 // cache link status 2558 GC3Dint value = 0; 2559 m_context->getProgramiv(objectOrZero(program), GraphicsContext3D::LINK_STATUS, &value); 2560 program->setLinkStatus(static_cast<bool>(value)); 2561 // Need to cache link status before caching active attribute locations. 2562 program->cacheActiveAttribLocations(); 2563 cleanupAfterGraphicsCall(false); 2564} 2565 2566void WebGLRenderingContext::pixelStorei(GC3Denum pname, GC3Dint param) 2567{ 2568 if (isContextLost()) 2569 return; 2570 switch (pname) { 2571 case GraphicsContext3D::UNPACK_FLIP_Y_WEBGL: 2572 m_unpackFlipY = param; 2573 break; 2574 case GraphicsContext3D::UNPACK_PREMULTIPLY_ALPHA_WEBGL: 2575 m_unpackPremultiplyAlpha = param; 2576 break; 2577 case GraphicsContext3D::UNPACK_COLORSPACE_CONVERSION_WEBGL: 2578 if (param == GraphicsContext3D::BROWSER_DEFAULT_WEBGL || param == GraphicsContext3D::NONE) 2579 m_unpackColorspaceConversion = static_cast<GC3Denum>(param); 2580 else { 2581 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2582 return; 2583 } 2584 break; 2585 case GraphicsContext3D::PACK_ALIGNMENT: 2586 case GraphicsContext3D::UNPACK_ALIGNMENT: 2587 if (param == 1 || param == 2 || param == 4 || param == 8) { 2588 if (pname == GraphicsContext3D::PACK_ALIGNMENT) 2589 m_packAlignment = param; 2590 else // GraphicsContext3D::UNPACK_ALIGNMENT: 2591 m_unpackAlignment = param; 2592 m_context->pixelStorei(pname, param); 2593 cleanupAfterGraphicsCall(false); 2594 } else { 2595 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2596 return; 2597 } 2598 break; 2599 default: 2600 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2601 return; 2602 } 2603} 2604 2605void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units) 2606{ 2607 if (isContextLost()) 2608 return; 2609 m_context->polygonOffset(factor, units); 2610 cleanupAfterGraphicsCall(false); 2611} 2612 2613void WebGLRenderingContext::readPixels(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height, GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec) 2614{ 2615 if (isContextLost()) 2616 return; 2617 if (!canvas()->originClean()) { 2618 ec = SECURITY_ERR; 2619 return; 2620 } 2621 // Validate input parameters. 2622 if (!pixels) { 2623 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2624 return; 2625 } 2626 switch (format) { 2627 case GraphicsContext3D::ALPHA: 2628 case GraphicsContext3D::RGB: 2629 case GraphicsContext3D::RGBA: 2630 break; 2631 default: 2632 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2633 return; 2634 } 2635 switch (type) { 2636 case GraphicsContext3D::UNSIGNED_BYTE: 2637 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: 2638 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: 2639 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: 2640 break; 2641 default: 2642 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2643 return; 2644 } 2645 if (format != GraphicsContext3D::RGBA || type != GraphicsContext3D::UNSIGNED_BYTE) { 2646 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2647 return; 2648 } 2649 // Validate array type against pixel type. 2650 if (!pixels->isUnsignedByteArray()) { 2651 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2652 return; 2653 } 2654 if (m_framebufferBinding && !m_framebufferBinding->onAccess(!isResourceSafe())) { 2655 m_context->synthesizeGLError(GraphicsContext3D::INVALID_FRAMEBUFFER_OPERATION); 2656 return; 2657 } 2658 // Calculate array size, taking into consideration of PACK_ALIGNMENT. 2659 unsigned int totalBytesRequired; 2660 unsigned int padding; 2661 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_packAlignment, &totalBytesRequired, &padding); 2662 if (error != GraphicsContext3D::NO_ERROR) { 2663 m_context->synthesizeGLError(error); 2664 return; 2665 } 2666 if (pixels->byteLength() < totalBytesRequired) { 2667 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2668 return; 2669 } 2670 void* data = pixels->baseAddress(); 2671 m_context->readPixels(x, y, width, height, format, type, data); 2672#if OS(DARWIN) 2673 // FIXME: remove this section when GL driver bug on Mac is fixed, i.e., 2674 // when alpha is off, readPixels should set alpha to 255 instead of 0. 2675 if (!m_context->getContextAttributes().alpha) { 2676 unsigned char* pixels = reinterpret_cast<unsigned char*>(data); 2677 for (GC3Dsizei iy = 0; iy < height; ++iy) { 2678 for (GC3Dsizei ix = 0; ix < width; ++ix) { 2679 pixels[3] = 255; 2680 pixels += 4; 2681 } 2682 pixels += padding; 2683 } 2684 } 2685#endif 2686 cleanupAfterGraphicsCall(false); 2687} 2688 2689void WebGLRenderingContext::releaseShaderCompiler() 2690{ 2691 if (isContextLost()) 2692 return; 2693 m_context->releaseShaderCompiler(); 2694 cleanupAfterGraphicsCall(false); 2695} 2696 2697void WebGLRenderingContext::renderbufferStorage(GC3Denum target, GC3Denum internalformat, GC3Dsizei width, GC3Dsizei height) 2698{ 2699 if (isContextLost()) 2700 return; 2701 if (target != GraphicsContext3D::RENDERBUFFER) { 2702 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2703 return; 2704 } 2705 if (!m_renderbufferBinding || !m_renderbufferBinding->object()) { 2706 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 2707 return; 2708 } 2709 if (!validateSize(width, height)) 2710 return; 2711 switch (internalformat) { 2712 case GraphicsContext3D::DEPTH_COMPONENT16: 2713 case GraphicsContext3D::RGBA4: 2714 case GraphicsContext3D::RGB5_A1: 2715 case GraphicsContext3D::RGB565: 2716 case GraphicsContext3D::STENCIL_INDEX8: 2717 m_context->renderbufferStorage(target, internalformat, width, height); 2718 m_renderbufferBinding->setInternalFormat(internalformat); 2719 m_renderbufferBinding->setIsValid(true); 2720 m_renderbufferBinding->setSize(width, height); 2721 cleanupAfterGraphicsCall(false); 2722 break; 2723 case GraphicsContext3D::DEPTH_STENCIL: 2724 if (isDepthStencilSupported()) { 2725 m_context->renderbufferStorage(target, Extensions3D::DEPTH24_STENCIL8, width, height); 2726 cleanupAfterGraphicsCall(false); 2727 } 2728 m_renderbufferBinding->setSize(width, height); 2729 m_renderbufferBinding->setIsValid(isDepthStencilSupported()); 2730 m_renderbufferBinding->setInternalFormat(internalformat); 2731 break; 2732 default: 2733 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2734 } 2735} 2736 2737void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert) 2738{ 2739 if (isContextLost()) 2740 return; 2741 m_context->sampleCoverage(value, invert); 2742 cleanupAfterGraphicsCall(false); 2743} 2744 2745void WebGLRenderingContext::scissor(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) 2746{ 2747 if (isContextLost()) 2748 return; 2749 if (!validateSize(width, height)) 2750 return; 2751 m_context->scissor(x, y, width, height); 2752 cleanupAfterGraphicsCall(false); 2753} 2754 2755void WebGLRenderingContext::shaderSource(WebGLShader* shader, const String& string, ExceptionCode& ec) 2756{ 2757 UNUSED_PARAM(ec); 2758 if (isContextLost() || !validateWebGLObject(shader)) 2759 return; 2760 String stringWithoutComments = StripComments(string).result(); 2761 if (!validateString(stringWithoutComments)) 2762 return; 2763 m_context->shaderSource(objectOrZero(shader), stringWithoutComments); 2764 cleanupAfterGraphicsCall(false); 2765} 2766 2767void WebGLRenderingContext::stencilFunc(GC3Denum func, GC3Dint ref, GC3Duint mask) 2768{ 2769 if (isContextLost()) 2770 return; 2771 if (!validateStencilFunc(func)) 2772 return; 2773 m_stencilFuncRef = ref; 2774 m_stencilFuncRefBack = ref; 2775 m_stencilFuncMask = mask; 2776 m_stencilFuncMaskBack = mask; 2777 m_context->stencilFunc(func, ref, mask); 2778 cleanupAfterGraphicsCall(false); 2779} 2780 2781void WebGLRenderingContext::stencilFuncSeparate(GC3Denum face, GC3Denum func, GC3Dint ref, GC3Duint mask) 2782{ 2783 if (isContextLost()) 2784 return; 2785 if (!validateStencilFunc(func)) 2786 return; 2787 switch (face) { 2788 case GraphicsContext3D::FRONT_AND_BACK: 2789 m_stencilFuncRef = ref; 2790 m_stencilFuncRefBack = ref; 2791 m_stencilFuncMask = mask; 2792 m_stencilFuncMaskBack = mask; 2793 break; 2794 case GraphicsContext3D::FRONT: 2795 m_stencilFuncRef = ref; 2796 m_stencilFuncMask = mask; 2797 break; 2798 case GraphicsContext3D::BACK: 2799 m_stencilFuncRefBack = ref; 2800 m_stencilFuncMaskBack = mask; 2801 break; 2802 default: 2803 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2804 return; 2805 } 2806 m_context->stencilFuncSeparate(face, func, ref, mask); 2807 cleanupAfterGraphicsCall(false); 2808} 2809 2810void WebGLRenderingContext::stencilMask(GC3Duint mask) 2811{ 2812 if (isContextLost()) 2813 return; 2814 m_stencilMask = mask; 2815 m_stencilMaskBack = mask; 2816 m_context->stencilMask(mask); 2817 cleanupAfterGraphicsCall(false); 2818} 2819 2820void WebGLRenderingContext::stencilMaskSeparate(GC3Denum face, GC3Duint mask) 2821{ 2822 if (isContextLost()) 2823 return; 2824 switch (face) { 2825 case GraphicsContext3D::FRONT_AND_BACK: 2826 m_stencilMask = mask; 2827 m_stencilMaskBack = mask; 2828 break; 2829 case GraphicsContext3D::FRONT: 2830 m_stencilMask = mask; 2831 break; 2832 case GraphicsContext3D::BACK: 2833 m_stencilMaskBack = mask; 2834 break; 2835 default: 2836 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 2837 return; 2838 } 2839 m_context->stencilMaskSeparate(face, mask); 2840 cleanupAfterGraphicsCall(false); 2841} 2842 2843void WebGLRenderingContext::stencilOp(GC3Denum fail, GC3Denum zfail, GC3Denum zpass) 2844{ 2845 if (isContextLost()) 2846 return; 2847 m_context->stencilOp(fail, zfail, zpass); 2848 cleanupAfterGraphicsCall(false); 2849} 2850 2851void WebGLRenderingContext::stencilOpSeparate(GC3Denum face, GC3Denum fail, GC3Denum zfail, GC3Denum zpass) 2852{ 2853 if (isContextLost()) 2854 return; 2855 m_context->stencilOpSeparate(face, fail, zfail, zpass); 2856 cleanupAfterGraphicsCall(false); 2857} 2858 2859void WebGLRenderingContext::texImage2DBase(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2860 GC3Dsizei width, GC3Dsizei height, GC3Dint border, 2861 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec) 2862{ 2863 // FIXME: For now we ignore any errors returned 2864 ec = 0; 2865 if (!validateTexFuncParameters(target, level, internalformat, width, height, border, format, type)) 2866 return; 2867 WebGLTexture* tex = validateTextureBinding(target, true); 2868 if (!tex) 2869 return; 2870 if (!isGLES2NPOTStrict()) { 2871 if (level && WebGLTexture::isNPOT(width, height)) { 2872 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2873 return; 2874 } 2875 } 2876 if (!pixels && !isResourceSafe()) { 2877 bool succeed = m_context->texImage2DResourceSafe(target, level, internalformat, width, height, 2878 border, format, type, m_unpackAlignment); 2879 if (!succeed) 2880 return; 2881 } else { 2882 m_context->texImage2D(target, level, internalformat, width, height, 2883 border, format, type, pixels); 2884 } 2885 tex->setLevelInfo(target, level, internalformat, width, height, type); 2886 cleanupAfterGraphicsCall(false); 2887} 2888 2889void WebGLRenderingContext::texImage2DImpl(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2890 GC3Denum format, GC3Denum type, Image* image, 2891 bool flipY, bool premultiplyAlpha, ExceptionCode& ec) 2892{ 2893 ec = 0; 2894 Vector<uint8_t> data; 2895 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) { 2896 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2897 return; 2898 } 2899 if (m_unpackAlignment != 1) 2900 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); 2901 texImage2DBase(target, level, internalformat, image->width(), image->height(), 0, 2902 format, type, data.data(), ec); 2903 if (m_unpackAlignment != 1) 2904 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); 2905} 2906 2907void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2908 GC3Dsizei width, GC3Dsizei height, GC3Dint border, 2909 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec) 2910{ 2911 if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels)) 2912 return; 2913 void* data = pixels ? pixels->baseAddress() : 0; 2914 Vector<uint8_t> tempData; 2915 bool changeUnpackAlignment = false; 2916 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { 2917 if (!m_context->extractTextureData(width, height, format, type, 2918 m_unpackAlignment, 2919 m_unpackFlipY, m_unpackPremultiplyAlpha, 2920 data, 2921 tempData)) 2922 return; 2923 data = tempData.data(); 2924 changeUnpackAlignment = true; 2925 } 2926 if (changeUnpackAlignment) 2927 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); 2928 texImage2DBase(target, level, internalformat, width, height, border, 2929 format, type, data, ec); 2930 if (changeUnpackAlignment) 2931 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); 2932} 2933 2934void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2935 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec) 2936{ 2937 ec = 0; 2938 if (isContextLost()) 2939 return; 2940 Vector<uint8_t> data; 2941 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { 2942 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2943 return; 2944 } 2945 if (m_unpackAlignment != 1) 2946 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); 2947 texImage2DBase(target, level, internalformat, pixels->width(), pixels->height(), 0, 2948 format, type, data.data(), ec); 2949 if (m_unpackAlignment != 1) 2950 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); 2951} 2952 2953void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2954 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec) 2955{ 2956 ec = 0; 2957 if (isContextLost()) 2958 return; 2959 if (!image || !image->cachedImage()) { 2960 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2961 return; 2962 } 2963 checkOrigin(image); 2964 texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(), 2965 m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 2966} 2967 2968void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, 2969 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec) 2970{ 2971 ec = 0; 2972 if (isContextLost()) 2973 return; 2974 if (!canvas || !canvas->buffer()) { 2975 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2976 return; 2977 } 2978 checkOrigin(canvas); 2979 texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(), 2980 m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 2981} 2982 2983PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video) 2984{ 2985 if (!video || !video->videoWidth() || !video->videoHeight()) { 2986 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 2987 return 0; 2988 } 2989 IntSize size(video->videoWidth(), video->videoHeight()); 2990 ImageBuffer* buf = m_videoCache.imageBuffer(size); 2991 if (!buf) { 2992 m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY); 2993 return 0; 2994 } 2995 checkOrigin(video); 2996 IntRect destRect(0, 0, size.width(), size.height()); 2997 // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback. 2998 video->paintCurrentFrameInContext(buf->context(), destRect); 2999 return buf->copyImage(); 3000} 3001 3002void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat, 3003 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec) 3004{ 3005 ec = 0; 3006 if (isContextLost()) 3007 return; 3008 RefPtr<Image> image = videoFrameToImage(video); 3009 if (!video) 3010 return; 3011 texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 3012} 3013 3014void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat) 3015{ 3016 if (isContextLost()) 3017 return; 3018 WebGLTexture* tex = validateTextureBinding(target, false); 3019 if (!tex) 3020 return; 3021 switch (pname) { 3022 case GraphicsContext3D::TEXTURE_MIN_FILTER: 3023 case GraphicsContext3D::TEXTURE_MAG_FILTER: 3024 break; 3025 case GraphicsContext3D::TEXTURE_WRAP_S: 3026 case GraphicsContext3D::TEXTURE_WRAP_T: 3027 if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT) 3028 || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) { 3029 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3030 return; 3031 } 3032 break; 3033 default: 3034 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3035 return; 3036 } 3037 if (isFloat) { 3038 tex->setParameterf(pname, paramf); 3039 m_context->texParameterf(target, pname, paramf); 3040 } else { 3041 tex->setParameteri(pname, parami); 3042 m_context->texParameteri(target, pname, parami); 3043 } 3044 cleanupAfterGraphicsCall(false); 3045} 3046 3047void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param) 3048{ 3049 texParameter(target, pname, param, 0, true); 3050} 3051 3052void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param) 3053{ 3054 texParameter(target, pname, 0, param, false); 3055} 3056 3057void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3058 GC3Dsizei width, GC3Dsizei height, 3059 GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec) 3060{ 3061 // FIXME: For now we ignore any errors returned 3062 ec = 0; 3063 if (isContextLost()) 3064 return; 3065 if (!validateTexFuncFormatAndType(format, type)) 3066 return; 3067 if (!validateTextureBinding(target, true)) 3068 return; 3069 if (!validateSize(xoffset, yoffset) || !validateSize(width, height)) 3070 return; 3071 m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels); 3072 cleanupAfterGraphicsCall(false); 3073} 3074 3075void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3076 GC3Denum format, GC3Denum type, 3077 Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec) 3078{ 3079 ec = 0; 3080 if (isContextLost()) 3081 return; 3082 Vector<uint8_t> data; 3083 if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) { 3084 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3085 return; 3086 } 3087 texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(), 3088 format, type, data.data(), ec); 3089} 3090 3091void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3092 GC3Dsizei width, GC3Dsizei height, 3093 GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec) 3094{ 3095 if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels)) 3096 return; 3097 void* data = pixels ? pixels->baseAddress() : 0; 3098 Vector<uint8_t> tempData; 3099 bool changeUnpackAlignment = false; 3100 if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) { 3101 if (!m_context->extractTextureData(width, height, format, type, 3102 m_unpackAlignment, 3103 m_unpackFlipY, m_unpackPremultiplyAlpha, 3104 data, 3105 tempData)) 3106 return; 3107 data = tempData.data(); 3108 changeUnpackAlignment = true; 3109 } 3110 if (changeUnpackAlignment) 3111 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1); 3112 texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec); 3113 if (changeUnpackAlignment) 3114 m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment); 3115} 3116 3117void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3118 GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec) 3119{ 3120 ec = 0; 3121 if (isContextLost()) 3122 return; 3123 Vector<uint8_t> data; 3124 if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) { 3125 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3126 return; 3127 } 3128 texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(), 3129 format, type, data.data(), ec); 3130} 3131 3132void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3133 GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec) 3134{ 3135 ec = 0; 3136 if (isContextLost()) 3137 return; 3138 if (!image || !image->cachedImage()) { 3139 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3140 return; 3141 } 3142 checkOrigin(image); 3143 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(), 3144 m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 3145} 3146 3147void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3148 GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec) 3149{ 3150 ec = 0; 3151 if (isContextLost()) 3152 return; 3153 if (!canvas || !canvas->buffer()) { 3154 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3155 return; 3156 } 3157 checkOrigin(canvas); 3158 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(), 3159 m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 3160} 3161 3162void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset, 3163 GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec) 3164{ 3165 ec = 0; 3166 if (isContextLost()) 3167 return; 3168 RefPtr<Image> image = videoFrameToImage(video); 3169 if (!video) 3170 return; 3171 texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec); 3172} 3173 3174void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec) 3175{ 3176 UNUSED_PARAM(ec); 3177 if (isContextLost() || !location) 3178 return; 3179 3180 if (location->program() != m_currentProgram) { 3181 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3182 return; 3183 } 3184 3185 m_context->uniform1f(location->location(), x); 3186 cleanupAfterGraphicsCall(false); 3187} 3188 3189void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) 3190{ 3191 UNUSED_PARAM(ec); 3192 if (isContextLost() || !validateUniformParameters(location, v, 1)) 3193 return; 3194 3195 m_context->uniform1fv(location->location(), v->data(), v->length()); 3196 cleanupAfterGraphicsCall(false); 3197} 3198 3199void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3200{ 3201 UNUSED_PARAM(ec); 3202 if (isContextLost() || !validateUniformParameters(location, v, size, 1)) 3203 return; 3204 3205 m_context->uniform1fv(location->location(), v, size); 3206 cleanupAfterGraphicsCall(false); 3207} 3208 3209void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec) 3210{ 3211 UNUSED_PARAM(ec); 3212 if (isContextLost() || !location) 3213 return; 3214 3215 if (location->program() != m_currentProgram) { 3216 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3217 return; 3218 } 3219 3220 m_context->uniform1i(location->location(), x); 3221 cleanupAfterGraphicsCall(false); 3222} 3223 3224void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) 3225{ 3226 UNUSED_PARAM(ec); 3227 if (isContextLost() || !validateUniformParameters(location, v, 1)) 3228 return; 3229 3230 m_context->uniform1iv(location->location(), v->data(), v->length()); 3231 cleanupAfterGraphicsCall(false); 3232} 3233 3234void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) 3235{ 3236 UNUSED_PARAM(ec); 3237 if (isContextLost() || !validateUniformParameters(location, v, size, 1)) 3238 return; 3239 3240 m_context->uniform1iv(location->location(), v, size); 3241 cleanupAfterGraphicsCall(false); 3242} 3243 3244void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec) 3245{ 3246 UNUSED_PARAM(ec); 3247 if (isContextLost() || !location) 3248 return; 3249 3250 if (location->program() != m_currentProgram) { 3251 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3252 return; 3253 } 3254 3255 m_context->uniform2f(location->location(), x, y); 3256 cleanupAfterGraphicsCall(false); 3257} 3258 3259void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) 3260{ 3261 UNUSED_PARAM(ec); 3262 if (isContextLost() || !validateUniformParameters(location, v, 2)) 3263 return; 3264 3265 m_context->uniform2fv(location->location(), v->data(), v->length() / 2); 3266 cleanupAfterGraphicsCall(false); 3267} 3268 3269void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3270{ 3271 UNUSED_PARAM(ec); 3272 if (isContextLost() || !validateUniformParameters(location, v, size, 2)) 3273 return; 3274 3275 m_context->uniform2fv(location->location(), v, size / 2); 3276 cleanupAfterGraphicsCall(false); 3277} 3278 3279void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec) 3280{ 3281 UNUSED_PARAM(ec); 3282 if (isContextLost() || !location) 3283 return; 3284 3285 if (location->program() != m_currentProgram) { 3286 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3287 return; 3288 } 3289 3290 m_context->uniform2i(location->location(), x, y); 3291 cleanupAfterGraphicsCall(false); 3292} 3293 3294void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) 3295{ 3296 UNUSED_PARAM(ec); 3297 if (isContextLost() || !validateUniformParameters(location, v, 2)) 3298 return; 3299 3300 m_context->uniform2iv(location->location(), v->data(), v->length() / 2); 3301 cleanupAfterGraphicsCall(false); 3302} 3303 3304void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) 3305{ 3306 UNUSED_PARAM(ec); 3307 if (isContextLost() || !validateUniformParameters(location, v, size, 2)) 3308 return; 3309 3310 m_context->uniform2iv(location->location(), v, size / 2); 3311 cleanupAfterGraphicsCall(false); 3312} 3313 3314void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec) 3315{ 3316 UNUSED_PARAM(ec); 3317 if (isContextLost() || !location) 3318 return; 3319 3320 if (location->program() != m_currentProgram) { 3321 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3322 return; 3323 } 3324 3325 m_context->uniform3f(location->location(), x, y, z); 3326 cleanupAfterGraphicsCall(false); 3327} 3328 3329void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) 3330{ 3331 UNUSED_PARAM(ec); 3332 if (isContextLost() || !validateUniformParameters(location, v, 3)) 3333 return; 3334 3335 m_context->uniform3fv(location->location(), v->data(), v->length() / 3); 3336 cleanupAfterGraphicsCall(false); 3337} 3338 3339void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3340{ 3341 UNUSED_PARAM(ec); 3342 if (isContextLost() || !validateUniformParameters(location, v, size, 3)) 3343 return; 3344 3345 m_context->uniform3fv(location->location(), v, size / 3); 3346 cleanupAfterGraphicsCall(false); 3347} 3348 3349void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec) 3350{ 3351 UNUSED_PARAM(ec); 3352 if (isContextLost() || !location) 3353 return; 3354 3355 if (location->program() != m_currentProgram) { 3356 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3357 return; 3358 } 3359 3360 m_context->uniform3i(location->location(), x, y, z); 3361 cleanupAfterGraphicsCall(false); 3362} 3363 3364void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) 3365{ 3366 UNUSED_PARAM(ec); 3367 if (isContextLost() || !validateUniformParameters(location, v, 3)) 3368 return; 3369 3370 m_context->uniform3iv(location->location(), v->data(), v->length() / 3); 3371 cleanupAfterGraphicsCall(false); 3372} 3373 3374void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) 3375{ 3376 UNUSED_PARAM(ec); 3377 if (isContextLost() || !validateUniformParameters(location, v, size, 3)) 3378 return; 3379 3380 m_context->uniform3iv(location->location(), v, size / 3); 3381 cleanupAfterGraphicsCall(false); 3382} 3383 3384void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec) 3385{ 3386 UNUSED_PARAM(ec); 3387 if (isContextLost() || !location) 3388 return; 3389 3390 if (location->program() != m_currentProgram) { 3391 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3392 return; 3393 } 3394 3395 m_context->uniform4f(location->location(), x, y, z, w); 3396 cleanupAfterGraphicsCall(false); 3397} 3398 3399void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec) 3400{ 3401 UNUSED_PARAM(ec); 3402 if (isContextLost() || !validateUniformParameters(location, v, 4)) 3403 return; 3404 3405 m_context->uniform4fv(location->location(), v->data(), v->length() / 4); 3406 cleanupAfterGraphicsCall(false); 3407} 3408 3409void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3410{ 3411 UNUSED_PARAM(ec); 3412 if (isContextLost() || !validateUniformParameters(location, v, size, 4)) 3413 return; 3414 3415 m_context->uniform4fv(location->location(), v, size / 4); 3416 cleanupAfterGraphicsCall(false); 3417} 3418 3419void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec) 3420{ 3421 UNUSED_PARAM(ec); 3422 if (isContextLost() || !location) 3423 return; 3424 3425 if (location->program() != m_currentProgram) { 3426 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3427 return; 3428 } 3429 3430 m_context->uniform4i(location->location(), x, y, z, w); 3431 cleanupAfterGraphicsCall(false); 3432} 3433 3434void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec) 3435{ 3436 UNUSED_PARAM(ec); 3437 if (isContextLost() || !validateUniformParameters(location, v, 4)) 3438 return; 3439 3440 m_context->uniform4iv(location->location(), v->data(), v->length() / 4); 3441 cleanupAfterGraphicsCall(false); 3442} 3443 3444void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec) 3445{ 3446 UNUSED_PARAM(ec); 3447 if (isContextLost() || !validateUniformParameters(location, v, size, 4)) 3448 return; 3449 3450 m_context->uniform4iv(location->location(), v, size / 4); 3451 cleanupAfterGraphicsCall(false); 3452} 3453 3454void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) 3455{ 3456 UNUSED_PARAM(ec); 3457 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 4)) 3458 return; 3459 m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4); 3460 cleanupAfterGraphicsCall(false); 3461} 3462 3463void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3464{ 3465 UNUSED_PARAM(ec); 3466 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 4)) 3467 return; 3468 m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4); 3469 cleanupAfterGraphicsCall(false); 3470} 3471 3472void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) 3473{ 3474 UNUSED_PARAM(ec); 3475 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 9)) 3476 return; 3477 m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9); 3478 cleanupAfterGraphicsCall(false); 3479} 3480 3481void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3482{ 3483 UNUSED_PARAM(ec); 3484 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 9)) 3485 return; 3486 m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9); 3487 cleanupAfterGraphicsCall(false); 3488} 3489 3490void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec) 3491{ 3492 UNUSED_PARAM(ec); 3493 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 16)) 3494 return; 3495 m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16); 3496 cleanupAfterGraphicsCall(false); 3497} 3498 3499void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec) 3500{ 3501 UNUSED_PARAM(ec); 3502 if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 16)) 3503 return; 3504 m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16); 3505 cleanupAfterGraphicsCall(false); 3506} 3507 3508void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec) 3509{ 3510 UNUSED_PARAM(ec); 3511 if (isContextLost()) 3512 return; 3513 if (program && program->context() != this) { 3514 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3515 return; 3516 } 3517 if (program && program->object() && !program->getLinkStatus()) { 3518 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3519 cleanupAfterGraphicsCall(false); 3520 return; 3521 } 3522 if (m_currentProgram != program) { 3523 if (m_currentProgram) 3524 m_currentProgram->onDetached(); 3525 m_currentProgram = program; 3526 m_context->useProgram(objectOrZero(program)); 3527 if (program && program->object()) 3528 program->onAttached(); 3529 } 3530 cleanupAfterGraphicsCall(false); 3531} 3532 3533void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec) 3534{ 3535 UNUSED_PARAM(ec); 3536 if (isContextLost() || !validateWebGLObject(program)) 3537 return; 3538 m_context->validateProgram(objectOrZero(program)); 3539 cleanupAfterGraphicsCall(false); 3540} 3541 3542void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0) 3543{ 3544 vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f); 3545} 3546 3547void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v) 3548{ 3549 vertexAttribfvImpl(index, v, 1); 3550} 3551 3552void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) 3553{ 3554 vertexAttribfvImpl(index, v, size, 1); 3555} 3556 3557void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1) 3558{ 3559 vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f); 3560} 3561 3562void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v) 3563{ 3564 vertexAttribfvImpl(index, v, 2); 3565} 3566 3567void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) 3568{ 3569 vertexAttribfvImpl(index, v, size, 2); 3570} 3571 3572void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2) 3573{ 3574 vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f); 3575} 3576 3577void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v) 3578{ 3579 vertexAttribfvImpl(index, v, 3); 3580} 3581 3582void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) 3583{ 3584 vertexAttribfvImpl(index, v, size, 3); 3585} 3586 3587void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) 3588{ 3589 vertexAttribfImpl(index, 4, v0, v1, v2, v3); 3590} 3591 3592void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v) 3593{ 3594 vertexAttribfvImpl(index, v, 4); 3595} 3596 3597void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size) 3598{ 3599 vertexAttribfvImpl(index, v, size, 4); 3600} 3601 3602void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, ExceptionCode& ec) 3603{ 3604 UNUSED_PARAM(ec); 3605 if (isContextLost()) 3606 return; 3607 switch (type) { 3608 case GraphicsContext3D::BYTE: 3609 case GraphicsContext3D::UNSIGNED_BYTE: 3610 case GraphicsContext3D::SHORT: 3611 case GraphicsContext3D::UNSIGNED_SHORT: 3612 case GraphicsContext3D::FLOAT: 3613 break; 3614 default: 3615 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3616 return; 3617 } 3618 if (index >= m_maxVertexAttribs) { 3619 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3620 return; 3621 } 3622 if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) { 3623 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 3624 return; 3625 } 3626 if (!m_boundArrayBuffer) { 3627 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3628 return; 3629 } 3630 // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride 3631 unsigned int typeSize = sizeInBytes(type); 3632 if (!typeSize) { 3633 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3634 return; 3635 } 3636 if ((stride % typeSize) || (offset % typeSize)) { 3637 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3638 return; 3639 } 3640 GC3Dsizei bytesPerElement = size * typeSize; 3641 3642 if (index >= m_vertexAttribState.size()) 3643 m_vertexAttribState.resize(index + 1); 3644 3645 GC3Dsizei validatedStride = stride ? stride : bytesPerElement; 3646 3647 m_vertexAttribState[index].bufferBinding = m_boundArrayBuffer; 3648 m_vertexAttribState[index].bytesPerElement = bytesPerElement; 3649 m_vertexAttribState[index].size = size; 3650 m_vertexAttribState[index].type = type; 3651 m_vertexAttribState[index].normalized = normalized; 3652 m_vertexAttribState[index].stride = validatedStride; 3653 m_vertexAttribState[index].originalStride = stride; 3654 m_vertexAttribState[index].offset = offset; 3655 m_context->vertexAttribPointer(index, size, type, normalized, stride, offset); 3656 cleanupAfterGraphicsCall(false); 3657} 3658 3659void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height) 3660{ 3661 if (isContextLost()) 3662 return; 3663 if (isnan(x)) 3664 x = 0; 3665 if (isnan(y)) 3666 y = 0; 3667 if (isnan(width)) 3668 width = 100; 3669 if (isnan(height)) 3670 height = 100; 3671 if (!validateSize(width, height)) 3672 return; 3673 m_context->viewport(x, y, width, height); 3674 cleanupAfterGraphicsCall(false); 3675} 3676 3677void WebGLRenderingContext::forceLostContext() 3678{ 3679 if (isContextLost()) { 3680 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 3681 return; 3682 } 3683 3684 m_restoreTimer.startOneShot(0); 3685} 3686 3687void WebGLRenderingContext::onLostContext() 3688{ 3689 m_contextLost = true; 3690 3691 detachAndRemoveAllObjects(); 3692 3693 // There is no direct way to clear errors from a GL implementation and 3694 // looping until getError() becomes NO_ERROR might cause an infinite loop if 3695 // the driver or context implementation had a bug. So, loop a reasonably 3696 // large number of times to clear any existing errors. 3697 for (int i = 0; i < 100; ++i) { 3698 if (m_context->getError() == GraphicsContext3D::NO_ERROR) 3699 break; 3700 } 3701 m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL); 3702 3703 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, "")); 3704} 3705 3706void WebGLRenderingContext::restoreContext() 3707{ 3708 RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow())); 3709 if (!context) 3710 return; 3711 3712 m_context = context; 3713 m_contextLost = false; 3714 initializeNewContext(); 3715 canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, "")); 3716} 3717 3718void WebGLRenderingContext::removeObject(WebGLObject* object) 3719{ 3720 m_canvasObjects.remove(object); 3721} 3722 3723void WebGLRenderingContext::addObject(WebGLObject* object) 3724{ 3725 ASSERT(!isContextLost()); 3726 removeObject(object); 3727 m_canvasObjects.add(object); 3728} 3729 3730void WebGLRenderingContext::detachAndRemoveAllObjects() 3731{ 3732 HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end(); 3733 for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) 3734 (*it)->detachContext(); 3735 3736 m_canvasObjects.clear(); 3737} 3738 3739WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj) 3740{ 3741 if (!obj) 3742 return 0; 3743 HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end(); 3744 for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { 3745 if ((*it)->isTexture() && (*it)->object() == obj) 3746 return reinterpret_cast<WebGLTexture*>((*it).get()); 3747 } 3748 return 0; 3749} 3750 3751WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj) 3752{ 3753 if (!obj) 3754 return 0; 3755 HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end(); 3756 for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { 3757 if ((*it)->isRenderbuffer() && (*it)->object() == obj) 3758 return reinterpret_cast<WebGLRenderbuffer*>((*it).get()); 3759 } 3760 return 0; 3761} 3762 3763WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj) 3764{ 3765 if (!obj) 3766 return 0; 3767 HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end(); 3768 for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { 3769 if ((*it)->isBuffer() && (*it)->object() == obj) 3770 return reinterpret_cast<WebGLBuffer*>((*it).get()); 3771 } 3772 return 0; 3773} 3774 3775WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj) 3776{ 3777 if (!obj) 3778 return 0; 3779 HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end(); 3780 for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) { 3781 if ((*it)->isShader() && (*it)->object() == obj) 3782 return reinterpret_cast<WebGLShader*>((*it).get()); 3783 } 3784 return 0; 3785} 3786 3787WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname) 3788{ 3789 GC3Dboolean value = 0; 3790 m_context->getBooleanv(pname, &value); 3791 return WebGLGetInfo(static_cast<bool>(value)); 3792} 3793 3794WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname) 3795{ 3796 if (pname != GraphicsContext3D::COLOR_WRITEMASK) { 3797 notImplemented(); 3798 return WebGLGetInfo(0, 0); 3799 } 3800 GC3Dboolean value[4] = {0}; 3801 m_context->getBooleanv(pname, value); 3802 bool boolValue[4]; 3803 for (int ii = 0; ii < 4; ++ii) 3804 boolValue[ii] = static_cast<bool>(value[ii]); 3805 return WebGLGetInfo(boolValue, 4); 3806} 3807 3808WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname) 3809{ 3810 GC3Dfloat value = 0; 3811 m_context->getFloatv(pname, &value); 3812 return WebGLGetInfo(value); 3813} 3814 3815WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname) 3816{ 3817 return getLongParameter(pname); 3818} 3819 3820WebGLGetInfo WebGLRenderingContext::getLongParameter(GC3Denum pname) 3821{ 3822 GC3Dint value = 0; 3823 m_context->getIntegerv(pname, &value); 3824 return WebGLGetInfo(static_cast<long>(value)); 3825} 3826 3827WebGLGetInfo WebGLRenderingContext::getUnsignedLongParameter(GC3Denum pname) 3828{ 3829 GC3Dint value = 0; 3830 m_context->getIntegerv(pname, &value); 3831 GC3Duint uValue = static_cast<GC3Duint>(value); 3832 return WebGLGetInfo(static_cast<unsigned long>(uValue)); 3833} 3834 3835WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname) 3836{ 3837 GC3Dfloat value[4] = {0}; 3838 m_context->getFloatv(pname, value); 3839 unsigned length = 0; 3840 switch (pname) { 3841 case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE: 3842 case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE: 3843 case GraphicsContext3D::DEPTH_RANGE: 3844 length = 2; 3845 break; 3846 case GraphicsContext3D::BLEND_COLOR: 3847 case GraphicsContext3D::COLOR_CLEAR_VALUE: 3848 length = 4; 3849 break; 3850 default: 3851 notImplemented(); 3852 } 3853 return WebGLGetInfo(Float32Array::create(value, length)); 3854} 3855 3856WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname) 3857{ 3858 GC3Dint value[4] = {0}; 3859 m_context->getIntegerv(pname, value); 3860 unsigned length = 0; 3861 switch (pname) { 3862 case GraphicsContext3D::MAX_VIEWPORT_DIMS: 3863 length = 2; 3864 break; 3865 case GraphicsContext3D::SCISSOR_BOX: 3866 case GraphicsContext3D::VIEWPORT: 3867 length = 4; 3868 break; 3869 default: 3870 notImplemented(); 3871 } 3872 return WebGLGetInfo(Int32Array::create(value, length)); 3873} 3874 3875void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw) 3876{ 3877 bool resetActiveUnit = false; 3878 for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) { 3879 if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()) 3880 || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) { 3881 if (ii != m_activeTextureUnit) { 3882 m_context->activeTexture(ii); 3883 resetActiveUnit = true; 3884 } else if (resetActiveUnit) { 3885 m_context->activeTexture(ii); 3886 resetActiveUnit = false; 3887 } 3888 WebGLTexture* tex2D; 3889 WebGLTexture* texCubeMap; 3890 if (prepareToDraw) { 3891 tex2D = m_blackTexture2D.get(); 3892 texCubeMap = m_blackTextureCubeMap.get(); 3893 } else { 3894 tex2D = m_textureUnits[ii].m_texture2DBinding.get(); 3895 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get(); 3896 } 3897 if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture()) 3898 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D)); 3899 if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture()) 3900 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap)); 3901 } 3902 } 3903 if (resetActiveUnit) 3904 m_context->activeTexture(m_activeTextureUnit); 3905} 3906 3907void WebGLRenderingContext::createFallbackBlackTextures1x1() 3908{ 3909 unsigned char black[] = {0, 0, 0, 255}; 3910 m_blackTexture2D = createTexture(); 3911 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object()); 3912 m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1, 3913 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3914 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0); 3915 m_blackTextureCubeMap = createTexture(); 3916 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object()); 3917 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, 3918 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3919 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1, 3920 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3921 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, 3922 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3923 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1, 3924 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3925 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, 3926 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3927 m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1, 3928 0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black); 3929 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0); 3930} 3931 3932bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat, 3933 GC3Denum colorBufferFormat) 3934{ 3935 switch (colorBufferFormat) { 3936 case GraphicsContext3D::ALPHA: 3937 if (texInternalFormat == GraphicsContext3D::ALPHA) 3938 return true; 3939 break; 3940 case GraphicsContext3D::RGB: 3941 if (texInternalFormat == GraphicsContext3D::LUMINANCE 3942 || texInternalFormat == GraphicsContext3D::RGB) 3943 return true; 3944 break; 3945 case GraphicsContext3D::RGBA: 3946 return true; 3947 } 3948 return false; 3949} 3950 3951GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat() 3952{ 3953 if (m_framebufferBinding && m_framebufferBinding->object()) 3954 return m_framebufferBinding->getColorBufferFormat(); 3955 if (m_attributes.alpha) 3956 return GraphicsContext3D::RGBA; 3957 return GraphicsContext3D::RGB; 3958} 3959 3960int WebGLRenderingContext::getBoundFramebufferWidth() 3961{ 3962 if (m_framebufferBinding && m_framebufferBinding->object()) 3963 return m_framebufferBinding->getWidth(); 3964 return m_context->getInternalFramebufferSize().width(); 3965} 3966 3967int WebGLRenderingContext::getBoundFramebufferHeight() 3968{ 3969 if (m_framebufferBinding && m_framebufferBinding->object()) 3970 return m_framebufferBinding->getHeight(); 3971 return m_context->getInternalFramebufferSize().height(); 3972} 3973 3974WebGLTexture* WebGLRenderingContext::validateTextureBinding(GC3Denum target, bool useSixEnumsForCubeMap) 3975{ 3976 WebGLTexture* tex = 0; 3977 switch (target) { 3978 case GraphicsContext3D::TEXTURE_2D: 3979 tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get(); 3980 break; 3981 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: 3982 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: 3983 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: 3984 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: 3985 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: 3986 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: 3987 if (!useSixEnumsForCubeMap) { 3988 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3989 return 0; 3990 } 3991 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); 3992 break; 3993 case GraphicsContext3D::TEXTURE_CUBE_MAP: 3994 if (useSixEnumsForCubeMap) { 3995 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 3996 return 0; 3997 } 3998 tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get(); 3999 break; 4000 default: 4001 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4002 return 0; 4003 } 4004 if (!tex) 4005 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4006 return tex; 4007} 4008 4009bool WebGLRenderingContext::validateSize(GC3Dint x, GC3Dint y) 4010{ 4011 if (x < 0 || y < 0) { 4012 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4013 return false; 4014 } 4015 return true; 4016} 4017 4018bool WebGLRenderingContext::validateString(const String& string) 4019{ 4020 for (size_t i = 0; i < string.length(); ++i) { 4021 if (!validateCharacter(string[i])) { 4022 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4023 return false; 4024 } 4025 } 4026 return true; 4027} 4028 4029bool WebGLRenderingContext::validateTexFuncFormatAndType(GC3Denum format, GC3Denum type) 4030{ 4031 switch (format) { 4032 case GraphicsContext3D::ALPHA: 4033 case GraphicsContext3D::LUMINANCE: 4034 case GraphicsContext3D::LUMINANCE_ALPHA: 4035 case GraphicsContext3D::RGB: 4036 case GraphicsContext3D::RGBA: 4037 break; 4038 default: 4039 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4040 return false; 4041 } 4042 4043 switch (type) { 4044 case GraphicsContext3D::UNSIGNED_BYTE: 4045 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: 4046 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: 4047 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: 4048 break; 4049 case GraphicsContext3D::FLOAT: 4050 if (m_oesTextureFloat) 4051 break; 4052 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4053 return false; 4054 default: 4055 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4056 return false; 4057 } 4058 4059 // Verify that the combination of format and type is supported. 4060 switch (format) { 4061 case GraphicsContext3D::ALPHA: 4062 case GraphicsContext3D::LUMINANCE: 4063 case GraphicsContext3D::LUMINANCE_ALPHA: 4064 if (type != GraphicsContext3D::UNSIGNED_BYTE 4065 && type != GraphicsContext3D::FLOAT) { 4066 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4067 return false; 4068 } 4069 break; 4070 case GraphicsContext3D::RGB: 4071 if (type != GraphicsContext3D::UNSIGNED_BYTE 4072 && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5 4073 && type != GraphicsContext3D::FLOAT) { 4074 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4075 return false; 4076 } 4077 break; 4078 case GraphicsContext3D::RGBA: 4079 if (type != GraphicsContext3D::UNSIGNED_BYTE 4080 && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4 4081 && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1 4082 && type != GraphicsContext3D::FLOAT) { 4083 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4084 return false; 4085 } 4086 break; 4087 default: 4088 ASSERT_NOT_REACHED(); 4089 } 4090 4091 return true; 4092} 4093 4094bool WebGLRenderingContext::validateTexFuncLevel(GC3Denum target, GC3Dint level) 4095{ 4096 if (level < 0) { 4097 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4098 return false; 4099 } 4100 switch (target) { 4101 case GraphicsContext3D::TEXTURE_2D: 4102 if (level > m_maxTextureLevel) { 4103 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4104 return false; 4105 } 4106 break; 4107 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: 4108 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: 4109 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: 4110 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: 4111 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: 4112 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: 4113 if (level > m_maxCubeMapTextureLevel) { 4114 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4115 return false; 4116 } 4117 break; 4118 } 4119 // This function only checks if level is legal, so we return true and don't 4120 // generate INVALID_ENUM if target is illegal. 4121 return true; 4122} 4123 4124bool WebGLRenderingContext::validateTexFuncParameters(GC3Denum target, GC3Dint level, 4125 GC3Denum internalformat, 4126 GC3Dsizei width, GC3Dsizei height, GC3Dint border, 4127 GC3Denum format, GC3Denum type) 4128{ 4129 // We absolutely have to validate the format and type combination. 4130 // The texImage2D entry points taking HTMLImage, etc. will produce 4131 // temporary data based on this combination, so it must be legal. 4132 if (!validateTexFuncFormatAndType(format, type) || !validateTexFuncLevel(target, level)) 4133 return false; 4134 4135 if (width < 0 || height < 0) { 4136 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4137 return false; 4138 } 4139 4140 switch (target) { 4141 case GraphicsContext3D::TEXTURE_2D: 4142 if (width > m_maxTextureSize || height > m_maxTextureSize) { 4143 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4144 return false; 4145 } 4146 break; 4147 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X: 4148 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X: 4149 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y: 4150 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y: 4151 case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z: 4152 case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z: 4153 if (width != height || width > m_maxCubeMapTextureSize) { 4154 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4155 return false; 4156 } 4157 break; 4158 default: 4159 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4160 return false; 4161 } 4162 4163 if (format != internalformat) { 4164 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4165 return false; 4166 } 4167 4168 if (border) { 4169 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4170 return false; 4171 } 4172 4173 return true; 4174} 4175 4176bool WebGLRenderingContext::validateTexFuncData(GC3Dsizei width, GC3Dsizei height, 4177 GC3Denum format, GC3Denum type, 4178 ArrayBufferView* pixels) 4179{ 4180 if (!pixels) 4181 return true; 4182 4183 if (!validateTexFuncFormatAndType(format, type)) 4184 return false; 4185 4186 switch (type) { 4187 case GraphicsContext3D::UNSIGNED_BYTE: 4188 if (!pixels->isUnsignedByteArray()) { 4189 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4190 return false; 4191 } 4192 break; 4193 case GraphicsContext3D::UNSIGNED_SHORT_5_6_5: 4194 case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4: 4195 case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1: 4196 if (!pixels->isUnsignedShortArray()) { 4197 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4198 return false; 4199 } 4200 break; 4201 case GraphicsContext3D::FLOAT: // OES_texture_float 4202 if (!pixels->isFloatArray()) { 4203 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4204 return false; 4205 } 4206 break; 4207 default: 4208 ASSERT_NOT_REACHED(); 4209 } 4210 4211 unsigned int totalBytesRequired; 4212 GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0); 4213 if (error != GraphicsContext3D::NO_ERROR) { 4214 m_context->synthesizeGLError(error); 4215 return false; 4216 } 4217 if (pixels->byteLength() < totalBytesRequired) { 4218 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4219 return false; 4220 } 4221 return true; 4222} 4223 4224bool WebGLRenderingContext::validateDrawMode(GC3Denum mode) 4225{ 4226 switch (mode) { 4227 case GraphicsContext3D::POINTS: 4228 case GraphicsContext3D::LINE_STRIP: 4229 case GraphicsContext3D::LINE_LOOP: 4230 case GraphicsContext3D::LINES: 4231 case GraphicsContext3D::TRIANGLE_STRIP: 4232 case GraphicsContext3D::TRIANGLE_FAN: 4233 case GraphicsContext3D::TRIANGLES: 4234 return true; 4235 default: 4236 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4237 return false; 4238 } 4239} 4240 4241bool WebGLRenderingContext::validateStencilSettings() 4242{ 4243 if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) { 4244 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4245 return false; 4246 } 4247 return true; 4248} 4249 4250bool WebGLRenderingContext::validateStencilFunc(GC3Denum func) 4251{ 4252 switch (func) { 4253 case GraphicsContext3D::NEVER: 4254 case GraphicsContext3D::LESS: 4255 case GraphicsContext3D::LEQUAL: 4256 case GraphicsContext3D::GREATER: 4257 case GraphicsContext3D::GEQUAL: 4258 case GraphicsContext3D::EQUAL: 4259 case GraphicsContext3D::NOTEQUAL: 4260 case GraphicsContext3D::ALWAYS: 4261 return true; 4262 default: 4263 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4264 return false; 4265 } 4266} 4267 4268void WebGLRenderingContext::printWarningToConsole(const String& message) 4269{ 4270 canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel, 4271 message, 0, canvas()->document()->url().string()); 4272} 4273 4274bool WebGLRenderingContext::validateFramebufferFuncParameters(GC3Denum target, GC3Denum attachment) 4275{ 4276 if (target != GraphicsContext3D::FRAMEBUFFER) { 4277 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4278 return false; 4279 } 4280 switch (attachment) { 4281 case GraphicsContext3D::COLOR_ATTACHMENT0: 4282 case GraphicsContext3D::DEPTH_ATTACHMENT: 4283 case GraphicsContext3D::STENCIL_ATTACHMENT: 4284 case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT: 4285 break; 4286 default: 4287 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4288 return false; 4289 } 4290 return true; 4291} 4292 4293bool WebGLRenderingContext::validateBlendEquation(GC3Denum mode) 4294{ 4295 switch (mode) { 4296 case GraphicsContext3D::FUNC_ADD: 4297 case GraphicsContext3D::FUNC_SUBTRACT: 4298 case GraphicsContext3D::FUNC_REVERSE_SUBTRACT: 4299 return true; 4300 default: 4301 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4302 return false; 4303 } 4304} 4305 4306bool WebGLRenderingContext::validateBlendFuncFactors(GC3Denum src, GC3Denum dst) 4307{ 4308 if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) 4309 && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA)) 4310 || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR) 4311 && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) { 4312 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4313 return false; 4314 } 4315 return true; 4316} 4317 4318bool WebGLRenderingContext::validateCapability(GC3Denum cap) 4319{ 4320 switch (cap) { 4321 case GraphicsContext3D::BLEND: 4322 case GraphicsContext3D::CULL_FACE: 4323 case GraphicsContext3D::DEPTH_TEST: 4324 case GraphicsContext3D::DITHER: 4325 case GraphicsContext3D::POLYGON_OFFSET_FILL: 4326 case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE: 4327 case GraphicsContext3D::SAMPLE_COVERAGE: 4328 case GraphicsContext3D::SCISSOR_TEST: 4329 case GraphicsContext3D::STENCIL_TEST: 4330 return true; 4331 default: 4332 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4333 return false; 4334 } 4335} 4336 4337bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize) 4338{ 4339 if (!v) { 4340 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4341 return false; 4342 } 4343 return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize); 4344} 4345 4346bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize) 4347{ 4348 if (!v) { 4349 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4350 return false; 4351 } 4352 return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize); 4353} 4354 4355bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) 4356{ 4357 return validateUniformMatrixParameters(location, false, v, size, requiredMinSize); 4358} 4359 4360bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize) 4361{ 4362 if (!v) { 4363 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4364 return false; 4365 } 4366 return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize); 4367} 4368 4369bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize) 4370{ 4371 if (!location) 4372 return false; 4373 if (location->program() != m_currentProgram) { 4374 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4375 return false; 4376 } 4377 if (!v) { 4378 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4379 return false; 4380 } 4381 if (transpose) { 4382 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4383 return false; 4384 } 4385 if (size < requiredMinSize) { 4386 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4387 return false; 4388 } 4389 return true; 4390} 4391 4392WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(GC3Denum target, GC3Denum usage) 4393{ 4394 WebGLBuffer* buffer = 0; 4395 switch (target) { 4396 case GraphicsContext3D::ELEMENT_ARRAY_BUFFER: 4397 buffer = m_boundElementArrayBuffer.get(); 4398 break; 4399 case GraphicsContext3D::ARRAY_BUFFER: 4400 buffer = m_boundArrayBuffer.get(); 4401 break; 4402 default: 4403 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4404 return 0; 4405 } 4406 if (!buffer) { 4407 m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION); 4408 return 0; 4409 } 4410 switch (usage) { 4411 case GraphicsContext3D::STREAM_DRAW: 4412 case GraphicsContext3D::STATIC_DRAW: 4413 case GraphicsContext3D::DYNAMIC_DRAW: 4414 return buffer; 4415 } 4416 m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM); 4417 return 0; 4418} 4419 4420void WebGLRenderingContext::vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3) 4421{ 4422 if (isContextLost()) 4423 return; 4424 if (index >= m_maxVertexAttribs) { 4425 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4426 return; 4427 } 4428 // In GL, we skip setting vertexAttrib0 values. 4429 if (index || isGLES2Compliant()) { 4430 switch (expectedSize) { 4431 case 1: 4432 m_context->vertexAttrib1f(index, v0); 4433 break; 4434 case 2: 4435 m_context->vertexAttrib2f(index, v0, v1); 4436 break; 4437 case 3: 4438 m_context->vertexAttrib3f(index, v0, v1, v2); 4439 break; 4440 case 4: 4441 m_context->vertexAttrib4f(index, v0, v1, v2, v3); 4442 break; 4443 } 4444 cleanupAfterGraphicsCall(false); 4445 } 4446 if (index >= m_vertexAttribState.size()) 4447 m_vertexAttribState.resize(index + 1); 4448 m_vertexAttribState[index].value[0] = v0; 4449 m_vertexAttribState[index].value[1] = v1; 4450 m_vertexAttribState[index].value[2] = v2; 4451 m_vertexAttribState[index].value[3] = v3; 4452} 4453 4454void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, Float32Array* v, GC3Dsizei expectedSize) 4455{ 4456 if (isContextLost()) 4457 return; 4458 if (!v) { 4459 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4460 return; 4461 } 4462 vertexAttribfvImpl(index, v->data(), v->length(), expectedSize); 4463} 4464 4465void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize) 4466{ 4467 if (isContextLost()) 4468 return; 4469 if (!v) { 4470 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4471 return; 4472 } 4473 if (size < expectedSize) { 4474 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4475 return; 4476 } 4477 if (index >= m_maxVertexAttribs) { 4478 m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE); 4479 return; 4480 } 4481 // In GL, we skip setting vertexAttrib0 values. 4482 if (index || isGLES2Compliant()) { 4483 switch (expectedSize) { 4484 case 1: 4485 m_context->vertexAttrib1fv(index, v); 4486 break; 4487 case 2: 4488 m_context->vertexAttrib2fv(index, v); 4489 break; 4490 case 3: 4491 m_context->vertexAttrib3fv(index, v); 4492 break; 4493 case 4: 4494 m_context->vertexAttrib4fv(index, v); 4495 break; 4496 } 4497 cleanupAfterGraphicsCall(false); 4498 } 4499 if (index >= m_vertexAttribState.size()) 4500 m_vertexAttribState.resize(index + 1); 4501 m_vertexAttribState[index].initValue(); 4502 for (int ii = 0; ii < expectedSize; ++ii) 4503 m_vertexAttribState[index].value[ii] = v[ii]; 4504} 4505 4506void WebGLRenderingContext::initVertexAttrib0() 4507{ 4508 m_vertexAttribState.resize(1); 4509 m_vertexAttrib0Buffer = createBuffer(); 4510 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); 4511 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW); 4512 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0); 4513 m_vertexAttribState[0].bufferBinding = m_vertexAttrib0Buffer; 4514 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0); 4515 m_context->enableVertexAttribArray(0); 4516 m_vertexAttrib0BufferSize = 0; 4517 m_vertexAttrib0BufferValue[0] = 0.0f; 4518 m_vertexAttrib0BufferValue[1] = 0.0f; 4519 m_vertexAttrib0BufferValue[2] = 0.0f; 4520 m_vertexAttrib0BufferValue[3] = 1.0f; 4521} 4522 4523bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex) 4524{ 4525 const VertexAttribState& state = m_vertexAttribState[0]; 4526 if (state.enabled || !m_currentProgram || !m_currentProgram->object() 4527 || !m_currentProgram->isUsingVertexAttrib0()) 4528 return false; 4529 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object()); 4530 GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat); 4531 if (bufferDataSize > m_vertexAttrib0BufferSize 4532 || state.value[0] != m_vertexAttrib0BufferValue[0] 4533 || state.value[1] != m_vertexAttrib0BufferValue[1] 4534 || state.value[2] != m_vertexAttrib0BufferValue[2] 4535 || state.value[3] != m_vertexAttrib0BufferValue[3]) { 4536 OwnArrayPtr<GC3Dfloat> bufferData(new GC3Dfloat[(numVertex + 1) * 4]); 4537 for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) { 4538 bufferData[ii * 4] = state.value[0]; 4539 bufferData[ii * 4 + 1] = state.value[1]; 4540 bufferData[ii * 4 + 2] = state.value[2]; 4541 bufferData[ii * 4 + 3] = state.value[3]; 4542 } 4543 m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, bufferData.get(), GraphicsContext3D::DYNAMIC_DRAW); 4544 m_vertexAttrib0BufferSize = bufferDataSize; 4545 m_vertexAttrib0BufferValue[0] = state.value[0]; 4546 m_vertexAttrib0BufferValue[1] = state.value[1]; 4547 m_vertexAttrib0BufferValue[2] = state.value[2]; 4548 m_vertexAttrib0BufferValue[3] = state.value[3]; 4549 } 4550 m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0); 4551 return true; 4552} 4553 4554void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation() 4555{ 4556 const VertexAttribState& state = m_vertexAttribState[0]; 4557 if (state.bufferBinding != m_vertexAttrib0Buffer) { 4558 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get())); 4559 m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset); 4560 } 4561 m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get())); 4562} 4563 4564int WebGLRenderingContext::getNumberOfExtensions() 4565{ 4566 return (m_oesStandardDerivatives ? 1 : 0) + (m_webkitLoseContext ? 1 : 0) + (m_oesTextureFloat ? 1 : 0); 4567} 4568 4569WebGLExtension* WebGLRenderingContext::getExtensionNumber(int i) 4570{ 4571 if (m_oesStandardDerivatives) { 4572 if (!i) 4573 return m_oesStandardDerivatives.get(); 4574 --i; 4575 } 4576 if (m_webkitLoseContext) { 4577 if (!i) 4578 return m_webkitLoseContext.get(); 4579 --i; 4580 } 4581 if (m_oesTextureFloat) { 4582 if (!i) 4583 return m_oesTextureFloat.get(); 4584 --i; 4585 } 4586 // Similar tests for other extensions would go here. 4587 return 0; 4588} 4589 4590WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity) 4591 : m_buffers(new OwnPtr<ImageBuffer>[capacity]) 4592 , m_capacity(capacity) 4593{ 4594} 4595 4596ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size) 4597{ 4598 int i; 4599 for (i = 0; i < m_capacity; ++i) { 4600 ImageBuffer* buf = m_buffers[i].get(); 4601 if (!buf) 4602 break; 4603 if (buf->size() != size) 4604 continue; 4605 bubbleToFront(i); 4606 return buf; 4607 } 4608 4609 OwnPtr<ImageBuffer> temp = ImageBuffer::create(size); 4610 if (!temp) 4611 return 0; 4612 i = std::min(m_capacity - 1, i); 4613 m_buffers[i] = temp.release(); 4614 4615 ImageBuffer* buf = m_buffers[i].get(); 4616 bubbleToFront(i); 4617 return buf; 4618} 4619 4620void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx) 4621{ 4622 for (int i = idx; i > 0; --i) 4623 m_buffers[i].swap(m_buffers[i-1]); 4624} 4625 4626} // namespace WebCore 4627 4628#endif // ENABLE(3D_CANVAS) 4629