Home | History | Annotate | Download | only in canvas
      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 
     74 namespace WebCore {
     75 
     76 const double secondsBetweenRestoreAttempts = 1.0;
     77 
     78 namespace {
     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 
    310 class WebGLStateRestorer {
    311 public:
    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 
    324 private:
    325     WebGLRenderingContext* m_context;
    326     bool m_changed;
    327 };
    328 
    329 void 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 
    350 class WebGLRenderingContextLostCallback : public GraphicsContext3D::ContextLostCallback {
    351 public:
    352     WebGLRenderingContextLostCallback(WebGLRenderingContext* cb) : m_contextLostCallback(cb) {}
    353     virtual void onContextLost() { m_contextLostCallback->forceLostContext(); }
    354     virtual ~WebGLRenderingContextLostCallback() {}
    355 private:
    356     WebGLRenderingContext* m_contextLostCallback;
    357 };
    358 
    359 PassOwnPtr<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 
    380 WebGLRenderingContext::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 
    394 void 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 
    456 void WebGLRenderingContext::setupFlags()
    457 {
    458     ASSERT(m_context);
    459 
    460     m_isGLES2Compliant = m_context->isGLES2Compliant();
    461     m_isErrorGeneratedOnOutOfBoundsAccesses = m_context->getExtensions()->isEnabled("GL_CHROMIUM_strict_attribs");
    462     m_isResourceSafe = m_context->getExtensions()->isEnabled("GL_CHROMIUM_resource_safe");
    463     if (m_isGLES2Compliant) {
    464         m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_OES_texture_npot");
    465         m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_OES_packed_depth_stencil");
    466     } else {
    467         m_isGLES2NPOTStrict = !m_context->getExtensions()->isEnabled("GL_ARB_texture_non_power_of_two");
    468         m_isDepthStencilSupported = m_context->getExtensions()->isEnabled("GL_EXT_packed_depth_stencil");
    469     }
    470 }
    471 
    472 WebGLRenderingContext::~WebGLRenderingContext()
    473 {
    474     detachAndRemoveAllObjects();
    475     m_context->setContextLostCallback(0);
    476     if (m_webkitLoseContext)
    477         m_webkitLoseContext->contextDestroyed();
    478 }
    479 
    480 void 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 
    500 bool WebGLRenderingContext::clearIfComposited(GC3Dbitfield mask)
    501 {
    502     if (isContextLost())
    503         return false;
    504 
    505     if (!m_context->layerComposited() || m_layerCleared
    506         || m_attributes.preserveDrawingBuffer || m_framebufferBinding)
    507         return false;
    508 
    509     RefPtr<WebGLContextAttributes> contextAttributes = getContextAttributes();
    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 
    548 void WebGLRenderingContext::markLayerComposited()
    549 {
    550     m_context->markLayerComposited();
    551 }
    552 
    553 void 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 
    569 PassRefPtr<ImageData> WebGLRenderingContext::paintRenderingResultsToImageData()
    570 {
    571     clearIfComposited();
    572     return m_context->paintRenderingResultsToImageData();
    573 }
    574 
    575 bool WebGLRenderingContext::paintsIntoCanvasBuffer() const
    576 {
    577     return m_context->paintsIntoCanvasBuffer();
    578 }
    579 
    580 void 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 
    596 unsigned 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 
    618 void 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 
    632 void 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 
    646 void 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 
    657 bool 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 
    672 void 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 
    699 void 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 
    718 void 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 
    737 void 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 
    776 void 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 
    784 void WebGLRenderingContext::blendEquation(GC3Denum mode)
    785 {
    786     if (isContextLost() || !validateBlendEquation(mode))
    787         return;
    788     m_context->blendEquation(mode);
    789     cleanupAfterGraphicsCall(false);
    790 }
    791 
    792 void 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 
    801 void 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 
    809 void 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 
    817 void 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 
    840 void 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 
    863 void 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 
    886 void 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 
    911 void 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 
    936 GC3Denum 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 
    953 void 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 
    970 void 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 
    990 void WebGLRenderingContext::clearDepth(GC3Dfloat depth)
    991 {
    992     if (isContextLost())
    993         return;
    994     m_clearDepth = depth;
    995     m_context->clearDepth(depth);
    996     cleanupAfterGraphicsCall(false);
    997 }
    998 
    999 void WebGLRenderingContext::clearStencil(GC3Dint s)
   1000 {
   1001     if (isContextLost())
   1002         return;
   1003     m_clearStencil = s;
   1004     m_context->clearStencil(s);
   1005     cleanupAfterGraphicsCall(false);
   1006 }
   1007 
   1008 void 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 
   1020 void 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 
   1029 void 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 
   1071 void 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 
   1129 PassRefPtr<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 
   1138 PassRefPtr<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 
   1147 PassRefPtr<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 
   1156 PassRefPtr<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 
   1165 PassRefPtr<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 
   1174 PassRefPtr<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 
   1189 void WebGLRenderingContext::cullFace(GC3Denum mode)
   1190 {
   1191     if (isContextLost())
   1192         return;
   1193     m_context->cullFace(mode);
   1194     cleanupAfterGraphicsCall(false);
   1195 }
   1196 
   1197 bool 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 
   1210 void 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 
   1234 void 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 
   1245 void 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 
   1252 void 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 
   1262 void WebGLRenderingContext::deleteShader(WebGLShader* shader)
   1263 {
   1264     deleteObject(shader);
   1265 }
   1266 
   1267 void 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 
   1281 void WebGLRenderingContext::depthFunc(GC3Denum func)
   1282 {
   1283     if (isContextLost())
   1284         return;
   1285     m_context->depthFunc(func);
   1286     cleanupAfterGraphicsCall(false);
   1287 }
   1288 
   1289 void WebGLRenderingContext::depthMask(GC3Dboolean flag)
   1290 {
   1291     if (isContextLost())
   1292         return;
   1293     m_context->depthMask(flag);
   1294     cleanupAfterGraphicsCall(false);
   1295 }
   1296 
   1297 void 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 
   1309 void 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 
   1323 void 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 
   1333 void 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 
   1352 bool 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 
   1381 bool 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 
   1434 bool 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 
   1478 bool 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 
   1522 bool 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 
   1535 void 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 
   1589 void 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 
   1665 void 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 
   1675 void 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 
   1692 void WebGLRenderingContext::finish()
   1693 {
   1694     if (isContextLost())
   1695         return;
   1696     m_context->finish();
   1697     cleanupAfterGraphicsCall(false);
   1698 }
   1699 
   1700 void WebGLRenderingContext::flush()
   1701 {
   1702     if (isContextLost())
   1703         return;
   1704     m_context->flush();
   1705     cleanupAfterGraphicsCall(false);
   1706 }
   1707 
   1708 void 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 
   1779 void 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 
   1804 void WebGLRenderingContext::frontFace(GC3Denum mode)
   1805 {
   1806     if (isContextLost())
   1807         return;
   1808     m_context->frontFace(mode);
   1809     cleanupAfterGraphicsCall(false);
   1810 }
   1811 
   1812 void 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 
   1841 PassRefPtr<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 
   1852 PassRefPtr<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 
   1866 bool 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 
   1893 GC3Dint 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 
   1902 WebGLGetInfo 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 
   1925 PassRefPtr<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 
   1934 GC3Denum WebGLRenderingContext::getError()
   1935 {
   1936     return m_context->getError();
   1937 }
   1938 
   1939 WebGLExtension* 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 
   1977 WebGLGetInfo 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 
   2025 WebGLGetInfo 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 
   2228 WebGLGetInfo 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 
   2255 String 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 
   2266 WebGLGetInfo 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 
   2333 WebGLGetInfo 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 
   2355 String 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 
   2366 String 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 
   2376 Vector<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 
   2389 WebGLGetInfo 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 
   2412 WebGLGetInfo 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 
   2556 PassRefPtr<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 
   2570 WebGLGetInfo 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 
   2606 GC3Dsizeiptr 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 
   2615 void 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 
   2637 GC3Dboolean 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 
   2648 bool 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 
   2661 GC3Dboolean WebGLRenderingContext::isEnabled(GC3Denum cap)
   2662 {
   2663     if (!validateCapability(cap) || isContextLost())
   2664         return 0;
   2665     return m_context->isEnabled(cap);
   2666 }
   2667 
   2668 GC3Dboolean 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 
   2679 GC3Dboolean WebGLRenderingContext::isProgram(WebGLProgram* program)
   2680 {
   2681     if (!program || isContextLost())
   2682         return 0;
   2683 
   2684     return m_context->isProgram(program->object());
   2685 }
   2686 
   2687 GC3Dboolean 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 
   2698 GC3Dboolean WebGLRenderingContext::isShader(WebGLShader* shader)
   2699 {
   2700     if (!shader || isContextLost())
   2701         return 0;
   2702 
   2703     return m_context->isShader(shader->object());
   2704 }
   2705 
   2706 GC3Dboolean 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 
   2717 void WebGLRenderingContext::lineWidth(GC3Dfloat width)
   2718 {
   2719     if (isContextLost())
   2720         return;
   2721     m_context->lineWidth(width);
   2722     cleanupAfterGraphicsCall(false);
   2723 }
   2724 
   2725 void 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 
   2748 void 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 
   2787 void WebGLRenderingContext::polygonOffset(GC3Dfloat factor, GC3Dfloat units)
   2788 {
   2789     if (isContextLost())
   2790         return;
   2791     m_context->polygonOffset(factor, units);
   2792     cleanupAfterGraphicsCall(false);
   2793 }
   2794 
   2795 void 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 
   2872 void WebGLRenderingContext::releaseShaderCompiler()
   2873 {
   2874     if (isContextLost())
   2875         return;
   2876     m_context->releaseShaderCompiler();
   2877     cleanupAfterGraphicsCall(false);
   2878 }
   2879 
   2880 void 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 
   2920 void WebGLRenderingContext::sampleCoverage(GC3Dfloat value, GC3Dboolean invert)
   2921 {
   2922     if (isContextLost())
   2923         return;
   2924     m_context->sampleCoverage(value, invert);
   2925     cleanupAfterGraphicsCall(false);
   2926 }
   2927 
   2928 void 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 
   2938 void 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 
   2951 void 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 
   2965 void 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 
   2994 void 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 
   3004 void 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 
   3027 void 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 
   3035 void 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 
   3043 void 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 
   3073 void 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 
   3091 void 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 
   3118 void 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 
   3137 void 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 (!validateHTMLImageElement(image))
   3144         return;
   3145     checkOrigin(image);
   3146     texImage2DImpl(target, level, internalformat, format, type, image->cachedImage()->image(),
   3147                    m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3148 }
   3149 
   3150 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
   3151                                        GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
   3152 {
   3153     ec = 0;
   3154     if (isContextLost())
   3155         return;
   3156     if (!canvas || !canvas->buffer()) {
   3157         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3158         return;
   3159     }
   3160     checkOrigin(canvas);
   3161     RefPtr<ImageData> imageData = canvas->getImageData();
   3162     if (imageData)
   3163         texImage2D(target, level, internalformat, format, type, imageData.get(), ec);
   3164     else
   3165         texImage2DImpl(target, level, internalformat, format, type, canvas->copiedImage(),
   3166                        m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3167 }
   3168 
   3169 #if ENABLE(VIDEO)
   3170 PassRefPtr<Image> WebGLRenderingContext::videoFrameToImage(HTMLVideoElement* video)
   3171 {
   3172     if (!video || !video->videoWidth() || !video->videoHeight()) {
   3173         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3174         return 0;
   3175     }
   3176     IntSize size(video->videoWidth(), video->videoHeight());
   3177     ImageBuffer* buf = m_videoCache.imageBuffer(size);
   3178     if (!buf) {
   3179         m_context->synthesizeGLError(GraphicsContext3D::OUT_OF_MEMORY);
   3180         return 0;
   3181     }
   3182     checkOrigin(video);
   3183     IntRect destRect(0, 0, size.width(), size.height());
   3184     // FIXME: Turn this into a GPU-GPU texture copy instead of CPU readback.
   3185     video->paintCurrentFrameInContext(buf->context(), destRect);
   3186     return buf->copyImage();
   3187 }
   3188 
   3189 void WebGLRenderingContext::texImage2D(GC3Denum target, GC3Dint level, GC3Denum internalformat,
   3190                                        GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
   3191 {
   3192     ec = 0;
   3193     if (isContextLost())
   3194         return;
   3195     RefPtr<Image> image = videoFrameToImage(video);
   3196     if (!video)
   3197         return;
   3198     texImage2DImpl(target, level, internalformat, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3199 }
   3200 #endif
   3201 
   3202 void WebGLRenderingContext::texParameter(GC3Denum target, GC3Denum pname, GC3Dfloat paramf, GC3Dint parami, bool isFloat)
   3203 {
   3204     if (isContextLost())
   3205         return;
   3206     WebGLTexture* tex = validateTextureBinding(target, false);
   3207     if (!tex)
   3208         return;
   3209     switch (pname) {
   3210     case GraphicsContext3D::TEXTURE_MIN_FILTER:
   3211     case GraphicsContext3D::TEXTURE_MAG_FILTER:
   3212         break;
   3213     case GraphicsContext3D::TEXTURE_WRAP_S:
   3214     case GraphicsContext3D::TEXTURE_WRAP_T:
   3215         if ((isFloat && paramf != GraphicsContext3D::CLAMP_TO_EDGE && paramf != GraphicsContext3D::MIRRORED_REPEAT && paramf != GraphicsContext3D::REPEAT)
   3216             || (!isFloat && parami != GraphicsContext3D::CLAMP_TO_EDGE && parami != GraphicsContext3D::MIRRORED_REPEAT && parami != GraphicsContext3D::REPEAT)) {
   3217             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   3218             return;
   3219         }
   3220         break;
   3221     default:
   3222         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   3223         return;
   3224     }
   3225     if (isFloat) {
   3226         tex->setParameterf(pname, paramf);
   3227         m_context->texParameterf(target, pname, paramf);
   3228     } else {
   3229         tex->setParameteri(pname, parami);
   3230         m_context->texParameteri(target, pname, parami);
   3231     }
   3232     cleanupAfterGraphicsCall(false);
   3233 }
   3234 
   3235 void WebGLRenderingContext::texParameterf(GC3Denum target, GC3Denum pname, GC3Dfloat param)
   3236 {
   3237     texParameter(target, pname, param, 0, true);
   3238 }
   3239 
   3240 void WebGLRenderingContext::texParameteri(GC3Denum target, GC3Denum pname, GC3Dint param)
   3241 {
   3242     texParameter(target, pname, 0, param, false);
   3243 }
   3244 
   3245 void WebGLRenderingContext::texSubImage2DBase(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3246                                               GC3Dsizei width, GC3Dsizei height,
   3247                                               GC3Denum format, GC3Denum type, void* pixels, ExceptionCode& ec)
   3248 {
   3249     // FIXME: For now we ignore any errors returned
   3250     ec = 0;
   3251     if (isContextLost())
   3252         return;
   3253     if (!validateTexFuncParameters(target, level, format, width, height, 0, format, type))
   3254         return;
   3255     if (!validateSize(xoffset, yoffset))
   3256         return;
   3257     WebGLTexture* tex = validateTextureBinding(target, true);
   3258     if (!tex)
   3259         return;
   3260     if (xoffset + width > tex->getWidth(target, level) || yoffset + height > tex->getHeight(target, level)) {
   3261         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3262         return;
   3263     }
   3264     if (tex->getInternalFormat(target, level) != format || tex->getType(target, level) != type) {
   3265         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3266         return;
   3267     }
   3268     m_context->texSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
   3269     cleanupAfterGraphicsCall(false);
   3270 }
   3271 
   3272 void WebGLRenderingContext::texSubImage2DImpl(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3273                                               GC3Denum format, GC3Denum type,
   3274                                               Image* image, bool flipY, bool premultiplyAlpha, ExceptionCode& ec)
   3275 {
   3276     ec = 0;
   3277     if (isContextLost())
   3278         return;
   3279     Vector<uint8_t> data;
   3280     if (!m_context->extractImageData(image, format, type, flipY, premultiplyAlpha, m_unpackColorspaceConversion == GraphicsContext3D::NONE, data)) {
   3281         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3282         return;
   3283     }
   3284     texSubImage2DBase(target, level, xoffset, yoffset, image->width(), image->height(),
   3285                       format, type, data.data(), ec);
   3286 }
   3287 
   3288 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3289                                           GC3Dsizei width, GC3Dsizei height,
   3290                                           GC3Denum format, GC3Denum type, ArrayBufferView* pixels, ExceptionCode& ec)
   3291 {
   3292     if (isContextLost() || !validateTexFuncData(width, height, format, type, pixels))
   3293         return;
   3294     void* data = pixels ? pixels->baseAddress() : 0;
   3295     Vector<uint8_t> tempData;
   3296     bool changeUnpackAlignment = false;
   3297     if (data && (m_unpackFlipY || m_unpackPremultiplyAlpha)) {
   3298         if (!m_context->extractTextureData(width, height, format, type,
   3299                                            m_unpackAlignment,
   3300                                            m_unpackFlipY, m_unpackPremultiplyAlpha,
   3301                                            data,
   3302                                            tempData))
   3303             return;
   3304         data = tempData.data();
   3305         changeUnpackAlignment = true;
   3306     }
   3307     if (changeUnpackAlignment)
   3308         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, 1);
   3309     texSubImage2DBase(target, level, xoffset, yoffset, width, height, format, type, data, ec);
   3310     if (changeUnpackAlignment)
   3311         m_context->pixelStorei(GraphicsContext3D::UNPACK_ALIGNMENT, m_unpackAlignment);
   3312 }
   3313 
   3314 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3315                                           GC3Denum format, GC3Denum type, ImageData* pixels, ExceptionCode& ec)
   3316 {
   3317     ec = 0;
   3318     if (isContextLost())
   3319         return;
   3320     Vector<uint8_t> data;
   3321     if (!m_context->extractImageData(pixels, format, type, m_unpackFlipY, m_unpackPremultiplyAlpha, data)) {
   3322         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3323         return;
   3324     }
   3325     texSubImage2DBase(target, level, xoffset, yoffset, pixels->width(), pixels->height(),
   3326                       format, type, data.data(), ec);
   3327 }
   3328 
   3329 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3330                                           GC3Denum format, GC3Denum type, HTMLImageElement* image, ExceptionCode& ec)
   3331 {
   3332     ec = 0;
   3333     if (isContextLost())
   3334         return;
   3335     if (!validateHTMLImageElement(image))
   3336         return;
   3337     checkOrigin(image);
   3338     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image->cachedImage()->image(),
   3339                       m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3340 }
   3341 
   3342 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3343                                           GC3Denum format, GC3Denum type, HTMLCanvasElement* canvas, ExceptionCode& ec)
   3344 {
   3345     ec = 0;
   3346     if (isContextLost())
   3347         return;
   3348     if (!canvas || !canvas->buffer()) {
   3349         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3350         return;
   3351     }
   3352     checkOrigin(canvas);
   3353     RefPtr<ImageData> imageData = canvas->getImageData();
   3354     if (imageData)
   3355         texSubImage2D(target, level, xoffset, yoffset, format, type, imageData.get(), ec);
   3356     else
   3357         texSubImage2DImpl(target, level, xoffset, yoffset, format, type, canvas->copiedImage(),
   3358                           m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3359 }
   3360 
   3361 #if ENABLE(VIDEO)
   3362 void WebGLRenderingContext::texSubImage2D(GC3Denum target, GC3Dint level, GC3Dint xoffset, GC3Dint yoffset,
   3363                                           GC3Denum format, GC3Denum type, HTMLVideoElement* video, ExceptionCode& ec)
   3364 {
   3365     ec = 0;
   3366     if (isContextLost())
   3367         return;
   3368     RefPtr<Image> image = videoFrameToImage(video);
   3369     if (!video)
   3370         return;
   3371     texSubImage2DImpl(target, level, xoffset, yoffset, format, type, image.get(), m_unpackFlipY, m_unpackPremultiplyAlpha, ec);
   3372 }
   3373 #endif
   3374 
   3375 void WebGLRenderingContext::uniform1f(const WebGLUniformLocation* location, GC3Dfloat x, ExceptionCode& ec)
   3376 {
   3377     UNUSED_PARAM(ec);
   3378     if (isContextLost() || !location)
   3379         return;
   3380 
   3381     if (location->program() != m_currentProgram) {
   3382         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3383         return;
   3384     }
   3385 
   3386     m_context->uniform1f(location->location(), x);
   3387     cleanupAfterGraphicsCall(false);
   3388 }
   3389 
   3390 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
   3391 {
   3392     UNUSED_PARAM(ec);
   3393     if (isContextLost() || !validateUniformParameters(location, v, 1))
   3394         return;
   3395 
   3396     m_context->uniform1fv(location->location(), v->data(), v->length());
   3397     cleanupAfterGraphicsCall(false);
   3398 }
   3399 
   3400 void WebGLRenderingContext::uniform1fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3401 {
   3402     UNUSED_PARAM(ec);
   3403     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
   3404         return;
   3405 
   3406     m_context->uniform1fv(location->location(), v, size);
   3407     cleanupAfterGraphicsCall(false);
   3408 }
   3409 
   3410 void WebGLRenderingContext::uniform1i(const WebGLUniformLocation* location, GC3Dint x, ExceptionCode& ec)
   3411 {
   3412     UNUSED_PARAM(ec);
   3413     if (isContextLost() || !location)
   3414         return;
   3415 
   3416     if (location->program() != m_currentProgram) {
   3417         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3418         return;
   3419     }
   3420 
   3421     m_context->uniform1i(location->location(), x);
   3422     cleanupAfterGraphicsCall(false);
   3423 }
   3424 
   3425 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
   3426 {
   3427     UNUSED_PARAM(ec);
   3428     if (isContextLost() || !validateUniformParameters(location, v, 1))
   3429         return;
   3430 
   3431     m_context->uniform1iv(location->location(), v->data(), v->length());
   3432     cleanupAfterGraphicsCall(false);
   3433 }
   3434 
   3435 void WebGLRenderingContext::uniform1iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
   3436 {
   3437     UNUSED_PARAM(ec);
   3438     if (isContextLost() || !validateUniformParameters(location, v, size, 1))
   3439         return;
   3440 
   3441     m_context->uniform1iv(location->location(), v, size);
   3442     cleanupAfterGraphicsCall(false);
   3443 }
   3444 
   3445 void WebGLRenderingContext::uniform2f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, ExceptionCode& ec)
   3446 {
   3447     UNUSED_PARAM(ec);
   3448     if (isContextLost() || !location)
   3449         return;
   3450 
   3451     if (location->program() != m_currentProgram) {
   3452         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3453         return;
   3454     }
   3455 
   3456     m_context->uniform2f(location->location(), x, y);
   3457     cleanupAfterGraphicsCall(false);
   3458 }
   3459 
   3460 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
   3461 {
   3462     UNUSED_PARAM(ec);
   3463     if (isContextLost() || !validateUniformParameters(location, v, 2))
   3464         return;
   3465 
   3466     m_context->uniform2fv(location->location(), v->data(), v->length() / 2);
   3467     cleanupAfterGraphicsCall(false);
   3468 }
   3469 
   3470 void WebGLRenderingContext::uniform2fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3471 {
   3472     UNUSED_PARAM(ec);
   3473     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
   3474         return;
   3475 
   3476     m_context->uniform2fv(location->location(), v, size / 2);
   3477     cleanupAfterGraphicsCall(false);
   3478 }
   3479 
   3480 void WebGLRenderingContext::uniform2i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, ExceptionCode& ec)
   3481 {
   3482     UNUSED_PARAM(ec);
   3483     if (isContextLost() || !location)
   3484         return;
   3485 
   3486     if (location->program() != m_currentProgram) {
   3487         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3488         return;
   3489     }
   3490 
   3491     m_context->uniform2i(location->location(), x, y);
   3492     cleanupAfterGraphicsCall(false);
   3493 }
   3494 
   3495 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
   3496 {
   3497     UNUSED_PARAM(ec);
   3498     if (isContextLost() || !validateUniformParameters(location, v, 2))
   3499         return;
   3500 
   3501     m_context->uniform2iv(location->location(), v->data(), v->length() / 2);
   3502     cleanupAfterGraphicsCall(false);
   3503 }
   3504 
   3505 void WebGLRenderingContext::uniform2iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
   3506 {
   3507     UNUSED_PARAM(ec);
   3508     if (isContextLost() || !validateUniformParameters(location, v, size, 2))
   3509         return;
   3510 
   3511     m_context->uniform2iv(location->location(), v, size / 2);
   3512     cleanupAfterGraphicsCall(false);
   3513 }
   3514 
   3515 void WebGLRenderingContext::uniform3f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, ExceptionCode& ec)
   3516 {
   3517     UNUSED_PARAM(ec);
   3518     if (isContextLost() || !location)
   3519         return;
   3520 
   3521     if (location->program() != m_currentProgram) {
   3522         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3523         return;
   3524     }
   3525 
   3526     m_context->uniform3f(location->location(), x, y, z);
   3527     cleanupAfterGraphicsCall(false);
   3528 }
   3529 
   3530 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
   3531 {
   3532     UNUSED_PARAM(ec);
   3533     if (isContextLost() || !validateUniformParameters(location, v, 3))
   3534         return;
   3535 
   3536     m_context->uniform3fv(location->location(), v->data(), v->length() / 3);
   3537     cleanupAfterGraphicsCall(false);
   3538 }
   3539 
   3540 void WebGLRenderingContext::uniform3fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3541 {
   3542     UNUSED_PARAM(ec);
   3543     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
   3544         return;
   3545 
   3546     m_context->uniform3fv(location->location(), v, size / 3);
   3547     cleanupAfterGraphicsCall(false);
   3548 }
   3549 
   3550 void WebGLRenderingContext::uniform3i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, ExceptionCode& ec)
   3551 {
   3552     UNUSED_PARAM(ec);
   3553     if (isContextLost() || !location)
   3554         return;
   3555 
   3556     if (location->program() != m_currentProgram) {
   3557         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3558         return;
   3559     }
   3560 
   3561     m_context->uniform3i(location->location(), x, y, z);
   3562     cleanupAfterGraphicsCall(false);
   3563 }
   3564 
   3565 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
   3566 {
   3567     UNUSED_PARAM(ec);
   3568     if (isContextLost() || !validateUniformParameters(location, v, 3))
   3569         return;
   3570 
   3571     m_context->uniform3iv(location->location(), v->data(), v->length() / 3);
   3572     cleanupAfterGraphicsCall(false);
   3573 }
   3574 
   3575 void WebGLRenderingContext::uniform3iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
   3576 {
   3577     UNUSED_PARAM(ec);
   3578     if (isContextLost() || !validateUniformParameters(location, v, size, 3))
   3579         return;
   3580 
   3581     m_context->uniform3iv(location->location(), v, size / 3);
   3582     cleanupAfterGraphicsCall(false);
   3583 }
   3584 
   3585 void WebGLRenderingContext::uniform4f(const WebGLUniformLocation* location, GC3Dfloat x, GC3Dfloat y, GC3Dfloat z, GC3Dfloat w, ExceptionCode& ec)
   3586 {
   3587     UNUSED_PARAM(ec);
   3588     if (isContextLost() || !location)
   3589         return;
   3590 
   3591     if (location->program() != m_currentProgram) {
   3592         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3593         return;
   3594     }
   3595 
   3596     m_context->uniform4f(location->location(), x, y, z, w);
   3597     cleanupAfterGraphicsCall(false);
   3598 }
   3599 
   3600 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, Float32Array* v, ExceptionCode& ec)
   3601 {
   3602     UNUSED_PARAM(ec);
   3603     if (isContextLost() || !validateUniformParameters(location, v, 4))
   3604         return;
   3605 
   3606     m_context->uniform4fv(location->location(), v->data(), v->length() / 4);
   3607     cleanupAfterGraphicsCall(false);
   3608 }
   3609 
   3610 void WebGLRenderingContext::uniform4fv(const WebGLUniformLocation* location, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3611 {
   3612     UNUSED_PARAM(ec);
   3613     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
   3614         return;
   3615 
   3616     m_context->uniform4fv(location->location(), v, size / 4);
   3617     cleanupAfterGraphicsCall(false);
   3618 }
   3619 
   3620 void WebGLRenderingContext::uniform4i(const WebGLUniformLocation* location, GC3Dint x, GC3Dint y, GC3Dint z, GC3Dint w, ExceptionCode& ec)
   3621 {
   3622     UNUSED_PARAM(ec);
   3623     if (isContextLost() || !location)
   3624         return;
   3625 
   3626     if (location->program() != m_currentProgram) {
   3627         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3628         return;
   3629     }
   3630 
   3631     m_context->uniform4i(location->location(), x, y, z, w);
   3632     cleanupAfterGraphicsCall(false);
   3633 }
   3634 
   3635 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, Int32Array* v, ExceptionCode& ec)
   3636 {
   3637     UNUSED_PARAM(ec);
   3638     if (isContextLost() || !validateUniformParameters(location, v, 4))
   3639         return;
   3640 
   3641     m_context->uniform4iv(location->location(), v->data(), v->length() / 4);
   3642     cleanupAfterGraphicsCall(false);
   3643 }
   3644 
   3645 void WebGLRenderingContext::uniform4iv(const WebGLUniformLocation* location, GC3Dint* v, GC3Dsizei size, ExceptionCode& ec)
   3646 {
   3647     UNUSED_PARAM(ec);
   3648     if (isContextLost() || !validateUniformParameters(location, v, size, 4))
   3649         return;
   3650 
   3651     m_context->uniform4iv(location->location(), v, size / 4);
   3652     cleanupAfterGraphicsCall(false);
   3653 }
   3654 
   3655 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
   3656 {
   3657     UNUSED_PARAM(ec);
   3658     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 4))
   3659         return;
   3660     m_context->uniformMatrix2fv(location->location(), transpose, v->data(), v->length() / 4);
   3661     cleanupAfterGraphicsCall(false);
   3662 }
   3663 
   3664 void WebGLRenderingContext::uniformMatrix2fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3665 {
   3666     UNUSED_PARAM(ec);
   3667     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 4))
   3668         return;
   3669     m_context->uniformMatrix2fv(location->location(), transpose, v, size / 4);
   3670     cleanupAfterGraphicsCall(false);
   3671 }
   3672 
   3673 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
   3674 {
   3675     UNUSED_PARAM(ec);
   3676     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 9))
   3677         return;
   3678     m_context->uniformMatrix3fv(location->location(), transpose, v->data(), v->length() / 9);
   3679     cleanupAfterGraphicsCall(false);
   3680 }
   3681 
   3682 void WebGLRenderingContext::uniformMatrix3fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3683 {
   3684     UNUSED_PARAM(ec);
   3685     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 9))
   3686         return;
   3687     m_context->uniformMatrix3fv(location->location(), transpose, v, size / 9);
   3688     cleanupAfterGraphicsCall(false);
   3689 }
   3690 
   3691 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, ExceptionCode& ec)
   3692 {
   3693     UNUSED_PARAM(ec);
   3694     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, 16))
   3695         return;
   3696     m_context->uniformMatrix4fv(location->location(), transpose, v->data(), v->length() / 16);
   3697     cleanupAfterGraphicsCall(false);
   3698 }
   3699 
   3700 void WebGLRenderingContext::uniformMatrix4fv(const WebGLUniformLocation* location, GC3Dboolean transpose, GC3Dfloat* v, GC3Dsizei size, ExceptionCode& ec)
   3701 {
   3702     UNUSED_PARAM(ec);
   3703     if (isContextLost() || !validateUniformMatrixParameters(location, transpose, v, size, 16))
   3704         return;
   3705     m_context->uniformMatrix4fv(location->location(), transpose, v, size / 16);
   3706     cleanupAfterGraphicsCall(false);
   3707 }
   3708 
   3709 void WebGLRenderingContext::useProgram(WebGLProgram* program, ExceptionCode& ec)
   3710 {
   3711     UNUSED_PARAM(ec);
   3712     bool deleted;
   3713     if (!checkObjectToBeBound(program, deleted))
   3714         return;
   3715     if (deleted)
   3716         program = 0;
   3717     if (program && !program->getLinkStatus()) {
   3718         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3719         cleanupAfterGraphicsCall(false);
   3720         return;
   3721     }
   3722     if (m_currentProgram != program) {
   3723         if (m_currentProgram)
   3724             m_currentProgram->onDetached();
   3725         m_currentProgram = program;
   3726         m_context->useProgram(objectOrZero(program));
   3727         if (program)
   3728             program->onAttached();
   3729     }
   3730     cleanupAfterGraphicsCall(false);
   3731 }
   3732 
   3733 void WebGLRenderingContext::validateProgram(WebGLProgram* program, ExceptionCode& ec)
   3734 {
   3735     UNUSED_PARAM(ec);
   3736     if (isContextLost() || !validateWebGLObject(program))
   3737         return;
   3738     m_context->validateProgram(objectOrZero(program));
   3739     cleanupAfterGraphicsCall(false);
   3740 }
   3741 
   3742 void WebGLRenderingContext::vertexAttrib1f(GC3Duint index, GC3Dfloat v0)
   3743 {
   3744     vertexAttribfImpl(index, 1, v0, 0.0f, 0.0f, 1.0f);
   3745 }
   3746 
   3747 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, Float32Array* v)
   3748 {
   3749     vertexAttribfvImpl(index, v, 1);
   3750 }
   3751 
   3752 void WebGLRenderingContext::vertexAttrib1fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
   3753 {
   3754     vertexAttribfvImpl(index, v, size, 1);
   3755 }
   3756 
   3757 void WebGLRenderingContext::vertexAttrib2f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1)
   3758 {
   3759     vertexAttribfImpl(index, 2, v0, v1, 0.0f, 1.0f);
   3760 }
   3761 
   3762 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, Float32Array* v)
   3763 {
   3764     vertexAttribfvImpl(index, v, 2);
   3765 }
   3766 
   3767 void WebGLRenderingContext::vertexAttrib2fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
   3768 {
   3769     vertexAttribfvImpl(index, v, size, 2);
   3770 }
   3771 
   3772 void WebGLRenderingContext::vertexAttrib3f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2)
   3773 {
   3774     vertexAttribfImpl(index, 3, v0, v1, v2, 1.0f);
   3775 }
   3776 
   3777 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, Float32Array* v)
   3778 {
   3779     vertexAttribfvImpl(index, v, 3);
   3780 }
   3781 
   3782 void WebGLRenderingContext::vertexAttrib3fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
   3783 {
   3784     vertexAttribfvImpl(index, v, size, 3);
   3785 }
   3786 
   3787 void WebGLRenderingContext::vertexAttrib4f(GC3Duint index, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
   3788 {
   3789     vertexAttribfImpl(index, 4, v0, v1, v2, v3);
   3790 }
   3791 
   3792 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, Float32Array* v)
   3793 {
   3794     vertexAttribfvImpl(index, v, 4);
   3795 }
   3796 
   3797 void WebGLRenderingContext::vertexAttrib4fv(GC3Duint index, GC3Dfloat* v, GC3Dsizei size)
   3798 {
   3799     vertexAttribfvImpl(index, v, size, 4);
   3800 }
   3801 
   3802 void WebGLRenderingContext::vertexAttribPointer(GC3Duint index, GC3Dint size, GC3Denum type, GC3Dboolean normalized, GC3Dsizei stride, GC3Dintptr offset, ExceptionCode& ec)
   3803 {
   3804     UNUSED_PARAM(ec);
   3805     if (isContextLost())
   3806         return;
   3807     switch (type) {
   3808     case GraphicsContext3D::BYTE:
   3809     case GraphicsContext3D::UNSIGNED_BYTE:
   3810     case GraphicsContext3D::SHORT:
   3811     case GraphicsContext3D::UNSIGNED_SHORT:
   3812     case GraphicsContext3D::FLOAT:
   3813         break;
   3814     default:
   3815         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   3816         return;
   3817     }
   3818     if (index >= m_maxVertexAttribs) {
   3819         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3820         return;
   3821     }
   3822     if (size < 1 || size > 4 || stride < 0 || stride > 255 || offset < 0) {
   3823         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   3824         return;
   3825     }
   3826     if (!m_boundArrayBuffer) {
   3827         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3828         return;
   3829     }
   3830     // Determine the number of elements the bound buffer can hold, given the offset, size, type and stride
   3831     unsigned int typeSize = sizeInBytes(type);
   3832     if (!typeSize) {
   3833         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   3834         return;
   3835     }
   3836     if ((stride % typeSize) || (offset % typeSize)) {
   3837         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3838         return;
   3839     }
   3840     GC3Dsizei bytesPerElement = size * typeSize;
   3841 
   3842     GC3Dsizei validatedStride = stride ? stride : bytesPerElement;
   3843 
   3844     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(index);
   3845     state.bufferBinding = m_boundArrayBuffer;
   3846     state.bytesPerElement = bytesPerElement;
   3847     state.size = size;
   3848     state.type = type;
   3849     state.normalized = normalized;
   3850     state.stride = validatedStride;
   3851     state.originalStride = stride;
   3852     state.offset = offset;
   3853     m_context->vertexAttribPointer(index, size, type, normalized, stride, offset);
   3854     cleanupAfterGraphicsCall(false);
   3855 }
   3856 
   3857 void WebGLRenderingContext::viewport(GC3Dint x, GC3Dint y, GC3Dsizei width, GC3Dsizei height)
   3858 {
   3859     if (isContextLost())
   3860         return;
   3861     if (isnan(x))
   3862         x = 0;
   3863     if (isnan(y))
   3864         y = 0;
   3865     if (isnan(width))
   3866         width = 100;
   3867     if (isnan(height))
   3868         height = 100;
   3869     if (!validateSize(width, height))
   3870         return;
   3871     m_context->viewport(x, y, width, height);
   3872     cleanupAfterGraphicsCall(false);
   3873 }
   3874 
   3875 void WebGLRenderingContext::forceLostContext()
   3876 {
   3877     if (isContextLost()) {
   3878         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   3879         return;
   3880     }
   3881 
   3882     m_restoreTimer.startOneShot(0);
   3883 }
   3884 
   3885 void WebGLRenderingContext::onLostContext()
   3886 {
   3887     m_contextLost = true;
   3888 
   3889     detachAndRemoveAllObjects();
   3890 
   3891     // There is no direct way to clear errors from a GL implementation and
   3892     // looping until getError() becomes NO_ERROR might cause an infinite loop if
   3893     // the driver or context implementation had a bug.  So, loop a reasonably
   3894     // large number of times to clear any existing errors.
   3895     for (int i = 0; i < 100; ++i) {
   3896         if (m_context->getError() == GraphicsContext3D::NO_ERROR)
   3897             break;
   3898     }
   3899     m_context->synthesizeGLError(GraphicsContext3D::CONTEXT_LOST_WEBGL);
   3900 
   3901     canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextlostEvent, false, true, ""));
   3902 }
   3903 
   3904 void WebGLRenderingContext::restoreContext()
   3905 {
   3906     RefPtr<GraphicsContext3D> context(GraphicsContext3D::create(m_attributes, canvas()->document()->view()->root()->hostWindow()));
   3907     if (!context)
   3908         return;
   3909 
   3910     m_context = context;
   3911     m_contextLost = false;
   3912     initializeNewContext();
   3913     canvas()->dispatchEvent(WebGLContextEvent::create(eventNames().webglcontextrestoredEvent, false, true, ""));
   3914 }
   3915 
   3916 void WebGLRenderingContext::removeObject(WebGLObject* object)
   3917 {
   3918     m_canvasObjects.remove(object);
   3919 }
   3920 
   3921 void WebGLRenderingContext::addObject(WebGLObject* object)
   3922 {
   3923     ASSERT(!isContextLost());
   3924     removeObject(object);
   3925     m_canvasObjects.add(object);
   3926 }
   3927 
   3928 void WebGLRenderingContext::detachAndRemoveAllObjects()
   3929 {
   3930     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
   3931     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it)
   3932         (*it)->detachContext();
   3933 
   3934     m_canvasObjects.clear();
   3935 }
   3936 
   3937 WebGLTexture* WebGLRenderingContext::findTexture(Platform3DObject obj)
   3938 {
   3939     if (!obj)
   3940         return 0;
   3941     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
   3942     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
   3943         if ((*it)->isTexture() && (*it)->object() == obj)
   3944             return reinterpret_cast<WebGLTexture*>((*it).get());
   3945     }
   3946     return 0;
   3947 }
   3948 
   3949 WebGLRenderbuffer* WebGLRenderingContext::findRenderbuffer(Platform3DObject obj)
   3950 {
   3951     if (!obj)
   3952         return 0;
   3953     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
   3954     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
   3955         if ((*it)->isRenderbuffer() && (*it)->object() == obj)
   3956             return reinterpret_cast<WebGLRenderbuffer*>((*it).get());
   3957     }
   3958     return 0;
   3959 }
   3960 
   3961 WebGLBuffer* WebGLRenderingContext::findBuffer(Platform3DObject obj)
   3962 {
   3963     if (!obj)
   3964         return 0;
   3965     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
   3966     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
   3967         if ((*it)->isBuffer() && (*it)->object() == obj)
   3968             return reinterpret_cast<WebGLBuffer*>((*it).get());
   3969     }
   3970     return 0;
   3971 }
   3972 
   3973 WebGLShader* WebGLRenderingContext::findShader(Platform3DObject obj)
   3974 {
   3975     if (!obj)
   3976         return 0;
   3977     HashSet<RefPtr<WebGLObject> >::iterator pend = m_canvasObjects.end();
   3978     for (HashSet<RefPtr<WebGLObject> >::iterator it = m_canvasObjects.begin(); it != pend; ++it) {
   3979         if ((*it)->isShader() && (*it)->object() == obj)
   3980             return reinterpret_cast<WebGLShader*>((*it).get());
   3981     }
   3982     return 0;
   3983 }
   3984 
   3985 WebGLGetInfo WebGLRenderingContext::getBooleanParameter(GC3Denum pname)
   3986 {
   3987     GC3Dboolean value = 0;
   3988     m_context->getBooleanv(pname, &value);
   3989     return WebGLGetInfo(static_cast<bool>(value));
   3990 }
   3991 
   3992 WebGLGetInfo WebGLRenderingContext::getBooleanArrayParameter(GC3Denum pname)
   3993 {
   3994     if (pname != GraphicsContext3D::COLOR_WRITEMASK) {
   3995         notImplemented();
   3996         return WebGLGetInfo(0, 0);
   3997     }
   3998     GC3Dboolean value[4] = {0};
   3999     m_context->getBooleanv(pname, value);
   4000     bool boolValue[4];
   4001     for (int ii = 0; ii < 4; ++ii)
   4002         boolValue[ii] = static_cast<bool>(value[ii]);
   4003     return WebGLGetInfo(boolValue, 4);
   4004 }
   4005 
   4006 WebGLGetInfo WebGLRenderingContext::getFloatParameter(GC3Denum pname)
   4007 {
   4008     GC3Dfloat value = 0;
   4009     m_context->getFloatv(pname, &value);
   4010     return WebGLGetInfo(value);
   4011 }
   4012 
   4013 WebGLGetInfo WebGLRenderingContext::getIntParameter(GC3Denum pname)
   4014 {
   4015     GC3Dint value = 0;
   4016     m_context->getIntegerv(pname, &value);
   4017     return WebGLGetInfo(value);
   4018 }
   4019 
   4020 WebGLGetInfo WebGLRenderingContext::getUnsignedIntParameter(GC3Denum pname)
   4021 {
   4022     GC3Dint value = 0;
   4023     m_context->getIntegerv(pname, &value);
   4024     return WebGLGetInfo(static_cast<unsigned int>(value));
   4025 }
   4026 
   4027 WebGLGetInfo WebGLRenderingContext::getWebGLFloatArrayParameter(GC3Denum pname)
   4028 {
   4029     GC3Dfloat value[4] = {0};
   4030     m_context->getFloatv(pname, value);
   4031     unsigned length = 0;
   4032     switch (pname) {
   4033     case GraphicsContext3D::ALIASED_POINT_SIZE_RANGE:
   4034     case GraphicsContext3D::ALIASED_LINE_WIDTH_RANGE:
   4035     case GraphicsContext3D::DEPTH_RANGE:
   4036         length = 2;
   4037         break;
   4038     case GraphicsContext3D::BLEND_COLOR:
   4039     case GraphicsContext3D::COLOR_CLEAR_VALUE:
   4040         length = 4;
   4041         break;
   4042     default:
   4043         notImplemented();
   4044     }
   4045     return WebGLGetInfo(Float32Array::create(value, length));
   4046 }
   4047 
   4048 WebGLGetInfo WebGLRenderingContext::getWebGLIntArrayParameter(GC3Denum pname)
   4049 {
   4050     GC3Dint value[4] = {0};
   4051     m_context->getIntegerv(pname, value);
   4052     unsigned length = 0;
   4053     switch (pname) {
   4054     case GraphicsContext3D::MAX_VIEWPORT_DIMS:
   4055         length = 2;
   4056         break;
   4057     case GraphicsContext3D::SCISSOR_BOX:
   4058     case GraphicsContext3D::VIEWPORT:
   4059         length = 4;
   4060         break;
   4061     default:
   4062         notImplemented();
   4063     }
   4064     return WebGLGetInfo(Int32Array::create(value, length));
   4065 }
   4066 
   4067 void WebGLRenderingContext::handleNPOTTextures(bool prepareToDraw)
   4068 {
   4069     bool resetActiveUnit = false;
   4070     for (unsigned ii = 0; ii < m_textureUnits.size(); ++ii) {
   4071         if ((m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
   4072             || (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())) {
   4073             if (ii != m_activeTextureUnit) {
   4074                 m_context->activeTexture(ii);
   4075                 resetActiveUnit = true;
   4076             } else if (resetActiveUnit) {
   4077                 m_context->activeTexture(ii);
   4078                 resetActiveUnit = false;
   4079             }
   4080             WebGLTexture* tex2D;
   4081             WebGLTexture* texCubeMap;
   4082             if (prepareToDraw) {
   4083                 tex2D = m_blackTexture2D.get();
   4084                 texCubeMap = m_blackTextureCubeMap.get();
   4085             } else {
   4086                 tex2D = m_textureUnits[ii].m_texture2DBinding.get();
   4087                 texCubeMap = m_textureUnits[ii].m_textureCubeMapBinding.get();
   4088             }
   4089             if (m_textureUnits[ii].m_texture2DBinding && m_textureUnits[ii].m_texture2DBinding->needToUseBlackTexture())
   4090                 m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, objectOrZero(tex2D));
   4091             if (m_textureUnits[ii].m_textureCubeMapBinding && m_textureUnits[ii].m_textureCubeMapBinding->needToUseBlackTexture())
   4092                 m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, objectOrZero(texCubeMap));
   4093         }
   4094     }
   4095     if (resetActiveUnit)
   4096         m_context->activeTexture(m_activeTextureUnit);
   4097 }
   4098 
   4099 void WebGLRenderingContext::createFallbackBlackTextures1x1()
   4100 {
   4101     unsigned char black[] = {0, 0, 0, 255};
   4102     m_blackTexture2D = createTexture();
   4103     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, m_blackTexture2D->object());
   4104     m_context->texImage2D(GraphicsContext3D::TEXTURE_2D, 0, GraphicsContext3D::RGBA, 1, 1,
   4105                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4106     m_context->bindTexture(GraphicsContext3D::TEXTURE_2D, 0);
   4107     m_blackTextureCubeMap = createTexture();
   4108     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, m_blackTextureCubeMap->object());
   4109     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
   4110                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4111     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GraphicsContext3D::RGBA, 1, 1,
   4112                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4113     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
   4114                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4115     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GraphicsContext3D::RGBA, 1, 1,
   4116                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4117     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
   4118                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4119     m_context->texImage2D(GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GraphicsContext3D::RGBA, 1, 1,
   4120                           0, GraphicsContext3D::RGBA, GraphicsContext3D::UNSIGNED_BYTE, black);
   4121     m_context->bindTexture(GraphicsContext3D::TEXTURE_CUBE_MAP, 0);
   4122 }
   4123 
   4124 bool WebGLRenderingContext::isTexInternalFormatColorBufferCombinationValid(GC3Denum texInternalFormat,
   4125                                                                            GC3Denum colorBufferFormat)
   4126 {
   4127     switch (colorBufferFormat) {
   4128     case GraphicsContext3D::ALPHA:
   4129         if (texInternalFormat == GraphicsContext3D::ALPHA)
   4130             return true;
   4131         break;
   4132     case GraphicsContext3D::RGB:
   4133         if (texInternalFormat == GraphicsContext3D::LUMINANCE
   4134             || texInternalFormat == GraphicsContext3D::RGB)
   4135             return true;
   4136         break;
   4137     case GraphicsContext3D::RGBA:
   4138         return true;
   4139     }
   4140     return false;
   4141 }
   4142 
   4143 GC3Denum WebGLRenderingContext::getBoundFramebufferColorFormat()
   4144 {
   4145     if (m_framebufferBinding && m_framebufferBinding->object())
   4146         return m_framebufferBinding->getColorBufferFormat();
   4147     if (m_attributes.alpha)
   4148         return GraphicsContext3D::RGBA;
   4149     return GraphicsContext3D::RGB;
   4150 }
   4151 
   4152 int WebGLRenderingContext::getBoundFramebufferWidth()
   4153 {
   4154     if (m_framebufferBinding && m_framebufferBinding->object())
   4155         return m_framebufferBinding->getWidth();
   4156     return m_context->getInternalFramebufferSize().width();
   4157 }
   4158 
   4159 int WebGLRenderingContext::getBoundFramebufferHeight()
   4160 {
   4161     if (m_framebufferBinding && m_framebufferBinding->object())
   4162         return m_framebufferBinding->getHeight();
   4163     return m_context->getInternalFramebufferSize().height();
   4164 }
   4165 
   4166 WebGLTexture* WebGLRenderingContext::validateTextureBinding(GC3Denum target, bool useSixEnumsForCubeMap)
   4167 {
   4168     WebGLTexture* tex = 0;
   4169     switch (target) {
   4170     case GraphicsContext3D::TEXTURE_2D:
   4171         tex = m_textureUnits[m_activeTextureUnit].m_texture2DBinding.get();
   4172         break;
   4173     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
   4174     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
   4175     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
   4176     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
   4177     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
   4178     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
   4179         if (!useSixEnumsForCubeMap) {
   4180             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4181             return 0;
   4182         }
   4183         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
   4184         break;
   4185     case GraphicsContext3D::TEXTURE_CUBE_MAP:
   4186         if (useSixEnumsForCubeMap) {
   4187             m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4188             return 0;
   4189         }
   4190         tex = m_textureUnits[m_activeTextureUnit].m_textureCubeMapBinding.get();
   4191         break;
   4192     default:
   4193         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4194         return 0;
   4195     }
   4196     if (!tex)
   4197         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4198     return tex;
   4199 }
   4200 
   4201 bool WebGLRenderingContext::validateSize(GC3Dint x, GC3Dint y)
   4202 {
   4203     if (x < 0 || y < 0) {
   4204         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4205         return false;
   4206     }
   4207     return true;
   4208 }
   4209 
   4210 bool WebGLRenderingContext::validateString(const String& string)
   4211 {
   4212     for (size_t i = 0; i < string.length(); ++i) {
   4213         if (!validateCharacter(string[i])) {
   4214             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4215             return false;
   4216         }
   4217     }
   4218     return true;
   4219 }
   4220 
   4221 bool WebGLRenderingContext::validateTexFuncFormatAndType(GC3Denum format, GC3Denum type)
   4222 {
   4223     switch (format) {
   4224     case GraphicsContext3D::ALPHA:
   4225     case GraphicsContext3D::LUMINANCE:
   4226     case GraphicsContext3D::LUMINANCE_ALPHA:
   4227     case GraphicsContext3D::RGB:
   4228     case GraphicsContext3D::RGBA:
   4229         break;
   4230     default:
   4231         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4232         return false;
   4233     }
   4234 
   4235     switch (type) {
   4236     case GraphicsContext3D::UNSIGNED_BYTE:
   4237     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
   4238     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
   4239     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
   4240         break;
   4241     case GraphicsContext3D::FLOAT:
   4242         if (m_oesTextureFloat)
   4243             break;
   4244         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4245         return false;
   4246     default:
   4247         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4248         return false;
   4249     }
   4250 
   4251     // Verify that the combination of format and type is supported.
   4252     switch (format) {
   4253     case GraphicsContext3D::ALPHA:
   4254     case GraphicsContext3D::LUMINANCE:
   4255     case GraphicsContext3D::LUMINANCE_ALPHA:
   4256         if (type != GraphicsContext3D::UNSIGNED_BYTE
   4257             && type != GraphicsContext3D::FLOAT) {
   4258             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4259             return false;
   4260         }
   4261         break;
   4262     case GraphicsContext3D::RGB:
   4263         if (type != GraphicsContext3D::UNSIGNED_BYTE
   4264             && type != GraphicsContext3D::UNSIGNED_SHORT_5_6_5
   4265             && type != GraphicsContext3D::FLOAT) {
   4266             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4267             return false;
   4268         }
   4269         break;
   4270     case GraphicsContext3D::RGBA:
   4271         if (type != GraphicsContext3D::UNSIGNED_BYTE
   4272             && type != GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4
   4273             && type != GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1
   4274             && type != GraphicsContext3D::FLOAT) {
   4275             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4276             return false;
   4277         }
   4278         break;
   4279     default:
   4280         ASSERT_NOT_REACHED();
   4281     }
   4282 
   4283     return true;
   4284 }
   4285 
   4286 bool WebGLRenderingContext::validateTexFuncLevel(GC3Denum target, GC3Dint level)
   4287 {
   4288     if (level < 0) {
   4289         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4290         return false;
   4291     }
   4292     switch (target) {
   4293     case GraphicsContext3D::TEXTURE_2D:
   4294         if (level > m_maxTextureLevel) {
   4295             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4296             return false;
   4297         }
   4298         break;
   4299     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
   4300     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
   4301     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
   4302     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
   4303     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
   4304     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
   4305         if (level > m_maxCubeMapTextureLevel) {
   4306             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4307             return false;
   4308         }
   4309         break;
   4310     }
   4311     // This function only checks if level is legal, so we return true and don't
   4312     // generate INVALID_ENUM if target is illegal.
   4313     return true;
   4314 }
   4315 
   4316 bool WebGLRenderingContext::validateTexFuncParameters(GC3Denum target, GC3Dint level,
   4317                                                       GC3Denum internalformat,
   4318                                                       GC3Dsizei width, GC3Dsizei height, GC3Dint border,
   4319                                                       GC3Denum format, GC3Denum type)
   4320 {
   4321     // We absolutely have to validate the format and type combination.
   4322     // The texImage2D entry points taking HTMLImage, etc. will produce
   4323     // temporary data based on this combination, so it must be legal.
   4324     if (!validateTexFuncFormatAndType(format, type) || !validateTexFuncLevel(target, level))
   4325         return false;
   4326 
   4327     if (width < 0 || height < 0) {
   4328         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4329         return false;
   4330     }
   4331 
   4332     switch (target) {
   4333     case GraphicsContext3D::TEXTURE_2D:
   4334         if (width > m_maxTextureSize || height > m_maxTextureSize) {
   4335             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4336             return false;
   4337         }
   4338         break;
   4339     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_X:
   4340     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_X:
   4341     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Y:
   4342     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Y:
   4343     case GraphicsContext3D::TEXTURE_CUBE_MAP_POSITIVE_Z:
   4344     case GraphicsContext3D::TEXTURE_CUBE_MAP_NEGATIVE_Z:
   4345         if (width != height || width > m_maxCubeMapTextureSize) {
   4346             m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4347             return false;
   4348         }
   4349         break;
   4350     default:
   4351         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4352         return false;
   4353     }
   4354 
   4355     if (format != internalformat) {
   4356         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4357         return false;
   4358     }
   4359 
   4360     if (border) {
   4361         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4362         return false;
   4363     }
   4364 
   4365     return true;
   4366 }
   4367 
   4368 bool WebGLRenderingContext::validateTexFuncData(GC3Dsizei width, GC3Dsizei height,
   4369                                                 GC3Denum format, GC3Denum type,
   4370                                                 ArrayBufferView* pixels)
   4371 {
   4372     if (!pixels)
   4373         return true;
   4374 
   4375     if (!validateTexFuncFormatAndType(format, type))
   4376         return false;
   4377 
   4378     switch (type) {
   4379     case GraphicsContext3D::UNSIGNED_BYTE:
   4380         if (!pixels->isUnsignedByteArray()) {
   4381             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4382             return false;
   4383         }
   4384         break;
   4385     case GraphicsContext3D::UNSIGNED_SHORT_5_6_5:
   4386     case GraphicsContext3D::UNSIGNED_SHORT_4_4_4_4:
   4387     case GraphicsContext3D::UNSIGNED_SHORT_5_5_5_1:
   4388         if (!pixels->isUnsignedShortArray()) {
   4389             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4390             return false;
   4391         }
   4392         break;
   4393     case GraphicsContext3D::FLOAT: // OES_texture_float
   4394         if (!pixels->isFloatArray()) {
   4395             m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4396             return false;
   4397         }
   4398         break;
   4399     default:
   4400         ASSERT_NOT_REACHED();
   4401     }
   4402 
   4403     unsigned int totalBytesRequired;
   4404     GC3Denum error = m_context->computeImageSizeInBytes(format, type, width, height, m_unpackAlignment, &totalBytesRequired, 0);
   4405     if (error != GraphicsContext3D::NO_ERROR) {
   4406         m_context->synthesizeGLError(error);
   4407         return false;
   4408     }
   4409     if (pixels->byteLength() < totalBytesRequired) {
   4410         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4411         return false;
   4412     }
   4413     return true;
   4414 }
   4415 
   4416 bool WebGLRenderingContext::validateDrawMode(GC3Denum mode)
   4417 {
   4418     switch (mode) {
   4419     case GraphicsContext3D::POINTS:
   4420     case GraphicsContext3D::LINE_STRIP:
   4421     case GraphicsContext3D::LINE_LOOP:
   4422     case GraphicsContext3D::LINES:
   4423     case GraphicsContext3D::TRIANGLE_STRIP:
   4424     case GraphicsContext3D::TRIANGLE_FAN:
   4425     case GraphicsContext3D::TRIANGLES:
   4426         return true;
   4427     default:
   4428         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4429         return false;
   4430     }
   4431 }
   4432 
   4433 bool WebGLRenderingContext::validateStencilSettings()
   4434 {
   4435     if (m_stencilMask != m_stencilMaskBack || m_stencilFuncRef != m_stencilFuncRefBack || m_stencilFuncMask != m_stencilFuncMaskBack) {
   4436         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4437         return false;
   4438     }
   4439     return true;
   4440 }
   4441 
   4442 bool WebGLRenderingContext::validateStencilFunc(GC3Denum func)
   4443 {
   4444     switch (func) {
   4445     case GraphicsContext3D::NEVER:
   4446     case GraphicsContext3D::LESS:
   4447     case GraphicsContext3D::LEQUAL:
   4448     case GraphicsContext3D::GREATER:
   4449     case GraphicsContext3D::GEQUAL:
   4450     case GraphicsContext3D::EQUAL:
   4451     case GraphicsContext3D::NOTEQUAL:
   4452     case GraphicsContext3D::ALWAYS:
   4453         return true;
   4454     default:
   4455         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4456         return false;
   4457     }
   4458 }
   4459 
   4460 void WebGLRenderingContext::printWarningToConsole(const String& message)
   4461 {
   4462     canvas()->document()->frame()->domWindow()->console()->addMessage(HTMLMessageSource, LogMessageType, WarningMessageLevel,
   4463                                                                       message, 0, canvas()->document()->url().string());
   4464 }
   4465 
   4466 bool WebGLRenderingContext::validateFramebufferFuncParameters(GC3Denum target, GC3Denum attachment)
   4467 {
   4468     if (target != GraphicsContext3D::FRAMEBUFFER) {
   4469         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4470         return false;
   4471     }
   4472     switch (attachment) {
   4473     case GraphicsContext3D::COLOR_ATTACHMENT0:
   4474     case GraphicsContext3D::DEPTH_ATTACHMENT:
   4475     case GraphicsContext3D::STENCIL_ATTACHMENT:
   4476     case GraphicsContext3D::DEPTH_STENCIL_ATTACHMENT:
   4477         break;
   4478     default:
   4479         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4480         return false;
   4481     }
   4482     return true;
   4483 }
   4484 
   4485 bool WebGLRenderingContext::validateBlendEquation(GC3Denum mode)
   4486 {
   4487     switch (mode) {
   4488     case GraphicsContext3D::FUNC_ADD:
   4489     case GraphicsContext3D::FUNC_SUBTRACT:
   4490     case GraphicsContext3D::FUNC_REVERSE_SUBTRACT:
   4491         return true;
   4492     default:
   4493         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4494         return false;
   4495     }
   4496 }
   4497 
   4498 bool WebGLRenderingContext::validateBlendFuncFactors(GC3Denum src, GC3Denum dst)
   4499 {
   4500     if (((src == GraphicsContext3D::CONSTANT_COLOR || src == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
   4501          && (dst == GraphicsContext3D::CONSTANT_ALPHA || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))
   4502         || ((dst == GraphicsContext3D::CONSTANT_COLOR || dst == GraphicsContext3D::ONE_MINUS_CONSTANT_COLOR)
   4503             && (src == GraphicsContext3D::CONSTANT_ALPHA || src == GraphicsContext3D::ONE_MINUS_CONSTANT_ALPHA))) {
   4504         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4505         return false;
   4506     }
   4507     return true;
   4508 }
   4509 
   4510 bool WebGLRenderingContext::validateCapability(GC3Denum cap)
   4511 {
   4512     switch (cap) {
   4513     case GraphicsContext3D::BLEND:
   4514     case GraphicsContext3D::CULL_FACE:
   4515     case GraphicsContext3D::DEPTH_TEST:
   4516     case GraphicsContext3D::DITHER:
   4517     case GraphicsContext3D::POLYGON_OFFSET_FILL:
   4518     case GraphicsContext3D::SAMPLE_ALPHA_TO_COVERAGE:
   4519     case GraphicsContext3D::SAMPLE_COVERAGE:
   4520     case GraphicsContext3D::SCISSOR_TEST:
   4521     case GraphicsContext3D::STENCIL_TEST:
   4522         return true;
   4523     default:
   4524         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4525         return false;
   4526     }
   4527 }
   4528 
   4529 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Float32Array* v, GC3Dsizei requiredMinSize)
   4530 {
   4531     if (!v) {
   4532         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4533         return false;
   4534     }
   4535     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
   4536 }
   4537 
   4538 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, Int32Array* v, GC3Dsizei requiredMinSize)
   4539 {
   4540     if (!v) {
   4541         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4542         return false;
   4543     }
   4544     return validateUniformMatrixParameters(location, false, v->data(), v->length(), requiredMinSize);
   4545 }
   4546 
   4547 bool WebGLRenderingContext::validateUniformParameters(const WebGLUniformLocation* location, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
   4548 {
   4549     return validateUniformMatrixParameters(location, false, v, size, requiredMinSize);
   4550 }
   4551 
   4552 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, Float32Array* v, GC3Dsizei requiredMinSize)
   4553 {
   4554     if (!v) {
   4555         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4556         return false;
   4557     }
   4558     return validateUniformMatrixParameters(location, transpose, v->data(), v->length(), requiredMinSize);
   4559 }
   4560 
   4561 bool WebGLRenderingContext::validateUniformMatrixParameters(const WebGLUniformLocation* location, GC3Dboolean transpose, void* v, GC3Dsizei size, GC3Dsizei requiredMinSize)
   4562 {
   4563     if (!location)
   4564         return false;
   4565     if (location->program() != m_currentProgram) {
   4566         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4567         return false;
   4568     }
   4569     if (!v) {
   4570         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4571         return false;
   4572     }
   4573     if (transpose) {
   4574         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4575         return false;
   4576     }
   4577     if (size < requiredMinSize || (size % requiredMinSize)) {
   4578         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4579         return false;
   4580     }
   4581     return true;
   4582 }
   4583 
   4584 WebGLBuffer* WebGLRenderingContext::validateBufferDataParameters(GC3Denum target, GC3Denum usage)
   4585 {
   4586     WebGLBuffer* buffer = 0;
   4587     switch (target) {
   4588     case GraphicsContext3D::ELEMENT_ARRAY_BUFFER:
   4589         buffer = m_boundVertexArrayObject->getElementArrayBuffer().get();
   4590         break;
   4591     case GraphicsContext3D::ARRAY_BUFFER:
   4592         buffer = m_boundArrayBuffer.get();
   4593         break;
   4594     default:
   4595         m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4596         return 0;
   4597     }
   4598     if (!buffer) {
   4599         m_context->synthesizeGLError(GraphicsContext3D::INVALID_OPERATION);
   4600         return 0;
   4601     }
   4602     switch (usage) {
   4603     case GraphicsContext3D::STREAM_DRAW:
   4604     case GraphicsContext3D::STATIC_DRAW:
   4605     case GraphicsContext3D::DYNAMIC_DRAW:
   4606         return buffer;
   4607     }
   4608     m_context->synthesizeGLError(GraphicsContext3D::INVALID_ENUM);
   4609     return 0;
   4610 }
   4611 
   4612 bool WebGLRenderingContext::validateHTMLImageElement(HTMLImageElement* image)
   4613 {
   4614     if (!image || !image->cachedImage()) {
   4615         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4616         return false;
   4617     }
   4618     const KURL& url = image->cachedImage()->response().url();
   4619     if (url.isNull() || url.isEmpty() || !url.isValid()) {
   4620         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4621         return false;
   4622     }
   4623     return true;
   4624 }
   4625 
   4626 void WebGLRenderingContext::vertexAttribfImpl(GC3Duint index, GC3Dsizei expectedSize, GC3Dfloat v0, GC3Dfloat v1, GC3Dfloat v2, GC3Dfloat v3)
   4627 {
   4628     if (isContextLost())
   4629         return;
   4630     if (index >= m_maxVertexAttribs) {
   4631         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4632         return;
   4633     }
   4634     // In GL, we skip setting vertexAttrib0 values.
   4635     if (index || isGLES2Compliant()) {
   4636         switch (expectedSize) {
   4637         case 1:
   4638             m_context->vertexAttrib1f(index, v0);
   4639             break;
   4640         case 2:
   4641             m_context->vertexAttrib2f(index, v0, v1);
   4642             break;
   4643         case 3:
   4644             m_context->vertexAttrib3f(index, v0, v1, v2);
   4645             break;
   4646         case 4:
   4647             m_context->vertexAttrib4f(index, v0, v1, v2, v3);
   4648             break;
   4649         }
   4650         cleanupAfterGraphicsCall(false);
   4651     }
   4652     VertexAttribValue& attribValue = m_vertexAttribValue[index];
   4653     attribValue.value[0] = v0;
   4654     attribValue.value[1] = v1;
   4655     attribValue.value[2] = v2;
   4656     attribValue.value[3] = v3;
   4657 }
   4658 
   4659 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, Float32Array* v, GC3Dsizei expectedSize)
   4660 {
   4661     if (isContextLost())
   4662         return;
   4663     if (!v) {
   4664         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4665         return;
   4666     }
   4667     vertexAttribfvImpl(index, v->data(), v->length(), expectedSize);
   4668 }
   4669 
   4670 void WebGLRenderingContext::vertexAttribfvImpl(GC3Duint index, GC3Dfloat* v, GC3Dsizei size, GC3Dsizei expectedSize)
   4671 {
   4672     if (isContextLost())
   4673         return;
   4674     if (!v) {
   4675         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4676         return;
   4677     }
   4678     if (size < expectedSize) {
   4679         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4680         return;
   4681     }
   4682     if (index >= m_maxVertexAttribs) {
   4683         m_context->synthesizeGLError(GraphicsContext3D::INVALID_VALUE);
   4684         return;
   4685     }
   4686     // In GL, we skip setting vertexAttrib0 values.
   4687     if (index || isGLES2Compliant()) {
   4688         switch (expectedSize) {
   4689         case 1:
   4690             m_context->vertexAttrib1fv(index, v);
   4691             break;
   4692         case 2:
   4693             m_context->vertexAttrib2fv(index, v);
   4694             break;
   4695         case 3:
   4696             m_context->vertexAttrib3fv(index, v);
   4697             break;
   4698         case 4:
   4699             m_context->vertexAttrib4fv(index, v);
   4700             break;
   4701         }
   4702         cleanupAfterGraphicsCall(false);
   4703     }
   4704     VertexAttribValue& attribValue = m_vertexAttribValue[index];
   4705     attribValue.initValue();
   4706     for (int ii = 0; ii < expectedSize; ++ii)
   4707         attribValue.value[ii] = v[ii];
   4708 }
   4709 
   4710 void WebGLRenderingContext::initVertexAttrib0()
   4711 {
   4712     WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
   4713 
   4714     m_vertexAttrib0Buffer = createBuffer();
   4715     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
   4716     m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, 0, GraphicsContext3D::DYNAMIC_DRAW);
   4717     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, false, 0, 0);
   4718     state.bufferBinding = m_vertexAttrib0Buffer;
   4719     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, 0);
   4720     m_context->enableVertexAttribArray(0);
   4721     m_vertexAttrib0BufferSize = 0;
   4722     m_vertexAttrib0BufferValue[0] = 0.0f;
   4723     m_vertexAttrib0BufferValue[1] = 0.0f;
   4724     m_vertexAttrib0BufferValue[2] = 0.0f;
   4725     m_vertexAttrib0BufferValue[3] = 1.0f;
   4726     m_forceAttrib0BufferRefill = false;
   4727     m_vertexAttrib0UsedBefore = false;
   4728 }
   4729 
   4730 bool WebGLRenderingContext::simulateVertexAttrib0(GC3Dsizei numVertex)
   4731 {
   4732     const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
   4733     const VertexAttribValue& attribValue = m_vertexAttribValue[0];
   4734     if (!m_currentProgram)
   4735         return false;
   4736     bool usingVertexAttrib0 = m_currentProgram->isUsingVertexAttrib0();
   4737     if (usingVertexAttrib0)
   4738         m_vertexAttrib0UsedBefore = true;
   4739     if (state.enabled && usingVertexAttrib0)
   4740         return false;
   4741     if (!usingVertexAttrib0 && !m_vertexAttrib0UsedBefore)
   4742         return false;
   4743     m_vertexAttrib0UsedBefore = true;
   4744     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, m_vertexAttrib0Buffer->object());
   4745     GC3Dsizeiptr bufferDataSize = (numVertex + 1) * 4 * sizeof(GC3Dfloat);
   4746     if (bufferDataSize > m_vertexAttrib0BufferSize) {
   4747         m_context->bufferData(GraphicsContext3D::ARRAY_BUFFER, bufferDataSize, 0, GraphicsContext3D::DYNAMIC_DRAW);
   4748         m_vertexAttrib0BufferSize = bufferDataSize;
   4749         m_forceAttrib0BufferRefill = true;
   4750     }
   4751     if (usingVertexAttrib0
   4752         && (m_forceAttrib0BufferRefill
   4753             || attribValue.value[0] != m_vertexAttrib0BufferValue[0]
   4754             || attribValue.value[1] != m_vertexAttrib0BufferValue[1]
   4755             || attribValue.value[2] != m_vertexAttrib0BufferValue[2]
   4756             || attribValue.value[3] != m_vertexAttrib0BufferValue[3])) {
   4757         OwnArrayPtr<GC3Dfloat> bufferData = adoptArrayPtr(new GC3Dfloat[(numVertex + 1) * 4]);
   4758         for (GC3Dsizei ii = 0; ii < numVertex + 1; ++ii) {
   4759             bufferData[ii * 4] = attribValue.value[0];
   4760             bufferData[ii * 4 + 1] = attribValue.value[1];
   4761             bufferData[ii * 4 + 2] = attribValue.value[2];
   4762             bufferData[ii * 4 + 3] = attribValue.value[3];
   4763         }
   4764         m_vertexAttrib0BufferValue[0] = attribValue.value[0];
   4765         m_vertexAttrib0BufferValue[1] = attribValue.value[1];
   4766         m_vertexAttrib0BufferValue[2] = attribValue.value[2];
   4767         m_vertexAttrib0BufferValue[3] = attribValue.value[3];
   4768         m_forceAttrib0BufferRefill = false;
   4769         m_context->bufferSubData(GraphicsContext3D::ARRAY_BUFFER, 0, bufferDataSize, bufferData.get());
   4770     }
   4771     m_context->vertexAttribPointer(0, 4, GraphicsContext3D::FLOAT, 0, 0, 0);
   4772     return true;
   4773 }
   4774 
   4775 void WebGLRenderingContext::restoreStatesAfterVertexAttrib0Simulation()
   4776 {
   4777     const WebGLVertexArrayObjectOES::VertexAttribState& state = m_boundVertexArrayObject->getVertexAttribState(0);
   4778     if (state.bufferBinding != m_vertexAttrib0Buffer) {
   4779         m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(state.bufferBinding.get()));
   4780         m_context->vertexAttribPointer(0, state.size, state.type, state.normalized, state.originalStride, state.offset);
   4781     }
   4782     m_context->bindBuffer(GraphicsContext3D::ARRAY_BUFFER, objectOrZero(m_boundArrayBuffer.get()));
   4783 }
   4784 
   4785 int WebGLRenderingContext::getNumberOfExtensions()
   4786 {
   4787     return (m_oesVertexArrayObject ? 1 : 0) + (m_oesStandardDerivatives ? 1 : 0) + (m_webkitLoseContext ? 1 : 0) + (m_oesTextureFloat ? 1 : 0);
   4788 }
   4789 
   4790 WebGLExtension* WebGLRenderingContext::getExtensionNumber(int i)
   4791 {
   4792     if (m_oesVertexArrayObject) {
   4793         if (!i)
   4794             return m_oesVertexArrayObject.get();
   4795         --i;
   4796     }
   4797     if (m_oesStandardDerivatives) {
   4798         if (!i)
   4799             return m_oesStandardDerivatives.get();
   4800         --i;
   4801     }
   4802     if (m_webkitLoseContext) {
   4803         if (!i)
   4804             return m_webkitLoseContext.get();
   4805         --i;
   4806     }
   4807     if (m_oesTextureFloat) {
   4808         if (!i)
   4809             return m_oesTextureFloat.get();
   4810         --i;
   4811     }
   4812     // Similar tests for other extensions would go here.
   4813     return 0;
   4814 }
   4815 
   4816 WebGLRenderingContext::LRUImageBufferCache::LRUImageBufferCache(int capacity)
   4817     : m_buffers(adoptArrayPtr(new OwnPtr<ImageBuffer>[capacity]))
   4818     , m_capacity(capacity)
   4819 {
   4820 }
   4821 
   4822 ImageBuffer* WebGLRenderingContext::LRUImageBufferCache::imageBuffer(const IntSize& size)
   4823 {
   4824     int i;
   4825     for (i = 0; i < m_capacity; ++i) {
   4826         ImageBuffer* buf = m_buffers[i].get();
   4827         if (!buf)
   4828             break;
   4829         if (buf->size() != size)
   4830             continue;
   4831         bubbleToFront(i);
   4832         return buf;
   4833     }
   4834 
   4835     OwnPtr<ImageBuffer> temp = ImageBuffer::create(size);
   4836     if (!temp)
   4837         return 0;
   4838     i = std::min(m_capacity - 1, i);
   4839     m_buffers[i] = temp.release();
   4840 
   4841     ImageBuffer* buf = m_buffers[i].get();
   4842     bubbleToFront(i);
   4843     return buf;
   4844 }
   4845 
   4846 void WebGLRenderingContext::LRUImageBufferCache::bubbleToFront(int idx)
   4847 {
   4848     for (int i = idx; i > 0; --i)
   4849         m_buffers[i].swap(m_buffers[i-1]);
   4850 }
   4851 
   4852 } // namespace WebCore
   4853 
   4854 #endif // ENABLE(WEBGL)
   4855