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